comisai 1.0.14 → 1.0.15
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/node_modules/@comis/agent/dist/bootstrap/index.d.ts +1 -1
- package/node_modules/@comis/agent/dist/bootstrap/index.js +1 -1
- package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.d.ts +26 -0
- package/node_modules/@comis/agent/dist/bootstrap/system-prompt-assembler.js +86 -54
- package/node_modules/@comis/agent/dist/bootstrap/types.d.ts +8 -2
- package/node_modules/@comis/agent/dist/bootstrap/workspace-loader.d.ts +12 -0
- package/node_modules/@comis/agent/dist/bootstrap/workspace-loader.js +21 -0
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +2 -0
- package/node_modules/@comis/agent/dist/executor/prompt-assembly.d.ts +8 -1
- package/node_modules/@comis/agent/dist/executor/prompt-assembly.js +22 -5
- package/node_modules/@comis/agent/dist/session/comis-session-manager.js +7 -2
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/dist/doctor/checks/channel-health.js +2 -2
- package/node_modules/@comis/cli/dist/wizard/index.d.ts +2 -3
- package/node_modules/@comis/cli/dist/wizard/index.js +2 -3
- package/node_modules/@comis/cli/dist/wizard/steps/10-write-config.js +1 -1
- package/node_modules/@comis/cli/dist/wizard/types.d.ts +1 -2
- package/node_modules/@comis/cli/dist/wizard/types.js +1 -2
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/config/schema-agent.d.ts +54 -10
- package/node_modules/@comis/core/dist/config/schema-agent.js +11 -0
- package/node_modules/@comis/core/dist/config/schema.d.ts +19 -14
- package/node_modules/@comis/core/dist/event-bus/events-infra.d.ts +8 -0
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/dist/daemon.js +2 -1
- package/node_modules/@comis/daemon/dist/wiring/setup-channels.js +19 -2
- package/node_modules/@comis/daemon/dist/wiring/setup-heartbeat.js +10 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-memory.d.ts +2 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-memory.js +15 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-schedulers.js +1 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-shutdown.d.ts +1 -0
- package/node_modules/@comis/daemon/dist/wiring/setup-shutdown.js +4 -0
- package/node_modules/@comis/daemon/package.json +1 -1
- package/node_modules/@comis/gateway/package.json +1 -1
- package/node_modules/@comis/infra/package.json +1 -1
- package/node_modules/@comis/memory/package.json +1 -1
- package/node_modules/@comis/scheduler/dist/cron/cron-types.d.ts +11 -0
- package/node_modules/@comis/scheduler/dist/cron/cron-types.js +11 -0
- package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.d.ts +26 -1
- package/node_modules/@comis/scheduler/dist/heartbeat/agent-heartbeat-source.js +23 -2
- package/node_modules/@comis/scheduler/dist/heartbeat/heartbeat-config.d.ts +7 -0
- package/node_modules/@comis/scheduler/dist/heartbeat/heartbeat-config.js +2 -0
- package/node_modules/@comis/scheduler/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +1 -1
- package/node_modules/@comis/skills/dist/index.d.ts +1 -1
- package/node_modules/@comis/skills/dist/index.js +1 -1
- package/node_modules/@comis/skills/dist/policy/tool-policy.js +25 -0
- package/node_modules/@comis/skills/package.json +1 -1
- package/package.json +12 -12
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { type BootstrapFile, type TruncationResult, type PromptMode, type RuntimeInfo, type InboundMetadata, type BootstrapContextFile, SUBAGENT_BOOTSTRAP_ALLOWLIST, BOOTSTRAP_HEAD_RATIO, BOOTSTRAP_TAIL_RATIO, } from "./types.js";
|
|
2
|
-
export { loadWorkspaceBootstrapFiles, truncateFileContent, filterBootstrapFilesForSubAgent, filterBootstrapFilesForLightContext, filterBootstrapFilesForGroupChat, buildBootstrapContextFiles, } from "./workspace-loader.js";
|
|
2
|
+
export { loadWorkspaceBootstrapFiles, truncateFileContent, filterBootstrapFilesForSubAgent, filterBootstrapFilesForLightContext, filterBootstrapFilesForCron, filterBootstrapFilesForGroupChat, buildBootstrapContextFiles, } from "./workspace-loader.js";
|
|
3
3
|
export * from "./sections/index.js";
|
|
4
4
|
export { extractMarkdownSections, MAX_POST_COMPACTION_CHARS } from "./section-extractor.js";
|
|
5
5
|
export { assembleRichSystemPrompt, assembleRichSystemPromptBlocks, SECTION_SEPARATOR } from "./system-prompt-assembler.js";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// Bootstrap — workspace file loading & system prompt assembly
|
|
3
3
|
export { SUBAGENT_BOOTSTRAP_ALLOWLIST, BOOTSTRAP_HEAD_RATIO, BOOTSTRAP_TAIL_RATIO, } from "./types.js";
|
|
4
|
-
export { loadWorkspaceBootstrapFiles, truncateFileContent, filterBootstrapFilesForSubAgent, filterBootstrapFilesForLightContext, filterBootstrapFilesForGroupChat, buildBootstrapContextFiles, } from "./workspace-loader.js";
|
|
4
|
+
export { loadWorkspaceBootstrapFiles, truncateFileContent, filterBootstrapFilesForSubAgent, filterBootstrapFilesForLightContext, filterBootstrapFilesForCron, filterBootstrapFilesForGroupChat, buildBootstrapContextFiles, } from "./workspace-loader.js";
|
|
5
5
|
export * from "./sections/index.js";
|
|
6
6
|
export { extractMarkdownSections, MAX_POST_COMPACTION_CHARS } from "./section-extractor.js";
|
|
7
7
|
export { assembleRichSystemPrompt, assembleRichSystemPromptBlocks, SECTION_SEPARATOR } from "./system-prompt-assembler.js";
|
|
@@ -82,6 +82,32 @@ export interface AssemblerParams {
|
|
|
82
82
|
/** Whether Silent Execution Planner (SEP) is enabled for this agent. */
|
|
83
83
|
sepEnabled?: boolean;
|
|
84
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* Internal descriptor for a system prompt section.
|
|
87
|
+
*
|
|
88
|
+
* Engineering notes:
|
|
89
|
+
* - `id` must be unique across SECTIONS and stable (used by tests).
|
|
90
|
+
* - `includeIn` must be non-empty.
|
|
91
|
+
* - `build` receives `(params, mode)` and is responsible for forwarding
|
|
92
|
+
* `mode === "minimal"` as the existing builders' `isMinimal` parameter.
|
|
93
|
+
*
|
|
94
|
+
* @internal exported for tests only
|
|
95
|
+
*/
|
|
96
|
+
export interface SectionDescriptor {
|
|
97
|
+
readonly id: string;
|
|
98
|
+
readonly includeIn: ReadonlySet<PromptMode>;
|
|
99
|
+
readonly build: (params: AssemblerParams, mode: PromptMode) => string[];
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Canonical section list in emission order.
|
|
103
|
+
*
|
|
104
|
+
* Order MUST match the previous hand-written `buildAllSections` so the
|
|
105
|
+
* `staticPrefix`/`attribution` index boundaries (2 + 2) continue to enclose
|
|
106
|
+
* identity+persona and safety+language respectively.
|
|
107
|
+
*
|
|
108
|
+
* @internal exported for tests only
|
|
109
|
+
*/
|
|
110
|
+
export declare const SECTIONS: ReadonlyArray<SectionDescriptor>;
|
|
85
111
|
/**
|
|
86
112
|
* Assemble a rich multi-section system prompt.
|
|
87
113
|
*
|
|
@@ -50,63 +50,92 @@ function joinSections(sections) {
|
|
|
50
50
|
const nonEmpty = sections.filter((lines) => lines.length > 0);
|
|
51
51
|
return nonEmpty.map((lines) => lines.join("\n")).join(SECTION_SEPARATOR);
|
|
52
52
|
}
|
|
53
|
+
/** Sections present in full, operational, and minimal modes.
|
|
54
|
+
* NB: builders may still self-filter to `[]` when their isMinimal flag is set. */
|
|
55
|
+
const MODES_ALL = new Set(["full", "operational", "minimal"]);
|
|
56
|
+
/** Sections present in full and minimal modes (stripped in operational).
|
|
57
|
+
* Interactive-only guidance that doesn't apply to autonomous cron/heartbeat runs
|
|
58
|
+
* but that minimal sub-agent contexts historically saw before this refactor.
|
|
59
|
+
* Minimal-mode builders typically self-filter to [] via their own isMinimal flag;
|
|
60
|
+
* membership here preserves pre-refactor behavior without changing minimal output. */
|
|
61
|
+
const MODES_FULL_MIN = new Set(["full", "minimal"]);
|
|
62
|
+
/** Sections present only in full mode (stripped in operational AND minimal).
|
|
63
|
+
* Reserved for sections whose builder is cheap but whose output is not desired
|
|
64
|
+
* in either non-interactive context. Currently unused; MODES_FULL_MIN is
|
|
65
|
+
* preferred to preserve pre-refactor minimal output. */
|
|
66
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- reserved for future use
|
|
67
|
+
const MODES_FULL = new Set(["full"]);
|
|
53
68
|
/**
|
|
54
|
-
*
|
|
69
|
+
* Canonical section list in emission order.
|
|
70
|
+
*
|
|
71
|
+
* Order MUST match the previous hand-written `buildAllSections` so the
|
|
72
|
+
* `staticPrefix`/`attribution` index boundaries (2 + 2) continue to enclose
|
|
73
|
+
* identity+persona and safety+language respectively.
|
|
74
|
+
*
|
|
75
|
+
* @internal exported for tests only
|
|
76
|
+
*/
|
|
77
|
+
export const SECTIONS = [
|
|
78
|
+
// --- Static prefix block (indices 0-1 in every mode that includes them) ---
|
|
79
|
+
{ id: "identity", includeIn: MODES_ALL, build: (p) => buildIdentitySection(p.agentName ?? "Comis") },
|
|
80
|
+
{ id: "persona", includeIn: MODES_ALL, build: (p) => buildPersonaSection(p.bootstrapFiles ?? []) },
|
|
81
|
+
// --- Attribution block (safety self-filters in minimal) ---
|
|
82
|
+
{ id: "safety", includeIn: MODES_ALL, build: (p, m) => buildSafetySection(m === "minimal") },
|
|
83
|
+
{ id: "language", includeIn: MODES_ALL, build: (p) => buildLanguageSection(p.userLanguage) },
|
|
84
|
+
// --- Semi-stable body: operational-kept sections (MODES_ALL -- builders self-filter for minimal) ---
|
|
85
|
+
{ id: "tooling", includeIn: MODES_ALL, build: (p, m) => buildToolingSection(p.toolNames ?? [], m === "minimal" ? "small" : "large", p.toolSummaries) },
|
|
86
|
+
{ id: "tool-call-style", includeIn: MODES_ALL, build: (p, m) => buildToolCallStyleSection(m === "minimal", p.toolNames ?? []) },
|
|
87
|
+
// --- Operational-stripped sections (MODES_FULL_MIN -- dropped in "operational") ---
|
|
88
|
+
{ id: "self-update", includeIn: MODES_FULL_MIN, build: (p, m) => buildSelfUpdateGatingSection(p.toolNames ?? [], m === "minimal", true) },
|
|
89
|
+
{ id: "config-secret", includeIn: MODES_FULL_MIN, build: (p, m) => buildConfigSecretIntegritySection(p.toolNames ?? [], m === "minimal") },
|
|
90
|
+
{ id: "privileged", includeIn: MODES_FULL_MIN, build: (p, m) => buildPrivilegedToolsSection(p.toolNames ?? [], m === "minimal", true) },
|
|
91
|
+
{ id: "compact-recover", includeIn: MODES_FULL_MIN, build: (p, m) => buildCompactedOutputRecoverySection(m === "minimal") },
|
|
92
|
+
{ id: "post-compact", includeIn: MODES_FULL_MIN, build: (p, m) => buildPostCompactionRecoverySection(p.bootstrapFiles ?? [], m === "minimal", p.postCompactionSections) },
|
|
93
|
+
{ id: "coding-fallback", includeIn: MODES_FULL_MIN, build: (p, m) => buildCodingFallbackSection(p.toolNames ?? [], m === "minimal", true) },
|
|
94
|
+
{ id: "task-delegation", includeIn: MODES_FULL_MIN, build: (p, m) => buildTaskDelegationSection(p.toolNames ?? [], m === "minimal", p.subAgentToolNames, p.mcpToolsInherited, true) },
|
|
95
|
+
// --- Operational-kept body (MODES_ALL) ---
|
|
96
|
+
{ id: "skills", includeIn: MODES_ALL, build: (p, m) => buildSkillsSection(p.skillsPrompt, m === "minimal", p.promptSkillsXml, p.activePromptSkillContent) },
|
|
97
|
+
{ id: "memory-recall", includeIn: MODES_ALL, build: (p, m) => buildMemoryRecallSection(p.hasMemoryTools ?? false, m === "minimal") },
|
|
98
|
+
{ id: "workspace", includeIn: MODES_ALL, build: (p, m) => buildWorkspaceSection(p.workspaceDir, m === "minimal") },
|
|
99
|
+
// --- Operational-stripped body ---
|
|
100
|
+
{ id: "documentation", includeIn: MODES_FULL_MIN, build: (p, m) => p.documentationConfig
|
|
101
|
+
? buildDocumentationSection(p.documentationConfig, p.toolNames ?? [], m === "minimal")
|
|
102
|
+
: [] },
|
|
103
|
+
{ id: "messaging", includeIn: MODES_ALL, build: (p, m) => buildMessagingSection(p.toolNames ?? [], m === "minimal", p.channelContext) },
|
|
104
|
+
{ id: "background", includeIn: MODES_FULL_MIN, build: (p, m) => buildBackgroundTaskSection(p.toolNames ?? [], m === "minimal", p.channelContext) },
|
|
105
|
+
{ id: "silent-replies", includeIn: MODES_FULL_MIN, build: (p, m) => buildSilentRepliesSection(m === "minimal") },
|
|
106
|
+
{ id: "heartbeats", includeIn: MODES_FULL_MIN, build: (p, m) => buildHeartbeatsSection(p.heartbeatPrompt, m === "minimal") },
|
|
107
|
+
{ id: "reactions", includeIn: MODES_FULL_MIN, build: (p, m) => buildReactionGuidanceSection(p.reactionLevel, p.channelContext?.channelType, m === "minimal") },
|
|
108
|
+
{ id: "media-sharing", includeIn: MODES_FULL_MIN, build: (p, m) => buildMediaSharingSection(p.outboundMediaEnabled, m === "minimal") },
|
|
109
|
+
{ id: "media-files", includeIn: MODES_FULL_MIN, build: (p, m) => buildMediaFilesSection(p.hasMemoryTools ?? false, (p.toolNames ?? []).includes("message"), p.workspaceDir, p.mediaPersistenceEnabled ?? false, m === "minimal") },
|
|
110
|
+
{ id: "autonomous-media", includeIn: MODES_FULL_MIN, build: (p, m) => buildAutonomousMediaSection(p.autonomousMediaEnabled ?? false, m === "minimal") },
|
|
111
|
+
{ id: "reasoning", includeIn: MODES_ALL, build: (p, m) => buildReasoningSection(p.reasoningEnabled ?? false, m === "minimal", p.reasoningTagHint ?? false) },
|
|
112
|
+
{ id: "sep", includeIn: MODES_FULL_MIN, build: (p, m) => buildTaskPlanningSection(p.sepEnabled ?? false, m === "minimal") },
|
|
113
|
+
{ id: "runtime-meta", includeIn: MODES_ALL, build: (p, m) => buildRuntimeMetadataSection(p.runtimeInfo ?? {}, m === "minimal") },
|
|
114
|
+
{ id: "sender-trust", includeIn: MODES_FULL_MIN, build: (p, m) => buildSenderTrustSection(p.senderTrustEntries ?? [], p.senderTrustDisplayMode ?? "raw", m === "minimal") },
|
|
115
|
+
{ id: "project-context", includeIn: MODES_ALL, build: (p, m) => buildProjectContextSection(p.bootstrapFiles ?? [], m === "minimal", p.excludeBootstrapFromContext ? new Set(["BOOTSTRAP.md"]) : undefined, p.workspaceProfile) },
|
|
116
|
+
];
|
|
117
|
+
/**
|
|
118
|
+
* Build all section arrays in the canonical order.
|
|
119
|
+
*
|
|
120
|
+
* Filters `SECTIONS` by mode inclusion, then builds each included descriptor.
|
|
121
|
+
* Subagent context is appended unconditionally as the last entry (matches the
|
|
122
|
+
* previous behavior).
|
|
55
123
|
*
|
|
56
124
|
* Shared by both `assembleRichSystemPrompt` and `assembleRichSystemPromptBlocks`
|
|
57
125
|
* to guarantee identity by construction between both assembly functions.
|
|
58
126
|
*
|
|
59
127
|
* @returns Array of section line arrays in fixed order
|
|
60
128
|
*/
|
|
61
|
-
function buildAllSections(params,
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
// --- Semi-stable body sections (indices 4+) ---
|
|
72
|
-
buildToolingSection(params.toolNames ?? [], modelTier, params.toolSummaries), // 3
|
|
73
|
-
buildToolCallStyleSection(isMinimal, params.toolNames ?? []), // 4
|
|
74
|
-
buildSelfUpdateGatingSection(params.toolNames ?? [], isMinimal, true), // 5: deferred to tool result
|
|
75
|
-
buildConfigSecretIntegritySection(params.toolNames ?? [], isMinimal), // 5a: always-present
|
|
76
|
-
buildPrivilegedToolsSection(params.toolNames ?? [], isMinimal, true), // 5b: deferred to tool result
|
|
77
|
-
buildCompactedOutputRecoverySection(isMinimal), // 6
|
|
78
|
-
buildPostCompactionRecoverySection(// 6a
|
|
79
|
-
params.bootstrapFiles ?? [], isMinimal, params.postCompactionSections),
|
|
80
|
-
buildCodingFallbackSection(params.toolNames ?? [], isMinimal, true), // 6b: deferred to tool result
|
|
81
|
-
buildTaskDelegationSection(params.toolNames ?? [], isMinimal, params.subAgentToolNames, params.mcpToolsInherited, true), // 6c: deferred to tool result
|
|
82
|
-
buildSkillsSection(params.skillsPrompt, isMinimal, params.promptSkillsXml, params.activePromptSkillContent), // 7: Merged filesystem + prompt skills
|
|
83
|
-
buildMemoryRecallSection(params.hasMemoryTools ?? false, isMinimal), // 8
|
|
84
|
-
buildWorkspaceSection(params.workspaceDir, isMinimal), // 9
|
|
85
|
-
params.documentationConfig
|
|
86
|
-
? buildDocumentationSection(params.documentationConfig, params.toolNames ?? [], isMinimal)
|
|
87
|
-
: [], // 9b: Documentation
|
|
88
|
-
buildMessagingSection(params.toolNames ?? [], isMinimal, params.channelContext), // 10
|
|
89
|
-
buildBackgroundTaskSection(params.toolNames ?? [], isMinimal, params.channelContext), // 11
|
|
90
|
-
buildSilentRepliesSection(isMinimal), // 14
|
|
91
|
-
buildHeartbeatsSection(params.heartbeatPrompt, isMinimal), // 15
|
|
92
|
-
buildReactionGuidanceSection(params.reactionLevel, params.channelContext?.channelType, isMinimal), // 16
|
|
93
|
-
buildMediaSharingSection(params.outboundMediaEnabled, isMinimal), // 16b
|
|
94
|
-
buildMediaFilesSection(// 16c
|
|
95
|
-
params.hasMemoryTools ?? false, (params.toolNames ?? []).includes("message"), params.workspaceDir, params.mediaPersistenceEnabled ?? false, isMinimal),
|
|
96
|
-
buildAutonomousMediaSection(params.autonomousMediaEnabled ?? false, isMinimal), // 16d
|
|
97
|
-
buildReasoningSection(params.reasoningEnabled ?? false, isMinimal, params.reasoningTagHint ?? false), // 17
|
|
98
|
-
buildTaskPlanningSection(params.sepEnabled ?? false, isMinimal), // 17b: SEP task planning (static, cache-stable)
|
|
99
|
-
// buildDateTimeSection() removed from system prompt (relocated to user-message preamble in prompt-assembly.ts)
|
|
100
|
-
buildRuntimeMetadataSection(params.runtimeInfo ?? {}, isMinimal), // 19
|
|
101
|
-
// buildInboundMetadataSection() removed from system prompt (relocated to user-message preamble in prompt-assembly.ts)
|
|
102
|
-
buildSenderTrustSection(params.senderTrustEntries ?? [], params.senderTrustDisplayMode ?? "raw", isMinimal), // 20b
|
|
103
|
-
buildProjectContextSection(// 21
|
|
104
|
-
params.bootstrapFiles ?? [], isMinimal, params.excludeBootstrapFromContext ? new Set(["BOOTSTRAP.md"]) : undefined, params.workspaceProfile),
|
|
105
|
-
// Subagent: prefer structured params, fall back to raw extraSystemPrompt
|
|
106
|
-
...(params.subagentRole
|
|
107
|
-
? [buildSubagentRoleSection(params.subagentRole)]
|
|
108
|
-
: [buildSubagentContextSection(params.extraSystemPrompt)]), // 22
|
|
109
|
-
];
|
|
129
|
+
function buildAllSections(params, mode) {
|
|
130
|
+
const base = SECTIONS
|
|
131
|
+
.filter((s) => s.includeIn.has(mode))
|
|
132
|
+
.map((s) => s.build(params, mode));
|
|
133
|
+
// Subagent section: prefer structured params, fall back to raw extraSystemPrompt.
|
|
134
|
+
// Unconditional; matches the previous hand-written emission.
|
|
135
|
+
const subagent = params.subagentRole
|
|
136
|
+
? buildSubagentRoleSection(params.subagentRole)
|
|
137
|
+
: buildSubagentContextSection(params.extraSystemPrompt);
|
|
138
|
+
return [...base, subagent];
|
|
110
139
|
}
|
|
111
140
|
/**
|
|
112
141
|
* Append additional sections (backward compat for RAG memory etc.) to a joined string.
|
|
@@ -141,8 +170,7 @@ export function assembleRichSystemPrompt(params) {
|
|
|
141
170
|
if (mode === "none") {
|
|
142
171
|
return buildIdentitySection(agentName).join("\n");
|
|
143
172
|
}
|
|
144
|
-
const
|
|
145
|
-
const allSections = buildAllSections(params, isMinimal);
|
|
173
|
+
const allSections = buildAllSections(params, mode);
|
|
146
174
|
// Filter out empty arrays, join each section's lines, then join sections
|
|
147
175
|
const joined = joinSections(allSections);
|
|
148
176
|
// Append additional sections (backward compat for RAG memory etc.)
|
|
@@ -186,9 +214,13 @@ export function assembleRichSystemPromptBlocks(params) {
|
|
|
186
214
|
semiStableBody: "",
|
|
187
215
|
};
|
|
188
216
|
}
|
|
189
|
-
const
|
|
190
|
-
const allSections = buildAllSections(params, isMinimal);
|
|
217
|
+
const allSections = buildAllSections(params, mode);
|
|
191
218
|
// Split at boundaries: identity+persona | safety+language | tooling+workspace+...
|
|
219
|
+
// Boundaries are index-based on the filtered section list. In `"full"` and
|
|
220
|
+
// `"operational"` modes the first 2 entries are identity+persona (both are
|
|
221
|
+
// in MODES_FULL_OP) and the next 2 are safety+language (MODES_ALL). In
|
|
222
|
+
// `"minimal"` mode persona is dropped, so the prefix shrinks by one and the
|
|
223
|
+
// byte-identity between full/operational is NOT expected in minimal mode.
|
|
192
224
|
const staticSections = allSections.slice(0, STATIC_PREFIX_SECTION_COUNT);
|
|
193
225
|
const attributionSections = allSections.slice(STATIC_PREFIX_SECTION_COUNT, STATIC_PREFIX_SECTION_COUNT + ATTRIBUTION_SECTION_COUNT);
|
|
194
226
|
const bodySections = allSections.slice(STATIC_PREFIX_SECTION_COUNT + ATTRIBUTION_SECTION_COUNT);
|
|
@@ -37,10 +37,16 @@ export interface TruncationResult {
|
|
|
37
37
|
* System prompt verbosity mode.
|
|
38
38
|
*
|
|
39
39
|
* - `"full"`: All workspace sections included (primary agents)
|
|
40
|
+
* - `"operational"`: All workspace sections relevant to autonomous operations;
|
|
41
|
+
* drops interactive-only guidance (compaction recovery, silent replies,
|
|
42
|
+
* heartbeats, reactions, media, SEP, sender trust). Used for cron and
|
|
43
|
+
* heartbeat executions. `staticPrefix` and `attribution` cache blocks
|
|
44
|
+
* remain byte-identical to `"full"` so the cached identity/attribution
|
|
45
|
+
* prefix is shared across modes.
|
|
40
46
|
* - `"minimal"`: Only AGENTS.md + TOOLS.md (sub-agents)
|
|
41
47
|
* - `"none"`: Identity-only prompt (lightweight contexts)
|
|
42
48
|
*/
|
|
43
|
-
export type PromptMode = "full" | "minimal" | "none";
|
|
49
|
+
export type PromptMode = "full" | "operational" | "minimal" | "none";
|
|
44
50
|
/**
|
|
45
51
|
* Runtime metadata injected into the system prompt header.
|
|
46
52
|
*/
|
|
@@ -89,7 +95,7 @@ export interface BootstrapContextFile {
|
|
|
89
95
|
* Workspace file names allowed in sub-agent bootstrap context.
|
|
90
96
|
* Sub-agents only receive AGENTS.md (instructions) and TOOLS.md (tool notes).
|
|
91
97
|
*/
|
|
92
|
-
export declare const SUBAGENT_BOOTSTRAP_ALLOWLIST: Set<"
|
|
98
|
+
export declare const SUBAGENT_BOOTSTRAP_ALLOWLIST: Set<"SOUL.md" | "IDENTITY.md" | "USER.md" | "AGENTS.md" | "ROLE.md" | "TOOLS.md" | "HEARTBEAT.md" | "BOOTSTRAP.md" | "BOOT.md">;
|
|
93
99
|
/** Head portion ratio for truncation (first 70% of maxChars) */
|
|
94
100
|
export declare const BOOTSTRAP_HEAD_RATIO = 0.7;
|
|
95
101
|
/** Tail portion ratio for truncation (last 20% of maxChars) */
|
|
@@ -87,6 +87,18 @@ export declare function filterBootstrapFilesForSubAgent(files: BootstrapFile[]):
|
|
|
87
87
|
* @returns Filtered array containing only HEARTBEAT.md
|
|
88
88
|
*/
|
|
89
89
|
export declare function filterBootstrapFilesForLightContext(files: BootstrapFile[]): BootstrapFile[];
|
|
90
|
+
/**
|
|
91
|
+
* Filter bootstrap files for cron execution.
|
|
92
|
+
*
|
|
93
|
+
* Autonomous cron runs don't need heartbeat cadence rules, user preferences,
|
|
94
|
+
* tooling docs, or workspace bootstrap -- only the agent's persona (SOUL.md)
|
|
95
|
+
* and role behavior (ROLE.md). Mirrors the pattern of
|
|
96
|
+
* filterBootstrapFilesForLightContext.
|
|
97
|
+
*
|
|
98
|
+
* @param files - Full array of loaded bootstrap files
|
|
99
|
+
* @returns Filtered array containing only SOUL.md and ROLE.md
|
|
100
|
+
*/
|
|
101
|
+
export declare function filterBootstrapFilesForCron(files: BootstrapFile[]): BootstrapFile[];
|
|
90
102
|
/**
|
|
91
103
|
* Filter bootstrap files for group chat context.
|
|
92
104
|
*
|
|
@@ -136,6 +136,27 @@ const HEARTBEAT_LIGHT_ALLOWLIST = new Set(["HEARTBEAT.md"]);
|
|
|
136
136
|
export function filterBootstrapFilesForLightContext(files) {
|
|
137
137
|
return files.filter((f) => HEARTBEAT_LIGHT_ALLOWLIST.has(f.name));
|
|
138
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Allowlist for cron execution context.
|
|
141
|
+
* Retains ONLY SOUL.md and ROLE.md -- the persona and role behavior needed
|
|
142
|
+
* for autonomous cron runs. Strips heartbeat cadence rules, user preferences,
|
|
143
|
+
* tooling docs, and workspace bootstrap.
|
|
144
|
+
*/
|
|
145
|
+
const CRON_BOOTSTRAP_ALLOWLIST = new Set(["SOUL.md", "ROLE.md"]);
|
|
146
|
+
/**
|
|
147
|
+
* Filter bootstrap files for cron execution.
|
|
148
|
+
*
|
|
149
|
+
* Autonomous cron runs don't need heartbeat cadence rules, user preferences,
|
|
150
|
+
* tooling docs, or workspace bootstrap -- only the agent's persona (SOUL.md)
|
|
151
|
+
* and role behavior (ROLE.md). Mirrors the pattern of
|
|
152
|
+
* filterBootstrapFilesForLightContext.
|
|
153
|
+
*
|
|
154
|
+
* @param files - Full array of loaded bootstrap files
|
|
155
|
+
* @returns Filtered array containing only SOUL.md and ROLE.md
|
|
156
|
+
*/
|
|
157
|
+
export function filterBootstrapFilesForCron(files) {
|
|
158
|
+
return files.filter((f) => CRON_BOOTSTRAP_ALLOWLIST.has(f.name));
|
|
159
|
+
}
|
|
139
160
|
/**
|
|
140
161
|
* Excludelist for group chat context mode.
|
|
141
162
|
* Excludes USER.md (privacy protection: personal preferences
|
|
@@ -169,6 +169,8 @@ export async function assembleTools(params) {
|
|
|
169
169
|
resolvedModelId: resolvedModel?.id,
|
|
170
170
|
resolvedModelProvider: resolvedModel?.provider,
|
|
171
171
|
resolvedModelReasoning: resolvedModel?.reasoning,
|
|
172
|
+
// "interactive" default guards the optional overrides; mirrors pi-executor.ts:1077.
|
|
173
|
+
operationType: executionOverrides?.operationType ?? "interactive",
|
|
172
174
|
});
|
|
173
175
|
// -------------------------------------------------------------------
|
|
174
176
|
// 5. System token estimate
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
-
import type { SessionKey, NormalizedMessage, PerAgentConfig, MemoryPort, HookRunner, SecretManager, EnvelopeConfig, WrapExternalContentOptions, TypedEventBus, SenderTrustDisplayConfig, SpawnPacket, DeliveryMirrorPort } from "@comis/core";
|
|
11
|
+
import type { SessionKey, NormalizedMessage, PerAgentConfig, MemoryPort, HookRunner, SecretManager, EnvelopeConfig, WrapExternalContentOptions, TypedEventBus, SenderTrustDisplayConfig, SpawnPacket, DeliveryMirrorPort, ModelOperationType } from "@comis/core";
|
|
12
12
|
import type { ComisLogger } from "@comis/infra";
|
|
13
13
|
import type { ToolDefinition } from "@mariozechner/pi-coding-agent";
|
|
14
14
|
import type { BootstrapContextFile } from "../bootstrap/types.js";
|
|
@@ -151,6 +151,13 @@ export interface PromptAssemblyParams {
|
|
|
151
151
|
/** Whether the resolved model has native reasoning support (e.g. encrypted thinking blocks).
|
|
152
152
|
* When true, the `<think>`/`<final>` tag hint is suppressed to avoid double-reasoning. */
|
|
153
153
|
resolvedModelReasoning?: boolean;
|
|
154
|
+
/** Operation type from ExecutionOverrides. Resolves promptMode and bootstrap filter.
|
|
155
|
+
* When omitted by callers at the TypeScript level, executor-tool-assembly supplies
|
|
156
|
+
* "interactive" as the default before invoking this function, so this is required
|
|
157
|
+
* at the call-site contract level. Values of "cron" or "heartbeat" auto-upgrade
|
|
158
|
+
* the promptMode from "full" to "operational" and dispatch operation-specific
|
|
159
|
+
* bootstrap filters. */
|
|
160
|
+
operationType: ModelOperationType;
|
|
154
161
|
}
|
|
155
162
|
/**
|
|
156
163
|
* Assemble the full system prompt for a PiExecutor execution cycle.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
import * as fs from "node:fs/promises";
|
|
13
13
|
import { wrapExternalContent, safePath, formatSessionKey, generateCanaryToken } from "@comis/core";
|
|
14
14
|
import { suppressError } from "@comis/shared";
|
|
15
|
-
import { loadWorkspaceBootstrapFiles, buildBootstrapContextFiles, assembleRichSystemPrompt, assembleRichSystemPromptBlocks, filterBootstrapFilesForLightContext, filterBootstrapFilesForGroupChat, resolveSenderDisplay, buildDateTimeSection, buildInboundMetadataSection, buildSenderTrustSection, buildSubagentRoleSection, // for dynamic preamble injection
|
|
15
|
+
import { loadWorkspaceBootstrapFiles, buildBootstrapContextFiles, assembleRichSystemPrompt, assembleRichSystemPromptBlocks, filterBootstrapFilesForLightContext, filterBootstrapFilesForCron, filterBootstrapFilesForGroupChat, resolveSenderDisplay, buildDateTimeSection, buildInboundMetadataSection, buildSenderTrustSection, buildSubagentRoleSection, // for dynamic preamble injection
|
|
16
16
|
buildVerbosityHintSection, resolveVerbosityProfile, } from "../bootstrap/index.js";
|
|
17
17
|
import { deduplicateResults } from "../rag/rag-retriever.js";
|
|
18
18
|
import { createHybridMemoryInjector } from "../rag/hybrid-memory-injector.js";
|
|
@@ -320,7 +320,19 @@ export async function assembleExecutionPrompt(params) {
|
|
|
320
320
|
return { systemPrompt: parentCache.frozenSystemPrompt, systemPromptBlocks: parentCache.frozenSystemPromptBlocks, dynamicPreamble, inlineMemory: undefined };
|
|
321
321
|
}
|
|
322
322
|
// 1. Resolve promptMode
|
|
323
|
-
|
|
323
|
+
// Cron and heartbeat auto-upgrade from "full" -> "operational" to trim
|
|
324
|
+
// interactive-only sections (compaction recovery, silent replies, reactions,
|
|
325
|
+
// media, SEP, sender trust). An explicit `config.bootstrap?.promptMode` wins
|
|
326
|
+
// -- operators can still force "minimal"/"none"/"full" if they have reason.
|
|
327
|
+
const baseMode = config.bootstrap?.promptMode ?? "full";
|
|
328
|
+
const promptMode = (params.operationType === "cron" || params.operationType === "heartbeat") && baseMode === "full"
|
|
329
|
+
? "operational"
|
|
330
|
+
: baseMode;
|
|
331
|
+
// Consolidated lightContext flag: heartbeat implies light-context regardless
|
|
332
|
+
// of the explicit msg.metadata.lightContext flag. Callers that only set the
|
|
333
|
+
// metadata flag OR only set operationType="heartbeat" produce identical
|
|
334
|
+
// prompt output (design-doc §Risks: "Heartbeat lightContext and operationType drift").
|
|
335
|
+
const effectiveLightContext = msg.metadata?.lightContext === true || params.operationType === "heartbeat";
|
|
324
336
|
// 2. Load workspace bootstrap files (skip for "none" mode)
|
|
325
337
|
let bootstrapContextFiles = [];
|
|
326
338
|
if (promptMode !== "none") {
|
|
@@ -337,11 +349,16 @@ export async function assembleExecutionPrompt(params) {
|
|
|
337
349
|
bootstrapFiles = await loadWorkspaceBootstrapFiles(deps.workspaceDir, bootstrapMaxChars);
|
|
338
350
|
sessionBootstrapFileSnapshots.set(bsSnapKey, bootstrapFiles);
|
|
339
351
|
}
|
|
340
|
-
//
|
|
341
|
-
|
|
352
|
+
// Bootstrap filter dispatch:
|
|
353
|
+
// - effectiveLightContext (heartbeat / explicit flag) -> HEARTBEAT.md only
|
|
354
|
+
// - operationType === "cron" -> SOUL.md + ROLE.md only
|
|
355
|
+
// - group chat context -> strip USER.md for privacy
|
|
356
|
+
if (effectiveLightContext) {
|
|
342
357
|
bootstrapFiles = filterBootstrapFilesForLightContext(bootstrapFiles);
|
|
343
358
|
}
|
|
344
|
-
|
|
359
|
+
else if (params.operationType === "cron") {
|
|
360
|
+
bootstrapFiles = filterBootstrapFilesForCron(bootstrapFiles);
|
|
361
|
+
}
|
|
345
362
|
else if (config.bootstrap?.groupChatFiltering !== false &&
|
|
346
363
|
isGroupContext(msg)) {
|
|
347
364
|
bootstrapFiles = filterBootstrapFilesForGroupChat(bootstrapFiles);
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
import { SessionManager as SdkSessionManager } from "@mariozechner/pi-coding-agent";
|
|
19
19
|
import { formatSessionKey, safePath } from "@comis/core";
|
|
20
20
|
import { suppressError } from "@comis/shared";
|
|
21
|
-
import { mkdir, unlink, rm } from "node:fs/promises";
|
|
21
|
+
import { mkdir, unlink, rm, rmdir } from "node:fs/promises";
|
|
22
22
|
import { existsSync, writeFileSync, readFileSync } from "node:fs";
|
|
23
23
|
import { dirname } from "node:path";
|
|
24
24
|
import { sessionKeyToPath } from "./session-key-mapper.js";
|
|
@@ -61,8 +61,13 @@ export function createComisSessionManager(deps) {
|
|
|
61
61
|
await unlink(sessionPath);
|
|
62
62
|
}
|
|
63
63
|
catch { /* ENOENT ok */ }
|
|
64
|
-
const
|
|
64
|
+
const sessionDir = dirname(sessionPath);
|
|
65
|
+
const toolResultsDir = safePath(sessionDir, "tool-results");
|
|
65
66
|
await suppressError(rm(toolResultsDir, { recursive: true, force: true }), "tool-results dir may not exist");
|
|
67
|
+
try {
|
|
68
|
+
await rmdir(sessionDir);
|
|
69
|
+
}
|
|
70
|
+
catch { /* non-empty or already gone */ }
|
|
66
71
|
}, { retries: 10, retryMinTimeout: 500 });
|
|
67
72
|
},
|
|
68
73
|
writeSessionMetadata(sessionKey, metadata) {
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
*
|
|
9
9
|
* @module
|
|
10
10
|
*/
|
|
11
|
-
import { CHANNEL_ENV_KEYS } from "../../wizard/
|
|
11
|
+
import { CHANNEL_ENV_KEYS } from "../../wizard/index.js";
|
|
12
12
|
const CATEGORY = "channels";
|
|
13
13
|
/**
|
|
14
14
|
* Map of channel types to their required credential environment variable names.
|
|
15
15
|
*
|
|
16
|
-
* Sourced from the shared CHANNEL_ENV_KEYS constant in
|
|
16
|
+
* Sourced from the shared CHANNEL_ENV_KEYS constant in the wizard module.
|
|
17
17
|
* These are format checks only -- we verify the credential appears to be
|
|
18
18
|
* a non-empty string, not that it's a valid API key.
|
|
19
19
|
*/
|
|
@@ -6,9 +6,8 @@
|
|
|
6
6
|
* init command, tests, future phases) imports from this single entry
|
|
7
7
|
* point rather than reaching into individual wizard files.
|
|
8
8
|
*
|
|
9
|
-
* Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts
|
|
10
|
-
*
|
|
11
|
-
* but are not part of the new wizard architecture.
|
|
9
|
+
* Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts,
|
|
10
|
+
* config-writer.ts) were removed -- superseded by the step-based architecture.
|
|
12
11
|
*
|
|
13
12
|
* @module
|
|
14
13
|
*/
|
|
@@ -7,9 +7,8 @@
|
|
|
7
7
|
* init command, tests, future phases) imports from this single entry
|
|
8
8
|
* point rather than reaching into individual wizard files.
|
|
9
9
|
*
|
|
10
|
-
* Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts
|
|
11
|
-
*
|
|
12
|
-
* but are not part of the new wizard architecture.
|
|
10
|
+
* Legacy wizard files (flow-types.ts, quickstart-flow.ts, manual-flow.ts,
|
|
11
|
+
* config-writer.ts) were removed -- superseded by the step-based architecture.
|
|
13
12
|
*
|
|
14
13
|
* @module
|
|
15
14
|
*/
|
|
@@ -17,7 +17,7 @@ import { updateState, heading, success as themeSuccess, PROVIDER_ENV_KEYS, CHANN
|
|
|
17
17
|
/**
|
|
18
18
|
* Get a sensible default model for a provider.
|
|
19
19
|
*
|
|
20
|
-
* Matches the defaults
|
|
20
|
+
* Matches the defaults used by the wizard.
|
|
21
21
|
*/
|
|
22
22
|
function getDefaultModel(provider) {
|
|
23
23
|
if (!provider)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Foundational types and constants for the init wizard redesign.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* that supports the full wizard architecture: immutable state
|
|
4
|
+
* Core type system for the wizard architecture: immutable state
|
|
6
5
|
* accumulation, structured validation, and multi-flow support.
|
|
7
6
|
*
|
|
8
7
|
* @module
|
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Foundational types and constants for the init wizard redesign.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
* that supports the full wizard architecture: immutable state
|
|
5
|
+
* Core type system for the wizard architecture: immutable state
|
|
7
6
|
* accumulation, structured validation, and multi-flow support.
|
|
8
7
|
*
|
|
9
8
|
* @module
|