comisai 1.0.18 → 1.0.22
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/dist/cli-entry.js +0 -0
- package/node_modules/@comis/agent/dist/context-engine/context-engine.js +43 -2
- package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.d.ts +51 -0
- package/node_modules/@comis/agent/dist/context-engine/signature-replay-scrubber.js +110 -0
- package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.d.ts +54 -0
- package/node_modules/@comis/agent/dist/context-engine/signature-surrogate-guard.js +145 -0
- package/node_modules/@comis/agent/dist/context-engine/types-core.d.ts +17 -0
- package/node_modules/@comis/agent/dist/executor/error-classifier.d.ts +11 -1
- package/node_modules/@comis/agent/dist/executor/error-classifier.js +13 -0
- package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.d.ts +1 -0
- package/node_modules/@comis/agent/dist/executor/executor-context-engine-setup.js +55 -0
- package/node_modules/@comis/agent/dist/executor/executor-prompt-runner.js +106 -5
- package/node_modules/@comis/agent/dist/executor/executor-tool-assembly.js +1 -0
- package/node_modules/@comis/agent/dist/executor/pi-executor.d.ts +1 -4
- package/node_modules/@comis/agent/dist/executor/replay-drift-detector.d.ts +85 -0
- package/node_modules/@comis/agent/dist/executor/replay-drift-detector.js +92 -0
- package/node_modules/@comis/agent/dist/executor/signature-block-scrubber.d.ts +34 -0
- package/node_modules/@comis/agent/dist/executor/signature-block-scrubber.js +69 -0
- package/node_modules/@comis/agent/dist/executor/signed-replay-detector.d.ts +39 -0
- package/node_modules/@comis/agent/dist/executor/signed-replay-detector.js +72 -0
- package/node_modules/@comis/agent/package.json +1 -1
- package/node_modules/@comis/channels/package.json +1 -1
- package/node_modules/@comis/cli/dist/cli.js +0 -0
- package/node_modules/@comis/cli/dist/wizard/steps/12-finish.d.ts +4 -5
- package/node_modules/@comis/cli/dist/wizard/steps/12-finish.js +99 -40
- package/node_modules/@comis/cli/package.json +1 -1
- package/node_modules/@comis/core/dist/config/git-manager.js +10 -4
- package/node_modules/@comis/core/dist/config/index.d.ts +1 -0
- package/node_modules/@comis/core/dist/config/index.js +2 -0
- package/node_modules/@comis/core/dist/config/managed-sections.d.ts +67 -0
- package/node_modules/@comis/core/dist/config/managed-sections.js +124 -0
- package/node_modules/@comis/core/dist/config/schema-agent.d.ts +28 -10
- package/node_modules/@comis/core/dist/config/schema-agent.js +6 -0
- package/node_modules/@comis/core/dist/config/schema-gateway.d.ts +2 -2
- package/node_modules/@comis/core/dist/config/schema.d.ts +65 -64
- package/node_modules/@comis/core/dist/event-bus/events-messaging.d.ts +16 -0
- package/node_modules/@comis/core/dist/exports/config.d.ts +1 -1
- package/node_modules/@comis/core/dist/exports/config.js +1 -1
- package/node_modules/@comis/core/package.json +1 -1
- package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/init-skill.py +0 -0
- package/node_modules/@comis/daemon/bundled-skills/skill-creator/scripts/validate-skill.py +0 -0
- package/node_modules/@comis/daemon/dist/daemon.js +0 -0
- package/node_modules/@comis/daemon/dist/rpc/config-handlers.js +20 -7
- package/node_modules/@comis/daemon/dist/rpc/session-handlers.js +27 -1
- 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/package.json +1 -1
- package/node_modules/@comis/shared/package.json +1 -1
- package/node_modules/@comis/skills/dist/bridge/tool-metadata-registry.js +23 -8
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.d.ts +1 -1
- package/node_modules/@comis/skills/dist/builtin/platform/gateway-tool.js +18 -14
- package/node_modules/@comis/skills/dist/builtin/platform/unified-session-tool.js +1 -1
- package/node_modules/@comis/skills/package.json +1 -1
- package/node_modules/@comis/web/package.json +1 -1
- package/package.json +24 -26
- package/node_modules/@comis/agent/dist/provider/response/strip-minimax-xml.d.ts +0 -9
- package/node_modules/@comis/agent/dist/provider/response/strip-minimax-xml.js +0 -17
- package/node_modules/@comis/agent/dist/provider/response/strip-model-tokens.d.ts +0 -13
- package/node_modules/@comis/agent/dist/provider/response/strip-model-tokens.js +0 -19
- package/node_modules/@comis/agent/dist/provider/response/strip-tool-text.d.ts +0 -11
- package/node_modules/@comis/agent/dist/provider/response/strip-tool-text.js +0 -32
- package/node_modules/@comis/agent/dist/safety/follow-through-detector.d.ts +0 -46
- package/node_modules/@comis/agent/dist/safety/follow-through-detector.js +0 -76
- package/node_modules/@comis/agent/dist/safety/post-compaction-safety.d.ts +0 -30
- package/node_modules/@comis/agent/dist/safety/post-compaction-safety.js +0 -51
- package/node_modules/@comis/agent/dist/safety/schema-normalizer.d.ts +0 -37
- package/node_modules/@comis/agent/dist/safety/schema-normalizer.js +0 -137
- package/node_modules/@comis/agent/dist/safety/schema-pruning.d.ts +0 -50
- package/node_modules/@comis/agent/dist/safety/schema-pruning.js +0 -112
- package/node_modules/@comis/agent/dist/safety/tool-image-sanitizer.d.ts +0 -43
- package/node_modules/@comis/agent/dist/safety/tool-image-sanitizer.js +0 -96
- package/node_modules/@comis/agent/dist/safety/tool-sanitizer.d.ts +0 -44
- package/node_modules/@comis/agent/dist/safety/tool-sanitizer.js +0 -94
- package/node_modules/@comis/channels/dist/shared/thinking-tag-filter.d.ts +0 -28
- package/node_modules/@comis/channels/dist/shared/thinking-tag-filter.js +0 -206
- package/node_modules/@comis/cli/dist/wizard/config-writer.d.ts +0 -25
- package/node_modules/@comis/cli/dist/wizard/config-writer.js +0 -144
- package/node_modules/@comis/cli/dist/wizard/flow-types.d.ts +0 -48
- package/node_modules/@comis/cli/dist/wizard/flow-types.js +0 -70
- package/node_modules/@comis/cli/dist/wizard/manual-flow.d.ts +0 -21
- package/node_modules/@comis/cli/dist/wizard/manual-flow.js +0 -345
- package/node_modules/@comis/cli/dist/wizard/quickstart-flow.d.ts +0 -21
- package/node_modules/@comis/cli/dist/wizard/quickstart-flow.js +0 -116
- package/node_modules/@comis/core/dist/config/schema-agent-model.d.ts +0 -135
- package/node_modules/@comis/core/dist/config/schema-agent-model.js +0 -114
- package/node_modules/@comis/core/dist/config/schema-agent-session.d.ts +0 -177
- package/node_modules/@comis/core/dist/config/schema-agent-session.js +0 -116
- package/node_modules/@comis/core/dist/config/schema-context-engine.d.ts +0 -92
- package/node_modules/@comis/core/dist/config/schema-context-engine.js +0 -92
- package/node_modules/@comis/core/dist/config/schema-context-guard.d.ts +0 -34
- package/node_modules/@comis/core/dist/config/schema-context-guard.js +0 -32
- package/node_modules/@comis/core/dist/config/schema-delivery-mirror.d.ts +0 -27
- package/node_modules/@comis/core/dist/config/schema-delivery-mirror.js +0 -26
- package/node_modules/@comis/core/dist/config/schema-delivery-queue.d.ts +0 -31
- package/node_modules/@comis/core/dist/config/schema-delivery-queue.js +0 -30
- package/node_modules/@comis/core/dist/config/schema-delivery-timing.d.ts +0 -41
- package/node_modules/@comis/core/dist/config/schema-delivery-timing.js +0 -31
- package/node_modules/@comis/core/dist/config/schema-monitoring.d.ts +0 -105
- package/node_modules/@comis/core/dist/config/schema-monitoring.js +0 -67
- package/node_modules/@comis/core/dist/ports/media-ports.d.ts +0 -278
- package/node_modules/@comis/core/dist/ports/media-ports.js +0 -1
- package/node_modules/@comis/core/dist/security/input-guard.d.ts +0 -46
- package/node_modules/@comis/core/dist/security/input-guard.js +0 -166
- package/node_modules/@comis/core/dist/security/scoped-secret-manager.d.ts +0 -38
- package/node_modules/@comis/core/dist/security/scoped-secret-manager.js +0 -94
- package/node_modules/@comis/daemon/dist/observability/delivery-context.d.ts +0 -37
- package/node_modules/@comis/daemon/dist/observability/delivery-context.js +0 -1
- package/node_modules/@comis/daemon/dist/observability/log-level-manager.d.ts +0 -23
- package/node_modules/@comis/daemon/dist/observability/log-level-manager.js +0 -34
- package/node_modules/@comis/daemon/dist/observability/log-transport.d.ts +0 -44
- package/node_modules/@comis/daemon/dist/observability/log-transport.js +0 -74
- package/node_modules/@comis/daemon/dist/observability/obs-write-buffer.d.ts +0 -53
- package/node_modules/@comis/daemon/dist/observability/obs-write-buffer.js +0 -68
- package/node_modules/@comis/daemon/dist/observability/types.d.ts +0 -6
- package/node_modules/@comis/daemon/dist/observability/types.js +0 -1
- package/node_modules/@comis/daemon/dist/wiring/seed-bundled-skills.d.ts +0 -41
- package/node_modules/@comis/daemon/dist/wiring/seed-bundled-skills.js +0 -84
- package/node_modules/@comis/daemon/dist/wiring/setup-delivery-mirror.d.ts +0 -24
- package/node_modules/@comis/daemon/dist/wiring/setup-delivery-mirror.js +0 -88
- package/node_modules/@comis/daemon/dist/wiring/setup-delivery-queue.d.ts +0 -31
- package/node_modules/@comis/daemon/dist/wiring/setup-delivery-queue.js +0 -132
- package/node_modules/@comis/daemon/dist/wiring/setup-monitoring.d.ts +0 -38
- package/node_modules/@comis/daemon/dist/wiring/setup-monitoring.js +0 -100
- package/node_modules/@comis/daemon/dist/wiring/setup-rpc-bridge.d.ts +0 -34
- package/node_modules/@comis/daemon/dist/wiring/setup-rpc-bridge.js +0 -52
- package/node_modules/@comis/daemon/dist/wiring/setup-task-extraction.d.ts +0 -41
- package/node_modules/@comis/daemon/dist/wiring/setup-task-extraction.js +0 -86
- package/node_modules/@comis/memory/dist/embedding-cache.d.ts +0 -36
- package/node_modules/@comis/memory/dist/embedding-cache.js +0 -94
- package/node_modules/@comis/skills/dist/bridge/tool-output-schemas.d.ts +0 -17
- package/node_modules/@comis/skills/dist/bridge/tool-output-schemas.js +0 -125
- package/node_modules/@comis/skills/dist/bridge/tool-parallelism-metadata.d.ts +0 -14
- package/node_modules/@comis/skills/dist/bridge/tool-parallelism-metadata.js +0 -92
- package/node_modules/@comis/skills/dist/bridge/tool-result-caps.d.ts +0 -14
- package/node_modules/@comis/skills/dist/bridge/tool-result-caps.js +0 -36
- package/node_modules/@comis/skills/dist/bridge/tool-search-hints.d.ts +0 -15
- package/node_modules/@comis/skills/dist/bridge/tool-search-hints.js +0 -68
- package/node_modules/@comis/skills/dist/bridge/tool-validators.d.ts +0 -11
- package/node_modules/@comis/skills/dist/bridge/tool-validators.js +0 -105
- package/node_modules/@comis/skills/dist/builtin/file/find-sort-wrapper.d.ts +0 -22
- package/node_modules/@comis/skills/dist/builtin/file/find-sort-wrapper.js +0 -95
- package/node_modules/@comis/skills/dist/builtin/file/grep-output-mode-wrapper.d.ts +0 -24
- package/node_modules/@comis/skills/dist/builtin/file/grep-output-mode-wrapper.js +0 -167
- package/node_modules/@comis/skills/dist/builtin/task-plan-tool.d.ts +0 -25
- package/node_modules/@comis/skills/dist/builtin/task-plan-tool.js +0 -67
- package/node_modules/@comis/skills/dist/integrations/mcp-tool-bridge.d.ts +0 -75
- package/node_modules/@comis/skills/dist/integrations/mcp-tool-bridge.js +0 -235
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Grep tool output mode wrapper.
|
|
3
|
-
*
|
|
4
|
-
* Post-processes grep tool results based on an `output_mode` parameter added
|
|
5
|
-
* at the Comis layer. The upstream SDK grep always returns full match output
|
|
6
|
-
* (file:line: content). This wrapper provides additional output formats:
|
|
7
|
-
* - `content` (default): unchanged upstream output
|
|
8
|
-
* - `files_with_matches`: deduplicated file paths only
|
|
9
|
-
* - `count`: per-file match counts, sorted by count descending
|
|
10
|
-
*
|
|
11
|
-
* @module
|
|
12
|
-
*/
|
|
13
|
-
import { Type } from "@sinclair/typebox";
|
|
14
|
-
/**
|
|
15
|
-
* Regex to extract file path and line number from grep output lines.
|
|
16
|
-
*
|
|
17
|
-
* Match lines: `filepath:linenum: content`
|
|
18
|
-
* Context lines: `filepath-linenum- content`
|
|
19
|
-
*
|
|
20
|
-
* The file path is everything before the first `:linenum:` or `-linenum-`.
|
|
21
|
-
*/
|
|
22
|
-
const MATCH_LINE_RE = /^(.+?):(\d+): /;
|
|
23
|
-
const CONTEXT_LINE_RE = /^(.+?)-(\d+)- /;
|
|
24
|
-
/** Sentinel for no-match output from pi-coding-agent grep. */
|
|
25
|
-
const NO_MATCHES = "No matches found";
|
|
26
|
-
/**
|
|
27
|
-
* Extract trailing notice lines (starting with `[`) from the output.
|
|
28
|
-
* Notices appear after a blank line at the end of grep output.
|
|
29
|
-
*/
|
|
30
|
-
function splitNotices(text) {
|
|
31
|
-
const lines = text.split("\n");
|
|
32
|
-
const notices = [];
|
|
33
|
-
// Walk backwards to find trailing notice lines
|
|
34
|
-
let i = lines.length - 1;
|
|
35
|
-
while (i >= 0 && (lines[i].startsWith("[") || lines[i].trim() === "")) {
|
|
36
|
-
if (lines[i].startsWith("[")) {
|
|
37
|
-
notices.unshift(lines[i]);
|
|
38
|
-
}
|
|
39
|
-
i--;
|
|
40
|
-
}
|
|
41
|
-
const body = lines.slice(0, i + 1).join("\n");
|
|
42
|
-
return { body, notices };
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Parse grep output into file-path-keyed match counts.
|
|
46
|
-
* Only counts actual match lines (`:linenum: `), not context lines (`-linenum- `).
|
|
47
|
-
*/
|
|
48
|
-
function countMatchesByFile(body) {
|
|
49
|
-
const counts = new Map();
|
|
50
|
-
for (const line of body.split("\n")) {
|
|
51
|
-
const match = MATCH_LINE_RE.exec(line);
|
|
52
|
-
if (match) {
|
|
53
|
-
const filePath = match[1];
|
|
54
|
-
counts.set(filePath, (counts.get(filePath) ?? 0) + 1);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return counts;
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Extract unique file paths from grep output (both match and context lines).
|
|
61
|
-
*/
|
|
62
|
-
function extractUniquePaths(body) {
|
|
63
|
-
const seen = new Set();
|
|
64
|
-
const paths = [];
|
|
65
|
-
for (const line of body.split("\n")) {
|
|
66
|
-
const matchResult = MATCH_LINE_RE.exec(line) ?? CONTEXT_LINE_RE.exec(line);
|
|
67
|
-
if (matchResult) {
|
|
68
|
-
const filePath = matchResult[1];
|
|
69
|
-
if (!seen.has(filePath)) {
|
|
70
|
-
seen.add(filePath);
|
|
71
|
-
paths.push(filePath);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return paths;
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Wrap the grep tool to support `output_mode` parameter.
|
|
79
|
-
*
|
|
80
|
-
* Extends the tool's parameter schema to add `output_mode`, strips it
|
|
81
|
-
* before delegating to the original tool, then post-processes the result
|
|
82
|
-
* based on the requested output mode.
|
|
83
|
-
*
|
|
84
|
-
* @param tool - The grep tool (already wrapped with safePath)
|
|
85
|
-
* @returns A new AgentTool with output_mode support
|
|
86
|
-
*/
|
|
87
|
-
export function wrapGrepWithOutputMode(
|
|
88
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- AgentTool generic requires `any` per pi-agent-core API
|
|
89
|
-
tool) {
|
|
90
|
-
// Extend parameter schema with output_mode
|
|
91
|
-
const originalParams = tool.parameters;
|
|
92
|
-
const extendedParams = Type.Object({
|
|
93
|
-
...originalParams.properties,
|
|
94
|
-
output_mode: Type.Optional(Type.Union([
|
|
95
|
-
Type.Literal("content"),
|
|
96
|
-
Type.Literal("files_with_matches"),
|
|
97
|
-
Type.Literal("count"),
|
|
98
|
-
], {
|
|
99
|
-
description: "Output format: 'content' (default, full match lines), 'files_with_matches' (file paths only), or 'count' (match counts per file)",
|
|
100
|
-
})),
|
|
101
|
-
offset: Type.Optional(Type.Number({
|
|
102
|
-
description: "Skip the first N result entries (lines for content mode, file paths for files_with_matches, count entries for count mode). Default: 0.",
|
|
103
|
-
})),
|
|
104
|
-
});
|
|
105
|
-
return {
|
|
106
|
-
...tool,
|
|
107
|
-
parameters: extendedParams,
|
|
108
|
-
async execute(toolCallId, params, signal, onUpdate) {
|
|
109
|
-
// Extract and strip output_mode + offset before delegating to upstream
|
|
110
|
-
const outputMode = params.output_mode ?? "content";
|
|
111
|
-
const offset = params.offset ?? 0;
|
|
112
|
-
const upstreamParams = { ...params };
|
|
113
|
-
delete upstreamParams.output_mode;
|
|
114
|
-
delete upstreamParams.offset;
|
|
115
|
-
// Delegate to original grep tool
|
|
116
|
-
const result = await tool.execute(toolCallId, upstreamParams, signal, onUpdate);
|
|
117
|
-
// Extract text content from result
|
|
118
|
-
const textParts = result.content
|
|
119
|
-
.filter((c) => c.type === "text")
|
|
120
|
-
.map((c) => c.text);
|
|
121
|
-
const fullText = textParts.join("");
|
|
122
|
-
// Passthrough for empty or no-match results
|
|
123
|
-
if (fullText.trim() === "" || fullText.trim() === NO_MATCHES) {
|
|
124
|
-
return result;
|
|
125
|
-
}
|
|
126
|
-
// For default/content mode, apply offset if needed then return
|
|
127
|
-
if (outputMode === "content") {
|
|
128
|
-
if (offset <= 0) {
|
|
129
|
-
return result;
|
|
130
|
-
}
|
|
131
|
-
const { body, notices } = splitNotices(fullText);
|
|
132
|
-
const lines = body.split("\n").slice(offset);
|
|
133
|
-
let transformedText = lines.join("\n");
|
|
134
|
-
if (notices.length > 0) {
|
|
135
|
-
transformedText += (transformedText ? "\n\n" : "") + notices.join("\n");
|
|
136
|
-
}
|
|
137
|
-
return {
|
|
138
|
-
...result,
|
|
139
|
-
content: [{ type: "text", text: transformedText }],
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
// Separate output body from trailing notices
|
|
143
|
-
const { body, notices } = splitNotices(fullText);
|
|
144
|
-
let transformedText;
|
|
145
|
-
if (outputMode === "files_with_matches") {
|
|
146
|
-
const paths = extractUniquePaths(body).slice(offset);
|
|
147
|
-
transformedText = paths.join("\n");
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
// count mode
|
|
151
|
-
const counts = countMatchesByFile(body);
|
|
152
|
-
const sorted = [...counts.entries()].sort((a, b) => b[1] - a[1]).slice(offset);
|
|
153
|
-
transformedText = sorted
|
|
154
|
-
.map(([filePath, count]) => `${filePath}: ${count} ${count === 1 ? "match" : "matches"}`)
|
|
155
|
-
.join("\n");
|
|
156
|
-
}
|
|
157
|
-
// Append notices if present
|
|
158
|
-
if (notices.length > 0) {
|
|
159
|
-
transformedText += (transformedText ? "\n\n" : "") + notices.join("\n");
|
|
160
|
-
}
|
|
161
|
-
return {
|
|
162
|
-
...result,
|
|
163
|
-
content: [{ type: "text", text: transformedText }],
|
|
164
|
-
};
|
|
165
|
-
},
|
|
166
|
-
};
|
|
167
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Task plan tool: stateless formatter for multi-step work plans.
|
|
3
|
-
*
|
|
4
|
-
* Agents use this tool to structure and communicate multi-step plans
|
|
5
|
-
* visible in conversation history. Pure formatting -- no persistence,
|
|
6
|
-
* no side effects, no state.
|
|
7
|
-
*
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
11
|
-
declare const TaskPlanParams: import("@sinclair/typebox").TObject<{
|
|
12
|
-
tasks: import("@sinclair/typebox").TArray<import("@sinclair/typebox").TObject<{
|
|
13
|
-
id: import("@sinclair/typebox").TString;
|
|
14
|
-
description: import("@sinclair/typebox").TString;
|
|
15
|
-
status: import("@sinclair/typebox").TUnion<[import("@sinclair/typebox").TLiteral<"pending">, import("@sinclair/typebox").TLiteral<"in-progress">, import("@sinclair/typebox").TLiteral<"done">, import("@sinclair/typebox").TLiteral<"skipped">]>;
|
|
16
|
-
}>>;
|
|
17
|
-
title: import("@sinclair/typebox").TOptional<import("@sinclair/typebox").TString>;
|
|
18
|
-
}>;
|
|
19
|
-
/**
|
|
20
|
-
* Create a stateless task_plan tool for structuring multi-step work plans.
|
|
21
|
-
*
|
|
22
|
-
* @returns AgentTool that formats task lists into readable plan text
|
|
23
|
-
*/
|
|
24
|
-
export declare function createTaskPlanTool(): AgentTool<typeof TaskPlanParams>;
|
|
25
|
-
export {};
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Task plan tool: stateless formatter for multi-step work plans.
|
|
3
|
-
*
|
|
4
|
-
* Agents use this tool to structure and communicate multi-step plans
|
|
5
|
-
* visible in conversation history. Pure formatting -- no persistence,
|
|
6
|
-
* no side effects, no state.
|
|
7
|
-
*
|
|
8
|
-
* @module
|
|
9
|
-
*/
|
|
10
|
-
import { Type } from "@sinclair/typebox";
|
|
11
|
-
import { jsonResult } from "./platform/tool-helpers.js";
|
|
12
|
-
// ---------------------------------------------------------------------------
|
|
13
|
-
// Parameter schema
|
|
14
|
-
// ---------------------------------------------------------------------------
|
|
15
|
-
const TaskPlanParams = Type.Object({
|
|
16
|
-
tasks: Type.Array(Type.Object({
|
|
17
|
-
id: Type.String({ description: "Unique task identifier" }),
|
|
18
|
-
description: Type.String({ description: "What needs to be done" }),
|
|
19
|
-
status: Type.Union([
|
|
20
|
-
Type.Literal("pending"),
|
|
21
|
-
Type.Literal("in-progress"),
|
|
22
|
-
Type.Literal("done"),
|
|
23
|
-
Type.Literal("skipped"),
|
|
24
|
-
], { description: "Current task status" }),
|
|
25
|
-
}), { description: "List of tasks in the plan" }),
|
|
26
|
-
title: Type.Optional(Type.String({ description: "Optional plan title (defaults to 'Task Plan')" })),
|
|
27
|
-
});
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
// Status icon mapping
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
const STATUS_ICONS = {
|
|
32
|
-
pending: "[ ]",
|
|
33
|
-
"in-progress": "[~]",
|
|
34
|
-
done: "[x]",
|
|
35
|
-
skipped: "[-]",
|
|
36
|
-
};
|
|
37
|
-
// ---------------------------------------------------------------------------
|
|
38
|
-
// Factory
|
|
39
|
-
// ---------------------------------------------------------------------------
|
|
40
|
-
/**
|
|
41
|
-
* Create a stateless task_plan tool for structuring multi-step work plans.
|
|
42
|
-
*
|
|
43
|
-
* @returns AgentTool that formats task lists into readable plan text
|
|
44
|
-
*/
|
|
45
|
-
export function createTaskPlanTool() {
|
|
46
|
-
return {
|
|
47
|
-
name: "task_plan",
|
|
48
|
-
label: "Task Plan",
|
|
49
|
-
description: "Structure and display a multi-step task plan. Returns a formatted summary. " +
|
|
50
|
-
"Stateless -- use this to organize your work and communicate progress.",
|
|
51
|
-
parameters: TaskPlanParams,
|
|
52
|
-
async execute(_toolCallId, params) {
|
|
53
|
-
const p = params;
|
|
54
|
-
const title = p.title ?? "Task Plan";
|
|
55
|
-
const tasks = p.tasks ?? [];
|
|
56
|
-
// Format each task line
|
|
57
|
-
const lines = tasks.map((t) => `${STATUS_ICONS[t.status]} ${t.id}: ${t.description}`);
|
|
58
|
-
// Count completed
|
|
59
|
-
const doneCount = tasks.filter((t) => t.status === "done").length;
|
|
60
|
-
const totalCount = tasks.length;
|
|
61
|
-
const summary = `${doneCount}/${totalCount} tasks completed`;
|
|
62
|
-
// Build plan text
|
|
63
|
-
const plan = [title, "", ...lines, "", summary].join("\n");
|
|
64
|
-
return jsonResult({ plan, summary, tasks });
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
}
|
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Tool Bridge: Converts MCP tool definitions to AgentTool instances.
|
|
3
|
-
*
|
|
4
|
-
* Follows the pattern established by skill-tool-bridge.ts for converting
|
|
5
|
-
* external tool definitions into the AgentTool format expected by the
|
|
6
|
-
* agent executor (pi-agent-core).
|
|
7
|
-
*
|
|
8
|
-
* Key functions:
|
|
9
|
-
* - mcpToolsToAgentTools: Batch convert MCP tools to AgentTool[]
|
|
10
|
-
* - jsonSchemaToTypeBox: Basic JSON Schema -> TypeBox conversion
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import type { AgentTool } from "@mariozechner/pi-agent-core";
|
|
15
|
-
import { type TSchema } from "@sinclair/typebox";
|
|
16
|
-
import { type ToolSourceProfile } from "../builtin/tool-source-profiles.js";
|
|
17
|
-
import type { McpToolDefinition, McpClientManager } from "./mcp-client.js";
|
|
18
|
-
/**
|
|
19
|
-
* Extract the MCP server name from a sanitized tool name.
|
|
20
|
-
*
|
|
21
|
-
* Sanitized MCP tool names use the format `mcp__serverName--toolName`.
|
|
22
|
-
* Returns `undefined` for non-MCP tools or malformed names.
|
|
23
|
-
*
|
|
24
|
-
* @example
|
|
25
|
-
* extractMcpServerName("mcp__context7--resolve-library-id") // "context7"
|
|
26
|
-
* extractMcpServerName("mcp__srv__v2--ns--tool") // "srv__v2"
|
|
27
|
-
* extractMcpServerName("bash") // undefined
|
|
28
|
-
*/
|
|
29
|
-
export declare function extractMcpServerName(toolName: string): string | undefined;
|
|
30
|
-
/**
|
|
31
|
-
* Classify an MCP error message into a category for observability.
|
|
32
|
-
*
|
|
33
|
-
* Returns one of: "timeout", "connection", "tool_error", "transport", "unknown".
|
|
34
|
-
*/
|
|
35
|
-
export declare function classifyMcpErrorType(errorText: string | undefined): string;
|
|
36
|
-
/**
|
|
37
|
-
* Convert a basic JSON Schema definition to a TypeBox TSchema.
|
|
38
|
-
*
|
|
39
|
-
* Handles primitive types, arrays, and objects. Complex schema features
|
|
40
|
-
* (oneOf, allOf, $ref, etc.) fall back to Type.Any().
|
|
41
|
-
*
|
|
42
|
-
* This is intentionally simple -- MCP tool schemas are typically flat
|
|
43
|
-
* objects with primitive properties. Complex schemas still work but
|
|
44
|
-
* lose TypeBox-level validation detail.
|
|
45
|
-
*/
|
|
46
|
-
export declare function jsonSchemaToTypeBox(schema: Record<string, unknown>): TSchema;
|
|
47
|
-
/** Maximum characters for LLM-facing MCP tool descriptions. */
|
|
48
|
-
export declare const MAX_LLM_DESCRIPTION_CHARS = 2048;
|
|
49
|
-
/**
|
|
50
|
-
* Sanitize a qualified MCP tool name for use as an LLM API tool name.
|
|
51
|
-
*
|
|
52
|
-
* LLM APIs (Anthropic, OpenAI) require tool names to match `^[a-zA-Z0-9_-]{1,128}$`.
|
|
53
|
-
* Qualified names like "mcp:context7/resolve-library-id" contain invalid characters
|
|
54
|
-
* (`:`, `/`). This function replaces them: "mcp:" -> "mcp__", "/" -> "--".
|
|
55
|
-
*
|
|
56
|
-
* Example: "mcp:context7/resolve-library-id" -> "mcp__context7--resolve-library-id"
|
|
57
|
-
*/
|
|
58
|
-
export declare function sanitizeMcpToolName(qualifiedName: string): string;
|
|
59
|
-
/**
|
|
60
|
-
* Convert an array of MCP tool definitions to AgentTool instances.
|
|
61
|
-
*
|
|
62
|
-
* Each AgentTool's execute() delegates to the provided callTool function,
|
|
63
|
-
* which dispatches to the correct MCP server connection. Error results
|
|
64
|
-
* from the MCP server are returned as text content (not thrown), matching
|
|
65
|
-
* the AgentTool contract.
|
|
66
|
-
*
|
|
67
|
-
* Successful results are capped to the resolved source profile's maxChars
|
|
68
|
-
* limit, preventing oversized MCP responses from consuming agent context.
|
|
69
|
-
*
|
|
70
|
-
* @param tools - MCP tool definitions from McpClientManager.getTools()
|
|
71
|
-
* @param callTool - McpClientManager.callTool bound function
|
|
72
|
-
* @param toolSourceProfiles - Optional per-tool overrides for source profiles
|
|
73
|
-
* @returns AgentTool instances ready for the agent executor
|
|
74
|
-
*/
|
|
75
|
-
export declare function mcpToolsToAgentTools(tools: McpToolDefinition[], callTool: McpClientManager["callTool"], toolSourceProfiles?: Record<string, Partial<ToolSourceProfile>>): AgentTool<any>[];
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* MCP Tool Bridge: Converts MCP tool definitions to AgentTool instances.
|
|
3
|
-
*
|
|
4
|
-
* Follows the pattern established by skill-tool-bridge.ts for converting
|
|
5
|
-
* external tool definitions into the AgentTool format expected by the
|
|
6
|
-
* agent executor (pi-agent-core).
|
|
7
|
-
*
|
|
8
|
-
* Key functions:
|
|
9
|
-
* - mcpToolsToAgentTools: Batch convert MCP tools to AgentTool[]
|
|
10
|
-
* - jsonSchemaToTypeBox: Basic JSON Schema -> TypeBox conversion
|
|
11
|
-
*
|
|
12
|
-
* @module
|
|
13
|
-
*/
|
|
14
|
-
import { Type } from "@sinclair/typebox";
|
|
15
|
-
import { registerToolMetadata } from "@comis/core";
|
|
16
|
-
import { resolveSourceProfile } from "../builtin/tool-source-profiles.js";
|
|
17
|
-
import { sanitizeMcpToolResult } from "./mcp-result-sanitizer.js";
|
|
18
|
-
// ---------------------------------------------------------------------------
|
|
19
|
-
// MCP tool name parsing and error classification
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
/**
|
|
22
|
-
* Extract the MCP server name from a sanitized tool name.
|
|
23
|
-
*
|
|
24
|
-
* Sanitized MCP tool names use the format `mcp__serverName--toolName`.
|
|
25
|
-
* Returns `undefined` for non-MCP tools or malformed names.
|
|
26
|
-
*
|
|
27
|
-
* @example
|
|
28
|
-
* extractMcpServerName("mcp__context7--resolve-library-id") // "context7"
|
|
29
|
-
* extractMcpServerName("mcp__srv__v2--ns--tool") // "srv__v2"
|
|
30
|
-
* extractMcpServerName("bash") // undefined
|
|
31
|
-
*/
|
|
32
|
-
export function extractMcpServerName(toolName) {
|
|
33
|
-
if (!toolName.startsWith("mcp__"))
|
|
34
|
-
return undefined;
|
|
35
|
-
const rest = toolName.slice(5); // strip "mcp__"
|
|
36
|
-
const sepIdx = rest.indexOf("--");
|
|
37
|
-
if (sepIdx <= 0)
|
|
38
|
-
return undefined; // no separator or empty server name
|
|
39
|
-
return rest.slice(0, sepIdx);
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Classify an MCP error message into a category for observability.
|
|
43
|
-
*
|
|
44
|
-
* Returns one of: "timeout", "connection", "tool_error", "transport", "unknown".
|
|
45
|
-
*/
|
|
46
|
-
export function classifyMcpErrorType(errorText) {
|
|
47
|
-
if (!errorText)
|
|
48
|
-
return "unknown";
|
|
49
|
-
const lower = errorText.toLowerCase();
|
|
50
|
-
if (lower.includes("timed out") || lower.includes("timeout"))
|
|
51
|
-
return "timeout";
|
|
52
|
-
if (lower.includes("not connected") || lower.includes("disconnected"))
|
|
53
|
-
return "connection";
|
|
54
|
-
if (lower.includes("crashed unexpectedly") || lower.includes("pipe") || lower.includes("epipe") || lower.includes("econnreset"))
|
|
55
|
-
return "transport";
|
|
56
|
-
if (lower.includes("mcp tool error:") || lower.includes("mcp tool returned an error"))
|
|
57
|
-
return "tool_error";
|
|
58
|
-
return "unknown";
|
|
59
|
-
}
|
|
60
|
-
// ---------------------------------------------------------------------------
|
|
61
|
-
// JSON Schema -> TypeBox conversion
|
|
62
|
-
// ---------------------------------------------------------------------------
|
|
63
|
-
/**
|
|
64
|
-
* Convert a basic JSON Schema definition to a TypeBox TSchema.
|
|
65
|
-
*
|
|
66
|
-
* Handles primitive types, arrays, and objects. Complex schema features
|
|
67
|
-
* (oneOf, allOf, $ref, etc.) fall back to Type.Any().
|
|
68
|
-
*
|
|
69
|
-
* This is intentionally simple -- MCP tool schemas are typically flat
|
|
70
|
-
* objects with primitive properties. Complex schemas still work but
|
|
71
|
-
* lose TypeBox-level validation detail.
|
|
72
|
-
*/
|
|
73
|
-
export function jsonSchemaToTypeBox(schema) {
|
|
74
|
-
const type = schema.type;
|
|
75
|
-
if (type === "string") {
|
|
76
|
-
return Type.String();
|
|
77
|
-
}
|
|
78
|
-
if (type === "number") {
|
|
79
|
-
return Type.Number();
|
|
80
|
-
}
|
|
81
|
-
if (type === "integer") {
|
|
82
|
-
return Type.Integer();
|
|
83
|
-
}
|
|
84
|
-
if (type === "boolean") {
|
|
85
|
-
return Type.Boolean();
|
|
86
|
-
}
|
|
87
|
-
if (type === "array") {
|
|
88
|
-
const items = schema.items;
|
|
89
|
-
if (items) {
|
|
90
|
-
return Type.Array(jsonSchemaToTypeBox(items));
|
|
91
|
-
}
|
|
92
|
-
return Type.Array(Type.Any());
|
|
93
|
-
}
|
|
94
|
-
if (type === "object") {
|
|
95
|
-
const properties = schema.properties;
|
|
96
|
-
const required = schema.required ?? [];
|
|
97
|
-
if (!properties) {
|
|
98
|
-
return Type.Object({});
|
|
99
|
-
}
|
|
100
|
-
const typeboxProps = {};
|
|
101
|
-
for (const [key, propSchema] of Object.entries(properties)) {
|
|
102
|
-
const converted = jsonSchemaToTypeBox(propSchema);
|
|
103
|
-
typeboxProps[key] = required.includes(key) ? converted : Type.Optional(converted);
|
|
104
|
-
}
|
|
105
|
-
return Type.Object(typeboxProps);
|
|
106
|
-
}
|
|
107
|
-
// Fallback for unknown or complex schema types
|
|
108
|
-
return Type.Any();
|
|
109
|
-
}
|
|
110
|
-
// ---------------------------------------------------------------------------
|
|
111
|
-
// Description truncation (CTX-01)
|
|
112
|
-
// ---------------------------------------------------------------------------
|
|
113
|
-
/** Maximum characters for LLM-facing MCP tool descriptions. */
|
|
114
|
-
export const MAX_LLM_DESCRIPTION_CHARS = 2048;
|
|
115
|
-
const TRUNCATED_SUFFIX = " [truncated]";
|
|
116
|
-
/**
|
|
117
|
-
* Truncate a tool description for LLM consumption. Returns the original
|
|
118
|
-
* string when it fits within the budget, or a truncated version with
|
|
119
|
-
* "[truncated]" suffix. Returns undefined for undefined input.
|
|
120
|
-
*/
|
|
121
|
-
function truncateDescription(desc) {
|
|
122
|
-
if (!desc || desc.length <= MAX_LLM_DESCRIPTION_CHARS)
|
|
123
|
-
return desc;
|
|
124
|
-
return desc.slice(0, MAX_LLM_DESCRIPTION_CHARS - TRUNCATED_SUFFIX.length) + TRUNCATED_SUFFIX;
|
|
125
|
-
}
|
|
126
|
-
// ---------------------------------------------------------------------------
|
|
127
|
-
// MCP tool -> AgentTool conversion
|
|
128
|
-
// ---------------------------------------------------------------------------
|
|
129
|
-
/**
|
|
130
|
-
* Extract the server name from a qualified tool name "mcp:{server}/{tool}".
|
|
131
|
-
* Returns the full name as fallback.
|
|
132
|
-
*/
|
|
133
|
-
function extractServerName(qualifiedName) {
|
|
134
|
-
const match = qualifiedName.match(/^mcp:([^/]+)\//);
|
|
135
|
-
return match ? match[1] : qualifiedName;
|
|
136
|
-
}
|
|
137
|
-
/**
|
|
138
|
-
* Sanitize a qualified MCP tool name for use as an LLM API tool name.
|
|
139
|
-
*
|
|
140
|
-
* LLM APIs (Anthropic, OpenAI) require tool names to match `^[a-zA-Z0-9_-]{1,128}$`.
|
|
141
|
-
* Qualified names like "mcp:context7/resolve-library-id" contain invalid characters
|
|
142
|
-
* (`:`, `/`). This function replaces them: "mcp:" -> "mcp__", "/" -> "--".
|
|
143
|
-
*
|
|
144
|
-
* Example: "mcp:context7/resolve-library-id" -> "mcp__context7--resolve-library-id"
|
|
145
|
-
*/
|
|
146
|
-
export function sanitizeMcpToolName(qualifiedName) {
|
|
147
|
-
return qualifiedName.replace(/:/g, "__").replace(/\//g, "--");
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* Convert an array of MCP tool definitions to AgentTool instances.
|
|
151
|
-
*
|
|
152
|
-
* Each AgentTool's execute() delegates to the provided callTool function,
|
|
153
|
-
* which dispatches to the correct MCP server connection. Error results
|
|
154
|
-
* from the MCP server are returned as text content (not thrown), matching
|
|
155
|
-
* the AgentTool contract.
|
|
156
|
-
*
|
|
157
|
-
* Successful results are capped to the resolved source profile's maxChars
|
|
158
|
-
* limit, preventing oversized MCP responses from consuming agent context.
|
|
159
|
-
*
|
|
160
|
-
* @param tools - MCP tool definitions from McpClientManager.getTools()
|
|
161
|
-
* @param callTool - McpClientManager.callTool bound function
|
|
162
|
-
* @param toolSourceProfiles - Optional per-tool overrides for source profiles
|
|
163
|
-
* @returns AgentTool instances ready for the agent executor
|
|
164
|
-
*/
|
|
165
|
-
export function mcpToolsToAgentTools(tools, callTool, toolSourceProfiles) {
|
|
166
|
-
return tools.map((tool) => {
|
|
167
|
-
const typeboxSchema = jsonSchemaToTypeBox(tool.inputSchema);
|
|
168
|
-
const serverName = extractServerName(tool.qualifiedName);
|
|
169
|
-
const sanitizedName = sanitizeMcpToolName(tool.qualifiedName);
|
|
170
|
-
// CTX-02: Register full description as searchHint for BM25 scoring in discover_tools
|
|
171
|
-
registerToolMetadata(sanitizedName, { searchHint: tool.description ?? "" });
|
|
172
|
-
return {
|
|
173
|
-
name: sanitizedName,
|
|
174
|
-
label: tool.name,
|
|
175
|
-
// CTX-01: Truncate description for LLM token budget; full text preserved in searchHint above
|
|
176
|
-
description: truncateDescription(tool.description) ?? `MCP tool from ${serverName}`,
|
|
177
|
-
parameters: typeboxSchema,
|
|
178
|
-
async execute(_toolCallId, params) {
|
|
179
|
-
try {
|
|
180
|
-
const result = await callTool(tool.qualifiedName, params);
|
|
181
|
-
if (!result.ok) {
|
|
182
|
-
return {
|
|
183
|
-
content: [{ type: "text", text: `MCP tool error: ${result.error.message}` }],
|
|
184
|
-
details: { success: false },
|
|
185
|
-
};
|
|
186
|
-
}
|
|
187
|
-
const value = result.value;
|
|
188
|
-
if (value.isError) {
|
|
189
|
-
const errorText = value.content
|
|
190
|
-
.filter((c) => c.type === "text" && c.text)
|
|
191
|
-
.map((c) => c.text)
|
|
192
|
-
.join("\n");
|
|
193
|
-
return {
|
|
194
|
-
content: [
|
|
195
|
-
{
|
|
196
|
-
type: "text",
|
|
197
|
-
text: errorText || "MCP tool returned an error with no details",
|
|
198
|
-
},
|
|
199
|
-
],
|
|
200
|
-
details: { success: false },
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
// Collect text content from the MCP result
|
|
204
|
-
let textParts = value.content
|
|
205
|
-
.filter((c) => c.type === "text" && c.text)
|
|
206
|
-
.map((c) => c.text)
|
|
207
|
-
.join("\n");
|
|
208
|
-
// CTX-07: Sanitize MCP result (NFKC normalization + invisible char removal)
|
|
209
|
-
textParts = sanitizeMcpToolResult(textParts);
|
|
210
|
-
// Source-gate: cap text to resolved profile's maxChars limit
|
|
211
|
-
const profile = resolveSourceProfile(sanitizedName, toolSourceProfiles?.[sanitizedName]);
|
|
212
|
-
if (textParts.length > profile.maxChars) {
|
|
213
|
-
const originalLen = textParts.length;
|
|
214
|
-
textParts = textParts.slice(0, profile.maxChars) +
|
|
215
|
-
`\n\n[MCP tool result truncated: ${originalLen} chars -> ${profile.maxChars} chars]`;
|
|
216
|
-
}
|
|
217
|
-
return {
|
|
218
|
-
content: [{ type: "text", text: textParts || "Tool returned no text content" }],
|
|
219
|
-
details: { success: true },
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
catch (error) {
|
|
223
|
-
// Defense-in-depth: callTool returns Result and should never throw,
|
|
224
|
-
// but if something unexpected happens, return a clean error to the agent
|
|
225
|
-
// instead of letting it propagate and produce an opaque SDK error message.
|
|
226
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
227
|
-
return {
|
|
228
|
-
content: [{ type: "text", text: `MCP tool "${tool.qualifiedName}" crashed unexpectedly: ${message}` }],
|
|
229
|
-
details: { success: false },
|
|
230
|
-
};
|
|
231
|
-
}
|
|
232
|
-
},
|
|
233
|
-
};
|
|
234
|
-
});
|
|
235
|
-
}
|