@code-yeongyu/senpi 2026.5.14 → 2026.5.15-2
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 +1107 -1182
- package/README.md +1 -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 +109 -7
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/dynamic-prompt/verification.d.ts +31 -0
- package/dist/core/dynamic-prompt/verification.d.ts.map +1 -1
- package/dist/core/dynamic-prompt/verification.js +41 -0
- package/dist/core/dynamic-prompt/verification.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +157 -29
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts +197 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js +690 -0
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/prompts.d.ts +3 -3
- package/dist/core/extensions/builtin/compaction/prompts.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/prompts.js +0 -22
- package/dist/core/extensions/builtin/compaction/prompts.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts +4 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.d.ts.map +1 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js +48 -0
- package/dist/core/extensions/builtin/compaction/repair-tool-pairs.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +3 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +82 -33
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts +8 -0
- package/dist/core/extensions/builtin/compaction/todo-bridge.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/todo-bridge.js +12 -6
- package/dist/core/extensions/builtin/compaction/todo-bridge.js.map +1 -1
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +0 -2
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/permission-system/prompt.js +0 -5
- package/dist/core/extensions/builtin/permission-system/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/system-messages.d.ts +7 -7
- package/dist/core/extensions/builtin/system-messages.d.ts.map +1 -1
- package/dist/core/extensions/builtin/system-messages.js +10 -10
- package/dist/core/extensions/builtin/system-messages.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js +1 -1
- package/dist/core/extensions/builtin/todotools/continuation/prompt.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts +1 -1
- package/dist/core/extensions/builtin/todotools/state.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/state.js +1 -1
- package/dist/core/extensions/builtin/todotools/state.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts +3 -3
- package/dist/core/extensions/builtin/todotools/system-messages.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/system-messages.js +6 -6
- package/dist/core/extensions/builtin/todotools/system-messages.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/index.js +8 -4
- package/dist/core/extensions/builtin/tool-pair-guard/index.js.map +1 -1
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js +89 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-chat-completions-payload.js.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts +3 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.d.ts.map +1 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js +122 -0
- package/dist/core/extensions/builtin/tool-pair-guard/sanitize-openai-responses-payload.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -0
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +18 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +22 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/messages.d.ts +3 -3
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +5 -10
- package/dist/core/messages.js.map +1 -1
- package/dist/core/sdk.d.ts +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -22
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +1 -1
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +0 -5
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/thinking-levels.d.ts +6 -0
- package/dist/core/thinking-levels.d.ts.map +1 -0
- package/dist/core/thinking-levels.js +36 -0
- package/dist/core/thinking-levels.js.map +1 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +15 -1
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +20 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +3 -1
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +11 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +96 -49
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/docs/extensions.md +0 -1
- package/docs/index.md +0 -1
- package/docs/sdk.md +0 -1
- package/docs/settings.md +1 -29
- package/docs/termux.md +2 -2
- package/docs/usage.md +1 -1
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/overlay-qa-tests.ts +1 -1
- package/package.json +4 -4
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts +0 -10
- package/dist/core/extensions/builtin/background-task/cancel-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/cancel-tool.js +0 -109
- package/dist/core/extensions/builtin/background-task/cancel-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.d.ts +0 -3
- package/dist/core/extensions/builtin/background-task/index.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/index.js +0 -207
- package/dist/core/extensions/builtin/background-task/index.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.d.ts +0 -17
- package/dist/core/extensions/builtin/background-task/manager.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/manager.js +0 -114
- package/dist/core/extensions/builtin/background-task/manager.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.d.ts +0 -22
- package/dist/core/extensions/builtin/background-task/notification.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/notification.js +0 -105
- package/dist/core/extensions/builtin/background-task/notification.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts +0 -11
- package/dist/core/extensions/builtin/background-task/output-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/output-tool.js +0 -127
- package/dist/core/extensions/builtin/background-task/output-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.d.ts +0 -8
- package/dist/core/extensions/builtin/background-task/spawner.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/spawner.js +0 -207
- package/dist/core/extensions/builtin/background-task/spawner.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts +0 -20
- package/dist/core/extensions/builtin/background-task/task-tool.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/task-tool.js +0 -302
- package/dist/core/extensions/builtin/background-task/task-tool.js.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.d.ts +0 -72
- package/dist/core/extensions/builtin/background-task/types.d.ts.map +0 -1
- package/dist/core/extensions/builtin/background-task/types.js +0 -32
- package/dist/core/extensions/builtin/background-task/types.js.map +0 -1
- package/docs/agents.md +0 -348
- package/examples/extensions/subagent/README.md +0 -172
- package/examples/extensions/subagent/agents/planner.md +0 -37
- package/examples/extensions/subagent/agents/reviewer.md +0 -35
- package/examples/extensions/subagent/agents/scout.md +0 -50
- package/examples/extensions/subagent/agents/worker.md +0 -24
- package/examples/extensions/subagent/agents.ts +0 -126
- package/examples/extensions/subagent/index.ts +0 -987
- package/examples/extensions/subagent/prompts/implement-and-review.md +0 -10
- package/examples/extensions/subagent/prompts/implement.md +0 -10
- package/examples/extensions/subagent/prompts/scout-and-plan.md +0 -9
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isContextOverflow, stream, } from "@earendil-works/pi-ai";
|
|
2
2
|
import { DEFAULT_COMPACTION_SETTINGS, estimateContextTokens, estimateTokens, prepareCompaction, serializeConversation, } from "../../../compaction/index.js";
|
|
3
3
|
import { convertToLlm } from "../../../messages.js";
|
|
4
4
|
import { computeEffectiveKeepRecentTokens, computeEffectiveThreshold } from "./policy.js";
|
|
@@ -6,6 +6,7 @@ import { buildPrompt } from "./prompts.js";
|
|
|
6
6
|
import * as truncation from "./tool-truncation.js";
|
|
7
7
|
const DEFAULT_CONTEXT_WINDOW = 200_000;
|
|
8
8
|
const COMPACTION_BUDGET_RATIO = 0.6;
|
|
9
|
+
const COMPACTION_RETRY_BUDGET_RATIO = 0.4;
|
|
9
10
|
const EMERGENCY_CONTEXT_TARGET_RATIO = 0.95;
|
|
10
11
|
const MAX_SUMMARY_TOKENS = 8192;
|
|
11
12
|
const SUMMARY_SCHEMA = "senpi.compaction.summary.v1";
|
|
@@ -22,6 +23,39 @@ function getSummaryText(message) {
|
|
|
22
23
|
.join("\n")
|
|
23
24
|
.trim();
|
|
24
25
|
}
|
|
26
|
+
function isAssistantMessage(message) {
|
|
27
|
+
return message.role === "assistant" && "stopReason" in message;
|
|
28
|
+
}
|
|
29
|
+
async function generateSummaryMessage(options) {
|
|
30
|
+
const conversationText = serializeConversation(convertToLlm(options.messages));
|
|
31
|
+
const responseStream = stream(options.snapshot.model, {
|
|
32
|
+
systemPrompt: options.prompt.system,
|
|
33
|
+
messages: [
|
|
34
|
+
{
|
|
35
|
+
role: "user",
|
|
36
|
+
content: [
|
|
37
|
+
{
|
|
38
|
+
type: "text",
|
|
39
|
+
text: `${options.prompt.user}\n\n<conversation>\n${conversationText}\n</conversation>`,
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
timestamp: Date.now(),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
}, {
|
|
46
|
+
apiKey: options.auth.apiKey,
|
|
47
|
+
headers: options.auth.headers,
|
|
48
|
+
extraBody: options.auth.extraBody,
|
|
49
|
+
maxTokens: MAX_SUMMARY_TOKENS,
|
|
50
|
+
signal: options.signal,
|
|
51
|
+
});
|
|
52
|
+
for await (const event of responseStream) {
|
|
53
|
+
if (event.type === "text_delta" && event.delta) {
|
|
54
|
+
options.onProgress?.(event.delta);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return await responseStream.result();
|
|
58
|
+
}
|
|
25
59
|
function pruneToolResults(messages, contextWindow) {
|
|
26
60
|
const toolResults = messages
|
|
27
61
|
.filter((message) => message.role === "toolResult")
|
|
@@ -114,6 +148,15 @@ function pruneOldMessagesToBudget(messages, targetTokens) {
|
|
|
114
148
|
}
|
|
115
149
|
return pruned;
|
|
116
150
|
}
|
|
151
|
+
function pruneMessagesForOverflowRetry(messages, targetTokens) {
|
|
152
|
+
const budgetPruned = pruneOldMessagesToBudget(messages, targetTokens);
|
|
153
|
+
if (budgetPruned.length < messages.length)
|
|
154
|
+
return budgetPruned;
|
|
155
|
+
const boundaryIndex = findLastUserLikeIndex(messages);
|
|
156
|
+
return (removeFirstOldToolPair(messages, boundaryIndex) ??
|
|
157
|
+
removeFirstOldMessage(messages, boundaryIndex) ??
|
|
158
|
+
(messages.length > 1 ? messages.slice(1) : undefined));
|
|
159
|
+
}
|
|
117
160
|
function estimateTotalTokens(messages) {
|
|
118
161
|
let total = 0;
|
|
119
162
|
for (const message of messages)
|
|
@@ -165,47 +208,53 @@ export function createSpeculativeCompactionSnapshot(context, options) {
|
|
|
165
208
|
customInstructions: options.customInstructions,
|
|
166
209
|
};
|
|
167
210
|
}
|
|
168
|
-
export async function runExtensionCompaction(context, snapshot, signal) {
|
|
211
|
+
export async function runExtensionCompaction(context, snapshot, signal, onProgress) {
|
|
169
212
|
const auth = await context.modelRegistry?.getApiKeyAndHeaders(snapshot.model);
|
|
170
213
|
if (!auth?.ok || !auth.apiKey)
|
|
171
214
|
return undefined;
|
|
172
|
-
|
|
215
|
+
let messages = pruneToolResults([...snapshot.preparation.messagesToSummarize, ...snapshot.preparation.turnPrefixMessages], snapshot.contextWindow);
|
|
173
216
|
const prompt = buildPrompt({
|
|
174
217
|
variant: snapshot.promptVariant,
|
|
175
218
|
previousSummary: snapshot.preparation.previousSummary,
|
|
176
219
|
customInstructions: snapshot.customInstructions,
|
|
177
220
|
});
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
221
|
+
for (let attempt = 0; attempt < 2; attempt++) {
|
|
222
|
+
const response = await generateSummaryMessage({
|
|
223
|
+
messages,
|
|
224
|
+
onProgress,
|
|
225
|
+
prompt,
|
|
226
|
+
signal,
|
|
227
|
+
snapshot,
|
|
228
|
+
auth: {
|
|
229
|
+
apiKey: auth.apiKey,
|
|
230
|
+
headers: auth.headers,
|
|
231
|
+
extraBody: auth.extraBody,
|
|
188
232
|
},
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
233
|
+
});
|
|
234
|
+
if (!response)
|
|
235
|
+
return undefined;
|
|
236
|
+
if (isAssistantMessage(response) && isContextOverflow(response, snapshot.contextWindow)) {
|
|
237
|
+
const retryMessages = pruneMessagesForOverflowRetry(messages, Math.floor(snapshot.contextWindow * COMPACTION_RETRY_BUDGET_RATIO));
|
|
238
|
+
if (!retryMessages || retryMessages.length === messages.length) {
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
messages = retryMessages;
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
const summary = getSummaryText(response);
|
|
245
|
+
if (!summary)
|
|
246
|
+
return undefined;
|
|
247
|
+
const tokenEstimate = estimateContextTokens(convertToLlm(messages)).tokens + approxTokens(summary);
|
|
248
|
+
if (tokenEstimate > snapshot.contextWindow * COMPACTION_BUDGET_RATIO)
|
|
249
|
+
return undefined;
|
|
250
|
+
return {
|
|
251
|
+
summary,
|
|
252
|
+
firstKeptEntryId: snapshot.preparation.firstKeptEntryId,
|
|
253
|
+
tokensBefore: snapshot.preparation.tokensBefore,
|
|
254
|
+
details: { schema: SUMMARY_SCHEMA, promptVariant: snapshot.promptVariant, tokenEstimate },
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
throw new Error("Compaction summary request exceeded the context window after retrying with a smaller input");
|
|
209
258
|
}
|
|
210
259
|
export async function applyGeneratedCompaction(context, snapshot, getCurrentGeneration, compaction) {
|
|
211
260
|
if (!snapshot || !compaction)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"speculative.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport { complete, type Message, type Model, type TextContent } from \"@earendil-works/pi-ai\";\nimport {\n\ttype CompactionPreparation,\n\ttype CompactionResult,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tprepareCompaction,\n\tserializeConversation,\n} from \"../../../compaction/index.js\";\nimport { convertToLlm } from \"../../../messages.js\";\nimport type { ModelRegistry } from \"../../../model-registry.js\";\nimport type { ReadonlySessionManager } from \"../../../session-manager.js\";\nimport type { ApplyCompactionResult, ContextUsage } from \"../../types.js\";\nimport { computeEffectiveKeepRecentTokens, computeEffectiveThreshold } from \"./policy.js\";\nimport { buildPrompt, type MergedCompactionPromptVariant } from \"./prompts.js\";\nimport * as truncation from \"./tool-truncation.js\";\n\nconst DEFAULT_CONTEXT_WINDOW = 200_000;\nconst COMPACTION_BUDGET_RATIO = 0.6;\nconst EMERGENCY_CONTEXT_TARGET_RATIO = 0.95;\nconst MAX_SUMMARY_TOKENS = 8192;\nconst SUMMARY_SCHEMA = \"senpi.compaction.summary.v1\";\n\nexport interface SpeculativeCompactionContext {\n\tmodel: Model<any> | undefined;\n\tsessionManager: ReadonlySessionManager;\n\tmodelRegistry?: ModelRegistry;\n\tgetContextUsage(): ContextUsage | undefined;\n\tgetCompactionSettings?(): CompactionPreparation[\"settings\"];\n\tgetMessageRevision(): number;\n\tapplyCompaction(\n\t\tprecomputed: CompactionResult,\n\t\toptions: { reason: \"extension\"; expectedRevision: number },\n\t): Promise<ApplyCompactionResult>;\n}\n\nexport interface SpeculativeCompactionSnapshot {\n\tgeneration: number;\n\texpectedRevision: number;\n\tmodel: Model<any>;\n\tcontextWindow: number;\n\tpreparation: CompactionPreparation;\n\tpromptVariant: MergedCompactionPromptVariant;\n\tcustomInstructions?: string;\n}\n\nexport type SpeculativeCompactionResult = ApplyCompactionResult | { applied: false; reason: \"unavailable\" };\n\nexport type ExtensionCompactionRequest = {\n\tcustomInstructions?: string;\n\tgeneration: number;\n\tsignal?: AbortSignal;\n};\n\nfunction approxTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction getSummaryText(message: Message): string {\n\tconst content = Array.isArray(message.content)\n\t\t? message.content\n\t\t: [{ type: \"text\" as const, text: message.content }];\n\treturn content\n\t\t.filter((content): content is TextContent => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\")\n\t\t.trim();\n}\n\nfunction pruneToolResults(messages: AgentMessage[], contextWindow: number): AgentMessage[] {\n\tconst toolResults = messages\n\t\t.filter((message) => message.role === \"toolResult\")\n\t\t.map((message) => ({ content: message.content, details: undefined }));\n\tif (toolResults.length === 0) return messages;\n\n\tconst prunedResults = truncation.prePruneToolOutputsToBudget(toolResults, contextWindow * COMPACTION_BUDGET_RATIO);\n\tlet resultIndex = 0;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"toolResult\") return message;\n\t\tconst pruned = prunedResults[resultIndex];\n\t\tresultIndex++;\n\t\treturn pruned ? { ...message, content: pruned.content } : message;\n\t});\n}\n\nexport function truncateContextMessages(messages: AgentMessage[]): AgentMessage[] {\n\tconst toolResults = messages\n\t\t.filter((message) => message.role === \"toolResult\")\n\t\t.map((message) => ({ content: message.content, details: undefined }));\n\tif (toolResults.length === 0) return messages;\n\n\tconst truncatedResults = truncation.truncateOversizedToolResults(toolResults);\n\tlet resultIndex = 0;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"toolResult\") return message;\n\t\tconst truncated = truncatedResults[resultIndex];\n\t\tresultIndex++;\n\t\treturn truncated ? { ...message, content: truncated.content } : message;\n\t});\n}\n\nfunction getToolCallIds(message: AgentMessage): Set<string> {\n\tconst ids = new Set<string>();\n\tif (message.role !== \"assistant\") return ids;\n\tfor (const block of message.content) {\n\t\tif (block.type === \"toolCall\") ids.add(block.id);\n\t}\n\treturn ids;\n}\n\nfunction findLastUserLikeIndex(messages: AgentMessage[]): number {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst role = messages[index]?.role;\n\t\tif (role === \"user\" || role === \"bashExecution\") return index;\n\t}\n\treturn messages.length;\n}\n\nfunction removeAssistantToolPair(messages: AgentMessage[], assistantIndex: number): AgentMessage[] {\n\tconst ids = getToolCallIds(messages[assistantIndex]);\n\treturn messages.filter((message, index) => {\n\t\tif (index === assistantIndex) return false;\n\t\treturn message.role !== \"toolResult\" || !ids.has(message.toolCallId);\n\t});\n}\n\nfunction removeFirstOldToolPair(messages: AgentMessage[], boundaryIndex: number): AgentMessage[] | undefined {\n\tfor (let index = 0; index < boundaryIndex; index++) {\n\t\tconst message = messages[index];\n\t\tif (!message) continue;\n\t\tif (message.role === \"assistant\" && getToolCallIds(message).size > 0)\n\t\t\treturn removeAssistantToolPair(messages, index);\n\t\tif (message.role === \"toolResult\") return messages.filter((_message, candidateIndex) => candidateIndex !== index);\n\t}\n\treturn undefined;\n}\n\nfunction removeFirstOldMessage(messages: AgentMessage[], boundaryIndex: number): AgentMessage[] | undefined {\n\tfor (let index = 0; index < boundaryIndex; index++) {\n\t\tconst message = messages[index];\n\t\tif (!message || message.role === \"toolResult\") continue;\n\t\tif (message.role === \"assistant\" && getToolCallIds(message).size > 0)\n\t\t\treturn removeAssistantToolPair(messages, index);\n\t\treturn messages.filter((_candidate, candidateIndex) => candidateIndex !== index);\n\t}\n\treturn undefined;\n}\n\nfunction pruneOldMessagesToBudget(messages: AgentMessage[], targetTokens: number): AgentMessage[] {\n\tlet pruned = messages;\n\twhile (estimateTotalTokens(pruned) > targetTokens) {\n\t\tconst boundaryIndex = findLastUserLikeIndex(pruned);\n\t\tconst next = removeFirstOldToolPair(pruned, boundaryIndex) ?? removeFirstOldMessage(pruned, boundaryIndex);\n\t\tif (!next || next.length === pruned.length) break;\n\t\tpruned = next;\n\t}\n\treturn pruned;\n}\n\nfunction estimateTotalTokens(messages: AgentMessage[]): number {\n\tlet total = 0;\n\tfor (const message of messages) total += estimateTokens(message);\n\treturn total;\n}\n\nexport function hardLimitEmergencyPrune(\n\tmessages: AgentMessage[],\n\tcontextWindow: number,\n): {\n\tmessages: AgentMessage[];\n\tneedsAggressiveCompaction: boolean;\n} {\n\tconst targetTokens = Math.floor(contextWindow * EMERGENCY_CONTEXT_TARGET_RATIO);\n\tconst noLlmPruned = truncateContextMessages(pruneToolResults(messages, contextWindow));\n\tif (estimateTotalTokens(noLlmPruned) <= targetTokens) {\n\t\treturn { messages: noLlmPruned, needsAggressiveCompaction: false };\n\t}\n\treturn {\n\t\tmessages: pruneOldMessagesToBudget(noLlmPruned, targetTokens),\n\t\tneedsAggressiveCompaction: true,\n\t};\n}\n\nexport function getPromptVariant(options: {\n\treason: string;\n\tpreparation: { previousSummary?: string; isSplitTurn: boolean };\n}): MergedCompactionPromptVariant {\n\tif (options.reason === \"branch\") return \"branch\";\n\tif (options.preparation.previousSummary) return \"update\";\n\tif (options.preparation.isSplitTurn) return \"turn_prefix\";\n\treturn \"default\";\n}\n\nexport function createSpeculativeCompactionSnapshot(\n\tcontext: SpeculativeCompactionContext,\n\toptions: { customInstructions?: string; generation: number },\n): SpeculativeCompactionSnapshot | undefined {\n\tconst model = context.model;\n\tif (!model) return undefined;\n\n\tconst expectedRevision = context.getMessageRevision();\n\tconst branchEntries = context.sessionManager.getBranch();\n\tconst contextWindow = context.getContextUsage()?.contextWindow ?? model.contextWindow ?? DEFAULT_CONTEXT_WINDOW;\n\tconst settings = context.getCompactionSettings?.() ?? DEFAULT_COMPACTION_SETTINGS;\n\tconst thresholdRatio = computeEffectiveThreshold(contextWindow);\n\tconst preparation = prepareCompaction(branchEntries, {\n\t\t...settings,\n\t\tkeepRecentTokens: computeEffectiveKeepRecentTokens(settings.keepRecentTokens, contextWindow, thresholdRatio),\n\t});\n\tif (!preparation) return undefined;\n\n\treturn {\n\t\tgeneration: options.generation,\n\t\texpectedRevision,\n\t\tmodel,\n\t\tcontextWindow,\n\t\tpreparation,\n\t\tpromptVariant: getPromptVariant({ reason: \"extension\", preparation }),\n\t\tcustomInstructions: options.customInstructions,\n\t};\n}\n\nexport async function runExtensionCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot,\n\tsignal?: AbortSignal,\n): Promise<CompactionResult | undefined> {\n\tconst auth = await context.modelRegistry?.getApiKeyAndHeaders(snapshot.model);\n\tif (!auth?.ok || !auth.apiKey) return undefined;\n\n\tconst messages = pruneToolResults(\n\t\t[...snapshot.preparation.messagesToSummarize, ...snapshot.preparation.turnPrefixMessages],\n\t\tsnapshot.contextWindow,\n\t);\n\tconst prompt = buildPrompt({\n\t\tvariant: snapshot.promptVariant,\n\t\tpreviousSummary: snapshot.preparation.previousSummary,\n\t\tcustomInstructions: snapshot.customInstructions,\n\t});\n\tconst conversationText = serializeConversation(convertToLlm(messages));\n\tconst response = await complete(\n\t\tsnapshot.model,\n\t\t{\n\t\t\tsystemPrompt: prompt.system,\n\t\t\tmessages: [\n\t\t\t\t{\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{ type: \"text\", text: `${prompt.user}\\n\\n<conversation>\\n${conversationText}\\n</conversation>` },\n\t\t\t\t\t],\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tapiKey: auth.apiKey,\n\t\t\theaders: auth.headers,\n\t\t\textraBody: auth.extraBody,\n\t\t\tmaxTokens: MAX_SUMMARY_TOKENS,\n\t\t\tsignal,\n\t\t},\n\t);\n\tconst summary = getSummaryText(response);\n\tif (!summary) return undefined;\n\n\tconst tokenEstimate = estimateContextTokens(convertToLlm(messages)).tokens + approxTokens(summary);\n\tif (tokenEstimate > snapshot.contextWindow * COMPACTION_BUDGET_RATIO) return undefined;\n\n\treturn {\n\t\tsummary,\n\t\tfirstKeptEntryId: snapshot.preparation.firstKeptEntryId,\n\t\ttokensBefore: snapshot.preparation.tokensBefore,\n\t\tdetails: { schema: SUMMARY_SCHEMA, promptVariant: snapshot.promptVariant, tokenEstimate },\n\t};\n}\n\nexport async function applyGeneratedCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tcompaction: CompactionResult | undefined,\n): Promise<SpeculativeCompactionResult> {\n\tif (!snapshot || !compaction) return { applied: false, reason: \"unavailable\" };\n\n\tif (snapshot.generation !== getCurrentGeneration() || snapshot.expectedRevision !== context.getMessageRevision()) {\n\t\treturn { applied: false, reason: \"stale\" };\n\t}\n\n\treturn await context.applyCompaction(compaction, {\n\t\treason: \"extension\",\n\t\texpectedRevision: snapshot.expectedRevision,\n\t});\n}\n\nexport function snapshotExtensionCompaction(\n\tcontext: SpeculativeCompactionContext,\n\trequest: ExtensionCompactionRequest,\n): SpeculativeCompactionSnapshot | undefined {\n\treturn createSpeculativeCompactionSnapshot(context, request);\n}\n\nexport async function applySpeculativeCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tgenerate: () => Promise<CompactionResult | undefined>,\n): Promise<SpeculativeCompactionResult> {\n\tif (!snapshot) return { applied: false, reason: \"unavailable\" };\n\n\tconst compaction = await generate();\n\treturn await applyGeneratedCompaction(context, snapshot, getCurrentGeneration, compaction);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"speculative.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/speculative.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@earendil-works/pi-agent-core\";\nimport {\n\ttype AssistantMessage,\n\tisContextOverflow,\n\ttype Message,\n\ttype Model,\n\tstream,\n\ttype TextContent,\n} from \"@earendil-works/pi-ai\";\nimport {\n\ttype CompactionPreparation,\n\ttype CompactionResult,\n\tDEFAULT_COMPACTION_SETTINGS,\n\testimateContextTokens,\n\testimateTokens,\n\tprepareCompaction,\n\tserializeConversation,\n} from \"../../../compaction/index.js\";\nimport { convertToLlm } from \"../../../messages.js\";\nimport type { ModelRegistry } from \"../../../model-registry.js\";\nimport type { ReadonlySessionManager } from \"../../../session-manager.js\";\nimport type { ApplyCompactionResult, ContextUsage } from \"../../types.js\";\nimport { computeEffectiveKeepRecentTokens, computeEffectiveThreshold } from \"./policy.js\";\nimport { buildPrompt, type MergedCompactionPromptVariant } from \"./prompts.js\";\nimport * as truncation from \"./tool-truncation.js\";\n\nconst DEFAULT_CONTEXT_WINDOW = 200_000;\nconst COMPACTION_BUDGET_RATIO = 0.6;\nconst COMPACTION_RETRY_BUDGET_RATIO = 0.4;\nconst EMERGENCY_CONTEXT_TARGET_RATIO = 0.95;\nconst MAX_SUMMARY_TOKENS = 8192;\nconst SUMMARY_SCHEMA = \"senpi.compaction.summary.v1\";\ntype CompactionProgressCallback = (delta: string) => void;\n\nexport interface SpeculativeCompactionContext {\n\tmodel: Model<any> | undefined;\n\tsessionManager: ReadonlySessionManager;\n\tmodelRegistry?: ModelRegistry;\n\tgetContextUsage(): ContextUsage | undefined;\n\tgetCompactionSettings?(): CompactionPreparation[\"settings\"];\n\tgetMessageRevision(): number;\n\tapplyCompaction(\n\t\tprecomputed: CompactionResult,\n\t\toptions: { reason: \"extension\"; expectedRevision: number },\n\t): Promise<ApplyCompactionResult>;\n}\n\nexport interface SpeculativeCompactionSnapshot {\n\tgeneration: number;\n\texpectedRevision: number;\n\tmodel: Model<any>;\n\tcontextWindow: number;\n\tpreparation: CompactionPreparation;\n\tpromptVariant: MergedCompactionPromptVariant;\n\tcustomInstructions?: string;\n}\n\nexport type SpeculativeCompactionResult = ApplyCompactionResult | { applied: false; reason: \"unavailable\" };\n\nexport type ExtensionCompactionRequest = {\n\tcustomInstructions?: string;\n\tgeneration: number;\n\tsignal?: AbortSignal;\n};\n\nfunction approxTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction getSummaryText(message: Message): string {\n\tconst content = Array.isArray(message.content)\n\t\t? message.content\n\t\t: [{ type: \"text\" as const, text: message.content }];\n\treturn content\n\t\t.filter((content): content is TextContent => content.type === \"text\")\n\t\t.map((content) => content.text)\n\t\t.join(\"\\n\")\n\t\t.trim();\n}\n\nfunction isAssistantMessage(message: Message): message is AssistantMessage {\n\treturn message.role === \"assistant\" && \"stopReason\" in message;\n}\n\nasync function generateSummaryMessage(options: {\n\tmessages: AgentMessage[];\n\tonProgress?: CompactionProgressCallback;\n\tprompt: ReturnType<typeof buildPrompt>;\n\tsignal?: AbortSignal;\n\tsnapshot: SpeculativeCompactionSnapshot;\n\tauth: {\n\t\tapiKey: string;\n\t\theaders?: Record<string, string>;\n\t\textraBody?: Record<string, unknown>;\n\t};\n}): Promise<Message | undefined> {\n\tconst conversationText = serializeConversation(convertToLlm(options.messages));\n\tconst responseStream = stream(\n\t\toptions.snapshot.model,\n\t\t{\n\t\t\tsystemPrompt: options.prompt.system,\n\t\t\tmessages: [\n\t\t\t\t{\n\t\t\t\t\trole: \"user\",\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\t\ttext: `${options.prompt.user}\\n\\n<conversation>\\n${conversationText}\\n</conversation>`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t\t{\n\t\t\tapiKey: options.auth.apiKey,\n\t\t\theaders: options.auth.headers,\n\t\t\textraBody: options.auth.extraBody,\n\t\t\tmaxTokens: MAX_SUMMARY_TOKENS,\n\t\t\tsignal: options.signal,\n\t\t},\n\t);\n\tfor await (const event of responseStream) {\n\t\tif (event.type === \"text_delta\" && event.delta) {\n\t\t\toptions.onProgress?.(event.delta);\n\t\t}\n\t}\n\treturn await responseStream.result();\n}\n\nfunction pruneToolResults(messages: AgentMessage[], contextWindow: number): AgentMessage[] {\n\tconst toolResults = messages\n\t\t.filter((message) => message.role === \"toolResult\")\n\t\t.map((message) => ({ content: message.content, details: undefined }));\n\tif (toolResults.length === 0) return messages;\n\n\tconst prunedResults = truncation.prePruneToolOutputsToBudget(toolResults, contextWindow * COMPACTION_BUDGET_RATIO);\n\tlet resultIndex = 0;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"toolResult\") return message;\n\t\tconst pruned = prunedResults[resultIndex];\n\t\tresultIndex++;\n\t\treturn pruned ? { ...message, content: pruned.content } : message;\n\t});\n}\n\nexport function truncateContextMessages(messages: AgentMessage[]): AgentMessage[] {\n\tconst toolResults = messages\n\t\t.filter((message) => message.role === \"toolResult\")\n\t\t.map((message) => ({ content: message.content, details: undefined }));\n\tif (toolResults.length === 0) return messages;\n\n\tconst truncatedResults = truncation.truncateOversizedToolResults(toolResults);\n\tlet resultIndex = 0;\n\treturn messages.map((message) => {\n\t\tif (message.role !== \"toolResult\") return message;\n\t\tconst truncated = truncatedResults[resultIndex];\n\t\tresultIndex++;\n\t\treturn truncated ? { ...message, content: truncated.content } : message;\n\t});\n}\n\nfunction getToolCallIds(message: AgentMessage): Set<string> {\n\tconst ids = new Set<string>();\n\tif (message.role !== \"assistant\") return ids;\n\tfor (const block of message.content) {\n\t\tif (block.type === \"toolCall\") ids.add(block.id);\n\t}\n\treturn ids;\n}\n\nfunction findLastUserLikeIndex(messages: AgentMessage[]): number {\n\tfor (let index = messages.length - 1; index >= 0; index--) {\n\t\tconst role = messages[index]?.role;\n\t\tif (role === \"user\" || role === \"bashExecution\") return index;\n\t}\n\treturn messages.length;\n}\n\nfunction removeAssistantToolPair(messages: AgentMessage[], assistantIndex: number): AgentMessage[] {\n\tconst ids = getToolCallIds(messages[assistantIndex]);\n\treturn messages.filter((message, index) => {\n\t\tif (index === assistantIndex) return false;\n\t\treturn message.role !== \"toolResult\" || !ids.has(message.toolCallId);\n\t});\n}\n\nfunction removeFirstOldToolPair(messages: AgentMessage[], boundaryIndex: number): AgentMessage[] | undefined {\n\tfor (let index = 0; index < boundaryIndex; index++) {\n\t\tconst message = messages[index];\n\t\tif (!message) continue;\n\t\tif (message.role === \"assistant\" && getToolCallIds(message).size > 0)\n\t\t\treturn removeAssistantToolPair(messages, index);\n\t\tif (message.role === \"toolResult\") return messages.filter((_message, candidateIndex) => candidateIndex !== index);\n\t}\n\treturn undefined;\n}\n\nfunction removeFirstOldMessage(messages: AgentMessage[], boundaryIndex: number): AgentMessage[] | undefined {\n\tfor (let index = 0; index < boundaryIndex; index++) {\n\t\tconst message = messages[index];\n\t\tif (!message || message.role === \"toolResult\") continue;\n\t\tif (message.role === \"assistant\" && getToolCallIds(message).size > 0)\n\t\t\treturn removeAssistantToolPair(messages, index);\n\t\treturn messages.filter((_candidate, candidateIndex) => candidateIndex !== index);\n\t}\n\treturn undefined;\n}\n\nfunction pruneOldMessagesToBudget(messages: AgentMessage[], targetTokens: number): AgentMessage[] {\n\tlet pruned = messages;\n\twhile (estimateTotalTokens(pruned) > targetTokens) {\n\t\tconst boundaryIndex = findLastUserLikeIndex(pruned);\n\t\tconst next = removeFirstOldToolPair(pruned, boundaryIndex) ?? removeFirstOldMessage(pruned, boundaryIndex);\n\t\tif (!next || next.length === pruned.length) break;\n\t\tpruned = next;\n\t}\n\treturn pruned;\n}\n\nfunction pruneMessagesForOverflowRetry(messages: AgentMessage[], targetTokens: number): AgentMessage[] | undefined {\n\tconst budgetPruned = pruneOldMessagesToBudget(messages, targetTokens);\n\tif (budgetPruned.length < messages.length) return budgetPruned;\n\tconst boundaryIndex = findLastUserLikeIndex(messages);\n\treturn (\n\t\tremoveFirstOldToolPair(messages, boundaryIndex) ??\n\t\tremoveFirstOldMessage(messages, boundaryIndex) ??\n\t\t(messages.length > 1 ? messages.slice(1) : undefined)\n\t);\n}\n\nfunction estimateTotalTokens(messages: AgentMessage[]): number {\n\tlet total = 0;\n\tfor (const message of messages) total += estimateTokens(message);\n\treturn total;\n}\n\nexport function hardLimitEmergencyPrune(\n\tmessages: AgentMessage[],\n\tcontextWindow: number,\n): {\n\tmessages: AgentMessage[];\n\tneedsAggressiveCompaction: boolean;\n} {\n\tconst targetTokens = Math.floor(contextWindow * EMERGENCY_CONTEXT_TARGET_RATIO);\n\tconst noLlmPruned = truncateContextMessages(pruneToolResults(messages, contextWindow));\n\tif (estimateTotalTokens(noLlmPruned) <= targetTokens) {\n\t\treturn { messages: noLlmPruned, needsAggressiveCompaction: false };\n\t}\n\treturn {\n\t\tmessages: pruneOldMessagesToBudget(noLlmPruned, targetTokens),\n\t\tneedsAggressiveCompaction: true,\n\t};\n}\n\nexport function getPromptVariant(options: {\n\treason: string;\n\tpreparation: { previousSummary?: string; isSplitTurn: boolean };\n}): MergedCompactionPromptVariant {\n\tif (options.reason === \"branch\") return \"branch\";\n\tif (options.preparation.previousSummary) return \"update\";\n\tif (options.preparation.isSplitTurn) return \"turn_prefix\";\n\treturn \"default\";\n}\n\nexport function createSpeculativeCompactionSnapshot(\n\tcontext: SpeculativeCompactionContext,\n\toptions: { customInstructions?: string; generation: number },\n): SpeculativeCompactionSnapshot | undefined {\n\tconst model = context.model;\n\tif (!model) return undefined;\n\n\tconst expectedRevision = context.getMessageRevision();\n\tconst branchEntries = context.sessionManager.getBranch();\n\tconst contextWindow = context.getContextUsage()?.contextWindow ?? model.contextWindow ?? DEFAULT_CONTEXT_WINDOW;\n\tconst settings = context.getCompactionSettings?.() ?? DEFAULT_COMPACTION_SETTINGS;\n\tconst thresholdRatio = computeEffectiveThreshold(contextWindow);\n\tconst preparation = prepareCompaction(branchEntries, {\n\t\t...settings,\n\t\tkeepRecentTokens: computeEffectiveKeepRecentTokens(settings.keepRecentTokens, contextWindow, thresholdRatio),\n\t});\n\tif (!preparation) return undefined;\n\n\treturn {\n\t\tgeneration: options.generation,\n\t\texpectedRevision,\n\t\tmodel,\n\t\tcontextWindow,\n\t\tpreparation,\n\t\tpromptVariant: getPromptVariant({ reason: \"extension\", preparation }),\n\t\tcustomInstructions: options.customInstructions,\n\t};\n}\n\nexport async function runExtensionCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot,\n\tsignal?: AbortSignal,\n\tonProgress?: CompactionProgressCallback,\n): Promise<CompactionResult | undefined> {\n\tconst auth = await context.modelRegistry?.getApiKeyAndHeaders(snapshot.model);\n\tif (!auth?.ok || !auth.apiKey) return undefined;\n\n\tlet messages = pruneToolResults(\n\t\t[...snapshot.preparation.messagesToSummarize, ...snapshot.preparation.turnPrefixMessages],\n\t\tsnapshot.contextWindow,\n\t);\n\tconst prompt = buildPrompt({\n\t\tvariant: snapshot.promptVariant,\n\t\tpreviousSummary: snapshot.preparation.previousSummary,\n\t\tcustomInstructions: snapshot.customInstructions,\n\t});\n\n\tfor (let attempt = 0; attempt < 2; attempt++) {\n\t\tconst response = await generateSummaryMessage({\n\t\t\tmessages,\n\t\t\tonProgress,\n\t\t\tprompt,\n\t\t\tsignal,\n\t\t\tsnapshot,\n\t\t\tauth: {\n\t\t\t\tapiKey: auth.apiKey,\n\t\t\t\theaders: auth.headers,\n\t\t\t\textraBody: auth.extraBody,\n\t\t\t},\n\t\t});\n\t\tif (!response) return undefined;\n\n\t\tif (isAssistantMessage(response) && isContextOverflow(response, snapshot.contextWindow)) {\n\t\t\tconst retryMessages = pruneMessagesForOverflowRetry(\n\t\t\t\tmessages,\n\t\t\t\tMath.floor(snapshot.contextWindow * COMPACTION_RETRY_BUDGET_RATIO),\n\t\t\t);\n\t\t\tif (!retryMessages || retryMessages.length === messages.length) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tmessages = retryMessages;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst summary = getSummaryText(response);\n\t\tif (!summary) return undefined;\n\n\t\tconst tokenEstimate = estimateContextTokens(convertToLlm(messages)).tokens + approxTokens(summary);\n\t\tif (tokenEstimate > snapshot.contextWindow * COMPACTION_BUDGET_RATIO) return undefined;\n\n\t\treturn {\n\t\t\tsummary,\n\t\t\tfirstKeptEntryId: snapshot.preparation.firstKeptEntryId,\n\t\t\ttokensBefore: snapshot.preparation.tokensBefore,\n\t\t\tdetails: { schema: SUMMARY_SCHEMA, promptVariant: snapshot.promptVariant, tokenEstimate },\n\t\t};\n\t}\n\n\tthrow new Error(\"Compaction summary request exceeded the context window after retrying with a smaller input\");\n}\n\nexport async function applyGeneratedCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tcompaction: CompactionResult | undefined,\n): Promise<SpeculativeCompactionResult> {\n\tif (!snapshot || !compaction) return { applied: false, reason: \"unavailable\" };\n\n\tif (snapshot.generation !== getCurrentGeneration() || snapshot.expectedRevision !== context.getMessageRevision()) {\n\t\treturn { applied: false, reason: \"stale\" };\n\t}\n\n\treturn await context.applyCompaction(compaction, {\n\t\treason: \"extension\",\n\t\texpectedRevision: snapshot.expectedRevision,\n\t});\n}\n\nexport function snapshotExtensionCompaction(\n\tcontext: SpeculativeCompactionContext,\n\trequest: ExtensionCompactionRequest,\n): SpeculativeCompactionSnapshot | undefined {\n\treturn createSpeculativeCompactionSnapshot(context, request);\n}\n\nexport async function applySpeculativeCompaction(\n\tcontext: SpeculativeCompactionContext,\n\tsnapshot: SpeculativeCompactionSnapshot | undefined,\n\tgetCurrentGeneration: () => number,\n\tgenerate: () => Promise<CompactionResult | undefined>,\n): Promise<SpeculativeCompactionResult> {\n\tif (!snapshot) return { applied: false, reason: \"unavailable\" };\n\n\tconst compaction = await generate();\n\treturn await applyGeneratedCompaction(context, snapshot, getCurrentGeneration, compaction);\n}\n"]}
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import type { SessionEntry } from "../../../session-manager.js";
|
|
2
2
|
import type { ExtensionAPI, ExtensionContext } from "../../types.js";
|
|
3
|
+
declare const TODO_SNAPSHOT_SCHEMA = "senpi.compaction.todo-snapshot.v1";
|
|
3
4
|
export interface TodoEntry {
|
|
4
5
|
id: string;
|
|
5
6
|
content?: string;
|
|
6
7
|
text?: string;
|
|
7
8
|
status?: "pending" | "in_progress" | "completed" | "cancelled";
|
|
8
9
|
}
|
|
10
|
+
export interface TodoSnapshotPayload {
|
|
11
|
+
schema: typeof TODO_SNAPSHOT_SCHEMA;
|
|
12
|
+
todos: TodoEntry[] | SessionEntry[];
|
|
13
|
+
capturedAt: number;
|
|
14
|
+
}
|
|
9
15
|
interface AppendEntryTarget {
|
|
10
16
|
appendEntry<T = unknown>(customType: string, data?: T): void;
|
|
11
17
|
}
|
|
@@ -17,6 +23,8 @@ export declare function findTodoEntries(ctx: ExtensionContext): SessionEntry[];
|
|
|
17
23
|
export declare function findTodoEntries(entries: SessionEntry[], options?: {
|
|
18
24
|
branchId?: string;
|
|
19
25
|
}): TodoEntry[];
|
|
26
|
+
export declare function createTodoSnapshot(ctx: ExtensionContext): TodoSnapshotPayload;
|
|
27
|
+
export declare function persistTodoSnapshot(pi: AppendEntryTarget, snapshot: TodoSnapshotPayload): void;
|
|
20
28
|
export declare function captureTodoSnapshot(pi: ExtensionAPI, ctx: ExtensionContext): void;
|
|
21
29
|
export declare function captureTodoSnapshot(currentTodos: TodoEntry[], pi: AppendEntryTarget, branchId?: string): void;
|
|
22
30
|
export declare function restoreTodosIfMissing(pi: ExtensionAPI, ctx: ExtensionContext): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"todo-bridge.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/todo-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"todo-bridge.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/todo-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAe,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAGrE,QAAA,MAAM,oBAAoB,sCAAsC,CAAC;AAEjE,MAAM,WAAW,SAAS;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,SAAS,GAAG,aAAa,GAAG,WAAW,GAAG,WAAW,CAAC;CAC/D;AAED,MAAM,WAAW,mBAAmB;IACnC,MAAM,EAAE,OAAO,oBAAoB,CAAC;IACpC,KAAK,EAAE,SAAS,EAAE,GAAG,YAAY,EAAE,CAAC;IACpC,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,iBAAiB;IAC1B,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC;CAC7D;AASD,UAAU,aAAa;IACtB,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,SAAS,EAAE,CAAC;CAC3B;AAiCD,wBAAgB,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,YAAY,EAAE,CAAC;AACvE,wBAAgB,eAAe,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,OAAO,CAAC,EAAE;IAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,EAAE,CAAC;AAevG,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,mBAAmB,CAM7E;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,iBAAiB,EAAE,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAE9F;AAED,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAC;AACnF,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,SAAS,EAAE,EAAE,EAAE,EAAE,iBAAiB,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;AAmB/G,wBAAgB,qBAAqB,CAAC,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,gBAAgB,GAAG,IAAI,CAAC;AACrF,wBAAgB,qBAAqB,CACpC,QAAQ,EAAE,SAAS,EAAE,EACrB,YAAY,EAAE,SAAS,EAAE,EACzB,EAAE,EAAE,iBAAiB,GACnB,aAAa,CAAC","sourcesContent":["import type { CustomEntry, SessionEntry } from \"../../../session-manager.js\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.js\";\n\nconst TODO_SNAPSHOT_CUSTOM_TYPE = \"compaction.todo-snapshot\";\nconst TODO_SNAPSHOT_SCHEMA = \"senpi.compaction.todo-snapshot.v1\";\n\nexport interface TodoEntry {\n\tid: string;\n\tcontent?: string;\n\ttext?: string;\n\tstatus?: \"pending\" | \"in_progress\" | \"completed\" | \"cancelled\";\n}\n\nexport interface TodoSnapshotPayload {\n\tschema: typeof TODO_SNAPSHOT_SCHEMA;\n\ttodos: TodoEntry[] | SessionEntry[];\n\tcapturedAt: number;\n}\n\ninterface AppendEntryTarget {\n\tappendEntry<T = unknown>(customType: string, data?: T): void;\n}\n\ninterface SendMessageTarget extends AppendEntryTarget {\n\tsendMessage<T = unknown>(\n\t\tmessage: { customType: string; content: string; display: boolean; details?: T },\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): void;\n}\n\ninterface RestoreResult {\n\tapplied: boolean;\n\trestoredTodos: TodoEntry[];\n}\n\nfunction isCustomTodoEntry(entry: SessionEntry): entry is CustomEntry {\n\treturn entry.type === \"custom\" && entry.customType.startsWith(\"todowrite\");\n}\n\nfunction isLegacyTodoListEntry(entry: SessionEntry): entry is CustomEntry {\n\treturn entry.type === \"custom\" && entry.customType === \"todo-list\";\n}\n\nfunction readTodosFromEntry(entry: CustomEntry): TodoEntry[] {\n\tconst data = entry.data;\n\tif (typeof data !== \"object\" || data === null || !(\"todos\" in data) || !Array.isArray(data.todos)) {\n\t\treturn [];\n\t}\n\treturn data.todos.filter((todo): todo is TodoEntry => {\n\t\treturn typeof todo === \"object\" && todo !== null && \"id\" in todo && typeof todo.id === \"string\";\n\t});\n}\n\nfunction findLatestTodoSnapshot(ctx: ExtensionContext): TodoSnapshotPayload | null {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry.type !== \"custom\" || entry.customType !== TODO_SNAPSHOT_CUSTOM_TYPE) continue;\n\t\tconst data = entry.data;\n\t\tif (typeof data === \"object\" && data !== null && \"schema\" in data && data.schema === TODO_SNAPSHOT_SCHEMA) {\n\t\t\treturn data as TodoSnapshotPayload;\n\t\t}\n\t}\n\treturn null;\n}\n\nexport function findTodoEntries(ctx: ExtensionContext): SessionEntry[];\nexport function findTodoEntries(entries: SessionEntry[], options?: { branchId?: string }): TodoEntry[];\nexport function findTodoEntries(\n\tctxOrEntries: ExtensionContext | SessionEntry[],\n\toptions?: { branchId?: string },\n): SessionEntry[] | TodoEntry[] {\n\tif (Array.isArray(ctxOrEntries)) {\n\t\treturn ctxOrEntries\n\t\t\t.filter(isLegacyTodoListEntry)\n\t\t\t.filter((entry) => options?.branchId === undefined || entry.parentId === options.branchId)\n\t\t\t.flatMap(readTodosFromEntry);\n\t}\n\n\treturn ctxOrEntries.sessionManager.getEntries().filter(isCustomTodoEntry);\n}\n\nexport function createTodoSnapshot(ctx: ExtensionContext): TodoSnapshotPayload {\n\treturn {\n\t\tschema: TODO_SNAPSHOT_SCHEMA,\n\t\ttodos: findTodoEntries(ctx),\n\t\tcapturedAt: Date.now(),\n\t};\n}\n\nexport function persistTodoSnapshot(pi: AppendEntryTarget, snapshot: TodoSnapshotPayload): void {\n\tpi.appendEntry(TODO_SNAPSHOT_CUSTOM_TYPE, snapshot);\n}\n\nexport function captureTodoSnapshot(pi: ExtensionAPI, ctx: ExtensionContext): void;\nexport function captureTodoSnapshot(currentTodos: TodoEntry[], pi: AppendEntryTarget, branchId?: string): void;\nexport function captureTodoSnapshot(\n\tpiOrTodos: ExtensionAPI | TodoEntry[],\n\tctxOrPi: ExtensionContext | AppendEntryTarget,\n\t_branchId?: string,\n): void {\n\tif (Array.isArray(piOrTodos)) {\n\t\tconst pi = ctxOrPi as AppendEntryTarget;\n\t\tpersistTodoSnapshot(pi, {\n\t\t\tschema: TODO_SNAPSHOT_SCHEMA,\n\t\t\ttodos: piOrTodos,\n\t\t\tcapturedAt: Date.now(),\n\t\t});\n\t\treturn;\n\t}\n\n\tpersistTodoSnapshot(piOrTodos, createTodoSnapshot(ctxOrPi as ExtensionContext));\n}\n\nexport function restoreTodosIfMissing(pi: ExtensionAPI, ctx: ExtensionContext): void;\nexport function restoreTodosIfMissing(\n\tsnapshot: TodoEntry[],\n\tcurrentTodos: TodoEntry[],\n\tpi: AppendEntryTarget,\n): RestoreResult;\nexport function restoreTodosIfMissing(\n\tpiOrSnapshot: ExtensionAPI | TodoEntry[],\n\tctxOrCurrentTodos: ExtensionContext | TodoEntry[],\n\t_pi?: AppendEntryTarget,\n): undefined | RestoreResult {\n\tif (Array.isArray(piOrSnapshot) && Array.isArray(ctxOrCurrentTodos)) {\n\t\tif (ctxOrCurrentTodos.length > 0) {\n\t\t\treturn { applied: false, restoredTodos: ctxOrCurrentTodos };\n\t\t}\n\t\treturn { applied: piOrSnapshot.length > 0, restoredTodos: piOrSnapshot };\n\t}\n\n\tconst pi = piOrSnapshot as SendMessageTarget;\n\tconst ctx = ctxOrCurrentTodos as ExtensionContext;\n\tif (findTodoEntries(ctx).length > 0) return;\n\n\tconst snapshot = findLatestTodoSnapshot(ctx);\n\tif (!snapshot || snapshot.todos.length === 0) return;\n\n\tpi.sendMessage(\n\t\t{\n\t\t\tcustomType: \"compaction.todo-restore-request\",\n\t\t\tcontent: `Restore missing todowrite todos from snapshot: ${JSON.stringify(snapshot.todos)}`,\n\t\t\tdisplay: false,\n\t\t\tdetails: snapshot,\n\t\t},\n\t\t{ triggerTurn: true, deliverAs: \"nextTurn\" },\n\t);\n}\n"]}
|
|
@@ -37,21 +37,27 @@ export function findTodoEntries(ctxOrEntries, options) {
|
|
|
37
37
|
}
|
|
38
38
|
return ctxOrEntries.sessionManager.getEntries().filter(isCustomTodoEntry);
|
|
39
39
|
}
|
|
40
|
+
export function createTodoSnapshot(ctx) {
|
|
41
|
+
return {
|
|
42
|
+
schema: TODO_SNAPSHOT_SCHEMA,
|
|
43
|
+
todos: findTodoEntries(ctx),
|
|
44
|
+
capturedAt: Date.now(),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function persistTodoSnapshot(pi, snapshot) {
|
|
48
|
+
pi.appendEntry(TODO_SNAPSHOT_CUSTOM_TYPE, snapshot);
|
|
49
|
+
}
|
|
40
50
|
export function captureTodoSnapshot(piOrTodos, ctxOrPi, _branchId) {
|
|
41
51
|
if (Array.isArray(piOrTodos)) {
|
|
42
52
|
const pi = ctxOrPi;
|
|
43
|
-
pi
|
|
53
|
+
persistTodoSnapshot(pi, {
|
|
44
54
|
schema: TODO_SNAPSHOT_SCHEMA,
|
|
45
55
|
todos: piOrTodos,
|
|
46
56
|
capturedAt: Date.now(),
|
|
47
57
|
});
|
|
48
58
|
return;
|
|
49
59
|
}
|
|
50
|
-
piOrTodos
|
|
51
|
-
schema: TODO_SNAPSHOT_SCHEMA,
|
|
52
|
-
todos: findTodoEntries(ctxOrPi),
|
|
53
|
-
capturedAt: Date.now(),
|
|
54
|
-
});
|
|
60
|
+
persistTodoSnapshot(piOrTodos, createTodoSnapshot(ctxOrPi));
|
|
55
61
|
}
|
|
56
62
|
export function restoreTodosIfMissing(piOrSnapshot, ctxOrCurrentTodos, _pi) {
|
|
57
63
|
if (Array.isArray(piOrSnapshot) && Array.isArray(ctxOrCurrentTodos)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"todo-bridge.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/todo-bridge.ts"],"names":[],"mappings":"AAGA,MAAM,yBAAyB,GAAG,0BAA0B,CAAC;AAC7D,MAAM,oBAAoB,GAAG,mCAAmC,CAAC;AA+BjE,SAAS,iBAAiB,CAAC,KAAmB,EAAwB;IACrE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;AAAA,CAC3E;AAED,SAAS,qBAAqB,CAAC,KAAmB,EAAwB;IACzE,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,KAAK,WAAW,CAAC;AAAA,CACnE;AAED,SAAS,kBAAkB,CAAC,KAAkB,EAAe;IAC5D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACnG,OAAO,EAAE,CAAC;IACX,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAqB,EAAE,CAAC;QACrD,OAAO,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC;IAAA,CAChG,CAAC,CAAC;AAAA,CACH;AAED,SAAS,sBAAsB,CAAC,GAAqB,EAA8B;IAClF,MAAM,OAAO,GAAG,GAAG,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC;IAChD,KAAK,IAAI,KAAK,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,KAAK,IAAI,CAAC,EAAE,KAAK,EAAE,EAAE,CAAC;QAC1D,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,KAAK,yBAAyB;YAAE,SAAS;QACxF,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;QACxB,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,oBAAoB,EAAE,CAAC;YAC3G,OAAO,IAA2B,CAAC;QACpC,CAAC;IACF,CAAC;IACD,OAAO,IAAI,CAAC;AAAA,CACZ;AAID,MAAM,UAAU,eAAe,CAC9B,YAA+C,EAC/C,OAA+B,EACA;IAC/B,IAAI,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACjC,OAAO,YAAY;aACjB,MAAM,CAAC,qBAAqB,CAAC;aAC7B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,EAAE,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC;aACzF,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC/B,CAAC;IAED,OAAO,YAAY,CAAC,cAAc,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAAA,CAC1E;AAID,MAAM,UAAU,mBAAmB,CAClC,SAAqC,EACrC,OAA6C,EAC7C,SAAkB,EACX;IACP,IAAI,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,MAAM,EAAE,GAAG,OAA4B,CAAC;QACxC,
|
|
1
|
+
{"version":3,"file":"todo-bridge.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/compaction/todo-bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import type { CustomEntry, SessionEntry } from \"../../../session-manager.js\";\nimport type { ExtensionAPI, ExtensionContext } from \"../../types.js\";\n\nconst TODO_SNAPSHOT_CUSTOM_TYPE = \"compaction.todo-snapshot\";\nconst TODO_SNAPSHOT_SCHEMA = \"senpi.compaction.todo-snapshot.v1\";\n\nexport interface TodoEntry {\n\tid: string;\n\tcontent?: string;\n\ttext?: string;\n\tstatus?: \"pending\" | \"in_progress\" | \"completed\" | \"cancelled\";\n}\n\nexport interface TodoSnapshotPayload {\n\tschema: typeof TODO_SNAPSHOT_SCHEMA;\n\ttodos: TodoEntry[] | SessionEntry[];\n\tcapturedAt: number;\n}\n\ninterface AppendEntryTarget {\n\tappendEntry<T = unknown>(customType: string, data?: T): void;\n}\n\ninterface SendMessageTarget extends AppendEntryTarget {\n\tsendMessage<T = unknown>(\n\t\tmessage: { customType: string; content: string; display: boolean; details?: T },\n\t\toptions?: { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" },\n\t): void;\n}\n\ninterface RestoreResult {\n\tapplied: boolean;\n\trestoredTodos: TodoEntry[];\n}\n\nfunction isCustomTodoEntry(entry: SessionEntry): entry is CustomEntry {\n\treturn entry.type === \"custom\" && entry.customType.startsWith(\"todowrite\");\n}\n\nfunction isLegacyTodoListEntry(entry: SessionEntry): entry is CustomEntry {\n\treturn entry.type === \"custom\" && entry.customType === \"todo-list\";\n}\n\nfunction readTodosFromEntry(entry: CustomEntry): TodoEntry[] {\n\tconst data = entry.data;\n\tif (typeof data !== \"object\" || data === null || !(\"todos\" in data) || !Array.isArray(data.todos)) {\n\t\treturn [];\n\t}\n\treturn data.todos.filter((todo): todo is TodoEntry => {\n\t\treturn typeof todo === \"object\" && todo !== null && \"id\" in todo && typeof todo.id === \"string\";\n\t});\n}\n\nfunction findLatestTodoSnapshot(ctx: ExtensionContext): TodoSnapshotPayload | null {\n\tconst entries = ctx.sessionManager.getEntries();\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry.type !== \"custom\" || entry.customType !== TODO_SNAPSHOT_CUSTOM_TYPE) continue;\n\t\tconst data = entry.data;\n\t\tif (typeof data === \"object\" && data !== null && \"schema\" in data && data.schema === TODO_SNAPSHOT_SCHEMA) {\n\t\t\treturn data as TodoSnapshotPayload;\n\t\t}\n\t}\n\treturn null;\n}\n\nexport function findTodoEntries(ctx: ExtensionContext): SessionEntry[];\nexport function findTodoEntries(entries: SessionEntry[], options?: { branchId?: string }): TodoEntry[];\nexport function findTodoEntries(\n\tctxOrEntries: ExtensionContext | SessionEntry[],\n\toptions?: { branchId?: string },\n): SessionEntry[] | TodoEntry[] {\n\tif (Array.isArray(ctxOrEntries)) {\n\t\treturn ctxOrEntries\n\t\t\t.filter(isLegacyTodoListEntry)\n\t\t\t.filter((entry) => options?.branchId === undefined || entry.parentId === options.branchId)\n\t\t\t.flatMap(readTodosFromEntry);\n\t}\n\n\treturn ctxOrEntries.sessionManager.getEntries().filter(isCustomTodoEntry);\n}\n\nexport function createTodoSnapshot(ctx: ExtensionContext): TodoSnapshotPayload {\n\treturn {\n\t\tschema: TODO_SNAPSHOT_SCHEMA,\n\t\ttodos: findTodoEntries(ctx),\n\t\tcapturedAt: Date.now(),\n\t};\n}\n\nexport function persistTodoSnapshot(pi: AppendEntryTarget, snapshot: TodoSnapshotPayload): void {\n\tpi.appendEntry(TODO_SNAPSHOT_CUSTOM_TYPE, snapshot);\n}\n\nexport function captureTodoSnapshot(pi: ExtensionAPI, ctx: ExtensionContext): void;\nexport function captureTodoSnapshot(currentTodos: TodoEntry[], pi: AppendEntryTarget, branchId?: string): void;\nexport function captureTodoSnapshot(\n\tpiOrTodos: ExtensionAPI | TodoEntry[],\n\tctxOrPi: ExtensionContext | AppendEntryTarget,\n\t_branchId?: string,\n): void {\n\tif (Array.isArray(piOrTodos)) {\n\t\tconst pi = ctxOrPi as AppendEntryTarget;\n\t\tpersistTodoSnapshot(pi, {\n\t\t\tschema: TODO_SNAPSHOT_SCHEMA,\n\t\t\ttodos: piOrTodos,\n\t\t\tcapturedAt: Date.now(),\n\t\t});\n\t\treturn;\n\t}\n\n\tpersistTodoSnapshot(piOrTodos, createTodoSnapshot(ctxOrPi as ExtensionContext));\n}\n\nexport function restoreTodosIfMissing(pi: ExtensionAPI, ctx: ExtensionContext): void;\nexport function restoreTodosIfMissing(\n\tsnapshot: TodoEntry[],\n\tcurrentTodos: TodoEntry[],\n\tpi: AppendEntryTarget,\n): RestoreResult;\nexport function restoreTodosIfMissing(\n\tpiOrSnapshot: ExtensionAPI | TodoEntry[],\n\tctxOrCurrentTodos: ExtensionContext | TodoEntry[],\n\t_pi?: AppendEntryTarget,\n): undefined | RestoreResult {\n\tif (Array.isArray(piOrSnapshot) && Array.isArray(ctxOrCurrentTodos)) {\n\t\tif (ctxOrCurrentTodos.length > 0) {\n\t\t\treturn { applied: false, restoredTodos: ctxOrCurrentTodos };\n\t\t}\n\t\treturn { applied: piOrSnapshot.length > 0, restoredTodos: piOrSnapshot };\n\t}\n\n\tconst pi = piOrSnapshot as SendMessageTarget;\n\tconst ctx = ctxOrCurrentTodos as ExtensionContext;\n\tif (findTodoEntries(ctx).length > 0) return;\n\n\tconst snapshot = findLatestTodoSnapshot(ctx);\n\tif (!snapshot || snapshot.todos.length === 0) return;\n\n\tpi.sendMessage(\n\t\t{\n\t\t\tcustomType: \"compaction.todo-restore-request\",\n\t\t\tcontent: `Restore missing todowrite todos from snapshot: ${JSON.stringify(snapshot.todos)}`,\n\t\t\tdisplay: false,\n\t\t\tdetails: snapshot,\n\t\t},\n\t\t{ triggerTurn: true, deliverAs: \"nextTurn\" },\n\t);\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAKpD,OAAO,aAAa,MAAM,WAAW,CAAC;AACtC,OAAO,cAAc,MAAM,YAAY,CAAC;AAKxC,OAAO,wBAAwB,MAAM,wBAAwB,CAAC;AAK9D,OAAO,YAAY,MAAM,UAAU,CAAC;AAEpC,MAAM,WAAW,uBAAuB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,gBAAgB,CAAC;CAC1B;AAED,eAAO,MAAM,yBAAyB,wDAAyD,CAAC;AAEhG,eAAO,MAAM,+BAA+B;;;;;CAKoC,CAAC;AAEjF,eAAO,MAAM,iBAAiB,EAAE,uBAAuB,EAatD,CAAC","sourcesContent":["import type { ExtensionFactory } from \"../types.js\";\nimport anthropicBashExtension from \"./anthropic-bash/index.js\";\nimport anthropicWebSearchExtension from \"./anthropic-web-search/index.js\";\nimport bashTimeoutExtension from \"./bash-timeout/index.js\";\nimport compactionExtension from \"./compaction/index.js\";\nimport diffExtension from \"./diff.js\";\nimport filesExtension from \"./files.js\";\nimport gptApplyPatchExtension from \"./gpt-apply-patch/index.js\";\nimport openaiWebSearchExtension from \"./openai-web-search/index.js\";\nimport permissionSystemExtension from \"./permission-system/index.js\";\nimport promptPresetExtension from \"./prompt-preset/index.js\";\nimport promptUrlWidgetExtension from \"./prompt-url-widget.js\";\nimport redrawsExtension from \"./redraws.js\";\nimport serviceTierExtension from \"./service-tier.js\";\nimport todowriteExtension from \"./todotools/index.js\";\nimport toolPairGuardExtension from \"./tool-pair-guard/index.js\";\nimport tpsExtension from \"./tps.js\";\n\nexport interface BuiltinExtensionFactory {\n\tid: string;\n\tfactory: ExtensionFactory;\n}\n\nexport const globalDefaultExtensionIds = [\"diff\", \"files\", \"prompt-url-widget\", \"tps\"] as const;\n\nexport const globalDefaultExtensionFactories = {\n\tdiff: diffExtension,\n\tfiles: filesExtension,\n\t\"prompt-url-widget\": promptUrlWidgetExtension,\n\ttps: tpsExtension,\n} satisfies Record<(typeof globalDefaultExtensionIds)[number], ExtensionFactory>;\n\nexport const builtinExtensions: BuiltinExtensionFactory[] = [\n\t{ id: \"permission-system\", factory: permissionSystemExtension },\n\t{ id: \"gpt-apply-patch\", factory: gptApplyPatchExtension },\n\t{ id: \"prompt-preset\", factory: promptPresetExtension },\n\t{ id: \"todowrite\", factory: todowriteExtension },\n\t{ id: \"redraws\", factory: redrawsExtension },\n\t{ id: \"anthropic-web-search\", factory: anthropicWebSearchExtension },\n\t{ id: \"anthropic-bash\", factory: anthropicBashExtension },\n\t{ id: \"openai-web-search\", factory: openaiWebSearchExtension },\n\t{ id: \"service-tier\", factory: serviceTierExtension },\n\t{ id: \"bash-timeout\", factory: bashTimeoutExtension },\n\t{ id: \"tool-pair-guard\", factory: toolPairGuardExtension },\n\t{ id: \"compaction\", factory: compactionExtension },\n];\n"]}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import anthropicBashExtension from "./anthropic-bash/index.js";
|
|
2
2
|
import anthropicWebSearchExtension from "./anthropic-web-search/index.js";
|
|
3
|
-
import backgroundTaskExtension from "./background-task/index.js";
|
|
4
3
|
import bashTimeoutExtension from "./bash-timeout/index.js";
|
|
5
4
|
import compactionExtension from "./compaction/index.js";
|
|
6
5
|
import diffExtension from "./diff.js";
|
|
@@ -23,7 +22,6 @@ export const globalDefaultExtensionFactories = {
|
|
|
23
22
|
tps: tpsExtension,
|
|
24
23
|
};
|
|
25
24
|
export const builtinExtensions = [
|
|
26
|
-
{ id: "background-task", factory: backgroundTaskExtension },
|
|
27
25
|
{ id: "permission-system", factory: permissionSystemExtension },
|
|
28
26
|
{ id: "gpt-apply-patch", factory: gptApplyPatchExtension },
|
|
29
27
|
{ id: "prompt-preset", factory: promptPresetExtension },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/index.ts"],"names":[],"mappings":"AACA,OAAO,sBAAsB,MAAM,2BAA2B,CAAC;AAC/D,OAAO,2BAA2B,MAAM,iCAAiC,CAAC;AAC1E,OAAO,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/index.ts"],"names":[],"mappings":"AACA,OAAO,sBAAsB,MAAM,2BAA2B,CAAC;AAC/D,OAAO,2BAA2B,MAAM,iCAAiC,CAAC;AAC1E,OAAO,oBAAoB,MAAM,yBAAyB,CAAC;AAC3D,OAAO,mBAAmB,MAAM,uBAAuB,CAAC;AACxD,OAAO,aAAa,MAAM,WAAW,CAAC;AACtC,OAAO,cAAc,MAAM,YAAY,CAAC;AACxC,OAAO,sBAAsB,MAAM,4BAA4B,CAAC;AAChE,OAAO,wBAAwB,MAAM,8BAA8B,CAAC;AACpE,OAAO,yBAAyB,MAAM,8BAA8B,CAAC;AACrE,OAAO,qBAAqB,MAAM,0BAA0B,CAAC;AAC7D,OAAO,wBAAwB,MAAM,wBAAwB,CAAC;AAC9D,OAAO,gBAAgB,MAAM,cAAc,CAAC;AAC5C,OAAO,oBAAoB,MAAM,mBAAmB,CAAC;AACrD,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AACtD,OAAO,sBAAsB,MAAM,4BAA4B,CAAC;AAChE,OAAO,YAAY,MAAM,UAAU,CAAC;AAOpC,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,mBAAmB,EAAE,KAAK,CAAU,CAAC;AAEhG,MAAM,CAAC,MAAM,+BAA+B,GAAG;IAC9C,IAAI,EAAE,aAAa;IACnB,KAAK,EAAE,cAAc;IACrB,mBAAmB,EAAE,wBAAwB;IAC7C,GAAG,EAAE,YAAY;CAC8D,CAAC;AAEjF,MAAM,CAAC,MAAM,iBAAiB,GAA8B;IAC3D,EAAE,EAAE,EAAE,mBAAmB,EAAE,OAAO,EAAE,yBAAyB,EAAE;IAC/D,EAAE,EAAE,EAAE,iBAAiB,EAAE,OAAO,EAAE,sBAAsB,EAAE;IAC1D,EAAE,EAAE,EAAE,eAAe,EAAE,OAAO,EAAE,qBAAqB,EAAE;IACvD,EAAE,EAAE,EAAE,WAAW,EAAE,OAAO,EAAE,kBAAkB,EAAE;IAChD,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,gBAAgB,EAAE;IAC5C,EAAE,EAAE,EAAE,sBAAsB,EAAE,OAAO,EAAE,2BAA2B,EAAE;IACpE,EAAE,EAAE,EAAE,gBAAgB,EAAE,OAAO,EAAE,sBAAsB,EAAE;IACzD,EAAE,EAAE,EAAE,mBAAmB,EAAE,OAAO,EAAE,wBAAwB,EAAE;IAC9D,EAAE,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAAE;IACrD,EAAE,EAAE,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,EAAE;IACrD,EAAE,EAAE,EAAE,iBAAiB,EAAE,OAAO,EAAE,sBAAsB,EAAE;IAC1D,EAAE,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,mBAAmB,EAAE;CAClD,CAAC","sourcesContent":["import type { ExtensionFactory } from \"../types.js\";\nimport anthropicBashExtension from \"./anthropic-bash/index.js\";\nimport anthropicWebSearchExtension from \"./anthropic-web-search/index.js\";\nimport bashTimeoutExtension from \"./bash-timeout/index.js\";\nimport compactionExtension from \"./compaction/index.js\";\nimport diffExtension from \"./diff.js\";\nimport filesExtension from \"./files.js\";\nimport gptApplyPatchExtension from \"./gpt-apply-patch/index.js\";\nimport openaiWebSearchExtension from \"./openai-web-search/index.js\";\nimport permissionSystemExtension from \"./permission-system/index.js\";\nimport promptPresetExtension from \"./prompt-preset/index.js\";\nimport promptUrlWidgetExtension from \"./prompt-url-widget.js\";\nimport redrawsExtension from \"./redraws.js\";\nimport serviceTierExtension from \"./service-tier.js\";\nimport todowriteExtension from \"./todotools/index.js\";\nimport toolPairGuardExtension from \"./tool-pair-guard/index.js\";\nimport tpsExtension from \"./tps.js\";\n\nexport interface BuiltinExtensionFactory {\n\tid: string;\n\tfactory: ExtensionFactory;\n}\n\nexport const globalDefaultExtensionIds = [\"diff\", \"files\", \"prompt-url-widget\", \"tps\"] as const;\n\nexport const globalDefaultExtensionFactories = {\n\tdiff: diffExtension,\n\tfiles: filesExtension,\n\t\"prompt-url-widget\": promptUrlWidgetExtension,\n\ttps: tpsExtension,\n} satisfies Record<(typeof globalDefaultExtensionIds)[number], ExtensionFactory>;\n\nexport const builtinExtensions: BuiltinExtensionFactory[] = [\n\t{ id: \"permission-system\", factory: permissionSystemExtension },\n\t{ id: \"gpt-apply-patch\", factory: gptApplyPatchExtension },\n\t{ id: \"prompt-preset\", factory: promptPresetExtension },\n\t{ id: \"todowrite\", factory: todowriteExtension },\n\t{ id: \"redraws\", factory: redrawsExtension },\n\t{ id: \"anthropic-web-search\", factory: anthropicWebSearchExtension },\n\t{ id: \"anthropic-bash\", factory: anthropicBashExtension },\n\t{ id: \"openai-web-search\", factory: openaiWebSearchExtension },\n\t{ id: \"service-tier\", factory: serviceTierExtension },\n\t{ id: \"bash-timeout\", factory: bashTimeoutExtension },\n\t{ id: \"tool-pair-guard\", factory: toolPairGuardExtension },\n\t{ id: \"compaction\", factory: compactionExtension },\n];\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/permission-system/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAS,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE7D,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BvG","sourcesContent":["import type { ExtensionContext } from \"../../types.js\";\nimport type { Reply, ReplyInput, Request } from \"./types.js\";\n\nexport async function showPermissionPrompt(ctx: ExtensionContext, request: Request): Promise<ReplyInput> {\n\tconst title = `Permission required: ${request.permission}`;\n\tconst message = formatRequestForDisplay(request);\n\n\tconst displayTitle = `${title}\\n\\n${message}`;\n\n\tconst options = [\"Allow once\", \"Allow always\", \"Deny\", \"Deny with feedback\"];\n\n\tconst choice = await ctx.ui.select(displayTitle, options);\n\n\tif (choice === \"Deny with feedback\") {\n\t\tconst feedback = await ctx.ui.input(\"Feedback\", \"Why are you denying this permission? (optional)\");\n\t\treturn {\n\t\t\trequestID: request.id,\n\t\t\treply: \"reject\",\n\t\t\tmessage: feedback || undefined,\n\t\t};\n\t}\n\n\tconst replyMap: Record<string, Reply> = {\n\t\t\"Allow once\": \"once\",\n\t\t\"Allow always\": \"always\",\n\t\tDeny: \"reject\",\n\t};\n\n\treturn {\n\t\trequestID: request.id,\n\t\treply: choice ? replyMap[choice] : \"reject\",\n\t};\n}\n\nfunction formatRequestForDisplay(request: Request): string {\n\tconst parts: string[] = [];\n\tconst meta = request.metadata || {};\n\n\tswitch (request.permission) {\n\t\tcase \"edit\":\n\t\t\tparts.push(`File: ${meta.filepath || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"read\":\n\t\t\tparts.push(`Path: ${meta.filePath || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"glob\":\n\t\tcase \"grep\":\n\t\t\tparts.push(`Pattern: ${meta.pattern || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"list\":\n\t\t\tparts.push(`Path: ${meta.path || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"bash\":\n\t\t\tif (meta.description) parts.push(`Description: ${meta.description}`);\n\t\t\tparts.push(`Command: $ ${meta.command || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/permission-system/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAS,UAAU,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE7D,wBAAsB,oBAAoB,CAAC,GAAG,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CA6BvG","sourcesContent":["import type { ExtensionContext } from \"../../types.js\";\nimport type { Reply, ReplyInput, Request } from \"./types.js\";\n\nexport async function showPermissionPrompt(ctx: ExtensionContext, request: Request): Promise<ReplyInput> {\n\tconst title = `Permission required: ${request.permission}`;\n\tconst message = formatRequestForDisplay(request);\n\n\tconst displayTitle = `${title}\\n\\n${message}`;\n\n\tconst options = [\"Allow once\", \"Allow always\", \"Deny\", \"Deny with feedback\"];\n\n\tconst choice = await ctx.ui.select(displayTitle, options);\n\n\tif (choice === \"Deny with feedback\") {\n\t\tconst feedback = await ctx.ui.input(\"Feedback\", \"Why are you denying this permission? (optional)\");\n\t\treturn {\n\t\t\trequestID: request.id,\n\t\t\treply: \"reject\",\n\t\t\tmessage: feedback || undefined,\n\t\t};\n\t}\n\n\tconst replyMap: Record<string, Reply> = {\n\t\t\"Allow once\": \"once\",\n\t\t\"Allow always\": \"always\",\n\t\tDeny: \"reject\",\n\t};\n\n\treturn {\n\t\trequestID: request.id,\n\t\treply: choice ? replyMap[choice] : \"reject\",\n\t};\n}\n\nfunction formatRequestForDisplay(request: Request): string {\n\tconst parts: string[] = [];\n\tconst meta = request.metadata || {};\n\n\tswitch (request.permission) {\n\t\tcase \"edit\":\n\t\t\tparts.push(`File: ${meta.filepath || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"read\":\n\t\t\tparts.push(`Path: ${meta.filePath || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"glob\":\n\t\tcase \"grep\":\n\t\t\tparts.push(`Pattern: ${meta.pattern || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"list\":\n\t\t\tparts.push(`Path: ${meta.path || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"bash\":\n\t\t\tif (meta.description) parts.push(`Description: ${meta.description}`);\n\t\t\tparts.push(`Command: $ ${meta.command || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"websearch\":\n\t\tcase \"codesearch\":\n\t\t\tparts.push(`Query: ${meta.query || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"external_directory\": {\n\t\t\tconst parent = typeof meta.parentDir === \"string\" ? meta.parentDir : undefined;\n\t\t\tconst filepath = typeof meta.filepath === \"string\" ? meta.filepath : undefined;\n\t\t\tconst pattern = request.patterns?.[0];\n\t\t\tconst derived =\n\t\t\t\ttypeof pattern === \"string\" ? (pattern.includes(\"*\") ? pattern.split(\"*\")[0] : pattern) : undefined;\n\t\t\tconst dir = parent ?? filepath ?? derived ?? \"Unknown\";\n\t\t\tparts.push(`Directory: ${dir}`);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tparts.push(`Tool: ${request.permission}`);\n\t\t\tbreak;\n\t}\n\n\tif (request.patterns && request.patterns.length > 0) {\n\t\tparts.push(`\\nPatterns:\\n${request.patterns.map((p) => ` - ${p}`).join(\"\\n\")}`);\n\t}\n\n\treturn parts.join(\"\\n\");\n}\n"]}
|
|
@@ -44,11 +44,6 @@ function formatRequestForDisplay(request) {
|
|
|
44
44
|
parts.push(`Description: ${meta.description}`);
|
|
45
45
|
parts.push(`Command: $ ${meta.command || "Unknown"}`);
|
|
46
46
|
break;
|
|
47
|
-
case "task":
|
|
48
|
-
parts.push(`Type: ${meta.subagent_type || "Unknown"}`);
|
|
49
|
-
if (meta.description)
|
|
50
|
-
parts.push(`Description: ${meta.description}`);
|
|
51
|
-
break;
|
|
52
47
|
case "websearch":
|
|
53
48
|
case "codesearch":
|
|
54
49
|
parts.push(`Query: ${meta.query || "Unknown"}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/permission-system/prompt.ts"],"names":[],"mappings":"AAGA,MAAM,CAAC,KAAK,UAAU,oBAAoB,CAAC,GAAqB,EAAE,OAAgB,EAAuB;IACxG,MAAM,KAAK,GAAG,wBAAwB,OAAO,CAAC,UAAU,EAAE,CAAC;IAC3D,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,CAAC,CAAC;IAEjD,MAAM,YAAY,GAAG,GAAG,KAAK,OAAO,OAAO,EAAE,CAAC;IAE9C,MAAM,OAAO,GAAG,CAAC,YAAY,EAAE,cAAc,EAAE,MAAM,EAAE,oBAAoB,CAAC,CAAC;IAE7E,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAE1D,IAAI,MAAM,KAAK,oBAAoB,EAAE,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,iDAAiD,CAAC,CAAC;QACnG,OAAO;YACN,SAAS,EAAE,OAAO,CAAC,EAAE;YACrB,KAAK,EAAE,QAAQ;YACf,OAAO,EAAE,QAAQ,IAAI,SAAS;SAC9B,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAA0B;QACvC,YAAY,EAAE,MAAM;QACpB,cAAc,EAAE,QAAQ;QACxB,IAAI,EAAE,QAAQ;KACd,CAAC;IAEF,OAAO;QACN,SAAS,EAAE,OAAO,CAAC,EAAE;QACrB,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ;KAC3C,CAAC;AAAA,CACF;AAED,SAAS,uBAAuB,CAAC,OAAgB,EAAU;IAC1D,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,IAAI,EAAE,CAAC;IAEpC,QAAQ,OAAO,CAAC,UAAU,EAAE,CAAC;QAC5B,KAAK,MAAM;YACV,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC,CAAC;YAClD,MAAM;QACP,KAAK,MAAM;YACV,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,QAAQ,IAAI,SAAS,EAAE,CAAC,CAAC;YAClD,MAAM;QACP,KAAK,MAAM,CAAC;QACZ,KAAK,MAAM;YACV,KAAK,CAAC,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC;YACpD,MAAM;QACP,KAAK,MAAM;YACV,KAAK,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,IAAI,IAAI,SAAS,EAAE,CAAC,CAAC;YAC9C,MAAM;QACP,KAAK,MAAM;YACV,IAAI,IAAI,CAAC,WAAW;gBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;YACrE,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC;YACtD,MAAM;QACP,KAAK,
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/permission-system/prompt.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionContext } from \"../../types.js\";\nimport type { Reply, ReplyInput, Request } from \"./types.js\";\n\nexport async function showPermissionPrompt(ctx: ExtensionContext, request: Request): Promise<ReplyInput> {\n\tconst title = `Permission required: ${request.permission}`;\n\tconst message = formatRequestForDisplay(request);\n\n\tconst displayTitle = `${title}\\n\\n${message}`;\n\n\tconst options = [\"Allow once\", \"Allow always\", \"Deny\", \"Deny with feedback\"];\n\n\tconst choice = await ctx.ui.select(displayTitle, options);\n\n\tif (choice === \"Deny with feedback\") {\n\t\tconst feedback = await ctx.ui.input(\"Feedback\", \"Why are you denying this permission? (optional)\");\n\t\treturn {\n\t\t\trequestID: request.id,\n\t\t\treply: \"reject\",\n\t\t\tmessage: feedback || undefined,\n\t\t};\n\t}\n\n\tconst replyMap: Record<string, Reply> = {\n\t\t\"Allow once\": \"once\",\n\t\t\"Allow always\": \"always\",\n\t\tDeny: \"reject\",\n\t};\n\n\treturn {\n\t\trequestID: request.id,\n\t\treply: choice ? replyMap[choice] : \"reject\",\n\t};\n}\n\nfunction formatRequestForDisplay(request: Request): string {\n\tconst parts: string[] = [];\n\tconst meta = request.metadata || {};\n\n\tswitch (request.permission) {\n\t\tcase \"edit\":\n\t\t\tparts.push(`File: ${meta.filepath || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"read\":\n\t\t\tparts.push(`Path: ${meta.filePath || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"glob\":\n\t\tcase \"grep\":\n\t\t\tparts.push(`Pattern: ${meta.pattern || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"list\":\n\t\t\tparts.push(`Path: ${meta.path || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"bash\":\n\t\t\tif (meta.description) parts.push(`Description: ${meta.description}`);\n\t\t\tparts.push(`Command: $ ${meta.command || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"websearch\":\n\t\tcase \"codesearch\":\n\t\t\tparts.push(`Query: ${meta.query || \"Unknown\"}`);\n\t\t\tbreak;\n\t\tcase \"external_directory\": {\n\t\t\tconst parent = typeof meta.parentDir === \"string\" ? meta.parentDir : undefined;\n\t\t\tconst filepath = typeof meta.filepath === \"string\" ? meta.filepath : undefined;\n\t\t\tconst pattern = request.patterns?.[0];\n\t\t\tconst derived =\n\t\t\t\ttypeof pattern === \"string\" ? (pattern.includes(\"*\") ? pattern.split(\"*\")[0] : pattern) : undefined;\n\t\t\tconst dir = parent ?? filepath ?? derived ?? \"Unknown\";\n\t\t\tparts.push(`Directory: ${dir}`);\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tparts.push(`Tool: ${request.permission}`);\n\t\t\tbreak;\n\t}\n\n\tif (request.patterns && request.patterns.length > 0) {\n\t\tparts.push(`\\nPatterns:\\n${request.patterns.map((p) => ` - ${p}`).join(\"\\n\")}`);\n\t}\n\n\treturn parts.join(\"\\n\");\n}\n"]}
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import type { ImageContent, TextContent } from "@earendil-works/pi-ai";
|
|
2
2
|
import type { CustomMessage } from "../../messages.js";
|
|
3
3
|
import type { ExtensionAPI } from "../types.js";
|
|
4
|
-
export declare const
|
|
5
|
-
export declare const
|
|
6
|
-
export type BuiltinSystemMessageRoute = "
|
|
7
|
-
export type
|
|
8
|
-
export interface
|
|
4
|
+
export declare const SENPI_SYSTEM_PREFIX = "[system:senpi]";
|
|
5
|
+
export declare const SENPI_CONVERSATION_EVENT = "senpi:conversation";
|
|
6
|
+
export type BuiltinSystemMessageRoute = "todotools.continuation";
|
|
7
|
+
export type SenpiConversationAction = "injected" | "failed";
|
|
8
|
+
export interface SenpiConversationEvent {
|
|
9
9
|
version: 1;
|
|
10
10
|
source: "builtin";
|
|
11
|
-
action:
|
|
11
|
+
action: SenpiConversationAction;
|
|
12
12
|
route: BuiltinSystemMessageRoute;
|
|
13
13
|
sessionId?: string;
|
|
14
14
|
timestamp: number;
|
|
15
15
|
conversation: {
|
|
16
|
-
prefix: typeof
|
|
16
|
+
prefix: typeof SENPI_SYSTEM_PREFIX;
|
|
17
17
|
kind: "custom_message" | "user_message";
|
|
18
18
|
customType?: string;
|
|
19
19
|
deliverAs?: "steer" | "followUp";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"system-messages.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/system-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,
|
|
1
|
+
{"version":3,"file":"system-messages.d.ts","sourceRoot":"","sources":["../../../../src/core/extensions/builtin/system-messages.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AACpD,eAAO,MAAM,wBAAwB,uBAAuB,CAAC;AAE7D,MAAM,MAAM,yBAAyB,GAAG,wBAAwB,CAAC;AACjE,MAAM,MAAM,uBAAuB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACtC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,SAAS,CAAC;IAClB,MAAM,EAAE,uBAAuB,CAAC;IAChC,KAAK,EAAE,yBAAyB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE;QACb,MAAM,EAAE,OAAO,mBAAmB,CAAC;QACnC,IAAI,EAAE,gBAAgB,GAAG,cAAc,CAAC;QACxC,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;QACjC,WAAW,CAAC,EAAE,OAAO,CAAC;KACtB,CAAC;IACF,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,KAAK,yBAAyB,GAAG;IAChC,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,KAAK,2BAA2B,GAAG;IAClC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,UAAU,CAAC;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAqFF,wBAAgB,sBAAsB,CACrC,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,yBAAyB,EAChC,OAAO,EAAE,MAAM,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,EAChD,OAAO,CAAC,EAAE,yBAAyB,GACjC,IAAI,CAqBN;AAED,wBAAgB,wBAAwB,CAAC,QAAQ,EAChD,EAAE,EAAE,YAAY,EAChB,KAAK,EAAE,yBAAyB,EAChC,OAAO,EAAE,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,EAAE,SAAS,GAAG,YAAY,GAAG,SAAS,GAAG,SAAS,CAAC,EACxF,OAAO,CAAC,EAAE,2BAA2B,GACnC,IAAI,CAgCN;AAED,wBAAgB,+BAA+B,CAC9C,EAAE,EAAE,YAAY,EAChB,IAAI,EAAE;IACL,KAAK,EAAE,yBAAyB,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,gBAAgB,GAAG,cAAc,CAAC;IACxC,OAAO,EAAE,MAAM,GAAG,CAAC,WAAW,GAAG,YAAY,CAAC,EAAE,CAAC;IACjD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,OAAO,GAAG,UAAU,CAAC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACrB,GACC,IAAI,CAiBN","sourcesContent":["import type { ImageContent, TextContent } from \"@earendil-works/pi-ai\";\nimport type { CustomMessage } from \"../../messages.js\";\nimport type { ExtensionAPI } from \"../types.js\";\n\nexport const SENPI_SYSTEM_PREFIX = \"[system:senpi]\";\nexport const SENPI_CONVERSATION_EVENT = \"senpi:conversation\";\n\nexport type BuiltinSystemMessageRoute = \"todotools.continuation\";\nexport type SenpiConversationAction = \"injected\" | \"failed\";\n\nexport interface SenpiConversationEvent {\n\tversion: 1;\n\tsource: \"builtin\";\n\taction: SenpiConversationAction;\n\troute: BuiltinSystemMessageRoute;\n\tsessionId?: string;\n\ttimestamp: number;\n\tconversation: {\n\t\tprefix: typeof SENPI_SYSTEM_PREFIX;\n\t\tkind: \"custom_message\" | \"user_message\";\n\t\tcustomType?: string;\n\t\tdeliverAs?: \"steer\" | \"followUp\";\n\t\ttriggerTurn?: boolean;\n\t};\n\ttext: string;\n\terrorMessage?: string;\n}\n\ntype BuiltinUserMessageOptions = {\n\tdeliverAs?: \"steer\" | \"followUp\";\n\tsessionId?: string;\n};\n\ntype BuiltinCustomMessageOptions = {\n\ttriggerTurn?: boolean;\n\tdeliverAs?: \"steer\" | \"followUp\" | \"nextTurn\";\n\tsessionId?: string;\n};\n\nfunction prefixText(text: string): string {\n\treturn text.startsWith(SENPI_SYSTEM_PREFIX) ? text : `${SENPI_SYSTEM_PREFIX}\\n${text}`;\n}\n\nfunction prefixContent(content: string | (TextContent | ImageContent)[]): string | (TextContent | ImageContent)[] {\n\tif (typeof content === \"string\") {\n\t\treturn prefixText(content);\n\t}\n\n\tconst firstTextIndex = content.findIndex((part) => part.type === \"text\");\n\tif (firstTextIndex === -1) {\n\t\treturn [{ type: \"text\", text: SENPI_SYSTEM_PREFIX }, ...content];\n\t}\n\n\treturn content.map((part, index) => {\n\t\tif (part.type !== \"text\" || index !== firstTextIndex) {\n\t\t\treturn part;\n\t\t}\n\n\t\treturn {\n\t\t\t...part,\n\t\t\ttext: prefixText(part.text),\n\t\t};\n\t});\n}\n\nfunction extractText(content: string | (TextContent | ImageContent)[]): string {\n\tif (typeof content === \"string\") {\n\t\treturn content;\n\t}\n\n\treturn content\n\t\t.filter((part): part is TextContent => part.type === \"text\")\n\t\t.map((part) => part.text)\n\t\t.join(\"\\n\");\n}\n\nfunction emitSenpiConversationEvent(pi: ExtensionAPI, event: SenpiConversationEvent): void {\n\tpi.events.emit(SENPI_CONVERSATION_EVENT, event);\n}\n\nfunction createBaseEvent(args: {\n\taction: SenpiConversationAction;\n\troute: BuiltinSystemMessageRoute;\n\tsessionId?: string;\n\tkind: \"custom_message\" | \"user_message\";\n\tcustomType?: string;\n\tdeliverAs?: \"steer\" | \"followUp\";\n\ttriggerTurn?: boolean;\n\ttext: string;\n\terrorMessage?: string;\n}): SenpiConversationEvent {\n\treturn {\n\t\tversion: 1,\n\t\tsource: \"builtin\",\n\t\taction: args.action,\n\t\troute: args.route,\n\t\tsessionId: args.sessionId,\n\t\ttimestamp: Date.now(),\n\t\tconversation: {\n\t\t\tprefix: SENPI_SYSTEM_PREFIX,\n\t\t\tkind: args.kind,\n\t\t\tcustomType: args.customType,\n\t\t\tdeliverAs: args.deliverAs,\n\t\t\ttriggerTurn: args.triggerTurn,\n\t\t},\n\t\ttext: args.text,\n\t\terrorMessage: args.errorMessage,\n\t};\n}\n\nfunction hasUserMessageOptions(\n\toptions: BuiltinUserMessageOptions | undefined,\n): options is BuiltinUserMessageOptions & { deliverAs: \"steer\" | \"followUp\" } {\n\treturn options?.deliverAs !== undefined;\n}\n\nfunction hasCustomMessageOptions(\n\toptions: BuiltinCustomMessageOptions | undefined,\n): options is BuiltinCustomMessageOptions & { triggerTurn?: boolean; deliverAs?: \"steer\" | \"followUp\" | \"nextTurn\" } {\n\treturn options?.triggerTurn === true || options?.deliverAs !== undefined;\n}\n\nexport function sendBuiltinUserMessage(\n\tpi: ExtensionAPI,\n\troute: BuiltinSystemMessageRoute,\n\tcontent: string | (TextContent | ImageContent)[],\n\toptions?: BuiltinUserMessageOptions,\n): void {\n\tconst prefixedContent = prefixContent(content);\n\n\temitSenpiConversationEvent(\n\t\tpi,\n\t\tcreateBaseEvent({\n\t\t\taction: \"injected\",\n\t\t\troute,\n\t\t\tsessionId: options?.sessionId,\n\t\t\tkind: \"user_message\",\n\t\t\ttext: extractText(prefixedContent),\n\t\t\tdeliverAs: options?.deliverAs,\n\t\t}),\n\t);\n\n\tif (hasUserMessageOptions(options)) {\n\t\tpi.sendUserMessage(prefixedContent, { deliverAs: options.deliverAs });\n\t\treturn;\n\t}\n\n\tpi.sendUserMessage(prefixedContent);\n}\n\nexport function sendBuiltinCustomMessage<TDetails>(\n\tpi: ExtensionAPI,\n\troute: BuiltinSystemMessageRoute,\n\tmessage: Pick<CustomMessage<TDetails>, \"content\" | \"customType\" | \"details\" | \"display\">,\n\toptions?: BuiltinCustomMessageOptions,\n): void {\n\tconst prefixedContent = prefixContent(message.content);\n\tconst deliverAs = options?.deliverAs === \"nextTurn\" ? undefined : options?.deliverAs;\n\n\temitSenpiConversationEvent(\n\t\tpi,\n\t\tcreateBaseEvent({\n\t\t\taction: \"injected\",\n\t\t\troute,\n\t\t\tsessionId: options?.sessionId,\n\t\t\tkind: \"custom_message\",\n\t\t\tcustomType: message.customType,\n\t\t\ttext: extractText(prefixedContent),\n\t\t\tdeliverAs,\n\t\t\ttriggerTurn: options?.triggerTurn,\n\t\t}),\n\t);\n\n\tconst prefixedMessage = {\n\t\t...message,\n\t\tcontent: prefixedContent,\n\t};\n\n\tif (hasCustomMessageOptions(options)) {\n\t\tpi.sendMessage(prefixedMessage, {\n\t\t\ttriggerTurn: options.triggerTurn,\n\t\t\tdeliverAs: options.deliverAs,\n\t\t});\n\t\treturn;\n\t}\n\n\tpi.sendMessage(prefixedMessage);\n}\n\nexport function emitBuiltinSystemMessageFailure(\n\tpi: ExtensionAPI,\n\targs: {\n\t\troute: BuiltinSystemMessageRoute;\n\t\tsessionId?: string;\n\t\tkind: \"custom_message\" | \"user_message\";\n\t\tcontent: string | (TextContent | ImageContent)[];\n\t\tcustomType?: string;\n\t\tdeliverAs?: \"steer\" | \"followUp\";\n\t\ttriggerTurn?: boolean;\n\t\terrorMessage: string;\n\t},\n): void {\n\tconst prefixedContent = prefixContent(args.content);\n\n\temitSenpiConversationEvent(\n\t\tpi,\n\t\tcreateBaseEvent({\n\t\t\taction: \"failed\",\n\t\t\troute: args.route,\n\t\t\tsessionId: args.sessionId,\n\t\t\tkind: args.kind,\n\t\t\tcustomType: args.customType,\n\t\t\ttext: extractText(prefixedContent),\n\t\t\tdeliverAs: args.deliverAs,\n\t\t\ttriggerTurn: args.triggerTurn,\n\t\t\terrorMessage: args.errorMessage,\n\t\t}),\n\t);\n}\n"]}
|