feat(settings): replicate the WorkBuddy agents panel and persist team-management preference (TODO 15)

This commit is contained in:
xiaohan.yuan committed 2026-10-17 12:58:25 +08:00
1 parent b3be45715e
commit 143516b3a8
33 files changed
+1071 -21

No files matched your search

@@ -4,13 +4,15 @@ import { decodeCanonicalBase64 } from '../domain/webScreenshot.js';
const MAX_ASSETS=4, MAX_ASSET_BYTES=2*1024*1024, MAX_TOTAL_BYTES=8*1024*1024;
const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
const types=new Set(['image/png','image/jpeg','image/gif','image/webp']);
const types=new Set(['image/png','image/jpeg','image/gif','image/webp','image/svg+xml']);
const mime=value=>value==='image/jpg'?'image/jpeg':value;
function sniff(bytes){
if(bytes.length>=24&&bytes.subarray(0,8).equals(Buffer.from([137,80,78,71,13,10,26,10])))return 'image/png';
if(bytes.length>=3&&bytes[0]===255&&bytes[1]===216&&bytes[2]===255)return 'image/jpeg';
if(bytes.length>=10&&/^GIF8[79]a$/.test(bytes.toString('ascii',0,6)))return 'image/gif';
if(bytes.length>=12&&bytes.toString('ascii',0,4)==='RIFF'&&bytes.toString('ascii',8,12)==='WEBP')return 'image/webp';
const text=bytes.toString('utf8',0,Math.min(bytes.length,4096)).replace(/^\uFEFF/,'').trimStart();
if(/^(?:<\?xml[\s\S]*?\?>\s*)?<svg(?:\s|>)/i.test(text))return 'image/svg+xml';
}
function safeSourceUrl(value){
try{const u=new URL(value);if(!['file:','http:','https:'].includes(u.protocol))return null;u.username='';u.password='';u.search='';u.hash='';const result=u.href;return result.length<=2048?result:null;}catch{return null;}
@@ -22,7 +24,7 @@ export async function captureElectronMediaAssets(snapshot,frames,selectors,send)
const result={items:[],total_bytes:0,limits:{max_assets:MAX_ASSETS,max_asset_bytes:MAX_ASSET_BYTES,max_total_bytes:MAX_TOTAL_BYTES},limitations:[
'Opt-in IMG resources only: exact unique selectors, authorized main file frame and snapshot backend identity. Visibility is reported separately and does not authorize new requests.',
'Only Page.getResourceTree resources already loaded by the selected frame are read with Page.getResourceContent. No HTTP fetch, cookies, headers, input values or renderer JavaScript are used.',
'PNG/JPEG/GIF/WebP only; SVG, canvas, video, CSS backgrounds and resources missing from the loaded frame tree remain unknown. Covered loaded images can be exported; bytes do not establish that this image is the currently visible layer.',
'PNG/JPEG/GIF/WebP/SVG only; canvas, video, CSS backgrounds and resources missing from the loaded frame tree remain unknown. Covered loaded images can be exported; bytes do not establish that this image is the currently visible layer.',
'Resource URLs in metadata omit credentials, query strings and fragments; URL SHA-256 identifies the exact selected URL. DOM and resource observations are sequential.'
]};
const main=frames[0],strings=snapshot.strings??[],str=index=>strings[index]??'';
@@ -32,7 +32,7 @@ const mediaIdentity = {
};
export const electronMediaAssetsSchema = z.object({
items:z.array(z.discriminatedUnion('status',[
z.object({...mediaIdentity,status:z.literal('exported'),artifact:z.object({mime_type:z.enum(['image/png','image/jpeg','image/gif','image/webp']),bytes:z.number().int().positive().max(2097152),sha256:z.string().regex(/^[a-f0-9]{64}$/),data_base64:z.string().max(2796204)})}),
z.object({...mediaIdentity,status:z.literal('exported'),artifact:z.object({mime_type:z.enum(['image/png','image/jpeg','image/gif','image/webp','image/svg+xml']),bytes:z.number().int().positive().max(2097152),sha256:z.string().regex(/^[a-f0-9]{64}$/),data_base64:z.string().max(2796204)})}),
z.object({...mediaIdentity,status:z.literal('unknown'),reason:z.string()})
])).max(4),
total_bytes:z.number().int().min(0).max(8388608),