@prismer/runtime 2.0.6 → 2.0.8
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/CHANGELOG.md +201 -0
- package/built-in-skills/agent-coordination/SKILL.md +235 -0
- package/built-in-skills/agent-meta/SKILL.md +52 -0
- package/built-in-skills/assets/SKILL.md +131 -0
- package/built-in-skills/canvas-design/LICENSE.txt +202 -0
- package/built-in-skills/canvas-design/SKILL.md +156 -0
- package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/built-in-skills/canvas-design/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Italiana-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-Light.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Lora-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/built-in-skills/canvas-design/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/built-in-skills/claim-agent-ownership/SKILL.md +254 -0
- package/built-in-skills/claude-api/LICENSE.txt +202 -0
- package/built-in-skills/claude-api/SKILL.md +324 -0
- package/built-in-skills/claude-api/csharp/claude-api.md +402 -0
- package/built-in-skills/claude-api/curl/examples.md +216 -0
- package/built-in-skills/claude-api/curl/managed-agents.md +336 -0
- package/built-in-skills/claude-api/go/claude-api.md +421 -0
- package/built-in-skills/claude-api/go/managed-agents/README.md +561 -0
- package/built-in-skills/claude-api/java/claude-api.md +432 -0
- package/built-in-skills/claude-api/java/managed-agents/README.md +442 -0
- package/built-in-skills/claude-api/php/claude-api.md +375 -0
- package/built-in-skills/claude-api/php/managed-agents/README.md +435 -0
- package/built-in-skills/claude-api/python/claude-api/README.md +420 -0
- package/built-in-skills/claude-api/python/claude-api/batches.md +185 -0
- package/built-in-skills/claude-api/python/claude-api/files-api.md +165 -0
- package/built-in-skills/claude-api/python/claude-api/streaming.md +162 -0
- package/built-in-skills/claude-api/python/claude-api/tool-use.md +590 -0
- package/built-in-skills/claude-api/python/managed-agents/README.md +332 -0
- package/built-in-skills/claude-api/ruby/claude-api.md +113 -0
- package/built-in-skills/claude-api/ruby/managed-agents/README.md +389 -0
- package/built-in-skills/claude-api/shared/agent-design.md +101 -0
- package/built-in-skills/claude-api/shared/error-codes.md +213 -0
- package/built-in-skills/claude-api/shared/live-sources.md +135 -0
- package/built-in-skills/claude-api/shared/managed-agents-api-reference.md +378 -0
- package/built-in-skills/claude-api/shared/managed-agents-client-patterns.md +209 -0
- package/built-in-skills/claude-api/shared/managed-agents-core.md +238 -0
- package/built-in-skills/claude-api/shared/managed-agents-environments.md +215 -0
- package/built-in-skills/claude-api/shared/managed-agents-events.md +195 -0
- package/built-in-skills/claude-api/shared/managed-agents-memory.md +197 -0
- package/built-in-skills/claude-api/shared/managed-agents-multiagent.md +99 -0
- package/built-in-skills/claude-api/shared/managed-agents-onboarding.md +114 -0
- package/built-in-skills/claude-api/shared/managed-agents-outcomes.md +106 -0
- package/built-in-skills/claude-api/shared/managed-agents-overview.md +68 -0
- package/built-in-skills/claude-api/shared/managed-agents-self-hosted-sandboxes.md +173 -0
- package/built-in-skills/claude-api/shared/managed-agents-tools.md +321 -0
- package/built-in-skills/claude-api/shared/managed-agents-webhooks.md +110 -0
- package/built-in-skills/claude-api/shared/model-migration.md +779 -0
- package/built-in-skills/claude-api/shared/models.md +121 -0
- package/built-in-skills/claude-api/shared/prompt-caching.md +171 -0
- package/built-in-skills/claude-api/shared/tool-use-concepts.md +327 -0
- package/built-in-skills/claude-api/typescript/claude-api/README.md +333 -0
- package/built-in-skills/claude-api/typescript/claude-api/batches.md +106 -0
- package/built-in-skills/claude-api/typescript/claude-api/files-api.md +98 -0
- package/built-in-skills/claude-api/typescript/claude-api/streaming.md +178 -0
- package/built-in-skills/claude-api/typescript/claude-api/tool-use.md +527 -0
- package/built-in-skills/claude-api/typescript/managed-agents/README.md +359 -0
- package/built-in-skills/doc-coauthoring/SKILL.md +375 -0
- package/built-in-skills/frontend-design/LICENSE.txt +177 -0
- package/built-in-skills/frontend-design/SKILL.md +42 -0
- package/built-in-skills/human-approval/SKILL.md +114 -0
- package/built-in-skills/image-generate/SKILL.md +327 -0
- package/built-in-skills/ingest/SKILL.md +105 -0
- package/built-in-skills/internal-comms/LICENSE.txt +202 -0
- package/built-in-skills/internal-comms/SKILL.md +32 -0
- package/built-in-skills/internal-comms/examples/3p-updates.md +47 -0
- package/built-in-skills/internal-comms/examples/company-newsletter.md +65 -0
- package/built-in-skills/internal-comms/examples/faq-answers.md +30 -0
- package/built-in-skills/internal-comms/examples/general-comms.md +16 -0
- package/built-in-skills/liteparse/SKILL.md +156 -0
- package/built-in-skills/mcp-builder/LICENSE.txt +202 -0
- package/built-in-skills/mcp-builder/SKILL.md +236 -0
- package/built-in-skills/mcp-builder/reference/evaluation.md +602 -0
- package/built-in-skills/mcp-builder/reference/mcp_best_practices.md +249 -0
- package/built-in-skills/mcp-builder/reference/node_mcp_server.md +970 -0
- package/built-in-skills/mcp-builder/reference/python_mcp_server.md +719 -0
- package/built-in-skills/mcp-builder/scripts/connections.py +151 -0
- package/built-in-skills/mcp-builder/scripts/evaluation.py +373 -0
- package/built-in-skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/built-in-skills/mcp-builder/scripts/requirements.txt +2 -0
- package/built-in-skills/memory/SKILL.md +106 -0
- package/built-in-skills/memory-curation/SKILL.md +135 -0
- package/built-in-skills/office-artifacts/SKILL.md +198 -0
- package/built-in-skills/prismer-im-collab/SKILL.md +148 -0
- package/built-in-skills/skill-authoring/SKILL.md +124 -0
- package/built-in-skills/skill-authoring/skill.json +74 -0
- package/built-in-skills/skill-creator/LICENSE.txt +202 -0
- package/built-in-skills/skill-creator/SKILL.md +485 -0
- package/built-in-skills/skill-creator/agents/analyzer.md +274 -0
- package/built-in-skills/skill-creator/agents/comparator.md +202 -0
- package/built-in-skills/skill-creator/agents/grader.md +223 -0
- package/built-in-skills/skill-creator/assets/eval_review.html +146 -0
- package/built-in-skills/skill-creator/eval-viewer/generate_review.py +471 -0
- package/built-in-skills/skill-creator/eval-viewer/viewer.html +1325 -0
- package/built-in-skills/skill-creator/references/schemas.md +430 -0
- package/built-in-skills/skill-creator/scripts/__init__.py +0 -0
- package/built-in-skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
- package/built-in-skills/skill-creator/scripts/generate_report.py +326 -0
- package/built-in-skills/skill-creator/scripts/improve_description.py +247 -0
- package/built-in-skills/skill-creator/scripts/package_skill.py +136 -0
- package/built-in-skills/skill-creator/scripts/quick_validate.py +103 -0
- package/built-in-skills/skill-creator/scripts/run_eval.py +310 -0
- package/built-in-skills/skill-creator/scripts/run_loop.py +328 -0
- package/built-in-skills/skill-creator/scripts/utils.py +47 -0
- package/built-in-skills/slack-gif-creator/LICENSE.txt +202 -0
- package/built-in-skills/slack-gif-creator/SKILL.md +271 -0
- package/built-in-skills/slack-gif-creator/core/easing.py +234 -0
- package/built-in-skills/slack-gif-creator/core/frame_composer.py +176 -0
- package/built-in-skills/slack-gif-creator/core/gif_builder.py +269 -0
- package/built-in-skills/slack-gif-creator/core/validators.py +136 -0
- package/built-in-skills/slack-gif-creator/requirements.txt +4 -0
- package/built-in-skills/tasks/SKILL.md +398 -0
- package/built-in-skills/team/SKILL.md +76 -0
- package/built-in-skills/web-artifacts-builder/LICENSE.txt +202 -0
- package/built-in-skills/web-artifacts-builder/SKILL.md +104 -0
- package/built-in-skills/web-artifacts-builder/scripts/bundle-artifact.sh +54 -0
- package/built-in-skills/web-artifacts-builder/scripts/init-artifact.sh +334 -0
- package/built-in-skills/web-artifacts-builder/scripts/shadcn-components.tar.gz +0 -0
- package/built-in-skills/webapp-testing/LICENSE.txt +202 -0
- package/built-in-skills/webapp-testing/SKILL.md +96 -0
- package/built-in-skills/webapp-testing/examples/console_logging.py +35 -0
- package/built-in-skills/webapp-testing/examples/element_discovery.py +40 -0
- package/built-in-skills/webapp-testing/examples/static_html_automation.py +33 -0
- package/built-in-skills/webapp-testing/scripts/with_server.py +106 -0
- package/dist/cli.cjs +10239 -3309
- package/dist/cli.js +10111 -3183
- package/dist/index.cjs +11275 -4344
- package/dist/index.d.cts +932 -43
- package/dist/index.d.ts +932 -43
- package/dist/index.js +13087 -6158
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -4,6 +4,136 @@ import { EventEmitter } from 'node:events';
|
|
|
4
4
|
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Sender / participant role within a conversation. Mirrors
|
|
9
|
+
* `TaskDispatchContextEntry['senderRole']` on the cloud side.
|
|
10
|
+
*/
|
|
11
|
+
type EnvelopeRole = 'human' | 'agent' | 'admin' | 'system';
|
|
12
|
+
/** Active participant of the conversation. */
|
|
13
|
+
interface ParticipantRef {
|
|
14
|
+
imUserId: string;
|
|
15
|
+
username: string;
|
|
16
|
+
displayName: string;
|
|
17
|
+
role: string;
|
|
18
|
+
agentType?: string | null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* One raw L1 message in the `recent` tail. Visibility-filtered per
|
|
22
|
+
* docs/release201/26 §5.1 (lifecycle / system events are stripped cloud-side).
|
|
23
|
+
*/
|
|
24
|
+
interface EnvelopeRecentEntry {
|
|
25
|
+
messageId: string;
|
|
26
|
+
role: EnvelopeRole;
|
|
27
|
+
sender: string;
|
|
28
|
+
content: string;
|
|
29
|
+
createdAt: string;
|
|
30
|
+
/** Asset IDs attached to this message; bytes are never inlined here. */
|
|
31
|
+
assetRefs?: AssetRef[];
|
|
32
|
+
}
|
|
33
|
+
/** Structured salient facts extracted by the L2 producer (all optional). */
|
|
34
|
+
interface EnvelopeSalientFacts {
|
|
35
|
+
topicHeadlines?: string[];
|
|
36
|
+
decisions?: string[];
|
|
37
|
+
openQuestions?: string[];
|
|
38
|
+
entitiesMentioned?: string[];
|
|
39
|
+
userPreferences?: string[];
|
|
40
|
+
agentCommitments?: string[];
|
|
41
|
+
discardedDirections?: string[];
|
|
42
|
+
/** metric-only: count of `task.*` lifecycle events covered by this segment. */
|
|
43
|
+
taskEventCount?: number;
|
|
44
|
+
/** metric-only: count of `awaiting_human_approval` events covered. */
|
|
45
|
+
approvalCount?: number;
|
|
46
|
+
}
|
|
47
|
+
/** A compressed L2 Range segment (Phase 1's only `segmentKind`). */
|
|
48
|
+
interface EnvelopeSegment {
|
|
49
|
+
segmentSeq: number;
|
|
50
|
+
coversFromAt: string;
|
|
51
|
+
coversToAt: string;
|
|
52
|
+
summary: string;
|
|
53
|
+
salientFacts: EnvelopeSalientFacts;
|
|
54
|
+
sourceCount: number;
|
|
55
|
+
tokenCountCl100k: number;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Quote snapshot. Decision C: the ref always points at the raw `messageId`;
|
|
59
|
+
* the snapshot survives source deletion via `sourceDeletedAt`.
|
|
60
|
+
*/
|
|
61
|
+
interface EnvelopeQuote {
|
|
62
|
+
quotedMessageId: string;
|
|
63
|
+
snippet: string;
|
|
64
|
+
quotedSender: string;
|
|
65
|
+
quotedAt: string;
|
|
66
|
+
/** Set when the quoted raw message has since been deleted. */
|
|
67
|
+
sourceDeletedAt?: string;
|
|
68
|
+
/**
|
|
69
|
+
* release201/26 §13.4a P2 — image assets on the quoted (older) message,
|
|
70
|
+
* re-attached by the cloud (with `cdnUrl`) so the adapter can re-inject them
|
|
71
|
+
* as image parts in the current turn. Cross-turn vision is blind on stateful
|
|
72
|
+
* upstreams (Hermes stores prior images as `[screenshot]` placeholders), so
|
|
73
|
+
* a text snippet / url-in-text is not enough — the agent must receive the
|
|
74
|
+
* image input again. Reuses the wire `AssetRef` shape.
|
|
75
|
+
*/
|
|
76
|
+
imageAssetRefs?: AssetRef[];
|
|
77
|
+
}
|
|
78
|
+
/** Resolved identifier (entity name → canonical id). Phase 3 only. */
|
|
79
|
+
interface EnvelopeIdentifier {
|
|
80
|
+
kind: string;
|
|
81
|
+
canonicalId: string;
|
|
82
|
+
displayLabel: string;
|
|
83
|
+
lastSeenAt: string;
|
|
84
|
+
}
|
|
85
|
+
/** Recent task execution trace. Phase 3 only. */
|
|
86
|
+
interface EnvelopeRecentTaskTrace {
|
|
87
|
+
taskId: string;
|
|
88
|
+
toolsUsed: string[];
|
|
89
|
+
outputs: string[];
|
|
90
|
+
decisions: string[];
|
|
91
|
+
}
|
|
92
|
+
/** Per-category token floors (cl100k). */
|
|
93
|
+
interface EnvelopeBudgetFloors {
|
|
94
|
+
recent: number;
|
|
95
|
+
compressedSegments: number;
|
|
96
|
+
quotes: number;
|
|
97
|
+
identifierIndex: number;
|
|
98
|
+
recentTaskTrace: number;
|
|
99
|
+
}
|
|
100
|
+
interface EnvelopeBudget {
|
|
101
|
+
/** Total budget in cl100k tokens (Phase 1 default 8000, §6). */
|
|
102
|
+
totalTokens: number;
|
|
103
|
+
floors: EnvelopeBudgetFloors;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Asset partition (decision D). `inputs` participate in the agent's context
|
|
107
|
+
* (image-as-input / file-as-input); `archives` are described only and do not
|
|
108
|
+
* consume vision tokens.
|
|
109
|
+
*/
|
|
110
|
+
interface EnvelopeAssets {
|
|
111
|
+
inputs: AssetRef[];
|
|
112
|
+
archives: AssetRef[];
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Conversation context envelope — the L3 input contract (cloud → daemon).
|
|
116
|
+
* See docs/release201/26 §5.
|
|
117
|
+
*/
|
|
118
|
+
interface ConversationContextEnvelope {
|
|
119
|
+
envelopeVersion: 1;
|
|
120
|
+
conversationId: string;
|
|
121
|
+
conversationType: 'direct' | 'group';
|
|
122
|
+
participants: ParticipantRef[];
|
|
123
|
+
/** L1 raw tail, oldest first. Visibility-filtered per §5.1. */
|
|
124
|
+
recent: EnvelopeRecentEntry[];
|
|
125
|
+
/** L2 Range segments (Phase 1's only kind). */
|
|
126
|
+
compressedSegments: EnvelopeSegment[];
|
|
127
|
+
/** Quote snapshots; ref always points at the raw messageId (decision C). */
|
|
128
|
+
quotes: EnvelopeQuote[];
|
|
129
|
+
/** Phase 3 only — undefined in Phase 1. */
|
|
130
|
+
identifierIndex?: EnvelopeIdentifier[];
|
|
131
|
+
/** Phase 3 only — undefined in Phase 1. */
|
|
132
|
+
recentTaskTrace?: EnvelopeRecentTaskTrace;
|
|
133
|
+
assets: EnvelopeAssets;
|
|
134
|
+
budget: EnvelopeBudget;
|
|
135
|
+
}
|
|
136
|
+
|
|
7
137
|
type IMAgentStatus = 'online' | 'busy' | 'idle' | 'offline';
|
|
8
138
|
interface HostedAgentDeclaration {
|
|
9
139
|
imUserId: string;
|
|
@@ -53,6 +183,21 @@ interface TaskDispatchContextEntry {
|
|
|
53
183
|
createdAt: string;
|
|
54
184
|
/** Wave-8 W1: assets the human attached to THIS chat message. */
|
|
55
185
|
attachedAssetIds?: string[];
|
|
186
|
+
/**
|
|
187
|
+
* 2026-05-31 release201/30 §XML-context P0 — enriched metadata for the
|
|
188
|
+
* assets attached to this message. Daemon renders each entry as
|
|
189
|
+
* `<asset id mime filename size_bytes/>` inside a `<attached_assets>`
|
|
190
|
+
* child of `<prior_message>` / `<current_message>` so the agent sees
|
|
191
|
+
* prior-turn file attachments (PDF / image / etc.) instead of a blank
|
|
192
|
+
* text body. Optional + forward-compat with older cloud builds (falls
|
|
193
|
+
* back to id-only rendering from `attachedAssetIds`).
|
|
194
|
+
*/
|
|
195
|
+
attachedAssets?: Array<{
|
|
196
|
+
id: string;
|
|
197
|
+
mime?: string;
|
|
198
|
+
filename?: string;
|
|
199
|
+
sizeBytes?: number;
|
|
200
|
+
}>;
|
|
56
201
|
}
|
|
57
202
|
/** Wave-8 W1: hydrated asset reference attached to a dispatch. */
|
|
58
203
|
interface AssetRef {
|
|
@@ -92,6 +237,18 @@ interface ResolvedAssetRef extends AssetRef {
|
|
|
92
237
|
}
|
|
93
238
|
interface TaskDispatchRequestPayload {
|
|
94
239
|
taskId: string;
|
|
240
|
+
/**
|
|
241
|
+
* release202/09 §3.2 — structural run-vs-task signal.
|
|
242
|
+
* - `'run'` → chat-dispatch run (`taskId` mirrors the run id). Daemon
|
|
243
|
+
* injects `PRISMER_RUN_ID` (not `PRISMER_TASK_ID`); the turn closes from
|
|
244
|
+
* the agent's reply — no `cloud task` op needed.
|
|
245
|
+
* - `'task'` → kanban task. Daemon injects `PRISMER_TASK_ID`.
|
|
246
|
+
* Optional + forward-compatible: missing → daemon falls back to id-shape
|
|
247
|
+
* (`run_` prefix) and then legacy probe-both.
|
|
248
|
+
*/
|
|
249
|
+
kind?: 'run' | 'task';
|
|
250
|
+
/** The run id when `kind === 'run'`. */
|
|
251
|
+
runId?: string;
|
|
95
252
|
/** Agent target for runtimeRoute='agent'. Shell dispatches do not use this. */
|
|
96
253
|
agentImUserId?: string;
|
|
97
254
|
/** Runtime/device target for runtimeRoute='shell'. */
|
|
@@ -105,6 +262,15 @@ interface TaskDispatchRequestPayload {
|
|
|
105
262
|
timeoutMs?: number;
|
|
106
263
|
context?: TaskDispatchContextEntry[];
|
|
107
264
|
conversationId?: string;
|
|
265
|
+
/**
|
|
266
|
+
* release201/30 §7 — end-to-end trace id, originated by the frontend
|
|
267
|
+
* (`X-Prismer-Trace-Id`) or generated by the cloud middleware when absent.
|
|
268
|
+
* Daemon prefixes its stderr lines with `[trace=${traceId}]` so an
|
|
269
|
+
* operator can grep one id across frontend → cloud → daemon. Optional and
|
|
270
|
+
* forward-compatible: missing means the wire frame predates the field;
|
|
271
|
+
* dispatch.ts falls back to `daemon-fallback-<rand>`.
|
|
272
|
+
*/
|
|
273
|
+
traceId?: string;
|
|
108
274
|
/**
|
|
109
275
|
* Channel mode for the originating conversation. Optional and
|
|
110
276
|
* forward-compatible: when missing, daemon renders 'unknown' in the
|
|
@@ -130,6 +296,45 @@ interface TaskDispatchRequestPayload {
|
|
|
130
296
|
}>;
|
|
131
297
|
/** Wave-8 W1: assets cloud wants daemon to fold into agent context. */
|
|
132
298
|
assetRefs?: AssetRef[];
|
|
299
|
+
/**
|
|
300
|
+
* release201/09 Phase 2 — task project scope. NULL = workspace-level
|
|
301
|
+
* (`_unscoped` sentinel on disk). Daemon uses this together with
|
|
302
|
+
* `agentImUserId` / `profile.workspaceId` to compose the per-task
|
|
303
|
+
* scratch path: `workspaces/<wid>/projects/<pid|_unscoped>/tasks/<tid>/`.
|
|
304
|
+
* Also forwarded into the spawned agent process as `PRISMER_ACTIVE_PROJECT_ID`
|
|
305
|
+
* (when non-null) so built-in skill --project flag defaults work.
|
|
306
|
+
*/
|
|
307
|
+
projectId?: string | null;
|
|
308
|
+
/**
|
|
309
|
+
* release201/30 — username of the chat sender that triggered this dispatch.
|
|
310
|
+
* Daemon uses this to label the <current_message author="..."> tag inside
|
|
311
|
+
* the XML-wrapped conversation context the sessions-style adapters send.
|
|
312
|
+
*
|
|
313
|
+
* Optional: when missing, daemon falls back to the trigger row's own
|
|
314
|
+
* username (typically the human owner), which is still correct for
|
|
315
|
+
* single-author dispatch flows.
|
|
316
|
+
*/
|
|
317
|
+
triggerSenderUsername?: string;
|
|
318
|
+
/**
|
|
319
|
+
* release201/30 — role of the trigger message sender. Mirrors
|
|
320
|
+
* `TaskDispatchContextEntry.senderRole` vocabulary.
|
|
321
|
+
*/
|
|
322
|
+
triggerSenderRole?: 'human' | 'agent' | 'admin' | 'system';
|
|
323
|
+
/**
|
|
324
|
+
* release201/25 §7 / release201/26 envelope refactor — typed L3 input
|
|
325
|
+
* contract built cloud-side by `ConversationMemoryService.buildEnvelope`.
|
|
326
|
+
*
|
|
327
|
+
* Envelope-aware adapters call `renderContextEnvelope` (per-adapter
|
|
328
|
+
* module under `sdk/.../adapters/<name>/context-render.ts`) to turn this
|
|
329
|
+
* into their native wire shape. Legacy fields above (`context`,
|
|
330
|
+
* `participants`, `triggerSenderUsername`, `triggerSenderRole`) are still
|
|
331
|
+
* populated for one release window so older adapters keep working.
|
|
332
|
+
*
|
|
333
|
+
* Optional + forward-compatible: missing means the cloud build predates
|
|
334
|
+
* the wiring (or the flag is off); adapter falls back to the legacy XML
|
|
335
|
+
* composer / N-message path.
|
|
336
|
+
*/
|
|
337
|
+
contextEnvelope?: ConversationContextEnvelope;
|
|
133
338
|
}
|
|
134
339
|
interface TaskDispatchProgressPayload {
|
|
135
340
|
taskId: string;
|
|
@@ -155,6 +360,21 @@ interface AssetDispatchObservation {
|
|
|
155
360
|
/** L5: end-to-end fetch duration in ms (DNS + connect + body read). */
|
|
156
361
|
durationMs?: number;
|
|
157
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* P1-2 (2026-05-25): per-file artifact rejection record. Surfaced when daemon's
|
|
365
|
+
* `artifacts-watcher` rejects an artifact because its magic bytes don't match
|
|
366
|
+
* the file extension (e.g. agent wrote `report.pdf` with markdown content).
|
|
367
|
+
* Cloud persists these on `IMTask.metadata.outboxRejections` (wire field name
|
|
368
|
+
* kept for the cross-process contract) and prepends a
|
|
369
|
+
* warning section to the next dispatch prompt so the agent can self-correct.
|
|
370
|
+
*/
|
|
371
|
+
interface OutboxRejectionRecord {
|
|
372
|
+
filename: string;
|
|
373
|
+
reason: string;
|
|
374
|
+
inferredMime: string;
|
|
375
|
+
detectedMime: string;
|
|
376
|
+
rejectedAt: string;
|
|
377
|
+
}
|
|
158
378
|
interface TaskDispatchReplyPayload {
|
|
159
379
|
taskId: string;
|
|
160
380
|
ok: boolean;
|
|
@@ -170,6 +390,13 @@ interface TaskDispatchReplyPayload {
|
|
|
170
390
|
};
|
|
171
391
|
/** Wave-8 W1: per-asset handling report. */
|
|
172
392
|
assetObservability?: AssetDispatchObservation[];
|
|
393
|
+
/**
|
|
394
|
+
* P1-2 (2026-05-25): files quarantined locally by artifacts-watcher's
|
|
395
|
+
* magic-bytes check during this turn. Cloud writes them onto
|
|
396
|
+
* `IMTask.metadata.outboxRejections` so the next dispatch prompt can warn
|
|
397
|
+
* the agent.
|
|
398
|
+
*/
|
|
399
|
+
outboxRejections?: OutboxRejectionRecord[];
|
|
173
400
|
}
|
|
174
401
|
interface TaskCancelPayload {
|
|
175
402
|
taskId: string;
|
|
@@ -338,7 +565,7 @@ declare class MemoryStore {
|
|
|
338
565
|
private rowToPage;
|
|
339
566
|
}
|
|
340
567
|
|
|
341
|
-
type MemoryScope = 'workspace-shared' | 'agent-private';
|
|
568
|
+
type MemoryScope = 'workspace-shared' | 'agent-private' | 'session-scratch' | 'role-shared' | 'project-shared' | 'global';
|
|
342
569
|
interface ScopedMemoryStoreOptions {
|
|
343
570
|
/** Filesystem root, e.g. `~/.prismer/memory` (will create per-workspace dir under). */
|
|
344
571
|
rootDir: string;
|
|
@@ -353,12 +580,37 @@ interface ScopedWriteInput extends Omit<MemoryWriteInput, 'workspaceId'> {
|
|
|
353
580
|
scope: MemoryScope;
|
|
354
581
|
/** Required when scope='agent-private'; rejected when scope='workspace-shared'. */
|
|
355
582
|
agentImUserId?: string;
|
|
583
|
+
/**
|
|
584
|
+
* Required when scope='session-scratch' (release201/26 §14.9 #A5) — opaque
|
|
585
|
+
* throwaway key, e.g. `eval-<runId>`. Rejected for the other scopes.
|
|
586
|
+
*/
|
|
587
|
+
sessionKey?: string;
|
|
588
|
+
/**
|
|
589
|
+
* Required when scope='role-shared' (release201/26 §14.6 #A5b) — role
|
|
590
|
+
* template slug; the bucket is shared across all agents of that role.
|
|
591
|
+
* Rejected for the other scopes.
|
|
592
|
+
*/
|
|
593
|
+
roleSlug?: string;
|
|
594
|
+
/**
|
|
595
|
+
* Required when scope='project-shared' (release201/26 §14.6 #A5b) — project
|
|
596
|
+
* identifier; the bucket is scoped to a project. Rejected for other scopes.
|
|
597
|
+
*/
|
|
598
|
+
projectId?: string;
|
|
356
599
|
}
|
|
357
600
|
interface ScopedSearchInput {
|
|
358
601
|
query: string;
|
|
359
602
|
scope: MemoryScope;
|
|
360
603
|
/** Required when scope='agent-private' — search only this agent's bucket. */
|
|
361
604
|
agentImUserId?: string;
|
|
605
|
+
/**
|
|
606
|
+
* Required when scope='session-scratch' — search only this throwaway bucket;
|
|
607
|
+
* never falls through to shared/agent buckets (full isolation, §14.9 #A5).
|
|
608
|
+
*/
|
|
609
|
+
sessionKey?: string;
|
|
610
|
+
/** Required when scope='role-shared' (release201/26 §14.6 #A5b). */
|
|
611
|
+
roleSlug?: string;
|
|
612
|
+
/** Required when scope='project-shared' (release201/26 §14.6 #A5b). */
|
|
613
|
+
projectId?: string;
|
|
362
614
|
options?: MemorySearchOptions;
|
|
363
615
|
}
|
|
364
616
|
/**
|
|
@@ -369,19 +621,67 @@ declare class ScopedMemoryStore {
|
|
|
369
621
|
private readonly opts;
|
|
370
622
|
private sharedStore;
|
|
371
623
|
private agentStores;
|
|
624
|
+
private scratchStores;
|
|
625
|
+
private roleStores;
|
|
626
|
+
private projectStores;
|
|
627
|
+
private globalStore;
|
|
372
628
|
private readonly workspaceDir;
|
|
373
629
|
constructor(opts: ScopedMemoryStoreOptions);
|
|
374
630
|
/** Resolve the shared store (lazy open). */
|
|
375
631
|
shared(): MemoryStore;
|
|
376
632
|
/** Resolve the per-agent store (lazy open). */
|
|
377
633
|
forAgent(agentImUserId: string): MemoryStore;
|
|
378
|
-
/**
|
|
379
|
-
|
|
634
|
+
/**
|
|
635
|
+
* Resolve the per-session scratch store (lazy open). release201/26 §14.9 #A5.
|
|
636
|
+
*
|
|
637
|
+
* The bucket lives under `<workspaceDir>/scratch/<sanitizedSessionKey>.db`.
|
|
638
|
+
* It is fully isolated: nothing in here is ever merged into shared/agent
|
|
639
|
+
* searches, and it is meant to be torn down via `dropScratch` after the run.
|
|
640
|
+
*/
|
|
641
|
+
forScratch(sessionKey: string): MemoryStore;
|
|
642
|
+
/**
|
|
643
|
+
* Resolve the per-role shared store (lazy open). release201/26 §14.6 #A5b.
|
|
644
|
+
* Bucket: `<workspaceDir>/roles/<sanitizedRoleSlug>.db` — shared across all
|
|
645
|
+
* agents instantiated from the same role template.
|
|
646
|
+
*/
|
|
647
|
+
forRole(roleSlug: string): MemoryStore;
|
|
648
|
+
/**
|
|
649
|
+
* Resolve the per-project shared store (lazy open). release201/26 §14.6 #A5b.
|
|
650
|
+
* Bucket: `<workspaceDir>/projects/<sanitizedProjectId>.db`.
|
|
651
|
+
*/
|
|
652
|
+
forProject(projectId: string): MemoryStore;
|
|
653
|
+
/**
|
|
654
|
+
* Resolve the CROSS-workspace global store (lazy open). release201/26 §14.6
|
|
655
|
+
* #A5b. The bucket lives at `<rootDir>/global.db` (one level ABOVE the
|
|
656
|
+
* per-workspace dir) so every ScopedMemoryStore sharing the same rootDir reads
|
|
657
|
+
* and writes the same global.db, regardless of workspaceId. The store is
|
|
658
|
+
* opened with the constant GLOBAL_WORKSPACE_ID so MemoryStore's single-
|
|
659
|
+
* workspace filter does not re-partition global rows per workspace.
|
|
660
|
+
*/
|
|
661
|
+
global(): MemoryStore;
|
|
662
|
+
/** Resolve the right store for (scope, agentImUserId, sessionKey, roleSlug, projectId). */
|
|
663
|
+
resolve(scope: MemoryScope, agentImUserId?: string, sessionKey?: string, roleSlug?: string, projectId?: string): MemoryStore;
|
|
664
|
+
/**
|
|
665
|
+
* Sanitize an opaque key (sessionKey / roleSlug / projectId) for filesystem
|
|
666
|
+
* safety. Rejects empty/blank keys; maps any char outside [A-Za-z0-9_-] to
|
|
667
|
+
* '_' so a key like `eval-../../etc` cannot escape its bucket dir.
|
|
668
|
+
* release201/26 §14.9 #A5 + §14.6 #A5b.
|
|
669
|
+
*/
|
|
670
|
+
private static sanitizeKey;
|
|
671
|
+
/**
|
|
672
|
+
* Sanitize an opaque sessionKey for filesystem safety. Rejects empty/blank
|
|
673
|
+
* keys; maps any char outside [A-Za-z0-9_-] to '_' so a key like
|
|
674
|
+
* `eval-../../etc` cannot escape the scratch dir. release201/26 §14.9 #A5.
|
|
675
|
+
*/
|
|
676
|
+
private static sanitizeSessionKey;
|
|
380
677
|
/** Write a memory page into the correct bucket. */
|
|
381
678
|
write(input: ScopedWriteInput): {
|
|
382
679
|
pageId: string;
|
|
383
680
|
scope: MemoryScope;
|
|
384
681
|
agentImUserId?: string;
|
|
682
|
+
sessionKey?: string;
|
|
683
|
+
roleSlug?: string;
|
|
684
|
+
projectId?: string;
|
|
385
685
|
};
|
|
386
686
|
/**
|
|
387
687
|
* Search only the requested bucket. This is the daemon-first FTS5 path
|
|
@@ -396,6 +696,18 @@ declare class ScopedMemoryStore {
|
|
|
396
696
|
searchForAgent(query: string, agentImUserId: string, options?: MemorySearchOptions): MemorySearchResult[];
|
|
397
697
|
/** List which agent ids currently have a private DB on disk (for diagnostics). */
|
|
398
698
|
listAgentBuckets(): string[];
|
|
699
|
+
/**
|
|
700
|
+
* List which scratch sessionKeys currently have a DB on disk. For
|
|
701
|
+
* housekeeping — e.g. dropping orphaned scratch buckets from crashed eval
|
|
702
|
+
* runs. release201/26 §14.9 #A5.
|
|
703
|
+
*/
|
|
704
|
+
listScratchKeys(): string[];
|
|
705
|
+
/**
|
|
706
|
+
* Close + delete a scratch bucket's db file(s) (incl. -wal / -shm sidecars).
|
|
707
|
+
* Called after an eval/throwaway run to clean up. Idempotent: a missing
|
|
708
|
+
* bucket is a no-op. release201/26 §14.9 #A5.
|
|
709
|
+
*/
|
|
710
|
+
dropScratch(sessionKey: string): void;
|
|
399
711
|
/** Total disk footprint (best-effort; sums each bucket's main DB file). */
|
|
400
712
|
diskBytes(): {
|
|
401
713
|
shared: number;
|
|
@@ -485,7 +797,23 @@ interface StepRecorderHandle {
|
|
|
485
797
|
}
|
|
486
798
|
interface TaskInput {
|
|
487
799
|
taskId: string;
|
|
800
|
+
/**
|
|
801
|
+
* release202/09 §3.2 — whether this dispatch is a chat-dispatch RUN or a
|
|
802
|
+
* kanban TASK. Threaded from `TaskDispatchRequestPayload.kind`. When 'run',
|
|
803
|
+
* `runId` carries the run id and `taskId` mirrors it (back-compat); adapters
|
|
804
|
+
* surface `<run_id>` (not `<task_id>`) in execution_context. Optional —
|
|
805
|
+
* adapters that don't read it fall back to the id shape (`run_` prefix).
|
|
806
|
+
*/
|
|
807
|
+
kind?: 'run' | 'task';
|
|
808
|
+
/** The run id when `kind === 'run'` (release202/09 §3.2). */
|
|
809
|
+
runId?: string;
|
|
488
810
|
prompt: string;
|
|
811
|
+
/**
|
|
812
|
+
* Adapter-private input metadata. release202/05 C2 — `metadata.conversationId`
|
|
813
|
+
* + `metadata.agentImUserId` are already populated on dispatch and are the
|
|
814
|
+
* keys ProviderSessionMapper.get()/put() use to scope a provider session to
|
|
815
|
+
* one (conversation × agent × adapter) triple.
|
|
816
|
+
*/
|
|
489
817
|
metadata?: Record<string, unknown>;
|
|
490
818
|
timeoutMs?: number;
|
|
491
819
|
onProgress?: (p: {
|
|
@@ -547,6 +875,110 @@ interface TaskInput {
|
|
|
547
875
|
* → passes here). Adapters never instantiate the store themselves.
|
|
548
876
|
*/
|
|
549
877
|
memoryStore?: ScopedMemoryStore;
|
|
878
|
+
/**
|
|
879
|
+
* Raw structured conversation history. Adapters that natively understand
|
|
880
|
+
* role-tagged messages (Hermes /v1/runs, OpenAI Responses) should consume
|
|
881
|
+
* this instead of parsing `prompt`. Adapters that don't (claude-code,
|
|
882
|
+
* codex CLI) can ignore it — dispatch.ts still concats into `prompt` as
|
|
883
|
+
* a fallback. 2026-05-29 — added to fix Hermes context-dropout where
|
|
884
|
+
* dispatch concatenated history into a single user-input string and
|
|
885
|
+
* Hermes treated it as one new turn (api_server.py:3537-3590).
|
|
886
|
+
*/
|
|
887
|
+
contextEntries?: Array<{
|
|
888
|
+
role: 'user' | 'assistant' | 'system';
|
|
889
|
+
content: string;
|
|
890
|
+
sender?: string;
|
|
891
|
+
senderRole?: string;
|
|
892
|
+
/**
|
|
893
|
+
* release201/30 — original IM message createdAt (ISO 8601). Consumed by
|
|
894
|
+
* sessions-dispatcher to stamp the `at="..."` attribute on each
|
|
895
|
+
* <prior_message> tag inside the conversation context XML so the model
|
|
896
|
+
* can reason about chronology. Optional for back-compat; missing
|
|
897
|
+
* timestamps degrade to "now" at compose time.
|
|
898
|
+
*/
|
|
899
|
+
createdAt?: string;
|
|
900
|
+
/**
|
|
901
|
+
* release201/30 §XML-context P0 (2026-05-31) — asset attachments
|
|
902
|
+
* carried alongside this prior chat message. Forwarded verbatim from
|
|
903
|
+
* cloud's `TaskDispatchContextEntry.attachedAssetIds /
|
|
904
|
+
* attachedAssets` so sessions-dispatcher can stamp
|
|
905
|
+
* `<attached_assets>` children inside `<prior_message>` and the agent
|
|
906
|
+
* sees prior PDF/image references even though the chat surface only
|
|
907
|
+
* carried the user's text body. Optional; absence is treated as "no
|
|
908
|
+
* attachments on this turn".
|
|
909
|
+
*/
|
|
910
|
+
attachedAssetIds?: string[];
|
|
911
|
+
attachedAssets?: Array<{
|
|
912
|
+
id: string;
|
|
913
|
+
mime?: string;
|
|
914
|
+
filename?: string;
|
|
915
|
+
sizeBytes?: number;
|
|
916
|
+
}>;
|
|
917
|
+
}>;
|
|
918
|
+
/**
|
|
919
|
+
* Unconcatenated original user prompt for adapters that take history
|
|
920
|
+
* separately via `contextEntries`. When set, Hermes /v1/runs sends this
|
|
921
|
+
* as `input` and the history as `conversation_history`. When unset,
|
|
922
|
+
* adapters fall back to `prompt` (already concatenated by dispatch.ts).
|
|
923
|
+
*/
|
|
924
|
+
currentPrompt?: string;
|
|
925
|
+
/**
|
|
926
|
+
* 2026-05-29 — asset reminder/inline blocks produced by
|
|
927
|
+
* `dispatch.ts:resolveAssetRefs` for non-image / text-like assets
|
|
928
|
+
* aggregated from the chat context window (W1).
|
|
929
|
+
*
|
|
930
|
+
* These blocks are also baked into `prompt` (so legacy text-only
|
|
931
|
+
* adapters keep working), but adapters that send only `currentPrompt`
|
|
932
|
+
* to a stateful upstream (Hermes sessions API, OpenAI Responses with
|
|
933
|
+
* server-side history) would otherwise drop them and the agent would
|
|
934
|
+
* be told "no file was attached" even though the cloud W1 collector
|
|
935
|
+
* picked the asset up. Sessions-dispatcher must prepend these to the
|
|
936
|
+
* current-turn message text.
|
|
937
|
+
*
|
|
938
|
+
* Empty / undefined → no assets resolved into prompt blocks; the
|
|
939
|
+
* adapter sends the bare currentPrompt.
|
|
940
|
+
*/
|
|
941
|
+
assetPromptBlocks?: string[];
|
|
942
|
+
/**
|
|
943
|
+
* release201/30 — fields required by sessions-style adapters (Hermes
|
|
944
|
+
* /api/sessions/{id}/chat/stream) to build a <conversation_context> XML
|
|
945
|
+
* block that disambiguates first-person voice across participants in
|
|
946
|
+
* group chats. Legacy /v1/runs path and non-Hermes adapters ignore these.
|
|
947
|
+
*
|
|
948
|
+
* See `daemon/conversation-context.ts` for the composer that consumes
|
|
949
|
+
* these fields.
|
|
950
|
+
*/
|
|
951
|
+
conversationType?: 'direct' | 'group' | 'unknown';
|
|
952
|
+
conversationId?: string;
|
|
953
|
+
/** profile.agentUsername — agent's human handle (ceo / engineer / etc). */
|
|
954
|
+
profileAgentUsername?: string;
|
|
955
|
+
/** profile.agentImUserId — agent's IM user id. */
|
|
956
|
+
profileAgentImUserId?: string;
|
|
957
|
+
/** Authoritative recipient list of the originating conversation. */
|
|
958
|
+
participants?: Array<{
|
|
959
|
+
imUserId: string;
|
|
960
|
+
username: string;
|
|
961
|
+
displayName: string;
|
|
962
|
+
role: string;
|
|
963
|
+
agentType?: string | null;
|
|
964
|
+
}>;
|
|
965
|
+
/** Username of the human/agent who sent the dispatch trigger message. */
|
|
966
|
+
currentMessageSender?: string;
|
|
967
|
+
/** Role of the dispatch trigger sender (human / agent / admin / system). */
|
|
968
|
+
currentMessageSenderRole?: 'human' | 'agent' | 'admin' | 'system';
|
|
969
|
+
/**
|
|
970
|
+
* release201/25 §7 / release201/26 — typed L3 input contract (cloud built
|
|
971
|
+
* via `ConversationMemoryService.buildEnvelope`). Envelope-aware adapter
|
|
972
|
+
* paths import their adapter's `context-render.ts` module
|
|
973
|
+
* (`adapters/<name>/context-render.ts`) and call `renderContextEnvelope`
|
|
974
|
+
* to translate this into their native history shape (Hermes XML body,
|
|
975
|
+
* OpenClaw `/v1/responses` input array, CLI markdown, ...).
|
|
976
|
+
*
|
|
977
|
+
* Optional + forward-compat: when undefined, adapters fall back to the
|
|
978
|
+
* legacy fields above (`contextEntries` + `participants` +
|
|
979
|
+
* `currentMessageSender*`) and compose the body themselves.
|
|
980
|
+
*/
|
|
981
|
+
contextEnvelope?: ConversationContextEnvelope;
|
|
550
982
|
}
|
|
551
983
|
interface TaskResult {
|
|
552
984
|
ok: boolean;
|
|
@@ -565,7 +997,16 @@ interface TaskResult {
|
|
|
565
997
|
tokensUsed?: number;
|
|
566
998
|
durationMs?: number;
|
|
567
999
|
};
|
|
568
|
-
/**
|
|
1000
|
+
/**
|
|
1001
|
+
* Adapter-private metadata used by daemon-side bridges/observability.
|
|
1002
|
+
*
|
|
1003
|
+
* release202/05 C2 — interactive adapters (codex / claude-code) MAY set
|
|
1004
|
+
* `metadata.providerSessionId?: string` here: the provider/CLI session
|
|
1005
|
+
* (thread) id to persist via ProviderSessionMapper so the next turn on the
|
|
1006
|
+
* same (conversation, agent, adapter) can `resume` it. No type change needed
|
|
1007
|
+
* (metadata is `Record<string, unknown>`); the daemon dispatch bridge reads
|
|
1008
|
+
* the key and persists when present.
|
|
1009
|
+
*/
|
|
569
1010
|
metadata?: Record<string, unknown>;
|
|
570
1011
|
}
|
|
571
1012
|
/**
|
|
@@ -660,7 +1101,29 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
|
|
|
660
1101
|
model: z.ZodDefault<z.ZodString>;
|
|
661
1102
|
/** Named custom provider written into Hermes config.yaml. */
|
|
662
1103
|
prismerProviderName: z.ZodDefault<z.ZodString>;
|
|
663
|
-
/**
|
|
1104
|
+
/**
|
|
1105
|
+
* 2026-05-30 — per-agent LLM proxy selector.
|
|
1106
|
+
*
|
|
1107
|
+
* Picks which Prismer Cloud upstream pool this hermes profile points its
|
|
1108
|
+
* `chat/completions` calls at. Default `newapi` is the platform aggregator
|
|
1109
|
+
* (gemini / kimi / etc.). `deepseek` swaps the cloud-side `base_url` to the
|
|
1110
|
+
* `/api/v1/proxy/deepseek/chat/completions` alias so the cloud forwards the
|
|
1111
|
+
* request directly to DeepSeek regardless of the global
|
|
1112
|
+
* `DEEPSEEK_BYPASS_ENABLED` env. Lets two agents share a workspace + daemon
|
|
1113
|
+
* but route to different LLM backends for an apples-to-apples comparison.
|
|
1114
|
+
*
|
|
1115
|
+
* Resolution priority for `custom_providers[0].base_url`:
|
|
1116
|
+
* 1. `prismerProviderBaseUrl` (explicit operator override) — wins always.
|
|
1117
|
+
* 2. `proxyProvider === 'deepseek'` → PRISMER_BASE_URL + `/api/v1/proxy/deepseek`
|
|
1118
|
+
* 3. `proxyProvider === 'newapi'` (default) → PRISMER_BASE_URL + `/api/v1`
|
|
1119
|
+
*/
|
|
1120
|
+
proxyProvider: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
1121
|
+
/**
|
|
1122
|
+
* Override cloud provider base. Defaults to PRISMER_BASE_URL + /api/v1
|
|
1123
|
+
* (or `/api/v1/proxy/<proxyProvider>` when `proxyProvider !== 'newapi'`).
|
|
1124
|
+
* An explicit value here WINS over `proxyProvider` — operators who pin
|
|
1125
|
+
* the base_url get exactly what they pinned.
|
|
1126
|
+
*/
|
|
664
1127
|
prismerProviderBaseUrl: z.ZodOptional<z.ZodString>;
|
|
665
1128
|
/** Env key Hermes reads from profile .env for the Prismer API key. */
|
|
666
1129
|
prismerApiKeyEnv: z.ZodDefault<z.ZodString>;
|
|
@@ -677,12 +1140,6 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
|
|
|
677
1140
|
* native state key directly and records the exact bridge result on the task.
|
|
678
1141
|
*/
|
|
679
1142
|
mirrorNativeGoals: z.ZodDefault<z.ZodBoolean>;
|
|
680
|
-
/**
|
|
681
|
-
* Optional checkout path for Hermes Agent source. Used only as a fallback
|
|
682
|
-
* when the installed `hermes` binary is older than the native Kanban CLI
|
|
683
|
-
* surface but the local source tree contains hermes_cli/kanban_db.py.
|
|
684
|
-
*/
|
|
685
|
-
hermesSourceDir: z.ZodOptional<z.ZodString>;
|
|
686
1143
|
nativeMirrorTimeoutMs: z.ZodDefault<z.ZodNumber>;
|
|
687
1144
|
/** Task authority level: executor (default) or orchestrator. */
|
|
688
1145
|
taskAuthority: z.ZodDefault<z.ZodOptional<z.ZodEnum<["executor", "orchestrator"]>>>;
|
|
@@ -703,6 +1160,74 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
|
|
|
703
1160
|
}, z.ZodTypeAny, "passthrough">>, "many">]>>;
|
|
704
1161
|
/** Override the skills root read for dispatch-time SKILL.md injection. */
|
|
705
1162
|
skillsDir: z.ZodOptional<z.ZodString>;
|
|
1163
|
+
/**
|
|
1164
|
+
* release201/24 §Phase2 — extra skill dirs registered into the gateway's
|
|
1165
|
+
* config.yaml `skills.external_dirs` so the skill-under-test enters Hermes'
|
|
1166
|
+
* NATIVE skill discovery (skills_list / skill tools). The daemon's
|
|
1167
|
+
* system-prompt injection alone is not seen by the agent's skill tools, and
|
|
1168
|
+
* HERMES_HOME does NOT scope skill loading (the ~90 bundled skills ship with
|
|
1169
|
+
* the hermes package). The eval session spawner sets this to its isolated
|
|
1170
|
+
* temp-home skills dir.
|
|
1171
|
+
*/
|
|
1172
|
+
skillsExternalDirs: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
1173
|
+
/**
|
|
1174
|
+
* release201/24 §Phase2 — install the prismer daemon memory hooks
|
|
1175
|
+
* (pre_llm_call recall / post_llm_call extract / on_session_end). Default
|
|
1176
|
+
* true. The eval session spawner sets this FALSE so a throwaway eval run
|
|
1177
|
+
* neither READS contaminated workspace memory (a prior failed run's
|
|
1178
|
+
* "skill X is stale" note biases the agent) nor WRITES memories that poison
|
|
1179
|
+
* later runs — the eval judges the skill on its own merits.
|
|
1180
|
+
*/
|
|
1181
|
+
installMemoryHooks: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1182
|
+
/**
|
|
1183
|
+
* release201/26 §14 Phase A (#A1) — enable hermes' BUILTIN knowledge memory
|
|
1184
|
+
* (`MEMORY.md` / `USER.md` injected into the system prompt). Default false.
|
|
1185
|
+
*
|
|
1186
|
+
* release201/09 §9.4b (2026-05-30 hotfix, Option B2) — important correction
|
|
1187
|
+
* to the previous comment claim "hermes' code default = False, we don't
|
|
1188
|
+
* write a memory: block so it stays off". That was WRONG: hermes
|
|
1189
|
+
* deep-merges user config OVER `DEFAULT_CONFIG` (hermes_cli/config.py:4701
|
|
1190
|
+
* `_deep_merge`), and `DEFAULT_CONFIG.memory.memory_enabled = True`
|
|
1191
|
+
* (config.py:1373). `agent_init.py:1076` reads from the MERGED config, so
|
|
1192
|
+
* not writing a `memory:` block leaves hermes builtin memory ON. Real
|
|
1193
|
+
* contamination symptom (2026-05-30 user report): after workspace clear +
|
|
1194
|
+
* new workspace spawn, CEO recited 5 prior-workspace agent IDs + 7 named
|
|
1195
|
+
* humans verbatim from `~/.hermes/profiles/ceo/memories/MEMORY.md`. Fix
|
|
1196
|
+
* here = ALWAYS write the `memory:` block with explicit values; default
|
|
1197
|
+
* (false) writes `memory_enabled: false` + `user_profile_enabled: false`
|
|
1198
|
+
* so hermes' builtin MEMORY.md/USER.md injection is genuinely off. When
|
|
1199
|
+
* true (release201/26 §14 Phase A cutover), writes `memory_enabled: true`
|
|
1200
|
+
* + `user_profile_enabled: true`. Operator-set sibling keys in an existing
|
|
1201
|
+
* memory: block (e.g. `memory_char_limit`, `provider`) are preserved.
|
|
1202
|
+
*/
|
|
1203
|
+
enableBuiltinMemory: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
1204
|
+
/**
|
|
1205
|
+
* release201/26 §13.4a (P2 spike, 2026-05-30) — pin hermes vision config so
|
|
1206
|
+
* an agent on a `custom:` provider can actually RECEIVE images.
|
|
1207
|
+
*
|
|
1208
|
+
* Production坑: hermes v0.15.0 does NOT route images through the main chat's
|
|
1209
|
+
* inline image part; it spins up a separate `vision_analyze_tool` aux LLM.
|
|
1210
|
+
* That aux path's provider auto-detect does NOT recognize `custom:` providers
|
|
1211
|
+
* → 502. Every daemon agent runs a custom provider (`custom:prismer` →
|
|
1212
|
+
* Prismer Cloud `/api/v1`), so DEFAULT behaviour is: agent receives an image
|
|
1213
|
+
* → guaranteed 502. The spike-verified fix is pure config (no hermes patch):
|
|
1214
|
+
* model.supports_vision: true + agent.image_input_mode: native
|
|
1215
|
+
* which takes the native fast-path and feeds the image straight to the main
|
|
1216
|
+
* model. The default model `us-kimi-k2.6` is vision-capable and correctly
|
|
1217
|
+
* described images under this config in the spike.
|
|
1218
|
+
*
|
|
1219
|
+
* Default取舍 (2026-05-30, evidence-based): when the caller does NOT set this
|
|
1220
|
+
* explicitly, the effective value is `VISION_CAPABLE_MODELS.has(config.model)`
|
|
1221
|
+
* — a per-model allowlist measured by real cloud-proxy vision probes (see the
|
|
1222
|
+
* `VISION_CAPABLE_MODELS` docblock). This REPLACES the prior
|
|
1223
|
+
* `proxyProvider === 'deepseek' ? false : true` heuristic. Verified vision
|
|
1224
|
+
* models (gemini-3.1-pro-preview, gemini-3.1-flash-lite-preview, us-kimi-k2.6
|
|
1225
|
+
* — the daemon default) default ON; verified text-only models
|
|
1226
|
+
* (deepseek-v4-flash / deepseek-v4-pro, which 400 on image parts) default OFF.
|
|
1227
|
+
* An explicit value here always wins; set `true` to force vision on an
|
|
1228
|
+
* unmeasured model, `false` for any text-only / reasoning model.
|
|
1229
|
+
*/
|
|
1230
|
+
supportsVision: z.ZodOptional<z.ZodBoolean>;
|
|
706
1231
|
/**
|
|
707
1232
|
* Role-template snapshot carried in AgentProfile.config by cloud ACP.
|
|
708
1233
|
* Expected fields used here:
|
|
@@ -773,22 +1298,26 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
|
|
|
773
1298
|
installPrismerMcpServer: boolean;
|
|
774
1299
|
model: string;
|
|
775
1300
|
prismerProviderName: string;
|
|
1301
|
+
proxyProvider: string;
|
|
776
1302
|
prismerApiKeyEnv: string;
|
|
777
1303
|
mirrorNativeKanban: boolean;
|
|
778
1304
|
mirrorNativeGoals: boolean;
|
|
779
1305
|
nativeMirrorTimeoutMs: number;
|
|
780
1306
|
taskAuthority: "executor" | "orchestrator";
|
|
781
1307
|
approvalPolicy: "strict" | "auto-low-risk" | "autonomous";
|
|
1308
|
+
installMemoryHooks: boolean;
|
|
1309
|
+
enableBuiltinMemory: boolean;
|
|
782
1310
|
hermesProfileName?: string | undefined;
|
|
783
1311
|
prismerMcpServerPath?: string | undefined;
|
|
784
1312
|
prismerProviderBaseUrl?: string | undefined;
|
|
785
|
-
hermesSourceDir?: string | undefined;
|
|
786
1313
|
mcpAllowlist?: string[] | null | undefined;
|
|
787
1314
|
operatingPrinciples?: string | Record<string, string> | z.objectOutputType<{
|
|
788
1315
|
source: z.ZodString;
|
|
789
1316
|
text: z.ZodString;
|
|
790
1317
|
}, z.ZodTypeAny, "passthrough">[] | undefined;
|
|
791
1318
|
skillsDir?: string | undefined;
|
|
1319
|
+
skillsExternalDirs?: string[] | undefined;
|
|
1320
|
+
supportsVision?: boolean | undefined;
|
|
792
1321
|
roleTemplate?: z.objectOutputType<{
|
|
793
1322
|
mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
794
1323
|
toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -819,11 +1348,11 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
|
|
|
819
1348
|
prismerMcpServerPath?: string | undefined;
|
|
820
1349
|
model?: string | undefined;
|
|
821
1350
|
prismerProviderName?: string | undefined;
|
|
1351
|
+
proxyProvider?: string | undefined;
|
|
822
1352
|
prismerProviderBaseUrl?: string | undefined;
|
|
823
1353
|
prismerApiKeyEnv?: string | undefined;
|
|
824
1354
|
mirrorNativeKanban?: boolean | undefined;
|
|
825
1355
|
mirrorNativeGoals?: boolean | undefined;
|
|
826
|
-
hermesSourceDir?: string | undefined;
|
|
827
1356
|
nativeMirrorTimeoutMs?: number | undefined;
|
|
828
1357
|
taskAuthority?: "executor" | "orchestrator" | undefined;
|
|
829
1358
|
approvalPolicy?: "strict" | "auto-low-risk" | "autonomous" | undefined;
|
|
@@ -833,6 +1362,10 @@ declare const HermesProfileConfigSchema: z.ZodObject<{
|
|
|
833
1362
|
text: z.ZodString;
|
|
834
1363
|
}, z.ZodTypeAny, "passthrough">[] | undefined;
|
|
835
1364
|
skillsDir?: string | undefined;
|
|
1365
|
+
skillsExternalDirs?: string[] | undefined;
|
|
1366
|
+
installMemoryHooks?: boolean | undefined;
|
|
1367
|
+
enableBuiltinMemory?: boolean | undefined;
|
|
1368
|
+
supportsVision?: boolean | undefined;
|
|
836
1369
|
roleTemplate?: z.objectInputType<{
|
|
837
1370
|
mcpServers: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
838
1371
|
toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
@@ -898,11 +1431,27 @@ declare const OpenClawProfileConfigSchema: z.ZodObject<{
|
|
|
898
1431
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
899
1432
|
}, z.ZodTypeAny, "passthrough">>>;
|
|
900
1433
|
skillsDir: z.ZodOptional<z.ZodString>;
|
|
1434
|
+
/**
|
|
1435
|
+
* release202/03 §3.2 — when set, ensure the OpenClaw gateway's openclaw.json
|
|
1436
|
+
* carries a `prismer` model provider pointing at our cloud gateway, and that
|
|
1437
|
+
* `agents.defaults.model.primary` is the curated model below. Lets each
|
|
1438
|
+
* OpenClaw agent run a different curated chat model through one sk-prismer key
|
|
1439
|
+
* (tiered model). Undefined = leave openclaw.json untouched (legacy).
|
|
1440
|
+
*/
|
|
1441
|
+
proxyProvider: z.ZodOptional<z.ZodEnum<["newapi", "deepseek"]>>;
|
|
1442
|
+
/** Curated LLM model id the gateway should use (e.g. 'us-kimi-k2.6'). */
|
|
1443
|
+
prismerModel: z.ZodOptional<z.ZodString>;
|
|
1444
|
+
/** Env var (in the gateway process) holding the sk-prismer-* key. */
|
|
1445
|
+
prismerApiKeyEnv: z.ZodDefault<z.ZodString>;
|
|
1446
|
+
/** openclaw.json path (default ~/.openclaw/openclaw.json or $OPENCLAW_HOME). */
|
|
1447
|
+
openclawConfigPath: z.ZodOptional<z.ZodString>;
|
|
901
1448
|
}, "strip", z.ZodTypeAny, {
|
|
902
1449
|
port: number;
|
|
903
1450
|
apiKey: string;
|
|
904
1451
|
model: string;
|
|
1452
|
+
prismerApiKeyEnv: string;
|
|
905
1453
|
approvalPolicy: "strict" | "auto-low-risk" | "autonomous";
|
|
1454
|
+
proxyProvider?: "newapi" | "deepseek" | undefined;
|
|
906
1455
|
mcpAllowlist?: string[] | null | undefined;
|
|
907
1456
|
skillsDir?: string | undefined;
|
|
908
1457
|
roleTemplate?: z.objectOutputType<{
|
|
@@ -914,10 +1463,14 @@ declare const OpenClawProfileConfigSchema: z.ZodObject<{
|
|
|
914
1463
|
toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
915
1464
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
916
1465
|
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
1466
|
+
prismerModel?: string | undefined;
|
|
1467
|
+
openclawConfigPath?: string | undefined;
|
|
917
1468
|
}, {
|
|
918
1469
|
apiKey: string;
|
|
919
1470
|
port?: number | undefined;
|
|
920
1471
|
model?: string | undefined;
|
|
1472
|
+
proxyProvider?: "newapi" | "deepseek" | undefined;
|
|
1473
|
+
prismerApiKeyEnv?: string | undefined;
|
|
921
1474
|
approvalPolicy?: "strict" | "auto-low-risk" | "autonomous" | undefined;
|
|
922
1475
|
mcpAllowlist?: string[] | null | undefined;
|
|
923
1476
|
skillsDir?: string | undefined;
|
|
@@ -930,6 +1483,8 @@ declare const OpenClawProfileConfigSchema: z.ZodObject<{
|
|
|
930
1483
|
toolsAllowlist: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
931
1484
|
}, z.ZodTypeAny, "passthrough">>, "many">>;
|
|
932
1485
|
}, z.ZodTypeAny, "passthrough"> | undefined;
|
|
1486
|
+
prismerModel?: string | undefined;
|
|
1487
|
+
openclawConfigPath?: string | undefined;
|
|
933
1488
|
}>;
|
|
934
1489
|
type OpenClawProfileConfig = z.infer<typeof OpenClawProfileConfigSchema>;
|
|
935
1490
|
declare const openclawAdapter: AdapterDef;
|
|
@@ -994,7 +1549,7 @@ type LocalDb = Database.Database;
|
|
|
994
1549
|
declare function openLocalDb(path: string): LocalDb;
|
|
995
1550
|
declare function runMigrations(db: LocalDb): void;
|
|
996
1551
|
declare function currentSchemaVersion(db: LocalDb): number;
|
|
997
|
-
declare const TARGET_SCHEMA_VERSION =
|
|
1552
|
+
declare const TARGET_SCHEMA_VERSION = 8;
|
|
998
1553
|
|
|
999
1554
|
type SyncResourceType = 'workspace' | 'agent' | 'agent_profile';
|
|
1000
1555
|
type SyncOperation = 'create' | 'update' | 'delete';
|
|
@@ -1191,11 +1746,28 @@ interface ConfigPaths {
|
|
|
1191
1746
|
cacheDir: string;
|
|
1192
1747
|
logsDir: string;
|
|
1193
1748
|
/**
|
|
1194
|
-
*
|
|
1195
|
-
*
|
|
1196
|
-
*
|
|
1749
|
+
* Legacy per-task run scratch dirs (pre-release201/09).
|
|
1750
|
+
*
|
|
1751
|
+
* Pre-09: `${runsDir}/${taskId}/_outbox|scratch/`.
|
|
1752
|
+
* 09 Phase 2 / release202/04: dispatch.ts now writes to
|
|
1753
|
+
* `${root}/workspaces/<wid>/projects/<pid|_unscoped>/tasks/<tid>/{artifacts,scratch}`
|
|
1754
|
+
* via `resolveTaskWorkdir()`. `runsDir` is kept as a fallback for tests + a
|
|
1755
|
+
* once-off startup migration helper (`runs/<tid>/` → new path; symlink 兜底
|
|
1756
|
+
* 90 天兼容期, §9.3.1).
|
|
1197
1757
|
*/
|
|
1198
1758
|
runsDir: string;
|
|
1759
|
+
/**
|
|
1760
|
+
* release201/09 Phase 2 root for workspace × project × task scoped scratch:
|
|
1761
|
+
* `${root}/workspaces/`. resolveTaskWorkdir() composes the per-task path
|
|
1762
|
+
* underneath. Cache GC + project archive scan this root.
|
|
1763
|
+
*/
|
|
1764
|
+
workspacesDir: string;
|
|
1765
|
+
/**
|
|
1766
|
+
* release201/09 Phase 2 root for device × agent role layer:
|
|
1767
|
+
* `${root}/devices/`. v2.0.7 Phase 2 不主动创建,Phase 3 (agent transfer)
|
|
1768
|
+
* 才落盘 `profile.json` / `skills/<slug>/` 等内容,本 helper 只解析路径。
|
|
1769
|
+
*/
|
|
1770
|
+
devicesDir: string;
|
|
1199
1771
|
}
|
|
1200
1772
|
/**
|
|
1201
1773
|
* Resolve paths for the prismer home directory. Honors `PRISMER_HOME` env var;
|
|
@@ -1628,13 +2200,14 @@ interface UrlResolution {
|
|
|
1628
2200
|
*/
|
|
1629
2201
|
declare function extractHttpUrls(text: string): string[];
|
|
1630
2202
|
|
|
1631
|
-
interface
|
|
2203
|
+
interface ArtifactsWatcherOptions {
|
|
1632
2204
|
/**
|
|
1633
2205
|
* Default directory to watch when no setActiveTask has narrowed it.
|
|
1634
|
-
* Container mode: `/workspace/_outbox
|
|
1635
|
-
*
|
|
2206
|
+
* Container mode: `/workspace/_outbox` (legacy path name kept for the
|
|
2207
|
+
* container controller contract). Host mode: omit (no default scan — only
|
|
2208
|
+
* watch when an active task points at a specific dir).
|
|
1636
2209
|
*/
|
|
1637
|
-
|
|
2210
|
+
artifactsDir?: string;
|
|
1638
2211
|
/** Cloud client (already configured with apiKey + baseUrl). */
|
|
1639
2212
|
cloud: CloudClient;
|
|
1640
2213
|
/**
|
|
@@ -1658,19 +2231,39 @@ interface OutboxWatcherOptions {
|
|
|
1658
2231
|
info: (msg: string) => void;
|
|
1659
2232
|
warn: (msg: string) => void;
|
|
1660
2233
|
};
|
|
2234
|
+
/**
|
|
2235
|
+
* release202/09 P2 — directory auto-scan gate. **Default FALSE.**
|
|
2236
|
+
*
|
|
2237
|
+
* When false, the polling scan loop does NOT run: the watcher never reads
|
|
2238
|
+
* `artifactsDir` and never auto-uploads files. File delivery is instead
|
|
2239
|
+
* driven EXPLICITLY by the agent via `cloud deliver` → daemon local-server
|
|
2240
|
+
* `POST /local/deliver` → `recordDeliveredAsset(taskId, assetId)`. The
|
|
2241
|
+
* `pendingByTask` / `flushPending` / `recordDeliveredAsset` plumbing and the
|
|
2242
|
+
* `upload()` path all still work — only the implicit directory-magic is off.
|
|
2243
|
+
*
|
|
2244
|
+
* The original directory-scan code (currentScanDirs / tick / scanDir /
|
|
2245
|
+
* quarantine) is retained intact behind this flag so it can be re-enabled
|
|
2246
|
+
* (autoScan:true) as a fallback if the explicit path needs to fall back to
|
|
2247
|
+
* the legacy auto-archive behaviour.
|
|
2248
|
+
*/
|
|
2249
|
+
autoScan?: boolean;
|
|
1661
2250
|
}
|
|
1662
2251
|
interface ActiveTask {
|
|
1663
2252
|
taskId: string;
|
|
1664
2253
|
/** Adapter name; surfaces in upload metadata for observability. */
|
|
1665
2254
|
adapter?: string;
|
|
1666
2255
|
/**
|
|
1667
|
-
* Per-task
|
|
1668
|
-
* addition to `opts.
|
|
2256
|
+
* Per-task artifacts directory. When set, scans this directory in
|
|
2257
|
+
* addition to `opts.artifactsDir`. Files uploaded from here are tagged
|
|
1669
2258
|
* with `kind=agent-output` (host-mode contract).
|
|
2259
|
+
*
|
|
2260
|
+
* Backward-compat (release202/04 P0): the watcher also scans the sibling
|
|
2261
|
+
* legacy `result/` and `_outbox/` dirs (resolved from this dir's parent)
|
|
2262
|
+
* for in-flight tasks created before the artifacts rename.
|
|
1670
2263
|
*/
|
|
1671
|
-
|
|
2264
|
+
artifactsDir?: string;
|
|
1672
2265
|
}
|
|
1673
|
-
declare class
|
|
2266
|
+
declare class ArtifactsWatcher {
|
|
1674
2267
|
private opts;
|
|
1675
2268
|
private timer?;
|
|
1676
2269
|
private uploaded;
|
|
@@ -1690,7 +2283,7 @@ declare class OutboxWatcher {
|
|
|
1690
2283
|
/**
|
|
1691
2284
|
* Legacy container/sandbox task. Used only when an `ActiveTask` is set
|
|
1692
2285
|
* **without** an `outboxDir` (i.e. the legacy `setActiveTask` shape
|
|
1693
|
-
* where the watcher's default `opts.
|
|
2286
|
+
* where the watcher's default `opts.artifactsDir` is the scan target).
|
|
1694
2287
|
* Single slot because the legacy container deployment only ever runs
|
|
1695
2288
|
* one task at a time per container.
|
|
1696
2289
|
*/
|
|
@@ -1703,13 +2296,13 @@ declare class OutboxWatcher {
|
|
|
1703
2296
|
* can stamp it onto task.dispatch.reply.assetIds.
|
|
1704
2297
|
*/
|
|
1705
2298
|
private pendingByTask;
|
|
1706
|
-
constructor(opts:
|
|
2299
|
+
constructor(opts: ArtifactsWatcherOptions);
|
|
1707
2300
|
/**
|
|
1708
2301
|
* Register a host-mode task envelope. Each call adds (or replaces) an
|
|
1709
2302
|
* entry keyed by `task.taskId` so concurrent dispatches do not clobber
|
|
1710
2303
|
* each other.
|
|
1711
2304
|
*
|
|
1712
|
-
* Requires `task.
|
|
2305
|
+
* Requires `task.artifactsDir` to be set — the per-task workdir is the
|
|
1713
2306
|
* isolation boundary. For the legacy container/sandbox single-slot
|
|
1714
2307
|
* shape (no per-task dir), use `setActiveTask` instead.
|
|
1715
2308
|
*/
|
|
@@ -1727,7 +2320,7 @@ declare class OutboxWatcher {
|
|
|
1727
2320
|
* mode). The caller is still responsible for `removeActiveTask`
|
|
1728
2321
|
* (or another `setActiveTask(null)`) at teardown.
|
|
1729
2322
|
* - Non-null **without** `outboxDir` → store in the legacy container
|
|
1730
|
-
* slot. Uploads from `opts.
|
|
2323
|
+
* slot. Uploads from `opts.artifactsDir` are tagged with this task.
|
|
1731
2324
|
* - `null` → clear the legacy container slot only. Does NOT touch
|
|
1732
2325
|
* the host-mode `activeTasks` map; concurrent host-mode dispatches
|
|
1733
2326
|
* keep their own slots until they call `removeActiveTask`
|
|
@@ -1745,6 +2338,46 @@ declare class OutboxWatcher {
|
|
|
1745
2338
|
* second time. dispatch.ts calls this once at reply-build time.
|
|
1746
2339
|
*/
|
|
1747
2340
|
flushPending(taskId: string): string[];
|
|
2341
|
+
/**
|
|
2342
|
+
* release202/09 P2 — explicit-delivery hook (动作 A).
|
|
2343
|
+
*
|
|
2344
|
+
* Append an already-uploaded assetId to `pendingByTask[taskId]` so the
|
|
2345
|
+
* dispatch-end `flushPending(taskId)` surfaces it on
|
|
2346
|
+
* `task.dispatch.reply.assetIds` — exactly the same channel the (now
|
|
2347
|
+
* gated-off) auto-scan used at lines ~578-580. This is the bridge that
|
|
2348
|
+
* lets the daemon local-server's `POST /local/deliver` handler reuse the
|
|
2349
|
+
* existing reply-attachment plumbing instead of inventing a parallel one.
|
|
2350
|
+
*
|
|
2351
|
+
* Idempotency: callers should pass each assetId once. We de-dup defensively
|
|
2352
|
+
* so a double-delivered file does not appear twice in reply.assetIds.
|
|
2353
|
+
*/
|
|
2354
|
+
recordDeliveredAsset(taskId: string, assetId: string): void;
|
|
2355
|
+
/**
|
|
2356
|
+
* release202/09 P2 — explicit upload entrypoint shared by the daemon
|
|
2357
|
+
* local-server `POST /local/deliver` handler. Reads the file off the
|
|
2358
|
+
* container FS, runs the SAME agent-output-policy + magic-bytes guards the
|
|
2359
|
+
* auto-scan `upload()` path uses, and POSTs via `DaemonAssetUploadClient`
|
|
2360
|
+
* with the daemon's credential. Returns the freshly-minted assetId.
|
|
2361
|
+
*
|
|
2362
|
+
* Unlike the private `upload()` (which is keyed on an ActiveTask + Stats
|
|
2363
|
+
* from the scan loop), this is a one-shot for a caller-supplied absolute
|
|
2364
|
+
* path; it does NOT touch `pendingByTask` — the caller decides whether the
|
|
2365
|
+
* file rides the reply (`recordDeliveredAsset`, 动作 A) or goes out as a
|
|
2366
|
+
* standalone message (动作 B).
|
|
2367
|
+
*
|
|
2368
|
+
* Throws a clear Error on policy / magic-bytes rejection so the agent can
|
|
2369
|
+
* read why its file was refused.
|
|
2370
|
+
*/
|
|
2371
|
+
deliverFile(input: {
|
|
2372
|
+
taskId: string;
|
|
2373
|
+
filePath: string;
|
|
2374
|
+
adapter?: string;
|
|
2375
|
+
}): Promise<{
|
|
2376
|
+
assetId: string;
|
|
2377
|
+
mime: string;
|
|
2378
|
+
filename: string;
|
|
2379
|
+
sizeBytes: number;
|
|
2380
|
+
}>;
|
|
1748
2381
|
start(): void;
|
|
1749
2382
|
stop(): void;
|
|
1750
2383
|
/**
|
|
@@ -1762,8 +2395,13 @@ declare class OutboxWatcher {
|
|
|
1762
2395
|
* and accumulated per-task without sharing global mutable state.
|
|
1763
2396
|
*
|
|
1764
2397
|
* Dedup so a directory configured in both spots only scans once
|
|
1765
|
-
* (legacy single-task case where opts.
|
|
2398
|
+
* (legacy single-task case where opts.artifactsDir == legacyTask.artifactsDir
|
|
1766
2399
|
* is unlikely but cheap to handle).
|
|
2400
|
+
*
|
|
2401
|
+
* Backward-compat (release202/04 P0): for each host-mode task pointing at
|
|
2402
|
+
* the new `artifacts/` dir, also enqueue its sibling legacy `result/` and
|
|
2403
|
+
* `_outbox/` dirs (same parent). readdir on a missing legacy dir is a cheap
|
|
2404
|
+
* ENOENT no-op in scanDir, so this is safe even when no legacy files exist.
|
|
1767
2405
|
*/
|
|
1768
2406
|
private currentScanDirs;
|
|
1769
2407
|
private tick;
|
|
@@ -1875,14 +2513,20 @@ interface DispatchDeps {
|
|
|
1875
2513
|
/** Hook for tests / observability. */
|
|
1876
2514
|
onProgress?: (taskId: string, p: TaskDispatchProgressPayload) => void;
|
|
1877
2515
|
/**
|
|
1878
|
-
*
|
|
1879
|
-
* directory
|
|
1880
|
-
*
|
|
1881
|
-
* time. Optional so tests can omit it.
|
|
2516
|
+
* Artifacts uploader. When provided, dispatch creates a per-task artifacts
|
|
2517
|
+
* directory, points the watcher at it via setActiveTask, and drains its
|
|
2518
|
+
* assetIds into reply.assetIds at flush time. Optional so tests can omit it.
|
|
1882
2519
|
*/
|
|
1883
|
-
|
|
1884
|
-
/** Daemon paths — used to derive the per-task
|
|
2520
|
+
artifactsWatcher?: ArtifactsWatcher;
|
|
2521
|
+
/** Daemon paths — used to derive the per-task artifacts dir. */
|
|
1885
2522
|
paths?: ConfigPaths;
|
|
2523
|
+
/**
|
|
2524
|
+
* release201/09 §9.9 — Stable device identifier from `config.toml`. Surfaced
|
|
2525
|
+
* to the spawned agent process as `PRISMER_DAEMON_ID` env for metric-outbox
|
|
2526
|
+
* emission + transfer manifest authoring. Optional so existing tests can
|
|
2527
|
+
* omit it; production runner always provides.
|
|
2528
|
+
*/
|
|
2529
|
+
daemonId?: string;
|
|
1886
2530
|
/**
|
|
1887
2531
|
* Multi-workspace asset metadata indexes for #filename resolution.
|
|
1888
2532
|
* Keyed by workspaceId. If absent, #ref resolution is skipped entirely.
|
|
@@ -2012,6 +2656,17 @@ declare class ServicePool {
|
|
|
2012
2656
|
* on first use or after a crash. Re-checks `healthy()` before returning a cached entry.
|
|
2013
2657
|
*/
|
|
2014
2658
|
ensureService(profile: AgentProfile, adapter: AdapterDef): Promise<AdapterService>;
|
|
2659
|
+
/**
|
|
2660
|
+
* Best-effort read of a cached service by profileId. Does NOT trigger
|
|
2661
|
+
* ensureService / health probe (use ensureService for that). Returns
|
|
2662
|
+
* `undefined` when the pool has never seen the profile or it crashed.
|
|
2663
|
+
*
|
|
2664
|
+
* Added for release201/25 §16.4 A6 — runner needs to reach a live
|
|
2665
|
+
* HermesService instance to call native `resolveApproval` without
|
|
2666
|
+
* paying ensureService's spawn cost (the service is already alive for
|
|
2667
|
+
* the in-flight task).
|
|
2668
|
+
*/
|
|
2669
|
+
peek(profileId: string): AdapterService | undefined;
|
|
2015
2670
|
/** Drop a service handle (e.g. on profile delete or daemon shutdown). */
|
|
2016
2671
|
drop(profileId: string): Promise<void>;
|
|
2017
2672
|
/** Drop all handles, e.g. on graceful shutdown. */
|
|
@@ -2085,11 +2740,72 @@ interface LocalServerOptions {
|
|
|
2085
2740
|
* When set, /healthz reports `assetReady: true`.
|
|
2086
2741
|
*/
|
|
2087
2742
|
attachAsset?: (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
|
|
2743
|
+
/**
|
|
2744
|
+
* release202/09 P2 — explicit file-delivery handler for
|
|
2745
|
+
* `POST /local/deliver`. The in-container agent's `cloud deliver` /
|
|
2746
|
+
* `cloud file send` proxy to this endpoint so the daemon (which holds the
|
|
2747
|
+
* usable IM credential the agent lacks) performs the upload + delivery.
|
|
2748
|
+
*
|
|
2749
|
+
* Body: `{ taskId, path, mode: 'attach' | 'send' | 'task-attach' | 'message-attach', conversationId?, messageId? }`.
|
|
2750
|
+
* - `mode:'attach'` (动作 A): upload + record the assetId onto the active
|
|
2751
|
+
* task's pending list so dispatch-end `flushPending` rides it on the
|
|
2752
|
+
* agent's reply (`reply.assetIds`).
|
|
2753
|
+
* - `mode:'send'` (动作 B): upload + post a standalone message carrying the
|
|
2754
|
+
* attachment to `conversationId`.
|
|
2755
|
+
* - `mode:'task-attach'` (动作 ③, P5#2): upload as a TASK-bound asset
|
|
2756
|
+
* (`sourceTaskId`) for a real kanban task; cloud auto-rolls it onto the
|
|
2757
|
+
* task card + re-emits the terminal digest. No chat reply, no message.
|
|
2758
|
+
* - `mode:'message-attach'` (动作 A2, P5#3): upload + append the asset to an
|
|
2759
|
+
* ALREADY-SENT message (`conversationId` + `messageId`) via the cloud
|
|
2760
|
+
* attach route, which re-emits `message.updated` so the UI picks it up.
|
|
2761
|
+
*
|
|
2762
|
+
* Returns a structured `{ status, body }`. The runner wires this from
|
|
2763
|
+
* `attachDeliver()` in `daemon/asset/deliver.ts`.
|
|
2764
|
+
*/
|
|
2765
|
+
onDeliver?: (body: unknown) => Promise<DeliverHandlerResult>;
|
|
2766
|
+
/**
|
|
2767
|
+
* Optional first-pass handler for `/v1/hooks/*` routes (v2.1 §9.5
|
|
2768
|
+
* daemon-as-hook-intake). Returns true if the request was handled
|
|
2769
|
+
* (response written); false to let the normal route table fall through.
|
|
2770
|
+
* Wired by the daemon runner from `attachHookServer()` in
|
|
2771
|
+
* `daemon/memory/hook-server.ts` whenever both memory + run-session
|
|
2772
|
+
* registry are available. When set, /healthz reports `hooksReady: true`.
|
|
2773
|
+
*/
|
|
2774
|
+
attachHooks?: (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
|
|
2775
|
+
/**
|
|
2776
|
+
* Optional first-pass handler for `/v1/checkpoints/*` routes
|
|
2777
|
+
* (release201/09 §9.4a.7 task product self-check). Independent of
|
|
2778
|
+
* `attachHooks` — checkpoints fire on SDK status-transition only, while
|
|
2779
|
+
* hooks fire per LLM call. Wired by the runner from
|
|
2780
|
+
* `attachCheckpointServer()` in `daemon/checkpoint-server.ts`. When set,
|
|
2781
|
+
* /healthz reports `checkpointsReady: true`.
|
|
2782
|
+
*/
|
|
2783
|
+
attachCheckpoints?: (req: IncomingMessage, res: ServerResponse) => Promise<boolean>;
|
|
2784
|
+
/**
|
|
2785
|
+
* Optional snapshot getter for the eval-session capability
|
|
2786
|
+
* (release201/08 §7.2). When provided, /healthz reports `evalSessions`
|
|
2787
|
+
* with the current active count + per-run summaries. The runner wires
|
|
2788
|
+
* this from `EvalSessionRunner.getState()`.
|
|
2789
|
+
*/
|
|
2790
|
+
getEvalSessions?: () => {
|
|
2791
|
+
active: number;
|
|
2792
|
+
queued: number;
|
|
2793
|
+
maxConcurrent: number;
|
|
2794
|
+
runs: Array<{
|
|
2795
|
+
runId: string;
|
|
2796
|
+
skillId: string;
|
|
2797
|
+
startedAt: string;
|
|
2798
|
+
}>;
|
|
2799
|
+
};
|
|
2088
2800
|
}
|
|
2089
2801
|
interface AssetWriteHandlerResult {
|
|
2090
2802
|
status: 200 | 400 | 502;
|
|
2091
2803
|
body: unknown;
|
|
2092
2804
|
}
|
|
2805
|
+
interface DeliverHandlerResult {
|
|
2806
|
+
status: 200 | 400 | 404 | 422 | 502;
|
|
2807
|
+
body: unknown;
|
|
2808
|
+
}
|
|
2093
2809
|
/**
|
|
2094
2810
|
* Dispatch envelope received from the sandbox controller proxy. The schema
|
|
2095
2811
|
* mirrors `DaemonDispatchSchema` in `infra/sandbox-controller/src/api/v1/
|
|
@@ -2177,6 +2893,16 @@ interface LocalServerState {
|
|
|
2177
2893
|
name: string;
|
|
2178
2894
|
ready: boolean;
|
|
2179
2895
|
version?: string;
|
|
2896
|
+
/**
|
|
2897
|
+
* Release 201 v2.0.7 P1 — pinned binary version range from
|
|
2898
|
+
* `adapters/known-versions.ts`. `minVersion` is the lowest upstream
|
|
2899
|
+
* the wrapper has actively run against; `knownGood` is the rev
|
|
2900
|
+
* exercised by the current cookbook + CI smoke. Both are surfaced
|
|
2901
|
+
* verbatim so cloud-side debug-pipeline can flag drift between the
|
|
2902
|
+
* detected `version` and what we've tested.
|
|
2903
|
+
*/
|
|
2904
|
+
minVersion?: string;
|
|
2905
|
+
knownGood?: string;
|
|
2180
2906
|
}>;
|
|
2181
2907
|
/**
|
|
2182
2908
|
* Resource snapshot (Release 200 §5.4 + 08 §175). v200 baseline returns
|
|
@@ -2223,7 +2949,7 @@ declare class LocalServer {
|
|
|
2223
2949
|
*
|
|
2224
2950
|
* Walks `snapshotRoot` (default `/workspace`), computes per-file
|
|
2225
2951
|
* sha256 + sizeBytes + mtime, returns `{ files: [...], rootPath }`.
|
|
2226
|
-
* Skips dotfiles + the
|
|
2952
|
+
* Skips dotfiles + the `<artifacts|_outbox|result>/_uploaded` reserved subdir. Phase 1
|
|
2227
2953
|
* caller (cloud or controller) is responsible for POSTing the result
|
|
2228
2954
|
* to `/api/sandboxes/:id/snapshot/manifest`.
|
|
2229
2955
|
*/
|
|
@@ -2245,6 +2971,19 @@ declare class LocalServer {
|
|
|
2245
2971
|
* 502 on cloud upstream failure; 501 if no sink wired.
|
|
2246
2972
|
*/
|
|
2247
2973
|
private handleAssetWrite;
|
|
2974
|
+
/**
|
|
2975
|
+
* POST /local/deliver — release202/09 P2 explicit file delivery.
|
|
2976
|
+
*
|
|
2977
|
+
* Body: { taskId, path, mode: 'attach' | 'send' | 'task-attach' | 'message-attach', conversationId?, messageId? }
|
|
2978
|
+
* 200: { ok: true, assetId }
|
|
2979
|
+
* 400 invalid body; 404 file not found; 422 policy/magic-bytes rejection;
|
|
2980
|
+
* 502 cloud upstream failure; 501 if no sink wired.
|
|
2981
|
+
*
|
|
2982
|
+
* The daemon-side `onDeliver` sink (daemon/asset/deliver.ts) owns the
|
|
2983
|
+
* upload (via ArtifactsWatcher.deliverFile, daemon credential) and the
|
|
2984
|
+
* attach-vs-send branch.
|
|
2985
|
+
*/
|
|
2986
|
+
private handleDeliver;
|
|
2248
2987
|
/**
|
|
2249
2988
|
* POST /dispatch — external channel message → hosted agent dispatch.
|
|
2250
2989
|
*
|
|
@@ -2297,8 +3036,12 @@ declare class Runner extends EventEmitter {
|
|
|
2297
3036
|
private servicePool;
|
|
2298
3037
|
private shellConfig;
|
|
2299
3038
|
private localServer?;
|
|
2300
|
-
private
|
|
3039
|
+
private evalRunner?;
|
|
3040
|
+
private artifactsWatcher?;
|
|
2301
3041
|
private memoryWiring?;
|
|
3042
|
+
private runSessionRegistry?;
|
|
3043
|
+
private runCheckpointStore?;
|
|
3044
|
+
private hermesSessionMapper?;
|
|
2302
3045
|
private assetMetadataIndexes;
|
|
2303
3046
|
private workspaceMirrors;
|
|
2304
3047
|
private assetOriginOutbox?;
|
|
@@ -2321,10 +3064,21 @@ declare class Runner extends EventEmitter {
|
|
|
2321
3064
|
private taskReaperTimer?;
|
|
2322
3065
|
private skillResyncTimer?;
|
|
2323
3066
|
private skillSyncInFlight;
|
|
3067
|
+
private resumeInFlightTimer?;
|
|
3068
|
+
private resumeInFlightDone;
|
|
2324
3069
|
private pendingReplyCache;
|
|
2325
3070
|
private pendingReplyRecoveryDone;
|
|
2326
3071
|
constructor(opts?: RunnerOptions);
|
|
2327
3072
|
start(): Promise<void>;
|
|
3073
|
+
/**
|
|
3074
|
+
* v2.1 §9.5 — build a ProfileResolver backed by the daemon's local
|
|
3075
|
+
* `agent_profiles` mirror. Used by the hook server to translate
|
|
3076
|
+
* `?profile=<name>` query into agentImUserId + workspaceId + role slug
|
|
3077
|
+
* when the run-session registry doesn't yet have the run mapping
|
|
3078
|
+
* (e.g. for the very first pre_llm_call of a session, before the
|
|
3079
|
+
* adapter has had a chance to call register()).
|
|
3080
|
+
*/
|
|
3081
|
+
private buildProfileResolver;
|
|
2328
3082
|
/**
|
|
2329
3083
|
* F16 (2026-05-20) — enumerate every non-deleted local agent_profile and
|
|
2330
3084
|
* fan-out `syncInstalledSkillsForDispatch` via `syncAllAgentSkills`.
|
|
@@ -2334,6 +3088,62 @@ declare class Runner extends EventEmitter {
|
|
|
2334
3088
|
private syncAllSkillsBackground;
|
|
2335
3089
|
/** F16 — read all live agent_profiles from local DB → AgentProfile[]. */
|
|
2336
3090
|
private loadAllProfiles;
|
|
3091
|
+
/**
|
|
3092
|
+
* P0-2 (2026-05-25) — daemon cold-start sweep.
|
|
3093
|
+
*
|
|
3094
|
+
* Pulls `IMTaskRun.status='running'` rows where the bound daemon (via
|
|
3095
|
+
* `IMAgentBinding.boundDaemonId`) is this daemon, then re-enqueues each
|
|
3096
|
+
* via the same `onTaskDispatch` handler the ws path uses. Replaces the
|
|
3097
|
+
* slow (~5min) cloud-side `sweepTimedOut()` fallback for pod restarts.
|
|
3098
|
+
*
|
|
3099
|
+
* Idempotent on the daemon side: `onTaskDispatch` dedupes by taskId
|
|
3100
|
+
* against `runningTasks`, so any task that happened to be redispatched
|
|
3101
|
+
* from cloud immediately after our reconnect (via redispatchPending on
|
|
3102
|
+
* the agent.host.declare path) won't double-trigger here.
|
|
3103
|
+
*
|
|
3104
|
+
* Caveat: if the agent was mid-LLM-call when the daemon crashed, the
|
|
3105
|
+
* resumed dispatch starts the call from scratch — token cost duplicated.
|
|
3106
|
+
* We accept that vs the alternative (5min of silence + cloud marks the
|
|
3107
|
+
* run `failed` without any retry).
|
|
3108
|
+
*/
|
|
3109
|
+
private resumeInFlightTasks;
|
|
3110
|
+
/**
|
|
3111
|
+
* release201/26 Phase 4 — daemon-local checkpoint resume scan.
|
|
3112
|
+
*
|
|
3113
|
+
* Looks at `local_run_checkpoints` (phase-level). A run that still has
|
|
3114
|
+
* checkpoints at boot means the daemon died before dispatch.ts reached its
|
|
3115
|
+
* terminal `finally` (which deletes them). For each:
|
|
3116
|
+
*
|
|
3117
|
+
* - adapter registered + healthy → RESUMABLE. The cloud-side sweep
|
|
3118
|
+
* (resumeInFlightTasks, which ran just before this) already re-dispatches
|
|
3119
|
+
* in-flight runs from cloud truth — that fresh dispatch writes new
|
|
3120
|
+
* checkpoints — so here we only confirm resumability, count it, and clear
|
|
3121
|
+
* the stale checkpoint. onResume is a confirm/log step, not a second
|
|
3122
|
+
* dispatch (onTaskDispatch would dedupe anyway).
|
|
3123
|
+
* - adapter missing / unhealthy → emit `task.dispatch.resume_failed` so
|
|
3124
|
+
* cloud marks IMTaskRun.status='resume_failed' and the chat strip renders
|
|
3125
|
+
* "task interrupted, retry".
|
|
3126
|
+
*
|
|
3127
|
+
* Best-effort + one-shot in spirit (the scan clears each run's checkpoints, so
|
|
3128
|
+
* a re-invocation is a no-op). Requires ws so resume_failed can be sent.
|
|
3129
|
+
*/
|
|
3130
|
+
private resumeFromCheckpoints;
|
|
3131
|
+
/**
|
|
3132
|
+
* release201/26 §9 — emit daemon_run_resume_total{result} (and, on failure,
|
|
3133
|
+
* task_dispatch_resume_failed_total). Fire-and-forget; the cloud /batch
|
|
3134
|
+
* endpoint requires workspaceId, so we attach this daemon's bound workspace
|
|
3135
|
+
* (best-effort — when unknown the event is dropped by cloud, which is fine:
|
|
3136
|
+
* an unscoped daemon has no run to attribute).
|
|
3137
|
+
*/
|
|
3138
|
+
private emitResumeMetric;
|
|
3139
|
+
/**
|
|
3140
|
+
* Rebuild a `task.dispatch.request` payload from an in-flight IMTaskRun
|
|
3141
|
+
* row + its parent IMTask. Mirrors what cloud-side
|
|
3142
|
+
* v19x-helpers.buildTaskDispatchRequest does, with one extra field:
|
|
3143
|
+
* `metadata.resumed = true` so downstream prompt injection can note
|
|
3144
|
+
* this is a recovery dispatch.
|
|
3145
|
+
*/
|
|
3146
|
+
private reconstructDispatchPayload;
|
|
2337
3147
|
stop(): Promise<void>;
|
|
2338
3148
|
isRunning(): boolean;
|
|
2339
3149
|
/**
|
|
@@ -2424,10 +3234,30 @@ declare class Runner extends EventEmitter {
|
|
|
2424
3234
|
* validation logic doesn't trip on an unknown field.
|
|
2425
3235
|
*/
|
|
2426
3236
|
private onWebhookDispatch;
|
|
3237
|
+
/**
|
|
3238
|
+
* release201/24 §3 — handle a cloud-pushed eval run. Ack immediately over
|
|
3239
|
+
* the reverse channel (so cloud's WsRpcService settles), then run the eval
|
|
3240
|
+
* asynchronously. Per-case results are POSTed by EvalSessionRunner.onFinish.
|
|
3241
|
+
*/
|
|
3242
|
+
private onEvalRequest;
|
|
2427
3243
|
private onHostAcked;
|
|
2428
3244
|
private applyHostAckOwnershipLock;
|
|
2429
3245
|
private onTaskDispatch;
|
|
2430
3246
|
private onTaskCancel;
|
|
3247
|
+
/**
|
|
3248
|
+
* release201/25 §16.4 A6 — additionally call hermes-native
|
|
3249
|
+
* `POST /v1/runs/{runId}/approval` so hermes-internal HITL state
|
|
3250
|
+
* (session-level "always" cache, pending approval timer) aligns with
|
|
3251
|
+
* the cloud-side decision. The cloud-side redispatch (approval.decided)
|
|
3252
|
+
* is still the authoritative continuation; this is the SECOND write
|
|
3253
|
+
* to keep hermes in sync.
|
|
3254
|
+
*
|
|
3255
|
+
* Best-effort and tolerant: any failure (no runId / no hermes service /
|
|
3256
|
+
* capability missing / hermes 4xx) is logged but never propagated. The
|
|
3257
|
+
* agent will still receive its `approval.decided` task dispatch.
|
|
3258
|
+
*/
|
|
3259
|
+
private onTaskApprovalResolve;
|
|
3260
|
+
private onTaskClarifyResolve;
|
|
2431
3261
|
private findMessageDispatchAgent;
|
|
2432
3262
|
private postMessageDispatchReply;
|
|
2433
3263
|
/**
|
|
@@ -2447,6 +3277,26 @@ declare class Runner extends EventEmitter {
|
|
|
2447
3277
|
private syncProfileFromCloud;
|
|
2448
3278
|
private resolveOwnedAgent;
|
|
2449
3279
|
private onWorkspaceChanged;
|
|
3280
|
+
/**
|
|
3281
|
+
* release201/09 §9.4b — wipe local hermes profile memories + per-agent
|
|
3282
|
+
* memory dir for every agent the cloud says belonged to the cleared
|
|
3283
|
+
* workspace. Cloud has already deleted the cloud-side rows (cascade
|
|
3284
|
+
* ordering: cloud-first, daemon-second), so this fan-out is purely
|
|
3285
|
+
* local-FS cleanup. Best-effort: every failure stderr-logs and continues.
|
|
3286
|
+
*
|
|
3287
|
+
* Resolution: iterate local agent_profiles rows whose agent_im_user_id
|
|
3288
|
+
* appears in payload.agentImUserIds; for each, derive the hermes profile
|
|
3289
|
+
* name via getHermesProfileName (same call site spawn / configure uses)
|
|
3290
|
+
* and call wipeHermesProfileMemory. Then for every agent_im_user_id,
|
|
3291
|
+
* wipe ~/.prismer/devices/<did>/agents/<aid>/memory/* (skills/ stays).
|
|
3292
|
+
*
|
|
3293
|
+
* We do NOT delete agent_profiles rows from local SQLite here — that
|
|
3294
|
+
* happens via the existing agent_profile.changed (delete) flow which the
|
|
3295
|
+
* cloud also emits as part of workspace clear (im_agent_profiles rows
|
|
3296
|
+
* are deleted by clearWorkspaceCascade). This handler is purely the
|
|
3297
|
+
* filesystem-layer counterpart of those Prisma deletes.
|
|
3298
|
+
*/
|
|
3299
|
+
private onWorkspaceClearDaemonCleanup;
|
|
2450
3300
|
private onAssetChanged;
|
|
2451
3301
|
private onWorkspaceFileChanged;
|
|
2452
3302
|
private snapshotAdapterObservability;
|
|
@@ -2554,13 +3404,13 @@ declare const CCConfigSchema: z.ZodObject<{
|
|
|
2554
3404
|
}, "strip", z.ZodTypeAny, {
|
|
2555
3405
|
name: string;
|
|
2556
3406
|
command: string;
|
|
2557
|
-
env?: Record<string, string> | undefined;
|
|
2558
3407
|
args?: string[] | undefined;
|
|
3408
|
+
env?: Record<string, string> | undefined;
|
|
2559
3409
|
}, {
|
|
2560
3410
|
name: string;
|
|
2561
3411
|
command: string;
|
|
2562
|
-
env?: Record<string, string> | undefined;
|
|
2563
3412
|
args?: string[] | undefined;
|
|
3413
|
+
env?: Record<string, string> | undefined;
|
|
2564
3414
|
}>, "many">>;
|
|
2565
3415
|
allowedTools: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
2566
3416
|
maxTurns: z.ZodDefault<z.ZodNumber>;
|
|
@@ -2575,8 +3425,8 @@ declare const CCConfigSchema: z.ZodObject<{
|
|
|
2575
3425
|
mcpServers?: {
|
|
2576
3426
|
name: string;
|
|
2577
3427
|
command: string;
|
|
2578
|
-
env?: Record<string, string> | undefined;
|
|
2579
3428
|
args?: string[] | undefined;
|
|
3429
|
+
env?: Record<string, string> | undefined;
|
|
2580
3430
|
}[] | undefined;
|
|
2581
3431
|
systemPrompt?: string | undefined;
|
|
2582
3432
|
allowedTools?: string[] | undefined;
|
|
@@ -2589,8 +3439,8 @@ declare const CCConfigSchema: z.ZodObject<{
|
|
|
2589
3439
|
mcpServers?: {
|
|
2590
3440
|
name: string;
|
|
2591
3441
|
command: string;
|
|
2592
|
-
env?: Record<string, string> | undefined;
|
|
2593
3442
|
args?: string[] | undefined;
|
|
3443
|
+
env?: Record<string, string> | undefined;
|
|
2594
3444
|
}[] | undefined;
|
|
2595
3445
|
systemPrompt?: string | undefined;
|
|
2596
3446
|
allowedTools?: string[] | undefined;
|
|
@@ -2628,20 +3478,59 @@ declare const CodexConfigSchema: z.ZodObject<{
|
|
|
2628
3478
|
* scoped key under a different name.
|
|
2629
3479
|
*/
|
|
2630
3480
|
apiKeyEnv: z.ZodDefault<z.ZodString>;
|
|
3481
|
+
/**
|
|
3482
|
+
* release202/03 §3.2 + 07 — route Codex through our cloud gateway instead of
|
|
3483
|
+
* the official OpenAI endpoint. When set, the adapter writes a per-dispatch
|
|
3484
|
+
* `CODEX_HOME/config.toml` pointing `model_provider=prismer` with
|
|
3485
|
+
* `wire_api="responses"` and a `sk-prismer-*` bearer at:
|
|
3486
|
+
* - `newapi` (or default) → `<PRISMER_BASE_URL>/api/v1` (→ /api/v1/responses)
|
|
3487
|
+
* - any other chain id → `<PRISMER_BASE_URL>/api/v1/proxy/<chain>` (→ /api/v1/proxy/<chain>/responses)
|
|
3488
|
+
* The cloud bridge translates Responses↔Chat and walks the selected provider
|
|
3489
|
+
* chain (07). release202/07 widened this from the old `'newapi'|'deepseek'`
|
|
3490
|
+
* enum to ANY configured chain id. Undefined = official OpenAI endpoint.
|
|
3491
|
+
*/
|
|
3492
|
+
proxyProvider: z.ZodOptional<z.ZodString>;
|
|
3493
|
+
/** Env var holding the sk-prismer-* key (default PRISMER_API_KEY). */
|
|
3494
|
+
prismerApiKeyEnv: z.ZodDefault<z.ZodString>;
|
|
3495
|
+
/**
|
|
3496
|
+
* release202/05 C2 — per-(conversation × agent) session continuity. When true
|
|
3497
|
+
* (default), the adapter persists codex session files (drops `--ephemeral`)
|
|
3498
|
+
* and, on subsequent turns of the same conversation, resumes the prior
|
|
3499
|
+
* codex thread via `codex exec resume <thread_id>` so context carries across
|
|
3500
|
+
* turns instead of re-bootstrapping every dispatch.
|
|
3501
|
+
*
|
|
3502
|
+
* Empirically verified (codex-cli 0.133.0, 2026-06-02): a fresh `codex exec`
|
|
3503
|
+
* emits `{"type":"thread.started","thread_id":"<uuid>"}`; `codex exec resume
|
|
3504
|
+
* --json --skip-git-repo-check <thread_id> "<prompt>"` reloads that thread and
|
|
3505
|
+
* recalls prior context. NOTE: `--sandbox`/`--cd` are NOT accepted on the
|
|
3506
|
+
* `resume` subcommand (the help lists them but the parser rejects them when a
|
|
3507
|
+
* positional SESSION_ID is present); sandbox is inherited from the persisted
|
|
3508
|
+
* session, so resume turns reuse turn-1's sandbox/cwd.
|
|
3509
|
+
*
|
|
3510
|
+
* Set false to keep the legacy `--ephemeral` one-shot behavior (no session
|
|
3511
|
+
* files, no resume).
|
|
3512
|
+
*/
|
|
3513
|
+
sessionContinuity: z.ZodDefault<z.ZodBoolean>;
|
|
2631
3514
|
}, "strip", z.ZodTypeAny, {
|
|
2632
3515
|
sandbox: "read-only" | "workspace-write" | "danger-full-access";
|
|
2633
3516
|
model: string;
|
|
3517
|
+
prismerApiKeyEnv: string;
|
|
2634
3518
|
cwd: string;
|
|
2635
3519
|
apiKeyEnv: string;
|
|
3520
|
+
sessionContinuity: boolean;
|
|
3521
|
+
proxyProvider?: string | undefined;
|
|
2636
3522
|
systemPrompt?: string | undefined;
|
|
2637
3523
|
envVars?: Record<string, string> | undefined;
|
|
2638
3524
|
}, {
|
|
2639
3525
|
cwd: string;
|
|
2640
3526
|
sandbox?: "read-only" | "workspace-write" | "danger-full-access" | undefined;
|
|
2641
3527
|
model?: string | undefined;
|
|
3528
|
+
proxyProvider?: string | undefined;
|
|
3529
|
+
prismerApiKeyEnv?: string | undefined;
|
|
2642
3530
|
systemPrompt?: string | undefined;
|
|
2643
|
-
envVars?: Record<string, string> | undefined;
|
|
2644
3531
|
apiKeyEnv?: string | undefined;
|
|
3532
|
+
envVars?: Record<string, string> | undefined;
|
|
3533
|
+
sessionContinuity?: boolean | undefined;
|
|
2645
3534
|
}>;
|
|
2646
3535
|
type CodexConfig = z.infer<typeof CodexConfigSchema>;
|
|
2647
3536
|
/**
|