@things-factory/ai-assistant 10.1.234 → 10.1.244

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.
Files changed (37) hide show
  1. package/dist-client/tsconfig.tsbuildinfo +1 -1
  2. package/dist-server/service/assistant-mode/mode-categories.js +5 -0
  3. package/dist-server/service/assistant-mode/mode-categories.js.map +1 -1
  4. package/dist-server/service/chat-message/chat-message.js +3 -3
  5. package/dist-server/service/chat-message/chat-message.js.map +1 -1
  6. package/dist-server/service/chat-session/chat-session.js +2 -2
  7. package/dist-server/service/chat-session/chat-session.js.map +1 -1
  8. package/dist-server/service/chat-session-participant/chat-session-participant.js +1 -1
  9. package/dist-server/service/chat-session-participant/chat-session-participant.js.map +1 -1
  10. package/dist-server/service/help-documents/help-keys.d.ts +1 -0
  11. package/dist-server/service/help-documents/help-keys.js +6 -0
  12. package/dist-server/service/help-documents/help-keys.js.map +1 -0
  13. package/dist-server/service/help-documents/help-tools.d.ts +38 -0
  14. package/dist-server/service/help-documents/help-tools.js +85 -0
  15. package/dist-server/service/help-documents/help-tools.js.map +1 -0
  16. package/dist-server/service/index.d.ts +1 -0
  17. package/dist-server/service/index.js +1 -0
  18. package/dist-server/service/index.js.map +1 -1
  19. package/dist-server/service/unattended-run/assistant-run.js +1 -1
  20. package/dist-server/service/unattended-run/assistant-run.js.map +1 -1
  21. package/dist-server/service/unattended-run/run-unattended.js +1 -1
  22. package/dist-server/service/unattended-run/run-unattended.js.map +1 -1
  23. package/dist-server/tsconfig.tsbuildinfo +1 -1
  24. package/package.json +7 -6
  25. package/server/service/assistant-mode/mode-categories.ts +5 -0
  26. package/server/service/assistant-mode/mode-front.test.ts +4 -3
  27. package/server/service/assistant-mode/resolve.test.ts +1 -1
  28. package/server/service/chat-message/chat-message.ts +3 -3
  29. package/server/service/chat-session/chat-session.ts +2 -2
  30. package/server/service/chat-session-participant/chat-session-participant.ts +1 -1
  31. package/server/service/data-entry/data-entry.test.ts +2 -2
  32. package/server/service/help-documents/help-keys.ts +2 -0
  33. package/server/service/help-documents/help-tools.test.ts +40 -0
  34. package/server/service/help-documents/help-tools.ts +86 -0
  35. package/server/service/index.ts +1 -0
  36. package/server/service/unattended-run/assistant-run.ts +1 -1
  37. package/server/service/unattended-run/run-unattended.ts +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yEAAgE;AAChE,6EAAoE;AACpE,4FAAmF;AACnF,yFAAgF;AAChF,iEAAwD;AACxD,sGAA+F;AAC/F,8FAAqF;AACrF,4FAAmF;AACnF,sDAAyE;AACzE,sDAAyE;AACzE,kEAAgG;AAChG,8CAA2C;AAC3C,2CAAwC;AACxC,8CAA2C;AAC3C,sEAAsE;AACtE,0CAAuC;AACvC,iHAAiH;AACjH,6BAA0B;AAC1B,wDAA6E;AAE7E,qDAA0B;AAC1B,qEAA0C;AAC1C,uEAA4C;AAC5C,oGAAoG;AACpG,oEAAyC;AACzC,iEAA2D;AAAlD,0HAAA,iBAAiB,OAAA;AAC1B,6EAAkD;AAClD;;;GAGG;AACH,2DAAgC;AAChC,+GAA+G;AAC/G,uEAA4C;AAC5C,8DAA+F;AAAtF,qHAAA,mBAAmB,OAAA;AAAE,iHAAA,eAAe,OAAA;AAAE,6GAAA,WAAW,OAAA;AAC1D,yHAAyH;AACzH,gEAA0E;AAAjE,iHAAA,cAAc,OAAA;AAAE,8GAAA,WAAW,OAAA;AACpC,uHAAuH;AACvH,qEAA0C;AAC1C,2DAA+I;AAAtI,mHAAA,kBAAkB,OAAA;AAAE,+GAAA,cAAc,OAAA;AAAE,mHAAA,kBAAkB,OAAA;AAAE,iHAAA,gBAAgB,OAAA;AAAE,0GAAA,SAAS,OAAA;AAC5F,mEAAwC;AACxC,4DAAiC;AACjC,mFAAmF;AACnF,0EAA+C;AAC/C,gDAAgD;AAChD,iEAAsC;AACtC,sDAAsD;AACtD,2EAAgD;AAChD,gHAAgH;AAChH,+EAAoD;AACpD,kEAAuC;AACvC,8DAA8D;AAC9D,0EAA+C;AAC/C,8EAAmD;AACnD,0EAA+C;AAC/C,qFAA0D;AAC1D,uFAA4D;AAC5D,wEAA6C;AAC7C,4EAAiD;AACjD,yEAA8C;AAC9C,wDAAwD;AACxD,iFAAsD;AACtD,iFAAsD;AACtD,mFAAwD;AACxD,4FAAiE;AACjE,2DAA2D;AAC3D,uFAA4D;AAC5D,iFAAsD;AACtD,kEAAuC;AACvC,8EAAmD;AACnD,gJAAgJ;AAChJ,0EAA4E;AAAnE,8HAAA,uBAAuB,OAAA;AAChC,8EAA4E;AAAnE,8HAAA,qBAAqB,OAAA;AAC9B,4GAA4G;AAC5G,oEAAyC;AAE5B,QAAA,QAAQ,GAAG,CAAC,GAAG,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,GAAG,mBAA8B,EAAE,GAAG,mBAAqB,CAAC,CAAA;AAExH,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,8CAAmB;QACnB,sDAAsD;QACtD,kDAAqB;QACrB,uDAAuD;QACvD,kDAAqB;QACrB,wDAAwD;QACxD,8DAA2B;QAC3B,mGAAmG;QACnG,sCAAe;QACf,sDAAuB;QACvB,wDAAwD;QACxD,oDAAsB;QACtB,qDAAqD;QACrD,gEAA6B;QAC7B,mDAAmD;QACnD,yCAAqB;KACtB;CACF,CAAA","sourcesContent":["import { ChatSessionResolver } from './chat-session-resolver.js'\nimport { AssistantChatResolver } from './assistant-chat-resolver.js'\nimport { AssistantModeResolver } from './assistant-mode/assistant-mode-resolver.js'\nimport { AssistantCapabilityResolver } from './assistant-capability-resolver.js'\nimport { AiAgentResolver } from './ai-agent-resolver.js'\nimport { MySessionActivitySubscription } from './chat-session/session-activity-subscription.js'\nimport { ChatMessageSubscription } from './chat-message/chat-message-subscription.js'\nimport { ChatTypingSubscription } from './chat-message/chat-typing-subscription.js'\nimport { entities as ChatSessionEntities } from './chat-session/index.js'\nimport { entities as ChatMessageEntities } from './chat-message/index.js'\nimport { entities as ChatSessionParticipantEntities } from './chat-session-participant/index.js'\nimport './chat-session/attachment-tools.js'\nimport './chat-session/session-purge.js'\nimport './chat-session/attachment-route.js'\nimport { EntryProposalResolver } from './data-entry/entry-resolver.js'\nimport './workspace/workspace-tools.js'\n/* Who works here, and the card that brings one of them into a conversation - every conversation carries both. */\nimport './people/index.js'\nimport { entities as UnattendedRunEntities } from './unattended-run/index.js'\n\nexport * from './types.js'\nexport * from './chat-session-resolver.js'\nexport * from './assistant-chat-resolver.js'\n/* The mode registry — each app server declares what its conversations are (ADR-0061 decision 7). */\nexport * from './assistant-mode/index.js'\nexport { requestTranslator } from './request-translator.js'\nexport * from './assistant-capability-resolver.js'\n/*\n * 대화 각본 하네스는 **런타임 export 에서 뺀다**(ADR-0070 A15 결정 ④) — 시험 도구가 서버 번들에\n * 실린다. 시험은 경로로 가져온다: `…/service/testing/conversation-script.js`.\n */\nexport * from './tool-access.js'\n/* Data entry from material - an app registers what it can enter; a mode names it (design/ai/data-entry.md). */\nexport * from './data-entry/entry-target.js'\nexport { registerEntryTarget, entryCategoryOf, runAsCaller } from './data-entry/entry-tools.js'\n/* An application's tool that prepares many changes at once makes the same change card the model's would (2026-10-24). */\nexport { proposeChanges, MAX_CHANGES } from './data-entry/entry-update.js'\n/* Reading an application's lists - an app registers what it lets read; a mode names it (design/ai/read-targets.md). */\nexport * from './data-read/read-target.js'\nexport { registerReadTarget, readCategoryOf, registerDetailRead, detailCategoryOf, runDetail, type DetailRun } from './data-read/read-tools.js'\nexport * from './data-read/list-read.js'\nexport * from './people/index.js'\n/* The AI 작업 패널 - large results on a page of their own (design/ai/workspace.md). */\nexport * from './workspace/workspace-blocks.js'\n/* 무엇이 근거인가 — 도구 결과 밖의 셋(프롬프트 · 대화 · 화면 스냅숏). */\nexport * from './grounding-sources.js'\n/* 앵커 순수 로직 — 호스트가 앵커 종류를 참조한다(리졸버는 데코레이터 때문에 무겁다). */\nexport * from './chat-session/session-anchor.js'\n/* Who may read a conversation — one rule, also asked by doors outside this package (board-ai's revertPatch). */\nexport * from './chat-session/session-visibility.js'\nexport * from './chat-session/index.js'\n/* 순수 로직들 — 호스트(board-ai 등)가 같은 규칙을 쓰라고 공개한다. 베끼면 한쪽만 고쳐진다. */\nexport * from './chat-session/session-inbox.js'\nexport * from './chat-session/attachment-policy.js'\nexport * from './chat-session/session-purge.js'\nexport * from './chat-session/session-activity-publish.js'\nexport * from './chat-session/session-activity-broadcast.js'\nexport * from './chat-message/llm-history.js'\nexport * from './chat-message/history-summary.js'\nexport * from './chat-message/fold-history.js'\n/* 상한 밖으로 밀려난 앞부분을 요약으로 접는 orchestration — 중립 문이 부른다. */\nexport * from './chat-message/fold-session-history.js'\nexport * from './chat-message/chat-message-publish.js'\nexport * from './chat-message/chat-message-broadcast.js'\nexport * from './chat-session-participant/invite-notification.js'\n/* 멘션이 사람을 불러들이는 자리 — 사람의 말을 저장하는 문만 부른다(ADR-0071 결정 1). */\nexport * from './chat-session-participant/mention-invite.js'\nexport * from './chat-session-participant/presence.js'\nexport * from './chat-message/index.js'\nexport * from './chat-session-participant/index.js'\n/* Reading the stored proposals of a conversation and whether one is answered - a package that applies its own card reads them as entry does. */\nexport { PROPOSAL_OUTCOME_PREFIX } from './chat-message/proposal-outcome.js'\nexport { assertMayWriteSession } from './chat-session/session-write-gate.js'\n/* A mode run with no person in it - a scheduled draft (operato-application/design/ai/unattended-run.md). */\nexport * from './unattended-run/index.js'\n\nexport const entities = [...ChatSessionEntities, ...ChatMessageEntities, ...ChatSessionParticipantEntities, ...UnattendedRunEntities]\n\nexport const schema = {\n resolverClasses: [\n ChatSessionResolver,\n /* 문서를 갖지 않은 표면의 대화 — board 를 안 싣는 제품이 물어볼 수 있는 자리. */\n AssistantChatResolver,\n /* 화면이 자기 대화가 무엇을 주는지 묻는 자리 — 문구는 서버가 요청 로케일로 옮겨 낸다. */\n AssistantModeResolver,\n /* 「이 배포에 AI 가 있나 · 무엇이 선언 없이 등록됐나」 — 창구 하나(표준 A7-a). */\n AssistantCapabilityResolver,\n /* A domain's AI agents - the settings card and the dock's picker (design/ai/agent-settings.md). */\n AiAgentResolver,\n ChatMessageSubscription,\n /* 「입력 중」 — 저장하지 않는 방의 한 줄. 듣는 사람은 메시지와 같은 방 판정을 지난다. */\n ChatTypingSubscription,\n /* 내가 참여한 모든 세션의 활동 — 창을 닫아 둔 표면이 배지·목록을 갱신할 수 있게. */\n MySessionActivitySubscription,\n /* 사람이 누른 입력 제안을 쓰는 자리 — 행마다 앱의 코드로, 그 사람의 권한으로. */\n EntryProposalResolver\n ]\n}\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/service/index.ts"],"names":[],"mappings":";;;;AAAA,yEAAgE;AAChE,6EAAoE;AACpE,4FAAmF;AACnF,yFAAgF;AAChF,iEAAwD;AACxD,sGAA+F;AAC/F,8FAAqF;AACrF,4FAAmF;AACnF,sDAAyE;AACzE,sDAAyE;AACzE,kEAAgG;AAChG,8CAA2C;AAC3C,2CAAwC;AACxC,8CAA2C;AAC3C,sEAAsE;AACtE,0CAAuC;AACvC,0CAAuC;AACvC,iHAAiH;AACjH,6BAA0B;AAC1B,wDAA6E;AAE7E,qDAA0B;AAC1B,qEAA0C;AAC1C,uEAA4C;AAC5C,oGAAoG;AACpG,oEAAyC;AACzC,iEAA2D;AAAlD,0HAAA,iBAAiB,OAAA;AAC1B,6EAAkD;AAClD;;;GAGG;AACH,2DAAgC;AAChC,+GAA+G;AAC/G,uEAA4C;AAC5C,8DAA+F;AAAtF,qHAAA,mBAAmB,OAAA;AAAE,iHAAA,eAAe,OAAA;AAAE,6GAAA,WAAW,OAAA;AAC1D,yHAAyH;AACzH,gEAA0E;AAAjE,iHAAA,cAAc,OAAA;AAAE,8GAAA,WAAW,OAAA;AACpC,uHAAuH;AACvH,qEAA0C;AAC1C,2DAA+I;AAAtI,mHAAA,kBAAkB,OAAA;AAAE,+GAAA,cAAc,OAAA;AAAE,mHAAA,kBAAkB,OAAA;AAAE,iHAAA,gBAAgB,OAAA;AAAE,0GAAA,SAAS,OAAA;AAC5F,mEAAwC;AACxC,4DAAiC;AACjC,mFAAmF;AACnF,0EAA+C;AAC/C,gDAAgD;AAChD,iEAAsC;AACtC,sDAAsD;AACtD,2EAAgD;AAChD,gHAAgH;AAChH,+EAAoD;AACpD,kEAAuC;AACvC,8DAA8D;AAC9D,0EAA+C;AAC/C,8EAAmD;AACnD,0EAA+C;AAC/C,qFAA0D;AAC1D,uFAA4D;AAC5D,wEAA6C;AAC7C,4EAAiD;AACjD,yEAA8C;AAC9C,wDAAwD;AACxD,iFAAsD;AACtD,iFAAsD;AACtD,mFAAwD;AACxD,4FAAiE;AACjE,2DAA2D;AAC3D,uFAA4D;AAC5D,iFAAsD;AACtD,kEAAuC;AACvC,8EAAmD;AACnD,gJAAgJ;AAChJ,0EAA4E;AAAnE,8HAAA,uBAAuB,OAAA;AAChC,8EAA4E;AAAnE,8HAAA,qBAAqB,OAAA;AAC9B,4GAA4G;AAC5G,oEAAyC;AAE5B,QAAA,QAAQ,GAAG,CAAC,GAAG,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,GAAG,mBAA8B,EAAE,GAAG,mBAAqB,CAAC,CAAA;AAExH,QAAA,MAAM,GAAG;IACpB,eAAe,EAAE;QACf,8CAAmB;QACnB,sDAAsD;QACtD,kDAAqB;QACrB,uDAAuD;QACvD,kDAAqB;QACrB,wDAAwD;QACxD,8DAA2B;QAC3B,mGAAmG;QACnG,sCAAe;QACf,sDAAuB;QACvB,wDAAwD;QACxD,oDAAsB;QACtB,qDAAqD;QACrD,gEAA6B;QAC7B,mDAAmD;QACnD,yCAAqB;KACtB;CACF,CAAA","sourcesContent":["import { ChatSessionResolver } from './chat-session-resolver.js'\nimport { AssistantChatResolver } from './assistant-chat-resolver.js'\nimport { AssistantModeResolver } from './assistant-mode/assistant-mode-resolver.js'\nimport { AssistantCapabilityResolver } from './assistant-capability-resolver.js'\nimport { AiAgentResolver } from './ai-agent-resolver.js'\nimport { MySessionActivitySubscription } from './chat-session/session-activity-subscription.js'\nimport { ChatMessageSubscription } from './chat-message/chat-message-subscription.js'\nimport { ChatTypingSubscription } from './chat-message/chat-typing-subscription.js'\nimport { entities as ChatSessionEntities } from './chat-session/index.js'\nimport { entities as ChatMessageEntities } from './chat-message/index.js'\nimport { entities as ChatSessionParticipantEntities } from './chat-session-participant/index.js'\nimport './chat-session/attachment-tools.js'\nimport './chat-session/session-purge.js'\nimport './chat-session/attachment-route.js'\nimport { EntryProposalResolver } from './data-entry/entry-resolver.js'\nimport './workspace/workspace-tools.js'\nimport './help-documents/help-tools.js'\n/* Who works here, and the card that brings one of them into a conversation - every conversation carries both. */\nimport './people/index.js'\nimport { entities as UnattendedRunEntities } from './unattended-run/index.js'\n\nexport * from './types.js'\nexport * from './chat-session-resolver.js'\nexport * from './assistant-chat-resolver.js'\n/* The mode registry — each app server declares what its conversations are (ADR-0061 decision 7). */\nexport * from './assistant-mode/index.js'\nexport { requestTranslator } from './request-translator.js'\nexport * from './assistant-capability-resolver.js'\n/*\n * 대화 각본 하네스는 **런타임 export 에서 뺀다**(ADR-0070 A15 결정 ④) — 시험 도구가 서버 번들에\n * 실린다. 시험은 경로로 가져온다: `…/service/testing/conversation-script.js`.\n */\nexport * from './tool-access.js'\n/* Data entry from material - an app registers what it can enter; a mode names it (design/ai/data-entry.md). */\nexport * from './data-entry/entry-target.js'\nexport { registerEntryTarget, entryCategoryOf, runAsCaller } from './data-entry/entry-tools.js'\n/* An application's tool that prepares many changes at once makes the same change card the model's would (2026-10-24). */\nexport { proposeChanges, MAX_CHANGES } from './data-entry/entry-update.js'\n/* Reading an application's lists - an app registers what it lets read; a mode names it (design/ai/read-targets.md). */\nexport * from './data-read/read-target.js'\nexport { registerReadTarget, readCategoryOf, registerDetailRead, detailCategoryOf, runDetail, type DetailRun } from './data-read/read-tools.js'\nexport * from './data-read/list-read.js'\nexport * from './people/index.js'\n/* The AI 작업 패널 - large results on a page of their own (design/ai/workspace.md). */\nexport * from './workspace/workspace-blocks.js'\n/* 무엇이 근거인가 — 도구 결과 밖의 셋(프롬프트 · 대화 · 화면 스냅숏). */\nexport * from './grounding-sources.js'\n/* 앵커 순수 로직 — 호스트가 앵커 종류를 참조한다(리졸버는 데코레이터 때문에 무겁다). */\nexport * from './chat-session/session-anchor.js'\n/* Who may read a conversation — one rule, also asked by doors outside this package (board-ai's revertPatch). */\nexport * from './chat-session/session-visibility.js'\nexport * from './chat-session/index.js'\n/* 순수 로직들 — 호스트(board-ai 등)가 같은 규칙을 쓰라고 공개한다. 베끼면 한쪽만 고쳐진다. */\nexport * from './chat-session/session-inbox.js'\nexport * from './chat-session/attachment-policy.js'\nexport * from './chat-session/session-purge.js'\nexport * from './chat-session/session-activity-publish.js'\nexport * from './chat-session/session-activity-broadcast.js'\nexport * from './chat-message/llm-history.js'\nexport * from './chat-message/history-summary.js'\nexport * from './chat-message/fold-history.js'\n/* 상한 밖으로 밀려난 앞부분을 요약으로 접는 orchestration — 중립 문이 부른다. */\nexport * from './chat-message/fold-session-history.js'\nexport * from './chat-message/chat-message-publish.js'\nexport * from './chat-message/chat-message-broadcast.js'\nexport * from './chat-session-participant/invite-notification.js'\n/* 멘션이 사람을 불러들이는 자리 — 사람의 말을 저장하는 문만 부른다(ADR-0071 결정 1). */\nexport * from './chat-session-participant/mention-invite.js'\nexport * from './chat-session-participant/presence.js'\nexport * from './chat-message/index.js'\nexport * from './chat-session-participant/index.js'\n/* Reading the stored proposals of a conversation and whether one is answered - a package that applies its own card reads them as entry does. */\nexport { PROPOSAL_OUTCOME_PREFIX } from './chat-message/proposal-outcome.js'\nexport { assertMayWriteSession } from './chat-session/session-write-gate.js'\n/* A mode run with no person in it - a scheduled draft (operato-application/design/ai/unattended-run.md). */\nexport * from './unattended-run/index.js'\n\nexport const entities = [...ChatSessionEntities, ...ChatMessageEntities, ...ChatSessionParticipantEntities, ...UnattendedRunEntities]\n\nexport const schema = {\n resolverClasses: [\n ChatSessionResolver,\n /* 문서를 갖지 않은 표면의 대화 — board 를 안 싣는 제품이 물어볼 수 있는 자리. */\n AssistantChatResolver,\n /* 화면이 자기 대화가 무엇을 주는지 묻는 자리 — 문구는 서버가 요청 로케일로 옮겨 낸다. */\n AssistantModeResolver,\n /* 「이 배포에 AI 가 있나 · 무엇이 선언 없이 등록됐나」 — 창구 하나(표준 A7-a). */\n AssistantCapabilityResolver,\n /* A domain's AI agents - the settings card and the dock's picker (design/ai/agent-settings.md). */\n AiAgentResolver,\n ChatMessageSubscription,\n /* 「입력 중」 — 저장하지 않는 방의 한 줄. 듣는 사람은 메시지와 같은 방 판정을 지난다. */\n ChatTypingSubscription,\n /* 내가 참여한 모든 세션의 활동 — 창을 닫아 둔 표면이 배지·목록을 갱신할 수 있게. */\n MySessionActivitySubscription,\n /* 사람이 누른 입력 제안을 쓰는 자리 — 행마다 앱의 코드로, 그 사람의 권한으로. */\n EntryProposalResolver\n ]\n}\n"]}
