iosm-cli 0.2.9 → 0.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/README.md +11 -2
- package/dist/core/agent-session.d.ts +9 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +425 -50
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/background-processes.d.ts +31 -0
- package/dist/core/background-processes.d.ts.map +1 -0
- package/dist/core/background-processes.js +241 -0
- package/dist/core/background-processes.js.map +1 -0
- package/dist/core/bash-executor.d.ts +6 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/extensions/types.d.ts +3 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +19 -2
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +23 -4
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/mcp/runtime.d.ts.map +1 -1
- package/dist/core/mcp/runtime.js +2 -0
- package/dist/core/mcp/runtime.js.map +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +2 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +30 -2
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +17 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +29 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +8 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/subagents.d.ts +10 -2
- package/dist/core/subagents.d.ts.map +1 -1
- package/dist/core/subagents.js +66 -17
- package/dist/core/subagents.js.map +1 -1
- package/dist/core/system-prompt.d.ts +25 -0
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +146 -14
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +28 -2
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/index.d.ts +2 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/permissions.d.ts +3 -0
- package/dist/core/tools/permissions.d.ts.map +1 -1
- package/dist/core/tools/permissions.js.map +1 -1
- package/dist/core/tools/task.d.ts +3 -1
- package/dist/core/tools/task.d.ts.map +1 -1
- package/dist/core/tools/task.js +48 -23
- package/dist/core/tools/task.js.map +1 -1
- package/dist/core/ultrathink.d.ts +122 -0
- package/dist/core/ultrathink.d.ts.map +1 -0
- package/dist/core/ultrathink.js +621 -0
- package/dist/core/ultrathink.js.map +1 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +93 -1
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +6 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +281 -24
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/cli-reference.md +10 -0
- package/docs/configuration.md +57 -1
- package/docs/development-and-testing.md +3 -2
- package/docs/extensions-packages-themes.md +27 -0
- package/docs/interactive-mode.md +7 -0
- package/docs/orchestration-and-subagents.md +16 -0
- package/docs/rpc-json-sdk.md +14 -0
- package/docs/sessions-traces-export.md +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
import { parseCommandArgs } from "./prompt-templates.js";
|
|
2
|
+
export const ULTRATHINK_COMMAND = "ultrathink";
|
|
3
|
+
export const ULTRATHINK_DEFAULT_ITERATIONS = 5;
|
|
4
|
+
export const ULTRATHINK_MAX_ITERATIONS = 12;
|
|
5
|
+
export const ULTRATHINK_MAX_CHECKPOINT_CHARS = 2200;
|
|
6
|
+
export const ULTRATHINK_MAX_CONTEXT_MESSAGES = 8;
|
|
7
|
+
export const ULTRATHINK_MAX_CONTEXT_MESSAGE_CHARS = 260;
|
|
8
|
+
export const ULTRATHINK_MAX_EVIDENCE_ENTRIES = 12;
|
|
9
|
+
export const ULTRATHINK_VISIBLE_PROMPT_PREFIX = "Ultrathink iteration";
|
|
10
|
+
export const ULTRATHINK_NO_NEW_EVIDENCE_MARKER = "[NO_NEW_EVIDENCE_OK]";
|
|
11
|
+
export const ULTRATHINK_STAGNATION_LIMIT = 2;
|
|
12
|
+
export const ULTRATHINK_MAX_ITERATION_INPUT_TOKENS = 50000;
|
|
13
|
+
export const ULTRATHINK_MAX_RUN_INPUT_TOKENS = 180000;
|
|
14
|
+
export const ULTRATHINK_MAX_RUN_TOTAL_TOKENS = 220000;
|
|
15
|
+
export const ULTRATHINK_MAX_RUN_COST = 0.03;
|
|
16
|
+
const CHECKPOINT_SECTIONS = [
|
|
17
|
+
"Goal",
|
|
18
|
+
"Verified Facts",
|
|
19
|
+
"Rejected Hypotheses",
|
|
20
|
+
"Open Questions",
|
|
21
|
+
"Next Checks",
|
|
22
|
+
];
|
|
23
|
+
const LIST_SECTION_PLACEHOLDERS = {
|
|
24
|
+
Goal: "Refine the objective based on discovered constraints.",
|
|
25
|
+
"Verified Facts": "(none yet)",
|
|
26
|
+
"Rejected Hypotheses": "(none yet)",
|
|
27
|
+
"Open Questions": "(none yet)",
|
|
28
|
+
"Next Checks": "Continue analysis with read-only evidence gathering.",
|
|
29
|
+
};
|
|
30
|
+
const ULTRATHINK_INTERNAL_MARKER = "[ULTRATHINK INTERNAL]";
|
|
31
|
+
const ULTRATHINK_READ_ONLY_TOOL_NAMES = new Set([
|
|
32
|
+
"read",
|
|
33
|
+
"grep",
|
|
34
|
+
"find",
|
|
35
|
+
"ls",
|
|
36
|
+
"rg",
|
|
37
|
+
"fd",
|
|
38
|
+
"ast_grep",
|
|
39
|
+
"comby",
|
|
40
|
+
"jq",
|
|
41
|
+
"yq",
|
|
42
|
+
"semgrep",
|
|
43
|
+
"sed",
|
|
44
|
+
"semantic_search",
|
|
45
|
+
"fetch",
|
|
46
|
+
"web_search",
|
|
47
|
+
"git_read",
|
|
48
|
+
"todo_read",
|
|
49
|
+
]);
|
|
50
|
+
export const ULTRATHINK_USAGE = [
|
|
51
|
+
"Usage:",
|
|
52
|
+
" /ultrathink",
|
|
53
|
+
" /ultrathink <query>",
|
|
54
|
+
" /ultrathink -q <1..12> <query>",
|
|
55
|
+
" /ultrathink --iterations <1..12> <query>",
|
|
56
|
+
"",
|
|
57
|
+
"Examples:",
|
|
58
|
+
" /ultrathink -q 7 audit auth architecture",
|
|
59
|
+
" /ultrathink --iterations 5",
|
|
60
|
+
].join("\n");
|
|
61
|
+
export const ULTRATHINK_CHECKPOINT_COMPRESSION_SYSTEM_PROMPT = [
|
|
62
|
+
"You compress ultrathink checkpoints for iterative reasoning.",
|
|
63
|
+
"Output must be plain text with the exact section names:",
|
|
64
|
+
"Goal:",
|
|
65
|
+
"Verified Facts:",
|
|
66
|
+
"Rejected Hypotheses:",
|
|
67
|
+
"Open Questions:",
|
|
68
|
+
"Next Checks:",
|
|
69
|
+
"Keep only decision-critical details. Preserve concrete file paths, command outputs, and constraints.",
|
|
70
|
+
"Do not add markdown headings, XML tags, or extra commentary.",
|
|
71
|
+
].join("\n");
|
|
72
|
+
export function parseUltrathinkCommand(text) {
|
|
73
|
+
const trimmed = text.trim();
|
|
74
|
+
if (!trimmed.startsWith(`/${ULTRATHINK_COMMAND}`))
|
|
75
|
+
return undefined;
|
|
76
|
+
if (!new RegExp(`^/${ULTRATHINK_COMMAND}(?:\\s|$)`).test(trimmed))
|
|
77
|
+
return undefined;
|
|
78
|
+
const argsText = trimmed.slice(ULTRATHINK_COMMAND.length + 1).trim();
|
|
79
|
+
const tokens = argsText ? parseCommandArgs(argsText) : [];
|
|
80
|
+
let iterations = ULTRATHINK_DEFAULT_ITERATIONS;
|
|
81
|
+
let query;
|
|
82
|
+
for (let index = 0; index < tokens.length; index++) {
|
|
83
|
+
const token = tokens[index] ?? "";
|
|
84
|
+
if (token === "--") {
|
|
85
|
+
query = tokens.slice(index + 1).join(" ").trim() || undefined;
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
if (token === "-q" || token === "--iterations") {
|
|
89
|
+
const value = tokens[index + 1];
|
|
90
|
+
if (!value) {
|
|
91
|
+
return {
|
|
92
|
+
kind: "error",
|
|
93
|
+
error: `Missing value for ${token}.`,
|
|
94
|
+
usage: ULTRATHINK_USAGE,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const parsed = parseIterations(value);
|
|
98
|
+
if (!parsed.ok) {
|
|
99
|
+
return {
|
|
100
|
+
kind: "error",
|
|
101
|
+
error: parsed.error,
|
|
102
|
+
usage: ULTRATHINK_USAGE,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
iterations = parsed.value;
|
|
106
|
+
index += 1;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
if (token.startsWith("-q=")) {
|
|
110
|
+
const value = token.slice(3);
|
|
111
|
+
const parsed = parseIterations(value);
|
|
112
|
+
if (!parsed.ok) {
|
|
113
|
+
return {
|
|
114
|
+
kind: "error",
|
|
115
|
+
error: parsed.error,
|
|
116
|
+
usage: ULTRATHINK_USAGE,
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
iterations = parsed.value;
|
|
120
|
+
continue;
|
|
121
|
+
}
|
|
122
|
+
if (token.startsWith("--iterations=")) {
|
|
123
|
+
const value = token.slice("--iterations=".length);
|
|
124
|
+
const parsed = parseIterations(value);
|
|
125
|
+
if (!parsed.ok) {
|
|
126
|
+
return {
|
|
127
|
+
kind: "error",
|
|
128
|
+
error: parsed.error,
|
|
129
|
+
usage: ULTRATHINK_USAGE,
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
iterations = parsed.value;
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (token.startsWith("-")) {
|
|
136
|
+
return {
|
|
137
|
+
kind: "error",
|
|
138
|
+
error: `Unknown option for /${ULTRATHINK_COMMAND}: ${token}`,
|
|
139
|
+
usage: ULTRATHINK_USAGE,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
query = tokens.slice(index).join(" ").trim() || undefined;
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
kind: "command",
|
|
147
|
+
command: { iterations, query },
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
function parseIterations(value) {
|
|
151
|
+
if (!/^\d+$/.test(value)) {
|
|
152
|
+
return {
|
|
153
|
+
ok: false,
|
|
154
|
+
error: `Invalid iteration count "${value}". Expected an integer from 1 to ${ULTRATHINK_MAX_ITERATIONS}.`,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
const parsed = Number.parseInt(value, 10);
|
|
158
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > ULTRATHINK_MAX_ITERATIONS) {
|
|
159
|
+
return {
|
|
160
|
+
ok: false,
|
|
161
|
+
error: `Invalid iteration count "${value}". Expected an integer from 1 to ${ULTRATHINK_MAX_ITERATIONS}.`,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
return { ok: true, value: parsed };
|
|
165
|
+
}
|
|
166
|
+
export function getUltrathinkPhase(iteration, totalIterations) {
|
|
167
|
+
if (totalIterations <= 1)
|
|
168
|
+
return "Synthesis";
|
|
169
|
+
if (iteration === 1)
|
|
170
|
+
return "Recon";
|
|
171
|
+
if (iteration === totalIterations)
|
|
172
|
+
return "Synthesis";
|
|
173
|
+
if (iteration === totalIterations - 1)
|
|
174
|
+
return "Verify";
|
|
175
|
+
return "Critique";
|
|
176
|
+
}
|
|
177
|
+
export function resolveUltrathinkReadOnlyTools(activeToolNames) {
|
|
178
|
+
return activeToolNames.filter((toolName) => ULTRATHINK_READ_ONLY_TOOL_NAMES.has(toolName));
|
|
179
|
+
}
|
|
180
|
+
export function findLastMeaningfulUserIntent(messages) {
|
|
181
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
182
|
+
const message = messages[index];
|
|
183
|
+
if (message.role !== "user")
|
|
184
|
+
continue;
|
|
185
|
+
const text = normalizeWhitespace(extractUserText(message));
|
|
186
|
+
if (!text)
|
|
187
|
+
continue;
|
|
188
|
+
if (text.startsWith("/"))
|
|
189
|
+
continue;
|
|
190
|
+
if (text.startsWith("!"))
|
|
191
|
+
continue;
|
|
192
|
+
if (text.includes(ULTRATHINK_INTERNAL_MARKER))
|
|
193
|
+
continue;
|
|
194
|
+
if (text.startsWith(ULTRATHINK_VISIBLE_PROMPT_PREFIX))
|
|
195
|
+
continue;
|
|
196
|
+
return text;
|
|
197
|
+
}
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
export function buildUltrathinkContextTail(messages) {
|
|
201
|
+
const rows = [];
|
|
202
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
203
|
+
if (rows.length >= ULTRATHINK_MAX_CONTEXT_MESSAGES)
|
|
204
|
+
break;
|
|
205
|
+
const message = messages[index];
|
|
206
|
+
const text = normalizeWhitespace(extractMessageText(message));
|
|
207
|
+
if (!text)
|
|
208
|
+
continue;
|
|
209
|
+
if (text.includes(ULTRATHINK_INTERNAL_MARKER))
|
|
210
|
+
continue;
|
|
211
|
+
if (isUltrathinkStructuredResponse(text))
|
|
212
|
+
continue;
|
|
213
|
+
if (message.role === "user" && (text.startsWith("/") || text.startsWith("!")))
|
|
214
|
+
continue;
|
|
215
|
+
if (message.role === "user" && text.startsWith(ULTRATHINK_VISIBLE_PROMPT_PREFIX))
|
|
216
|
+
continue;
|
|
217
|
+
rows.push(`[${message.role}] ${truncate(text, ULTRATHINK_MAX_CONTEXT_MESSAGE_CHARS)}`);
|
|
218
|
+
}
|
|
219
|
+
if (rows.length === 0)
|
|
220
|
+
return "";
|
|
221
|
+
return rows.reverse().join("\n");
|
|
222
|
+
}
|
|
223
|
+
export function extractUltrathinkToolEvidence(messages) {
|
|
224
|
+
const byId = new Map();
|
|
225
|
+
for (const message of messages) {
|
|
226
|
+
if (!isToolResultMessage(message))
|
|
227
|
+
continue;
|
|
228
|
+
const toolCallId = typeof message.toolCallId === "string" ? message.toolCallId : "";
|
|
229
|
+
const toolName = typeof message.toolName === "string" ? message.toolName : "unknown";
|
|
230
|
+
if (!toolCallId)
|
|
231
|
+
continue;
|
|
232
|
+
const summary = truncate(normalizeWhitespace(extractToolResultText(message) || "(no text output)"), 160);
|
|
233
|
+
byId.set(toolCallId, { toolCallId, toolName, summary });
|
|
234
|
+
}
|
|
235
|
+
return [...byId.values()];
|
|
236
|
+
}
|
|
237
|
+
export function buildUltrathinkEvidenceCatalog(evidence) {
|
|
238
|
+
if (evidence.length === 0)
|
|
239
|
+
return "- (none captured yet)";
|
|
240
|
+
const recent = evidence.slice(-ULTRATHINK_MAX_EVIDENCE_ENTRIES);
|
|
241
|
+
return recent.map((entry) => `- [evidence:${entry.toolCallId}] ${entry.toolName}: ${entry.summary}`).join("\n");
|
|
242
|
+
}
|
|
243
|
+
export function extractUltrathinkEvidenceTags(text) {
|
|
244
|
+
const tags = new Set();
|
|
245
|
+
for (const match of text.matchAll(/\[evidence:([^\]\s]+)\]/gi)) {
|
|
246
|
+
const value = match[1]?.trim();
|
|
247
|
+
if (value)
|
|
248
|
+
tags.add(value);
|
|
249
|
+
}
|
|
250
|
+
return [...tags];
|
|
251
|
+
}
|
|
252
|
+
export function hasUltrathinkNoNewEvidenceMarker(text) {
|
|
253
|
+
return text.includes(ULTRATHINK_NO_NEW_EVIDENCE_MARKER);
|
|
254
|
+
}
|
|
255
|
+
export function evaluateUltrathinkEvidencePolicy(input) {
|
|
256
|
+
const hasNumericClaims = hasUltrathinkNumericClaims(input.text);
|
|
257
|
+
const evidenceTags = extractUltrathinkEvidenceTags(input.text);
|
|
258
|
+
const hasEvidenceTags = evidenceTags.length > 0;
|
|
259
|
+
const knownEvidence = new Set(input.knownEvidenceIds);
|
|
260
|
+
const invalidEvidenceTags = evidenceTags.filter((tag) => !knownEvidence.has(tag));
|
|
261
|
+
const hasNoNewEvidenceMarker = hasUltrathinkNoNewEvidenceMarker(input.text);
|
|
262
|
+
const needsNoNewEvidenceMarker = (input.phase === "Verify" || input.phase === "Synthesis") && input.toolChecksThisIteration === 0;
|
|
263
|
+
return {
|
|
264
|
+
hasNumericClaims,
|
|
265
|
+
hasEvidenceTags,
|
|
266
|
+
invalidEvidenceTags,
|
|
267
|
+
missingEvidenceForNumbers: hasNumericClaims && !hasEvidenceTags,
|
|
268
|
+
needsNoNewEvidenceMarker,
|
|
269
|
+
hasNoNewEvidenceMarker,
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
export function createInitialUltrathinkCheckpoint(objective) {
|
|
273
|
+
return normalizeUltrathinkCheckpoint([
|
|
274
|
+
`Goal: ${objective}`,
|
|
275
|
+
"Verified Facts:",
|
|
276
|
+
"- (none yet)",
|
|
277
|
+
"Rejected Hypotheses:",
|
|
278
|
+
"- (none yet)",
|
|
279
|
+
"Open Questions:",
|
|
280
|
+
"- (none yet)",
|
|
281
|
+
"Next Checks:",
|
|
282
|
+
"- Continue analysis with read-only evidence gathering.",
|
|
283
|
+
].join("\n"), objective);
|
|
284
|
+
}
|
|
285
|
+
export function normalizeUltrathinkCheckpoint(rawCheckpoint, objective) {
|
|
286
|
+
const source = rawCheckpoint.trim();
|
|
287
|
+
const goal = normalizeGoal(extractCheckpointSection(source, "Goal") ?? objective, objective);
|
|
288
|
+
const verifiedFacts = normalizeListSection(extractCheckpointSection(source, "Verified Facts"), "Verified Facts");
|
|
289
|
+
const rejectedHypotheses = normalizeListSection(extractCheckpointSection(source, "Rejected Hypotheses"), "Rejected Hypotheses");
|
|
290
|
+
const openQuestions = normalizeListSection(extractCheckpointSection(source, "Open Questions"), "Open Questions");
|
|
291
|
+
const nextChecks = normalizeListSection(extractCheckpointSection(source, "Next Checks"), "Next Checks");
|
|
292
|
+
return [
|
|
293
|
+
`Goal: ${goal}`,
|
|
294
|
+
"Verified Facts:",
|
|
295
|
+
verifiedFacts,
|
|
296
|
+
"Rejected Hypotheses:",
|
|
297
|
+
rejectedHypotheses,
|
|
298
|
+
"Open Questions:",
|
|
299
|
+
openQuestions,
|
|
300
|
+
"Next Checks:",
|
|
301
|
+
nextChecks,
|
|
302
|
+
].join("\n");
|
|
303
|
+
}
|
|
304
|
+
export function truncateUltrathinkCheckpoint(checkpoint, maxChars) {
|
|
305
|
+
if (checkpoint.length <= maxChars)
|
|
306
|
+
return checkpoint;
|
|
307
|
+
return `${checkpoint.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
308
|
+
}
|
|
309
|
+
export function extractUltrathinkIterationSummary(text) {
|
|
310
|
+
const summary = extractMarkdownSection(text, "Iteration Summary");
|
|
311
|
+
if (summary) {
|
|
312
|
+
return truncate(normalizeWhitespace(summary), 420);
|
|
313
|
+
}
|
|
314
|
+
const fallback = normalizeWhitespace(text);
|
|
315
|
+
return truncate(fallback || "Iteration completed without a structured summary.", 420);
|
|
316
|
+
}
|
|
317
|
+
export function extractUltrathinkCheckpoint(text) {
|
|
318
|
+
const checkpoint = extractMarkdownSection(text, "Next Checkpoint");
|
|
319
|
+
return checkpoint?.trim() || undefined;
|
|
320
|
+
}
|
|
321
|
+
export function buildUltrathinkIterationPrompt(input) {
|
|
322
|
+
const isFinalIteration = input.iteration === input.totalIterations;
|
|
323
|
+
const formatBlock = buildUltrathinkResponseFormat(isFinalIteration);
|
|
324
|
+
return [
|
|
325
|
+
`${ULTRATHINK_INTERNAL_MARKER} iteration ${input.iteration}/${input.totalIterations}`,
|
|
326
|
+
`Phase: ${input.phase}`,
|
|
327
|
+
"You are running an ultrathink analysis pass with the ROOT agent and tools.",
|
|
328
|
+
"STRICT RULES:",
|
|
329
|
+
"- Operate in read-only mode only.",
|
|
330
|
+
"- You may inspect files and repository state, but do not modify files or run mutating commands.",
|
|
331
|
+
"- No implementation changes in this mode; analysis and verification only.",
|
|
332
|
+
"- Do not invent metrics, counts, percentages, coverage numbers, or ROI claims.",
|
|
333
|
+
"- Any quantitative claim must include evidence tags: `[evidence:<toolCallId>]`.",
|
|
334
|
+
"- In Verify/Synthesis with zero new tool checks, include `[NO_NEW_EVIDENCE_OK]` in Evidence Notes.",
|
|
335
|
+
"",
|
|
336
|
+
"Objective:",
|
|
337
|
+
input.objective,
|
|
338
|
+
"",
|
|
339
|
+
input.contextTail
|
|
340
|
+
? ["Session context tail (compact):", input.contextTail, ""].join("\n")
|
|
341
|
+
: "",
|
|
342
|
+
input.previousSummary
|
|
343
|
+
? ["Previous iteration summary (compact):", input.previousSummary, ""].join("\n")
|
|
344
|
+
: "",
|
|
345
|
+
input.evidenceCatalog
|
|
346
|
+
? ["Known evidence from tool results (carry-forward):", input.evidenceCatalog, ""].join("\n")
|
|
347
|
+
: "",
|
|
348
|
+
input.budgetStatus
|
|
349
|
+
? ["Current budget status:", input.budgetStatus, ""].join("\n")
|
|
350
|
+
: "",
|
|
351
|
+
"Current checkpoint:",
|
|
352
|
+
input.checkpoint,
|
|
353
|
+
"",
|
|
354
|
+
"Return in the exact markdown shape below:",
|
|
355
|
+
formatBlock,
|
|
356
|
+
"",
|
|
357
|
+
"Keep this response concise and evidence-based.",
|
|
358
|
+
]
|
|
359
|
+
.filter((line) => line.length > 0)
|
|
360
|
+
.join("\n");
|
|
361
|
+
}
|
|
362
|
+
export function buildUltrathinkVisibleIterationPrompt(input) {
|
|
363
|
+
return `${ULTRATHINK_VISIBLE_PROMPT_PREFIX} ${input.iteration}/${input.totalIterations} (${input.phase}). Objective: ${truncate(input.objective, 160)}. Running ROOT-agent read-only analysis pass.`;
|
|
364
|
+
}
|
|
365
|
+
export function buildUltrathinkBudgetStatusLine(input) {
|
|
366
|
+
return [
|
|
367
|
+
`input_tokens=${input.accumulatedInputTokens}/${ULTRATHINK_MAX_RUN_INPUT_TOKENS}`,
|
|
368
|
+
`total_tokens=${input.accumulatedTotalTokens}/${ULTRATHINK_MAX_RUN_TOTAL_TOKENS}`,
|
|
369
|
+
`cost=${input.accumulatedCost.toFixed(6)}/${ULTRATHINK_MAX_RUN_COST.toFixed(6)}`,
|
|
370
|
+
`iter_input_limit=${ULTRATHINK_MAX_ITERATION_INPUT_TOKENS}`,
|
|
371
|
+
].join(", ");
|
|
372
|
+
}
|
|
373
|
+
export function buildUltrathinkComplianceRepairPrompt(input) {
|
|
374
|
+
const isFinalIteration = input.iteration === input.totalIterations;
|
|
375
|
+
return [
|
|
376
|
+
`${ULTRATHINK_INTERNAL_MARKER} compliance repair ${input.iteration}/${input.totalIterations}`,
|
|
377
|
+
`Phase: ${input.phase}`,
|
|
378
|
+
"You must rewrite the previous iteration response to satisfy ultrathink evidence policy.",
|
|
379
|
+
"",
|
|
380
|
+
"Issues detected:",
|
|
381
|
+
...input.issues.map((issue) => `- ${issue}`),
|
|
382
|
+
"",
|
|
383
|
+
"Objective:",
|
|
384
|
+
input.objective,
|
|
385
|
+
"",
|
|
386
|
+
input.evidenceCatalog
|
|
387
|
+
? ["Known evidence from tool results:", input.evidenceCatalog, ""].join("\n")
|
|
388
|
+
: "",
|
|
389
|
+
"Current checkpoint:",
|
|
390
|
+
input.checkpoint,
|
|
391
|
+
"",
|
|
392
|
+
"Previous non-compliant response:",
|
|
393
|
+
input.originalResponse,
|
|
394
|
+
"",
|
|
395
|
+
"Rewrite with these constraints:",
|
|
396
|
+
"- Keep conclusions concise and evidence-grounded.",
|
|
397
|
+
"- Remove any unsupported quantitative claims.",
|
|
398
|
+
"- Any quantitative claim must include `[evidence:<toolCallId>]`.",
|
|
399
|
+
"- If no new tool checks were needed in Verify/Synthesis, include `[NO_NEW_EVIDENCE_OK]` in Evidence Notes.",
|
|
400
|
+
"",
|
|
401
|
+
"Return in the exact markdown shape below:",
|
|
402
|
+
buildUltrathinkResponseFormat(isFinalIteration),
|
|
403
|
+
]
|
|
404
|
+
.filter((line) => line.length > 0)
|
|
405
|
+
.join("\n");
|
|
406
|
+
}
|
|
407
|
+
export function shouldUltrathinkForceToolGrounding(input) {
|
|
408
|
+
if (input.toolChecksThisIteration > 0)
|
|
409
|
+
return false;
|
|
410
|
+
if (input.phase === "Recon")
|
|
411
|
+
return true;
|
|
412
|
+
if (input.phase === "Critique" && input.cumulativeEvidenceCount === 0)
|
|
413
|
+
return true;
|
|
414
|
+
return false;
|
|
415
|
+
}
|
|
416
|
+
export function buildUltrathinkToolGroundingPrompt(input) {
|
|
417
|
+
const isFinalIteration = input.iteration === input.totalIterations;
|
|
418
|
+
const tools = input.availableReadOnlyTools.join(", ");
|
|
419
|
+
return [
|
|
420
|
+
`${ULTRATHINK_INTERNAL_MARKER} grounding retry ${input.iteration}/${input.totalIterations}`,
|
|
421
|
+
`Phase: ${input.phase}`,
|
|
422
|
+
"Grounding retry is required because no tool evidence was captured in this phase.",
|
|
423
|
+
"MANDATORY ACTIONS:",
|
|
424
|
+
"- Use read-only tools against the current workspace before finalizing this response.",
|
|
425
|
+
"- Run at least 2 concrete checks (e.g., ls/rg/read/git_read).",
|
|
426
|
+
"- Reference concrete file paths and observations from tool outputs.",
|
|
427
|
+
"- Do not answer from prior knowledge only.",
|
|
428
|
+
"",
|
|
429
|
+
`Available read-only tools: ${tools || "(none listed)"}`,
|
|
430
|
+
"",
|
|
431
|
+
"Objective:",
|
|
432
|
+
input.objective,
|
|
433
|
+
"",
|
|
434
|
+
input.evidenceCatalog
|
|
435
|
+
? ["Known evidence from tool results:", input.evidenceCatalog, ""].join("\n")
|
|
436
|
+
: "",
|
|
437
|
+
"Current checkpoint:",
|
|
438
|
+
input.checkpoint,
|
|
439
|
+
"",
|
|
440
|
+
"Return in the exact markdown shape below:",
|
|
441
|
+
buildUltrathinkResponseFormat(isFinalIteration),
|
|
442
|
+
]
|
|
443
|
+
.filter((line) => line.length > 0)
|
|
444
|
+
.join("\n");
|
|
445
|
+
}
|
|
446
|
+
export function buildUltrathinkCheckpointCompressionPrompt(input) {
|
|
447
|
+
return [
|
|
448
|
+
"Compress this checkpoint while preserving all decision-critical details.",
|
|
449
|
+
`Maximum length target: ${input.maxChars} characters.`,
|
|
450
|
+
"",
|
|
451
|
+
"Objective:",
|
|
452
|
+
input.objective,
|
|
453
|
+
"",
|
|
454
|
+
"Checkpoint to compress:",
|
|
455
|
+
input.checkpoint,
|
|
456
|
+
].join("\n");
|
|
457
|
+
}
|
|
458
|
+
export function hasUltrathinkEvidenceViolations(policy) {
|
|
459
|
+
if (policy.invalidEvidenceTags.length > 0)
|
|
460
|
+
return true;
|
|
461
|
+
if (policy.missingEvidenceForNumbers)
|
|
462
|
+
return true;
|
|
463
|
+
if (policy.needsNoNewEvidenceMarker && !policy.hasNoNewEvidenceMarker)
|
|
464
|
+
return true;
|
|
465
|
+
return false;
|
|
466
|
+
}
|
|
467
|
+
export function isUltrathinkStagnated(input) {
|
|
468
|
+
if (input.toolChecksThisIteration > 0)
|
|
469
|
+
return false;
|
|
470
|
+
return normalizeWhitespace(input.previousCheckpoint) === normalizeWhitespace(input.nextCheckpoint);
|
|
471
|
+
}
|
|
472
|
+
function buildUltrathinkResponseFormat(isFinalIteration) {
|
|
473
|
+
const rows = [
|
|
474
|
+
"### Iteration Summary",
|
|
475
|
+
"- 2-4 bullets, max 350 characters total.",
|
|
476
|
+
];
|
|
477
|
+
if (isFinalIteration) {
|
|
478
|
+
rows.push("### Final Analysis");
|
|
479
|
+
rows.push("- Explain the best approach with concrete evidence and tradeoffs.");
|
|
480
|
+
rows.push("- Start this section with: `I used ultrathink mode.`");
|
|
481
|
+
}
|
|
482
|
+
rows.push("### Evidence Notes");
|
|
483
|
+
rows.push("- Add evidence tags for quantitative claims: `[evidence:<toolCallId>]`.");
|
|
484
|
+
rows.push(`- If no new tool checks were needed in Verify/Synthesis, include ${ULTRATHINK_NO_NEW_EVIDENCE_MARKER}.`);
|
|
485
|
+
rows.push("### Next Checkpoint");
|
|
486
|
+
rows.push("Goal: <single line>");
|
|
487
|
+
rows.push("Verified Facts:");
|
|
488
|
+
rows.push("- ...");
|
|
489
|
+
rows.push("Rejected Hypotheses:");
|
|
490
|
+
rows.push("- ...");
|
|
491
|
+
rows.push("Open Questions:");
|
|
492
|
+
rows.push("- ...");
|
|
493
|
+
rows.push("Next Checks:");
|
|
494
|
+
rows.push("- ...");
|
|
495
|
+
return rows.join("\n");
|
|
496
|
+
}
|
|
497
|
+
function hasUltrathinkNumericClaims(text) {
|
|
498
|
+
const finalAnalysis = extractMarkdownSection(text, "Final Analysis");
|
|
499
|
+
const source = normalizeWhitespace(finalAnalysis ?? text);
|
|
500
|
+
if (!source)
|
|
501
|
+
return false;
|
|
502
|
+
if (/\b\d+\s*(?:%|percent|hours?|hrs?|minutes?|mins?|sec|seconds?|tokens?|files?|tests?|issues?|iterations?|insights?)\b/i.test(source)) {
|
|
503
|
+
return true;
|
|
504
|
+
}
|
|
505
|
+
if (/\b\d+(?:\.\d+)?\s*\/\s*\d+(?:\.\d+)?\b/.test(source)) {
|
|
506
|
+
return true;
|
|
507
|
+
}
|
|
508
|
+
if (/\b\d+\+\b/.test(source)) {
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
return false;
|
|
512
|
+
}
|
|
513
|
+
function isUltrathinkStructuredResponse(text) {
|
|
514
|
+
return text.includes("### Iteration Summary") && text.includes("### Next Checkpoint");
|
|
515
|
+
}
|
|
516
|
+
function extractMessageText(message) {
|
|
517
|
+
switch (message.role) {
|
|
518
|
+
case "user":
|
|
519
|
+
return extractUserText(message);
|
|
520
|
+
case "assistant":
|
|
521
|
+
return extractAssistantText(message);
|
|
522
|
+
case "bashExecution":
|
|
523
|
+
return [message.command, message.output].filter((part) => typeof part === "string" && part.trim()).join(" | ");
|
|
524
|
+
case "branchSummary":
|
|
525
|
+
case "compactionSummary":
|
|
526
|
+
return typeof message.summary === "string" ? message.summary : "";
|
|
527
|
+
default:
|
|
528
|
+
return "";
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
function extractUserText(message) {
|
|
532
|
+
const content = message.content;
|
|
533
|
+
if (typeof content === "string")
|
|
534
|
+
return content;
|
|
535
|
+
if (!Array.isArray(content))
|
|
536
|
+
return "";
|
|
537
|
+
return content
|
|
538
|
+
.filter((part) => part.type === "text")
|
|
539
|
+
.map((part) => part.text)
|
|
540
|
+
.join("\n");
|
|
541
|
+
}
|
|
542
|
+
function extractAssistantText(message) {
|
|
543
|
+
return message.content
|
|
544
|
+
.filter((part) => part.type === "text")
|
|
545
|
+
.map((part) => part.text)
|
|
546
|
+
.join("\n");
|
|
547
|
+
}
|
|
548
|
+
function isToolResultMessage(message) {
|
|
549
|
+
if (message.role !== "toolResult")
|
|
550
|
+
return false;
|
|
551
|
+
const candidate = message;
|
|
552
|
+
return (typeof candidate.toolCallId === "string" &&
|
|
553
|
+
candidate.toolCallId.length > 0 &&
|
|
554
|
+
typeof candidate.toolName === "string" &&
|
|
555
|
+
candidate.toolName.length > 0 &&
|
|
556
|
+
Array.isArray(candidate.content));
|
|
557
|
+
}
|
|
558
|
+
function extractToolResultText(message) {
|
|
559
|
+
return message.content
|
|
560
|
+
.filter((part) => part.type === "text")
|
|
561
|
+
.map((part) => part.text)
|
|
562
|
+
.join("\n");
|
|
563
|
+
}
|
|
564
|
+
function extractMarkdownSection(text, heading) {
|
|
565
|
+
const escapedHeading = escapeRegExp(heading);
|
|
566
|
+
const regex = new RegExp(`(?:^|\\n)###\\s*${escapedHeading}\\s*\\n([\\s\\S]*?)(?=\\n###\\s+|$)`, "i");
|
|
567
|
+
const match = text.match(regex);
|
|
568
|
+
if (!match)
|
|
569
|
+
return undefined;
|
|
570
|
+
return match[1]?.trim() || undefined;
|
|
571
|
+
}
|
|
572
|
+
function extractCheckpointSection(raw, sectionName) {
|
|
573
|
+
const escapedSection = escapeRegExp(sectionName);
|
|
574
|
+
const otherSections = CHECKPOINT_SECTIONS.filter((name) => name !== sectionName).map((name) => escapeRegExp(name));
|
|
575
|
+
const lookahead = otherSections.length > 0 ? `(?=\\n(?:${otherSections.join("|")})\\s*:|$)` : "$";
|
|
576
|
+
const regex = new RegExp(`(?:^|\\n)${escapedSection}\\s*:\\s*([\\s\\S]*?)${lookahead}`, "i");
|
|
577
|
+
const match = raw.match(regex);
|
|
578
|
+
if (!match)
|
|
579
|
+
return undefined;
|
|
580
|
+
return match[1]?.trim() || undefined;
|
|
581
|
+
}
|
|
582
|
+
function normalizeGoal(goalCandidate, fallbackGoal) {
|
|
583
|
+
const normalized = normalizeWhitespace(goalCandidate);
|
|
584
|
+
if (normalized.length > 0)
|
|
585
|
+
return truncate(normalized, 280);
|
|
586
|
+
return truncate(normalizeWhitespace(fallbackGoal), 280);
|
|
587
|
+
}
|
|
588
|
+
function normalizeListSection(candidate, sectionName) {
|
|
589
|
+
const normalized = normalizeWhitespace(candidate ?? "");
|
|
590
|
+
if (!normalized) {
|
|
591
|
+
return `- ${LIST_SECTION_PLACEHOLDERS[sectionName]}`;
|
|
592
|
+
}
|
|
593
|
+
const lines = normalized
|
|
594
|
+
.split("\n")
|
|
595
|
+
.map((line) => line.trim())
|
|
596
|
+
.filter((line) => line.length > 0)
|
|
597
|
+
.map((line) => line.replace(/^[*-]\s*/, "").replace(/^\d+[.)]\s*/, "").trim())
|
|
598
|
+
.filter((line) => line.length > 0)
|
|
599
|
+
.map((line) => `- ${truncate(line, 280)}`);
|
|
600
|
+
if (lines.length === 0) {
|
|
601
|
+
return `- ${LIST_SECTION_PLACEHOLDERS[sectionName]}`;
|
|
602
|
+
}
|
|
603
|
+
return lines.join("\n");
|
|
604
|
+
}
|
|
605
|
+
function truncate(text, maxChars) {
|
|
606
|
+
if (text.length <= maxChars)
|
|
607
|
+
return text;
|
|
608
|
+
return `${text.slice(0, Math.max(0, maxChars - 3)).trimEnd()}...`;
|
|
609
|
+
}
|
|
610
|
+
function normalizeWhitespace(value) {
|
|
611
|
+
return value
|
|
612
|
+
.replace(/\r\n/g, "\n")
|
|
613
|
+
.split("\n")
|
|
614
|
+
.map((line) => line.replace(/\s+/g, " ").trim())
|
|
615
|
+
.filter((line) => line.length > 0)
|
|
616
|
+
.join("\n");
|
|
617
|
+
}
|
|
618
|
+
function escapeRegExp(value) {
|
|
619
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
620
|
+
}
|
|
621
|
+
//# sourceMappingURL=ultrathink.js.map
|