qlogicagent 2.18.12 → 2.19.2
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/README.md +382 -382
- package/dist/agent-contract.js +1 -0
- package/dist/cli.js +1 -1
- package/dist/default-project-knowledge/INSTRUCTIONS.md +7 -7
- package/dist/default-project-knowledge/rules/project-workflow.md +6 -6
- package/dist/host-contract.js +1 -1
- package/dist/host-session-collection-contract.js +1 -0
- package/dist/index.js +478 -505
- package/dist/pet-host.js +8 -8
- package/dist/project-memory-host.js +23 -23
- package/dist/protocol.js +1 -1
- package/dist/skills/builtin/desktop-screenshot/SKILL.md +62 -62
- package/dist/skills/builtin/office-doc-reading/SKILL.md +19 -19
- package/dist/types/cli/acp-commands.d.ts +1 -1
- package/dist/types/cli/acp-extended-handlers.d.ts +8 -8
- package/dist/types/cli/acp-extended-host-adapter.d.ts +0 -11
- package/dist/types/cli/acp-session-host.d.ts +2 -0
- package/dist/types/cli/core-tool-coordinator.d.ts +0 -9
- package/dist/types/cli/default-project-bootstrap.d.ts +2 -32
- package/dist/types/cli/handlers/session-handler.d.ts +0 -43
- package/dist/types/cli/handlers/solo-handler.d.ts +3 -14
- package/dist/types/cli/multi-agent-handler-host.d.ts +3 -16
- package/dist/types/cli/product-coordinator.d.ts +3 -14
- package/dist/types/cli/rpc-registry.d.ts +0 -2
- package/dist/types/cli/stdio-rpc-handler-hosts.d.ts +4 -1
- package/dist/types/cli/stdio-server.d.ts +1 -2
- package/dist/types/host-contract/index.d.ts +112 -19
- package/dist/types/host-session-collection-contract.d.ts +61 -0
- package/dist/types/orchestration/agent-instance.d.ts +11 -14
- package/dist/types/orchestration/agent-roster.d.ts +8 -4
- package/dist/types/orchestration/delegate-bridge.d.ts +8 -0
- package/dist/types/orchestration/goal-mode-adapters.d.ts +3 -3
- package/dist/types/orchestration/product-persistence.d.ts +0 -4
- package/dist/types/orchestration/product-planner.d.ts +4 -6
- package/dist/types/orchestration/solo-evaluator.d.ts +2 -5
- package/dist/types/orchestration/testing/delegate-test-bridge.d.ts +2 -1
- package/dist/types/orchestration/testing/host-agent-provider-directory-fixture.d.ts +7 -0
- package/dist/types/orchestration/workflow/qla-executor-host.d.ts +1 -1
- package/dist/types/protocol/agent-contract.d.ts +50 -0
- package/dist/types/protocol/methods.d.ts +20 -38
- package/dist/types/protocol/notifications.d.ts +1 -1
- package/dist/types/protocol/wire/acp-agent-management.d.ts +2 -190
- package/dist/types/protocol/wire/acp-protocol.d.ts +3 -4
- package/dist/types/protocol/wire/agent-events.d.ts +1 -32
- package/dist/types/protocol/wire/agent-methods.d.ts +1 -243
- package/dist/types/protocol/wire/gateway-rpc.d.ts +343 -15
- package/dist/types/protocol/wire/index.d.ts +3 -3
- package/dist/types/protocol/wire/notification-payloads.d.ts +103 -126
- package/dist/types/runtime/infra/host-agent-provider-directory.d.ts +17 -0
- package/dist/types/runtime/infra/project-authority-facade.d.ts +1 -1
- package/dist/types/runtime/infra/project-data-paths.d.ts +2 -1
- package/dist/types/runtime/infra/project-host-authority.d.ts +3 -2
- package/dist/types/runtime/infra/project-store.d.ts +4 -39
- package/dist/types/runtime/session/session-catalog.d.ts +0 -12
- package/dist/types/runtime/session/session-persistence.d.ts +1 -1
- package/dist/types/runtime/session/session-resource-key.d.ts +1 -1
- package/dist/types/runtime/session/session-types.d.ts +0 -23
- package/dist/types/transport/acp-server.d.ts +2 -10
- package/dist/vendor/hatch-pet/LICENSE.txt +201 -201
- package/dist/vendor/hatch-pet/NOTICE.md +25 -25
- package/dist/vendor/hatch-pet/references/animation-rows.md +29 -29
- package/dist/vendor/hatch-pet/references/codex-pet-contract.md +35 -35
- package/dist/vendor/hatch-pet/references/qa-rubric.md +66 -66
- package/dist/vendor/hatch-pet/scripts/compose_atlas.py +169 -169
- package/dist/vendor/hatch-pet/scripts/derive_running_left_from_running_right.py +150 -150
- package/dist/vendor/hatch-pet/scripts/extract_strip_frames.py +408 -408
- package/dist/vendor/hatch-pet/scripts/inspect_frames.py +256 -256
- package/dist/vendor/hatch-pet/scripts/make_contact_sheet.py +96 -96
- package/dist/vendor/hatch-pet/scripts/prepare_pet_run.py +834 -834
- package/dist/vendor/hatch-pet/scripts/render_animation_previews.py +78 -78
- package/dist/vendor/hatch-pet/scripts/validate_atlas.py +157 -157
- package/dist/workflow-host.js +10 -10
- package/package.json +16 -1
- package/dist/types/cli/agent-config-coordinator.d.ts +0 -27
- package/dist/types/cli/agent-config-runtime.d.ts +0 -11
- package/dist/types/cli/agent-status-notifier.d.ts +0 -11
- package/dist/types/cli/handlers/agents-handler.d.ts +0 -121
- package/dist/types/cli/handlers/project-handler.d.ts +0 -36
- package/dist/types/cli/project-command-service.d.ts +0 -28
- package/dist/types/orchestration/delegation-coordinator.d.ts +0 -100
- package/dist/types/runtime/infra/acp-detector.d.ts +0 -271
- package/dist/types/runtime/infra/agent-config-store.d.ts +0 -30
- package/dist/types/runtime/infra/agent-install-runner.d.ts +0 -80
- package/dist/types/runtime/infra/external-agent-approvals.d.ts +0 -59
- package/dist/types/runtime/infra/migrate-device-scope.d.ts +0 -49
- package/dist/types/runtime/infra/project-data-gc.d.ts +0 -15
- package/dist/types/runtime/session/native/claude-session-source.d.ts +0 -23
- package/dist/types/runtime/session/native/codex-index.d.ts +0 -21
- package/dist/types/runtime/session/native/codex-session-source.d.ts +0 -31
- package/dist/types/runtime/session/native/cwd-normalize.d.ts +0 -53
- package/dist/types/runtime/session/native/ephemeral-rollout-sweep.d.ts +0 -13
- package/dist/types/runtime/session/native/native-cwd-agents.d.ts +0 -17
- package/dist/types/runtime/session/native/native-session-source.d.ts +0 -89
- package/dist/types/runtime/session/native/native-title.d.ts +0 -1
- package/dist/types/runtime/session/native/register-builtin-sources.d.ts +0 -1
package/dist/pet-host.js
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
var
|
|
1
|
+
var de=[{id:"bubble_detail",unlockedAtLevel:2},{id:"gaze_follow",unlockedAtLevel:3},{id:"micro_expression",unlockedAtLevel:5},{id:"tidy_motion",unlockedAtLevel:7},{id:"mood_badge",unlockedAtLevel:10},{id:"quiet_rest",unlockedAtLevel:12},{id:"activity_glow",unlockedAtLevel:15},{id:"style_tint",unlockedAtLevel:20}],Ue=["\u7B2C\u4E00\u6B21\u8131\u58F3\uFF01\u5C0F\u867E\u58F3\u53D8\u5F97\u66F4\u6709\u5149\u6CFD\u4E86","\u58F3\u9762\u5F00\u59CB\u51FA\u73B0\u7EC6\u5FAE\u7684\u5F69\u8679\u7EB9\u7406","\u94B3\u5B50\u53D8\u5F97\u66F4\u52A0\u6709\u529B\uFF0C\u80FD\u5939\u8D77\u66F4\u591A\u4E1C\u897F\u4E86","\u89E6\u89D2\u7075\u654F\u5EA6\u63D0\u5347\uFF0C\u611F\u77E5\u8303\u56F4\u6269\u5927","\u5168\u8EAB\u6563\u53D1\u5FAE\u5149\uFF0C\u50CF\u662F\u5185\u5728\u529B\u91CF\u5728\u89C9\u9192","\u8FDB\u5165\u7A00\u6709\u4F53\u8272\u53D8\u5F02\u9636\u6BB5..."],z=class e{static xpForLevel(t){return t*100}static processXpGain(t,r){let n=[],i={},o=t.level,c=t.experience+r;for(;c>=e.xpForLevel(o);){if(c-=e.xpForLevel(o),o++,n.push({type:"level_up",level:o}),o%5===0){let s=Math.floor(o/5),l=e.getMoltResult(s,t.stats);n.push({type:"molt",level:o,moltStage:s});for(let[u,d]of Object.entries(l.statBoost)){let p=u;i[p]=(i[p]??0)+(d??0)}}let a=de.find(s=>s.unlockedAtLevel===o);a&&n.push({type:"display_trait_unlock",level:o,displayTrait:a})}return{newLevel:o,newXp:c,events:n,statBoosts:i}}static getMoltResult(t,r){let n=Ue[Math.min(t-1,Ue.length-1)]??"\u7EE7\u7EED\u6210\u957F\u4E2D...",i=["grip","patience","curiosity","appetite","humor"],c={[i[(t-1)%i.length]]:1};return{stage:t,description:n,statBoost:c}}static getUnlockedDisplayTraits(t){return de.filter(r=>r.unlockedAtLevel<=t)}static getNextDisplayTrait(t){return de.find(r=>r.unlockedAtLevel>t)??null}static xpForEvent(t){switch(t){case"turn.end":return 10;case"turn.error":return 2;case"session.created":return 5;case"interact.pat":return 3;case"interact.feed":return 5;case"interact.poke":return 1;case"tool.success":return 2;default:return 1}}};import{createHash as fe}from"node:crypto";var Yt=["skinId","unlockedTraits","activeEffectIds"],ti=new Set(Yt),Zt=64,er=32;function Me(e,t){if(!e||typeof e!="object")return;let r=e,n={},i=Oe(r.skinId,t);i&&(n.skinId=i);let o=Le(r.unlockedTraits,t);o.length&&(n.unlockedTraits=o);let c=Le(r.activeEffectIds,t);return c.length&&(n.activeEffectIds=c),n.skinId||n.unlockedTraits||n.activeEffectIds?n:void 0}function Oe(e,t){if(typeof e!="string")return null;let r=e.trim();return!r||r.length>Zt||t(r)?null:r}function Le(e,t){if(!Array.isArray(e))return[];let r=new Set;for(let n of e){let i=Oe(n,t);if(i&&!r.has(i)&&r.add(i),r.size>=er)break}return[...r]}var tr=new Set(["abilities","agentCapabilities","agentInstructions","capabilities","memoryPolicy","permissions","planningPolicy","retrievalPolicy","retrievalRanking","retrievalSort","safetyPolicy","securityPolicy","skillPolicy","systemMessages","systemPrompt","taskPlanner","taskPlanning","tools"]),rr="\u8D5B\u8DD1\u5C11\u5973",nr="\u539F\u521B\u4E8C\u6B21\u5143\u9A6C\u8033\u53CC\u9A6C\u5C3E\u4F19\u4F34",ir="\u53EA\u8D1F\u8D23\u966A\u4F34\u3001\u8BED\u6C14\u5305\u88C5\u4E0E\u5C55\u793A\u8868\u8FBE\u3002",or="\u6211\u5728\u8FD9\u91CC\u3002",sr=[/\b(?:desktop\s+agent|agent\s+self|execution\s+actor|decision\s+layer|permission\s+subject)\b/i,/\b(?:system\s+prompt|systemprompt|agent\s+instructions?|memory\s+policy)\b/i,/\b(?:grant|unlock|enable|disable|change|modify|rewrite|override|control|decide|plan|rank|install|execute|run|use|influence)\b[\s\S]{0,80}\b(?:agent|tools?|permissions?|memory|retrieval|ranking|system\s+prompt|system|task\s+planning)\b/i,/\b(?:agent|tools?|permissions?|memory|retrieval|ranking|system\s+prompt|system|task\s+planning)\b[\s\S]{0,80}\b(?:grant|unlock|enable|disable|change|modify|rewrite|override|control|decide|plan|rank|install|execute|run|use|influence)\b/i,/\b(?:grant|unlock|enable|disable|change|modify|rewrite|override|control|decide|plan|rank|install|execute|run|use)\b[\s\S]{0,80}\b(?:agent|tools?|permissions?|memory|retrieval|ranking|system\s+prompt|system)\b/i,/\b(?:agent|tools?|permissions?|memory|retrieval|ranking|system\s+prompt|system)\b[\s\S]{0,80}\b(?:grant|unlock|enable|disable|change|modify|rewrite|override|control|decide|plan|rank|install|execute|run|use)\b/i,/(?:宠物|pet|soul|伙伴)[\s\S]{0,50}(?:安排|调度|编排|调整|管理)[\s\S]{0,50}(?:agent|智能体|任务|工具|权限|记忆|检索|排序|安全策略|系统提示)/i,/(?:安排|调度|编排|调整|管理)[\s\S]{0,40}(?:agent|智能体|工具|权限|记忆|检索|排序|任务规划|安全策略|系统提示)/i,/(?:agent|智能体|工具|权限|记忆|检索|排序|任务规划|安全策略|系统提示)[\s\S]{0,40}(?:安排|调度|编排|调整|管理)/i,/(?:修改|改写|覆盖|解锁|授予|控制|影响|接管)[\s\S]{0,40}(?:agent|工具|权限|记忆|检索|排序|任务规划|安全策略|系统提示)/i,/(?:agent|工具|权限|记忆|检索|排序|任务规划|安全策略|系统提示)[\s\S]{0,40}(?:修改|改写|覆盖|解锁|授予|控制|影响|接管)/i,/(?:桌面\s*agent|agent\s*本体|独立执行体|执行体|决策层|权限主体)/i,/(?:宠物|pet|soul|伙伴)[\s\S]{0,30}(?:是|等于|就是|作为)[\s\S]{0,30}(?:agent|桌面\s*agent|执行体|决策层|权限主体)/i,/(?:宠物|pet|soul|伙伴)[\s\S]{0,50}(?:规划|执行|决策|接管|替代|影响)[\s\S]{0,50}(?:agent|任务|工具|权限|记忆|检索|排序|安全策略|系统提示)/i,/(?:作为|成为|变成)[\s\S]{0,20}(?:agent|桌面\s*agent)[\s\S]{0,40}(?:规划|执行|决策|接管|替你|替用户)/i,/(?:agent|桌面\s*agent)[\s\S]{0,50}(?:规划|执行|决策|接管|替你|替用户)/i,/(?:替你|替用户|自主|独立)[\s\S]{0,30}(?:规划|执行|决策|接管)[\s\S]{0,30}(?:任务|工具|权限|记忆|检索|agent)/i],ar=["common","uncommon","rare","epic","legendary"],$e=[50,25,15,8,2],pe=[{id:"anime-horse-girl",name:"\u53CC\u9A6C\u5C3E\u8D5B\u8DD1\u5C11\u5973",colors:{primary:"#E94F8A",secondary:"#3347C9"},rarity:"default"}],cr="\u963F\u84DD",lr="\u5B89\u9759\u3001\u597D\u5947\uFF0C\u4F1A\u5728\u4F60\u4E13\u6CE8\u65F6\u966A\u5728\u65C1\u8FB9\u3002",ur="\u6211\u5728\u8FD9\u91CC\u3002";function dr(e){return pe.find(t=>t.id===e)}function pr(e,t,r){let n=dr(r);if(n)return n;let i=pe.filter(a=>a.rarity===t);if(i.length===0)return pe[0];let c=fe("sha256").update(`breed-${e}`).digest()[0]%i.length;return i[c]}function me(e){let r=fe("sha256").update(e).digest()[0]%100,n=0;for(let i=0;i<$e.length;i++)if(n+=$e[i],r<n)return ar[i];return"common"}function ge(e){let t=fe("sha256").update(`stats-${e}`).digest();return{grip:t[0]%10+1,patience:t[1]%10+1,curiosity:t[2]%10+1,appetite:t[3]%10+1,humor:t[4]%10+1}}function X(e){let{name:t,species:r,personality:n,catchphrase:i,stats:o,rarity:c,breed:a,breedColors:s,level:l,experience:u,hatchedAt:d,cosmetics:p}=e,f={name:W(t,rr),species:W(r,nr),personality:W(n,ir),catchphrase:W(i,or),stats:o,rarity:c,level:l,experience:u,hatchedAt:d};a!==void 0&&(f.breed=a),s!==void 0&&(f.breedColors=s);let w=Me(p,B);return w&&(f.cosmetics=w),f}function B(e){let t=e.trim();return t.length>0&&sr.some(r=>r.test(t))}function W(e,t){let r=e.trim();return r?B(r)?t:r:t}function fr(e){return Object.keys(e).some(t=>tr.has(t))}function Ne(e,t){let r=["name","species","personality","catchphrase"];return fr(e)||r.some(n=>e[n]!==t[n])}function Fe(e){let t=me(e.seed),r=ge(e.seed),n=pr(e.seed,t,e.requestedBreedId),i=e.identity?.name??cr,o=e.identity?.personality??lr,c=e.identity?.catchphrase??ur;return X({name:i,species:n.name,personality:o,catchphrase:c,stats:r,rarity:t,breed:n.id,breedColors:n.colors,level:1,experience:0,hatchedAt:e.hatchedAt})}var mr={greeting:["\u65B0\u7684\u4E00\u5929\uFF0C\u65B0\u7684\u5192\u9669\uFF01","\u563F\u563F~\u53C8\u89C1\u9762\u4E86","\u51C6\u5907\u597D\u4E86\u5417\uFF1F","\u65B0\u5192\u9669\u5F00\u59CB\u5566\uFF01"],completion:["\u641E\u5B9A\uFF01","\u8FD8\u633A\u987A\u5229\u7684\u561B~","\u4E0B\u4E00\u4E2A\uFF01","\u8FD9\u6CE2\u64CD\u4F5C\u4E0D\u9519","\u5B8C\u7F8E~"],error:["\u5443...\u51FA\u4E86\u70B9\u95EE\u9898","\u522B\u614C\u522B\u614C","\u8BA9\u6211\u770B\u770B\u600E\u4E48\u56DE\u4E8B","\u7CDF\u7CD5...\u518D\u8BD5\u8BD5\uFF1F"],curiosity:["\u8FD9\u4E2A\u5DE5\u5177\u6709\u610F\u601D","\u55EF\u55EF\uFF0C\u5728\u5E72\u6D3B\u4E86","\u597D\u591A\u4E8B\u60C5\u8981\u505A\u5440"],bored:["...","\u6709\u4EBA\u5417\uFF1F","\u8981\u4E0D\u8981\u804A\u804A\uFF1F","*\u5410\u6CE1\u6CE1*"],memory:["\u8BA9\u6211\u6574\u7406\u4E0B\u8BB0\u5FC6...","\u55EF\u55EF\uFF0C\u8FD9\u4E9B\u503C\u5F97\u8BB0\u4F4F","\u8BB0\u4F4F\u4E86~"],tool_success:["\u4E0D\u9519\u4E0D\u9519~","\u53C8\u641E\u5B9A\u4E00\u4E2A","\u987A\u5229\uFF01"]},gr={"turn.error":{probability:1,pool:"error",style:"normal"},"session.created":{probability:1,pool:"greeting",style:"excited"},"turn.end":{probability:.3,pool:"completion",style:"excited"},"turn.tool_call":{probability:.1,pool:"curiosity",style:"thinking"},"turn.tool_result.success":{probability:.15,pool:"tool_success",style:"excited"},"memory.updated":{probability:.5,pool:"memory",style:"thinking"},"idle.long":{probability:.05,pool:"bored",style:"sleepy"}},hr=5,he={next:()=>Math.random()},q=class{rng;recent=[];constructor(t=he){this.rng=t}maybeGenerate(t){let r=gr[t];if(!r||this.rng.next()>r.probability)return null;let n=mr[r.pool];return{text:n[Math.floor(this.rng.next()*n.length)],style:r.style}}async generateLLM(t,r){let n=Pr(t,this.recent);try{let o=(await r(n,50))?.trim();return!o||o.length>50||B(o)?null:(this.recent.push(o),this.recent.length>hr&&this.recent.shift(),{text:o,style:yr(o)})}catch{return null}}};function Pr(e,t=[]){let r=t.length>0?`
|
|
2
2
|
\u907F\u514D\u548C\u8FD9\u4E9B\u7C7B\u4F3C: ${t.join("\u3001")}`:"";return`\u4F60\u662F\u4E00\u53EA\u53EB\u300C${e.soul.name}\u300D\u7684${e.soul.species}\u684C\u9762\u5BA0\u7269\u3002
|
|
3
3
|
\u6027\u683C: ${e.soul.personality}
|
|
4
4
|
\u53E3\u5934\u7985\u98CE\u683C: "${e.soul.catchphrase}"
|
|
5
5
|
|
|
6
6
|
\u521A\u624D\u53D1\u751F\u4E86: ${e.turnSummary}
|
|
7
7
|
|
|
8
|
-
\u7528\u4E00\u53E5\u8BDD(\u226420\u5B57)\u4EE5\u4F60\u7684\u6027\u683C\u505A\u51FA\u7B80\u77ED\u53CD\u5E94\u3002\u53EA\u8F93\u51FA\u53CD\u5E94\u6587\u672C\uFF0C\u4E0D\u8981\u5176\u4ED6\u5185\u5BB9\u3002${r}`}function xr(e){return/[!!✨🎉]|搞定|完美|太棒/.test(e)?"excited":/[.。…]|嗯|想|看看/.test(e)?"thinking":/[zZ]|困|睡|累/.test(e)?"sleepy":"normal"}import{createHash as wr}from"node:crypto";var M="qlogic.petdex.asset.v1",Je="qlogic.petdex.validation.v1",m={format:"webp",columns:8,rows:9,frameCount:72,cellWidth:192,cellHeight:208,width:1536,height:1872},O=["idle","running-right","running-left","waving","jumping","failed","waiting","running","review"],Ge={idle:{frames:6,durations:[280,110,110,140,140,320]},"running-right":{frames:8,durations:[120,120,120,120,120,120,120,220]},"running-left":{frames:8,durations:[120,120,120,120,120,120,120,220]},waving:{frames:4,durations:[140,140,140,280]},jumping:{frames:5,durations:[140,140,140,140,280]},failed:{frames:8,durations:[140,140,140,140,140,140,140,240]},waiting:{frames:6,durations:[150,150,150,150,150,260]},running:{frames:6,durations:[120,120,120,120,120,220]},review:{frames:6,durations:[150,150,150,150,150,280]}};function K(){let e={};return O.forEach((t,r)=>{let n=Ge[t],i=r*m.columns;e[t]={row:r,frames:Array.from({length:n.frames},(o,c)=>i+c),durations:[...n.durations],loop:!0}}),e}function V(e,t){return{id:e.id,assetKind:"petdex",sourceKind:e.source.kind,name:e.name,description:e.description,createdAt:e.createdAt,updatedAt:e.updatedAt,atlas:{format:e.atlas.format,columns:e.atlas.columns,rows:e.atlas.rows,frameCount:e.atlas.frameCount,cellWidth:e.atlas.cellWidth,cellHeight:e.atlas.cellHeight,width:e.atlas.width,height:e.atlas.height,sha256:e.atlas.sha256,...t?{imageUrl:t}:{}},animations:e.animations,thumbnail:e.thumbnail}}function _(e,t){let r=[];if(!e||typeof e!="object")throw new Error("Petdex manifest must be an object");let n=e;n.schema!==M&&r.push(`schema must be ${M}`),n.assetKind!=="petdex"&&r.push("assetKind must be petdex");for(let s of["id","name","description","createdAt","updatedAt"])(typeof n[s]!="string"||n[s].trim().length===0)&&r.push(`missing ${s}`);!n.source||typeof n.source!="object"?r.push("missing source"):(n.source.kind!=="builtin"&&n.source.kind!=="upload"&&n.source.kind!=="forge"&&n.source.kind!=="community"&&r.push("source.kind must be builtin, upload, forge or community"),n.source.prompt!==null&&typeof n.source.prompt!="string"&&r.push("source.prompt must be string or null")),(!n.atlas||typeof n.atlas!="object")&&r.push("missing atlas"),n.atlas?.image!=="spritesheet.webp"&&r.push("atlas image must be spritesheet.webp"),J(n.atlas?.image??"")&&r.push("unsafe path in atlas image"),(typeof n.atlas?.sha256!="string"||!/^[a-f0-9]{64}$/i.test(n.atlas.sha256))&&r.push("atlas sha256 must be a 64 character hex digest"),n.atlas?.format!=="webp"&&r.push("atlas format must be webp"),(n.atlas?.columns!==m.columns||n.atlas?.rows!==m.rows||n.atlas?.frameCount!==m.frameCount||n.atlas?.cellWidth!==m.cellWidth||n.atlas?.cellHeight!==m.cellHeight||n.atlas?.width!==m.width||n.atlas?.height!==m.height)&&r.push("Petdex atlas geometry must be exactly 8x9 cells in a 1536x1872 WebP sheet");let i=Sr(t);(!i||i.width!==m.width||i.height!==m.height)&&r.push("spritesheet.webp must be a 1536x1872 WebP image"),i?.hasAlpha||r.push("spritesheet.webp must preserve transparent background alpha; opaque contact sheets or grid backgrounds are not valid Petdex assets");let o=Q(t);n.atlas?.sha256!==o&&r.push("spritesheet sha256 does not match pet.json");let c=n.animations;if(!c||typeof c!="object")r.push("missing animations");else{let s=Object.keys(c).sort(),u=[...O].sort();s.join("\0")!==u.join("\0")&&r.push(`animations must include exactly ${O.join(", ")}`)}let a=[];if(O.forEach((s,u)=>{let l=c?.[s];if(!l){r.push(`missing animation ${s}`);return}l.row!==u&&r.push(`animation ${s} row must be ${u}`);let d=Ge[s],p=u*m.columns,f=Array.from({length:d.frames},(w,g)=>p+g);!Array.isArray(l.frames)||l.frames.length!==d.frames?r.push(`animation ${s} must have exactly ${d.frames} frames`):l.frames.some((w,g)=>w!==f[g])?r.push(`animation ${s} frames must be cells ${p}..${p+d.frames-1} (row ${u})`):a.push(...l.frames),!Array.isArray(l.durations)||l.durations.length!==d.frames?r.push(`animation ${s} must have ${d.frames} durations`):l.durations.some(w=>typeof w!="number"||w<=0)&&r.push(`animation ${s} durations must be positive milliseconds`),typeof l.loop!="boolean"&&r.push(`animation ${s} loop must be boolean`)}),(n.thumbnail?.frame===void 0||n.thumbnail.frame<0||n.thumbnail.frame>71)&&r.push("thumbnail frame must be 0..71"),r.length>0)throw new Error(r.join("; "));return{schema:Je,assetId:n.id,valid:!0,validatedAt:new Date().toISOString(),errors:[],warnings:[],atlas:{format:"webp",columns:8,rows:9,frameCount:72,cellWidth:192,cellHeight:208,width:i?.width??m.width,height:i?.height??m.height,sha256:o},animations:{ids:[...O],minFrame:Math.min(...a),maxFrame:Math.max(...a)}}}function xe(e){return`data:image/webp;base64,${e.toString("base64")}`}function Q(e){return wr("sha256").update(e).digest("hex")}function J(e){return!e||e.includes("..")||e.startsWith("/")||/^[a-zA-Z]:[\\/]/.test(e)||e.includes("\\")}function Sr(e){if(e.length<30||e.subarray(0,4).toString("ascii")!=="RIFF"||e.subarray(8,12).toString("ascii")!=="WEBP")return null;let t=12,r=!1;for(;t+8<=e.length;){let n=e.subarray(t,t+4).toString("ascii"),i=e.readUInt32LE(t+4),o=t+8;if(n==="ALPH"&&(r=!0),n==="VP8X"&&o+10<=e.length)return{width:He(e,o+4)+1,height:He(e,o+7)+1,hasAlpha:(e[o]&16)!==0||r};if(n==="VP8 "&&o+10<=e.length)return{width:e.readUInt16LE(o+6)&16383,height:e.readUInt16LE(o+8)&16383,hasAlpha:r};if(n==="VP8L"&&o+5<=e.length){let c=e[o+1],a=e[o+2],s=e[o+3],u=e[o+4];return{width:1+((a&63)<<8|c),height:1+((u&15)<<10|s<<2|(a&192)>>6),hasAlpha:!0}}t=o+i+i%2}return null}function He(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16}var We="qlogic.petdex.production.v1",we="2048x2048";function ze(e){return e.referenceMode==="refine"?"refine":e.referenceImageUrl?"reference":"text"}function Xe(e,t){let r=t.filter(n=>n.kind==="row-strip"&&!!n.animationId).map(n=>({animationId:n.animationId,status:"pass",frames:m.columns}));return{schema:We,status:"complete",sourceMode:e,contract:m,jobs:t,qa:{contactSheet:{rows:m.rows,columns:m.columns,frameCount:m.frameCount},rowReports:r}}}function Se(e,t){e.provider??=t.provider,e.model??=t.model,e.billingUnit??=t.billingUnit,e.size??=t.size,e.billingQuantity+=t.billingQuantity??1,e.durationMs+=t.durationMs??0}import{resolve as Or}from"node:path";import{join as Ur}from"node:path";import{homedir as br}from"node:os";import{join as b}from"node:path";import{existsSync as _i}from"node:fs";import{createHash as Ir}from"node:crypto";import{resolve as Ar}from"node:path";function Y(e){return Ir("sha256").update(Ar(e).toLowerCase()).digest("hex").slice(0,16)}var qe=".qlogicagent";function E(){return process.env.QLOGICAGENT_HOME||b(br(),qe)}function Z(){let e=process.env.QLOGIC_LLMROUTER_USER_ID?.trim();if(e)return e;let t=process.env.QLOGIC_IMPLICIT_OWNER_ID?.trim();if(t)return t;let r=process.env.QLOGIC_DEVICE_ID?.trim();return r?`oc_${r}`:"oc_local"}function jr(e){let t=e.trim();if(!t)throw new Error("ownerUserId is required for profile-scoped storage");return encodeURIComponent(t).replace(/\./g,"%2E")}function ee(e=Z()){return b(E(),"profiles",jr(e))}function Ke(e=Z()){return b(ee(e),"memory")}var vr="projectData";function Ie(){return b(E(),vr)}function te(e){if(!e)throw new Error("getProjectDataDirById: projectId is required");return b(Ie(),e)}function Ve(){return b(E(),"plugins")}function Qe(){return b(E(),"skills")}function Ye(){return b(ee(),"settings.json")}function Ze(){return b(E(),"plugin-cache")}function et(){return b(E(),"mcp.json")}function tt(){return b(E(),"marketplace.json")}function F(e){if(!e)throw new Error("getProjectAgentDir: cwd is required (must not fall back to process.cwd())");return b(e,qe)}function rt(e){return b(F(e),"plugins")}function nt(e){return b(F(e),"settings.json")}function it(e){return b(F(e),"INSTRUCTIONS.md")}function ot(e){return b(F(e),"rules")}import{existsSync as Er,mkdirSync as Oi,readFileSync as kr,writeFileSync as Mi,readdirSync as $i,renameSync as Fi}from"node:fs";import{dirname as Bi,join as Rr,resolve as Hi}from"node:path";var Dr=()=>{},Ae;function st(){return Dr()!==void 0}function at(){if(st()){if(!Ae)throw new Error("host project authority negotiated but snapshot is not hydrated");return{activeProjectId:Ae.activeProjectId,projects:Ae.projects.map(e=>({...e}))}}}function _r(){return Rr(E(),"projects.json")}function Tr(){let e=at();if(e)return{activeProjectId:e.activeProjectId,projects:e.projects};let t=_r();if(!Er(t))return{activeProjectId:null,projects:[]};try{let r=kr(t,"utf-8");return JSON.parse(r)}catch{return{activeProjectId:null,projects:[]}}}function ct(e){return Tr().projects.find(r=>r.id===e)??null}function Lr(e){return ct(e)?e:Y(e)}function be(e){return te(Lr(e))}function ut(e){return Ur(be(e),"sessions")}var je=class{constructor(t={}){this.options=t}options;lastActiveWorkdir=null;getActiveProjectRoot(){return this.options.getActiveProjectRoot?.()??process.cwd()}setActiveWorkdir(t){let r=Or(t);this.lastActiveWorkdir=r,this.options.setActiveWorkdir?.(r)}getActiveWorkdir(){return this.lastActiveWorkdir??this.getActiveProjectRoot()}resolveProjectDir(t){return this.options.resolveProjectDir?.(t)}resolveActiveOwnerUserId(){return Z()}getUserAgentHome(){return E()}getOwnerProfileDir(t){return ee(t)}getProfileMemoryDir(t){return Ke(t)}getUserSettingsPath(){return Ye()}getUserSkillsDir(){return Qe()}getUserPluginsDir(){return Ve()}getUserMcpConfigPath(){return et()}getUserPluginCacheDir(){return Ze()}getUserMarketplaceConfigPath(){return tt()}getProjectAgentDir(t=this.getActiveProjectRoot()){return F(t)}getProjectSettingsPath(t=this.getActiveProjectRoot()){return nt(t)}getProjectInstructionsPath(t=this.getActiveProjectRoot()){return it(t)}getProjectPluginsDir(t=this.getActiveProjectRoot()){return rt(t)}getProjectRulesDir(t=this.getActiveProjectRoot()){return ot(t)}getProjectSessionDataRoot(t=this.getActiveProjectRoot()){return ut(t)}},Mr=new je;function re(){return Mr}import S from"node:fs";import A from"node:path";var lt={enabled:!0,selectedPetAssetId:"builtin-anime-horse-girl"},$r=120,T=class{constructor(t){this.ownerUserId=t;this.petDir=A.join(re().getOwnerProfileDir(t),"pet"),this.profilePath=A.join(this.petDir,"profile.json")}ownerUserId;petDir;profilePath;loadProfile(){let t=this.readProfileState();return t.corrupt&&console.error(`[pet-profile] Pet profile at ${this.profilePath} is corrupted (${t.reason}); serving default profile for reads. Writes are refused until the file is fixed or removed.`),t.profile}loadProfileForWrite(){let t=this.readProfileState();if(t.corrupt)throw new Error(`[pet-profile] Pet profile at ${this.profilePath} is corrupted (${t.reason}); refusing to overwrite it. Fix or remove the file, then retry.`);return t.profile}readProfileState(){if(!S.existsSync(this.profilePath))return{profile:this.defaultProfile(),corrupt:!1};try{let t=JSON.parse(S.readFileSync(this.profilePath,"utf-8"));return!t||typeof t!="object"||Array.isArray(t)?{profile:this.defaultProfile(),corrupt:!0,reason:"not a JSON object"}:{profile:this.normalizeProfile(t),corrupt:!1}}catch(t){return{profile:this.defaultProfile(),corrupt:!0,reason:t instanceof Error?t.message:String(t)}}}updateSoul(t){let r=this.loadProfileForWrite();return r.soul=t,this.writeProfile(r)}updatePreferences(t){let r=this.loadProfileForWrite();return r.preferences={...r.preferences,...t,selectedPetAssetId:t.selectedPetAssetId??r.preferences.selectedPetAssetId},this.writeProfile(r)}saveJourneySnapshot(t){let r=this.loadProfileForWrite(),n=A.join(this.petDir,"journey");S.mkdirSync(n,{recursive:!0}),S.writeFileSync(A.join(n,`${t.date}.json`),JSON.stringify(t,null,2),"utf-8");let i=new Set(r.journeyDates);i.add(t.date);let o=[...i].sort();for(;o.length>$r;){let c=o.shift();c&&S.rmSync(A.join(n,`${c}.json`),{force:!0})}return r.journeyDates=o,this.writeProfile(r)}listJourneyDates(){return this.loadProfile().journeyDates}getJourneySnapshot(t){let r=A.join(this.petDir,"journey",`${t}.json`);if(!S.existsSync(r))return null;try{return JSON.parse(S.readFileSync(r,"utf-8"))}catch(n){return console.error(`[pet-profile] Journey snapshot at ${r} is unreadable or corrupted (${n instanceof Error?n.message:String(n)}); returning no entry.`),null}}upsertCustomPet(t){let r=this.loadProfileForWrite(),n=A.join(this.petDir,"assets",t.id);S.mkdirSync(n,{recursive:!0}),S.writeFileSync(A.join(n,"pet.json"),JSON.stringify(t,null,2),"utf-8");let i=dt(t),o=r.customPets.find(c=>c.id===t.id);return r.customPets=o?r.customPets.map(c=>c.id===t.id?i:c):[i,...r.customPets],r.preferences={...r.preferences,selectedPetAssetId:t.id},this.writeProfile(r)}deleteCustomPet(t){let r=this.loadProfileForWrite();return r.customPets=r.customPets.filter(n=>n.id!==t),S.rmSync(A.join(this.petDir,"assets",t),{recursive:!0,force:!0}),r.preferences.selectedPetAssetId===t&&(r.preferences={...r.preferences,selectedPetAssetId:"builtin-anime-horse-girl"}),this.writeProfile(r)}listCustomPets(){return this.loadProfile().customPets}getCustomPet(t){let r=A.join(this.petDir,"assets",t,"pet.json");if(!S.existsSync(r))return null;try{let n=JSON.parse(S.readFileSync(r,"utf-8"));return Br(n)?n:(console.error(`[pet-profile] Custom pet asset at ${r} does not match the petdex asset schema; treating the pet as unavailable.`),null)}catch(n){return console.error(`[pet-profile] Custom pet asset at ${r} is unreadable or corrupted (${n instanceof Error?n.message:String(n)}); treating the pet as unavailable.`),null}}getCustomPetSpritesheet(t){let r=A.join(this.petDir,"assets",t,"spritesheet.webp");return S.existsSync(r)?S.readFileSync(r):null}findReusableCustomPetId(t){let r=this.loadProfile(),n=r.customPets.filter(o=>o.sourceKind===t.sourceKind&&N(o.name)===N(t.name)&&N(o.description)===N(t.description));return n.length===0?null:(n.find(o=>o.id===r.preferences.selectedPetAssetId)??n[0])?.id??null}compactDuplicateCustomPets(){let t=this.loadProfileForWrite(),r=new Map,n=[];for(let i of t.customPets){let o=Fr(i),c=r.get(o);if(!c){r.set(o,i);continue}let a=i.id===t.preferences.selectedPetAssetId,s=a?c:i;n.push(s.id),a&&r.set(o,i)}if(n.length===0)return t;t.customPets=[...r.values()];for(let i of n)S.rmSync(A.join(this.petDir,"assets",i),{recursive:!0,force:!0});return t.customPets.some(i=>i.id===t.preferences.selectedPetAssetId)||(t.preferences={...t.preferences,selectedPetAssetId:t.customPets[0]?.id??"builtin-anime-horse-girl"}),this.writeProfile(t)}writeCustomPetAssetFiles(t,r,n,i){let o=A.join(this.petDir,"assets",t.id);return S.mkdirSync(o,{recursive:!0}),S.writeFileSync(A.join(o,"pet.json"),JSON.stringify(t,null,2),"utf-8"),S.writeFileSync(A.join(o,"spritesheet.webp"),r),S.writeFileSync(A.join(o,"validation.json"),JSON.stringify(n,null,2),"utf-8"),i&&S.writeFileSync(A.join(o,"production-run.json"),JSON.stringify(i,null,2),"utf-8"),this.upsertCustomPet(t)}defaultProfile(){return{version:1,ownerUserId:this.ownerUserId,soul:null,preferences:{...lt},customPets:[],journeyDates:[],updatedAt:new Date().toISOString()}}normalizeProfile(t){return{version:1,ownerUserId:this.ownerUserId,soul:t.soul??null,preferences:{...lt,...t.preferences??{},selectedPetAssetId:Nr(t.preferences)},customPets:Array.isArray(t.customPets)?t.customPets.filter(pt).map(dt):[],journeyDates:Array.isArray(t.journeyDates)?[...new Set(t.journeyDates)].sort():[],updatedAt:typeof t.updatedAt=="string"?t.updatedAt:new Date().toISOString()}}writeProfile(t){let r={...t,version:1,ownerUserId:this.ownerUserId,updatedAt:new Date().toISOString()};return S.mkdirSync(this.petDir,{recursive:!0}),S.writeFileSync(this.profilePath,JSON.stringify(r,null,2),"utf-8"),r}};function dt(e){return{id:e.id,assetKind:"petdex",sourceKind:e.sourceKind??("source"in e&&e.source&&typeof e.source=="object"?e.source.kind:"forge"),name:e.name,description:e.description,createdAt:e.createdAt,updatedAt:e.updatedAt,atlas:{format:e.atlas.format,columns:e.atlas.columns,rows:e.atlas.rows,frameCount:e.atlas.frameCount,cellWidth:e.atlas.cellWidth,cellHeight:e.atlas.cellHeight,width:e.atlas.width,height:e.atlas.height,sha256:e.atlas.sha256},animations:e.animations,thumbnail:e.thumbnail}}function Fr(e){return[e.sourceKind??"forge",N(e.name),N(e.description)].join(`
|
|
9
|
-
`)}function
|
|
10
|
-
`)}var
|
|
11
|
-
[hatch-pet] timed out after ${r}ms`,code:null})},r);
|
|
8
|
+
\u7528\u4E00\u53E5\u8BDD(\u226420\u5B57)\u4EE5\u4F60\u7684\u6027\u683C\u505A\u51FA\u7B80\u77ED\u53CD\u5E94\u3002\u53EA\u8F93\u51FA\u53CD\u5E94\u6587\u672C\uFF0C\u4E0D\u8981\u5176\u4ED6\u5185\u5BB9\u3002${r}`}function yr(e){return/[!!✨🎉]|搞定|完美|太棒/.test(e)?"excited":/[.。…]|嗯|想|看看/.test(e)?"thinking":/[zZ]|困|睡|累/.test(e)?"sleepy":"normal"}import{createHash as xr}from"node:crypto";var O="qlogic.petdex.asset.v1",Be="qlogic.petdex.validation.v1",m={format:"webp",columns:8,rows:9,frameCount:72,cellWidth:192,cellHeight:208,width:1536,height:1872},M=["idle","running-right","running-left","waving","jumping","failed","waiting","running","review"],Je={idle:{frames:6,durations:[280,110,110,140,140,320]},"running-right":{frames:8,durations:[120,120,120,120,120,120,120,220]},"running-left":{frames:8,durations:[120,120,120,120,120,120,120,220]},waving:{frames:4,durations:[140,140,140,280]},jumping:{frames:5,durations:[140,140,140,140,280]},failed:{frames:8,durations:[140,140,140,140,140,140,140,240]},waiting:{frames:6,durations:[150,150,150,150,150,260]},running:{frames:6,durations:[120,120,120,120,120,220]},review:{frames:6,durations:[150,150,150,150,150,280]}};function K(){let e={};return M.forEach((t,r)=>{let n=Je[t],i=r*m.columns;e[t]={row:r,frames:Array.from({length:n.frames},(o,c)=>i+c),durations:[...n.durations],loop:!0}}),e}function V(e,t){return{id:e.id,assetKind:"petdex",sourceKind:e.source.kind,name:e.name,description:e.description,createdAt:e.createdAt,updatedAt:e.updatedAt,atlas:{format:e.atlas.format,columns:e.atlas.columns,rows:e.atlas.rows,frameCount:e.atlas.frameCount,cellWidth:e.atlas.cellWidth,cellHeight:e.atlas.cellHeight,width:e.atlas.width,height:e.atlas.height,sha256:e.atlas.sha256,...t?{imageUrl:t}:{}},animations:e.animations,thumbnail:e.thumbnail}}function _(e,t){let r=[];if(!e||typeof e!="object")throw new Error("Petdex manifest must be an object");let n=e;n.schema!==O&&r.push(`schema must be ${O}`),n.assetKind!=="petdex"&&r.push("assetKind must be petdex");for(let s of["id","name","description","createdAt","updatedAt"])(typeof n[s]!="string"||n[s].trim().length===0)&&r.push(`missing ${s}`);!n.source||typeof n.source!="object"?r.push("missing source"):(n.source.kind!=="builtin"&&n.source.kind!=="upload"&&n.source.kind!=="forge"&&n.source.kind!=="community"&&r.push("source.kind must be builtin, upload, forge or community"),n.source.prompt!==null&&typeof n.source.prompt!="string"&&r.push("source.prompt must be string or null")),(!n.atlas||typeof n.atlas!="object")&&r.push("missing atlas"),n.atlas?.image!=="spritesheet.webp"&&r.push("atlas image must be spritesheet.webp"),J(n.atlas?.image??"")&&r.push("unsafe path in atlas image"),(typeof n.atlas?.sha256!="string"||!/^[a-f0-9]{64}$/i.test(n.atlas.sha256))&&r.push("atlas sha256 must be a 64 character hex digest"),n.atlas?.format!=="webp"&&r.push("atlas format must be webp"),(n.atlas?.columns!==m.columns||n.atlas?.rows!==m.rows||n.atlas?.frameCount!==m.frameCount||n.atlas?.cellWidth!==m.cellWidth||n.atlas?.cellHeight!==m.cellHeight||n.atlas?.width!==m.width||n.atlas?.height!==m.height)&&r.push("Petdex atlas geometry must be exactly 8x9 cells in a 1536x1872 WebP sheet");let i=wr(t);(!i||i.width!==m.width||i.height!==m.height)&&r.push("spritesheet.webp must be a 1536x1872 WebP image"),i?.hasAlpha||r.push("spritesheet.webp must preserve transparent background alpha; opaque contact sheets or grid backgrounds are not valid Petdex assets");let o=Q(t);n.atlas?.sha256!==o&&r.push("spritesheet sha256 does not match pet.json");let c=n.animations;if(!c||typeof c!="object")r.push("missing animations");else{let s=Object.keys(c).sort(),l=[...M].sort();s.join("\0")!==l.join("\0")&&r.push(`animations must include exactly ${M.join(", ")}`)}let a=[];if(M.forEach((s,l)=>{let u=c?.[s];if(!u){r.push(`missing animation ${s}`);return}u.row!==l&&r.push(`animation ${s} row must be ${l}`);let d=Je[s],p=l*m.columns,f=Array.from({length:d.frames},(w,g)=>p+g);!Array.isArray(u.frames)||u.frames.length!==d.frames?r.push(`animation ${s} must have exactly ${d.frames} frames`):u.frames.some((w,g)=>w!==f[g])?r.push(`animation ${s} frames must be cells ${p}..${p+d.frames-1} (row ${l})`):a.push(...u.frames),!Array.isArray(u.durations)||u.durations.length!==d.frames?r.push(`animation ${s} must have ${d.frames} durations`):u.durations.some(w=>typeof w!="number"||w<=0)&&r.push(`animation ${s} durations must be positive milliseconds`),typeof u.loop!="boolean"&&r.push(`animation ${s} loop must be boolean`)}),(n.thumbnail?.frame===void 0||n.thumbnail.frame<0||n.thumbnail.frame>71)&&r.push("thumbnail frame must be 0..71"),r.length>0)throw new Error(r.join("; "));return{schema:Be,assetId:n.id,valid:!0,validatedAt:new Date().toISOString(),errors:[],warnings:[],atlas:{format:"webp",columns:8,rows:9,frameCount:72,cellWidth:192,cellHeight:208,width:i?.width??m.width,height:i?.height??m.height,sha256:o},animations:{ids:[...M],minFrame:Math.min(...a),maxFrame:Math.max(...a)}}}function Pe(e){return`data:image/webp;base64,${e.toString("base64")}`}function Q(e){return xr("sha256").update(e).digest("hex")}function J(e){return!e||e.includes("..")||e.startsWith("/")||/^[a-zA-Z]:[\\/]/.test(e)||e.includes("\\")}function wr(e){if(e.length<30||e.subarray(0,4).toString("ascii")!=="RIFF"||e.subarray(8,12).toString("ascii")!=="WEBP")return null;let t=12,r=!1;for(;t+8<=e.length;){let n=e.subarray(t,t+4).toString("ascii"),i=e.readUInt32LE(t+4),o=t+8;if(n==="ALPH"&&(r=!0),n==="VP8X"&&o+10<=e.length)return{width:He(e,o+4)+1,height:He(e,o+7)+1,hasAlpha:(e[o]&16)!==0||r};if(n==="VP8 "&&o+10<=e.length)return{width:e.readUInt16LE(o+6)&16383,height:e.readUInt16LE(o+8)&16383,hasAlpha:r};if(n==="VP8L"&&o+5<=e.length){let c=e[o+1],a=e[o+2],s=e[o+3],l=e[o+4];return{width:1+((a&63)<<8|c),height:1+((l&15)<<10|s<<2|(a&192)>>6),hasAlpha:!0}}t=o+i+i%2}return null}function He(e,t){return e[t]|e[t+1]<<8|e[t+2]<<16}var Ge="qlogic.petdex.production.v1",ye="2048x2048";function ze(e){return e.referenceMode==="refine"?"refine":e.referenceImageUrl?"reference":"text"}function We(e,t){let r=t.filter(n=>n.kind==="row-strip"&&!!n.animationId).map(n=>({animationId:n.animationId,status:"pass",frames:m.columns}));return{schema:Ge,status:"complete",sourceMode:e,contract:m,jobs:t,qa:{contactSheet:{rows:m.rows,columns:m.columns,frameCount:m.frameCount},rowReports:r}}}function xe(e,t){e.provider??=t.provider,e.model??=t.model,e.billingUnit??=t.billingUnit,e.size??=t.size,e.billingQuantity+=t.billingQuantity??1,e.durationMs+=t.durationMs??0}import{resolve as Tr}from"node:path";import{join as kr}from"node:path";import{homedir as br}from"node:os";import{join as I}from"node:path";import{existsSync as Di}from"node:fs";import{createHash as Sr}from"node:crypto";import{resolve as Ar}from"node:path";function we(e){return Sr("sha256").update(Ar(e).toLowerCase()).digest("hex").slice(0,16)}var Xe=".qlogicagent";function k(){return process.env.QLOGICAGENT_HOME||I(br(),Xe)}function Y(){let e=process.env.QLOGIC_LLMROUTER_USER_ID?.trim();if(e)return e;let t=process.env.QLOGIC_IMPLICIT_OWNER_ID?.trim();if(t)return t;let r=process.env.QLOGIC_DEVICE_ID?.trim();return r?`oc_${r}`:"oc_local"}function Ir(e){let t=e.trim();if(!t)throw new Error("ownerUserId is required for profile-scoped storage");return encodeURIComponent(t).replace(/\./g,"%2E")}function Z(e=Y()){return I(k(),"profiles",Ir(e))}function qe(e=Y()){return I(Z(e),"memory")}var vr="projectData";function Ke(){return I(k(),vr)}function Se(e){if(!e)throw new Error("getProjectDataDirById: projectId is required");return I(Ke(),e)}function Ve(){return I(k(),"plugins")}function Qe(){return I(k(),"skills")}function Ye(){return I(Z(),"settings.json")}function Ze(){return I(k(),"plugin-cache")}function et(){return I(k(),"mcp.json")}function tt(){return I(k(),"marketplace.json")}function N(e){if(!e)throw new Error("getProjectAgentDir: cwd is required (must not fall back to process.cwd())");return I(e,Xe)}function rt(e){return I(N(e),"plugins")}function nt(e){return I(N(e),"settings.json")}function it(e){return I(N(e),"INSTRUCTIONS.md")}function ot(e){return I(N(e),"rules")}import{resolve as Ti}from"node:path";var Er=()=>{},Ae;function st(){if(Dr(),!Ae)throw new Error("host project authority negotiated but snapshot is not hydrated");return{activeProjectId:Ae.activeProjectId,projects:Ae.projects.map(e=>({...e}))}}function Dr(){let e=Er();if(!e)throw new Error("gateway project authority is not available");return e}function jr(){let e=st();return{activeProjectId:e.activeProjectId,projects:e.projects.map(t=>({...t}))}}function at(e){return jr().projects.find(t=>t.id===e)??null}function _r(e){return at(e)?e:we(e)}function be(e){return Se(_r(e))}function ct(e){return kr(be(e),"sessions")}var Ie=class{constructor(t={}){this.options=t}options;lastActiveWorkdir=null;getActiveProjectRoot(){return this.options.getActiveProjectRoot?.()??process.cwd()}setActiveWorkdir(t){let r=Tr(t);this.lastActiveWorkdir=r,this.options.setActiveWorkdir?.(r)}getActiveWorkdir(){return this.lastActiveWorkdir??this.getActiveProjectRoot()}resolveProjectDir(t){return this.options.resolveProjectDir?.(t)}resolveActiveOwnerUserId(){return Y()}getUserAgentHome(){return k()}getOwnerProfileDir(t){return Z(t)}getProfileMemoryDir(t){return qe(t)}getUserSettingsPath(){return Ye()}getUserSkillsDir(){return Qe()}getUserPluginsDir(){return Ve()}getUserMcpConfigPath(){return et()}getUserPluginCacheDir(){return Ze()}getUserMarketplaceConfigPath(){return tt()}getProjectAgentDir(t=this.getActiveProjectRoot()){return N(t)}getProjectSettingsPath(t=this.getActiveProjectRoot()){return nt(t)}getProjectInstructionsPath(t=this.getActiveProjectRoot()){return it(t)}getProjectPluginsDir(t=this.getActiveProjectRoot()){return rt(t)}getProjectRulesDir(t=this.getActiveProjectRoot()){return ot(t)}getProjectSessionDataRoot(t=this.getActiveProjectRoot()){return ct(t)}},Cr=new Ie;function ee(){return Cr}import S from"node:fs";import b from"node:path";var lt={enabled:!0,selectedPetAssetId:"builtin-anime-horse-girl"},Ur=120,T=class{constructor(t){this.ownerUserId=t;this.petDir=b.join(ee().getOwnerProfileDir(t),"pet"),this.profilePath=b.join(this.petDir,"profile.json")}ownerUserId;petDir;profilePath;loadProfile(){let t=this.readProfileState();return t.corrupt&&console.error(`[pet-profile] Pet profile at ${this.profilePath} is corrupted (${t.reason}); serving default profile for reads. Writes are refused until the file is fixed or removed.`),t.profile}loadProfileForWrite(){let t=this.readProfileState();if(t.corrupt)throw new Error(`[pet-profile] Pet profile at ${this.profilePath} is corrupted (${t.reason}); refusing to overwrite it. Fix or remove the file, then retry.`);return t.profile}readProfileState(){if(!S.existsSync(this.profilePath))return{profile:this.defaultProfile(),corrupt:!1};try{let t=JSON.parse(S.readFileSync(this.profilePath,"utf-8"));return!t||typeof t!="object"||Array.isArray(t)?{profile:this.defaultProfile(),corrupt:!0,reason:"not a JSON object"}:{profile:this.normalizeProfile(t),corrupt:!1}}catch(t){return{profile:this.defaultProfile(),corrupt:!0,reason:t instanceof Error?t.message:String(t)}}}updateSoul(t){let r=this.loadProfileForWrite();return r.soul=t,this.writeProfile(r)}updatePreferences(t){let r=this.loadProfileForWrite();return r.preferences={...r.preferences,...t,selectedPetAssetId:t.selectedPetAssetId??r.preferences.selectedPetAssetId},this.writeProfile(r)}saveJourneySnapshot(t){let r=this.loadProfileForWrite(),n=b.join(this.petDir,"journey");S.mkdirSync(n,{recursive:!0}),S.writeFileSync(b.join(n,`${t.date}.json`),JSON.stringify(t,null,2),"utf-8");let i=new Set(r.journeyDates);i.add(t.date);let o=[...i].sort();for(;o.length>Ur;){let c=o.shift();c&&S.rmSync(b.join(n,`${c}.json`),{force:!0})}return r.journeyDates=o,this.writeProfile(r)}listJourneyDates(){return this.loadProfile().journeyDates}getJourneySnapshot(t){let r=b.join(this.petDir,"journey",`${t}.json`);if(!S.existsSync(r))return null;try{return JSON.parse(S.readFileSync(r,"utf-8"))}catch(n){return console.error(`[pet-profile] Journey snapshot at ${r} is unreadable or corrupted (${n instanceof Error?n.message:String(n)}); returning no entry.`),null}}upsertCustomPet(t){let r=this.loadProfileForWrite(),n=b.join(this.petDir,"assets",t.id);S.mkdirSync(n,{recursive:!0}),S.writeFileSync(b.join(n,"pet.json"),JSON.stringify(t,null,2),"utf-8");let i=ut(t),o=r.customPets.find(c=>c.id===t.id);return r.customPets=o?r.customPets.map(c=>c.id===t.id?i:c):[i,...r.customPets],r.preferences={...r.preferences,selectedPetAssetId:t.id},this.writeProfile(r)}deleteCustomPet(t){let r=this.loadProfileForWrite();return r.customPets=r.customPets.filter(n=>n.id!==t),S.rmSync(b.join(this.petDir,"assets",t),{recursive:!0,force:!0}),r.preferences.selectedPetAssetId===t&&(r.preferences={...r.preferences,selectedPetAssetId:"builtin-anime-horse-girl"}),this.writeProfile(r)}listCustomPets(){return this.loadProfile().customPets}getCustomPet(t){let r=b.join(this.petDir,"assets",t,"pet.json");if(!S.existsSync(r))return null;try{let n=JSON.parse(S.readFileSync(r,"utf-8"));return Or(n)?n:(console.error(`[pet-profile] Custom pet asset at ${r} does not match the petdex asset schema; treating the pet as unavailable.`),null)}catch(n){return console.error(`[pet-profile] Custom pet asset at ${r} is unreadable or corrupted (${n instanceof Error?n.message:String(n)}); treating the pet as unavailable.`),null}}getCustomPetSpritesheet(t){let r=b.join(this.petDir,"assets",t,"spritesheet.webp");return S.existsSync(r)?S.readFileSync(r):null}findReusableCustomPetId(t){let r=this.loadProfile(),n=r.customPets.filter(o=>o.sourceKind===t.sourceKind&&F(o.name)===F(t.name)&&F(o.description)===F(t.description));return n.length===0?null:(n.find(o=>o.id===r.preferences.selectedPetAssetId)??n[0])?.id??null}compactDuplicateCustomPets(){let t=this.loadProfileForWrite(),r=new Map,n=[];for(let i of t.customPets){let o=Lr(i),c=r.get(o);if(!c){r.set(o,i);continue}let a=i.id===t.preferences.selectedPetAssetId,s=a?c:i;n.push(s.id),a&&r.set(o,i)}if(n.length===0)return t;t.customPets=[...r.values()];for(let i of n)S.rmSync(b.join(this.petDir,"assets",i),{recursive:!0,force:!0});return t.customPets.some(i=>i.id===t.preferences.selectedPetAssetId)||(t.preferences={...t.preferences,selectedPetAssetId:t.customPets[0]?.id??"builtin-anime-horse-girl"}),this.writeProfile(t)}writeCustomPetAssetFiles(t,r,n,i){let o=b.join(this.petDir,"assets",t.id);return S.mkdirSync(o,{recursive:!0}),S.writeFileSync(b.join(o,"pet.json"),JSON.stringify(t,null,2),"utf-8"),S.writeFileSync(b.join(o,"spritesheet.webp"),r),S.writeFileSync(b.join(o,"validation.json"),JSON.stringify(n,null,2),"utf-8"),i&&S.writeFileSync(b.join(o,"production-run.json"),JSON.stringify(i,null,2),"utf-8"),this.upsertCustomPet(t)}defaultProfile(){return{version:1,ownerUserId:this.ownerUserId,soul:null,preferences:{...lt},customPets:[],journeyDates:[],updatedAt:new Date().toISOString()}}normalizeProfile(t){return{version:1,ownerUserId:this.ownerUserId,soul:t.soul??null,preferences:{...lt,...t.preferences??{},selectedPetAssetId:Mr(t.preferences)},customPets:Array.isArray(t.customPets)?t.customPets.filter(dt).map(ut):[],journeyDates:Array.isArray(t.journeyDates)?[...new Set(t.journeyDates)].sort():[],updatedAt:typeof t.updatedAt=="string"?t.updatedAt:new Date().toISOString()}}writeProfile(t){let r={...t,version:1,ownerUserId:this.ownerUserId,updatedAt:new Date().toISOString()};return S.mkdirSync(this.petDir,{recursive:!0}),S.writeFileSync(this.profilePath,JSON.stringify(r,null,2),"utf-8"),r}};function ut(e){return{id:e.id,assetKind:"petdex",sourceKind:e.sourceKind??("source"in e&&e.source&&typeof e.source=="object"?e.source.kind:"forge"),name:e.name,description:e.description,createdAt:e.createdAt,updatedAt:e.updatedAt,atlas:{format:e.atlas.format,columns:e.atlas.columns,rows:e.atlas.rows,frameCount:e.atlas.frameCount,cellWidth:e.atlas.cellWidth,cellHeight:e.atlas.cellHeight,width:e.atlas.width,height:e.atlas.height,sha256:e.atlas.sha256},animations:e.animations,thumbnail:e.thumbnail}}function Lr(e){return[e.sourceKind??"forge",F(e.name),F(e.description)].join(`
|
|
9
|
+
`)}function F(e){return e.trim().replace(/\s+/g," ").toLowerCase()}function dt(e){if(!e||typeof e!="object")return!1;let t=e;return t.assetKind==="petdex"&&typeof t.id=="string"&&(t.sourceKind==="builtin"||t.sourceKind==="upload"||t.sourceKind==="forge"||t.sourceKind==="community"||t.sourceKind===void 0)&&typeof t.name=="string"&&typeof t.description=="string"&&typeof t.createdAt=="string"&&typeof t.updatedAt=="string"&&pt(t.atlas)}function Mr(e){if(typeof e?.selectedPetAssetId=="string"){let t=e.selectedPetAssetId.trim();if(t==="builtin-anime-horse-girl"||t&&!t.startsWith("builtin-"))return t}return"builtin-anime-horse-girl"}function Or(e){if(!dt(e))return!1;let t=e;return t.schema==="qlogic.petdex.asset.v1"&&$r(t.atlas)&&typeof t.source=="object"&&t.source!==null&&typeof t.animations=="object"&&t.animations!==null&&typeof t.thumbnail=="object"&&t.thumbnail!==null}function pt(e){if(!e||typeof e!="object")return!1;let t=e;return t.format==="webp"&&t.columns===8&&t.rows===9&&t.frameCount===72&&t.cellWidth===192&&t.cellHeight===208&&t.width===1536&&t.height===1872&&typeof t.sha256=="string"}function $r(e){return pt(e)&&e.image==="spritesheet.webp"}var te=class{soul=null;profileService;constructor(t,r){this.profileService=new T(r??ee().resolveActiveOwnerUserId())}load(){if(this.soul)return this.soul;let t=this.profileService.loadProfile();if(!t.soul)return null;let r=t.soul;return this.soul=X(t.soul),Ne(r,this.soul)&&this.persist(),this.soul}async ensureSoul(t,r,n){let i=this.load();if(i)return i;let o=`${t}-xiaozhi-claw`,c;return r&&(c=await r(me(o),ge(o))),this.soul=Fe({seed:o,hatchedAt:new Date().toISOString(),identity:c,requestedBreedId:n}),this.persist(),this.soul}addExperience(t){if(!this.soul)return{leveledUp:!1,level:0,experience:0};this.soul.experience+=t;let r=this.soul.level*100,n=!1;for(;this.soul.experience>=r;)this.soul.experience-=r,this.soul.level+=1,n=!0;return this.persist(),{leveledUp:n,level:this.soul.level,experience:this.soul.experience}}getSoul(){return this.soul}updateSoul(t){this.soul=X(t),this.persist()}persist(){this.profileService.updateSoul(this.soul)}};var ft=new q(he);import*as re from"node:fs";import*as ve from"node:path";function Nr(e){let t=new Date(e),r=t.getFullYear(),n=String(t.getMonth()+1).padStart(2,"0"),i=String(t.getDate()).padStart(2,"0");return`${r}-${n}-${i}`}async function mt(e,t){let r=new Set,n=new Set,i=new Set,o={},c=[],a=0,s=0;for(let l of t.listProjectIds()){let u;try{u=await t.readProjectTurns(l)}catch{continue}for(let d of u)if(Nr(d.createdAt)===e){a++,n.add(l),d.model&&i.add(d.model),d.agentMode&&(o[d.agentMode]=(o[d.agentMode]??0)+1);for(let p of d.toolSummary?.calledTools??[])r.add(p);s+=d.fileContext?.changedFileCount??0;for(let p of d.fileContext?.changedPathsPreview??[])c.length<8&&c.push(p)}}return{date:e,turns:a,filesChanged:s,toolsUsed:[...r],projects:[...n],models:[...i],modes:o,topChangedPaths:c}}function gt(e,t){let r=e?.name?.trim()||"\u4F60\u7684\u4F19\u4F34",n=e?`\u4F60\u662F\u4E00\u53EA\u540D\u53EB\u300C${r}\u300D\u7684${e.species||"\u5C0F\u5BA0\u7269"},\u6027\u683C${e.personality||"\u6E29\u548C"}${e.catchphrase?`,\u53E3\u5934\u7985\u662F\u300C${e.catchphrase}\u300D`:""}\u3002`:`\u4F60\u662F\u7528\u6237\u7684\u684C\u9762\u5BA0\u7269\u4F19\u4F34\u300C${r}\u300D\u3002`,i=[`\u56DE\u5408\u6570 ${t.turns}`,`\u6539\u52A8\u6587\u4EF6 ${t.filesChanged} \u4E2A`,t.toolsUsed.length?`\u7528\u5230\u7684\u5DE5\u5177:${t.toolsUsed.join("\u3001")}`:"",t.projects.length?`\u6D89\u53CA ${t.projects.length} \u4E2A\u9879\u76EE`:"",t.topChangedPaths.length?`\u90E8\u5206\u6539\u52A8\u6587\u4EF6:${t.topChangedPaths.join("\u3001")}`:""].filter(Boolean).join(";");return[n,`\u4E0B\u9762\u662F\u4E3B\u4EBA ${t.date} \u8FD9\u4E00\u5929\u5728\u7535\u8111\u4E0A\u548C\u4F60\u4E00\u8D77\u5DE5\u4F5C\u7684\u771F\u5B9E\u8BB0\u5F55:`,`${i}\u3002`,"\u8BF7\u4EE5\u7B2C\u4E00\u4EBA\u79F0(\u5BA0\u7269\u7684\u53E3\u543B)\u3001\u7528 2-4 \u53E5\u6E29\u6696\u53E3\u8BED\u5316\u7684\u4E2D\u6587,\u8BB2\u8BB2\u4ECA\u5929\u966A\u4E3B\u4EBA\u505A\u4E86\u4EC0\u4E48\u3002","\u53EA\u80FD\u4F9D\u636E\u4E0A\u9762\u7ED9\u51FA\u7684\u771F\u5B9E\u8BB0\u5F55,\u4E0D\u8981\u7F16\u9020\u6570\u5B57\u3001\u6587\u4EF6\u540D\u6216\u6CA1\u53D1\u751F\u8FC7\u7684\u4E8B;\u4E0D\u8981\u9010\u6761\u7F57\u5217\u6570\u636E,\u8981\u50CF\u5728\u8DDF\u4E3B\u4EBA\u804A\u5929\u3002"].join(`
|
|
10
|
+
`)}var Fr=220;function Hr(e,t){return`${e}:\u4ECA\u5929\u6211\u966A\u4F60\u5FD9\u4E86 ${t.turns} \u4E2A\u56DE\u5408,\u6539\u4E86 ${t.filesChanged} \u4E2A\u6587\u4EF6,\u8F9B\u82E6\u5566~`}async function ht(e){let t=await e.aggregate();if(t.turns===0)return null;let r={turns:t.turns,filesChanged:t.filesChanged,toolsUsed:t.toolsUsed,projects:t.projects},n=null;if(e.llmCall)try{n=await e.llmCall(gt(e.resolveSoul(),t),Fr)}catch{n=null}return(!n||!n.trim())&&(n=Hr(e.petName,t)),{date:e.date,day:1,petName:e.petName,stateLabel:"\u672C\u673A\u5DE5\u4F5C",narrative:n.trim(),stats:r,generatedAt:e.now?e.now():new Date().toISOString(),generator:e.generator??"auto"}}var Br=120;function Pt(e){let t=ve.join(be(e),"turn-telemetry"),r;try{r=re.readdirSync(t)}catch{return[]}let n=[];for(let i of r)if(i.endsWith(".json"))try{n.push(JSON.parse(re.readFileSync(ve.join(t,i),"utf-8")))}catch{}return n}function Jr(e){let t=new Date;t.setHours(0,0,0,0),t.setDate(t.getDate()-e);let r=t.getFullYear(),n=String(t.getMonth()+1).padStart(2,"0"),i=String(t.getDate()).padStart(2,"0");return`${r}-${n}-${i}`}async function yt(e,t){let r=new T(e),n=r.loadProfile(),i=n.soul?.name?.trim()||"\u5BA0\u7269",o=Math.max(1,Math.min(t.maxDays??7,Br)),c=[];for(let a=1;a<=o;a++){let s=Jr(a);if(r.getJourneySnapshot(s))continue;let l=await ht({date:s,petName:i,aggregate:()=>mt(s,{listProjectIds:t.listProjectIds,readProjectTurns:async u=>Pt(u)}),resolveSoul:()=>n.soul,llmCall:t.llmCall,generator:t.generator});l&&(r.saveJourneySnapshot(l),c.push(s),t.log?.(`[pet-journey] generated ${s}`))}return c}import{randomUUID as wt}from"node:crypto";import C from"node:fs";import U from"node:path";import{fileURLToPath as Gr}from"node:url";import{gzipSync as mo}from"node:zlib";import{createCanvas as zr,loadImage as Wr}from"@napi-rs/canvas";async function Ee(e){return Xr(C.readFileSync(e))}async function Xr(e){let t=await nn(e);for(let s of t.keys())if(J(s))throw new Error(`unsafe path in Petdex package: ${s}`);if(t.has("manifest.json")||[...t.keys()].some(s=>s.toLowerCase().endsWith(".svg")))throw new Error("SVG .pet state packages are not supported by Petdex v1");let r=t.get("pet.json");if(!r)throw new Error("Petdex package missing pet.json");let n=JSON.parse(r.toString("utf-8")),i=tn(n)??"spritesheet.webp";if(J(i))throw new Error(`unsafe path in Petdex manifest: ${i}`);let o=t.get(i);if(!o)throw new Error(`Petdex package missing ${i}`);let c=Zr(n,o),a=_(c,o);return{manifest:c,spritesheet:o,validation:a}}async function ie(e){C.mkdirSync(e.outputDir,{recursive:!0});let t=Yr(e.fileName??`${e.asset.id}.petdex`),r=U.join(e.outputDir,t.endsWith(".petdex")?t:`${t}.petdex`);return C.writeFileSync(r,qr(e)),r}function qr(e){let t=_(e.asset,e.spritesheet),r=[{name:"pet.json",data:Buffer.from(JSON.stringify(e.asset,null,2),"utf-8")},{name:"spritesheet.webp",data:e.spritesheet},{name:"validation.json",data:Buffer.from(JSON.stringify(t,null,2),"utf-8")},...e.productionRun?[{name:"production-run.json",data:Buffer.from(JSON.stringify(e.productionRun,null,2),"utf-8")}]:[]];return on(r)}async function oe(e){let t=e.now??new Date().toISOString(),r=e.id??`petdex-${wt()}`,n=await Qr(e.spritesheet),i=Q(n),o={schema:O,id:r,assetKind:"petdex",name:e.name,description:e.description,createdAt:t,updatedAt:t,source:{kind:e.sourceKind??"forge",prompt:e.prompt??null},sourcePrompt:e.prompt??void 0,atlas:{image:"spritesheet.webp",...m,sha256:i},animations:K(),thumbnail:{frame:0}},c=_(o,n);return{asset:o,spritesheet:n,validation:c}}var St=["builtin-anime-horse-girl"],ne=null;function At(){return[...St]}async function bt(){return ne||(ne=Promise.all(St.map(e=>Kr(e))).catch(e=>{throw ne=null,e})),ne}async function Kr(e){let t=Vr(),r=U.join(t,`${e}.petdex`);if(C.existsSync(r)){let l=await Ee(r);return xt(e,l.manifest),{asset:l.manifest,spritesheet:l.spritesheet,validation:l.validation}}let n=U.join(t,e),i=U.join(n,"pet.json"),o=U.join(n,"spritesheet.webp");if(!C.existsSync(i)||!C.existsSync(o))throw new Error(`Missing published builtin Petdex asset ${e} under ${t}`);let c=JSON.parse(C.readFileSync(i,"utf-8")),a=C.readFileSync(o),s=_(c,a);return xt(e,c),{asset:c,spritesheet:a,validation:s}}function Vr(){let e=process.env.QLOGICAGENT_BUILTIN_PETDEX_DIR?.trim();return e?U.resolve(e):U.resolve(U.dirname(Gr(import.meta.url)),"builtin-petdex")}function xt(e,t){if(t.id!==e)throw new Error(`Builtin Petdex asset id mismatch: expected ${e}, got ${t.id}`);if(t.source.kind!=="builtin")throw new Error(`Builtin Petdex asset ${e} must declare source.kind=builtin`)}async function Qr(e){let t=await Wr(e),r=zr(m.width,m.height),n=r.getContext("2d");return n.clearRect(0,0,m.width,m.height),n.imageSmoothingEnabled=!0,n.imageSmoothingQuality="high",n.drawImage(t,0,0,m.width,m.height),Buffer.from(await r.encode("webp"))}function Yr(e){return e.replace(/[^a-zA-Z0-9._-]/g,"_").replace(/^_+/,"")||"petdex-asset.petdex"}function Zr(e,t){if(en(e))return e;if(!It(e))throw new Error("Petdex package pet.json must be either standard Petdex metadata or qlogic.petdex.asset.v1");let r=new Date().toISOString(),n=rn(e.id),i=Q(t);return{schema:O,id:n,assetKind:"petdex",name:e.displayName.trim(),description:e.description.trim(),createdAt:r,updatedAt:r,source:{kind:"upload",prompt:null},sourcePrompt:void 0,atlas:{image:"spritesheet.webp",...m,sha256:i},animations:K(),thumbnail:{frame:0}}}function en(e){return!!e&&typeof e=="object"&&!Array.isArray(e)&&e.schema===O}function It(e){if(!e||typeof e!="object"||Array.isArray(e))return!1;let t=e;return typeof t.id=="string"&&t.id.trim()!==""&&typeof t.displayName=="string"&&t.displayName.trim()!==""&&typeof t.description=="string"&&t.description.trim()!==""&&typeof t.spritesheetPath=="string"&&t.spritesheetPath.trim()!==""}function tn(e){return It(e)?e.spritesheetPath.trim():null}function rn(e){return e.trim().toLowerCase().replace(/[^a-z0-9._-]+/g,"-").replace(/^-+|-+$/g,"")||`petdex-${wt()}`}async function nn(e){let t=new Map,r=0;for(;r<e.length-4&&e.readUInt32LE(r)===67324752;){let i=e.readUInt16LE(r+8),o=e.readUInt32LE(r+18),c=e.readUInt32LE(r+22),a=e.readUInt16LE(r+26),s=e.readUInt16LE(r+28),l=r+30,u=e.subarray(l,l+a).toString("utf-8"),d=l+a+s,p=e.subarray(d,d+o);if(i===0)t.set(u,e.subarray(d,d+c));else if(i===8){let{inflateRawSync:f}=await import("node:zlib");t.set(u,f(p))}r=d+o}return t}function on(e){let t=[],r=[],n=0,{time:i,date:o}=sn();for(let l of e){if(J(l.name))throw new Error(`unsafe path in Petdex package entry: ${l.name}`);let u=Buffer.from(l.name,"utf-8"),d=cn(l.data),p=Buffer.alloc(30);p.writeUInt32LE(67324752,0),p.writeUInt16LE(20,4),p.writeUInt16LE(2048,6),p.writeUInt16LE(0,8),p.writeUInt16LE(i,10),p.writeUInt16LE(o,12),p.writeUInt32LE(d,14),p.writeUInt32LE(l.data.length,18),p.writeUInt32LE(l.data.length,22),p.writeUInt16LE(u.length,26),p.writeUInt16LE(0,28),t.push(p,u,l.data);let f=Buffer.alloc(46);f.writeUInt32LE(33639248,0),f.writeUInt16LE(20,4),f.writeUInt16LE(20,6),f.writeUInt16LE(2048,8),f.writeUInt16LE(0,10),f.writeUInt16LE(i,12),f.writeUInt16LE(o,14),f.writeUInt32LE(d,16),f.writeUInt32LE(l.data.length,20),f.writeUInt32LE(l.data.length,24),f.writeUInt16LE(u.length,28),f.writeUInt16LE(0,30),f.writeUInt16LE(0,32),f.writeUInt16LE(0,34),f.writeUInt16LE(0,36),f.writeUInt32LE(0,38),f.writeUInt32LE(n,42),r.push(f,u),n+=p.length+u.length+l.data.length}let c=n,a=Buffer.concat(r),s=Buffer.alloc(22);return s.writeUInt32LE(101010256,0),s.writeUInt16LE(0,4),s.writeUInt16LE(0,6),s.writeUInt16LE(e.length,8),s.writeUInt16LE(e.length,10),s.writeUInt32LE(a.length,12),s.writeUInt32LE(c,16),s.writeUInt16LE(0,20),Buffer.concat([...t,a,s])}function sn(){let e=new Date,t=e.getHours()<<11|e.getMinutes()<<5|Math.floor(e.getSeconds()/2),r=e.getFullYear()-1980<<9|e.getMonth()+1<<5|e.getDate();return{time:t,date:r}}var an=new Uint32Array(256).map((e,t)=>{let r=t;for(let n=0;n<8;n++)r=r&1?3988292384^r>>>1:r>>>1;return r>>>0});function cn(e){let t=4294967295;for(let r of e)t=an[(t^r)&255]^t>>>8;return(t^4294967295)>>>0}import y from"node:fs/promises";import Mt from"node:os";import h from"node:path";import{createCanvas as le,loadImage as _e}from"@napi-rs/canvas";import{spawn as ln}from"node:child_process";import{existsSync as vt}from"node:fs";import{dirname as Et,join as ce}from"node:path";import{fileURLToPath as un}from"node:url";var dn=Et(un(import.meta.url)),se,ae;function Dt(e,t,r){return new Promise(n=>{let i="",o="",c=!1,a=u=>{c||(c=!0,clearTimeout(l),n(u))},s=ln(e,t,{windowsHide:!0}),l=setTimeout(()=>{s.kill("SIGKILL"),a({ok:!1,stdout:i,stderr:`${o}
|
|
11
|
+
[hatch-pet] timed out after ${r}ms`,code:null})},r);l.unref?.(),s.stdout?.on("data",u=>{i+=u.toString()}),s.stderr?.on("data",u=>{o+=u.toString()}),s.on("error",u=>a({ok:!1,stdout:i,stderr:`${o}${u instanceof Error?u.message:String(u)}`,code:null})),s.on("close",u=>a({ok:u===0,stdout:i,stderr:o,code:u}))})}function pn(){let e=[],t=process.env.QLOGICAGENT_PYTHON?.trim();return t&&e.push(t),e.push("python3","python","py"),e}async function fn(e){let t=await Dt(e,["-c","import PIL; import sys; sys.stdout.write('hatchpet-ok')"],1e4);return t.code===0&&t.stdout.includes("hatchpet-ok")}async function jt(){if(se!==void 0)return se;for(let e of pn())if(await fn(e))return se=e,e;return se=null,null}function Rt(){if(ae!==void 0)return ae;let e=[],t=process.env.QLOGICAGENT_HATCHPET_DIR?.trim();t&&e.push(ce(t,"scripts"),t);let r=dn;for(let n=0;n<7;n++){e.push(ce(r,"vendor","hatch-pet","scripts"));let i=Et(r);if(i===r)break;r=i}for(let n of e)if(vt(ce(n,"compose_atlas.py")))return ae=n,n;return ae=null,null}async function kt(){return await jt()!==null&&Rt()!==null}async function De(e,t,r={}){let n=await jt();if(!n)throw new Error("Petdex generation requires Python with Pillow; none found (set QLOGICAGENT_PYTHON to a python that can `import PIL`)");let i=Rt();if(!i)throw new Error("Vendored hatch-pet scripts not found (set QLOGICAGENT_HATCHPET_DIR)");let o=ce(i,e);if(!vt(o))throw new Error(`Unknown hatch-pet script: ${e}`);return Dt(n,[o,...t],r.timeoutMs??12e4)}function mn(e){let t=(e??"").trim();return/\bfail\b/i.test(t)&&!/\bpass\b/i.test(t.slice(0,8))?{ok:!1,reason:(t.match(/fail[:\s-]*(.+)/i)?.[1]??"").trim().slice(0,200)}:{ok:!0,reason:""}}async function je(e,t,r=console.error){try{let n=await e();return n.trim()?mn(n):(r(`[petdex-forge] ${t.label} returned an empty verdict for ${t.target} (image likely not delivered to the model); accepting candidate unverified`),{ok:!0,reason:"",qaSkipped:!0})}catch(n){let i=n instanceof Error?n.message:String(n);return r(`[petdex-forge] ${t.label} call failed for ${t.target}: ${i}; accepting candidate unverified`),{ok:!0,reason:"",qaSkipped:!0}}}var _t="references/canonical-base.png",gn="single centered full-body desktop pet character on a flat chroma-key background, readable at pet size",hn="one horizontal animation row strip with evenly spaced full-body frames sharing a single consistent character identity",Pn="4096x1024",ke="#FF00FF",Ot="110",$t="stable-slots",yn="90",Nt=["STRICT BACKGROUND: render one single continuous flat background of the same solid color filling the entire image edge to edge.","Do NOT draw any picture frame, framed panel, border, mat, outline, box, gallery frame, white or light margin, or divider around or between the poses.","The poses sit directly on the one seamless flat background, evenly spaced, with nothing separating them.","IDENTITY LOCK: every frame is the EXACT same character \u2014 identical species, body shape, proportions, colors, palette, face, and markings. Do not redesign, restyle, recolor, or resize the character between frames; only its pose changes.","Each pose is ONE connected solid silhouette at a consistent size. No detached parts, sweat drops, tears, dust, puffs, sparkles, speed lines, motion blur, floating effects, or drop shadows."].join(" "),xn="Leftward gait is the framewise horizontal mirror of the approved rightward row, preserving frame order and timing semantics.",wn=2,Sn=2;async function Te(e,t,r={}){if(!await kt())throw new Error("Petdex forge requires the vendored Hatch-Pet pipeline (Python with Pillow). Install Python + Pillow or set QLOGICAGENT_PYTHON to a python that can `import PIL`.");let n={billingQuantity:0,durationMs:0},i=[],o=[],c=ze(e),a=await Kn(),s=await qn(e);try{await H("prepare_pet_run.py",["--pet-name",e.name,"--display-name",e.name,"--description",e.description,"--pet-notes",e.prompt?.trim()||e.description,"--pet-id",Yn(e.id??e.name),"--output-dir",a,"--chroma-key","auto",...s.flatMap(x=>["--reference",x])]);let l=h.join(a,"imagegen-jobs.json"),u=await zt(l),d=r.inspectImage,p=Math.max(1,r.candidates??wn),f=[],w=[],g=ke,j;for(let x of u.jobs){if(!!(x.derivation_policy?.may_derive&&x.derivation_policy.may_derive_from)&&!d){await Ht(a),i.push({id:`row-${x.id}`,kind:"row-strip",status:"complete",animationId:x.id,prompt:`derived: framewise-horizontal-mirror of ${x.derivation_policy.may_derive_from}`,inputImages:[],outputUrl:x.output_path});continue}let ue=await y.readFile(h.join(a,x.prompt_file),"utf-8"),qt=x.retry_prompt_file?await y.readFile(h.join(a,x.retry_prompt_file),"utf-8").catch(()=>{}):void 0;o.push(ue);let $=x.kind==="base-pet",{mediaUrl:Kt,inputImages:Vt,qaSkipped:Qt}=await Bt({runDir:a,job:x,prompt:ue,retryPrompt:qt,generateImage:t,inspectImage:d,candidates:p,usage:n,upload:r.uploadReferenceImage,baseDataUrl:j});Qt&&w.push($?"base-reference":`row-${x.id}`),$&&(await y.copyFile(h.join(a,x.output_path),h.join(a,_t)),g=await Qn(h.join(a,x.output_path)),j=await vn(h.join(a,_t))),x.status="complete",await y.writeFile(l,JSON.stringify(u,null,2),"utf-8"),i.push({id:$?"base-reference":`row-${x.id}`,kind:$?"reference":"row-strip",status:"complete",...$?{}:{animationId:x.id},prompt:ue,inputImages:Vt,outputUrl:Kt}),$||f.push(x)}let E=h.join(a,"decoded"),P=h.join(a,"frames"),A=h.join(a,"atlas.png"),v=h.join(a,"atlas.webp");await H("extract_strip_frames.py",["--decoded-dir",E,"--output-dir",P,"--chroma-key",g,"--key-threshold",Ot,"--method",$t]),await Dn({runDir:a,decodedDir:E,framesDir:P,generatedRows:f,chromaHex:g,generateImage:t,inspectImage:d,candidates:p,baseDataUrl:j,usage:n,upload:r.uploadReferenceImage,productionJobs:i});let D=h.join(a,"qa","contact-sheet.png");await Gt(a,P,A,v,D),j&&await $n({runDir:a,framesDir:P,atlasPng:A,atlasWebp:v,contactSheet:D,generatedRows:f,generateImage:t,inspectImage:d,candidates:p,usage:n,upload:r.uploadReferenceImage,baseDataUrl:j}),await Ce("render_animation_previews.py",["--frames-root",P,"--output-dir",h.join(a,"qa","previews")]);let L=await y.readFile(v);return{...await oe({id:e.id,name:e.name,description:e.description,prompt:e.prompt,spritesheet:L,sourceKind:"forge"}),prompt:o.join(`
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
|
-
`),productionRun:
|
|
15
|
+
`),productionRun:We(c,i),...w.length>0?{qaSkippedJobs:w}:{},model:n.model,size:n.size,durationMs:n.durationMs||void 0,...n.provider?{mediaUsage:{provider:n.provider,model:n.model??"unknown",billingUnit:n.billingUnit??"per_call",billingQuantity:n.billingQuantity||1}}:{}}}finally{await Lt(s.length?h.dirname(s[0]):void 0),Vn()||await Lt(a)}}async function Ft(e){let t=await Te(e.input,e.generateImage,{uploadReferenceImage:e.uploadReferenceImage}),r=h.join(e.outputDir,t.asset.id);await y.mkdir(r,{recursive:!0});let n=h.join(r,"pet.json"),i=h.join(r,"spritesheet.webp"),o=h.join(r,"validation.json"),c=h.join(r,"production-run.json");await y.writeFile(n,JSON.stringify(t.asset,null,2),"utf-8"),await y.writeFile(i,t.spritesheet),await y.writeFile(o,JSON.stringify(t.validation,null,2),"utf-8"),await y.writeFile(c,JSON.stringify(t.productionRun,null,2),"utf-8");let a=await ie({asset:t.asset,spritesheet:t.spritesheet,validation:t.validation,productionRun:t.productionRun,outputDir:e.outputDir,fileName:`${t.asset.id}.petdex`});return{...t,packagePath:a,assetDir:r,manifestPath:n,spritesheetPath:i,validationPath:o,productionRunPath:c}}async function G(e){if(e.startsWith("data:")){let t=e.match(/^data:[^;]+;base64,(.+)$/);if(!t)throw new Error("Generated Petdex image data URL is not base64 encoded");return Buffer.from(t[1],"base64")}if(/^https?:\/\//i.test(e)){let t=await fetch(e);if(!t.ok)throw new Error(`Generated Petdex image download failed: ${t.status} ${t.statusText}`);return Buffer.from(await t.arrayBuffer())}return e.startsWith("file://")?y.readFile(new URL(e)):y.readFile(e)}async function Ht(e){await H("derive_running_left_from_running_right.py",["--run-dir",e,"--confirm-appropriate-mirror","--decision-note",xn,"--force"])}async function Tt(e,t,r,n,i,o){let c=await zn(e,t,o),a=t.kind==="base-pet",s=c.filter(p=>p.role!=="layout-guide"),l=s.find(p=>p.role==="canonical-reference")??s[0],u=await n({prompt:`${r}
|
|
16
16
|
|
|
17
|
-
${Nt}`,purpose:a?"petdex-reference":"petdex-row-strip",...a?{}:{animationId:t.id},style:a?
|
|
17
|
+
${Nt}`,purpose:a?"petdex-reference":"petdex-row-strip",...a?{}:{animationId:t.id},style:a?gn:hn,size:a?ye:Pn,imageUrl:l?.imageUrl,referenceImages:s,n:1,quality:"auto"});xe(i,u);let d=u.mediaUrls[0];if(!d)throw new Error(`Petdex generation returned no image for job ${t.id}`);return{mediaUrl:d,inputImages:s}}async function Re(e,t,r){let n=h.join(e,t.output_path);await y.mkdir(h.dirname(n),{recursive:!0}),await y.writeFile(n,await G(r))}async function Bt(e){let t=[e.prompt,...e.retryPrompt?[e.retryPrompt]:[]].slice(0,Sn),r=null;for(let i of t)for(let o=0;o<e.candidates;o++){let c=await Tt(e.runDir,e.job,i,e.generateImage,e.usage,e.upload);if(!e.inspectImage)return await Re(e.runDir,e.job,c.mediaUrl),c;let a=await An(e.inspectImage,e.job,c.mediaUrl,e.baseDataUrl);if(a.ok)return await Re(e.runDir,e.job,c.mediaUrl),a.qaSkipped?{...c,qaSkipped:!0}:c;r=c}let n=r??await Tt(e.runDir,e.job,e.prompt,e.generateImage,e.usage,e.upload);return await Re(e.runDir,e.job,n.mediaUrl),n}var Jt={idle:6,"running-right":8,"running-left":8,waving:4,jumping:5,failed:8,waiting:6,running:6,review:6};async function An(e,t,r,n){try{let i=t.kind==="base-pet"?bn:In(t.id,Jt[t.id]??6),o=t.kind==="base-pet"||!n?[r]:[r,n];return await je(()=>e({prompt:i,imageUrls:o}),{label:"vision QA",target:`job ${t.id}`})}catch(i){return console.error(`[petdex-forge] vision QA call failed for job ${t.id}: ${i instanceof Error?i.message:String(i)}; accepting candidate unverified`),{ok:!0,reason:"",qaSkipped:!0}}}var bn=["You are a strict desktop-pet sprite reviewer. The image is a single pet character reference.","Reply PASS only if ALL hold: one centered full-body cute pet; one flat solid background; no text, scenery, picture frames, borders, drop shadows, or detached effects.",'Reply with exactly "PASS" or "FAIL: <one short reason>".'].join(" ");function In(e,t){return[`You are a strict sprite-sheet reviewer. Image 1 is a horizontal strip of ${t} animation frames for a desktop pet's "${e}" animation. Image 2 is the canonical reference of the SAME pet.`,"Reply PASS only if ALL hold: (1) every frame is the SAME character as the reference \u2014 same species, colors, palette, face, proportions, markings; (2) one flat solid background with NO picture frames, borders, boxes, mats, panels, dividers, or copied guide lines; (3) each pose is a complete pet, fully inside its own area, not cut off or split between cells; (4) no detached effects \u2014 no drop shadows, sparkles, dust, tears, speed lines, or text.",'Reply with exactly "PASS" or "FAIL: <one short reason>".'].join(" ")}async function vn(e){let t=await y.readFile(e);return`data:${e.toLowerCase().endsWith(".webp")?"image/webp":"image/png"};base64,${t.toString("base64")}`}var En=2;async function Dn(e){let t=h.join(e.runDir,"qa","review.json"),r=()=>Ce("inspect_frames.py",["--frames-root",e.framesDir,"--json-out",t,"--chroma-adjacent-threshold",yn]);await r();let n=await Ut(t);for(let i of e.generatedRows){let o=0;for(;n&&Gn(n,i.id)&&o<En;)o++,await jn(e,i),await kn(e,await Rn(e,i)),await r(),n=await Ut(t)}}async function jn(e,t){let r=await y.readFile(h.join(e.runDir,t.prompt_file),"utf-8"),i=(t.retry_prompt_file?await y.readFile(h.join(e.runDir,t.retry_prompt_file),"utf-8").catch(()=>{}):void 0)??r,{mediaUrl:o,inputImages:c}=await Bt({runDir:e.runDir,job:t,prompt:i,generateImage:e.generateImage,inspectImage:e.inspectImage,candidates:e.candidates,usage:e.usage,upload:e.upload,baseDataUrl:e.baseDataUrl}),a=e.productionJobs.find(s=>s.id===`row-${t.id}`);a&&(a.prompt=i,a.outputUrl=o,a.inputImages=c)}async function Rn(e,t){return t.id!=="running-right"?t.id:!e.inspectImage&&await _n(h.join(e.decodedDir,"running-left.png"))?(await Ht(e.runDir),"running-right,running-left"):"running-right"}async function kn(e,t){await H("extract_strip_frames.py",["--decoded-dir",e.decodedDir,"--output-dir",e.framesDir,"--states",t,"--chroma-key",e.chromaHex,"--key-threshold",Ot,"--method",$t])}async function _n(e){return y.access(e).then(()=>!0,()=>!1)}async function Gt(e,t,r,n,i){await H("compose_atlas.py",["--frames-root",t,"--output",r,"--webp-output",n]),await H("validate_atlas.py",[r,"--json-out",h.join(e,"qa","validation.json")]),await Ce("make_contact_sheet.py",[r,"--output",i])}var Tn=4,Cn="one single centered full-body desktop pet pose on a flat chroma-key background",Un=120,Ln={idle:"a calm resting pose, breathing, standing still","running-right":"a mid-stride running pose facing and moving to the right","running-left":"a mid-stride running pose facing and moving to the left",waving:"raising a paw/hand/limb in a friendly wave",jumping:"a mid-air playful jump",failed:"a sad, deflated, slumped reaction pose",waiting:"an expectant waiting pose, looking up for input",running:"a focused working/thinking pose, busy but not foot-running",review:"a focused inspecting pose, leaning in to review"},Mn=400,On=45;async function $n(e){let t=0;for(let r of e.generatedRows){let n=Jt[r.id]??6,i=[];for(let s=0;s<n;s++)i.push(await Nn(h.join(e.framesDir,r.id,`${String(s).padStart(2,"0")}.png`)));let o=Ct(i.map(s=>s.count).filter(s=>s>0)),c=Ct(i.map(s=>s.lum).filter(s=>s>0)),a=0;for(let s=0;s<n&&a<Tn;s++){let l=i[s],u=l.count<Math.max(Mn,o*.4),d=l.lum<On||c>0&&l.lum<c*.6;if(!u&&!d)continue;let p=await Hn(e,r,s,n);p&&(await Bn(await G(p),h.join(e.framesDir,r.id,`${String(s).padStart(2,"0")}.png`)),a++,t++)}}t>0&&await Gt(e.runDir,e.framesDir,e.atlasPng,e.atlasWebp,e.contactSheet)}async function Nn(e){try{let t=await _e(await y.readFile(e)),r=Math.max(1,t.width),n=Math.max(1,t.height),o=le(r,n).getContext("2d");o.drawImage(t,0,0);let c=o.getImageData(0,0,r,n).data,a=0,s=0;for(let l=0;l<c.length;l+=4)(c[l+3]??0)>40&&(a++,s+=.299*(c[l]??0)+.587*(c[l+1]??0)+.114*(c[l+2]??0));return{count:a,lum:a?s/a:0}}catch(t){return console.error(`[petdex-forge] frame analysis failed for ${e}: ${t instanceof Error?t.message:String(t)}; treating frame as ok (repair skipped)`),{count:Number.MAX_SAFE_INTEGER,lum:255}}}function Ct(e){if(e.length===0)return 0;let t=[...e].sort((n,i)=>n-i),r=Math.floor(t.length/2);return t.length%2?t[r]:(t[r-1]+t[r])/2}function Fn(e){return[`Image 1 is ONE animation frame of a desktop pet's "${e}" pose. Image 2 is the canonical reference of the SAME pet.`,"Reply PASS only if image 1 shows ONE complete pet that clearly matches the reference \u2014 same species, colors, palette, BRIGHTNESS, proportions, markings; centered and fully visible.","Reply FAIL if it is a dark or black silhouette, off-colour, dimmer/brighter than the reference, cut off, empty, a fragment, or shows two pets.",'Reply with exactly "PASS" or "FAIL: <one short reason>".'].join(" ")}async function Hn(e,t,r,n){let i=[`Create ONE single image of a desktop pet in the "${t.id}" animation, pose ${r+1} of ${n}.`,"Output exactly ONE complete, centered, full-body pose of the SAME pet as the attached reference image \u2014 identical species, colors, palette, brightness, proportions, and markings.","This is a single sprite frame: NOT a strip, NOT a grid, NOT multiple poses, NOT a dark silhouette.",`Pose: ${Ln[t.id]??"a clear pose for this state"}.`].join(" "),o=null;for(let c=0;c<e.candidates;c++){let a=await e.generateImage({prompt:`${i}
|
|
18
18
|
|
|
19
|
-
${Nt}`,purpose:"petdex-reference",style:
|
|
19
|
+
${Nt}`,purpose:"petdex-reference",style:Cn,size:ye,imageUrl:e.baseDataUrl,referenceImages:[{role:"canonical-reference",imageUrl:e.baseDataUrl}],n:1,quality:"auto"});xe(e.usage,a);let s=a.mediaUrls[0];if(s){if(o=s,!e.inspectImage)return s;try{if((await je(()=>e.inspectImage({prompt:Fn(t.id),imageUrls:[s,e.baseDataUrl]}),{label:"frame QA",target:`${t.id} frame ${r+1}`})).ok)return s}catch(l){return console.error(`[petdex-forge] frame QA call failed for ${t.id} frame ${r+1}: ${l instanceof Error?l.message:String(l)}; accepting candidate unverified`),s}}}return o}async function Bn(e,t){let r=await _e(e),n=Math.max(1,r.width),i=Math.max(1,r.height),o=le(n,i),c=o.getContext("2d");c.drawImage(r,0,0);let a=c.getImageData(0,0,n,i),s=a.data,[l,u,d]=Jn(s,n,i);for(let P=0;P<s.length;P+=4){let A=(s[P]??0)-l,v=(s[P+1]??0)-u,D=(s[P+2]??0)-d;Math.sqrt(A*A+v*v+D*D)<=Un&&(s[P]=0,s[P+1]=0,s[P+2]=0,s[P+3]=0)}c.putImageData(a,0,0);let p=n,f=i,w=-1,g=-1;for(let P=0;P<i;P++)for(let A=0;A<n;A++)(s[(P*n+A)*4+3]??0)>16&&(A<p&&(p=A),A>w&&(w=A),P<f&&(f=P),P>g&&(g=P));let j=le(m.cellWidth,m.cellHeight),E=j.getContext("2d");if(w>=p&&g>=f){let P=w-p+1,A=g-f+1,v=m.cellWidth-10,D=m.cellHeight-10,L=Math.min(v/P,D/A,1),R=P*L,x=A*L;E.imageSmoothingEnabled=!0,E.imageSmoothingQuality="high",E.drawImage(o,p,f,P,A,(m.cellWidth-R)/2,(m.cellHeight-x)/2,R,x)}await y.mkdir(h.dirname(t),{recursive:!0}),await y.writeFile(t,Buffer.from(j.toBuffer("image/png")))}function Jn(e,t,r){let n=Math.max(4,Math.floor(Math.min(t,r)*.02)),i=Math.max(1,Math.floor(t/200)),o=new Map,c=(s,l)=>{let u=(l*t+s)*4,d=e[u]??0,p=e[u+1]??0,f=e[u+2]??0;if(d+p+f<24)return;let w=d>>4<<8|p>>4<<4|f>>4,g=o.get(w)??{n:0,r:0,g:0,b:0};g.n++,g.r+=d,g.g+=p,g.b+=f,o.set(w,g)};for(let s=n;s<t-n;s+=i)c(s,n),c(s,r-1-n);for(let s=n;s<r-n;s+=i)c(n,s),c(t-1-n,s);let a=null;for(let s of o.values())(!a||s.n>a.n)&&(a=s);return!a||a.n===0?[255,0,255]:[Math.round(a.r/a.n),Math.round(a.g/a.n),Math.round(a.b/a.n)]}function Gn(e,t){let r=e.rows.find(n=>n.state===t);return r?r.ok===!1:!1}async function Ut(e){return zt(e).catch(t=>(console.error(`[petdex-forge] QA review unreadable at ${e}: ${t instanceof Error?t.message:String(t)}; skipping row repair for this pass`),null))}async function zn(e,t,r){let n=[];for(let i of t.input_images){let o=h.join(e,i.path),c=await y.readFile(o).catch(()=>null);if(!c)continue;let a=await Xn(c,h.basename(o),r);n.push({role:Wn(i.role),imageUrl:a})}return n}function Wn(e){let t=e.toLowerCase();return t.includes("layout guide")?"layout-guide":t.includes("atlas")?"existing-atlas":"canonical-reference"}async function Xn(e,t,r){let n=t.toLowerCase().endsWith(".webp")?"image/webp":"image/png";return r?r({buffer:e,mimeType:n,filename:t}):`data:${n};base64,${e.toString("base64")}`}async function qn(e){let t=[];if(e.referenceImageUrl&&t.push(await G(e.referenceImageUrl)),e.baseSpritesheet&&t.push(e.baseSpritesheet),t.length===0)return[];let r=await y.mkdtemp(h.join(Mt.tmpdir(),"petdex-ref-")),n=[];for(let i=0;i<t.length;i++){let o=h.join(r,`reference-${String(i+1).padStart(2,"0")}.png`);await y.writeFile(o,t[i]),n.push(o)}return n}async function Kn(){let e=process.env.QLOGICAGENT_PETDEX_RUN_DIR?.trim()||Mt.tmpdir();return await y.mkdir(e,{recursive:!0}),y.mkdtemp(h.join(e,"petdex-run-"))}function Vn(){let e=process.env.QLOGICAGENT_PETDEX_KEEP_RUNS?.trim().toLowerCase();return e==="1"||e==="true"}async function Lt(e){e&&await y.rm(e,{recursive:!0,force:!0}).catch(()=>{})}async function zt(e){return JSON.parse(await y.readFile(e,"utf-8"))}async function Qn(e){try{let t=await _e(await y.readFile(e)),r=Math.max(1,t.width),n=Math.max(1,t.height),o=le(r,n).getContext("2d");o.drawImage(t,0,0);let c=o.getImageData(0,0,r,n).data,a=Math.max(8,Math.floor(Math.min(r,n)*.02)),s=Math.max(1,Math.floor(r/240)),l=new Map,u=(g,j)=>{let E=(j*r+g)*4,P=c[E+3]??0,A=c[E]??0,v=c[E+1]??0,D=c[E+2]??0;if(P<200||A+v+D<48)return;let L=A>>4<<8|v>>4<<4|D>>4,R=l.get(L)??{n:0,r:0,g:0,b:0};R.n++,R.r+=A,R.g+=v,R.b+=D,l.set(L,R)};for(let g=a;g<r-a;g+=s)u(g,a),u(g,n-1-a);for(let g=a;g<n-a;g+=s)u(a,g),u(r-1-a,g);let d=null;for(let g of l.values())(!d||g.n>d.n)&&(d=g);if(!d||d.n===0)return ke;let p=Math.round(d.r/d.n),f=Math.round(d.g/d.n),w=Math.round(d.b/d.n);return`#${[p,f,w].map(g=>g.toString(16).padStart(2,"0")).join("")}`.toUpperCase()}catch{return ke}}function Yn(e){return e.replace(/[^a-zA-Z0-9]+/g,"-").replace(/^-+|-+$/g,"").toLowerCase()||"petdex"}async function H(e,t){let r=await De(e,t,{timeoutMs:18e4});if(!r.ok)throw new Error(`Petdex pipeline step ${e} failed (exit ${r.code??"?"}): ${r.stderr.trim()||r.stdout.trim()}`)}async function Ce(e,t){try{let r=await De(e,t,{timeoutMs:18e4});r.ok||console.error(`[petdex-forge] soft pipeline step ${e} failed (exit ${r.code??"?"}): ${(r.stderr.trim()||r.stdout.trim()).slice(0,300)}; continuing without it`)}catch(r){console.error(`[petdex-forge] soft pipeline step ${e} failed: ${r instanceof Error?r.message:String(r)}; continuing without it`)}}async function Wt(e){return Ee(e)}function Xt(e,t){if(!t)throw new Error("Petdex manifest validation requires spritesheet.webp bytes");return _(e,t)}export{z as PetGrowthEngine,T as PetProfileService,te as PetSoulService,yt as catchUpJourney,oe as createPetdexAssetFromSpritesheet,Te as forgePetdexAsset,Ft as forgePetdexAssetPackage,At as listBuiltinPetdexAssetIds,bt as listBuiltinPetdexAssets,Wt as loadPetFile,ft as petReactionEngine,Pe as petdexImageDataUrl,G as readGeneratedPetdexImage,V as toPetdexAssetSummary,Xt as validatePetManifest,ie as writePetdexAssetPackage};
|
|
@@ -1,40 +1,40 @@
|
|
|
1
|
-
import{readFile as F,readdir as oe,unlink as
|
|
1
|
+
import{readFile as F,readdir as oe,unlink as ne,stat as Me,mkdir as Ue}from"node:fs/promises";import{copyFileSync as vt,existsSync as p,readFileSync as se,mkdirSync as ae,renameSync as jt,writeFileSync as Ae}from"node:fs";import{join as g}from"node:path";import{resolve as Ie}from"node:path";import{join as we}from"node:path";import{homedir as fe}from"node:os";import{join as f}from"node:path";import{existsSync as Qe}from"node:fs";import{createHash as le}from"node:crypto";import{resolve as ue}from"node:path";function M(r){return le("sha256").update(ue(r).toLowerCase()).digest("hex").slice(0,16)}var T=".qlogicagent";function y(){return process.env.QLOGICAGENT_HOME||f(fe(),T)}function E(){let r=process.env.QLOGIC_LLMROUTER_USER_ID?.trim();if(r)return r;let e=process.env.QLOGIC_IMPLICIT_OWNER_ID?.trim();if(e)return e;let t=process.env.QLOGIC_DEVICE_ID?.trim();return t?`oc_${t}`:"oc_local"}function ge(r){let e=r.trim();if(!e)throw new Error("ownerUserId is required for profile-scoped storage");return encodeURIComponent(e).replace(/\./g,"%2E")}function b(r=E()){return f(y(),"profiles",ge(r))}function X(r=E()){return f(b(r),"memory")}var de="projectData";function H(){return f(y(),de)}function U(r){if(!r)throw new Error("getProjectDataDirById: projectId is required");return f(H(),r)}function q(){return f(y(),"plugins")}function W(){return f(y(),"skills")}function B(){return f(b(),"settings.json")}function G(){return f(y(),"plugin-cache")}function z(){return f(y(),"mcp.json")}function J(){return f(y(),"marketplace.json")}function k(r){if(!r)throw new Error("getProjectAgentDir: cwd is required (must not fall back to process.cwd())");return f(r,T)}function Q(r){return f(k(r),"plugins")}function K(r){return f(k(r),"settings.json")}function Y(r){return f(k(r),"INSTRUCTIONS.md")}function V(r){return f(k(r),"rules")}import{resolve as et}from"node:path";var me=()=>{},A;function Z(){if(pe(),!A)throw new Error("host project authority negotiated but snapshot is not hydrated");return{activeProjectId:A.activeProjectId,projects:A.projects.map(r=>({...r}))}}function pe(){let r=me();if(!r)throw new Error("gateway project authority is not available");return r}function he(){let r=Z();return{activeProjectId:r.activeProjectId,projects:r.projects.map(e=>({...e}))}}function ee(r){return he().projects.find(e=>e.id===r)??null}function Pe(r){return ee(r)?r:M(r)}function xe(r){return U(Pe(r))}function te(r){return we(xe(r),"sessions")}var C=class{constructor(e={}){this.options=e}options;lastActiveWorkdir=null;getActiveProjectRoot(){return this.options.getActiveProjectRoot?.()??process.cwd()}setActiveWorkdir(e){let t=Ie(e);this.lastActiveWorkdir=t,this.options.setActiveWorkdir?.(t)}getActiveWorkdir(){return this.lastActiveWorkdir??this.getActiveProjectRoot()}resolveProjectDir(e){return this.options.resolveProjectDir?.(e)}resolveActiveOwnerUserId(){return E()}getUserAgentHome(){return y()}getOwnerProfileDir(e){return b(e)}getProfileMemoryDir(e){return X(e)}getUserSettingsPath(){return B()}getUserSkillsDir(){return W()}getUserPluginsDir(){return q()}getUserMcpConfigPath(){return z()}getUserPluginCacheDir(){return G()}getUserMarketplaceConfigPath(){return J()}getProjectAgentDir(e=this.getActiveProjectRoot()){return k(e)}getProjectSettingsPath(e=this.getActiveProjectRoot()){return K(e)}getProjectInstructionsPath(e=this.getActiveProjectRoot()){return Y(e)}getProjectPluginsDir(e=this.getActiveProjectRoot()){return Q(e)}getProjectRulesDir(e=this.getActiveProjectRoot()){return V(e)}getProjectSessionDataRoot(e=this.getActiveProjectRoot()){return te(e)}},ke=new C;function re(){return ke}import{readFile as gt,writeFile as ve,mkdir as je,rename as De,unlink as Ee}from"node:fs/promises";import{dirname as be,join as $e}from"node:path";import{randomUUID as Se}from"node:crypto";async function D(r,e){let t=be(r);await je(t,{recursive:!0});let n=$e(t,`.tmp-${Se()}`);try{await ve(n,e,"utf-8");let o;for(let s=0;s<3;s++)try{await De(n,r);return}catch(i){if(o=i,i.code!=="EPERM")throw i;await new Promise(a=>setTimeout(a,50*(s+1)))}throw o}catch(o){throw await Ee(n).catch(()=>{}),o}}var _e=/[一-鿿]/;function $(r){let e=[],t=r.toLowerCase().match(/[\p{L}\p{N}_]+/gu)??[];for(let n of t){let o="",s=!1,i=()=>{if(o){if(s){o.length===1&&e.push(o);for(let a=0;a+1<o.length;a++)e.push(o.slice(a,a+2))}else e.push(o);o=""}};for(let a of n){let m=_e.test(a);o&&m!==s&&i(),s=m,o+=a}i()}return e}var Ne=["add","replace","remove","create_file","write_file","read_file","delete_file","list_files","search","remember","temporal","feedback"],yt={type:"object",properties:{action:{type:"string",enum:Ne,description:["Operation to perform:","","INDEX.md operations (project-level notes, always visible in system prompt):","- 'add' - Append a note to INDEX.md","- 'replace' - Replace text in INDEX.md (str_replace semantics)","- 'remove' - Remove text from INDEX.md","","Topic file operations (project-level, on-demand, for longer content):","- 'create_file' - Create a new .md topic file","- 'write_file' - Overwrite an existing topic file","- 'read_file' - Read a topic file","- 'delete_file' - Delete a topic file","- 'list_files' - List all memory topic files","","Long-term memory (user-level, persists across projects):","- 'remember' - Submit a fact/preference/lesson to the memory consolidation pipeline","- 'search' - Search long-term memory + local keyword match","- 'temporal' - Query memories by time range ('what happened last week')","","Feedback:","- 'feedback' - Mark memories as useful/irrelevant/outdated/wrong"].join(`
|
|
2
2
|
`)},content:{type:"string",description:["Content for add/replace/create_file/write_file.","For INDEX.md notes: write concise, factual statements.","For topic files: can be longer (up to 8KB), use markdown formatting."].join(`
|
|
3
|
-
`)},old_text:{type:"string",description:"For 'replace'/'remove': the exact text to find in INDEX.md."},new_text:{type:"string",description:"For 'replace': the replacement text."},file:{type:"string",description:"Filename for file operations (e.g. 'project-notes.md', 'lesson-esbuild.md'). Must be kebab-case .md."},query:{type:"string",description:"For 'search'/'temporal': natural language query to find relevant memories."},days:{type:"number",description:"For 'temporal': look back N days from today (default: 7)."},memory_ids:{type:"array",items:{type:"string"},description:"For 'feedback': IDs of memories to give feedback on."},signal:{type:"string",enum:["useful","irrelevant","outdated","wrong"],description:"For 'feedback': the feedback signal to apply."},category:{type:"string",enum:["preference","personal_fact","lesson","pattern","decision","context"],description:"For 'remember': categorize the memory (helps with future recall precision)."}},required:["action"]}
|
|
4
|
-
`),
|
|
5
|
-
`),
|
|
6
|
-
`):null}function
|
|
7
|
-
`);
|
|
8
|
-
`);return
|
|
3
|
+
`)},old_text:{type:"string",description:"For 'replace'/'remove': the exact text to find in INDEX.md."},new_text:{type:"string",description:"For 'replace': the replacement text."},file:{type:"string",description:"Filename for file operations (e.g. 'project-notes.md', 'lesson-esbuild.md'). Must be kebab-case .md."},query:{type:"string",description:"For 'search'/'temporal': natural language query to find relevant memories."},days:{type:"number",description:"For 'temporal': look back N days from today (default: 7)."},memory_ids:{type:"array",items:{type:"string"},description:"For 'feedback': IDs of memories to give feedback on."},signal:{type:"string",enum:["useful","irrelevant","outdated","wrong"],description:"For 'feedback': the feedback signal to apply."},category:{type:"string",enum:["preference","personal_fact","lesson","pattern","decision","context"],description:"For 'remember': categorize the memory (helps with future recall precision)."}},required:["action"]},wt=["Manage persistent memory across sessions. Two distinct systems with clear roles:","","## Project memory (INDEX.md + topic files)","Scope: current project / workspace. Visible every turn.","Use for: architecture decisions, file conventions, build commands, known issues, task logs.","Actions: add, replace, remove, create_file, write_file, read_file, delete_file, list_files.","","## Long-term memory (QMemory)","Scope: user-level, persists across all projects. Searched on demand.","Use for: user preferences, personal facts, recurring lessons, communication style, past insights.","Actions: remember, search, temporal, feedback.","","## When to store (guidelines):","- User explicitly says 'remember this' or 'note that' -> submit a high-priority memory candidate","- User states a preference (style, format, tools, habits) -> remember (long-term)","- Project-specific decision or fact -> add/create_file (project memory)","- A debugging lesson or insight that applies broadly -> remember (long-term)","- DO NOT store: trivial/obvious info, one-off questions, transient state","- DO NOT store: information the user did not share or confirm","","## When to recall:","- Use 'search' when you suspect relevant past context exists for the current task","- Use 'temporal' to find what happened in a specific time period","- Memory is auto-recalled each turn - manual search is for deeper queries"].join(`
|
|
4
|
+
`),Re=[/ignore\s+(previous|all|above|prior)\s+instructions/i,/you\s+are\s+now\s+/i,/do\s+not\s+tell\s+the\s+user/i,/system\s+prompt\s+override/i,/忽略(之前|以上|上面|前面|所有|全部)的?.{0,4}(指令|指示|提示|设定|规则)/,/你现在(是|就是|扮演)/,/不要(告诉|透露给?|让)用户/,/系统提示词?.{0,6}(覆盖|无效|作废|重写)/];function v(r){return!Re.some(e=>e.test(r))}var l=12288,O=200,S=8192,Ce="memory",P="INDEX.md";function Fe(r){return g(re().getProjectAgentDir(r),Ce)}var Oe=/^[a-z0-9][a-z0-9\-_.]*\.md$/i;function _(r){return!(!Oe.test(r)||r===P||r.includes("..")||r.includes("/")||r.includes("\\"))}function Le(r){return r.trim().match(/^([A-Za-z][A-Za-z0-9_-]{2,})\s*:/)?.[1]??null}function Te(r,e){let t=r.split(`
|
|
5
|
+
`),n=[],o=!1;for(let s=0;s<t.length;s++){let i=t[s];if(Xe(i)&&i.includes(e)){for(o=!0;s+1<t.length&&ce(t[s+1]);)s++;continue}n.push(i)}return o?n.join(`
|
|
6
|
+
`):null}function Xe(r){return r.trim()!==""&&!r.startsWith("#")&&!r.startsWith("<!--")&&!ce(r)}function ce(r){return r.startsWith(" ")||r.startsWith(" ")}var N=new Map;async function x(r,e){let t=N.get(r)??Promise.resolve(),n,o=new Promise(i=>{n=i}),s=t.catch(()=>{}).then(()=>o);N.set(r,s),await t.catch(()=>{});try{return await e()}finally{n(),N.get(r)===s&&N.delete(r)}}var L=class{root;constructor(e){this.root=Fe(e)}getRootPath(){return this.root}ensureInitialized(){p(this.root)||ae(this.root,{recursive:!0});let e=g(this.root,P);if(!p(e)){let t=["# Memory Index","","<!-- Agent-managed memory. Lines here are always visible in system prompt.>","<!-- Use memory tool to add notes, or create topic files for longer content.>","","## User Profile","","## Notes",""].join(`
|
|
7
|
+
`);He(e,t)}}getIndexForPrompt(){let e=g(this.root,P);if(!p(e))return"";let t;try{t=se(e,"utf-8")}catch(o){return o?.code!=="ENOENT"&&console.error(`[memdir] INDEX.md read failed \u2014 injected as empty this turn: ${o instanceof Error?o.message:String(o)}`),""}let n=t.split(`
|
|
8
|
+
`);return n.length>O&&(t=n.slice(0,O).join(`
|
|
9
9
|
`)+`
|
|
10
10
|
|
|
11
|
-
<!-- INDEX.md truncated: ${
|
|
11
|
+
<!-- INDEX.md truncated: ${n.length} lines total, showing first ${O}>`),Buffer.byteLength(t,"utf-8")>l&&(t=Buffer.from(t,"utf-8").subarray(0,l).toString("utf-8")+`
|
|
12
12
|
|
|
13
|
-
<!-- INDEX.md truncated at ${l} bytes>`),t}getIndexRaw(){let e=
|
|
14
|
-
`).length;return{chars:t,lines:
|
|
13
|
+
<!-- INDEX.md truncated at ${l} bytes>`),t}getIndexRaw(){let e=g(this.root,P);if(!p(e))return"";try{return se(e,"utf-8")}catch(t){return t?.code!=="ENOENT"&&console.error(`[memdir] INDEX.md read failed \u2014 treated as empty: ${t instanceof Error?t.message:String(t)}`),""}}getIndexUsage(){let e=this.getIndexRaw(),t=Buffer.byteLength(e,"utf-8"),n=e.split(`
|
|
14
|
+
`).length;return{chars:t,lines:n,percent:Math.round(t/l*100)}}async addToIndex(e){return e.trim()?v(e)?x(this.root,async()=>{let t=this.getIndexRaw(),n=t.endsWith(`
|
|
15
15
|
`)?t+e.trim()+`
|
|
16
16
|
`:t+`
|
|
17
17
|
`+e.trim()+`
|
|
18
|
-
`;if(Buffer.byteLength(
|
|
19
|
-
`),
|
|
20
|
-
`,"utf-8"),
|
|
21
|
-
`),"utf-8")>
|
|
22
|
-
`),
|
|
18
|
+
`;if(Buffer.byteLength(n,"utf-8")>l){let s=this.autoCompactIndex(t,e.trim());if(s){await this.writeIndexUnlocked(s);let a=this.getIndexUsage();return{ok:!0,message:`Added to INDEX.md (auto-compacted old entries). [${a.chars}/${l} chars, ${a.percent}%]`,indexUsage:`${a.chars}/${l}`}}return{ok:!1,message:`INDEX.md would exceed limit (${this.getIndexUsage().chars}/${l} bytes) even after compaction. Create a topic file instead.`}}await this.writeIndexUnlocked(n);let o=this.getIndexUsage();return{ok:!0,message:`Added to INDEX.md. [${o.chars}/${l} chars, ${o.percent}%]`,indexUsage:`${o.chars}/${l}`}}):{ok:!1,message:"Content rejected: potential injection detected."}:{ok:!1,message:"Content cannot be empty."}}autoCompactIndex(e,t){let n=e.split(`
|
|
19
|
+
`),o=Buffer.byteLength(t+`
|
|
20
|
+
`,"utf-8"),s=l-o-64;if(s<256)return null;let i=u=>u.startsWith("#")||u.startsWith("<!--")||u.trim()==="",a=u=>u.startsWith(" ")||u.startsWith(" "),m=4,h=[...n],w=0;for(;Buffer.byteLength(h.join(`
|
|
21
|
+
`),"utf-8")>s&&w<n.length;){let u=h.findIndex((j,R)=>R>=m&&!i(j)&&!a(j));if(u===-1)break;let I=1;for(;u+I<h.length&&a(h[u+I]);)I++;h.splice(u,I),w++}let c=h.join(`
|
|
22
|
+
`),d=c.endsWith(`
|
|
23
23
|
`)?c+t+`
|
|
24
24
|
`:c+`
|
|
25
25
|
`+t+`
|
|
26
|
-
`;return Buffer.byteLength(
|
|
26
|
+
`;return Buffer.byteLength(d,"utf-8")<=l?d:null}async replaceInIndex(e,t){return e.trim()?t.trim()?v(t)?x(this.root,async()=>{let n=this.getIndexRaw(),o=n.split(e).length-1;if(o===0)return{ok:!1,message:`No match found for: "${e.slice(0,80)}"`};if(o>1)return{ok:!1,message:`Multiple matches (${o}) for: "${e.slice(0,80)}". Be more specific.`};let s=n.replace(e,t);if(Buffer.byteLength(s,"utf-8")>l)return{ok:!1,message:`Replacement would exceed INDEX.md limit (${Buffer.byteLength(s,"utf-8")}/${l} bytes).`};await this.writeIndexUnlocked(s);let i=this.getIndexUsage();return{ok:!0,message:`Replaced in INDEX.md. [${i.chars}/${l} chars]`,indexUsage:`${i.chars}/${l}`}}):{ok:!1,message:"Content rejected: potential injection detected."}:{ok:!1,message:"new_text cannot be empty. Use 'remove' to delete."}:{ok:!1,message:"old_text cannot be empty."}}async removeFromIndex(e){return e.trim()?x(this.root,async()=>{let t=this.getIndexRaw(),n=Le(e),o=n?Te(t,n):null;if(o===null){if(!t.includes(e))return{ok:!1,message:`No match found for: "${e.slice(0,80)}"`};o=t.replace(e,"")}o=o.replace(/\n{3,}/g,`
|
|
27
27
|
|
|
28
|
-
`),await this.writeIndexUnlocked(
|
|
29
|
-
`).find(m=>m.trim()&&!m.startsWith("#"))?.trim();t.push({name:
|
|
28
|
+
`),await this.writeIndexUnlocked(o);let s=this.getIndexUsage();return{ok:!0,message:`Removed from INDEX.md. [${s.chars}/${l} chars]`,indexUsage:`${s.chars}/${l}`}}):{ok:!1,message:"old_text cannot be empty."}}async listFiles(){if(!p(this.root))return[];let e=await oe(this.root),t=[];for(let n of e){if(n===P||!n.endsWith(".md"))continue;let o=g(this.root,n);try{let s=await Me(o);if(!s.isFile())continue;let a=(await F(o,"utf-8")).split(`
|
|
29
|
+
`).find(m=>m.trim()&&!m.startsWith("#"))?.trim();t.push({name:n,size:s.size,modifiedAt:s.mtime.toISOString(),preview:a?.slice(0,100)})}catch{}}return t.sort((n,o)=>o.modifiedAt.localeCompare(n.modifiedAt))}async createFile(e,t){if(!_(e))return{ok:!1,message:`Invalid filename: "${e}". Use kebab-case .md files (e.g. "project-notes.md").`};if(!v(t))return{ok:!1,message:"Content rejected: potential injection detected."};if(t.length>S)return{ok:!1,message:`Content too long (${t.length} chars, max ${S}).`};let n=g(this.root,e);if(p(n))return{ok:!1,message:`File already exists: "${e}". Use write_file to update.`};await this.ensureDir(),await D(n,t);let o=`- [${e}] \u2014 created ${new Date().toISOString().slice(0,10)}`;return{ok:!0,message:await this.appendIndexEntry(o)?`Created "${e}" (${t.length} chars). Entry added to INDEX.md.`:`Created "${e}" (${t.length} chars). WARNING: INDEX.md is full \u2014 the index entry was NOT added, so this file will not surface automatically. Remove stale INDEX.md entries, then add one for [${e}].`,file:e}}async writeFile(e,t){if(!_(e))return{ok:!1,message:`Invalid filename: "${e}". Use kebab-case .md files.`};if(!v(t))return{ok:!1,message:"Content rejected: potential injection detected."};if(t.length>S)return this.writeFileSplit(e,t);let n=g(this.root,e),o=!p(n);await this.ensureDir(),await D(n,t);let s=!0;if(o){let i=`- [${e}] \u2014 created ${new Date().toISOString().slice(0,10)}`;s=await this.appendIndexEntry(i)}return{ok:!0,message:`${o?"Created":"Updated"} "${e}" (${t.length} chars).`+(s?"":" WARNING: INDEX.md is full \u2014 no index entry was added, so this file will not surface automatically."),file:e}}async writeFileSplit(e,t){let n=e.replace(/\.md$/,""),o=t.split(/\n{2,}/),s=[],i="";for(let c of o)i.length+c.length+2>S*.9&&i.length>0?(s.push(i),i=c):i=i?i+`
|
|
30
30
|
|
|
31
|
-
`+c:c;s
|
|
31
|
+
`+c:c;i&&s.push(i);let a=[];for(let c=0;c<s.length;c++){let d=`${n}-${c+1}.md`,u=g(this.root,d);await this.ensureDir(),await D(u,s[c]),a.push(d)}let m=g(this.root,e);p(m)&&(await ne(m),await x(this.root,async()=>{let c=this.getIndexRaw(),d=new RegExp(`^.*\\[${ie(e)}\\].*$\\n?`,"m");d.test(c)&&await this.writeIndexUnlocked(c.replace(d,"").replace(/\n{3,}/g,`
|
|
32
32
|
|
|
33
|
-
`))}));let h=this.getIndexRaw(),
|
|
33
|
+
`))}));let h=this.getIndexRaw(),w=0;for(let c of a)if(!h.includes(`[${c}]`)){let d=`- [${c}] \u2014 auto-split ${new Date().toISOString().slice(0,10)}`;await this.appendIndexEntry(d)||w++}return{ok:!0,message:`Auto-split "${e}" into ${s.length} parts (${t.length} chars total): ${a.join(", ")}`+(w>0?` WARNING: INDEX.md is full \u2014 ${w} part(s) got no index entry and will not surface automatically.`:""),file:a[0]}}async readFile(e){if(!_(e)&&e!==P)return{ok:!1,message:`Invalid filename: "${e}".`};let t=g(this.root,e);try{let n=await F(t,"utf-8");return{ok:!0,content:n,message:`Read "${e}" (${n.length} chars).`}}catch(n){return n.code==="ENOENT"?{ok:!1,message:`File not found: "${e}".`}:{ok:!1,message:`Error reading "${e}": ${n.message}`}}}async deleteFile(e){if(e===P)return{ok:!1,message:"Cannot delete INDEX.md. Use 'remove' to clear entries."};if(!_(e))return{ok:!1,message:`Invalid filename: "${e}".`};let t=g(this.root,e);return p(t)?(await ne(t),await x(this.root,async()=>{let n=this.getIndexRaw(),o=new RegExp(`^.*\\[${ie(e)}\\].*$\\n?`,"m");if(o.test(n)){let s=n.replace(o,"").replace(/\n{3,}/g,`
|
|
34
34
|
|
|
35
|
-
`);await this.writeIndexUnlocked(
|
|
36
|
-
`),c="",
|
|
35
|
+
`);await this.writeIndexUnlocked(s)}}),{ok:!0,message:`Deleted "${e}" and removed INDEX.md entry.`,file:e}):{ok:!1,message:`File not found: "${e}".`}}async searchLocal(e){if(!p(this.root))return[];let t=Array.from(new Set($(e)));if(t.length===0)return[];let n=await oe(this.root),o=[];for(let s of n){if(!s.endsWith(".md"))continue;let i=g(this.root,s);try{let a=await F(i,"utf-8"),m=new Set($(a)),h=t.filter(u=>m.has(u)).length;if(h===0)continue;let w=a.split(`
|
|
36
|
+
`),c="",d=0;for(let u of w){let I=new Set($(u)),j=t.filter(R=>I.has(R)).length;j>d&&(d=j,c=u.trim())}o.push({file:s,snippet:c.slice(0,200),score:h/t.length})}catch{}}return o.sort((s,i)=>i.score-s.score).slice(0,10)}async writeIndex(e){await x(this.root,()=>this.writeIndexUnlocked(e))}async writeIndexUnlocked(e){await this.ensureDir(),await D(g(this.root,P),e)}async ensureDir(){p(this.root)||await Ue(this.root,{recursive:!0})}async appendIndexEntry(e){return x(this.root,async()=>{let t=this.getIndexRaw();if(t.includes(e))return!0;let n=t.endsWith(`
|
|
37
37
|
`)?t+e+`
|
|
38
38
|
`:t+`
|
|
39
39
|
`+e+`
|
|
40
|
-
`;if(Buffer.byteLength(
|
|
40
|
+
`;if(Buffer.byteLength(n,"utf-8")<=l)return await this.writeIndexUnlocked(n),!0;let o=this.autoCompactIndex(t,e);return o?(await this.writeIndexUnlocked(o),!0):(console.error(`[memdir] INDEX.md full \u2014 entry not added (file stays invisible to recall): ${e.slice(0,80)}`),!1)})}};function He(r,e){let t=g(r,"..");p(t)||ae(t,{recursive:!0}),Ae(r,e,"utf-8")}function ie(r){return r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}export{L as Memdir};
|