@@ -176,7 +176,7 @@ tslib_1.__decorate([
176
176
  tslib_1.__metadata("design:paramtypes", [])
177
177
  ], AssistantRun.prototype, "attemptsJson", null);
178
178
  tslib_1.__decorate([
179
- (0, typeorm_1.Column)({ type: 'varchar', length: 1024, nullable: true }),
179
+ (0, typeorm_1.Column)({ type: 'text', nullable: true }),
180
180
  tslib_1.__metadata("design:type", String)
181
181
  ], AssistantRun.prototype, "groundingWarnings", void 0);
182
182
  tslib_1.__decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"assistant-run.js","sourceRoot":"","sources":["../../../server/service/unattended-run/assistant-run.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AssistantRun — one occurrence of a mode run with no person in it, and what it left (design/ai/unattended-run.md).\n *\n * The one place the facts of an AI run are kept: its attempts, its state, the draft, the reads the draft rested on,\n * what it spent and the doors behind it. The application that scheduled it keeps its own facts and points here by\n * (source, subject, scheduledAt) or by id - it does not copy these (chief architect ruling, 2026-10-20).\n */\nimport { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\nimport { Field, ID, Int, ObjectType } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { config } from '@things-factory/env'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nconst LONG_TEXT = {\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'text',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined,\n nullable: true\n} as const\n\nconst parsed = (text?: string | null) => {\n if (!text) return null\n try {\n return JSON.parse(text)\n } catch {\n return null\n }\n}\n\n@Entity()\n/* One occurrence, one row - two first calls at once make one row and the other reads it (§5). */\n@Index('ix_assistant_run_0', (run: AssistantRun) => [run.domain, run.source, run.subject, run.scheduledAt], { unique: true })\n@Index('ix_assistant_run_1', (run: AssistantRun) => [run.domain, run.source, run.subject, run.createdAt])\n@ObjectType({ description: 'One scheduled run of an assistant mode with no person in it, and the draft it left.' })\nexport class AssistantRun {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Run id.' })\n readonly id?: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the run is in.' })\n domain?: Domain\n\n @RelationId((run: AssistantRun) => run.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Readable name of the occurrence - source, subject and time.' })\n name: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Description.' })\n description?: string\n\n @Column({ length: 64 })\n @Field({ description: \"Who scheduled it - '<app>.<work>', e.g. 'office.strategy-review'.\" })\n source: string\n\n @Column({ length: 64 })\n @Field({ description: \"What it is about in the source's terms, e.g. a policy id.\" })\n subject: string\n\n @Column()\n @Field({ description: 'The occurrence this run is.' })\n scheduledAt: Date\n\n @Column({ length: 64 })\n @Field({ description: 'The assistant mode that ran.' })\n modeKind: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'What the mode was about.' })\n modeTarget?: string\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'The person the run acted as - its privileges and doors were theirs.' })\n runAs?: User\n\n @RelationId((run: AssistantRun) => run.runAs)\n runAsId?: string\n\n @Column({ length: 16 })\n @Field({ description: \"'running' | 'succeeded' | 'failed' | 'refused'.\" })\n status: string\n\n @Column({ type: 'int', default: 1 })\n @Field(type => Int, { description: 'Which attempt at this occurrence the row holds, from 1.' })\n attempt: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When this attempt started.' })\n startedAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Past this a running attempt is taken as gone and the next call takes the occurrence over.' })\n deadlineAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When this attempt ended.' })\n finishedAt?: Date\n\n @Column(LONG_TEXT as any)\n @Field({ nullable: true, description: 'The draft - only when the run succeeded.' })\n draft?: string\n\n /** Each call of the run as the audit digests it (`ToolCallRecord`, never raw values), as JSON. */\n @Column(LONG_TEXT as any)\n reads?: string\n\n @Field(() => GraphQLJSON, { nullable: true, description: 'The reads the draft rested on: tool, category, ids, rows, hash, ok or the error code.' })\n get readsJson(): any {\n return parsed(this.reads)\n }\n\n @Column({ type: 'simple-array', nullable: true })\n @Field(() => [String], { nullable: true, description: 'GraphQL doors the reads went through. A reader of the draft must pass all of them.' })\n doors?: string[]\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Why it failed or was refused - a code; the screen says it.' })\n outcomeCode?: string\n\n @Column({ type: 'text', nullable: true })\n outcomeParams?: string\n\n @Field(() => GraphQLJSON, { nullable: true, description: 'Values of the outcome code.' })\n get outcomeParamsJson(): any {\n return parsed(this.outcomeParams)\n }\n\n /** The earlier attempts' endings, `[{ attempt, status, outcomeCode, startedAt, finishedAt }]`, as JSON. */\n @Column({ type: 'text', nullable: true })\n attempts?: string\n\n @Field(() => GraphQLJSON, { nullable: true, description: 'How the earlier attempts ended.' })\n get attemptsJson(): any {\n return parsed(this.attempts)\n }\n\n @Column({ type: 'varchar', length: 1024, nullable: true })\n groundingWarnings?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The AI agent that answered.' })\n agentId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'provider:model.' })\n clientId?: string\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Model requests of this attempt.' })\n modelCalls: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Input tokens of this attempt.' })\n inputTokens: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Output tokens of this attempt.' })\n outputTokens: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Cards a read offered that were not kept - there was no person to press them.' })\n cardsDropped: number\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Creator.' })\n creator?: User\n\n @RelationId((run: AssistantRun) => run.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Last updater.' })\n updater?: User\n\n @RelationId((run: AssistantRun) => run.updater)\n updaterId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n}\n"]}
