@things-factory/ai-assistant 10.1.233 → 10.1.241
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/client/components/assistant-chat.ts +11 -3
- package/dist-client/components/assistant-chat.js +11 -4
- package/dist-client/components/assistant-chat.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/service/assistant-chat-resolver.js +1 -1
- package/dist-server/service/assistant-chat-resolver.js.map +1 -1
- package/dist-server/service/chat-message/chat-message.js +3 -3
- package/dist-server/service/chat-message/chat-message.js.map +1 -1
- package/dist-server/service/chat-session/chat-session.js +2 -2
- package/dist-server/service/chat-session/chat-session.js.map +1 -1
- package/dist-server/service/chat-session/session-name.d.ts +8 -0
- package/dist-server/service/chat-session/session-name.js +32 -0
- package/dist-server/service/chat-session/session-name.js.map +1 -0
- package/dist-server/service/chat-session-participant/chat-session-participant.js +1 -1
- package/dist-server/service/chat-session-participant/chat-session-participant.js.map +1 -1
- package/dist-server/service/chat-session-resolver.js +24 -18
- package/dist-server/service/chat-session-resolver.js.map +1 -1
- package/dist-server/service/unattended-run/assistant-run.js +1 -1
- package/dist-server/service/unattended-run/assistant-run.js.map +1 -1
- package/dist-server/service/unattended-run/run-unattended.js +1 -1
- package/dist-server/service/unattended-run/run-unattended.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/server/service/assistant-chat-resolver.ts +1 -1
- package/server/service/chat-message/chat-message.ts +3 -3
- package/server/service/chat-session/chat-session.ts +2 -2
- package/server/service/chat-session/group-room.test.ts +1 -1
- package/server/service/chat-session/session-name.ts +32 -0
- package/server/service/chat-session-participant/chat-session-participant.ts +1 -1
- package/server/service/chat-session-resolver.ts +27 -16
- package/server/service/unattended-run/assistant-run.ts +1 -1
- package/server/service/unattended-run/run-unattended.ts +1 -1
- package/test/refusals-in-korean.test.ts +80 -0
- package/translations/en.json +22 -2
- package/translations/ko.json +22 -2
|
@@ -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: '
|
|
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)
|
|
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"]}
|