comisai 1.0.13 → 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/sections/core-sections.js +4 -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 +25 -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 +20 -3
- 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";
|
|
@@ -127,7 +127,10 @@ export function buildInboundMetadataSection(meta, _isMinimal) {
|
|
|
127
127
|
"This is the metadata for the message you are currently responding to.",
|
|
128
128
|
"Do not reveal these internal identifiers to the user.",
|
|
129
129
|
];
|
|
130
|
-
if (meta.flags.
|
|
130
|
+
if (meta.flags.isCronAgentTurn) {
|
|
131
|
+
lines.push("", "**CRON AGENT TURN:** This is an autonomous scheduled execution — you were invoked by a cron job to check on something, NOT by a user message.", "Use your tools to gather current data, then decide whether there is anything worth reporting.", "If there is nothing actionable or noteworthy to report, respond with exactly NO_REPLY — the system will suppress delivery and the user will not be disturbed.", "If there IS something to report, respond with a concise, actionable message for the user.", "Do NOT use the message tool (the system delivers your response automatically).");
|
|
132
|
+
}
|
|
133
|
+
else if (meta.flags.isScheduled) {
|
|
131
134
|
lines.push("", "**SCHEDULED REMINDER:** This message is a scheduled reminder delivery, NOT a new user request.", "Your job is to deliver the reminder content to the user in a friendly, concise way.", "Do NOT ask follow-up questions, offer to reschedule, or search for context.", "Respond directly with the reminder text — do NOT use the message tool (the system delivers your response automatically).", "Do NOT respond with NO_REPLY or empty text.");
|
|
132
135
|
}
|
|
133
136
|
return lines;
|
|
@@ -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";
|
|
@@ -189,6 +189,9 @@ function buildMessageFlags(msg) {
|
|
|
189
189
|
if (meta.isScheduled === true) {
|
|
190
190
|
flags.isScheduled = true;
|
|
191
191
|
}
|
|
192
|
+
if (meta.isCronAgentTurn === true) {
|
|
193
|
+
flags.isCronAgentTurn = true;
|
|
194
|
+
}
|
|
192
195
|
return flags;
|
|
193
196
|
}
|
|
194
197
|
/**
|
|
@@ -317,7 +320,19 @@ export async function assembleExecutionPrompt(params) {
|
|
|
317
320
|
return { systemPrompt: parentCache.frozenSystemPrompt, systemPromptBlocks: parentCache.frozenSystemPromptBlocks, dynamicPreamble, inlineMemory: undefined };
|
|
318
321
|
}
|
|
319
322
|
// 1. Resolve promptMode
|
|
320
|
-
|
|
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";
|
|
321
336
|
// 2. Load workspace bootstrap files (skip for "none" mode)
|
|
322
337
|
let bootstrapContextFiles = [];
|
|
323
338
|
if (promptMode !== "none") {
|
|
@@ -334,11 +349,16 @@ export async function assembleExecutionPrompt(params) {
|
|
|
334
349
|
bootstrapFiles = await loadWorkspaceBootstrapFiles(deps.workspaceDir, bootstrapMaxChars);
|
|
335
350
|
sessionBootstrapFileSnapshots.set(bsSnapKey, bootstrapFiles);
|
|
336
351
|
}
|
|
337
|
-
//
|
|
338
|
-
|
|
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) {
|
|
339
357
|
bootstrapFiles = filterBootstrapFilesForLightContext(bootstrapFiles);
|
|
340
358
|
}
|
|
341
|
-
|
|
359
|
+
else if (params.operationType === "cron") {
|
|
360
|
+
bootstrapFiles = filterBootstrapFilesForCron(bootstrapFiles);
|
|
361
|
+
}
|
|
342
362
|
else if (config.bootstrap?.groupChatFiltering !== false &&
|
|
343
363
|
isGroupContext(msg)) {
|
|
344
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
|