1
+ {"version":3,"file":"assistant-run.js","sourceRoot":"","sources":["../../../server/service/unattended-run/assistant-run.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * AssistantRun — one occurrence of a mode run with no person in it, and what it left (design/ai/unattended-run.md).\n *\n * The one place the facts of an AI run are kept: its attempts, its state, the draft, the reads the draft rested on,\n * what it spent and the doors behind it. The application that scheduled it keeps its own facts and points here by\n * (source, subject, scheduledAt) or by id - it does not copy these (chief architect ruling, 2026-10-20).\n */\nimport { Column, CreateDateColumn, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId, UpdateDateColumn } from 'typeorm'\nimport { Field, ID, Int, ObjectType } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport { Domain } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { config } from '@things-factory/env'\n\nconst ORMCONFIG = config.get('ormconfig', {})\nconst DATABASE_TYPE = ORMCONFIG.type\n\nconst LONG_TEXT = {\n type:\n DATABASE_TYPE == 'mysql' || DATABASE_TYPE == 'mariadb'\n ? 'longtext'\n : DATABASE_TYPE == 'oracle'\n ? 'clob'\n : DATABASE_TYPE == 'mssql'\n ? 'nvarchar'\n : 'text',\n length: DATABASE_TYPE == 'mssql' ? 'MAX' : undefined,\n nullable: true\n} as const\n\nconst parsed = (text?: string | null) => {\n if (!text) return null\n try {\n return JSON.parse(text)\n } catch {\n return null\n }\n}\n\n@Entity()\n/* One occurrence, one row - two first calls at once make one row and the other reads it (§5). */\n@Index('ix_assistant_run_0', (run: AssistantRun) => [run.domain, run.source, run.subject, run.scheduledAt], { unique: true })\n@Index('ix_assistant_run_1', (run: AssistantRun) => [run.domain, run.source, run.subject, run.createdAt])\n@ObjectType({ description: 'One scheduled run of an assistant mode with no person in it, and the draft it left.' })\nexport class AssistantRun {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Run id.' })\n readonly id?: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the run is in.' })\n domain?: Domain\n\n @RelationId((run: AssistantRun) => run.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'Readable name of the occurrence - source, subject and time.' })\n name: string\n\n @Column({ type: 'text', nullable: true })\n @Field({ nullable: true, description: 'Description.' })\n description?: string\n\n @Column({ length: 64 })\n @Field({ description: \"Who scheduled it - '<app>.<work>', e.g. 'office.strategy-review'.\" })\n source: string\n\n @Column({ length: 64 })\n @Field({ description: \"What it is about in the source's terms, e.g. a policy id.\" })\n subject: string\n\n @Column()\n @Field({ description: 'The occurrence this run is.' })\n scheduledAt: Date\n\n @Column({ length: 64 })\n @Field({ description: 'The assistant mode that ran.' })\n modeKind: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'What the mode was about.' })\n modeTarget?: string\n\n @ManyToOne(type => User)\n @Field(type => User, { nullable: true, description: 'The person the run acted as - its privileges and doors were theirs.' })\n runAs?: User\n\n @RelationId((run: AssistantRun) => run.runAs)\n runAsId?: string\n\n @Column({ length: 16 })\n @Field({ description: \"'running' | 'succeeded' | 'failed' | 'refused'.\" })\n status: string\n\n @Column({ type: 'int', default: 1 })\n @Field(type => Int, { description: 'Which attempt at this occurrence the row holds, from 1.' })\n attempt: number\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When this attempt started.' })\n startedAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Past this a running attempt is taken as gone and the next call takes the occurrence over.' })\n deadlineAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When this attempt ended.' })\n finishedAt?: Date\n\n @Column(LONG_TEXT as any)\n @Field({ nullable: true, description: 'The draft - only when the run succeeded.' })\n draft?: string\n\n /** Each call of the run as the audit digests it (`ToolCallRecord`, never raw values), as JSON. */\n @Column(LONG_TEXT as any)\n reads?: string\n\n @Field(() => GraphQLJSON, { nullable: true, description: 'The reads the draft rested on: tool, category, ids, rows, hash, ok or the error code.' })\n get readsJson(): any {\n return parsed(this.reads)\n }\n\n @Column({ type: 'simple-array', nullable: true })\n @Field(() => [String], { nullable: true, description: 'GraphQL doors the reads went through. A reader of the draft must pass all of them.' })\n doors?: string[]\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Why it failed or was refused - a code; the screen says it.' })\n outcomeCode?: string\n\n @Column({ type: 'text', nullable: true })\n outcomeParams?: string\n\n @Field(() => GraphQLJSON, { nullable: true, description: 'Values of the outcome code.' })\n get outcomeParamsJson(): any {\n return parsed(this.outcomeParams)\n }\n\n /** The earlier attempts' endings, `[{ attempt, status, outcomeCode, startedAt, finishedAt }]`, as JSON. */\n @Column({ type: 'text', nullable: true })\n attempts?: string\n\n @Field(() => GraphQLJSON, { nullable: true, description: 'How the earlier attempts ended.' })\n get attemptsJson(): any {\n return parsed(this.attempts)\n }\n\n @Column({ type: 'text', nullable: true })\n groundingWarnings?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The AI agent that answered.' })\n agentId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'provider:model.' })\n clientId?: string\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Model requests of this attempt.' })\n modelCalls: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Input tokens of this attempt.' })\n inputTokens: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Output tokens of this attempt.' })\n outputTokens: number\n\n @Column({ type: 'int', default: 0 })\n @Field(type => Int, { description: 'Cards a read offered that were not kept - there was no person to press them.' })\n cardsDropped: number\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Creator.' })\n creator?: User\n\n @RelationId((run: AssistantRun) => run.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Last updater.' })\n updater?: User\n\n @RelationId((run: AssistantRun) => run.updater)\n updaterId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n}\n"]}
@@ -200,7 +200,7 @@ async function runAssistantUnattended(input, deps = defaultDeps()) {
200
200
  draft: result.baseText,
201
201
  doors,
202
202
  cardsDropped: result.loop.proposals?.length ?? 0,
203
- groundingWarnings: result.groundingWarnings?.length ? JSON.stringify(result.groundingWarnings).slice(0, 1024) : null,
203
+ groundingWarnings: result.groundingWarnings?.length ? JSON.stringify(result.groundingWarnings) : null,
204
204
  ...spent()
205
205
  });
