@kanyun-ai-infra/band-cli 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bundled/kernel/fixture.js +1 -1
- package/bundled/kernel/index.js +1 -1
- package/bundled/official/activity/package.json +1 -1
- package/bundled/official/approval/package.json +1 -1
- package/bundled/official/artifacts/package.json +1 -1
- package/bundled/official/chat/package.json +1 -1
- package/bundled/official/chunks/chunk-SB74RUTN.js +1 -0
- package/bundled/official/comment/dist/index.js +1 -1
- package/bundled/official/comment/package.json +2 -2
- package/bundled/official/header/package.json +1 -1
- package/bundled/official/home/package.json +1 -1
- package/bundled/official/layouts/package.json +1 -1
- package/bundled/official/library/package.json +1 -1
- package/bundled/official/members/dist/index.js +1 -1
- package/bundled/official/members/package.json +2 -2
- package/bundled/official/memory/dist/index.js +2 -2
- package/bundled/official/memory/package.json +2 -2
- package/bundled/official/native/package.json +1 -1
- package/bundled/official/params-form/package.json +1 -1
- package/bundled/official/plugins/package.json +1 -1
- package/bundled/official/project/dist/index.js +1 -1
- package/bundled/official/project/package.json +2 -2
- package/bundled/official/queue/package.json +1 -1
- package/bundled/official/settings/dist/index.js +1 -1
- package/bundled/official/settings/package.json +2 -2
- package/bundled/official/settings/plugin.yaml +7 -0
- package/bundled/official/shell/dist/index.js +1 -1
- package/bundled/official/shell/package.json +2 -2
- package/bundled/official/stages/package.json +1 -1
- package/bundled/official/threads/package.json +1 -1
- package/bundled/official/turn-bar/package.json +1 -1
- package/bundled/official/turn-trace/package.json +1 -1
- package/bundled/official/version-switch/dist/index.js +1 -1
- package/bundled/official/version-switch/package.json +1 -1
- package/bundled/official/viewer-entity/package.json +1 -1
- package/bundled/official/viewer-external/package.json +1 -1
- package/bundled/official/viewer-image/package.json +1 -1
- package/bundled/official/viewer-media/index.js +2 -2
- package/bundled/official/viewer-media/package.json +2 -2
- package/bundled/official/viewer-storyboard/index.js +2 -2
- package/bundled/official/viewer-storyboard/package.json +2 -2
- package/bundled/official/viewer-text/dist/index.js +2 -2
- package/bundled/official/viewer-text/package.json +2 -2
- package/bundled/official/viewer-tool/package.json +1 -1
- package/bundled/official/viewer-web/package.json +1 -1
- package/bundled/official/viewer-web-app/package.json +1 -1
- package/bundled/official/workshops/dist/index.js +2 -2
- package/bundled/official/workshops/package.json +2 -2
- package/bundled/skills/band-plugin/SKILL.md +20 -273
- package/bundled/skills/band-plugin/references/code.md +58 -0
- package/bundled/skills/band-plugin/references/dev.md +37 -0
- package/bundled/skills/band-plugin/references/execution.md +26 -0
- package/bundled/skills/band-plugin/references/manifest.md +65 -0
- package/bundled/skills/band-plugin/references/placement.md +34 -0
- package/bundled/skills/band-plugin/references/reuse.md +38 -0
- package/bundled/skills/band-plugin/references/rules.md +12 -0
- package/bundled/skills/band-plugin/references/shape.md +17 -0
- package/bundled/skills/band-plugin/references/testing-publish.md +35 -0
- package/bundled/skills/band-plugin/references/viewer-comments.md +25 -0
- package/bundled/skills/band-plugin/templates/dev/fixture.ts +15 -0
- package/bundled/skills/band-plugin/templates/dev/resources.ts +6 -0
- package/bundled/skills/band-plugin/templates/panel/index.ts +24 -0
- package/bundled/skills/band-plugin/templates/panel/package.json +12 -0
- package/bundled/skills/band-plugin/templates/panel/plugin.yaml +5 -0
- package/bundled/skills/band-plugin/templates/toolbar-dock/plugin.yaml +11 -0
- package/dev-host/Inspector.tsx +28 -10
- package/dev-host/app.tsx +2 -1
- package/dev-host/host.css +11 -0
- package/dev-host/main.tsx +5 -0
- package/dist/bin.js +3 -3
- package/dist/build-plugin.d.ts +1 -1
- package/dist/build-plugin.js +1 -1
- package/dist/{chunk-RAD6MMSL.js → chunk-JWZU3NOD.js} +1 -1
- package/dist/{chunk-TN7Z3OF6.js → chunk-TQHHHXXU.js} +1 -1
- package/dist/{chunk-VVJNG5GV.js → chunk-VTAJX7NN.js} +10 -10
- package/dist/{dev-server-RAZQ32W7.js → dev-server-SB5FMSVP.js} +101 -11
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/vite.d.ts +1 -1
- package/dist/vite.js +2 -2
- package/dist/{workshop-repo-CO6YMDee.d.ts → workshop-repo-Uq6blxyt.d.ts} +10 -10
- package/package.json +5 -4
- package/src/inspector-plugins.ts +18 -0
- package/bundled/official/chunks/chunk-JI6ZNGOE.js +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEFAULT_AGENT as DEFAULT_AGENT2,DeliverInputSchema,MessageExtrasSchema,PLUGIN_STORAGE_LIMITS,ReactionEmojiSchema,ReceiptChoiceSchema,attachmentKind,dedupeAttachmentName,memoryProblem,paramsProblems,pluginStorageBytes}from"@kanyun-ai-infra/band-contracts";import{StorageLimitError}from"@kanyun-ai-infra/band-plugin-sdk";import{DEFAULT_AGENT}from"@kanyun-ai-infra/band-contracts";import{needsMeByProject}from"@kanyun-ai-infra/band-contracts/needs-me";import{CUSTOM_MODEL_PRESET_ID}from"@kanyun-ai-infra/band-contracts/api";import{NET_CREDENTIAL_PRESET_NAMES}from"@kanyun-ai-infra/band-contracts/api";var PROBE_MS=1200;var PRESET={id:"modelgate",label:"ModelGate",description:"\u516C\u53F8\u6A21\u578B\u7F51\u5173\u7684 key",keyHint:"\u5230 ModelGate \u63A7\u5236\u53F0\u521B\u5EFA\u3002",docsUrl:null,unauthorizedHint:null,capabilities:["text"],endpoint:"https://modelgate.example/anthropic",defaultModels:{model:"claude-sonnet",opus:"claude-sonnet",sonnet:"claude-sonnet",haiku:"claude-sonnet"}};var FIXTURE_PROVIDER_MODELS=["model-deepseek-v4.1-flash","model-glm-5.3","model-glm-5.3-flash",PRESET.defaultModels.model];function probe(key){if(key.includes("401"))return"unauthorized";if(key.includes("403"))return"forbidden";if(key.includes("model"))return"model_unavailable";if(key.includes("down"))return"unreachable";return"ok"}function fixtureModelCredentials(opts){const rows=[];let seq=0;if(opts.seedDefault){const at=opts.now();rows.push({id:`mc-${++seq}`,name:PRESET.label,preset:PRESET.id,endpoint:PRESET.endpoint,model:PRESET.defaultModels.model,last4:"seed",isDefault:true,version:1,createdAt:at,replacedAt:null,lastVerifiedAt:at,lastVerifiedMs:PROBE_MS,usedBy:[]})}const wait=()=>new Promise(r=>setTimeout(r,PROBE_MS));const find=id=>{const row=rows.find(r=>r.id===id);if(!row)throw Object.assign(new Error("\u6CA1\u6709\u8FD9\u4EFD\u6A21\u578B\u914D\u7F6E"),{code:"NOT_FOUND"});return row};const tail=key=>key.length>=12?key.slice(-4):null;const sorted=()=>[...rows].sort((a,b)=>Number(b.isDefault)-Number(a.isDefault));const usedByOf=id=>[...selections.entries()].filter(([,s])=>s.credentialId===id).map(([,s])=>({projectId:s.projectId,projectName:s.projectName,agentId:s.agentId}));const selections=new Map;const me="kld";const projectOf=projectId=>opts.projectPolicy?.(projectId)??{policy:"off",agents:[],teamKey:false};const view=projectId=>({policy:projectOf(projectId).policy,teamKey:projectOf(projectId).teamKey,canManage:true,agents:projectOf(projectId).agents.map(agentId=>{const s=selections.get(`${projectId}/${agentId}`);const cred=s?rows.find(r=>r.id===s.credentialId):void 0;return{agentId,selection:s&&cred?{credentialId:cred.id,ownerKind:"user",ownerId:"kld",ownerName:"\u6211",name:cred.name,preset:cred.preset,last4:cred.last4,mine:true,selectedBy:s.selectedBy??"kld",selectedAt:s.selectedAt??opts.now()}:null}})});const projectAgentModels={list:async projectId=>structuredClone(view(projectId)),select:async(projectId,agentId,input)=>{find(input.credentialId);if(projectOf(projectId).policy==="off")throw Object.assign(new Error("\u8FD9\u4E2A\u5DE5\u574A\u53EA\u7528\u56E2\u961F key\uFF0C\u4E0D\u80FD\u7ED9 agent \u6539\u9009"),{code:"FORBIDDEN"});selections.set(`${projectId}/${agentId}`,{credentialId:input.credentialId,projectId,projectName:"",agentId,selectedBy:me,selectedAt:opts.now()});return view(projectId)},clear:async(projectId,agentId)=>{if(!selections.delete(`${projectId}/${agentId}`))throw Object.assign(new Error("\u8FD9\u4E2A agent \u6CA1\u6709\u9009\u7528"),{code:"NOT_FOUND"});return view(projectId)}};return{list:async()=>({presets:[{...PRESET}],credentials:structuredClone(sorted().map(r=>({...r,usedBy:usedByOf(r.id)})))}),projectAgentModels,bind:(id,agents,project)=>{find(id);for(const agentId of agents){selections.set(`${project.id}/${agentId}`,{credentialId:id,projectId:project.id,projectName:project.name,agentId})}},save:async input=>{const key=input.key.trim();const custom=input.preset===CUSTOM_MODEL_PRESET_ID;if(custom&&(!input.endpoint?.startsWith("https://")||!input.model?.trim()))throw Object.assign(new Error("\u81EA\u5B9A\u4E49\u8981\u586B https \u7AEF\u70B9\u548C\u6A21\u578B\u540D"),{code:"VALIDATION_ERROR",details:{field:input.endpoint?"model":"endpoint"}});await wait();const outcome=probe(key);if(outcome!=="ok")return{outcome};const first=rows.length===0;const at=opts.now();if(input.isDefault&&!first)for(const r of rows)r.isDefault=false;const model=input.model?.trim()||(custom?void 0:PRESET.defaultModels.model);if(!model)throw new Error("\u5939\u5177\u6CA1\u6709\u6A21\u578B\u540D");const row={id:`mc-${++seq}`,name:input.name?.trim()||(custom?"\u81EA\u5B9A\u4E49":PRESET.label),preset:custom?CUSTOM_MODEL_PRESET_ID:PRESET.id,endpoint:custom?input.endpoint?.replace(/\/+$/,"")??"":PRESET.endpoint,model,last4:tail(key),isDefault:first||input.isDefault===true,version:1,createdAt:at,replacedAt:null,lastVerifiedAt:at,lastVerifiedMs:PROBE_MS,usedBy:[]};rows.push(row);return{outcome:"ok",credential:structuredClone(row),latencyMs:PROBE_MS}},replaceKey:async(id,raw)=>{const row=find(id);const key=raw.trim();await wait();const outcome=probe(key);if(outcome!=="ok")return{outcome};const at=opts.now();row.last4=tail(key);row.version+=1;row.replacedAt=at;row.lastVerifiedAt=at;row.lastVerifiedMs=PROBE_MS;return{outcome:"ok",credential:structuredClone(row),latencyMs:PROBE_MS}},listProviderModels:async input=>{const custom=input.preset===CUSTOM_MODEL_PRESET_ID;if(custom&&!input.endpoint?.startsWith("https://"))throw Object.assign(new Error("\u81EA\u5B9A\u4E49\u8981\u586B https \u7AEF\u70B9"),{code:"VALIDATION_ERROR",details:{field:"endpoint"}});if(!custom&&(input.endpoint!==void 0||input.authScheme!==void 0))throw Object.assign(new Error("\u7AEF\u70B9\u548C\u9274\u6743\u65B9\u5F0F\u7531\u9884\u8BBE\u5E26\u51FA\uFF0C\u4E0D\u7528\u586B"),{code:"VALIDATION_ERROR"});const key=input.key.trim();await wait();if(key.includes("401"))return{outcome:"unavailable",reason:"\u6A21\u578B\u670D\u52A1\u62D2\u7EDD\u4E86\u8FD9\u4E2A key\uFF08\u65E0\u6548\u6216\u5DF2\u4F5C\u5E9F\uFF09\uFF0C\u53D6\u4E0D\u5230\u6A21\u578B\u5217\u8868"};if(key.includes("down"))return{outcome:"unavailable",reason:"\u8FDE\u4E0D\u4E0A\u6A21\u578B\u670D\u52A1\uFF0C\u53D6\u4E0D\u5230\u6A21\u578B\u5217\u8868"};if(key.includes("nolist"))return{outcome:"unavailable",reason:"\u8FD9\u4E2A\u670D\u52A1\u5546\u6CA1\u6709\u6A21\u578B\u5217\u8868\u63A5\u53E3"};return{outcome:"ok",models:[...FIXTURE_PROVIDER_MODELS]}},listCredentialModels:async id=>{find(id);await wait();return{outcome:"ok",models:[...FIXTURE_PROVIDER_MODELS]}},updateModelCredentialModels:async(id,input)=>{const row=find(id);const model=input.model.trim();if(model.length===0)throw Object.assign(new Error("\u8BF7\u586B\u5199\u6A21\u578B\u540D"),{code:"VALIDATION_ERROR"});await wait();if(model.includes("model-unavailable"))return{outcome:"model_unavailable"};row.model=model;row.version+=1;row.lastVerifiedAt=opts.now();row.lastVerifiedMs=PROBE_MS;return{outcome:"ok",credential:structuredClone(row),latencyMs:PROBE_MS}},setDefault:async id=>{const row=find(id);for(const r of rows)r.isDefault=r===row;return structuredClone(row)},remove:async id=>{const row=find(id);rows.splice(rows.indexOf(row),1);const unselected=[];for(const[k,s]of selections){if(s.credentialId!==id)continue;unselected.push({projectId:s.projectId,agentId:s.agentId});selections.delete(k)}return{unselected}}}}var FixtureNetCredentialError=class extends Error{constructor(status,code,message,details={}){super(message);this.status=status;this.code=code;this.details=details;this.name="BandApiError"}status;code;details};var PURPOSE={BAND_NET_DEFAULT:"\u9ED8\u8BA4\uFF0Cagent \u4E0D\u6307\u5B9A\u7528\u9014\u65F6\u7528",BAND_NET_IMAGE:"\u51FA\u56FE",BAND_NET_TTS:"\u914D\u97F3",BAND_NET_VIDEO:"\u89C6\u9891",BAND_NET_LLM:"\u53E6\u4E00\u4E2A\u6A21\u578B",BAND_NET_MUSIC:"\u914D\u4E50"};var PRESETS=NET_CREDENTIAL_PRESET_NAMES.map(name=>({name,purpose:PURPOSE[name]}));var BEARER={header:"Authorization",prefix:"Bearer "};var PROVIDER_PRESETS=[{id:"ark",scheme:"static",label:"\u706B\u5C71\u65B9\u821F",description:"\u51FA\u56FE\uFF08Seedream\uFF09\u3001\u89C6\u9891\uFF08Seedance\uFF09",keyHint:"\u7528\u63A7\u5236\u53F0\u521B\u5EFA\u7684 API Key\uFF0CAccess Key \u4E0D\u80FD\u7528\u3002",docsUrl:"https://www.volcengine.com/docs/ark/api-key",capabilities:["image","video"],purposes:[{name:"BAND_NET_IMAGE",purpose:"\u51FA\u56FE\uFF08Seedream\uFF09",preselected:true},{name:"BAND_NET_VIDEO",purpose:"\u89C6\u9891\uFF08Seedance\uFF09",preselected:true}],domains:["ark.cn-beijing.volces.com"],inject:BEARER},{id:"vertex",scheme:"gcp_service_account",label:"Google Vertex AI",description:"\u914D\u4E50\uFF08Lyria\uFF09",keyHint:"\u7C98\u8D34\u670D\u52A1\u8D26\u53F7\u7684 JSON key \u6587\u4EF6\uFF1B\u5355\u72EC\u5EFA\u4E00\u4E2A\u8D26\u53F7\uFF0C\u53EA\u7ED9 Vertex AI User \u6743\u9650\u3002",docsUrl:"https://cloud.google.com/iam/docs/keys-create-delete",capabilities:["music"],purposes:[{name:"BAND_NET_MUSIC",purpose:"\u914D\u4E50\uFF08Lyria\uFF09",preselected:true}],domains:["us-central1-aiplatform.googleapis.com"]}];var invalid=(field,message)=>new FixtureNetCredentialError(400,"VALIDATION_ERROR",message,{field});function checkName(name){const suffix=name.startsWith("BAND_NET_")?name.slice("BAND_NET_".length):"";if(!/^[A-Z][A-Z0-9_]{0,31}$/.test(suffix)||suffix.endsWith("_")||suffix.includes("__")||name.endsWith("_BASE_URL")||name.endsWith("_GCP_PROJECT_ID"))throw invalid("name","\u540D\u5B57\u53EA\u80FD\u7528\u5927\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E0B\u5212\u7EBF\uFF0C\u540E\u7F00 1\u201332 \u4E2A\u5B57\u7B26\uFF0C\u4E0D\u80FD\u4EE5\u4E0B\u5212\u7EBF\u7ED3\u5C3E\uFF0C\u4E0D\u80FD\u4EE5 _BASE_URL \u7ED3\u5C3E")}function checkDomains(domains){if(domains.length===0)throw invalid("domains","\u81F3\u5C11\u5199\u4E00\u4E2A\u751F\u6548\u57DF\u540D");if(domains.length>10)throw invalid("domains","\u6700\u591A 10 \u4E2A");for(const d of domains){if(/[/:@?#\s]/.test(d)||d!==d.toLowerCase())throw invalid("domains","\u53EA\u5199\u57DF\u540D\uFF0C\u4E0D\u5E26 https:// \u548C\u8DEF\u5F84");if(d==="localhost"||/^\d+(\.\d+){3}$/.test(d)||!d.includes("."))throw invalid("domains","\u4E0D\u80FD\u662F IP\u3001localhost \u6216\u5185\u7F51\u540E\u7F00")}}function checkKey(key){if(!key||key.length>4096||key!==key.trim()||/[\u0000-\u001f\u007f]/.test(key))throw invalid("key","key \u4E0D\u80FD\u6709\u6362\u884C\uFF0C\u4E0D\u80FD\u6709\u524D\u540E\u7A7A\u683C\uFF0C\u6700\u957F 4096 \u4E2A\u5B57\u7B26")}function checkServiceAccount(raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw invalid("serviceAccount","\u670D\u52A1\u8D26\u53F7 JSON \u89E3\u6790\u4E0D\u5F00\uFF0C\u6574\u4EFD\u7C98\u8D34 key \u6587\u4EF6\u7684\u5185\u5BB9")}const o=parsed??{};if(o.type!=="service_account"||typeof o.project_id!=="string"||typeof o.client_email!=="string"||typeof o.private_key!=="string")throw invalid("serviceAccount","\u8981 type \u4E3A service_account \u7684 JSON key \u6587\u4EF6");return{projectId:o.project_id,clientEmail:o.client_email}}var keyOf=o=>o.kind==="user"?"user":`project:${o.projectId}`;function fixtureNetCredentials(opts){const byOwner=new Map;let seq=0;const rowsOf=o=>{const k=keyOf(o);let rows=byOwner.get(k);if(!rows){rows=[];byOwner.set(k,rows)}return rows};const find=(o,id)=>{const row=rowsOf(o).find(r=>r.id===id);if(!row)throw new FixtureNetCredentialError(404,"NOT_FOUND","\u6CA1\u6709\u8FD9\u6761\u7F51\u7EDC\u51ED\u636E");return row};const checkCreate=(rows,inputs)=>{if(inputs.length===0)throw invalid("name","\u81F3\u5C11\u5EFA\u4E00\u6761\u7F51\u7EDC\u51ED\u636E");for(const input of inputs)checkName(input.name);const names=inputs.map(i=>i.name);const duplicated=names.find((n,i)=>names.indexOf(n)!==i);const taken=duplicated??names.find(n=>rows.some(r=>r.name===n))??void 0;if(taken)throw new FixtureNetCredentialError(409,"CONFLICT",`\u5DF2\u7ECF\u6709\u4E00\u6761\u53EB ${taken} \u7684`,{reason:"NAME_TAKEN"});if(rows.length+inputs.length>50)throw new FixtureNetCredentialError(409,"CONFLICT","\u6700\u591A 50 \u6761\uFF0C\u5148\u5220\u6389\u4E0D\u7528\u7684",{reason:"LIMIT_REACHED"});for(const input of inputs){if(input.note!==void 0&&input.note.length>40)throw invalid("note","\u5907\u6CE8\u6700\u591A 40 \u4E2A\u5B57");checkDomains(input.domains);if("serviceAccount"in input)checkServiceAccount(input.serviceAccount);else checkKey(input.key)}};const build=(owner,input)=>{seq+=1;if("serviceAccount"in input){const gcp=checkServiceAccount(input.serviceAccount);return{id:`nc-${seq}`,ownerKind:owner.kind,name:input.name,note:input.note??null,domains:[...input.domains],scheme:"gcp_service_account",gcp,inject:BEARER,last4:null,version:1,createdAt:opts.now(),replacedAt:null}}return{id:`nc-${seq}`,ownerKind:owner.kind,name:input.name,note:input.note??null,domains:[...input.domains],scheme:"static",gcp:null,inject:input.inject??BEARER,last4:input.key.length>=12?input.key.slice(-4):null,version:1,createdAt:opts.now(),replacedAt:null}};return{list:async()=>structuredClone({presets:PRESETS,providerPresets:PROVIDER_PRESETS,credentials:rowsOf({kind:"user"}),canManage:true}),listProject:async projectId=>{const project=rowsOf({kind:"project",projectId});const names=new Set(project.map(c=>c.name));const effective=[...project.map(c=>({credentialId:c.id,name:c.name,domains:c.domains,source:"project",ownerId:projectId})),...rowsOf({kind:"user"}).filter(c=>!names.has(c.name)).map(c=>({credentialId:c.id,name:c.name,domains:c.domains,source:"creator",ownerId:opts.userId??"me"}))];return structuredClone({presets:PRESETS,providerPresets:PROVIDER_PRESETS,credentials:project,canManage:true,effective})},save:async(owner,input)=>{const rows=rowsOf(owner);checkCreate(rows,[input]);const row=build(owner,input);rows.push(row);return structuredClone({credential:row})},saveMany:async(owner,input)=>{const rows=rowsOf(owner);checkCreate(rows,input.credentials);const created=input.credentials.map(c=>build(owner,c));rows.push(...created);return structuredClone({credentials:created})},update:async(owner,id,input)=>{const row=find(owner,id);if(input.domains)checkDomains(input.domains);if(typeof input.note==="string"&&input.note.length>40)throw invalid("note","\u5907\u6CE8\u6700\u591A 40 \u4E2A\u5B57");if(row.scheme==="gcp_service_account"&&input.inject)throw invalid("inject","GCP \u670D\u52A1\u8D26\u53F7\u51ED\u636E\u56FA\u5B9A\u6CE8\u5165 Authorization: Bearer\uFF0C\u4E0D\u80FD\u6539\u6CE8\u5165\u683C\u5F0F");const bump=input.domains&&input.domains.join("\n")!==row.domains.join("\n")||input.inject&&(input.inject.header!==row.inject.header||input.inject.prefix!==row.inject.prefix);if(input.note!==void 0)row.note=input.note;if(input.domains)row.domains=[...input.domains];if(input.inject)row.inject={...input.inject};if(bump){row.version+=1;row.replacedAt=opts.now()}return structuredClone({credential:row})},replaceKey:async(owner,id,value)=>{const row=find(owner,id);if("serviceAccount"in value){if(row.scheme!=="gcp_service_account")throw invalid("serviceAccount","\u8FD9\u6761\u662F\u9759\u6001 key \u51ED\u636E\uFF0C\u6362 key \u7528 key \u5B57\u6BB5");row.gcp=checkServiceAccount(value.serviceAccount)}else{if(row.scheme!=="static")throw invalid("key","\u8FD9\u6761\u662F GCP \u670D\u52A1\u8D26\u53F7\u51ED\u636E\uFF0C\u6574\u4EFD\u91CD\u8D34\u670D\u52A1\u8D26\u53F7 JSON");checkKey(value.key);row.last4=value.key.length>=12?value.key.slice(-4):null}row.version+=1;row.replacedAt=opts.now();return structuredClone({credential:row})},remove:async(owner,id)=>{find(owner,id);const rows=rowsOf(owner);byOwner.set(keyOf(owner),rows.filter(r=>r.id!==id));return{invalidatedSessions:0,stops:0}}}}function agentsOfWorkshop(w){const out=new Set([DEFAULT_AGENT]);for(const wf of w.workflows)for(const st of wf.stages)if(st.kind==="agent"&&st.agent)out.add(st.agent);return[...out]}function liveVersion(p){const versions=p.detail?.versions;if(!versions)return p.version;return versions.find(v=>v.yanked===void 0)?.version}function liveCard(p){const{usedIn=[],detail={},...card}=p;const version=liveVersion(p)??card.version;const versions=(detail.versions??[{version:card.version,current:true}]).map(v=>({...v,current:v.version===version}));return{card:{...card,version},usedIn,detail,versions}}var SOURCE_ORDER={official:0,shared:1,workshop:2};function cardOf(w){const{hubProjectId:_h,ref:_r,admins:_a,workflows:_w,artifactTypes:_t,roles:_ro,views:_v,releases:_re,formTarget:_f,...card}=w;return{...card,stages:w.stages.map(s=>({id:s.id,...s.label?{label:s.label}:{},kind:s.kind}))}}var includes=(text,q)=>text.toLowerCase().includes(q);function createFixtureAppData(seed,opts={}){const state=structuredClone(seed);state.inbox??={needsYou:[],inProgress:[]};state.threads??=[];const now=opts.now??(()=>new Date().toISOString());const modelCredentials=fixtureModelCredentials({now,...opts.seedModelCredential?{seedDefault:true}:{},projectPolicy:projectId=>{const w=state.workshops.find(x=>x.id===workshopOfProject(projectId));return{policy:w?.userModelKey??"off",agents:w?agentsOfWorkshop(w):[],teamKey:(w?.userModelKey??"off")!=="require"}}});let seq=0;const newId=opts.newId??(()=>`p-${++seq}`);const listeners=new Set;const notify=()=>{for(const fn of[...listeners])fn()};const workshopOfProject=projectId=>state.projects.find(p=>p.project.id===projectId)?.workshop.id;const inWorkshop=(projectId,f)=>f?.workshop===void 0||workshopOfProject(projectId)===f.workshop;let mentionsOnly=false;let guide={status:"off",step:1,total:7};const feedback=[{id:"fb-2",author:"chen",authorName:"\u9648\u9759",createdAt:"2026-11-05T09:30:00.000Z",pageUrl:"/w/teaching-tool/fen-niu",projectId:null,projectName:"\u5206\u725B\u95EE\u9898",workshopId:"teaching-tool",workshopName:"\u6559\u5177",body:"\u6279\u51C6\u6309\u94AE\u70B9\u4E86\u6CA1\u53CD\u5E94\uFF0C\u5237\u65B0\u540E\u624D\u53D8\u6210\u5DF2\u6279\u51C6\u3002",status:"new",adminNote:null,reply:null,repliedBy:null,repliedAt:null,replySeenAt:null},{id:"fb-1",author:"zhou",authorName:null,createdAt:"2026-11-04T15:10:00.000Z",pageUrl:"/",projectId:null,projectName:null,workshopId:null,workshopName:null,body:"\u9996\u9875\u7684\u641C\u7D22\u6846\u80FD\u4E0D\u80FD\u652F\u6301\u6309\u5DE5\u574A\u7B5B\u9009\uFF1F",status:"seen",adminNote:null,reply:null,repliedBy:null,repliedAt:null,replySeenAt:null}];const withAlert=i=>mentionsOnly?{...i,alert:i.kind==="mention"}:i;function inbox(f){const box=state.inbox??{needsYou:[],inProgress:[]};return{needsYou:box.needsYou.filter(i=>inWorkshop(i.projectId,f)).map(withAlert),inProgress:box.inProgress.filter(i=>inWorkshop(i.projectId,f))}}function projects(f){const needs=needsMeByProject((state.inbox?.needsYou??[]).map(withAlert));return state.projects.filter(p=>f?.workshop===void 0||p.workshop.id===f.workshop).filter(p=>p.project.archivedAt===void 0).map(p=>({...p,needsMe:needs.get(p.project.id)??0}))}function workshops(f){return state.workshops.filter(w=>f?.workshop===void 0||w.id===f.workshop).filter(w=>w.archivedAt===void 0).map(cardOf)}const copy=v=>Promise.resolve(structuredClone(v));return{workshops:async f=>copy(workshops(f)),workshop:async id=>copy(state.workshops.find(w=>w.id===id)??null),projects:async f=>copy(projects(f)),inbox:async f=>copy(inbox(f)),myArtifacts:async(query={})=>copy({query:{...query.tab!==void 0?{tab:query.tab}:{},...query.workshop!==void 0?{workshop:query.workshop}:{},...query.project!==void 0?{project:query.project}:{},...query.type!==void 0?{type:query.type}:{},...query.status!==void 0?{status:query.status}:{},...query.q!==void 0?{q:query.q}:{}},counts:{joined:0,mine:0,review:0,starred:0},facets:{workshops:[],projects:[],types:[]},rows:[]}),search:async(query,f)=>{const q=query.trim().toLowerCase();if(q==="")return{projects:[],workshops:[],threads:[]};return copy({projects:projects(f).filter(p=>includes(p.project.name,q)),workshops:workshops(f).filter(w=>includes(w.name,q)||includes(w.description,q)||includes(w.id,q)),threads:(state.threads??[]).filter(t=>inWorkshop(t.projectId,f)&&(includes(t.excerpt,q)||includes(t.projectName,q)||includes(`#${t.mark}`,q)))})},plugins:async(query={})=>{const q=query.q?.trim().toLowerCase()??"";const list=(state.plugins??[]).filter(p=>query.workshop===void 0?p.source!=="workshop":p.workshop?.id===query.workshop||(p.usedIn??[]).includes(query.workshop)).filter(p=>query.kind===void 0||p.kinds.includes(query.kind)).filter(p=>p.source==="official"||liveVersion(p)!==void 0).filter(p=>q===""||[p.name,p.title,p.description??"",...p.keywords??[]].some(t=>includes(t,q))).map((p,i)=>({p,i})).sort((a,b)=>SOURCE_ORDER[a.p.source]-SOURCE_ORDER[b.p.source]||a.i-b.i).map(({p})=>liveCard(p).card);return copy(list)},plugin:async name=>{const p=(state.plugins??[]).find(x=>x.name===name&&x.source!=="workshop");if(!p)return null;const{card,usedIn,detail,versions}=liveCard(p);const names=new Map(state.workshops.map(w=>[w.id,w.name]));return copy({...card,...detail.readme?{readme:detail.readme}:{},versions,...detail.canYank?{canYank:true}:{},face:detail.face??{contributions:[],slots:[],services:[],anchors:[]},resources:detail.resources??[],usedIn:usedIn.map(id=>({id,name:names.get(id)??id}))})},subscribe:fn=>{listeners.add(fn);return()=>listeners.delete(fn)},write:{...opts.platformTokens?{platformTokens:opts.platformTokens}:{},modelCredentials,projectAgentModels:modelCredentials.projectAgentModels,netCredentials:fixtureNetCredentials({now}),feedbackAdmin:{isAdmin:async()=>true,list:async query=>{const want=query.status??"open";const items=feedback.filter(f=>want==="all"?true:want==="open"?f.status!=="resolved":f.status===want);return{items:structuredClone(items),nextCursor:null}},patch:async(id,input)=>{const row=feedback.find(f=>f.id===id);if(!row)throw new Error("\u6CA1\u6709\u8FD9\u6761\u53CD\u9988");if(input.status!==void 0)row.status=input.status;if(input.adminNote!==void 0)row.adminNote=input.adminNote;if(input.reply!==void 0){row.reply=input.reply;row.repliedBy=input.reply===null?null:"kld";row.repliedAt=input.reply===null?null:now();if(input.reply!==null)row.replySeenAt=null}notify();return{feedback:structuredClone(row)}}},pluginYank:{yank:async(name,version,reason)=>{const v=state.plugins?.find(p=>p.name===name&&p.source==="shared")?.detail?.versions?.find(x=>x.version===version);if(!v)throw new Error("\u63D2\u4EF6\u7248\u672C\u4E0D\u5B58\u5728\u6216\u6CA1\u5171\u4EAB");if(v.yanked)throw new Error(`${name}@${version} \u5DF2\u7ECF\u64A4\u56DE\u4E86`);v.yanked={reason};notify()},unyank:async(name,version)=>{const v=state.plugins?.find(p=>p.name===name&&p.source==="shared")?.detail?.versions?.find(x=>x.version===version);if(!v?.yanked)throw new Error(`${name}@${version} \u6CA1\u6709\u64A4\u56DE`);v.yanked=void 0;notify()}},guide:{get:async()=>guide,set:async action=>{guide=action==="restart"||guide.status==="done"||guide.status==="off"?{status:"active",step:1,total:7}:{...guide,status:action==="collapse"?"collapsed":action==="skip"?"skipped":"active"};notify();return guide}},userSettings:{get:async()=>({mentionsOnly}),set:async patch=>{if(patch.mentionsOnly!==void 0)mentionsOnly=patch.mentionsOnly;notify();return{mentionsOnly}}},createProject:async({workshop:workshop2,name,modelCredentialId})=>{const w=state.workshops.find(x=>x.id===workshop2&&x.archivedAt===void 0);if(!w)throw new Error(`\u6CA1\u6709\u5DE5\u574A ${workshop2}`);const policy=w.userModelKey??"off";const mine=policy==="off"?null:await modelCredentials.list();if(modelCredentialId!==void 0){if(policy==="off")throw Object.assign(new Error("\u8FD9\u4E2A\u5DE5\u574A\u53EA\u7528\u56E2\u961F key\uFF0C\u5EFA\u9879\u76EE\u65F6\u4E0D\u80FD\u9009\u6A21\u578B\u914D\u7F6E"),{code:"VALIDATION_ERROR"});if(!mine?.credentials.some(c=>c.id===modelCredentialId))throw Object.assign(new Error("\u6A21\u578B\u914D\u7F6E\u4E0D\u5B58\u5728"),{code:"NOT_FOUND"})}const bind=modelCredentialId??mine?.credentials.find(c=>c.isDefault)?.id;if(policy==="require"&&bind===void 0)throw Object.assign(new Error("\u8FD9\u4E2A\u5DE5\u574A\u8981\u7528\u4F60\u81EA\u5DF1\u7684\u6A21\u578B\u914D\u7F6E\uFF1A\u5230\u4E2A\u4EBA\u8BBE\u7F6E\u6DFB\u52A0\u4E00\u4EFD\u6A21\u578B\u914D\u7F6E\uFF0C\u518D\u5EFA\u9879\u76EE"),{code:"CONFLICT",details:{reason:"model-required"}});const trimmed=name.trim();if(trimmed==="")throw new Error("\u9879\u76EE\u540D\u4E0D\u80FD\u4E3A\u7A7A");if(trimmed.length>200)throw new Error("\u9879\u76EE\u540D\u6700\u957F 200 \u5B57");const id=newId();const at=now();if(bind!==void 0)modelCredentials.bind(bind,agentsOfWorkshop(w),{id,name:trimmed});state.projects.unshift({project:{id,name:trimmed,workshopRef:w.id,createdBy:state.me.id,createdAt:at},workshop:{id:w.id,name:w.name,...w.icon?{icon:w.icon}:{}},myRoles:w.roles.map(r=>r.name),canAdmin:true,memberCount:1,lastActivityAt:at});w.projectCount+=1;notify();return{id}},markRead:async commentId=>{const box=state.inbox;if(!box)return;const before=box.needsYou.length;box.needsYou=box.needsYou.filter(i=>!(i.kind==="mention"&&i.commentId===commentId));if(box.needsYou.length!==before)notify()}},update:fn=>{fn(state);notify()}}}var T=d=>`2026-10-${d}Z`;function workshop(w){return{id:w.id,name:w.name,description:w.description,maintainer:w.maintainer,scope:w.scope,...w.icon?{icon:w.icon}:{},version:w.version,stages:w.stages.map(s=>({id:s.id,kind:s.kind})),projectCount:w.projectCount,canAdmin:false,hubProjectId:`hub-${w.id}`,model:{state:"not_provisioned",hubProject:"ready",agent:"ready"},ref:"main",admins:[],workflows:[{name:"main",stages:w.stages}],...w.formTarget?{formTarget:w.formTarget}:{},artifactTypes:w.artifactTypes,roles:w.roles,views:{plugins:w.plugins,viewers:[]},releases:w.releases.map((r,i)=>({version:w.releases.length-i,workshopHash:`${w.id}-${w.releases.length-i}`.padEnd(12,"0"),commit:`c${(w.releases.length-i).toString(16).padStart(6,"0")}`,note:r.note,publishedBy:w.maintainer,publishedAt:r.at}))}}function sampleAppFixture(){const teaching=workshop({id:"teaching",name:"\u6559\u5177",description:"\u628A\u4E00\u4E2A\u77E5\u8BC6\u70B9\u505A\u6210\u80FD\u5728\u8BFE\u5802\u4E0A\u62D6\u3001\u70B9\u3001\u6F14\u793A\u7684\u4E92\u52A8\u6559\u5177\uFF1B\u6559\u7814\u786E\u8BA4\u9700\u6C42\uFF0C\u8BBE\u8BA1\u628A\u5173\uFF0C\u8001\u5E08\u8BD5\u7528\u3002",maintainer:"\u6559\u7814\u4E2D\u53F0",scope:"public",icon:"genre:classical",version:4,stages:[{id:"\u9700\u6C42",kind:"human",needs:[],produces:["brief"]},{id:"\u751F\u6210",kind:"agent",agent:"rondo",needs:["\u9700\u6C42:brief"],produces:["tool"]},{id:"\u8BC4\u5BA1",kind:"human",needs:["\u751F\u6210:tool"],produces:[],gate:{approveBy:["designer","teacher"],mode:"all",noteRequired:false}},{id:"\u4E0A\u67B6",kind:"external",needs:["\u751F\u6210:tool"],produces:[]}],artifactTypes:[{name:"brief",storage:"store"},{name:"tool",storage:"git"}],roles:[{name:"researcher",permissions:["comment","submit-change","confirm","admin"]},{name:"designer",permissions:["comment","approve"]},{name:"teacher",permissions:["comment","approve","publish"]}],projectCount:38,releases:[{note:"\u8BC4\u5BA1\u6539\u6210\u8BBE\u8BA1\u4E0E\u8001\u5E08\u90FD\u8981\u6279",at:T("20T08:00:00")},{note:"\u4E0A\u67B6\u63A5\u8BFE\u4EF6\u5E93",at:T("12T03:30:00")},{note:"\u751F\u6210\u9636\u6BB5\u6362\u6210 Rondo",at:T("02T09:00:00")},{note:"\u9996\u7248",at:"2026-09-18T06:00:00Z"}],plugins:["band-stages","band-threads","viewer-web"],formTarget:{stage:"\u9700\u6C42"}});const site=workshop({id:"site",name:"\u5EFA\u7AD9",description:"\u6D3B\u52A8\u9875\u3001\u843D\u5730\u9875\u3001\u5C0F\u7AD9\u70B9\uFF1A\u5199\u6E05\u76EE\u6807\u548C\u7D20\u6750\uFF0CRondo \u51FA\u7AD9\uFF0C\u8FD0\u8425\u6539\u5B57\uFF0C\u4E00\u952E\u53D1\u5E03\u5230 rush\u3002",maintainer:"\u589E\u957F\u7EC4",scope:"team",icon:"genre:pop",version:7,stages:[{id:"brief",kind:"human",needs:[],produces:["brief"],params:{type:"object",properties:{kind:{type:"string",title:"\u7AD9\u70B9\u7C7B\u578B",enum:["landing","docs"],enumNames:["\u843D\u5730\u9875","\u6587\u6863\u7AD9"]}},required:["kind"]}},{id:"build",kind:"agent",agent:"rondo",needs:["brief:brief"],produces:["site"]},{id:"publish",kind:"external",needs:["build:site"],produces:[]}],artifactTypes:[{name:"brief",storage:"store"},{name:"site",storage:"git"}],roles:[{name:"owner",permissions:["comment","submit-change","confirm","publish","admin"]},{name:"editor",permissions:["comment","submit-change"]}],projectCount:112,releases:[{note:"\u53D1\u5E03\u524D\u8DD1\u4E00\u904D\u94FE\u63A5\u68C0\u67E5",at:T("21T02:00:00")},{note:"\u9884\u89C8\u6539\u6210\u5B9E\u65F6\u9884\u89C8",at:T("15T10:00:00")}],plugins:["band-chat","viewer-web"],formTarget:{stage:"brief"}});const video=workshop({id:"video",name:"\u89C6\u9891",description:"\u5BA3\u4F20\u7247\u3001\u8BFE\u7A0B\u7247\u5934\uFF1A\u5206\u955C\u3001\u65C1\u767D\u3001\u526A\u8F91\u4E00\u6761\u7EBF\uFF0C\u6309\u955C\u5934\u63D0\u610F\u89C1\u3002",maintainer:"\u54C1\u724C\u8BBE\u8BA1",scope:"public",icon:"genre:jazz",version:2,stages:[{id:"\u5206\u955C",kind:"agent",agent:"rondo",needs:[],produces:["storyboard"]},{id:"\u65C1\u767D",kind:"agent",agent:"rondo",needs:["\u5206\u955C:storyboard"],produces:["vo"]},{id:"\u526A\u8F91",kind:"human",needs:["\u5206\u955C:storyboard","\u65C1\u767D:vo"],produces:["cut"],gate:{approveBy:["director"],mode:"any",noteRequired:true}}],artifactTypes:[{name:"storyboard",storage:"store"},{name:"vo",storage:"store"},{name:"cut",storage:"external"}],roles:[{name:"director",permissions:["comment","submit-change","confirm","approve","admin"]},{name:"editor",permissions:["comment"]}],projectCount:9,releases:[{note:"\u526A\u8F91\u95E8\u7981\u8981\u5199\u8BF4\u660E",at:T("19T07:00:00")},{note:"\u9996\u7248",at:T("01T07:00:00")}],plugins:["band-stages","viewer-media"]});const ws=w=>({id:w.id,name:w.name,...w.icon?{icon:w.icon}:{}});const project=(id,name,w,myRoles,lastActivityAt,memberCount)=>({project:{id,name,workshopRef:w.id,createdBy:"wangmin",createdAt:T("10T02:00:00")},workshop:ws(w),myRoles,canAdmin:myRoles.includes("researcher")||myRoles.includes("owner"),memberCount,lastActivityAt});return{me:{id:"wangmin",displayName:"\u738B\u654F",title:"\u6570\u5B66\u6559\u7814"},workshops:[teaching,site,video],projects:[project("jitu","\u9E21\u5154\u540C\u7B3C",teaching,["researcher"],T("23T01:40:00"),4),project("fenshu","\u5206\u6570\u7684\u610F\u4E49",teaching,["researcher"],T("22T09:12:00"),3),project("chunzhao","\u6625\u62DB\u6D3B\u52A8\u9875",site,["owner"],T("23T00:55:00"),5),project("zhoukao","\u5468\u8003\u6210\u7EE9\u5355",site,["editor"],T("18T06:00:00"),2),project("xinxueqi","\u65B0\u5B66\u671F\u5BA3\u4F20\u7247",video,["editor"],T("21T11:30:00"),6)],inbox:{needsYou:[{kind:"confirm",projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-3",mark:3,at:T("23T01:40:00")},{kind:"mention",projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-5",commentId:"c-12",mark:5,by:"\u674E\u7136",at:T("23T01:20:00")},{kind:"publish",projectId:"chunzhao",projectName:"\u6625\u62DB\u6D3B\u52A8\u9875",runId:"run-1",stage:"publish",at:T("23T00:55:00"),alert:false},{kind:"unsent",projectId:"fenshu",projectName:"\u5206\u6570\u7684\u610F\u4E49",count:2,at:T("22T09:12:00"),alert:false}],inProgress:[{projectId:"xinxueqi",projectName:"\u65B0\u5B66\u671F\u5BA3\u4F20\u7247",runId:"run-2",stage:"\u65C1\u767D",agent:"rondo",status:"running",since:T("23T01:50:00")},{projectId:"chunzhao",projectName:"\u6625\u62DB\u6D3B\u52A8\u9875",runId:"run-1",stage:"build",agent:"rondo",status:"queued",position:1,since:T("23T01:52:00")}]},threads:[{projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-3",mark:3,status:"awaiting_confirm",excerpt:"\u5154\u5B50\u7684\u811A\u6570\u6CA1\u6709\u8DDF\u7740\u5207\u6362\u53D8\u5316\uFF0C\u62D6\u52A8\u4EE5\u540E\u8FD8\u662F 2 \u53EA\u811A"},{projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-5",mark:5,status:"open",excerpt:"\u8BB2\u89E3\u5047\u8BBE\u6CD5\u90A3\u4E00\u6B65\u5B57\u592A\u5C0F\uFF0C\u6295\u5F71\u4E0A\u770B\u4E0D\u6E05"},{projectId:"chunzhao",projectName:"\u6625\u62DB\u6D3B\u52A8\u9875",threadId:"t-2",mark:2,status:"open",excerpt:"\u62A5\u540D\u6309\u94AE\u5728\u624B\u673A\u4E0A\u88AB\u5E95\u90E8\u680F\u6321\u4F4F\u4E86"}],plugins:samplePlugins()}}function samplePlugins(){const official=(short,title,kinds,description,keywords,usedBy)=>({name:`@kanyun-ai-infra/band-${short}`,version:"0.0.0",title,description,keywords,kinds,source:"official",usedBy});return[official("viewer-web","\u7F51\u9875",["viewer"],"\u5728\u72EC\u7ACB\u9884\u89C8\u6E90\u91CC\u6253\u5F00\u7F51\u9875\u7C7B\u4EA7\u7269\uFF0C\u652F\u6301\u5143\u7D20\u6807\u6CE8\u4E0E\u5B9E\u65F6\u9884\u89C8",["\u7F51\u9875","\u9884\u89C8","\u6807\u6CE8"],3),official("viewer-text","\u6587\u6863",["viewer"],"Markdown \u4E0E\u7EAF\u6587\u672C\uFF0C\u6309\u6BB5\u843D\u3001\u9009\u4E2D\u6587\u5B57\u63D0\u610F\u89C1",["\u6587\u6863","markdown"],4),official("viewer-image","\u56FE\u7247",["viewer"],"\u56FE\u7247\u4E0E\u5019\u9009\u7F51\u683C\uFF0C\u6846\u9009\u533A\u57DF\u63D0\u610F\u89C1\uFF0C\u7248\u672C\u5E76\u6392\u5BF9\u6BD4",["\u56FE\u7247","\u5019\u9009","\u5BF9\u6BD4"],2),official("viewer-media","\u97F3\u89C6\u9891",["viewer"],"\u97F3\u9891\u4E0E\u89C6\u9891\uFF0C\u6309\u65F6\u95F4\u70B9\u63D0\u610F\u89C1\uFF0C\u9010\u5E27\u5BF9\u9F50",["\u89C6\u9891","\u97F3\u9891","\u65F6\u95F4\u8F74"],1),official("stages","\u6D41\u7A0B",["panel"],"\u9636\u6BB5\u5217\u8868\u4E0E\u8FDB\u5EA6\uFF0C\u70B9\u9636\u6BB5\u770B\u5F53\u65F6\u4EA4\u51FA\u7684\u7248\u672C",["\u9636\u6BB5","\u6D41\u7A0B"],5),official("threads","\u610F\u89C1",["panel"],"\u6309\u72B6\u6001\u5217\u51FA\u610F\u89C1\u7EBF\u7A0B\uFF0C\u70B9\u5F00\u5B9A\u4F4D\u5230\u5185\u5BB9\u4E0A",["\u610F\u89C1","\u8BC4\u5BA1"],5),official("chat","\u5BF9\u8BDD",["panel"],"\u548C Agent \u7684\u5BF9\u8BDD\u6D41\uFF0C\u6BCF\u6761\u6D88\u606F\u6302\u5728\u6574\u4EFD\u4EA7\u7269\u4E0A",["\u5BF9\u8BDD","Agent"],3),{name:"@site/rush-db",version:"1.2.0",title:"\u6570\u636E\u5E93",description:"\u67E5\u770B\u4E0E\u7F16\u8F91\u5EFA\u7AD9\u9879\u76EE\u7684\u6570\u636E\u8868\uFF0C\u5199\u7EBF\u4E0A\u524D\u786E\u8BA4",keywords:["\u6570\u636E\u5E93","\u8868\u683C"],kinds:["panel","toolbar"],source:"shared",workshop:{id:"site",name:"\u5EFA\u7AD9"},usedBy:2,usedIn:["site","video"],detail:{readme:"# \u6570\u636E\u5E93\n\n\u67E5\u770B\u4E0E\u7F16\u8F91\u5EFA\u7AD9\u9879\u76EE\u7684\u6570\u636E\u8868\u3002\u6539\u7EBF\u4E0A\u6570\u636E\u524D\u5148\u5F39\u786E\u8BA4\u3002\n\n```yaml\nviews:\n plugins:\n - '@site/rush-db@1.2.0'\n```\n",versions:[{version:"1.2.0",registeredAt:"2026-10-20T08:00:00.000Z",current:true,pinned:{workshops:1,instances:2}},{version:"1.1.0",registeredAt:"2026-10-12T08:00:00.000Z",current:false,pinned:{workshops:1,instances:1},behind:true}],face:{contributions:[{slot:"@kanyun-ai-infra/band-project/panels",id:"db",title:"\u6570\u636E\u5E93"},{slot:"@kanyun-ai-infra/band-viewer-web/toolbar",id:"db-open",title:"\u770B\u6570\u636E"}],slots:[{name:"row.actions",kind:"list",scope:"project"}],services:[{name:"tables",scope:"project"}],anchors:[]},resources:[{key:"tables",api:"https://db.example.test",read:["GET /tables/*"],write:["POST /tables/*"],prod:["DELETE /tables/*"]}]}},{name:"@teaching/storyboard",version:"0.3.0",title:"\u5206\u955C\u5899",description:"\u628A\u6559\u5177\u7684\u6BCF\u4E00\u6B65\u6392\u6210\u5206\u955C\uFF0C\u6309\u955C\u5934\u63D0\u610F\u89C1",kinds:["viewer"],source:"workshop",workshop:{id:"teaching",name:"\u6559\u5177"},usedBy:1,usedIn:["teaching"]}]}async function blobBytes(blob){if(typeof blob.arrayBuffer==="function")return new Uint8Array(await blob.arrayBuffer());return new Promise((resolve,reject)=>{const r=new FileReader;r.onload=()=>resolve(new Uint8Array(r.result));r.onerror=()=>reject(r.error);r.readAsArrayBuffer(blob)})}async function sha256Hex(bytes){const digest=await crypto.subtle.digest("SHA-256",bytes);return[...new Uint8Array(digest)].map(b=>b.toString(16).padStart(2,"0")).join("")}function createFixtureTransport(data,opts){const now=opts.now??(()=>new Date().toISOString());let actor=opts.actor;const threads=new Map((data.threads??[]).map(t2=>[t2.id,structuredClone(t2)]));const attachments=new Map((data.attachments??[]).map(({url,...meta})=>[meta.id,{meta:structuredClone(meta),...url?{url}:{}}]));const memory=(data.memory??[]).map((m,i)=>({meta:memoryMeta(i+1,m,m.files),files:structuredClone(m.files)}));const comments=structuredClone(data.comments??[]);const stages=new Map((data.stages??[]).map(s=>[s.stage,{...s}]));const gates=new Map((data.gates??[]).map(g=>[g.stage,{...g,approvedBy:[...g.approvedBy],...g.approvals?{approvals:g.approvals.map(a=>({...a}))}:{}}]));const versions=new Map(data.versions.map(v=>[v.id,v]));const members=structuredClone(data.members??[]);const turn=structuredClone(data.turn??{current:null,last:null,queue:[]});const defaultAgent=opts.defaultAgent??DEFAULT_AGENT2;const audit=[];const activity=structuredClone(data.activity??[]);const listeners=new Set;let seq=0;const seeded=new Set([...threads.keys(),...comments.map(c=>c.id),...versions.keys(),...activity.map(a=>a.id),...attachments.keys(),...turn.current?[turn.current.changeRequestId]:[],...turn.queue.map(q=>q.changeRequestId)]);const nextId=prefix=>{let id=`${prefix}_${++seq}`;while(seeded.has(id))id=`${prefix}_${++seq}`;return id};function emit(type,payload){const e={id:nextId("evt"),type,projectId:data.projectId,at:now(),source:"band",payload};for(const fn of[...listeners])fn(e);return e}function record(via,action,detail,level){const at=now();audit.push({at,actor:actor.id,via,action,detail,...level?{level}:{}});const text=activityText(action,detail);if(text){const threadId=typeof detail.threadId==="string"?detail.threadId:void 0;const stage2=typeof detail.stage==="string"?detail.stage:void 0;const versionId=typeof detail.versionId==="string"?detail.versionId:void 0;const artifactId=threadId?threads.get(threadId)?.artifactId:action==="version.deliver"&&versionId?versions.get(versionId)?.artifactId:void 0;activity.push({id:nextId("act"),at,actor,action,text,...threadId?{threadId}:{},...artifactId?{artifactId}:{},...stage2?{stage:stage2}:{},...versionId?{versionId}:{}})}}const nameOf=id=>members.find(m=>m.actor.id===id)?.displayName??id;const markOf=id=>{const t2=typeof id==="string"?threads.get(id):void 0;return t2?`#${t2.mark}`:""};const stageName=s=>typeof s==="string"?stages.get(s)?.name??gates.get(s)?.name??s:"";function activityText(action,d){const who=nameOf(actor.id);switch(action){case"thread.create":return`${who} \u63D0\u4E86\u610F\u89C1 ${markOf(d.threadId)}`;case"thread.comment":return`${who} \u56DE\u590D\u4E86 ${markOf(d.threadId)}`;case"confirmed":return`${who} \u786E\u8BA4\u89E3\u51B3 ${markOf(d.threadId)}`;case"rejected":return`${who} \u6253\u56DE ${markOf(d.threadId)}`;case"withdrawn":return`${who} \u64A4\u56DE\u4E86 ${markOf(d.threadId)}`;case"closed":return`${who} \u5173\u95ED\u4E86 ${markOf(d.threadId)}`;case"reopened":return`${who} \u91CD\u5F00\u4E86 ${markOf(d.threadId)}`;case"change_request.create":{const ids=Array.isArray(d.threadIds)?d.threadIds:[];if(ids.length===0)return null;const t2=threads.get(String(ids[0]));return`${who} \u628A ${ids.map(markOf).join(" ")} \u4EA4\u7ED9\u4E86 ${nameOf(t2?.agent??defaultAgent)}`}case"gate.approve":return`${who} \u6279\u51C6\u4E86 ${stageName(d.stage)}`;case"gate.revoke":return`${who} \u64A4\u56DE\u4E86 ${stageName(d.stage)} \u7684\u6279\u51C6`;case"stage.start":return`${who} \u542F\u52A8\u4E86 ${stageName(d.stage)}`;case"stage.rerun":return`${who} \u91CD\u8DD1\u4E86 ${stageName(d.stage)}`;case"version.human":return`${who} \u76F4\u63A5\u7F16\u8F91\uFF0C\u751F\u6210\u65B0\u7248\u672C`;case"version.deliver":return`${who} \u4EA4\u4ED8\u4E86\u65B0\u7248\u672C`;default:return null}}function projectStage(){const all=[...stages.values()];const first=all.find(s=>s.kind==="agent")??(all.length===1&&all[0]?.kind===void 0?all[0]:void 0);if(!first)throw new Error("\u8FD9\u4E2A\u6D41\u7A0B\u6CA1\u6709 agent \u9636\u6BB5\uFF0C\u9879\u76EE\u7EA7\u7684\u610F\u89C1\u6CA1\u6709\u4EBA\u63A5");return first.stage}function artifactStage(artifactId){const explicit=data.artifacts?.find(a=>a.id===artifactId)?.stage;if(explicit!==void 0)return explicit;const owning=[...stages.values()].find(s=>s.outputs?.some(o=>o.artifactId===artifactId)||s.versionId!==void 0&&versions.get(s.versionId)?.artifactId===artifactId);if(owning)return owning.stage;const[only]=stages.values();if(stages.size===1&&only)return only.stage;throw new Error(`\u6CA1\u6709\u4EA7\u7269 ${artifactId}`)}function threadStage(id){if(id===void 0)return projectStage();const t2=thread(id);return t2.artifactId===void 0?projectStage():artifactStage(t2.artifactId)}function emitChangeRequested(changeRequestId,threadIds){const queued=turn.queue.find(q=>q.changeRequestId===changeRequestId);emit("change.requested",{changeRequestId,stage:queued?.stage,kind:"feedback"});for(const threadId of threadIds){emit("thread.queued",{threadId,by:actor,changeRequestId})}}let turnNumber=turn.current?.number??0;let turnSequence=0;let currentTurnId=turn.current?`turn-${++turnSequence}`:void 0;function emitTurnStarted(stage2,kind){currentTurnId=`turn-${++turnSequence}`;emit("turn.started",{runId:data.runId,turnId:currentTurnId,stage:stage2,kind,number:++turnNumber})}function thread(id){const t2=threads.get(id);if(!t2)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u7EBF\u7A0B ${id}`);return t2}function setStatus(via,id,status,action,event){const t2=thread(id);t2.status=status;t2.updatedAt=now();record(via,action,{threadId:id});emit(event,{threadId:id,by:actor,...action==="closed"?{closed:true}:{}})}function checkExtras(extras={}){for(const id of extras.attachments??[]){if(!attachments.has(id))throw new Error(`\u9644\u4EF6 ${id} \u4E0D\u662F\u5728\u8FD9\u4E2A\u9879\u76EE\u91CC\u4E0A\u4F20\u7684`)}const ex=MessageExtrasSchema.parse(extras);return Object.fromEntries(Object.entries(ex).filter(([,v])=>Array.isArray(v)&&v.length>0))}function addComment(threadId,body,mentions=[],extras={}){if(actor.kind==="human"){for(const c of comments)if(c.threadId===threadId&&c.receipt?.optionsOpen)c.receipt.optionsOpen=void 0}const comment={id:nextId("cmt"),threadId,kind:"comment",author:actor,body,mentions,...extras,createdAt:now()};comments.push(comment);return comment}function enqueue(ids,agent,stage2=threadStage(ids[0])){const own=(stage2===void 0?void 0:stages.get(stage2)?.agent)??defaultAgent;if(agent!==void 0&&agent!==own)throw new Error(`\u8FD9\u4E2A\u9636\u6BB5\u7684 agent \u662F ${own}\uFF0C\u4E0D\u80FD\u4EA4\u7ED9 ${agent}`);const entry={changeRequestId:nextId("cr"),stage:stage2,threadIds:[...ids],agent:(ids[0]?thread(ids[0]).agent:void 0)??own,by:actor,at:now()};for(const id of ids){const s=thread(id).status;if(s==="queued"||s==="running")throw new Error(`\u7EBF\u7A0B ${id} \u5DF2\u7ECF\u4EA4\u7ED9 Agent\uFF08${s}\uFF09`)}for(const id of ids){const t2=thread(id);t2.status="queued";t2.agent=entry.agent;t2.sentBy=actor;t2.updatedAt=entry.at}turn.queue.push(entry);return entry}function gate(stage2){const g=gates.get(stage2);if(!g)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u9636\u6BB5 ${stage2} \u7684\u95E8\u7981`);return g}function gateSatisfied(g){if(!g.approveBy||g.approveBy.length===0)return g.approvedBy.length>0;const roles=g.approveBy;const valid=g.approvedBy.filter(id=>members.some(m=>m.actor.id===id&&m.roles.some(r=>roles.includes(r))));const mode=g.mode??"any";if(typeof mode==="object")return valid.length>=mode.quorum;if(mode==="every"){const holders=members.filter(m=>m.roles.some(r=>roles.includes(r)));return holders.length>0&&holders.every(m=>g.approvedBy.includes(m.actor.id))}const done=g.approveBy.filter(role=>members.some(m=>m.roles.includes(role)&&g.approvedBy.includes(m.actor.id)));return mode==="all"?done.length===g.approveBy.length:done.length>0}function pickedKey(g){const votes=g.approvals??[];return[...new Set(votes.map(a=>a.key))].find(k=>k!==void 0&&gateSatisfied({...g,approvedBy:votes.filter(a=>a.key===k).map(a=>a.userId)}))}function stage(name){const s=stages.get(name);if(!s)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u9636\u6BB5 ${name}`);return s}const blobUrls=new Map;const deliveredFiles=new Map;function file(versionId,path){const f=deliveredFiles.get(versionId)?.[path]??data.files?.[versionId]?.[path];if(f===void 0)throw new Error(`\u5939\u5177\u91CC\u7248\u672C ${versionId} \u6CA1\u6709\u6587\u4EF6 ${path}`);return f}let preview=data.preview;const t={setPreview(p){if(preview===void 0)throw new Error("\u5939\u5177\u6CA1\u6709\u5199 preview\uFF0C\u67E5\u770B\u5668\u62FF\u4E0D\u5230 ctx.live");preview=structuredClone(p)},audit,comments,threads:()=>[...threads.values()],gates:()=>[...gates.values()],turn:()=>structuredClone(turn),emit,actAs(next){actor=next},async readFile(versionId,path){const f=file(versionId,path);if(typeof f==="string")return new TextEncoder().encode(f);if(f instanceof Uint8Array)return f;const res=await fetch(f.url);if(!res.ok)throw new Error(`\u5939\u5177\u6587\u4EF6 ${path} \u53D6\u4E0D\u5230\uFF1A${res.status}`);return new Uint8Array(await res.arrayBuffer())},async objectUrl(versionId,path){const f=file(versionId,path);if(typeof f==="object"&&!(f instanceof Uint8Array))return f.url;if(typeof URL.createObjectURL!=="function")return`fixture://${versionId}/${path}`;const key=`${versionId}\0${path}`;const cached=blobUrls.get(key);if(cached)return cached;const mime=versions.get(versionId)?.entries.find(e=>e.path===path)?.mime;const bytes=typeof f==="string"?new TextEncoder().encode(f):f;const url=URL.createObjectURL(new Blob([bytes],mime?{type:mime}:{}));blobUrls.set(key,url);return url},async listThreads(filter){return[...threads.values()].filter(t2=>matches(t2,filter)).map(t2=>structuredClone(t2))},async listComments(threadId){thread(threadId);return structuredClone(comments.filter(c=>c.threadId===threadId))},async listVersions(artifactId){return structuredClone([...versions.values()].filter(v=>v.artifactId===artifactId).sort((a,b)=>a.createdAt.localeCompare(b.createdAt)))},async listMembers(){return structuredClone(members)},async projectUsage(){return null},async turnState(){return structuredClone(turn)},async gateState(name){return structuredClone(gate(name))},async stage(name){return{...stage(name)}},async listStages(){return[...stages.values()].map(s=>({...s}))},async listArtifacts(){const base=data.artifacts??[...new Set(data.versions.map(v=>v.artifactId))].map(id=>({id,name:id,artifactType:"unknown"}));return base.map(a=>{const history=[...versions.values()].filter(x=>x.artifactId===a.id).sort((x,y)=>x.createdAt.localeCompare(y.createdAt));const v=history.at(-1);const{latest:_,unused:__,...rest}=structuredClone(a);const g=a.stage===void 0?void 0:gates.get(a.stage);const picked=g?.per==="pick"?pickedKey(g):void 0;if(picked!==void 0&&a.key!==picked)Object.assign(rest,{unused:true});if(!v)return rest;return{...rest,latest:{versionId:v.id,at:v.createdAt,number:history.length,author:structuredClone(v.author)}}})},async listActivity(limit){return activity.map((a,i)=>({a,i})).sort((x,y)=>y.a.at.localeCompare(x.a.at)||y.i-x.i).slice(0,limit).map(({a})=>structuredClone(a))},async startStage(via,name,params){const s=stage(name);const given=Object.keys(params).length>0;if(given){const problems=s.paramsSchema?paramsProblems(s.paramsSchema,params):["\u8FD9\u4E2A\u9636\u6BB5\u6CA1\u6709\u58F0\u660E\u53C2\u6570\uFF0C\u4E0D\u80FD\u5E26\u53C2\u6570\u5F00\u5DE5"];if(problems.length>0)throw new Error(problems.join("\uFF1B"))}s.status="in_progress";if(given)s.params=structuredClone(params);record(via,"stage.start",{stage:name,...given?{params}:{}});emitTurnStarted(name,"produce")},async rerunStage(via,name,versionId){if(versionId!==void 0&&!versions.has(versionId))throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u7248\u672C ${versionId}`);stage(name).status="in_progress";record(via,"stage.rerun",{stage:name,...versionId?{versionId}:{}});emitTurnStarted(name,versionId?"feedback":"produce")},async rerunStageWith(via,name,message){const target=stage(name);const extras=checkExtras({attachments:message.attachments});const id=nextId("thr");const at=now();const anchor={id:nextId("anc"),kind:"project",payload:{}};threads.set(id,{id,projectId:data.projectId,runId:data.runId,anchorId:anchor.id,mark:Math.max(0,...[...threads.values()].map(t2=>t2.mark))+1,status:"open",createdBy:actor,createdAt:at,updatedAt:at,anchor,excerpt:message.body.slice(0,80)});addComment(id,message.body,[],extras);emit("thread.created",{threadId:id,by:actor,mark:thread(id).mark});const{changeRequestId}=enqueue([id],void 0,name);target.status="in_progress";record(via,"stage.rerun",{stage:name,threadId:id});emitChangeRequested(changeRequestId,[id]);emitTurnStarted(name,"produce")},async changeRequest(via,ids){const changeRequestId=ids.length>0?enqueue(ids,void 0).changeRequestId:nextId("cr");record(via,"change_request.create",{changeRequestId,threadIds:ids});if(ids.length>0)emitChangeRequested(changeRequestId,ids);return{changeRequestId}},async humanVersion(via,patch){const stage2=artifactStage(patch.artifactId);const versionId=nextId("ver");record(via,"version.human",{versionId,patch});emit("version.created",{runId:data.runId,stage:stage2,versionId,artifactId:patch.artifactId,by:actor});return{ok:true,versionId,results:[]}},async proxy(req){const handler=opts.resources?.[req.key];if(!handler)return new Response(`\u5939\u5177\u6CA1\u6709\u8D44\u6E90 ${req.key}`,{status:502});if(req.level!=="read"){record(req.via,"resource.write",{key:req.key,method:req.method,path:req.path},req.level);emit("resource.written",{key:req.key,method:req.method,path:req.path,level:req.level})}return handler(req)},subscribe(fn){listeners.add(fn);return()=>{listeners.delete(fn)}},async createThread(via,input){const artifact=artifactOf(input.anchor);const targetStage=input.anchor.kind==="project"?projectStage():input.handToAgent&&artifact.artifactId?artifactStage(artifact.artifactId):void 0;const extras=checkExtras({attachments:input.attachments,refs:input.refs,capabilities:input.capabilities,connectors:input.connectors});const id=nextId("thr");const marks=[...threads.values()].map(t3=>t3.mark);const at=now();const t2={id,projectId:data.projectId,runId:data.runId,...artifact,anchorId:input.anchor.id,mark:Math.max(0,...marks)+1,status:"open",createdBy:actor,createdAt:at,updatedAt:at,anchor:input.anchor,excerpt:input.body.slice(0,80)};if(input.intent)t2.intent=input.intent;threads.set(id,t2);addComment(id,input.body,input.mentions,extras);record(via,"thread.create",{threadId:id});emit("thread.created",{threadId:id,by:actor,mark:t2.mark});if(input.handToAgent){const{changeRequestId}=enqueue([id],input.agent,targetStage);record(via,"change_request.create",{changeRequestId,threadIds:[id]});emitChangeRequested(changeRequestId,[id])}return structuredClone(t2)},async createProjectThread(via,input){return this.createThread(via,{...input,anchor:{id:nextId("anc"),kind:"project",payload:{}}})},async comment(via,id,body,extras,mentions){const t2=thread(id);const{choice,...message}=extras??{};const checked=checkExtras(message);let replyBody=body;let replyExtras=checked;let replyMentions=mentions??[];if(choice!==void 0){const unavailable=()=>new Error("\u95EE\u9898\u6216\u9009\u9879\u4E0D\u53EF\u7528");const parsed=ReceiptChoiceSchema.safeParse(choice);if(!parsed.success||actor.kind!=="human"||replyMentions.length||Object.values(checked).some(items=>items?.length))throw unavailable();const source=comments.find(c=>c.threadId===id&&c.id===parsed.data.receiptCommentId);const option=source?.receipt?.options?.find(o=>o.id===parsed.data.choiceId);if(source?.kind!=="receipt"||source.receipt?.outcome!=="needs-input"||!option)throw unavailable();const prior=comments.find(c=>c.threadId===id&&c.choice?.receiptCommentId===source.id);if(prior){if(prior.choice?.choiceId===parsed.data.choiceId)return;throw new Error("\u9009\u62E9\u5DF2\u63D0\u4EA4\uFF0C\u8BF7\u7528\u6587\u5B57\u8865\u5145\u65B0\u7684\u60F3\u6CD5")}if(t2.status!=="open"||source.receipt.optionsOpen!==true)throw unavailable();replyBody=option.label;replyExtras={choice:parsed.data};replyMentions=[]}const comment=addComment(id,replyBody,replyMentions,replyExtras);record(via,"thread.comment",{threadId:id});emit("comment.added",{threadId:id,commentId:comment.id,by:actor,kind:comment.kind})},async confirm(via,id){setStatus(via,id,"resolved","confirmed","thread.resolved")},async reject(via,id,body,extras,mentions){addComment(id,body,mentions??[],checkExtras(extras));setStatus(via,id,"open","rejected","thread.rejected")},async withdraw(via,id){const t2=thread(id);if(t2.status!=="queued")throw new Error(`\u7EBF\u7A0B ${id} \u4E0D\u5728\u961F\u5217\u91CC\uFF0C\u4E0D\u80FD\u64A4\u56DE`);turn.queue=turn.queue.map(q=>({...q,threadIds:q.threadIds.filter(x=>x!==id)})).filter(q=>q.threadIds.length>0);t2.agent=void 0;t2.sentBy=void 0;setStatus(via,id,"open","withdrawn","thread.withdrawn")},async undoPick(via,id){const t2=thread(id);if(t2.intent!=="pick")throw new Error(`\u7EBF\u7A0B ${id} \u4E0D\u662F\u9009\u7528\u7EBF\u7A0B`);if(t2.status!=="queued")throw new Error(`\u7EBF\u7A0B ${id} \u4E0D\u5728\u961F\u5217\u91CC\uFF0C\u4E0D\u80FD\u64A4\u9500`);turn.queue=turn.queue.map(q=>({...q,threadIds:q.threadIds.filter(x=>x!==id)})).filter(q=>q.threadIds.length>0);t2.agent=void 0;t2.sentBy=void 0;addComment(id,"\u5DF2\u64A4\u9500").kind="system";setStatus(via,id,"resolved","closed","thread.resolved")},async settlePick(){return"skipped"},async stopTurn(via,changeRequestId){const queued=turn.queue.find(q=>q.changeRequestId===changeRequestId);if(queued){const stage2=queued.stage??threadStage(queued.threadIds[0]);turn.queue=turn.queue.filter(q=>q!==queued);for(const id of queued.threadIds){const t2=thread(id);t2.agent=void 0;t2.sentBy=void 0;setStatus(via,id,"open","withdrawn","thread.withdrawn")}record(via,"turn.stop",{changeRequestId});emit("change.withdrawn",{runId:data.runId,changeRequestId,stage:stage2,by:actor});return}const cur=turn.current;if(cur?.changeRequestId!==changeRequestId)throw new Error(`\u4FEE\u6539\u8BF7\u6C42 ${changeRequestId} \u6CA1\u6709\u5728\u8DD1\u7684\u56DE\u5408`);if(cur.stopping)return;cur.stopping={by:actor.id};record(via,"turn.stop",{changeRequestId});emit("turn.stopping",{runId:data.runId,turnId:currentTurnId,by:actor})},async close(via,id){setStatus(via,id,"resolved","closed","thread.resolved")},async reopen(via,id){if(thread(id).status!=="resolved")throw new Error(`\u7EBF\u7A0B ${id} \u6CA1\u6709\u5173\u95ED`);setStatus(via,id,"open","reopened","thread.reopened")},async approve(via,name,input){const g=gate(name);const key=input?.key;if(g.per&&key===void 0)throw new Error(`\u9636\u6BB5 ${name} \u6309\u952E\u6279\u51C6`);if(g.per==="pick"){g.approvals=[...(g.approvals??[]).filter(a=>a.userId!==actor.id),{userId:actor.id,key}];const forKey=(g.approvals??[]).filter(a=>a.key===key).map(a=>a.userId);const picked=gateSatisfied({...g,approvedBy:forKey})?key:pickedKey(g);if(picked!==void 0)g.approvals=g.approvals.filter(a=>a.key===picked);g.approvedBy=[...new Set(g.approvals.map(a=>a.userId))];g.status=picked===void 0?"in_review":"approved"}else if(g.per==="key"){const votes=(g.approvals??[]).filter(a=>a.userId!==actor.id||a.key!==key);g.approvals=[...votes,{userId:actor.id,key}];g.approvedBy=[...new Set(g.approvals.map(a=>a.userId))];const keys=[...new Set((data.artifacts??[]).filter(a=>a.stage===name).map(a=>a.key??"main"))];const ok=k=>gateSatisfied({...g,approvedBy:(g.approvals??[]).filter(a=>a.key===k).map(a=>a.userId)});g.status=keys.length>0&&keys.every(ok)?"approved":"in_review"}else{if(!g.approvedBy.includes(actor.id))g.approvedBy.push(actor.id);g.status=gateSatisfied(g)?"approved":"in_review"}const note=input?.note;record(via,"gate.approve",{stage:name,...note?{note}:{},...key!==void 0?{key}:{}});emit("gate.approval",{runId:data.runId,stage:name,user:actor.id,...key!==void 0?{key}:{}});if(g.status==="approved")emit("stage.approved",{runId:data.runId,stage:name,by:actor})},async revoke(via,name,key){const g=gate(name);if(g.per&&key===void 0)throw new Error(`\u9636\u6BB5 ${name} \u6309\u952E\u6279\u51C6\uFF0C\u64A4\u56DE\u8981\u5E26\u952E`);const mine=a=>a.userId===actor.id&&(key===void 0||a.key===key);if(g.approvals)g.approvals=g.approvals.filter(a=>!mine(a));g.approvedBy=g.approvals?[...new Set(g.approvals.map(a=>a.userId))]:g.approvedBy.filter(id=>id!==actor.id);g.status=(g.per==="pick"?pickedKey(g)!==void 0:gateSatisfied(g))?"approved":"in_review";record(via,"gate.revoke",{stage:name,...key!==void 0?{key}:{}});emit("gate.revoked",{runId:data.runId,stage:name,user:actor.id,...key!==void 0?{key}:{}})}};if(preview!==void 0)t.preview=async()=>structuredClone(preview??null);t.uploadAttachment=async(via,file2,o)=>{o.signal?.throwIfAborted();const bytes=new Uint8Array(await file2.arrayBuffer());const digest=await crypto.subtle.digest("SHA-256",bytes);const sha256=[...new Uint8Array(digest)].map(b=>b.toString(16).padStart(2,"0")).join("");o.signal?.throwIfAborted();o.onProgress?.(1);const live=[...attachments.values()].filter(a=>a.meta.deletedAt===void 0);const same=live.find(a=>a.meta.sha256===sha256);if(same)return{...structuredClone(same.meta),existing:true};const meta={id:nextId("att"),projectId:data.projectId,name:dedupeAttachmentName(file2.name,new Set(live.map(a=>a.meta.name))),mime:file2.type||"application/octet-stream",size:bytes.byteLength,kind:attachmentKind(file2.name,file2.type),sha256,createdBy:actor,createdAt:now()};attachments.set(meta.id,{meta,blob:file2});record(via,"attachment.upload",{attachmentId:meta.id,size:meta.size});return structuredClone(meta)};const objects=new Map;t.putObject=async(via,blob,o)=>{o.signal?.throwIfAborted();const bytes=await blobBytes(blob);const objectId=await sha256Hex(bytes);o.signal?.throwIfAborted();o.onProgress?.(1);const mime=blob.type||"application/octet-stream";objects.set(objectId,{bytes,mime});record(via,"object.put",{objectId,size:bytes.byteLength});return{objectId,size:bytes.byteLength,mime}};t.deliver=async(via,raw)=>{const input=DeliverInputSchema.parse(raw);const history=[...versions.values()].filter(v2=>v2.artifactId===input.artifactId).sort((a,b)=>a.createdAt.localeCompare(b.createdAt));const latest=history.at(-1);if(!latest)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u4EA7\u7269 ${input.artifactId}`);if(latest.id!==input.baseVersion){return{ok:false,code:"BASE_MOVED",latestVersion:latest.id}}const stage2=artifactStage(input.artifactId);const replaced=new Map;const bytesOf=new Map;for(const f of input.files){const obj=objects.get(f.objectId);if(!obj)return{ok:false,code:"UNKNOWN_OBJECT"};bytesOf.set(f.path,obj.bytes);replaced.set(f.path,{path:f.path,sha256:f.objectId,size:obj.bytes.byteLength,mime:obj.mime,storage:"store",ref:f.objectId})}const entries=[...latest.entries.map(e=>replaced.get(e.path)??e),...[...replaced.values()].filter(e=>!latest.entries.some(b=>b.path===e.path))];const hash=await sha256Hex(new TextEncoder().encode(entries.map(e=>`${e.path}\0${e.sha256}`).join("\n")));const key=es=>es.map(e=>`${e.path}\0${e.sha256}`).join("\n");const same=history.find(v2=>key(v2.entries)===key(entries));if(same)return{ok:true,versionId:same.id,unchanged:true};const files=Object.fromEntries(entries.map(e=>[e.path,bytesOf.get(e.path)??file(latest.id,e.path)]));const at=now()>latest.createdAt?now():new Date(Date.parse(latest.createdAt)+1).toISOString();const{meta:_meta,...rest}=latest;const v={...rest,id:`${input.artifactId}@${hash}`,hash,entries,author:actor,createdAt:at,provenance:[{inputs:latest.provenance.at(-1)?.inputs??[],at}]};deliveredFiles.set(v.id,files);versions.set(v.id,v);record(via,"version.deliver",{versionId:v.id,baseVersion:input.baseVersion});emit("version.created",{runId:data.runId,stage:stage2,versionId:v.id,artifactId:v.artifactId,by:actor});return{ok:true,versionId:v.id,unchanged:false}};t.attachmentUrl=async id=>{const a=attachments.get(id);if(!a||a.meta.deletedAt!==void 0)throw new Error(`\u627E\u4E0D\u5230\u9644\u4EF6 ${id}`);if(!a.url&&!a.blob)throw new Error(`\u5939\u5177\u91CC\u9644\u4EF6 ${id} \u6CA1\u6709\u5199 url`);a.url??=URL.createObjectURL(a.blob);return a.url};t.deleteAttachment=async(via,id)=>{const a=attachments.get(id);if(!a||a.meta.deletedAt!==void 0)throw new Error(`\u627E\u4E0D\u5230\u9644\u4EF6 ${id}`);a.meta={...a.meta,deletedAt:now()};record(via,"attachment.delete",{attachmentId:id})};t.listAttachments=async o=>{const seen=new Map;const ordered=comments.map((c,i)=>({c,i})).sort((x,y)=>x.c.createdAt.localeCompare(y.c.createdAt)||x.i-y.i);for(const{c}of ordered){for(const id of c.attachments??[]){const a=attachments.get(id);if(!a||seen.has(id))continue;if(a.meta.deletedAt!==void 0&&!o?.includeDeleted)continue;const th=threads.get(c.threadId);seen.set(id,{...structuredClone(a.meta),source:{threadId:c.threadId,commentId:c.id,...th?{artifactId:th.artifactId,mark:th.mark}:{},...th?.anchor.kind==="artifact"?{chat:true}:{}}})}}const latest=new Map;for(const v of[...versions.values()].sort((x,y)=>x.createdAt.localeCompare(y.createdAt)))latest.set(v.artifactId,{v,number:(latest.get(v.artifactId)?.number??0)+1});const cmp=(x,y)=>x<y?-1:x>y?1:0;const usedIn=sha256=>[...latest.values()].flatMap(({v,number})=>v.entries.filter(e=>e.sha256===sha256).map(e=>({artifactId:v.artifactId,versionId:v.id,number,path:e.path}))).sort((a,b)=>cmp(a.artifactId,b.artifactId)||cmp(a.path,b.path));for(const a of seen.values())a.usedIn=usedIn(a.sha256);const at=x=>comments.find(c=>c.id===x.source.commentId)?.createdAt??"";return[...seen.values()].reverse().sort((x,y)=>at(y).localeCompare(at(x)))};t.react=async(via,commentId,emoji,on)=>{ReactionEmojiSchema.parse(emoji);const c=comments.find(x=>x.id===commentId);if(!c)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u8BC4\u8BBA ${commentId}`);if(c.kind==="system")throw new Error("\u7CFB\u7EDF\u8BC4\u8BBA\u4E0D\u80FD\u56DE\u5E94");const same=a=>a.kind===actor.kind&&a.id===actor.id;const list=(c.reactions??[]).map(r=>({...r,actors:[...r.actors]}));const hit=list.find(r=>r.emoji===emoji);if(on===Boolean(hit?.actors.some(same)))return;if(on){if(hit)hit.actors.push(actor);else list.push({emoji,actors:[actor]})}else if(hit){hit.actors=hit.actors.filter(a=>!same(a))}const kept=list.filter(r=>r.actors.length>0);const idx=comments.indexOf(c);const{reactions:_,...rest}=c;comments[idx]=kept.length>0?{...rest,reactions:kept}:rest;record(via,"comment.react",{commentId,emoji,on});emit("reaction.changed",{threadId:c.threadId,commentId})};function createFixtureMemory(){const filesAt=v=>v===0?[]:memory[v-1]?.files??[];const need=v=>{const m=memory[v-1];if(!m)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u7B2C ${v} \u7248\u8BB0\u5FC6`);return m};const same=(a,b)=>JSON.stringify(sortFiles(a))===JSON.stringify(sortFiles(b));function commit(files,meta){if(data.archived)return{ok:false,code:"READ_ONLY"};const problem=memoryProblem(files);if(problem)return{ok:false,code:"INVALID",message:problem};if(same(files,filesAt(memory.length))){return{ok:true,version:memory.length,unchanged:true}}const version=memory.length+1;const input={...meta,author:actor,createdAt:now(),files};memory.push({meta:memoryMeta(version,input,files),files:sortFiles(files)});emit("memory.updated",{version});return{ok:true,version,unchanged:false}}return{async current(){const last=memory.at(-1);return{version:memory.length,files:structuredClone(last?.files??[]),...last?{latest:structuredClone(last.meta)}:{}}},async versions(){return memory.map(m=>structuredClone(m.meta)).reverse()},async version(v){const m=need(v);return{version:structuredClone(m.meta),files:structuredClone(m.files),changes:memoryChanges(filesAt(v-1),m.files)}},async save(via,input){if(input.baseVersion!==memory.length){return{ok:false,code:"CONFLICT",latestVersion:memory.length}}const next=new Map(filesAt(memory.length).map(f=>[f.path,f.content]));for(const f of input.files)next.set(f.path,f.content);for(const p of input.removed)next.delete(p);const r=commit([...next].map(([path,content])=>({path,content})),{action:"edit"});if(r.ok&&!r.unchanged)record(via,"memory.edit",{version:r.version});return r},async revert(via,v){need(v);const before=new Map(filesAt(v-1).map(f=>[f.path,f.content]));const after=new Map(filesAt(v).map(f=>[f.path,f.content]));const next=new Map(filesAt(memory.length).map(f=>[f.path,f.content]));for(const path of new Set([...before.keys(),...after.keys()])){if(before.get(path)===after.get(path)||next.get(path)!==after.get(path))continue;const old=before.get(path);if(old===void 0)next.delete(path);else next.set(path,old)}const r=commit([...next].map(([path,content])=>({path,content})),{action:"revert",revertsVersion:v});if(r.ok&&!r.unchanged)record(via,"memory.revert",{version:r.version,of:v});return r},async restore(via,v){const r=commit(structuredClone(need(v).files),{action:"restore",revertsVersion:v});if(r.ok&&!r.unchanged)record(via,"memory.restore",{version:r.version,of:v});return r}}}t.capabilities=async()=>structuredClone(data.capabilities??[]);t.connectors=async()=>structuredClone(data.connectors??[]);t.memory=createFixtureMemory();t.storage=createFixtureStorage();return t;function createFixtureStorage(){const byPlugin=new Map;const of=plugin=>{let m=byPlugin.get(plugin);if(!m){m=new Map;byPlugin.set(plugin,m)}return m};const writable=()=>{if(data.archived)throw new Error("\u9879\u76EE\u5DF2\u5F52\u6863\uFF0C\u63D2\u4EF6\u5B58\u50A8\u53EA\u8BFB")};return{async list(plugin){const m=of(plugin);const entries=[...m.entries()].sort(([a],[b])=>a<b?-1:a>b?1:0).map(([key,e])=>({key,size:e.size,updatedAt:e.at}));return{entries,totalBytes:entries.reduce((n,e)=>n+e.size,0)}},async get(plugin,key){const e=of(plugin).get(key);return e?{value:JSON.parse(e.text)}:null},async set(plugin,key,value){writable();const m=of(plugin);const size=pluginStorageBytes(value);if(size===null)throw new StorageLimitError(key,"value",`${key}\uFF1A\u503C\u8981\u80FD\u5E8F\u5217\u5316\u6210 JSON`);const old=m.get(key);if(!old&&m.size>=PLUGIN_STORAGE_LIMITS.maxKeys){throw new StorageLimitError(key,"keys",`\u6BCF\u4E2A\u63D2\u4EF6\u6700\u591A\u5B58 ${PLUGIN_STORAGE_LIMITS.maxKeys} \u4E2A\u952E`)}let total=size;for(const[k,e]of m)if(k!==key)total+=e.size;if(total>PLUGIN_STORAGE_LIMITS.maxTotalBytes){throw new StorageLimitError(key,"total",`\u6BCF\u4E2A\u63D2\u4EF6\u5408\u8BA1\u6700\u591A\u5B58 ${PLUGIN_STORAGE_LIMITS.maxTotalBytes/1024} KB`)}const at=now();m.set(key,{text:JSON.stringify(value),size,at});emit("storage.written",{plugin,key,size,by:actor});return{key,size,updatedAt:at}},async remove(plugin,key){writable();const removed=of(plugin).delete(key);if(removed)emit("storage.written",{plugin,key,size:0,by:actor,removed:true});return removed}}}function artifactOf(anchor){if(anchor.versionId===void 0)return{};const v=versions.get(anchor.versionId);if(!v)throw new Error(`\u951A\u70B9\u6307\u5411\u7684\u7248\u672C ${anchor.versionId} \u4E0D\u5728\u5939\u5177\u91CC`);return{artifactId:v.artifactId}}}function sortFiles(files){return[...files].sort((a,b)=>a.path.localeCompare(b.path)).map(f=>({...f}))}function memoryMeta(version,m,files){return{...structuredClone(m),version,files:sortFiles(files).map(f=>({path:f.path,size:new TextEncoder().encode(f.content).byteLength}))}}function memoryChanges(before,after){const a=new Map(before.map(f=>[f.path,f.content]));const b=new Map(after.map(f=>[f.path,f.content]));const out=[];for(const path of[...new Set([...a.keys(),...b.keys()])].sort()){const x=a.get(path);const y=b.get(path);if(x===y)continue;if(x===void 0)out.push({path,change:"added",after:y});else if(y===void 0)out.push({path,change:"removed",before:x});else out.push({path,change:"modified",before:x,after:y})}return out}function matches(t,f){if(f.artifactId&&t.artifactId!==f.artifactId)return false;if(f.anchorKind&&t.anchor.kind!==f.anchorKind)return false;if(f.status&&!f.status.includes(t.status))return false;if(f.payload){for(const[k,v]of Object.entries(f.payload)){if(JSON.stringify(t.anchor.payload[k])!==JSON.stringify(v))return false}}return true}export{createFixtureAppData,createFixtureTransport,sampleAppFixture,samplePlugins};
|
|
1
|
+
import{DEFAULT_AGENT as DEFAULT_AGENT2,DeliverInputSchema,MessageExtrasSchema,PLUGIN_STORAGE_LIMITS,ReactionEmojiSchema,ReceiptChoiceSchema,attachmentKind,dedupeAttachmentName,memoryProblem,paramsProblems,pluginStorageBytes}from"@kanyun-ai-infra/band-contracts";import{StorageLimitError}from"@kanyun-ai-infra/band-plugin-sdk";import{DEFAULT_AGENT}from"@kanyun-ai-infra/band-contracts";import{needsMeByProject}from"@kanyun-ai-infra/band-contracts/needs-me";import{CUSTOM_MODEL_PRESET_ID}from"@kanyun-ai-infra/band-contracts/api";import{NET_CREDENTIAL_PRESET_NAMES}from"@kanyun-ai-infra/band-contracts/api";var PROBE_MS=1200;var PRESET={id:"modelgate",label:"ModelGate",description:"\u516C\u53F8\u6A21\u578B\u7F51\u5173\u7684 key",keyHint:"\u5230 ModelGate \u63A7\u5236\u53F0\u521B\u5EFA\u3002",docsUrl:null,unauthorizedHint:null,capabilities:["text"],endpoint:"https://modelgate.example/anthropic",defaultModels:{model:"claude-sonnet",opus:"claude-sonnet",sonnet:"claude-sonnet",haiku:"claude-sonnet"}};var FIXTURE_PROVIDER_MODELS=["model-deepseek-v4.1-flash","model-glm-5.3","model-glm-5.3-flash",PRESET.defaultModels.model];function probe(key){if(key.includes("401"))return"unauthorized";if(key.includes("403"))return"forbidden";if(key.includes("model"))return"model_unavailable";if(key.includes("down"))return"unreachable";return"ok"}function fixtureModelCredentials(opts){const rows=[];let seq=0;if(opts.seedDefault){const at=opts.now();rows.push({id:`mc-${++seq}`,name:PRESET.label,preset:PRESET.id,endpoint:PRESET.endpoint,model:PRESET.defaultModels.model,last4:"seed",isDefault:true,version:1,createdAt:at,replacedAt:null,lastVerifiedAt:at,lastVerifiedMs:PROBE_MS,usedBy:[]})}const wait=()=>new Promise(r=>setTimeout(r,PROBE_MS));const find=id=>{const row=rows.find(r=>r.id===id);if(!row)throw Object.assign(new Error("\u6CA1\u6709\u8FD9\u4EFD\u6A21\u578B\u914D\u7F6E"),{code:"NOT_FOUND"});return row};const tail=key=>key.length>=12?key.slice(-4):null;const sorted=()=>[...rows].sort((a,b)=>Number(b.isDefault)-Number(a.isDefault));const usedByOf=id=>[...selections.entries()].filter(([,s])=>s.credentialId===id).map(([,s])=>({projectId:s.projectId,projectName:s.projectName,agentId:s.agentId}));const selections=new Map;const me="kld";const projectOf=projectId=>opts.projectPolicy?.(projectId)??{policy:"off",agents:[],teamKey:false};const view=projectId=>({policy:projectOf(projectId).policy,teamKey:projectOf(projectId).teamKey,canManage:true,agents:projectOf(projectId).agents.map(agentId=>{const s=selections.get(`${projectId}/${agentId}`);const cred=s?rows.find(r=>r.id===s.credentialId):void 0;return{agentId,selection:s&&cred?{credentialId:cred.id,ownerKind:"user",ownerId:"kld",ownerName:"\u6211",name:cred.name,preset:cred.preset,last4:cred.last4,mine:true,selectedBy:s.selectedBy??"kld",selectedAt:s.selectedAt??opts.now()}:null}})});const projectAgentModels={list:async projectId=>structuredClone(view(projectId)),select:async(projectId,agentId,input)=>{find(input.credentialId);if(projectOf(projectId).policy==="off")throw Object.assign(new Error("\u8FD9\u4E2A\u5DE5\u574A\u53EA\u7528\u56E2\u961F key\uFF0C\u4E0D\u80FD\u7ED9 agent \u6539\u9009"),{code:"FORBIDDEN"});selections.set(`${projectId}/${agentId}`,{credentialId:input.credentialId,projectId,projectName:"",agentId,selectedBy:me,selectedAt:opts.now()});return view(projectId)},clear:async(projectId,agentId)=>{if(!selections.delete(`${projectId}/${agentId}`))throw Object.assign(new Error("\u8FD9\u4E2A agent \u6CA1\u6709\u9009\u7528"),{code:"NOT_FOUND"});return view(projectId)}};return{list:async()=>({presets:[{...PRESET}],credentials:structuredClone(sorted().map(r=>({...r,usedBy:usedByOf(r.id)})))}),projectAgentModels,bind:(id,agents,project)=>{find(id);for(const agentId of agents){selections.set(`${project.id}/${agentId}`,{credentialId:id,projectId:project.id,projectName:project.name,agentId})}},save:async input=>{const key=input.key.trim();const custom=input.preset===CUSTOM_MODEL_PRESET_ID;if(custom&&(!input.endpoint?.startsWith("https://")||!input.model?.trim()))throw Object.assign(new Error("\u81EA\u5B9A\u4E49\u8981\u586B https \u7AEF\u70B9\u548C\u6A21\u578B\u540D"),{code:"VALIDATION_ERROR",details:{field:input.endpoint?"model":"endpoint"}});await wait();const outcome=probe(key);if(outcome!=="ok")return{outcome};const first=rows.length===0;const at=opts.now();if(input.isDefault&&!first)for(const r of rows)r.isDefault=false;const model=input.model?.trim()||(custom?void 0:PRESET.defaultModels.model);if(!model)throw new Error("\u5939\u5177\u6CA1\u6709\u6A21\u578B\u540D");const row={id:`mc-${++seq}`,name:input.name?.trim()||(custom?"\u81EA\u5B9A\u4E49":PRESET.label),preset:custom?CUSTOM_MODEL_PRESET_ID:PRESET.id,endpoint:custom?input.endpoint?.replace(/\/+$/,"")??"":PRESET.endpoint,model,last4:tail(key),isDefault:first||input.isDefault===true,version:1,createdAt:at,replacedAt:null,lastVerifiedAt:at,lastVerifiedMs:PROBE_MS,usedBy:[]};rows.push(row);return{outcome:"ok",credential:structuredClone(row),latencyMs:PROBE_MS}},replaceKey:async(id,raw)=>{const row=find(id);const key=raw.trim();await wait();const outcome=probe(key);if(outcome!=="ok")return{outcome};const at=opts.now();row.last4=tail(key);row.version+=1;row.replacedAt=at;row.lastVerifiedAt=at;row.lastVerifiedMs=PROBE_MS;return{outcome:"ok",credential:structuredClone(row),latencyMs:PROBE_MS}},listProviderModels:async input=>{const custom=input.preset===CUSTOM_MODEL_PRESET_ID;if(custom&&!input.endpoint?.startsWith("https://"))throw Object.assign(new Error("\u81EA\u5B9A\u4E49\u8981\u586B https \u7AEF\u70B9"),{code:"VALIDATION_ERROR",details:{field:"endpoint"}});if(!custom&&(input.endpoint!==void 0||input.authScheme!==void 0))throw Object.assign(new Error("\u7AEF\u70B9\u548C\u9274\u6743\u65B9\u5F0F\u7531\u9884\u8BBE\u5E26\u51FA\uFF0C\u4E0D\u7528\u586B"),{code:"VALIDATION_ERROR"});const key=input.key.trim();await wait();if(key.includes("401"))return{outcome:"unavailable",reason:"\u6A21\u578B\u670D\u52A1\u62D2\u7EDD\u4E86\u8FD9\u4E2A key\uFF08\u65E0\u6548\u6216\u5DF2\u4F5C\u5E9F\uFF09\uFF0C\u53D6\u4E0D\u5230\u6A21\u578B\u5217\u8868"};if(key.includes("down"))return{outcome:"unavailable",reason:"\u8FDE\u4E0D\u4E0A\u6A21\u578B\u670D\u52A1\uFF0C\u53D6\u4E0D\u5230\u6A21\u578B\u5217\u8868"};if(key.includes("nolist"))return{outcome:"unavailable",reason:"\u8FD9\u4E2A\u670D\u52A1\u5546\u6CA1\u6709\u6A21\u578B\u5217\u8868\u63A5\u53E3"};return{outcome:"ok",models:[...FIXTURE_PROVIDER_MODELS]}},listCredentialModels:async id=>{find(id);await wait();return{outcome:"ok",models:[...FIXTURE_PROVIDER_MODELS]}},updateModelCredentialModels:async(id,input)=>{const row=find(id);const model=input.model.trim();if(model.length===0)throw Object.assign(new Error("\u8BF7\u586B\u5199\u6A21\u578B\u540D"),{code:"VALIDATION_ERROR"});await wait();if(model.includes("model-unavailable"))return{outcome:"model_unavailable"};row.model=model;row.version+=1;row.lastVerifiedAt=opts.now();row.lastVerifiedMs=PROBE_MS;return{outcome:"ok",credential:structuredClone(row),latencyMs:PROBE_MS}},setDefault:async id=>{const row=find(id);for(const r of rows)r.isDefault=r===row;return structuredClone(row)},remove:async id=>{const row=find(id);rows.splice(rows.indexOf(row),1);const unselected=[];for(const[k,s]of selections){if(s.credentialId!==id)continue;unselected.push({projectId:s.projectId,agentId:s.agentId});selections.delete(k)}return{unselected}}}}var FixtureNetCredentialError=class extends Error{constructor(status,code,message,details={}){super(message);this.status=status;this.code=code;this.details=details;this.name="BandApiError"}status;code;details};var PURPOSE={BAND_NET_DEFAULT:"\u9ED8\u8BA4\uFF0Cagent \u4E0D\u6307\u5B9A\u7528\u9014\u65F6\u7528",BAND_NET_IMAGE:"\u51FA\u56FE",BAND_NET_TTS:"\u914D\u97F3",BAND_NET_VIDEO:"\u89C6\u9891",BAND_NET_LLM:"\u53E6\u4E00\u4E2A\u6A21\u578B",BAND_NET_MUSIC:"\u914D\u4E50"};var PRESETS=NET_CREDENTIAL_PRESET_NAMES.map(name=>({name,purpose:PURPOSE[name]}));var BEARER={header:"Authorization",prefix:"Bearer "};var PROVIDER_PRESETS=[{id:"ark",scheme:"static",label:"\u706B\u5C71\u65B9\u821F",description:"\u51FA\u56FE\uFF08Seedream\uFF09\u3001\u89C6\u9891\uFF08Seedance\uFF09",keyHint:"\u7528\u63A7\u5236\u53F0\u521B\u5EFA\u7684 API Key\uFF0CAccess Key \u4E0D\u80FD\u7528\u3002",docsUrl:"https://www.volcengine.com/docs/ark/api-key",capabilities:["image","video"],purposes:[{name:"BAND_NET_IMAGE",purpose:"\u51FA\u56FE\uFF08Seedream\uFF09",preselected:true},{name:"BAND_NET_VIDEO",purpose:"\u89C6\u9891\uFF08Seedance\uFF09",preselected:true}],domains:["ark.cn-beijing.volces.com"],inject:BEARER},{id:"vertex",scheme:"gcp_service_account",label:"Google Vertex AI",description:"\u914D\u4E50\uFF08Lyria\uFF09",keyHint:"\u7C98\u8D34\u670D\u52A1\u8D26\u53F7\u7684 JSON key \u6587\u4EF6\uFF1B\u5355\u72EC\u5EFA\u4E00\u4E2A\u8D26\u53F7\uFF0C\u53EA\u7ED9 Vertex AI User \u6743\u9650\u3002",docsUrl:"https://cloud.google.com/iam/docs/keys-create-delete",capabilities:["music"],purposes:[{name:"BAND_NET_MUSIC",purpose:"\u914D\u4E50\uFF08Lyria\uFF09",preselected:true}],domains:["us-central1-aiplatform.googleapis.com"]}];var invalid=(field,message)=>new FixtureNetCredentialError(400,"VALIDATION_ERROR",message,{field});function checkName(name){const suffix=name.startsWith("BAND_NET_")?name.slice("BAND_NET_".length):"";if(!/^[A-Z][A-Z0-9_]{0,31}$/.test(suffix)||suffix.endsWith("_")||suffix.includes("__")||name.endsWith("_BASE_URL")||name.endsWith("_GCP_PROJECT_ID"))throw invalid("name","\u540D\u5B57\u53EA\u80FD\u7528\u5927\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u4E0B\u5212\u7EBF\uFF0C\u540E\u7F00 1\u201332 \u4E2A\u5B57\u7B26\uFF0C\u4E0D\u80FD\u4EE5\u4E0B\u5212\u7EBF\u7ED3\u5C3E\uFF0C\u4E0D\u80FD\u4EE5 _BASE_URL \u7ED3\u5C3E")}function checkDomains(domains){if(domains.length===0)throw invalid("domains","\u81F3\u5C11\u5199\u4E00\u4E2A\u751F\u6548\u57DF\u540D");if(domains.length>10)throw invalid("domains","\u6700\u591A 10 \u4E2A");for(const d of domains){if(/[/:@?#\s]/.test(d)||d!==d.toLowerCase())throw invalid("domains","\u53EA\u5199\u57DF\u540D\uFF0C\u4E0D\u5E26 https:// \u548C\u8DEF\u5F84");if(d==="localhost"||/^\d+(\.\d+){3}$/.test(d)||!d.includes("."))throw invalid("domains","\u4E0D\u80FD\u662F IP\u3001localhost \u6216\u5185\u7F51\u540E\u7F00")}}function checkKey(key){if(!key||key.length>4096||key!==key.trim()||/[\u0000-\u001f\u007f]/.test(key))throw invalid("key","key \u4E0D\u80FD\u6709\u6362\u884C\uFF0C\u4E0D\u80FD\u6709\u524D\u540E\u7A7A\u683C\uFF0C\u6700\u957F 4096 \u4E2A\u5B57\u7B26")}function checkServiceAccount(raw){let parsed;try{parsed=JSON.parse(raw)}catch{throw invalid("serviceAccount","\u670D\u52A1\u8D26\u53F7 JSON \u89E3\u6790\u4E0D\u5F00\uFF0C\u6574\u4EFD\u7C98\u8D34 key \u6587\u4EF6\u7684\u5185\u5BB9")}const o=parsed??{};if(o.type!=="service_account"||typeof o.project_id!=="string"||typeof o.client_email!=="string"||typeof o.private_key!=="string")throw invalid("serviceAccount","\u8981 type \u4E3A service_account \u7684 JSON key \u6587\u4EF6");return{projectId:o.project_id,clientEmail:o.client_email}}var keyOf=o=>o.kind==="user"?"user":`project:${o.projectId}`;function fixtureNetCredentials(opts){const byOwner=new Map;let seq=0;const rowsOf=o=>{const k=keyOf(o);let rows=byOwner.get(k);if(!rows){rows=[];byOwner.set(k,rows)}return rows};const find=(o,id)=>{const row=rowsOf(o).find(r=>r.id===id);if(!row)throw new FixtureNetCredentialError(404,"NOT_FOUND","\u6CA1\u6709\u8FD9\u6761\u7F51\u7EDC\u51ED\u636E");return row};const checkCreate=(rows,inputs)=>{if(inputs.length===0)throw invalid("name","\u81F3\u5C11\u5EFA\u4E00\u6761\u7F51\u7EDC\u51ED\u636E");for(const input of inputs)checkName(input.name);const names=inputs.map(i=>i.name);const duplicated=names.find((n,i)=>names.indexOf(n)!==i);const taken=duplicated??names.find(n=>rows.some(r=>r.name===n))??void 0;if(taken)throw new FixtureNetCredentialError(409,"CONFLICT",`\u5DF2\u7ECF\u6709\u4E00\u6761\u53EB ${taken} \u7684`,{reason:"NAME_TAKEN"});if(rows.length+inputs.length>50)throw new FixtureNetCredentialError(409,"CONFLICT","\u6700\u591A 50 \u6761\uFF0C\u5148\u5220\u6389\u4E0D\u7528\u7684",{reason:"LIMIT_REACHED"});for(const input of inputs){if(input.note!==void 0&&input.note.length>40)throw invalid("note","\u5907\u6CE8\u6700\u591A 40 \u4E2A\u5B57");checkDomains(input.domains);if("serviceAccount"in input)checkServiceAccount(input.serviceAccount);else checkKey(input.key)}};const build=(owner,input)=>{seq+=1;if("serviceAccount"in input){const gcp=checkServiceAccount(input.serviceAccount);return{id:`nc-${seq}`,ownerKind:owner.kind,name:input.name,note:input.note??null,domains:[...input.domains],scheme:"gcp_service_account",gcp,inject:BEARER,last4:null,version:1,createdAt:opts.now(),replacedAt:null}}return{id:`nc-${seq}`,ownerKind:owner.kind,name:input.name,note:input.note??null,domains:[...input.domains],scheme:"static",gcp:null,inject:input.inject??BEARER,last4:input.key.length>=12?input.key.slice(-4):null,version:1,createdAt:opts.now(),replacedAt:null}};return{list:async()=>structuredClone({presets:PRESETS,providerPresets:PROVIDER_PRESETS,credentials:rowsOf({kind:"user"}),canManage:true}),listProject:async projectId=>{const project=rowsOf({kind:"project",projectId});const names=new Set(project.map(c=>c.name));const effective=[...project.map(c=>({credentialId:c.id,name:c.name,domains:c.domains,source:"project",ownerId:projectId})),...rowsOf({kind:"user"}).filter(c=>!names.has(c.name)).map(c=>({credentialId:c.id,name:c.name,domains:c.domains,source:"creator",ownerId:opts.userId??"me"}))];return structuredClone({presets:PRESETS,providerPresets:PROVIDER_PRESETS,credentials:project,canManage:true,effective})},save:async(owner,input)=>{const rows=rowsOf(owner);checkCreate(rows,[input]);const row=build(owner,input);rows.push(row);return structuredClone({credential:row})},saveMany:async(owner,input)=>{const rows=rowsOf(owner);checkCreate(rows,input.credentials);const created=input.credentials.map(c=>build(owner,c));rows.push(...created);return structuredClone({credentials:created})},update:async(owner,id,input)=>{const row=find(owner,id);if(input.domains)checkDomains(input.domains);if(typeof input.note==="string"&&input.note.length>40)throw invalid("note","\u5907\u6CE8\u6700\u591A 40 \u4E2A\u5B57");if(row.scheme==="gcp_service_account"&&input.inject)throw invalid("inject","GCP \u670D\u52A1\u8D26\u53F7\u51ED\u636E\u56FA\u5B9A\u6CE8\u5165 Authorization: Bearer\uFF0C\u4E0D\u80FD\u6539\u6CE8\u5165\u683C\u5F0F");const bump=input.domains&&input.domains.join("\n")!==row.domains.join("\n")||input.inject&&(input.inject.header!==row.inject.header||input.inject.prefix!==row.inject.prefix);if(input.note!==void 0)row.note=input.note;if(input.domains)row.domains=[...input.domains];if(input.inject)row.inject={...input.inject};if(bump){row.version+=1;row.replacedAt=opts.now()}return structuredClone({credential:row})},replaceKey:async(owner,id,value)=>{const row=find(owner,id);if("serviceAccount"in value){if(row.scheme!=="gcp_service_account")throw invalid("serviceAccount","\u8FD9\u6761\u662F\u9759\u6001 key \u51ED\u636E\uFF0C\u6362 key \u7528 key \u5B57\u6BB5");row.gcp=checkServiceAccount(value.serviceAccount)}else{if(row.scheme!=="static")throw invalid("key","\u8FD9\u6761\u662F GCP \u670D\u52A1\u8D26\u53F7\u51ED\u636E\uFF0C\u6574\u4EFD\u91CD\u8D34\u670D\u52A1\u8D26\u53F7 JSON");checkKey(value.key);row.last4=value.key.length>=12?value.key.slice(-4):null}row.version+=1;row.replacedAt=opts.now();return structuredClone({credential:row})},remove:async(owner,id)=>{find(owner,id);const rows=rowsOf(owner);byOwner.set(keyOf(owner),rows.filter(r=>r.id!==id));return{invalidatedSessions:0,stops:0}}}}function agentsOfWorkshop(w){const out=new Set([DEFAULT_AGENT]);for(const wf of w.workflows)for(const st of wf.stages)if(st.kind==="agent"&&st.agent)out.add(st.agent);return[...out]}function liveVersion(p){const versions=p.detail?.versions;if(!versions)return p.version;return versions.find(v=>v.yanked===void 0)?.version}function liveCard(p){const{usedIn=[],detail={},...card}=p;const version=liveVersion(p)??card.version;const versions=(detail.versions??[{version:card.version,current:true}]).map(v=>({...v,current:v.version===version}));return{card:{...card,version},usedIn,detail,versions}}var SOURCE_ORDER={official:0,shared:1,workshop:2};function cardOf(w){const{hubProjectId:_h,ref:_r,admins:_a,workflows:_w,artifactTypes:_t,roles:_ro,views:_v,releases:_re,formTarget:_f,...card}=w;return{...card,stages:w.stages.map(s=>({id:s.id,...s.label?{label:s.label}:{},kind:s.kind}))}}var includes=(text,q)=>text.toLowerCase().includes(q);function createFixtureAppData(seed,opts={}){const state=structuredClone(seed);state.inbox??={needsYou:[],inProgress:[]};state.threads??=[];const now=opts.now??(()=>new Date().toISOString());const modelCredentials=fixtureModelCredentials({now,...opts.seedModelCredential?{seedDefault:true}:{},projectPolicy:projectId=>{const w=state.workshops.find(x=>x.id===workshopOfProject(projectId));return{policy:w?.userModelKey??"off",agents:w?agentsOfWorkshop(w):[],teamKey:(w?.userModelKey??"off")!=="require"}}});let seq=0;const newId=opts.newId??(()=>`p-${++seq}`);const listeners=new Set;const notify=()=>{for(const fn of[...listeners])fn()};const workshopOfProject=projectId=>state.projects.find(p=>p.project.id===projectId)?.workshop.id;const inWorkshop=(projectId,f)=>f?.workshop===void 0||workshopOfProject(projectId)===f.workshop;let mentionsOnly=false;let guide={status:"off",step:1,total:7};const feedback=[{id:"fb-2",author:"chen",authorName:"\u9648\u9759",createdAt:"2026-11-05T09:30:00.000Z",pageUrl:"/w/teaching-tool/fen-niu",projectId:null,projectName:"\u5206\u725B\u95EE\u9898",workshopId:"teaching-tool",workshopName:"\u6559\u5177",body:"\u6279\u51C6\u6309\u94AE\u70B9\u4E86\u6CA1\u53CD\u5E94\uFF0C\u5237\u65B0\u540E\u624D\u53D8\u6210\u5DF2\u6279\u51C6\u3002",status:"new",adminNote:null,reply:null,repliedBy:null,repliedAt:null,replySeenAt:null},{id:"fb-1",author:"zhou",authorName:null,createdAt:"2026-11-04T15:10:00.000Z",pageUrl:"/",projectId:null,projectName:null,workshopId:null,workshopName:null,body:"\u9996\u9875\u7684\u641C\u7D22\u6846\u80FD\u4E0D\u80FD\u652F\u6301\u6309\u5DE5\u574A\u7B5B\u9009\uFF1F",status:"seen",adminNote:null,reply:null,repliedBy:null,repliedAt:null,replySeenAt:null}];const withAlert=i=>mentionsOnly?{...i,alert:i.kind==="mention"}:i;function inbox(f){const box=state.inbox??{needsYou:[],inProgress:[]};return{needsYou:box.needsYou.filter(i=>inWorkshop(i.projectId,f)).map(withAlert),inProgress:box.inProgress.filter(i=>inWorkshop(i.projectId,f))}}function projects(f){const needs=needsMeByProject((state.inbox?.needsYou??[]).map(withAlert));return state.projects.filter(p=>f?.workshop===void 0||p.workshop.id===f.workshop).filter(p=>p.project.archivedAt===void 0).map(p=>({...p,needsMe:needs.get(p.project.id)??0}))}function workshops(f){return state.workshops.filter(w=>f?.workshop===void 0||w.id===f.workshop).filter(w=>f?.archived===true===(w.archivedAt!==void 0)).map(cardOf)}const copy=v=>Promise.resolve(structuredClone(v));return{workshops:async f=>copy(workshops(f)),workshop:async id=>copy(state.workshops.find(w=>w.id===id)??null),projects:async f=>copy(projects(f)),inbox:async f=>copy(inbox(f)),myArtifacts:async(query={})=>copy({query:{...query.tab!==void 0?{tab:query.tab}:{},...query.workshop!==void 0?{workshop:query.workshop}:{},...query.project!==void 0?{project:query.project}:{},...query.type!==void 0?{type:query.type}:{},...query.status!==void 0?{status:query.status}:{},...query.q!==void 0?{q:query.q}:{}},counts:{joined:0,mine:0,review:0,starred:0},facets:{workshops:[],projects:[],types:[]},rows:[]}),search:async(query,f)=>{const q=query.trim().toLowerCase();if(q==="")return{projects:[],workshops:[],threads:[]};return copy({projects:projects(f).filter(p=>includes(p.project.name,q)),workshops:workshops(f).filter(w=>includes(w.name,q)||includes(w.description,q)||includes(w.id,q)),threads:(state.threads??[]).filter(t=>inWorkshop(t.projectId,f)&&(includes(t.excerpt,q)||includes(t.projectName,q)||includes(`#${t.mark}`,q)))})},plugins:async(query={})=>{const q=query.q?.trim().toLowerCase()??"";const list=(state.plugins??[]).filter(p=>query.workshop===void 0?p.source!=="workshop":p.workshop?.id===query.workshop||(p.usedIn??[]).includes(query.workshop)).filter(p=>query.kind===void 0||p.kinds.includes(query.kind)).filter(p=>p.source==="official"||liveVersion(p)!==void 0).filter(p=>q===""||[p.name,p.title,p.description??"",...p.keywords??[]].some(t=>includes(t,q))).map((p,i)=>({p,i})).sort((a,b)=>SOURCE_ORDER[a.p.source]-SOURCE_ORDER[b.p.source]||a.i-b.i).map(({p})=>liveCard(p).card);return copy(list)},plugin:async name=>{const p=(state.plugins??[]).find(x=>x.name===name&&x.source!=="workshop");if(!p)return null;const{card,usedIn,detail,versions}=liveCard(p);const names=new Map(state.workshops.map(w=>[w.id,w.name]));return copy({...card,...detail.readme?{readme:detail.readme}:{},versions,...detail.canYank?{canYank:true}:{},face:detail.face??{contributions:[],slots:[],services:[],anchors:[]},resources:detail.resources??[],usedIn:usedIn.map(id=>({id,name:names.get(id)??id}))})},subscribe:fn=>{listeners.add(fn);return()=>listeners.delete(fn)},write:{...opts.platformTokens?{platformTokens:opts.platformTokens}:{},modelCredentials,projectAgentModels:modelCredentials.projectAgentModels,netCredentials:fixtureNetCredentials({now}),feedbackAdmin:{isAdmin:async()=>true,list:async query=>{const want=query.status??"open";const items=feedback.filter(f=>want==="all"?true:want==="open"?f.status!=="resolved":f.status===want);return{items:structuredClone(items),nextCursor:null}},patch:async(id,input)=>{const row=feedback.find(f=>f.id===id);if(!row)throw new Error("\u6CA1\u6709\u8FD9\u6761\u53CD\u9988");if(input.status!==void 0)row.status=input.status;if(input.adminNote!==void 0)row.adminNote=input.adminNote;if(input.reply!==void 0){row.reply=input.reply;row.repliedBy=input.reply===null?null:"kld";row.repliedAt=input.reply===null?null:now();if(input.reply!==null)row.replySeenAt=null}notify();return{feedback:structuredClone(row)}}},pluginYank:{yank:async(name,version,reason)=>{const v=state.plugins?.find(p=>p.name===name&&p.source==="shared")?.detail?.versions?.find(x=>x.version===version);if(!v)throw new Error("\u63D2\u4EF6\u7248\u672C\u4E0D\u5B58\u5728\u6216\u6CA1\u5171\u4EAB");if(v.yanked)throw new Error(`${name}@${version} \u5DF2\u7ECF\u64A4\u56DE\u4E86`);v.yanked={reason};notify()},unyank:async(name,version)=>{const v=state.plugins?.find(p=>p.name===name&&p.source==="shared")?.detail?.versions?.find(x=>x.version===version);if(!v?.yanked)throw new Error(`${name}@${version} \u6CA1\u6709\u64A4\u56DE`);v.yanked=void 0;notify()}},guide:{get:async()=>guide,set:async action=>{guide=action==="restart"||guide.status==="done"||guide.status==="off"?{status:"active",step:1,total:7}:{...guide,status:action==="collapse"?"collapsed":action==="skip"?"skipped":"active"};notify();return guide}},userSettings:{get:async()=>({mentionsOnly}),set:async patch=>{if(patch.mentionsOnly!==void 0)mentionsOnly=patch.mentionsOnly;notify();return{mentionsOnly}}},createProject:async({workshop:workshop2,name,modelCredentialId})=>{const w=state.workshops.find(x=>x.id===workshop2&&x.archivedAt===void 0);if(!w)throw new Error(`\u6CA1\u6709\u5DE5\u574A ${workshop2}`);const policy=w.userModelKey??"off";const mine=policy==="off"?null:await modelCredentials.list();if(modelCredentialId!==void 0){if(policy==="off")throw Object.assign(new Error("\u8FD9\u4E2A\u5DE5\u574A\u53EA\u7528\u56E2\u961F key\uFF0C\u5EFA\u9879\u76EE\u65F6\u4E0D\u80FD\u9009\u6A21\u578B\u914D\u7F6E"),{code:"VALIDATION_ERROR"});if(!mine?.credentials.some(c=>c.id===modelCredentialId))throw Object.assign(new Error("\u6A21\u578B\u914D\u7F6E\u4E0D\u5B58\u5728"),{code:"NOT_FOUND"})}const bind=modelCredentialId??mine?.credentials.find(c=>c.isDefault)?.id;if(policy==="require"&&bind===void 0)throw Object.assign(new Error("\u8FD9\u4E2A\u5DE5\u574A\u8981\u7528\u4F60\u81EA\u5DF1\u7684\u6A21\u578B\u914D\u7F6E\uFF1A\u5230\u4E2A\u4EBA\u8BBE\u7F6E\u6DFB\u52A0\u4E00\u4EFD\u6A21\u578B\u914D\u7F6E\uFF0C\u518D\u5EFA\u9879\u76EE"),{code:"CONFLICT",details:{reason:"model-required"}});const trimmed=name.trim();if(trimmed==="")throw new Error("\u9879\u76EE\u540D\u4E0D\u80FD\u4E3A\u7A7A");if(trimmed.length>200)throw new Error("\u9879\u76EE\u540D\u6700\u957F 200 \u5B57");const id=newId();const at=now();if(bind!==void 0)modelCredentials.bind(bind,agentsOfWorkshop(w),{id,name:trimmed});state.projects.unshift({project:{id,name:trimmed,workshopRef:w.id,createdBy:state.me.id,createdAt:at},workshop:{id:w.id,name:w.name,...w.icon?{icon:w.icon}:{}},myRoles:w.roles.map(r=>r.name),canAdmin:true,memberCount:1,lastActivityAt:at});w.projectCount+=1;notify();return{id}},markRead:async commentId=>{const box=state.inbox;if(!box)return;const before=box.needsYou.length;box.needsYou=box.needsYou.filter(i=>!(i.kind==="mention"&&i.commentId===commentId));if(box.needsYou.length!==before)notify()}},update:fn=>{fn(state);notify()}}}var T=d=>`2026-10-${d}Z`;function workshop(w){return{id:w.id,name:w.name,description:w.description,maintainer:w.maintainer,scope:w.scope,...w.icon?{icon:w.icon}:{},version:w.version,stages:w.stages.map(s=>({id:s.id,kind:s.kind})),projectCount:w.projectCount,canAdmin:false,hubProjectId:`hub-${w.id}`,model:{state:"not_provisioned",hubProject:"ready",agent:"ready"},ref:"main",admins:[],workflows:[{name:"main",stages:w.stages}],...w.formTarget?{formTarget:w.formTarget}:{},artifactTypes:w.artifactTypes,roles:w.roles,views:{plugins:w.plugins,viewers:[]},releases:w.releases.map((r,i)=>({version:w.releases.length-i,workshopHash:`${w.id}-${w.releases.length-i}`.padEnd(12,"0"),commit:`c${(w.releases.length-i).toString(16).padStart(6,"0")}`,note:r.note,publishedBy:w.maintainer,publishedAt:r.at}))}}function sampleAppFixture(){const teaching=workshop({id:"teaching",name:"\u6559\u5177",description:"\u628A\u4E00\u4E2A\u77E5\u8BC6\u70B9\u505A\u6210\u80FD\u5728\u8BFE\u5802\u4E0A\u62D6\u3001\u70B9\u3001\u6F14\u793A\u7684\u4E92\u52A8\u6559\u5177\uFF1B\u6559\u7814\u786E\u8BA4\u9700\u6C42\uFF0C\u8BBE\u8BA1\u628A\u5173\uFF0C\u8001\u5E08\u8BD5\u7528\u3002",maintainer:"\u6559\u7814\u4E2D\u53F0",scope:"public",icon:"genre:classical",version:4,stages:[{id:"\u9700\u6C42",kind:"human",needs:[],produces:["brief"]},{id:"\u751F\u6210",kind:"agent",agent:"rondo",needs:["\u9700\u6C42:brief"],produces:["tool"]},{id:"\u8BC4\u5BA1",kind:"human",needs:["\u751F\u6210:tool"],produces:[],gate:{approveBy:["designer","teacher"],mode:"all",noteRequired:false}},{id:"\u4E0A\u67B6",kind:"external",needs:["\u751F\u6210:tool"],produces:[]}],artifactTypes:[{name:"brief",storage:"store"},{name:"tool",storage:"git"}],roles:[{name:"researcher",permissions:["comment","submit-change","confirm","admin"]},{name:"designer",permissions:["comment","approve"]},{name:"teacher",permissions:["comment","approve","publish"]}],projectCount:38,releases:[{note:"\u8BC4\u5BA1\u6539\u6210\u8BBE\u8BA1\u4E0E\u8001\u5E08\u90FD\u8981\u6279",at:T("20T08:00:00")},{note:"\u4E0A\u67B6\u63A5\u8BFE\u4EF6\u5E93",at:T("12T03:30:00")},{note:"\u751F\u6210\u9636\u6BB5\u6362\u6210 Rondo",at:T("02T09:00:00")},{note:"\u9996\u7248",at:"2026-09-18T06:00:00Z"}],plugins:["band-stages","band-threads","viewer-web"],formTarget:{stage:"\u9700\u6C42"}});const site=workshop({id:"site",name:"\u5EFA\u7AD9",description:"\u6D3B\u52A8\u9875\u3001\u843D\u5730\u9875\u3001\u5C0F\u7AD9\u70B9\uFF1A\u5199\u6E05\u76EE\u6807\u548C\u7D20\u6750\uFF0CRondo \u51FA\u7AD9\uFF0C\u8FD0\u8425\u6539\u5B57\uFF0C\u4E00\u952E\u53D1\u5E03\u5230 rush\u3002",maintainer:"\u589E\u957F\u7EC4",scope:"team",icon:"genre:pop",version:7,stages:[{id:"brief",kind:"human",needs:[],produces:["brief"],params:{type:"object",properties:{kind:{type:"string",title:"\u7AD9\u70B9\u7C7B\u578B",enum:["landing","docs"],enumNames:["\u843D\u5730\u9875","\u6587\u6863\u7AD9"]}},required:["kind"]}},{id:"build",kind:"agent",agent:"rondo",needs:["brief:brief"],produces:["site"]},{id:"publish",kind:"external",needs:["build:site"],produces:[]}],artifactTypes:[{name:"brief",storage:"store"},{name:"site",storage:"git"}],roles:[{name:"owner",permissions:["comment","submit-change","confirm","publish","admin"]},{name:"editor",permissions:["comment","submit-change"]}],projectCount:112,releases:[{note:"\u53D1\u5E03\u524D\u8DD1\u4E00\u904D\u94FE\u63A5\u68C0\u67E5",at:T("21T02:00:00")},{note:"\u9884\u89C8\u6539\u6210\u5B9E\u65F6\u9884\u89C8",at:T("15T10:00:00")}],plugins:["band-chat","viewer-web"],formTarget:{stage:"brief"}});const video=workshop({id:"video",name:"\u89C6\u9891",description:"\u5BA3\u4F20\u7247\u3001\u8BFE\u7A0B\u7247\u5934\uFF1A\u5206\u955C\u3001\u65C1\u767D\u3001\u526A\u8F91\u4E00\u6761\u7EBF\uFF0C\u6309\u955C\u5934\u63D0\u610F\u89C1\u3002",maintainer:"\u54C1\u724C\u8BBE\u8BA1",scope:"public",icon:"genre:jazz",version:2,stages:[{id:"\u5206\u955C",kind:"agent",agent:"rondo",needs:[],produces:["storyboard"]},{id:"\u65C1\u767D",kind:"agent",agent:"rondo",needs:["\u5206\u955C:storyboard"],produces:["vo"]},{id:"\u526A\u8F91",kind:"human",needs:["\u5206\u955C:storyboard","\u65C1\u767D:vo"],produces:["cut"],gate:{approveBy:["director"],mode:"any",noteRequired:true}}],artifactTypes:[{name:"storyboard",storage:"store"},{name:"vo",storage:"store"},{name:"cut",storage:"external"}],roles:[{name:"director",permissions:["comment","submit-change","confirm","approve","admin"]},{name:"editor",permissions:["comment"]}],projectCount:9,releases:[{note:"\u526A\u8F91\u95E8\u7981\u8981\u5199\u8BF4\u660E",at:T("19T07:00:00")},{note:"\u9996\u7248",at:T("01T07:00:00")}],plugins:["band-stages","viewer-media"]});const ws=w=>({id:w.id,name:w.name,...w.icon?{icon:w.icon}:{}});const project=(id,name,w,myRoles,lastActivityAt,memberCount)=>({project:{id,name,workshopRef:w.id,createdBy:"wangmin",createdAt:T("10T02:00:00")},workshop:ws(w),myRoles,canAdmin:myRoles.includes("researcher")||myRoles.includes("owner"),memberCount,lastActivityAt});return{me:{id:"wangmin",displayName:"\u738B\u654F",title:"\u6570\u5B66\u6559\u7814"},workshops:[teaching,site,video],projects:[project("jitu","\u9E21\u5154\u540C\u7B3C",teaching,["researcher"],T("23T01:40:00"),4),project("fenshu","\u5206\u6570\u7684\u610F\u4E49",teaching,["researcher"],T("22T09:12:00"),3),project("chunzhao","\u6625\u62DB\u6D3B\u52A8\u9875",site,["owner"],T("23T00:55:00"),5),project("zhoukao","\u5468\u8003\u6210\u7EE9\u5355",site,["editor"],T("18T06:00:00"),2),project("xinxueqi","\u65B0\u5B66\u671F\u5BA3\u4F20\u7247",video,["editor"],T("21T11:30:00"),6)],inbox:{needsYou:[{kind:"confirm",projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-3",mark:3,at:T("23T01:40:00")},{kind:"mention",projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-5",commentId:"c-12",mark:5,by:"\u674E\u7136",at:T("23T01:20:00")},{kind:"publish",projectId:"chunzhao",projectName:"\u6625\u62DB\u6D3B\u52A8\u9875",runId:"run-1",stage:"publish",at:T("23T00:55:00"),alert:false},{kind:"unsent",projectId:"fenshu",projectName:"\u5206\u6570\u7684\u610F\u4E49",count:2,at:T("22T09:12:00"),alert:false}],inProgress:[{projectId:"xinxueqi",projectName:"\u65B0\u5B66\u671F\u5BA3\u4F20\u7247",runId:"run-2",stage:"\u65C1\u767D",agent:"rondo",status:"running",since:T("23T01:50:00")},{projectId:"chunzhao",projectName:"\u6625\u62DB\u6D3B\u52A8\u9875",runId:"run-1",stage:"build",agent:"rondo",status:"queued",position:1,since:T("23T01:52:00")}]},threads:[{projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-3",mark:3,status:"awaiting_confirm",excerpt:"\u5154\u5B50\u7684\u811A\u6570\u6CA1\u6709\u8DDF\u7740\u5207\u6362\u53D8\u5316\uFF0C\u62D6\u52A8\u4EE5\u540E\u8FD8\u662F 2 \u53EA\u811A"},{projectId:"jitu",projectName:"\u9E21\u5154\u540C\u7B3C",threadId:"t-5",mark:5,status:"open",excerpt:"\u8BB2\u89E3\u5047\u8BBE\u6CD5\u90A3\u4E00\u6B65\u5B57\u592A\u5C0F\uFF0C\u6295\u5F71\u4E0A\u770B\u4E0D\u6E05"},{projectId:"chunzhao",projectName:"\u6625\u62DB\u6D3B\u52A8\u9875",threadId:"t-2",mark:2,status:"open",excerpt:"\u62A5\u540D\u6309\u94AE\u5728\u624B\u673A\u4E0A\u88AB\u5E95\u90E8\u680F\u6321\u4F4F\u4E86"}],plugins:samplePlugins()}}function samplePlugins(){const official=(short,title,kinds,description,keywords,usedBy)=>({name:`@kanyun-ai-infra/band-${short}`,version:"0.0.0",title,description,keywords,kinds,source:"official",usedBy});return[official("viewer-web","\u7F51\u9875",["viewer"],"\u5728\u72EC\u7ACB\u9884\u89C8\u6E90\u91CC\u6253\u5F00\u7F51\u9875\u7C7B\u4EA7\u7269\uFF0C\u652F\u6301\u5143\u7D20\u6807\u6CE8\u4E0E\u5B9E\u65F6\u9884\u89C8",["\u7F51\u9875","\u9884\u89C8","\u6807\u6CE8"],3),official("viewer-text","\u6587\u6863",["viewer"],"Markdown \u4E0E\u7EAF\u6587\u672C\uFF0C\u6309\u6BB5\u843D\u3001\u9009\u4E2D\u6587\u5B57\u63D0\u610F\u89C1",["\u6587\u6863","markdown"],4),official("viewer-image","\u56FE\u7247",["viewer"],"\u56FE\u7247\u4E0E\u5019\u9009\u7F51\u683C\uFF0C\u6846\u9009\u533A\u57DF\u63D0\u610F\u89C1\uFF0C\u7248\u672C\u5E76\u6392\u5BF9\u6BD4",["\u56FE\u7247","\u5019\u9009","\u5BF9\u6BD4"],2),official("viewer-media","\u97F3\u89C6\u9891",["viewer"],"\u97F3\u9891\u4E0E\u89C6\u9891\uFF0C\u6309\u65F6\u95F4\u70B9\u63D0\u610F\u89C1\uFF0C\u9010\u5E27\u5BF9\u9F50",["\u89C6\u9891","\u97F3\u9891","\u65F6\u95F4\u8F74"],1),official("stages","\u6D41\u7A0B",["panel"],"\u9636\u6BB5\u5217\u8868\u4E0E\u8FDB\u5EA6\uFF0C\u70B9\u9636\u6BB5\u770B\u5F53\u65F6\u4EA4\u51FA\u7684\u7248\u672C",["\u9636\u6BB5","\u6D41\u7A0B"],5),official("threads","\u610F\u89C1",["panel"],"\u6309\u72B6\u6001\u5217\u51FA\u610F\u89C1\u7EBF\u7A0B\uFF0C\u70B9\u5F00\u5B9A\u4F4D\u5230\u5185\u5BB9\u4E0A",["\u610F\u89C1","\u8BC4\u5BA1"],5),official("chat","\u5BF9\u8BDD",["panel"],"\u548C Agent \u7684\u5BF9\u8BDD\u6D41\uFF0C\u6BCF\u6761\u6D88\u606F\u6302\u5728\u6574\u4EFD\u4EA7\u7269\u4E0A",["\u5BF9\u8BDD","Agent"],3),{name:"@site/rush-db",version:"1.2.0",title:"\u6570\u636E\u5E93",description:"\u67E5\u770B\u4E0E\u7F16\u8F91\u5EFA\u7AD9\u9879\u76EE\u7684\u6570\u636E\u8868\uFF0C\u5199\u7EBF\u4E0A\u524D\u786E\u8BA4",keywords:["\u6570\u636E\u5E93","\u8868\u683C"],kinds:["panel","toolbar"],source:"shared",workshop:{id:"site",name:"\u5EFA\u7AD9"},usedBy:2,usedIn:["site","video"],detail:{readme:"# \u6570\u636E\u5E93\n\n\u67E5\u770B\u4E0E\u7F16\u8F91\u5EFA\u7AD9\u9879\u76EE\u7684\u6570\u636E\u8868\u3002\u6539\u7EBF\u4E0A\u6570\u636E\u524D\u5148\u5F39\u786E\u8BA4\u3002\n\n```yaml\nviews:\n plugins:\n - '@site/rush-db@1.2.0'\n```\n",versions:[{version:"1.2.0",registeredAt:"2026-10-20T08:00:00.000Z",current:true,pinned:{workshops:1,instances:2}},{version:"1.1.0",registeredAt:"2026-10-12T08:00:00.000Z",current:false,pinned:{workshops:1,instances:1},behind:true}],face:{contributions:[{slot:"@kanyun-ai-infra/band-project/panels",id:"db",title:"\u6570\u636E\u5E93"},{slot:"@kanyun-ai-infra/band-viewer-web/toolbar",id:"db-open",title:"\u770B\u6570\u636E"}],slots:[{name:"row.actions",kind:"list",scope:"project"}],services:[{name:"tables",scope:"project"}],anchors:[]},resources:[{key:"tables",api:"https://db.example.test",read:["GET /tables/*"],write:["POST /tables/*"],prod:["DELETE /tables/*"]}]}},{name:"@teaching/storyboard",version:"0.3.0",title:"\u5206\u955C\u5899",description:"\u628A\u6559\u5177\u7684\u6BCF\u4E00\u6B65\u6392\u6210\u5206\u955C\uFF0C\u6309\u955C\u5934\u63D0\u610F\u89C1",kinds:["viewer"],source:"workshop",workshop:{id:"teaching",name:"\u6559\u5177"},usedBy:1,usedIn:["teaching"]}]}async function blobBytes(blob){if(typeof blob.arrayBuffer==="function")return new Uint8Array(await blob.arrayBuffer());return new Promise((resolve,reject)=>{const r=new FileReader;r.onload=()=>resolve(new Uint8Array(r.result));r.onerror=()=>reject(r.error);r.readAsArrayBuffer(blob)})}async function sha256Hex(bytes){const digest=await crypto.subtle.digest("SHA-256",bytes);return[...new Uint8Array(digest)].map(b=>b.toString(16).padStart(2,"0")).join("")}function createFixtureTransport(data,opts){const now=opts.now??(()=>new Date().toISOString());let actor=opts.actor;const threads=new Map((data.threads??[]).map(t2=>[t2.id,structuredClone(t2)]));const attachments=new Map((data.attachments??[]).map(({url,...meta})=>[meta.id,{meta:structuredClone(meta),...url?{url}:{}}]));const memory=(data.memory??[]).map((m,i)=>({meta:memoryMeta(i+1,m,m.files),files:structuredClone(m.files)}));const comments=structuredClone(data.comments??[]);const stages=new Map((data.stages??[]).map(s=>[s.stage,{...s}]));const gates=new Map((data.gates??[]).map(g=>[g.stage,{...g,approvedBy:[...g.approvedBy],...g.approvals?{approvals:g.approvals.map(a=>({...a}))}:{}}]));const versions=new Map(data.versions.map(v=>[v.id,v]));const members=structuredClone(data.members??[]);const turn=structuredClone(data.turn??{current:null,last:null,queue:[]});const defaultAgent=opts.defaultAgent??DEFAULT_AGENT2;const audit=[];const activity=structuredClone(data.activity??[]);const listeners=new Set;let seq=0;const seeded=new Set([...threads.keys(),...comments.map(c=>c.id),...versions.keys(),...activity.map(a=>a.id),...attachments.keys(),...turn.current?[turn.current.changeRequestId]:[],...turn.queue.map(q=>q.changeRequestId)]);const nextId=prefix=>{let id=`${prefix}_${++seq}`;while(seeded.has(id))id=`${prefix}_${++seq}`;return id};function emit(type,payload){const e={id:nextId("evt"),type,projectId:data.projectId,at:now(),source:"band",payload};for(const fn of[...listeners])fn(e);return e}function record(via,action,detail,level){const at=now();audit.push({at,actor:actor.id,via,action,detail,...level?{level}:{}});const text=activityText(action,detail);if(text){const threadId=typeof detail.threadId==="string"?detail.threadId:void 0;const stage2=typeof detail.stage==="string"?detail.stage:void 0;const versionId=typeof detail.versionId==="string"?detail.versionId:void 0;const artifactId=threadId?threads.get(threadId)?.artifactId:action==="version.deliver"&&versionId?versions.get(versionId)?.artifactId:void 0;activity.push({id:nextId("act"),at,actor,action,text,...threadId?{threadId}:{},...artifactId?{artifactId}:{},...stage2?{stage:stage2}:{},...versionId?{versionId}:{}})}}const nameOf=id=>members.find(m=>m.actor.id===id)?.displayName??id;const markOf=id=>{const t2=typeof id==="string"?threads.get(id):void 0;return t2?`#${t2.mark}`:""};const stageName=s=>typeof s==="string"?stages.get(s)?.name??gates.get(s)?.name??s:"";function activityText(action,d){const who=nameOf(actor.id);switch(action){case"thread.create":return`${who} \u63D0\u4E86\u610F\u89C1 ${markOf(d.threadId)}`;case"thread.comment":return`${who} \u56DE\u590D\u4E86 ${markOf(d.threadId)}`;case"confirmed":return`${who} \u786E\u8BA4\u89E3\u51B3 ${markOf(d.threadId)}`;case"rejected":return`${who} \u6253\u56DE ${markOf(d.threadId)}`;case"withdrawn":return`${who} \u64A4\u56DE\u4E86 ${markOf(d.threadId)}`;case"closed":return`${who} \u5173\u95ED\u4E86 ${markOf(d.threadId)}`;case"reopened":return`${who} \u91CD\u5F00\u4E86 ${markOf(d.threadId)}`;case"change_request.create":{const ids=Array.isArray(d.threadIds)?d.threadIds:[];if(ids.length===0)return null;const t2=threads.get(String(ids[0]));return`${who} \u628A ${ids.map(markOf).join(" ")} \u4EA4\u7ED9\u4E86 ${nameOf(t2?.agent??defaultAgent)}`}case"gate.approve":return`${who} \u6279\u51C6\u4E86 ${stageName(d.stage)}`;case"gate.revoke":return`${who} \u64A4\u56DE\u4E86 ${stageName(d.stage)} \u7684\u6279\u51C6`;case"stage.start":return`${who} \u542F\u52A8\u4E86 ${stageName(d.stage)}`;case"stage.rerun":return`${who} \u91CD\u8DD1\u4E86 ${stageName(d.stage)}`;case"version.human":return`${who} \u76F4\u63A5\u7F16\u8F91\uFF0C\u751F\u6210\u65B0\u7248\u672C`;case"version.deliver":return`${who} \u4EA4\u4ED8\u4E86\u65B0\u7248\u672C`;default:return null}}function projectStage(){const all=[...stages.values()];const first=all.find(s=>s.kind==="agent")??(all.length===1&&all[0]?.kind===void 0?all[0]:void 0);if(!first)throw new Error("\u8FD9\u4E2A\u6D41\u7A0B\u6CA1\u6709 agent \u9636\u6BB5\uFF0C\u9879\u76EE\u7EA7\u7684\u610F\u89C1\u6CA1\u6709\u4EBA\u63A5");return first.stage}function artifactStage(artifactId){const explicit=data.artifacts?.find(a=>a.id===artifactId)?.stage;if(explicit!==void 0)return explicit;const owning=[...stages.values()].find(s=>s.outputs?.some(o=>o.artifactId===artifactId)||s.versionId!==void 0&&versions.get(s.versionId)?.artifactId===artifactId);if(owning)return owning.stage;const[only]=stages.values();if(stages.size===1&&only)return only.stage;throw new Error(`\u6CA1\u6709\u4EA7\u7269 ${artifactId}`)}function threadStage(id){if(id===void 0)return projectStage();const t2=thread(id);return t2.artifactId===void 0?projectStage():artifactStage(t2.artifactId)}function emitChangeRequested(changeRequestId,threadIds){const queued=turn.queue.find(q=>q.changeRequestId===changeRequestId);emit("change.requested",{changeRequestId,stage:queued?.stage,kind:"feedback"});for(const threadId of threadIds){emit("thread.queued",{threadId,by:actor,changeRequestId})}}let turnNumber=turn.current?.number??0;let turnSequence=0;let currentTurnId=turn.current?`turn-${++turnSequence}`:void 0;function emitTurnStarted(stage2,kind){currentTurnId=`turn-${++turnSequence}`;emit("turn.started",{runId:data.runId,turnId:currentTurnId,stage:stage2,kind,number:++turnNumber})}function thread(id){const t2=threads.get(id);if(!t2)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u7EBF\u7A0B ${id}`);return t2}function setStatus(via,id,status,action,event){const t2=thread(id);t2.status=status;t2.updatedAt=now();record(via,action,{threadId:id});emit(event,{threadId:id,by:actor,...action==="closed"?{closed:true}:{}})}function checkExtras(extras={}){for(const id of extras.attachments??[]){if(!attachments.has(id))throw new Error(`\u9644\u4EF6 ${id} \u4E0D\u662F\u5728\u8FD9\u4E2A\u9879\u76EE\u91CC\u4E0A\u4F20\u7684`)}const ex=MessageExtrasSchema.parse(extras);return Object.fromEntries(Object.entries(ex).filter(([,v])=>Array.isArray(v)&&v.length>0))}function addComment(threadId,body,mentions=[],extras={}){if(actor.kind==="human"){for(const c of comments)if(c.threadId===threadId&&c.receipt?.optionsOpen)c.receipt.optionsOpen=void 0}const comment={id:nextId("cmt"),threadId,kind:"comment",author:actor,body,mentions,...extras,createdAt:now()};comments.push(comment);return comment}function enqueue(ids,agent,stage2=threadStage(ids[0])){const own=(stage2===void 0?void 0:stages.get(stage2)?.agent)??defaultAgent;if(agent!==void 0&&agent!==own)throw new Error(`\u8FD9\u4E2A\u9636\u6BB5\u7684 agent \u662F ${own}\uFF0C\u4E0D\u80FD\u4EA4\u7ED9 ${agent}`);const entry={changeRequestId:nextId("cr"),stage:stage2,threadIds:[...ids],agent:(ids[0]?thread(ids[0]).agent:void 0)??own,by:actor,at:now()};for(const id of ids){const s=thread(id).status;if(s==="queued"||s==="running")throw new Error(`\u7EBF\u7A0B ${id} \u5DF2\u7ECF\u4EA4\u7ED9 Agent\uFF08${s}\uFF09`)}for(const id of ids){const t2=thread(id);t2.status="queued";t2.agent=entry.agent;t2.sentBy=actor;t2.updatedAt=entry.at}turn.queue.push(entry);return entry}function gate(stage2){const g=gates.get(stage2);if(!g)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u9636\u6BB5 ${stage2} \u7684\u95E8\u7981`);return g}function gateSatisfied(g){if(!g.approveBy||g.approveBy.length===0)return g.approvedBy.length>0;const roles=g.approveBy;const valid=g.approvedBy.filter(id=>members.some(m=>m.actor.id===id&&m.roles.some(r=>roles.includes(r))));const mode=g.mode??"any";if(typeof mode==="object")return valid.length>=mode.quorum;if(mode==="every"){const holders=members.filter(m=>m.roles.some(r=>roles.includes(r)));return holders.length>0&&holders.every(m=>g.approvedBy.includes(m.actor.id))}const done=g.approveBy.filter(role=>members.some(m=>m.roles.includes(role)&&g.approvedBy.includes(m.actor.id)));return mode==="all"?done.length===g.approveBy.length:done.length>0}function pickedKey(g){const votes=g.approvals??[];return[...new Set(votes.map(a=>a.key))].find(k=>k!==void 0&&gateSatisfied({...g,approvedBy:votes.filter(a=>a.key===k).map(a=>a.userId)}))}function stage(name){const s=stages.get(name);if(!s)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u9636\u6BB5 ${name}`);return s}const blobUrls=new Map;const deliveredFiles=new Map;function file(versionId,path){const f=deliveredFiles.get(versionId)?.[path]??data.files?.[versionId]?.[path];if(f===void 0)throw new Error(`\u5939\u5177\u91CC\u7248\u672C ${versionId} \u6CA1\u6709\u6587\u4EF6 ${path}`);return f}let preview=data.preview;const t={setPreview(p){if(preview===void 0)throw new Error("\u5939\u5177\u6CA1\u6709\u5199 preview\uFF0C\u67E5\u770B\u5668\u62FF\u4E0D\u5230 ctx.live");preview=structuredClone(p)},audit,comments,threads:()=>[...threads.values()],gates:()=>[...gates.values()],turn:()=>structuredClone(turn),emit,actAs(next){actor=next},async readFile(versionId,path){const f=file(versionId,path);if(typeof f==="string")return new TextEncoder().encode(f);if(f instanceof Uint8Array)return f;const res=await fetch(f.url);if(!res.ok)throw new Error(`\u5939\u5177\u6587\u4EF6 ${path} \u53D6\u4E0D\u5230\uFF1A${res.status}`);return new Uint8Array(await res.arrayBuffer())},async objectUrl(versionId,path){const f=file(versionId,path);if(typeof f==="object"&&!(f instanceof Uint8Array))return f.url;if(typeof URL.createObjectURL!=="function")return`fixture://${versionId}/${path}`;const key=`${versionId}\0${path}`;const cached=blobUrls.get(key);if(cached)return cached;const mime=versions.get(versionId)?.entries.find(e=>e.path===path)?.mime;const bytes=typeof f==="string"?new TextEncoder().encode(f):f;const url=URL.createObjectURL(new Blob([bytes],mime?{type:mime}:{}));blobUrls.set(key,url);return url},async listThreads(filter){return[...threads.values()].filter(t2=>matches(t2,filter)).map(t2=>structuredClone(t2))},async listComments(threadId){thread(threadId);return structuredClone(comments.filter(c=>c.threadId===threadId))},async listVersions(artifactId){return structuredClone([...versions.values()].filter(v=>v.artifactId===artifactId).sort((a,b)=>a.createdAt.localeCompare(b.createdAt)))},async listMembers(){return structuredClone(members)},async projectUsage(){return null},async turnState(){return structuredClone(turn)},async gateState(name){return structuredClone(gate(name))},async stage(name){return{...stage(name)}},async listStages(){return[...stages.values()].map(s=>({...s}))},async listArtifacts(){const base=data.artifacts??[...new Set(data.versions.map(v=>v.artifactId))].map(id=>({id,name:id,artifactType:"unknown"}));return base.map(a=>{const history=[...versions.values()].filter(x=>x.artifactId===a.id).sort((x,y)=>x.createdAt.localeCompare(y.createdAt));const v=history.at(-1);const{latest:_,unused:__,...rest}=structuredClone(a);const g=a.stage===void 0?void 0:gates.get(a.stage);const picked=g?.per==="pick"?pickedKey(g):void 0;if(picked!==void 0&&a.key!==picked)Object.assign(rest,{unused:true});if(!v)return rest;return{...rest,latest:{versionId:v.id,at:v.createdAt,number:history.length,author:structuredClone(v.author)}}})},async listActivity(limit){return activity.map((a,i)=>({a,i})).sort((x,y)=>y.a.at.localeCompare(x.a.at)||y.i-x.i).slice(0,limit).map(({a})=>structuredClone(a))},async startStage(via,name,params){const s=stage(name);const given=Object.keys(params).length>0;if(given){const problems=s.paramsSchema?paramsProblems(s.paramsSchema,params):["\u8FD9\u4E2A\u9636\u6BB5\u6CA1\u6709\u58F0\u660E\u53C2\u6570\uFF0C\u4E0D\u80FD\u5E26\u53C2\u6570\u5F00\u5DE5"];if(problems.length>0)throw new Error(problems.join("\uFF1B"))}s.status="in_progress";if(given)s.params=structuredClone(params);record(via,"stage.start",{stage:name,...given?{params}:{}});emitTurnStarted(name,"produce")},async rerunStage(via,name,versionId){if(versionId!==void 0&&!versions.has(versionId))throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u7248\u672C ${versionId}`);stage(name).status="in_progress";record(via,"stage.rerun",{stage:name,...versionId?{versionId}:{}});emitTurnStarted(name,versionId?"feedback":"produce")},async rerunStageWith(via,name,message){const target=stage(name);const extras=checkExtras({attachments:message.attachments});const id=nextId("thr");const at=now();const anchor={id:nextId("anc"),kind:"project",payload:{}};threads.set(id,{id,projectId:data.projectId,runId:data.runId,anchorId:anchor.id,mark:Math.max(0,...[...threads.values()].map(t2=>t2.mark))+1,status:"open",createdBy:actor,createdAt:at,updatedAt:at,anchor,excerpt:message.body.slice(0,80)});addComment(id,message.body,[],extras);emit("thread.created",{threadId:id,by:actor,mark:thread(id).mark});const{changeRequestId}=enqueue([id],void 0,name);target.status="in_progress";record(via,"stage.rerun",{stage:name,threadId:id});emitChangeRequested(changeRequestId,[id]);emitTurnStarted(name,"produce")},async changeRequest(via,ids){const changeRequestId=ids.length>0?enqueue(ids,void 0).changeRequestId:nextId("cr");record(via,"change_request.create",{changeRequestId,threadIds:ids});if(ids.length>0)emitChangeRequested(changeRequestId,ids);return{changeRequestId}},async humanVersion(via,patch){const stage2=artifactStage(patch.artifactId);const versionId=nextId("ver");record(via,"version.human",{versionId,patch});emit("version.created",{runId:data.runId,stage:stage2,versionId,artifactId:patch.artifactId,by:actor});return{ok:true,versionId,results:[]}},async proxy(req){const handler=opts.resources?.[req.key];if(!handler)return new Response(`\u5939\u5177\u6CA1\u6709\u8D44\u6E90 ${req.key}`,{status:502});if(req.level!=="read"){record(req.via,"resource.write",{key:req.key,method:req.method,path:req.path},req.level);emit("resource.written",{key:req.key,method:req.method,path:req.path,level:req.level})}return handler(req)},subscribe(fn){listeners.add(fn);return()=>{listeners.delete(fn)}},async createThread(via,input){const artifact=artifactOf(input.anchor);const targetStage=input.anchor.kind==="project"?projectStage():input.handToAgent&&artifact.artifactId?artifactStage(artifact.artifactId):void 0;const extras=checkExtras({attachments:input.attachments,refs:input.refs,capabilities:input.capabilities,connectors:input.connectors});const id=nextId("thr");const marks=[...threads.values()].map(t3=>t3.mark);const at=now();const t2={id,projectId:data.projectId,runId:data.runId,...artifact,anchorId:input.anchor.id,mark:Math.max(0,...marks)+1,status:"open",createdBy:actor,createdAt:at,updatedAt:at,anchor:input.anchor,excerpt:input.body.slice(0,80)};if(input.intent)t2.intent=input.intent;threads.set(id,t2);addComment(id,input.body,input.mentions,extras);record(via,"thread.create",{threadId:id});emit("thread.created",{threadId:id,by:actor,mark:t2.mark});if(input.handToAgent){const{changeRequestId}=enqueue([id],input.agent,targetStage);record(via,"change_request.create",{changeRequestId,threadIds:[id]});emitChangeRequested(changeRequestId,[id])}return structuredClone(t2)},async createProjectThread(via,input){return this.createThread(via,{...input,anchor:{id:nextId("anc"),kind:"project",payload:{}}})},async comment(via,id,body,extras,mentions){const t2=thread(id);const{choice,...message}=extras??{};const checked=checkExtras(message);let replyBody=body;let replyExtras=checked;let replyMentions=mentions??[];if(choice!==void 0){const unavailable=()=>new Error("\u95EE\u9898\u6216\u9009\u9879\u4E0D\u53EF\u7528");const parsed=ReceiptChoiceSchema.safeParse(choice);if(!parsed.success||actor.kind!=="human"||replyMentions.length||Object.values(checked).some(items=>items?.length))throw unavailable();const source=comments.find(c=>c.threadId===id&&c.id===parsed.data.receiptCommentId);const option=source?.receipt?.options?.find(o=>o.id===parsed.data.choiceId);if(source?.kind!=="receipt"||source.receipt?.outcome!=="needs-input"||!option)throw unavailable();const prior=comments.find(c=>c.threadId===id&&c.choice?.receiptCommentId===source.id);if(prior){if(prior.choice?.choiceId===parsed.data.choiceId)return;throw new Error("\u9009\u62E9\u5DF2\u63D0\u4EA4\uFF0C\u8BF7\u7528\u6587\u5B57\u8865\u5145\u65B0\u7684\u60F3\u6CD5")}if(t2.status!=="open"||source.receipt.optionsOpen!==true)throw unavailable();replyBody=option.label;replyExtras={choice:parsed.data};replyMentions=[]}const comment=addComment(id,replyBody,replyMentions,replyExtras);record(via,"thread.comment",{threadId:id});emit("comment.added",{threadId:id,commentId:comment.id,by:actor,kind:comment.kind})},async confirm(via,id){setStatus(via,id,"resolved","confirmed","thread.resolved")},async reject(via,id,body,extras,mentions){addComment(id,body,mentions??[],checkExtras(extras));setStatus(via,id,"open","rejected","thread.rejected")},async withdraw(via,id){const t2=thread(id);if(t2.status!=="queued")throw new Error(`\u7EBF\u7A0B ${id} \u4E0D\u5728\u961F\u5217\u91CC\uFF0C\u4E0D\u80FD\u64A4\u56DE`);turn.queue=turn.queue.map(q=>({...q,threadIds:q.threadIds.filter(x=>x!==id)})).filter(q=>q.threadIds.length>0);t2.agent=void 0;t2.sentBy=void 0;setStatus(via,id,"open","withdrawn","thread.withdrawn")},async undoPick(via,id){const t2=thread(id);if(t2.intent!=="pick")throw new Error(`\u7EBF\u7A0B ${id} \u4E0D\u662F\u9009\u7528\u7EBF\u7A0B`);if(t2.status!=="queued")throw new Error(`\u7EBF\u7A0B ${id} \u4E0D\u5728\u961F\u5217\u91CC\uFF0C\u4E0D\u80FD\u64A4\u9500`);turn.queue=turn.queue.map(q=>({...q,threadIds:q.threadIds.filter(x=>x!==id)})).filter(q=>q.threadIds.length>0);t2.agent=void 0;t2.sentBy=void 0;addComment(id,"\u5DF2\u64A4\u9500").kind="system";setStatus(via,id,"resolved","closed","thread.resolved")},async settlePick(){return"skipped"},async stopTurn(via,changeRequestId){const queued=turn.queue.find(q=>q.changeRequestId===changeRequestId);if(queued){const stage2=queued.stage??threadStage(queued.threadIds[0]);turn.queue=turn.queue.filter(q=>q!==queued);for(const id of queued.threadIds){const t2=thread(id);t2.agent=void 0;t2.sentBy=void 0;setStatus(via,id,"open","withdrawn","thread.withdrawn")}record(via,"turn.stop",{changeRequestId});emit("change.withdrawn",{runId:data.runId,changeRequestId,stage:stage2,by:actor});return}const cur=turn.current;if(cur?.changeRequestId!==changeRequestId)throw new Error(`\u4FEE\u6539\u8BF7\u6C42 ${changeRequestId} \u6CA1\u6709\u5728\u8DD1\u7684\u56DE\u5408`);if(cur.stopping)return;cur.stopping={by:actor.id};record(via,"turn.stop",{changeRequestId});emit("turn.stopping",{runId:data.runId,turnId:currentTurnId,by:actor})},async close(via,id){setStatus(via,id,"resolved","closed","thread.resolved")},async reopen(via,id){if(thread(id).status!=="resolved")throw new Error(`\u7EBF\u7A0B ${id} \u6CA1\u6709\u5173\u95ED`);setStatus(via,id,"open","reopened","thread.reopened")},async approve(via,name,input){const g=gate(name);const key=input?.key;if(g.per&&key===void 0)throw new Error(`\u9636\u6BB5 ${name} \u6309\u952E\u6279\u51C6`);if(g.per==="pick"){g.approvals=[...(g.approvals??[]).filter(a=>a.userId!==actor.id),{userId:actor.id,key}];const forKey=(g.approvals??[]).filter(a=>a.key===key).map(a=>a.userId);const picked=gateSatisfied({...g,approvedBy:forKey})?key:pickedKey(g);if(picked!==void 0)g.approvals=g.approvals.filter(a=>a.key===picked);g.approvedBy=[...new Set(g.approvals.map(a=>a.userId))];g.status=picked===void 0?"in_review":"approved"}else if(g.per==="key"){const votes=(g.approvals??[]).filter(a=>a.userId!==actor.id||a.key!==key);g.approvals=[...votes,{userId:actor.id,key}];g.approvedBy=[...new Set(g.approvals.map(a=>a.userId))];const keys=[...new Set((data.artifacts??[]).filter(a=>a.stage===name).map(a=>a.key??"main"))];const ok=k=>gateSatisfied({...g,approvedBy:(g.approvals??[]).filter(a=>a.key===k).map(a=>a.userId)});g.status=keys.length>0&&keys.every(ok)?"approved":"in_review"}else{if(!g.approvedBy.includes(actor.id))g.approvedBy.push(actor.id);g.status=gateSatisfied(g)?"approved":"in_review"}const note=input?.note;record(via,"gate.approve",{stage:name,...note?{note}:{},...key!==void 0?{key}:{}});emit("gate.approval",{runId:data.runId,stage:name,user:actor.id,...key!==void 0?{key}:{}});if(g.status==="approved")emit("stage.approved",{runId:data.runId,stage:name,by:actor})},async revoke(via,name,key){const g=gate(name);if(g.per&&key===void 0)throw new Error(`\u9636\u6BB5 ${name} \u6309\u952E\u6279\u51C6\uFF0C\u64A4\u56DE\u8981\u5E26\u952E`);const mine=a=>a.userId===actor.id&&(key===void 0||a.key===key);if(g.approvals)g.approvals=g.approvals.filter(a=>!mine(a));g.approvedBy=g.approvals?[...new Set(g.approvals.map(a=>a.userId))]:g.approvedBy.filter(id=>id!==actor.id);g.status=(g.per==="pick"?pickedKey(g)!==void 0:gateSatisfied(g))?"approved":"in_review";record(via,"gate.revoke",{stage:name,...key!==void 0?{key}:{}});emit("gate.revoked",{runId:data.runId,stage:name,user:actor.id,...key!==void 0?{key}:{}})}};if(preview!==void 0)t.preview=async()=>structuredClone(preview??null);t.uploadAttachment=async(via,file2,o)=>{o.signal?.throwIfAborted();const bytes=new Uint8Array(await file2.arrayBuffer());const digest=await crypto.subtle.digest("SHA-256",bytes);const sha256=[...new Uint8Array(digest)].map(b=>b.toString(16).padStart(2,"0")).join("");o.signal?.throwIfAborted();o.onProgress?.(1);const live=[...attachments.values()].filter(a=>a.meta.deletedAt===void 0);const same=live.find(a=>a.meta.sha256===sha256);if(same)return{...structuredClone(same.meta),existing:true};const meta={id:nextId("att"),projectId:data.projectId,name:dedupeAttachmentName(file2.name,new Set(live.map(a=>a.meta.name))),mime:file2.type||"application/octet-stream",size:bytes.byteLength,kind:attachmentKind(file2.name,file2.type),sha256,createdBy:actor,createdAt:now()};attachments.set(meta.id,{meta,blob:file2});record(via,"attachment.upload",{attachmentId:meta.id,size:meta.size});return structuredClone(meta)};const objects=new Map;t.putObject=async(via,blob,o)=>{o.signal?.throwIfAborted();const bytes=await blobBytes(blob);const objectId=await sha256Hex(bytes);o.signal?.throwIfAborted();o.onProgress?.(1);const mime=blob.type||"application/octet-stream";objects.set(objectId,{bytes,mime});record(via,"object.put",{objectId,size:bytes.byteLength});return{objectId,size:bytes.byteLength,mime}};t.deliver=async(via,raw)=>{const input=DeliverInputSchema.parse(raw);const history=[...versions.values()].filter(v2=>v2.artifactId===input.artifactId).sort((a,b)=>a.createdAt.localeCompare(b.createdAt));const latest=history.at(-1);if(!latest)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u4EA7\u7269 ${input.artifactId}`);if(latest.id!==input.baseVersion){return{ok:false,code:"BASE_MOVED",latestVersion:latest.id}}const stage2=artifactStage(input.artifactId);const replaced=new Map;const bytesOf=new Map;for(const f of input.files){const obj=objects.get(f.objectId);if(!obj)return{ok:false,code:"UNKNOWN_OBJECT"};bytesOf.set(f.path,obj.bytes);replaced.set(f.path,{path:f.path,sha256:f.objectId,size:obj.bytes.byteLength,mime:obj.mime,storage:"store",ref:f.objectId})}const entries=[...latest.entries.map(e=>replaced.get(e.path)??e),...[...replaced.values()].filter(e=>!latest.entries.some(b=>b.path===e.path))];const hash=await sha256Hex(new TextEncoder().encode(entries.map(e=>`${e.path}\0${e.sha256}`).join("\n")));const key=es=>es.map(e=>`${e.path}\0${e.sha256}`).join("\n");const same=history.find(v2=>key(v2.entries)===key(entries));if(same)return{ok:true,versionId:same.id,unchanged:true};const files=Object.fromEntries(entries.map(e=>[e.path,bytesOf.get(e.path)??file(latest.id,e.path)]));const at=now()>latest.createdAt?now():new Date(Date.parse(latest.createdAt)+1).toISOString();const{meta:_meta,...rest}=latest;const v={...rest,id:`${input.artifactId}@${hash}`,hash,entries,author:actor,createdAt:at,provenance:[{inputs:latest.provenance.at(-1)?.inputs??[],at}]};deliveredFiles.set(v.id,files);versions.set(v.id,v);record(via,"version.deliver",{versionId:v.id,baseVersion:input.baseVersion});emit("version.created",{runId:data.runId,stage:stage2,versionId:v.id,artifactId:v.artifactId,by:actor});return{ok:true,versionId:v.id,unchanged:false}};t.attachmentUrl=async id=>{const a=attachments.get(id);if(!a||a.meta.deletedAt!==void 0)throw new Error(`\u627E\u4E0D\u5230\u9644\u4EF6 ${id}`);if(!a.url&&!a.blob)throw new Error(`\u5939\u5177\u91CC\u9644\u4EF6 ${id} \u6CA1\u6709\u5199 url`);a.url??=URL.createObjectURL(a.blob);return a.url};t.deleteAttachment=async(via,id)=>{const a=attachments.get(id);if(!a||a.meta.deletedAt!==void 0)throw new Error(`\u627E\u4E0D\u5230\u9644\u4EF6 ${id}`);a.meta={...a.meta,deletedAt:now()};record(via,"attachment.delete",{attachmentId:id})};t.listAttachments=async o=>{const seen=new Map;const ordered=comments.map((c,i)=>({c,i})).sort((x,y)=>x.c.createdAt.localeCompare(y.c.createdAt)||x.i-y.i);for(const{c}of ordered){for(const id of c.attachments??[]){const a=attachments.get(id);if(!a||seen.has(id))continue;if(a.meta.deletedAt!==void 0&&!o?.includeDeleted)continue;const th=threads.get(c.threadId);seen.set(id,{...structuredClone(a.meta),source:{threadId:c.threadId,commentId:c.id,...th?{artifactId:th.artifactId,mark:th.mark}:{},...th?.anchor.kind==="artifact"?{chat:true}:{}}})}}const latest=new Map;for(const v of[...versions.values()].sort((x,y)=>x.createdAt.localeCompare(y.createdAt)))latest.set(v.artifactId,{v,number:(latest.get(v.artifactId)?.number??0)+1});const cmp=(x,y)=>x<y?-1:x>y?1:0;const usedIn=sha256=>[...latest.values()].flatMap(({v,number})=>v.entries.filter(e=>e.sha256===sha256).map(e=>({artifactId:v.artifactId,versionId:v.id,number,path:e.path}))).sort((a,b)=>cmp(a.artifactId,b.artifactId)||cmp(a.path,b.path));for(const a of seen.values())a.usedIn=usedIn(a.sha256);const at=x=>comments.find(c=>c.id===x.source.commentId)?.createdAt??"";return[...seen.values()].reverse().sort((x,y)=>at(y).localeCompare(at(x)))};t.react=async(via,commentId,emoji,on)=>{ReactionEmojiSchema.parse(emoji);const c=comments.find(x=>x.id===commentId);if(!c)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u8BC4\u8BBA ${commentId}`);if(c.kind==="system")throw new Error("\u7CFB\u7EDF\u8BC4\u8BBA\u4E0D\u80FD\u56DE\u5E94");const same=a=>a.kind===actor.kind&&a.id===actor.id;const list=(c.reactions??[]).map(r=>({...r,actors:[...r.actors]}));const hit=list.find(r=>r.emoji===emoji);if(on===Boolean(hit?.actors.some(same)))return;if(on){if(hit)hit.actors.push(actor);else list.push({emoji,actors:[actor]})}else if(hit){hit.actors=hit.actors.filter(a=>!same(a))}const kept=list.filter(r=>r.actors.length>0);const idx=comments.indexOf(c);const{reactions:_,...rest}=c;comments[idx]=kept.length>0?{...rest,reactions:kept}:rest;record(via,"comment.react",{commentId,emoji,on});emit("reaction.changed",{threadId:c.threadId,commentId})};function createFixtureMemory(){const filesAt=v=>v===0?[]:memory[v-1]?.files??[];const need=v=>{const m=memory[v-1];if(!m)throw new Error(`\u5939\u5177\u91CC\u6CA1\u6709\u7B2C ${v} \u7248\u8BB0\u5FC6`);return m};const same=(a,b)=>JSON.stringify(sortFiles(a))===JSON.stringify(sortFiles(b));function commit(files,meta){if(data.archived)return{ok:false,code:"READ_ONLY"};const problem=memoryProblem(files);if(problem)return{ok:false,code:"INVALID",message:problem};if(same(files,filesAt(memory.length))){return{ok:true,version:memory.length,unchanged:true}}const version=memory.length+1;const input={...meta,author:actor,createdAt:now(),files};memory.push({meta:memoryMeta(version,input,files),files:sortFiles(files)});emit("memory.updated",{version});return{ok:true,version,unchanged:false}}return{async current(){const last=memory.at(-1);return{version:memory.length,files:structuredClone(last?.files??[]),...last?{latest:structuredClone(last.meta)}:{}}},async versions(){return memory.map(m=>structuredClone(m.meta)).reverse()},async version(v){const m=need(v);return{version:structuredClone(m.meta),files:structuredClone(m.files),changes:memoryChanges(filesAt(v-1),m.files)}},async save(via,input){if(input.baseVersion!==memory.length){return{ok:false,code:"CONFLICT",latestVersion:memory.length}}const next=new Map(filesAt(memory.length).map(f=>[f.path,f.content]));for(const f of input.files)next.set(f.path,f.content);for(const p of input.removed)next.delete(p);const r=commit([...next].map(([path,content])=>({path,content})),{action:"edit"});if(r.ok&&!r.unchanged)record(via,"memory.edit",{version:r.version});return r},async revert(via,v){need(v);const before=new Map(filesAt(v-1).map(f=>[f.path,f.content]));const after=new Map(filesAt(v).map(f=>[f.path,f.content]));const next=new Map(filesAt(memory.length).map(f=>[f.path,f.content]));for(const path of new Set([...before.keys(),...after.keys()])){if(before.get(path)===after.get(path)||next.get(path)!==after.get(path))continue;const old=before.get(path);if(old===void 0)next.delete(path);else next.set(path,old)}const r=commit([...next].map(([path,content])=>({path,content})),{action:"revert",revertsVersion:v});if(r.ok&&!r.unchanged)record(via,"memory.revert",{version:r.version,of:v});return r},async restore(via,v){const r=commit(structuredClone(need(v).files),{action:"restore",revertsVersion:v});if(r.ok&&!r.unchanged)record(via,"memory.restore",{version:r.version,of:v});return r}}}t.capabilities=async()=>structuredClone(data.capabilities??[]);t.connectors=async()=>structuredClone(data.connectors??[]);t.memory=createFixtureMemory();t.storage=createFixtureStorage();return t;function createFixtureStorage(){const byPlugin=new Map;const of=plugin=>{let m=byPlugin.get(plugin);if(!m){m=new Map;byPlugin.set(plugin,m)}return m};const writable=()=>{if(data.archived)throw new Error("\u9879\u76EE\u5DF2\u5F52\u6863\uFF0C\u63D2\u4EF6\u5B58\u50A8\u53EA\u8BFB")};return{async list(plugin){const m=of(plugin);const entries=[...m.entries()].sort(([a],[b])=>a<b?-1:a>b?1:0).map(([key,e])=>({key,size:e.size,updatedAt:e.at}));return{entries,totalBytes:entries.reduce((n,e)=>n+e.size,0)}},async get(plugin,key){const e=of(plugin).get(key);return e?{value:JSON.parse(e.text)}:null},async set(plugin,key,value){writable();const m=of(plugin);const size=pluginStorageBytes(value);if(size===null)throw new StorageLimitError(key,"value",`${key}\uFF1A\u503C\u8981\u80FD\u5E8F\u5217\u5316\u6210 JSON`);const old=m.get(key);if(!old&&m.size>=PLUGIN_STORAGE_LIMITS.maxKeys){throw new StorageLimitError(key,"keys",`\u6BCF\u4E2A\u63D2\u4EF6\u6700\u591A\u5B58 ${PLUGIN_STORAGE_LIMITS.maxKeys} \u4E2A\u952E`)}let total=size;for(const[k,e]of m)if(k!==key)total+=e.size;if(total>PLUGIN_STORAGE_LIMITS.maxTotalBytes){throw new StorageLimitError(key,"total",`\u6BCF\u4E2A\u63D2\u4EF6\u5408\u8BA1\u6700\u591A\u5B58 ${PLUGIN_STORAGE_LIMITS.maxTotalBytes/1024} KB`)}const at=now();m.set(key,{text:JSON.stringify(value),size,at});emit("storage.written",{plugin,key,size,by:actor});return{key,size,updatedAt:at}},async remove(plugin,key){writable();const removed=of(plugin).delete(key);if(removed)emit("storage.written",{plugin,key,size:0,by:actor,removed:true});return removed}}}function artifactOf(anchor){if(anchor.versionId===void 0)return{};const v=versions.get(anchor.versionId);if(!v)throw new Error(`\u951A\u70B9\u6307\u5411\u7684\u7248\u672C ${anchor.versionId} \u4E0D\u5728\u5939\u5177\u91CC`);return{artifactId:v.artifactId}}}function sortFiles(files){return[...files].sort((a,b)=>a.path.localeCompare(b.path)).map(f=>({...f}))}function memoryMeta(version,m,files){return{...structuredClone(m),version,files:sortFiles(files).map(f=>({path:f.path,size:new TextEncoder().encode(f.content).byteLength}))}}function memoryChanges(before,after){const a=new Map(before.map(f=>[f.path,f.content]));const b=new Map(after.map(f=>[f.path,f.content]));const out=[];for(const path of[...new Set([...a.keys(),...b.keys()])].sort()){const x=a.get(path);const y=b.get(path);if(x===y)continue;if(x===void 0)out.push({path,change:"added",after:y});else if(y===void 0)out.push({path,change:"removed",before:x});else out.push({path,change:"modified",before:x,after:y})}return out}function matches(t,f){if(f.artifactId&&t.artifactId!==f.artifactId)return false;if(f.anchorKind&&t.anchor.kind!==f.anchorKind)return false;if(f.status&&!f.status.includes(t.status))return false;if(f.payload){for(const[k,v]of Object.entries(f.payload)){if(JSON.stringify(t.anchor.payload[k])!==JSON.stringify(v))return false}}return true}export{createFixtureAppData,createFixtureTransport,sampleAppFixture,samplePlugins};
|