206
206
  }
@@ -1 +1 @@
1
- {"version":3,"file":"run-unattended.js","sourceRoot":"","sources":["../../../server/service/unattended-run/run-unattended.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Run an assistant mode with no person in it, for scheduled work, and keep what it wrote as a draft\n * (operato-application/design/ai/unattended-run.md, ADR-0142 §8.1, user ruling C 2026-10-20).\n *\n * A server function and no GraphQL door: a door would let a person name someone else as `runAs`. The caller is a\n * server's scheduled task - Office's periodic strategy review is the first.\n *\n * identity (domain, source, subject, scheduledAt) is one row - a retry hands the stored run back (§5)\n * who the run-as user, judged again now; refused when they cannot ask the assistant themselves (§2)\n * tools the mode's read tools behind that user's own doors; no 입력안, no cards kept (§3)\n * limits the mode's: model requests, tokens, wall time (§4)\n * outcome succeeded with a draft, failed or refused with a code - never an empty success (§7)\n *\n * Every tool call goes through the registry door, so the recorders write it down as they do a turn's (§6).\n */\nimport { aiClientFor, findToolSpec, registryAssistantChat, type AgentClient, type AiClientRequest, type ToolAccessCheck, type ToolCallRecord } from '@things-factory/ai-client-base'\nimport { User, canUserCheckinDomain, checkPermission } from '@things-factory/auth-base'\nimport { getRepository } from '@things-factory/shell'\n\nimport { getAssistantMode } from '../assistant-mode/registry.js'\nimport { unattendedToolCategories } from '../assistant-mode/mode-categories.js'\nimport { doorsForAnswer } from '../chat-message/message-doors.js'\nimport { groundingSourcesFor } from '../grounding-sources.js'\nimport { toolAccessFor } from '../tool-access.js'\nimport { AssistantRun } from './assistant-run.js'\nimport { ABANDON_MARGIN_MS, unattendedLimits } from './limits.js'\nimport { budgetedClient, RunBudgetExceeded } from './run-budget.js'\nimport { judgeRunAs, type RunAsChecks } from './run-as.js'\nimport { typeormRunStore, type RunEnding, type RunStore } from './run-store.js'\nimport { unattendedPrompt } from './unattended-prompt.js'\n\nexport interface UnattendedRunInput {\n /** The domain the run is in, as loaded - its parent and owner decide who can enter it. */\n domain: { id: string; [key: string]: any }\n /** The user the run acts as - the policy owner. Their privileges and doors only. */\n runAs: string\n /** Which occurrence this is. The same three again is the same run. */\n run: {\n /** Who scheduled it - `<app>.<work>`, e.g. `office.strategy-review`. */\n source: string\n /** What it is about in the source's terms - a policy id. */\n subject: string\n scheduledAt: Date\n }\n /** A registered mode that declares `unattended`. */\n mode: { kind: string; target?: string }\n /** What this occurrence is asked to do - the caller server's text, read by the model (English). */\n instruction: string\n /** What the run is about, for the tools. Filled by the caller's server; still never used for authorization. */\n hostContext?: Record<string, any>\n /** The language of the draft - the owner's. Absent: their account's locale. */\n lng?: string\n}\n\n/** What the run reaches outside itself. The defaults are the server's; the tests hand their own. */\nexport interface UnattendedRunDeps {\n store: RunStore\n runAs: RunAsChecks<any, any>\n clientFor: (request: AiClientRequest) => Promise<AgentClient>\n toolAccess: (state: any) => ToolAccessCheck\n now: () => Date\n}\n\nconst KEY = /^[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*$/\n\nfunction invalid(field: string): Error {\n const error: any = new Error(`runAssistantUnattended: '${field}' is missing or not usable`)\n error.code = 'assistant-run-input-invalid'\n error.params = { field }\n return error\n}\n\nfunction checkInput(input: UnattendedRunInput) {\n if (!input?.domain?.id) throw invalid('domain')\n if (!input.runAs) throw invalid('runAs')\n if (!KEY.test(String(input.run?.source ?? '')) || input.run.source.length > 64) throw invalid('run.source')\n if (!String(input.run.subject ?? '').trim() || String(input.run.subject).length > 64) throw invalid('run.subject')\n if (!(input.run.scheduledAt instanceof Date) || !Number.isFinite(input.run.scheduledAt.valueOf())) throw invalid('run.scheduledAt')\n if (!input.mode?.kind) throw invalid('mode.kind')\n if (!String(input.instruction ?? '').trim()) throw invalid('instruction')\n}\n\nfunction defaultDeps(): UnattendedRunDeps {\n return {\n store: typeormRunStore(() => getRepository(AssistantRun)),\n runAs: {\n findUser: id => getRepository(User).findOne({ where: { id } }),\n mayCheckin: (user, domain) => canUserCheckinDomain(user, domain),\n /* No request: no address to refuse from, and no license prohibition - those cover writes this run never makes. */\n permits: (gate, user, domain) => checkPermission(gate as any, user, domain, false, [])\n },\n clientFor: aiClientFor,\n toolAccess: state => toolAccessFor({ state }),\n now: () => new Date()\n }\n}\n\n/** Why the loop stopped, as the run's code. Only a clean end with text is a draft. */\nfunction failureOf(loop: any, baseText: string): { code: string; params?: any } | undefined {\n const abort = loop?.abortReason\n if (abort?.type === 'max_iterations') return { code: 'assistant-run-step-limit', params: { steps: abort.iter } }\n if (abort?.type === 'provider_error') return { code: 'assistant-run-model-error', params: { message: String(abort.message ?? '').slice(0, 500) } }\n if (abort) return { code: 'assistant-run-model-error', params: { stopped: abort.type } }\n if (!baseText.trim()) return { code: 'assistant-run-empty-draft' }\n return undefined\n}\n\nconst TIMED_OUT = Symbol('timed-out')\n\nexport async function runAssistantUnattended(input: UnattendedRunInput, deps: UnattendedRunDeps = defaultDeps()): Promise<AssistantRun> {\n checkInput(input)\n const { domain, run } = input\n const mode = getAssistantMode(input.mode.kind)\n const limits = unattendedLimits(mode?.unattended)\n const startedAt = deps.now()\n /* The account as stored now - read once, and judged after the occurrence is held. */\n const account = await deps.runAs.findUser(input.runAs)\n\n const { claimed, row } = await deps.store.claim(\n { domainId: domain.id, source: run.source, subject: run.subject, scheduledAt: run.scheduledAt },\n {\n name: `${run.source} ${run.subject} ${run.scheduledAt.toISOString()}`,\n modeKind: input.mode.kind,\n modeTarget: input.mode.target,\n runAsId: account?.id,\n startedAt,\n deadlineAt: new Date(startedAt.valueOf() + limits.timeoutMs + ABANDON_MARGIN_MS)\n },\n startedAt\n )\n /* Succeeded, or running elsewhere and still alive - the caller gets that row and the model is not called again. */\n if (!claimed) return row\n\n const held = { id: row.id!, attempt: row.attempt }\n const end = (ending: RunEnding) => deps.store.finish(held, { finishedAt: deps.now(), ...ending })\n const refuse = (code: string, params?: any) => end({ status: 'refused', outcomeCode: code, outcomeParams: params ? JSON.stringify(params) : null } as any)\n const fail = (code: string, params?: any, spent?: RunEnding) =>\n end({ status: 'failed', outcomeCode: code, outcomeParams: params ? JSON.stringify(params) : null, ...spent } as any)\n\n if (!mode) return refuse('unknown-assistant-mode', { kind: input.mode.kind })\n if (!mode.unattended) return refuse('assistant-mode-not-unattended', { kind: mode.kind })\n\n const judged = await judgeRunAs(account, domain, deps.runAs)\n if ('refused' in judged) return refuse(judged.refused, { userId: input.runAs })\n const user = judged.user\n\n let agentClient: AgentClient\n try {\n agentClient = await deps.clientFor({ domain: domain as any, user, modeKind: mode.kind })\n } catch (error: any) {\n /* No AI here, or not the agent asked for - nothing ran. Its own code, as the conversation door says it. */\n if (error?.code) return refuse(String(error.code), error.params)\n return fail('assistant-run-model-error', { message: String(error?.message ?? error).slice(0, 500) })\n }\n\n const { client, spend } = budgetedClient(agentClient, limits)\n const reads: ToolCallRecord[] = []\n let over = false\n const state: any = { domain, user, lng: input.lng ?? user.locale, aiAgentId: agentClient.agent.id }\n const categories = unattendedToolCategories(mode)\n const systemPrompt = unattendedPrompt(mode.systemPrompt, state.lng)\n const messages = [{ role: 'user' as const, content: input.instruction }]\n\n const abort = new AbortController()\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<typeof TIMED_OUT>(resolve => {\n timer = setTimeout(() => {\n abort.abort()\n resolve(TIMED_OUT)\n }, limits.timeoutMs)\n })\n\n const spent = (): RunEnding => ({\n reads: JSON.stringify(reads),\n agentId: agentClient.agent.id,\n clientId: agentClient.id,\n modelCalls: spend.modelCalls,\n inputTokens: spend.inputTokens,\n outputTokens: spend.outputTokens\n })\n\n let result: any\n try {\n result = await Promise.race([\n registryAssistantChat({\n client,\n messages,\n systemPrompt,\n toolCategories: categories,\n /* No screen and no conversation - the mode's own tools in front, the lists opened as the run needs (ADR-0061 decision 9). */\n front: { categories: mode.toolCategories ?? [] },\n mode: { kind: mode.kind, ...(input.mode.target ? { target: input.mode.target } : {}) },\n toolAccess: deps.toolAccess(state),\n hostContext: input.hostContext,\n state,\n temperature: mode.temperature,\n maxTokens: mode.maxTokens,\n requireToolOnFirstTurn: mode.requireToolOnFirstTurn,\n /* Each step is one request. A run that reaches the last step without an answer failed - no wrap-up call (§4). */\n maxIterations: limits.maxModelCalls,\n salvageOnMaxIterations: false,\n signal: abort.signal,\n onToolCall: record => {\n if (!over) reads.push(record)\n },\n run: { id: held.id, source: run.source, subject: run.subject, scheduledAt: run.scheduledAt.toISOString() },\n groundingSources: groundingSourcesFor({ systemPrompt, messages: messages as any, hostContext: input.hostContext })\n }),\n timeout\n ])\n } catch (error: any) {\n over = true\n clearTimeout(timer)\n if (error instanceof RunBudgetExceeded) return fail(error.code, error.params, spent())\n return fail('assistant-run-model-error', { message: String(error?.message ?? error).slice(0, 500) }, spent())\n }\n over = true\n clearTimeout(timer)\n\n if (result === TIMED_OUT) return fail('assistant-run-timeout', { timeoutMs: limits.timeoutMs }, spent())\n /* The loop turns a refused request into a provider error; the budget says which limit it was. */\n if (spend.exceeded) return fail('assistant-run-budget-exceeded', spend.exceeded, spent())\n\n const failure = failureOf(result.loop, result.baseText ?? '')\n if (failure) return fail(failure.code, failure.params, spent())\n\n const doors = doorsForAnswer(\n (result.loop.toolUsages ?? []).map((usage: any) => usage?.name).filter(Boolean),\n name => (findToolSpec(name, categories) as any)?.doors\n )\n return end({\n status: 'succeeded',\n draft: result.baseText,\n doors,\n cardsDropped: result.loop.proposals?.length ?? 0,\n groundingWarnings: result.groundingWarnings?.length ? JSON.stringify(result.groundingWarnings).slice(0, 1024) : null,\n ...spent()\n } as any)\n}\n\n/** The stored run of an occurrence, for the application that scheduled it - read behind that application's own door. */\nexport async function findAssistantRun(identity: { domainId: string; source: string; subject: string; scheduledAt: Date } | { id: string }): Promise<AssistantRun | null> {\n const repository = getRepository(AssistantRun)\n if ('id' in identity) return repository.findOne({ where: { id: identity.id } })\n return repository.findOne({\n where: { domain: { id: identity.domainId }, source: identity.source, subject: identity.subject, scheduledAt: identity.scheduledAt } as any\n })\n}\n"]}
1
+ {"version":3,"file":"run-unattended.js","sourceRoot":"","sources":["../../../server/service/unattended-run/run-unattended.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * Run an assistant mode with no person in it, for scheduled work, and keep what it wrote as a draft\n * (operato-application/design/ai/unattended-run.md, ADR-0142 §8.1, user ruling C 2026-10-20).\n *\n * A server function and no GraphQL door: a door would let a person name someone else as `runAs`. The caller is a\n * server's scheduled task - Office's periodic strategy review is the first.\n *\n * identity (domain, source, subject, scheduledAt) is one row - a retry hands the stored run back (§5)\n * who the run-as user, judged again now; refused when they cannot ask the assistant themselves (§2)\n * tools the mode's read tools behind that user's own doors; no 입력안, no cards kept (§3)\n * limits the mode's: model requests, tokens, wall time (§4)\n * outcome succeeded with a draft, failed or refused with a code - never an empty success (§7)\n *\n * Every tool call goes through the registry door, so the recorders write it down as they do a turn's (§6).\n */\nimport { aiClientFor, findToolSpec, registryAssistantChat, type AgentClient, type AiClientRequest, type ToolAccessCheck, type ToolCallRecord } from '@things-factory/ai-client-base'\nimport { User, canUserCheckinDomain, checkPermission } from '@things-factory/auth-base'\nimport { getRepository } from '@things-factory/shell'\n\nimport { getAssistantMode } from '../assistant-mode/registry.js'\nimport { unattendedToolCategories } from '../assistant-mode/mode-categories.js'\nimport { doorsForAnswer } from '../chat-message/message-doors.js'\nimport { groundingSourcesFor } from '../grounding-sources.js'\nimport { toolAccessFor } from '../tool-access.js'\nimport { AssistantRun } from './assistant-run.js'\nimport { ABANDON_MARGIN_MS, unattendedLimits } from './limits.js'\nimport { budgetedClient, RunBudgetExceeded } from './run-budget.js'\nimport { judgeRunAs, type RunAsChecks } from './run-as.js'\nimport { typeormRunStore, type RunEnding, type RunStore } from './run-store.js'\nimport { unattendedPrompt } from './unattended-prompt.js'\n\nexport interface UnattendedRunInput {\n /** The domain the run is in, as loaded - its parent and owner decide who can enter it. */\n domain: { id: string; [key: string]: any }\n /** The user the run acts as - the policy owner. Their privileges and doors only. */\n runAs: string\n /** Which occurrence this is. The same three again is the same run. */\n run: {\n /** Who scheduled it - `<app>.<work>`, e.g. `office.strategy-review`. */\n source: string\n /** What it is about in the source's terms - a policy id. */\n subject: string\n scheduledAt: Date\n }\n /** A registered mode that declares `unattended`. */\n mode: { kind: string; target?: string }\n /** What this occurrence is asked to do - the caller server's text, read by the model (English). */\n instruction: string\n /** What the run is about, for the tools. Filled by the caller's server; still never used for authorization. */\n hostContext?: Record<string, any>\n /** The language of the draft - the owner's. Absent: their account's locale. */\n lng?: string\n}\n\n/** What the run reaches outside itself. The defaults are the server's; the tests hand their own. */\nexport interface UnattendedRunDeps {\n store: RunStore\n runAs: RunAsChecks<any, any>\n clientFor: (request: AiClientRequest) => Promise<AgentClient>\n toolAccess: (state: any) => ToolAccessCheck\n now: () => Date\n}\n\nconst KEY = /^[a-z][a-z0-9-]*\\.[a-z][a-z0-9-]*$/\n\nfunction invalid(field: string): Error {\n const error: any = new Error(`runAssistantUnattended: '${field}' is missing or not usable`)\n error.code = 'assistant-run-input-invalid'\n error.params = { field }\n return error\n}\n\nfunction checkInput(input: UnattendedRunInput) {\n if (!input?.domain?.id) throw invalid('domain')\n if (!input.runAs) throw invalid('runAs')\n if (!KEY.test(String(input.run?.source ?? '')) || input.run.source.length > 64) throw invalid('run.source')\n if (!String(input.run.subject ?? '').trim() || String(input.run.subject).length > 64) throw invalid('run.subject')\n if (!(input.run.scheduledAt instanceof Date) || !Number.isFinite(input.run.scheduledAt.valueOf())) throw invalid('run.scheduledAt')\n if (!input.mode?.kind) throw invalid('mode.kind')\n if (!String(input.instruction ?? '').trim()) throw invalid('instruction')\n}\n\nfunction defaultDeps(): UnattendedRunDeps {\n return {\n store: typeormRunStore(() => getRepository(AssistantRun)),\n runAs: {\n findUser: id => getRepository(User).findOne({ where: { id } }),\n mayCheckin: (user, domain) => canUserCheckinDomain(user, domain),\n /* No request: no address to refuse from, and no license prohibition - those cover writes this run never makes. */\n permits: (gate, user, domain) => checkPermission(gate as any, user, domain, false, [])\n },\n clientFor: aiClientFor,\n toolAccess: state => toolAccessFor({ state }),\n now: () => new Date()\n }\n}\n\n/** Why the loop stopped, as the run's code. Only a clean end with text is a draft. */\nfunction failureOf(loop: any, baseText: string): { code: string; params?: any } | undefined {\n const abort = loop?.abortReason\n if (abort?.type === 'max_iterations') return { code: 'assistant-run-step-limit', params: { steps: abort.iter } }\n if (abort?.type === 'provider_error') return { code: 'assistant-run-model-error', params: { message: String(abort.message ?? '').slice(0, 500) } }\n if (abort) return { code: 'assistant-run-model-error', params: { stopped: abort.type } }\n if (!baseText.trim()) return { code: 'assistant-run-empty-draft' }\n return undefined\n}\n\nconst TIMED_OUT = Symbol('timed-out')\n\nexport async function runAssistantUnattended(input: UnattendedRunInput, deps: UnattendedRunDeps = defaultDeps()): Promise<AssistantRun> {\n checkInput(input)\n const { domain, run } = input\n const mode = getAssistantMode(input.mode.kind)\n const limits = unattendedLimits(mode?.unattended)\n const startedAt = deps.now()\n /* The account as stored now - read once, and judged after the occurrence is held. */\n const account = await deps.runAs.findUser(input.runAs)\n\n const { claimed, row } = await deps.store.claim(\n { domainId: domain.id, source: run.source, subject: run.subject, scheduledAt: run.scheduledAt },\n {\n name: `${run.source} ${run.subject} ${run.scheduledAt.toISOString()}`,\n modeKind: input.mode.kind,\n modeTarget: input.mode.target,\n runAsId: account?.id,\n startedAt,\n deadlineAt: new Date(startedAt.valueOf() + limits.timeoutMs + ABANDON_MARGIN_MS)\n },\n startedAt\n )\n /* Succeeded, or running elsewhere and still alive - the caller gets that row and the model is not called again. */\n if (!claimed) return row\n\n const held = { id: row.id!, attempt: row.attempt }\n const end = (ending: RunEnding) => deps.store.finish(held, { finishedAt: deps.now(), ...ending })\n const refuse = (code: string, params?: any) => end({ status: 'refused', outcomeCode: code, outcomeParams: params ? JSON.stringify(params) : null } as any)\n const fail = (code: string, params?: any, spent?: RunEnding) =>\n end({ status: 'failed', outcomeCode: code, outcomeParams: params ? JSON.stringify(params) : null, ...spent } as any)\n\n if (!mode) return refuse('unknown-assistant-mode', { kind: input.mode.kind })\n if (!mode.unattended) return refuse('assistant-mode-not-unattended', { kind: mode.kind })\n\n const judged = await judgeRunAs(account, domain, deps.runAs)\n if ('refused' in judged) return refuse(judged.refused, { userId: input.runAs })\n const user = judged.user\n\n let agentClient: AgentClient\n try {\n agentClient = await deps.clientFor({ domain: domain as any, user, modeKind: mode.kind })\n } catch (error: any) {\n /* No AI here, or not the agent asked for - nothing ran. Its own code, as the conversation door says it. */\n if (error?.code) return refuse(String(error.code), error.params)\n return fail('assistant-run-model-error', { message: String(error?.message ?? error).slice(0, 500) })\n }\n\n const { client, spend } = budgetedClient(agentClient, limits)\n const reads: ToolCallRecord[] = []\n let over = false\n const state: any = { domain, user, lng: input.lng ?? user.locale, aiAgentId: agentClient.agent.id }\n const categories = unattendedToolCategories(mode)\n const systemPrompt = unattendedPrompt(mode.systemPrompt, state.lng)\n const messages = [{ role: 'user' as const, content: input.instruction }]\n\n const abort = new AbortController()\n let timer: ReturnType<typeof setTimeout> | undefined\n const timeout = new Promise<typeof TIMED_OUT>(resolve => {\n timer = setTimeout(() => {\n abort.abort()\n resolve(TIMED_OUT)\n }, limits.timeoutMs)\n })\n\n const spent = (): RunEnding => ({\n reads: JSON.stringify(reads),\n agentId: agentClient.agent.id,\n clientId: agentClient.id,\n modelCalls: spend.modelCalls,\n inputTokens: spend.inputTokens,\n outputTokens: spend.outputTokens\n })\n\n let result: any\n try {\n result = await Promise.race([\n registryAssistantChat({\n client,\n messages,\n systemPrompt,\n toolCategories: categories,\n /* No screen and no conversation - the mode's own tools in front, the lists opened as the run needs (ADR-0061 decision 9). */\n front: { categories: mode.toolCategories ?? [] },\n mode: { kind: mode.kind, ...(input.mode.target ? { target: input.mode.target } : {}) },\n toolAccess: deps.toolAccess(state),\n hostContext: input.hostContext,\n state,\n temperature: mode.temperature,\n maxTokens: mode.maxTokens,\n requireToolOnFirstTurn: mode.requireToolOnFirstTurn,\n /* Each step is one request. A run that reaches the last step without an answer failed - no wrap-up call (§4). */\n maxIterations: limits.maxModelCalls,\n salvageOnMaxIterations: false,\n signal: abort.signal,\n onToolCall: record => {\n if (!over) reads.push(record)\n },\n run: { id: held.id, source: run.source, subject: run.subject, scheduledAt: run.scheduledAt.toISOString() },\n groundingSources: groundingSourcesFor({ systemPrompt, messages: messages as any, hostContext: input.hostContext })\n }),\n timeout\n ])\n } catch (error: any) {\n over = true\n clearTimeout(timer)\n if (error instanceof RunBudgetExceeded) return fail(error.code, error.params, spent())\n return fail('assistant-run-model-error', { message: String(error?.message ?? error).slice(0, 500) }, spent())\n }\n over = true\n clearTimeout(timer)\n\n if (result === TIMED_OUT) return fail('assistant-run-timeout', { timeoutMs: limits.timeoutMs }, spent())\n /* The loop turns a refused request into a provider error; the budget says which limit it was. */\n if (spend.exceeded) return fail('assistant-run-budget-exceeded', spend.exceeded, spent())\n\n const failure = failureOf(result.loop, result.baseText ?? '')\n if (failure) return fail(failure.code, failure.params, spent())\n\n const doors = doorsForAnswer(\n (result.loop.toolUsages ?? []).map((usage: any) => usage?.name).filter(Boolean),\n name => (findToolSpec(name, categories) as any)?.doors\n )\n return end({\n status: 'succeeded',\n draft: result.baseText,\n doors,\n cardsDropped: result.loop.proposals?.length ?? 0,\n groundingWarnings: result.groundingWarnings?.length ? JSON.stringify(result.groundingWarnings) : null,\n ...spent()\n } as any)\n}\n\n/** The stored run of an occurrence, for the application that scheduled it - read behind that application's own door. */\nexport async function findAssistantRun(identity: { domainId: string; source: string; subject: string; scheduledAt: Date } | { id: string }): Promise<AssistantRun | null> {\n const repository = getRepository(AssistantRun)\n if ('id' in identity) return repository.findOne({ where: { id: identity.id } })\n return repository.findOne({\n where: { domain: { id: identity.domainId }, source: identity.source, subject: identity.subject, scheduledAt: identity.scheduledAt } as any\n })\n}\n"]}