@caupulican/pi-adaptative 0.80.23 → 0.80.26

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.
Files changed (67) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/README.md +16 -2
  3. package/dist/cli/args.d.ts +2 -0
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +14 -0
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/core/agent-session-services.d.ts +4 -0
  8. package/dist/core/agent-session-services.d.ts.map +1 -1
  9. package/dist/core/agent-session-services.js +22 -0
  10. package/dist/core/agent-session-services.js.map +1 -1
  11. package/dist/core/agent-session.d.ts +7 -1
  12. package/dist/core/agent-session.d.ts.map +1 -1
  13. package/dist/core/agent-session.js +126 -20
  14. package/dist/core/agent-session.js.map +1 -1
  15. package/dist/core/extensions/builtin.d.ts +3 -0
  16. package/dist/core/extensions/builtin.d.ts.map +1 -0
  17. package/dist/core/extensions/builtin.js +247 -0
  18. package/dist/core/extensions/builtin.js.map +1 -0
  19. package/dist/core/package-manager.d.ts +3 -0
  20. package/dist/core/package-manager.d.ts.map +1 -1
  21. package/dist/core/package-manager.js +58 -0
  22. package/dist/core/package-manager.js.map +1 -1
  23. package/dist/core/prompt-templates.d.ts.map +1 -1
  24. package/dist/core/prompt-templates.js +3 -1
  25. package/dist/core/prompt-templates.js.map +1 -1
  26. package/dist/core/resource-loader.d.ts +15 -2
  27. package/dist/core/resource-loader.d.ts.map +1 -1
  28. package/dist/core/resource-loader.js +235 -134
  29. package/dist/core/resource-loader.js.map +1 -1
  30. package/dist/core/resource-profile-blocks.d.ts +16 -0
  31. package/dist/core/resource-profile-blocks.d.ts.map +1 -0
  32. package/dist/core/resource-profile-blocks.js +120 -0
  33. package/dist/core/resource-profile-blocks.js.map +1 -0
  34. package/dist/core/sdk.d.ts +9 -0
  35. package/dist/core/sdk.d.ts.map +1 -1
  36. package/dist/core/sdk.js +17 -0
  37. package/dist/core/sdk.js.map +1 -1
  38. package/dist/core/settings-manager.d.ts +45 -1
  39. package/dist/core/settings-manager.d.ts.map +1 -1
  40. package/dist/core/settings-manager.js +218 -10
  41. package/dist/core/settings-manager.js.map +1 -1
  42. package/dist/core/skills.d.ts.map +1 -1
  43. package/dist/core/skills.js +3 -0
  44. package/dist/core/skills.js.map +1 -1
  45. package/dist/index.d.ts +2 -1
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js +2 -1
  48. package/dist/index.js.map +1 -1
  49. package/dist/main.d.ts.map +1 -1
  50. package/dist/main.js +17 -0
  51. package/dist/main.js.map +1 -1
  52. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  53. package/dist/modes/interactive/interactive-mode.js +20 -20
  54. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  55. package/docs/extensions.md +18 -1
  56. package/docs/prompt-templates.md +1 -0
  57. package/docs/settings.md +43 -1
  58. package/docs/skills.md +12 -0
  59. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  60. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  61. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  62. package/examples/extensions/sandbox/package-lock.json +2 -2
  63. package/examples/extensions/sandbox/package.json +1 -1
  64. package/examples/extensions/with-deps/package-lock.json +2 -2
  65. package/examples/extensions/with-deps/package.json +1 -1
  66. package/npm-shrinkwrap.json +12 -12
  67. package/package.json +4 -4
@@ -0,0 +1,3 @@
1
+ import type { ToolDefinition, ToolInfo } from "./types.ts";
2
+ export declare function createCoreDiagnosticsToolDefinitions(getActiveTools: () => string[], getAllTools: () => ToolInfo[]): ToolDefinition[];
3
+ //# sourceMappingURL=builtin.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin.d.ts","sourceRoot":"","sources":["../../../src/core/extensions/builtin.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAmK3D,wBAAgB,oCAAoC,CACnD,cAAc,EAAE,MAAM,MAAM,EAAE,EAC9B,WAAW,EAAE,MAAM,QAAQ,EAAE,GAC3B,cAAc,EAAE,CAqHlB","sourcesContent":["import type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport { Type } from \"typebox\";\nimport { estimateTokens } from \"../compaction/compaction.ts\";\nimport { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from \"../messages.ts\";\nimport type { CompactionEntry, SessionEntry } from \"../session-manager.ts\";\nimport type { ToolDefinition, ToolInfo } from \"./types.ts\";\n\ntype ContextAuditParams = {\n\tmaxItems?: number;\n\tminTokens?: number;\n\tquery?: string;\n\tincludePreviews?: boolean;\n};\n\ntype AuditRow = {\n\tkind: string;\n\trole?: string;\n\tentryId?: string;\n\ttimestamp?: string;\n\ttokens: number;\n\tchars: number;\n\tlabel: string;\n\tpreview: string;\n};\n\nconst DEFAULT_MAX_ITEMS = 40;\nconst MAX_MAX_ITEMS = 200;\nconst DEFAULT_PREVIEW_CHARS = 220;\nconst MAX_PREVIEW_CHARS = 600;\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction cap(text: string, limit = DEFAULT_PREVIEW_CHARS): string {\n\tconst compact = text.replace(/\\s+/g, \" \").trim();\n\treturn compact.length > limit ? `${compact.slice(0, Math.max(0, limit - 1))}…` : compact;\n}\n\nfunction contentText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.map((part) => {\n\t\t\tif (!part || typeof part !== \"object\") return \"\";\n\t\t\tconst typed = part as { type?: string; text?: string; thinking?: string; name?: string; arguments?: unknown };\n\t\t\tif (typed.type === \"text\") return typed.text || \"\";\n\t\t\tif (typed.type === \"thinking\") return `[thinking ${typed.thinking?.length ?? 0} chars]`;\n\t\t\tif (typed.type === \"toolCall\")\n\t\t\t\treturn `[toolCall ${typed.name || \"unknown\"} ${JSON.stringify(typed.arguments ?? {})}]`;\n\t\t\tif (typed.type === \"image\") return \"[image]\";\n\t\t\treturn \"\";\n\t\t})\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\");\n}\n\nfunction messagePreview(message: AgentMessage): string {\n\tswitch (message.role) {\n\t\tcase \"assistant\":\n\t\tcase \"user\":\n\t\tcase \"toolResult\":\n\t\tcase \"custom\":\n\t\t\treturn contentText((message as { content?: unknown }).content);\n\t\tcase \"bashExecution\":\n\t\t\treturn `Ran ${message.command}\\n${message.output}`;\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn message.summary;\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nfunction messageLabel(message: AgentMessage): string {\n\tif (message.role === \"assistant\") {\n\t\tconst toolCalls = message.content.filter((part) => part.type === \"toolCall\").length;\n\t\treturn toolCalls > 0 ? `assistant (${toolCalls} tool call${toolCalls === 1 ? \"\" : \"s\"})` : \"assistant\";\n\t}\n\tif (message.role === \"toolResult\") return `tool result: ${message.toolName}`;\n\tif (message.role === \"custom\") return `custom: ${message.customType}`;\n\tif (message.role === \"bashExecution\") return \"bash execution\";\n\tif (message.role === \"branchSummary\") return \"branch summary\";\n\tif (message.role === \"compactionSummary\") return \"compaction summary\";\n\treturn message.role;\n}\n\nfunction addRow(rows: AuditRow[], entry: SessionEntry, message: AgentMessage, kindOverride?: string) {\n\tconst preview = messagePreview(message);\n\trows.push({\n\t\tkind: kindOverride || entry.type,\n\t\trole: message.role,\n\t\tentryId: entry.id,\n\t\ttimestamp: entry.timestamp,\n\t\ttokens: estimateTokens(message),\n\t\tchars: preview.length,\n\t\tlabel: messageLabel(message),\n\t\tpreview: cap(preview),\n\t});\n}\n\nfunction messageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tif (entry.type === \"message\") return entry.message;\n\tif (entry.type === \"custom_message\") {\n\t\treturn createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp);\n\t}\n\tif (entry.type === \"branch_summary\" && entry.summary) {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction latestCompaction(entries: SessionEntry[]): CompactionEntry | undefined {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"compaction\") return entry;\n\t}\n\treturn undefined;\n}\n\nfunction activeContextRows(entries: SessionEntry[]): AuditRow[] {\n\tconst rows: AuditRow[] = [];\n\tconst compaction = latestCompaction(entries);\n\tif (!compaction) {\n\t\tfor (const entry of entries) {\n\t\t\tconst message = messageFromEntry(entry);\n\t\t\tif (message) addRow(rows, entry, message);\n\t\t}\n\t\treturn rows;\n\t}\n\n\tconst compactionMessage = createCompactionSummaryMessage(\n\t\tcompaction.summary,\n\t\tcompaction.tokensBefore,\n\t\tcompaction.timestamp,\n\t);\n\taddRow(rows, compaction, compactionMessage, \"compaction\");\n\n\tconst compactionIndex = entries.findIndex((entry) => entry.id === compaction.id);\n\tlet foundFirstKept = false;\n\tfor (let index = 0; index < compactionIndex; index++) {\n\t\tconst entry = entries[index];\n\t\tif (entry.id === compaction.firstKeptEntryId) foundFirstKept = true;\n\t\tif (!foundFirstKept) continue;\n\t\tconst message = messageFromEntry(entry);\n\t\tif (message) addRow(rows, entry, message);\n\t}\n\tfor (let index = compactionIndex + 1; index < entries.length; index++) {\n\t\tconst entry = entries[index];\n\t\tconst message = messageFromEntry(entry);\n\t\tif (message) addRow(rows, entry, message);\n\t}\n\treturn rows;\n}\n\nfunction groupRows(rows: AuditRow[]): Array<[string, { count: number; tokens: number; chars: number }]> {\n\tconst groups = new Map<string, { count: number; tokens: number; chars: number }>();\n\tfor (const row of rows) {\n\t\tconst key = row.label;\n\t\tconst current = groups.get(key) ?? { count: 0, tokens: 0, chars: 0 };\n\t\tcurrent.count += 1;\n\t\tcurrent.tokens += row.tokens;\n\t\tcurrent.chars += row.chars;\n\t\tgroups.set(key, current);\n\t}\n\treturn [...groups.entries()].sort((a, b) => b[1].tokens - a[1].tokens);\n}\n\nexport function createCoreDiagnosticsToolDefinitions(\n\tgetActiveTools: () => string[],\n\tgetAllTools: () => ToolInfo[],\n): ToolDefinition[] {\n\treturn [\n\t\t{\n\t\t\tname: \"context_audit\",\n\t\t\tlabel: \"Context Audit\",\n\t\t\tdescription:\n\t\t\t\t\"Audit the current provider-visible context composition: model window usage, system prompt estimate, active tool schema estimate, active session message rows, and heaviest context contributors.\",\n\t\t\tpromptSnippet: \"Audit current loaded context composition before optimizing context usage.\",\n\t\t\tpromptGuidelines: [\n\t\t\t\t\"Use context_audit when the user asks what is consuming context, why the footer shows a high percentage, or which messages/tools/system prompt content are loaded.\",\n\t\t\t\t\"Keep output bounded; use query/minTokens/maxItems to narrow rather than dumping full context.\",\n\t\t\t\t\"Treat token counts as estimates except provider usage from ctx.getContextUsage, which is still model/provider dependent.\",\n\t\t\t],\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tmaxItems: Type.Optional(\n\t\t\t\t\t\tType.Number({ description: \"Maximum heaviest session-context rows to show. Default 40, max 200.\" }),\n\t\t\t\t\t),\n\t\t\t\t\tminTokens: Type.Optional(\n\t\t\t\t\t\tType.Number({\n\t\t\t\t\t\t\tdescription: \"Only show session-context rows with at least this many estimated tokens.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tquery: Type.Optional(\n\t\t\t\t\t\tType.String({ description: \"Case-insensitive filter over row label and preview.\" }),\n\t\t\t\t\t),\n\t\t\t\t\tincludePreviews: Type.Optional(\n\t\t\t\t\t\tType.Boolean({ description: \"Include bounded row previews. Defaults true.\" }),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\tasync execute(_toolCallId, params: ContextAuditParams, _signal, _onUpdate, ctx) {\n\t\t\t\tconst maxItems = Math.max(1, Math.min(MAX_MAX_ITEMS, Math.floor(params.maxItems ?? DEFAULT_MAX_ITEMS)));\n\t\t\t\tconst minTokens = Math.max(0, Math.floor(params.minTokens ?? 0));\n\t\t\t\tconst includePreviews = params.includePreviews !== false;\n\t\t\t\tconst query = params.query?.trim().toLowerCase();\n\n\t\t\t\tconst branch = ctx.sessionManager.getBranch();\n\t\t\t\tconst rows = activeContextRows(branch);\n\t\t\t\tconst contextUsage = ctx.getContextUsage();\n\t\t\t\tconst systemPrompt = ctx.getSystemPrompt?.() || \"\";\n\t\t\t\tconst activeTools = new Set(getActiveTools());\n\t\t\t\tconst allTools = getAllTools();\n\t\t\t\tconst activeToolInfos = allTools.filter((tool) => activeTools.has(tool.name));\n\t\t\t\tconst systemTokens = estimateTextTokens(systemPrompt);\n\t\t\t\tconst toolSchemaChars = JSON.stringify(\n\t\t\t\t\tactiveToolInfos.map((tool) => ({\n\t\t\t\t\t\tname: tool.name,\n\t\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\t\tparameters: tool.parameters,\n\t\t\t\t\t\tpromptGuidelines: tool.promptGuidelines,\n\t\t\t\t\t})),\n\t\t\t\t).length;\n\t\t\t\tconst toolSchemaTokens = Math.ceil(toolSchemaChars / 4);\n\t\t\t\tconst rowTokenSum = rows.reduce((sum, row) => sum + row.tokens, 0);\n\t\t\t\tconst usageText = contextUsage\n\t\t\t\t\t? contextUsage.tokens === null || contextUsage.percent === null\n\t\t\t\t\t\t? `provider usage: unknown/${contextUsage.contextWindow} tokens (usually right after compaction)`\n\t\t\t\t\t\t: `provider usage: ${contextUsage.tokens}/${contextUsage.contextWindow} tokens (${contextUsage.percent.toFixed(1)}%)`\n\t\t\t\t\t: \"provider usage: unavailable (no active model/context window)\";\n\t\t\t\tconst providerTokens = contextUsage?.tokens ?? null;\n\t\t\t\tconst unattributed =\n\t\t\t\t\tproviderTokens === null\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: Math.max(0, providerTokens - systemTokens - toolSchemaTokens - rowTokenSum);\n\n\t\t\t\tlet filtered = rows.filter((row) => row.tokens >= minTokens);\n\t\t\t\tif (query) {\n\t\t\t\t\tfiltered = filtered.filter((row) => `${row.label}\\n${row.preview}`.toLowerCase().includes(query));\n\t\t\t\t}\n\t\t\t\tconst heaviest = [...filtered].sort((a, b) => b.tokens - a.tokens).slice(0, maxItems);\n\t\t\t\tconst groupLines = groupRows(rows)\n\t\t\t\t\t.slice(0, 12)\n\t\t\t\t\t.map(([label, group]) => `- ${label}: ${group.tokens} est tok across ${group.count} row(s)`);\n\t\t\t\tconst rowLines = heaviest.map((row, index) => {\n\t\t\t\t\tconst base = `${index + 1}. ${row.tokens} est tok · ${row.label} · ${row.entryId ?? \"no-entry\"}`;\n\t\t\t\t\treturn includePreviews\n\t\t\t\t\t\t? `${base}\\n ${cap(row.preview, MAX_PREVIEW_CHARS) || \"(no text preview)\"}`\n\t\t\t\t\t\t: base;\n\t\t\t\t});\n\n\t\t\t\tconst lines = [\n\t\t\t\t\t\"Context audit\",\n\t\t\t\t\tusageText,\n\t\t\t\t\t`active branch rows: ${rows.length}; session row estimate: ${rowTokenSum} tokens`,\n\t\t\t\t\t`system prompt estimate: ${systemTokens} tokens (${systemPrompt.length} chars)`,\n\t\t\t\t\t`active tool schema estimate: ${toolSchemaTokens} tokens across ${activeToolInfos.length} active tool(s)`,\n\t\t\t\t\tunattributed === null\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: `provider-reported remainder not mapped by chars/4 rows: ${unattributed} tokens`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Largest groups:\",\n\t\t\t\t\t...(groupLines.length ? groupLines : [\"- none\"]),\n\t\t\t\t\t\"\",\n\t\t\t\t\t`Heaviest rows${query ? ` matching ${JSON.stringify(params.query)}` : \"\"}:`,\n\t\t\t\t\t...(rowLines.length ? rowLines : [\"- none\"]),\n\t\t\t\t].filter((line): line is string => line !== undefined);\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: lines.join(\"\\n\") }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tcontextUsage,\n\t\t\t\t\t\tsystemPrompt: {\n\t\t\t\t\t\t\tchars: systemPrompt.length,\n\t\t\t\t\t\t\testimatedTokens: systemTokens,\n\t\t\t\t\t\t\tpreview: cap(systemPrompt, MAX_PREVIEW_CHARS),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tactiveTools: activeToolInfos.map((tool) => tool.name),\n\t\t\t\t\t\ttoolSchemaEstimate: { chars: toolSchemaChars, estimatedTokens: toolSchemaTokens },\n\t\t\t\t\t\trowTokenSum,\n\t\t\t\t\t\trows,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t];\n}\n"]}
@@ -0,0 +1,247 @@
1
+ import { Type } from "typebox";
2
+ import { estimateTokens } from "../compaction/compaction.js";
3
+ import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from "../messages.js";
4
+ const DEFAULT_MAX_ITEMS = 40;
5
+ const MAX_MAX_ITEMS = 200;
6
+ const DEFAULT_PREVIEW_CHARS = 220;
7
+ const MAX_PREVIEW_CHARS = 600;
8
+ function estimateTextTokens(text) {
9
+ return Math.ceil(text.length / 4);
10
+ }
11
+ function cap(text, limit = DEFAULT_PREVIEW_CHARS) {
12
+ const compact = text.replace(/\s+/g, " ").trim();
13
+ return compact.length > limit ? `${compact.slice(0, Math.max(0, limit - 1))}…` : compact;
14
+ }
15
+ function contentText(content) {
16
+ if (typeof content === "string")
17
+ return content;
18
+ if (!Array.isArray(content))
19
+ return "";
20
+ return content
21
+ .map((part) => {
22
+ if (!part || typeof part !== "object")
23
+ return "";
24
+ const typed = part;
25
+ if (typed.type === "text")
26
+ return typed.text || "";
27
+ if (typed.type === "thinking")
28
+ return `[thinking ${typed.thinking?.length ?? 0} chars]`;
29
+ if (typed.type === "toolCall")
30
+ return `[toolCall ${typed.name || "unknown"} ${JSON.stringify(typed.arguments ?? {})}]`;
31
+ if (typed.type === "image")
32
+ return "[image]";
33
+ return "";
34
+ })
35
+ .filter(Boolean)
36
+ .join("\n");
37
+ }
38
+ function messagePreview(message) {
39
+ switch (message.role) {
40
+ case "assistant":
41
+ case "user":
42
+ case "toolResult":
43
+ case "custom":
44
+ return contentText(message.content);
45
+ case "bashExecution":
46
+ return `Ran ${message.command}\n${message.output}`;
47
+ case "branchSummary":
48
+ case "compactionSummary":
49
+ return message.summary;
50
+ default:
51
+ return "";
52
+ }
53
+ }
54
+ function messageLabel(message) {
55
+ if (message.role === "assistant") {
56
+ const toolCalls = message.content.filter((part) => part.type === "toolCall").length;
57
+ return toolCalls > 0 ? `assistant (${toolCalls} tool call${toolCalls === 1 ? "" : "s"})` : "assistant";
58
+ }
59
+ if (message.role === "toolResult")
60
+ return `tool result: ${message.toolName}`;
61
+ if (message.role === "custom")
62
+ return `custom: ${message.customType}`;
63
+ if (message.role === "bashExecution")
64
+ return "bash execution";
65
+ if (message.role === "branchSummary")
66
+ return "branch summary";
67
+ if (message.role === "compactionSummary")
68
+ return "compaction summary";
69
+ return message.role;
70
+ }
71
+ function addRow(rows, entry, message, kindOverride) {
72
+ const preview = messagePreview(message);
73
+ rows.push({
74
+ kind: kindOverride || entry.type,
75
+ role: message.role,
76
+ entryId: entry.id,
77
+ timestamp: entry.timestamp,
78
+ tokens: estimateTokens(message),
79
+ chars: preview.length,
80
+ label: messageLabel(message),
81
+ preview: cap(preview),
82
+ });
83
+ }
84
+ function messageFromEntry(entry) {
85
+ if (entry.type === "message")
86
+ return entry.message;
87
+ if (entry.type === "custom_message") {
88
+ return createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp);
89
+ }
90
+ if (entry.type === "branch_summary" && entry.summary) {
91
+ return createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);
92
+ }
93
+ return undefined;
94
+ }
95
+ function latestCompaction(entries) {
96
+ for (let index = entries.length - 1; index >= 0; index--) {
97
+ const entry = entries[index];
98
+ if (entry?.type === "compaction")
99
+ return entry;
100
+ }
101
+ return undefined;
102
+ }
103
+ function activeContextRows(entries) {
104
+ const rows = [];
105
+ const compaction = latestCompaction(entries);
106
+ if (!compaction) {
107
+ for (const entry of entries) {
108
+ const message = messageFromEntry(entry);
109
+ if (message)
110
+ addRow(rows, entry, message);
111
+ }
112
+ return rows;
113
+ }
114
+ const compactionMessage = createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp);
115
+ addRow(rows, compaction, compactionMessage, "compaction");
116
+ const compactionIndex = entries.findIndex((entry) => entry.id === compaction.id);
117
+ let foundFirstKept = false;
118
+ for (let index = 0; index < compactionIndex; index++) {
119
+ const entry = entries[index];
120
+ if (entry.id === compaction.firstKeptEntryId)
121
+ foundFirstKept = true;
122
+ if (!foundFirstKept)
123
+ continue;
124
+ const message = messageFromEntry(entry);
125
+ if (message)
126
+ addRow(rows, entry, message);
127
+ }
128
+ for (let index = compactionIndex + 1; index < entries.length; index++) {
129
+ const entry = entries[index];
130
+ const message = messageFromEntry(entry);
131
+ if (message)
132
+ addRow(rows, entry, message);
133
+ }
134
+ return rows;
135
+ }
136
+ function groupRows(rows) {
137
+ const groups = new Map();
138
+ for (const row of rows) {
139
+ const key = row.label;
140
+ const current = groups.get(key) ?? { count: 0, tokens: 0, chars: 0 };
141
+ current.count += 1;
142
+ current.tokens += row.tokens;
143
+ current.chars += row.chars;
144
+ groups.set(key, current);
145
+ }
146
+ return [...groups.entries()].sort((a, b) => b[1].tokens - a[1].tokens);
147
+ }
148
+ export function createCoreDiagnosticsToolDefinitions(getActiveTools, getAllTools) {
149
+ return [
150
+ {
151
+ name: "context_audit",
152
+ label: "Context Audit",
153
+ description: "Audit the current provider-visible context composition: model window usage, system prompt estimate, active tool schema estimate, active session message rows, and heaviest context contributors.",
154
+ promptSnippet: "Audit current loaded context composition before optimizing context usage.",
155
+ promptGuidelines: [
156
+ "Use context_audit when the user asks what is consuming context, why the footer shows a high percentage, or which messages/tools/system prompt content are loaded.",
157
+ "Keep output bounded; use query/minTokens/maxItems to narrow rather than dumping full context.",
158
+ "Treat token counts as estimates except provider usage from ctx.getContextUsage, which is still model/provider dependent.",
159
+ ],
160
+ parameters: Type.Object({
161
+ maxItems: Type.Optional(Type.Number({ description: "Maximum heaviest session-context rows to show. Default 40, max 200." })),
162
+ minTokens: Type.Optional(Type.Number({
163
+ description: "Only show session-context rows with at least this many estimated tokens.",
164
+ })),
165
+ query: Type.Optional(Type.String({ description: "Case-insensitive filter over row label and preview." })),
166
+ includePreviews: Type.Optional(Type.Boolean({ description: "Include bounded row previews. Defaults true." })),
167
+ }, { additionalProperties: false }),
168
+ async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
169
+ const maxItems = Math.max(1, Math.min(MAX_MAX_ITEMS, Math.floor(params.maxItems ?? DEFAULT_MAX_ITEMS)));
170
+ const minTokens = Math.max(0, Math.floor(params.minTokens ?? 0));
171
+ const includePreviews = params.includePreviews !== false;
172
+ const query = params.query?.trim().toLowerCase();
173
+ const branch = ctx.sessionManager.getBranch();
174
+ const rows = activeContextRows(branch);
175
+ const contextUsage = ctx.getContextUsage();
176
+ const systemPrompt = ctx.getSystemPrompt?.() || "";
177
+ const activeTools = new Set(getActiveTools());
178
+ const allTools = getAllTools();
179
+ const activeToolInfos = allTools.filter((tool) => activeTools.has(tool.name));
180
+ const systemTokens = estimateTextTokens(systemPrompt);
181
+ const toolSchemaChars = JSON.stringify(activeToolInfos.map((tool) => ({
182
+ name: tool.name,
183
+ description: tool.description,
184
+ parameters: tool.parameters,
185
+ promptGuidelines: tool.promptGuidelines,
186
+ }))).length;
187
+ const toolSchemaTokens = Math.ceil(toolSchemaChars / 4);
188
+ const rowTokenSum = rows.reduce((sum, row) => sum + row.tokens, 0);
189
+ const usageText = contextUsage
190
+ ? contextUsage.tokens === null || contextUsage.percent === null
191
+ ? `provider usage: unknown/${contextUsage.contextWindow} tokens (usually right after compaction)`
192
+ : `provider usage: ${contextUsage.tokens}/${contextUsage.contextWindow} tokens (${contextUsage.percent.toFixed(1)}%)`
193
+ : "provider usage: unavailable (no active model/context window)";
194
+ const providerTokens = contextUsage?.tokens ?? null;
195
+ const unattributed = providerTokens === null
196
+ ? null
197
+ : Math.max(0, providerTokens - systemTokens - toolSchemaTokens - rowTokenSum);
198
+ let filtered = rows.filter((row) => row.tokens >= minTokens);
199
+ if (query) {
200
+ filtered = filtered.filter((row) => `${row.label}\n${row.preview}`.toLowerCase().includes(query));
201
+ }
202
+ const heaviest = [...filtered].sort((a, b) => b.tokens - a.tokens).slice(0, maxItems);
203
+ const groupLines = groupRows(rows)
204
+ .slice(0, 12)
205
+ .map(([label, group]) => `- ${label}: ${group.tokens} est tok across ${group.count} row(s)`);
206
+ const rowLines = heaviest.map((row, index) => {
207
+ const base = `${index + 1}. ${row.tokens} est tok · ${row.label} · ${row.entryId ?? "no-entry"}`;
208
+ return includePreviews
209
+ ? `${base}\n ${cap(row.preview, MAX_PREVIEW_CHARS) || "(no text preview)"}`
210
+ : base;
211
+ });
212
+ const lines = [
213
+ "Context audit",
214
+ usageText,
215
+ `active branch rows: ${rows.length}; session row estimate: ${rowTokenSum} tokens`,
216
+ `system prompt estimate: ${systemTokens} tokens (${systemPrompt.length} chars)`,
217
+ `active tool schema estimate: ${toolSchemaTokens} tokens across ${activeToolInfos.length} active tool(s)`,
218
+ unattributed === null
219
+ ? undefined
220
+ : `provider-reported remainder not mapped by chars/4 rows: ${unattributed} tokens`,
221
+ "",
222
+ "Largest groups:",
223
+ ...(groupLines.length ? groupLines : ["- none"]),
224
+ "",
225
+ `Heaviest rows${query ? ` matching ${JSON.stringify(params.query)}` : ""}:`,
226
+ ...(rowLines.length ? rowLines : ["- none"]),
227
+ ].filter((line) => line !== undefined);
228
+ return {
229
+ content: [{ type: "text", text: lines.join("\n") }],
230
+ details: {
231
+ contextUsage,
232
+ systemPrompt: {
233
+ chars: systemPrompt.length,
234
+ estimatedTokens: systemTokens,
235
+ preview: cap(systemPrompt, MAX_PREVIEW_CHARS),
236
+ },
237
+ activeTools: activeToolInfos.map((tool) => tool.name),
238
+ toolSchemaEstimate: { chars: toolSchemaChars, estimatedTokens: toolSchemaTokens },
239
+ rowTokenSum,
240
+ rows,
241
+ },
242
+ };
243
+ },
244
+ },
245
+ ];
246
+ }
247
+ //# sourceMappingURL=builtin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"builtin.js","sourceRoot":"","sources":["../../../src/core/extensions/builtin.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentMessage } from \"@caupulican/pi-agent-core\";\nimport { Type } from \"typebox\";\nimport { estimateTokens } from \"../compaction/compaction.ts\";\nimport { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage } from \"../messages.ts\";\nimport type { CompactionEntry, SessionEntry } from \"../session-manager.ts\";\nimport type { ToolDefinition, ToolInfo } from \"./types.ts\";\n\ntype ContextAuditParams = {\n\tmaxItems?: number;\n\tminTokens?: number;\n\tquery?: string;\n\tincludePreviews?: boolean;\n};\n\ntype AuditRow = {\n\tkind: string;\n\trole?: string;\n\tentryId?: string;\n\ttimestamp?: string;\n\ttokens: number;\n\tchars: number;\n\tlabel: string;\n\tpreview: string;\n};\n\nconst DEFAULT_MAX_ITEMS = 40;\nconst MAX_MAX_ITEMS = 200;\nconst DEFAULT_PREVIEW_CHARS = 220;\nconst MAX_PREVIEW_CHARS = 600;\n\nfunction estimateTextTokens(text: string): number {\n\treturn Math.ceil(text.length / 4);\n}\n\nfunction cap(text: string, limit = DEFAULT_PREVIEW_CHARS): string {\n\tconst compact = text.replace(/\\s+/g, \" \").trim();\n\treturn compact.length > limit ? `${compact.slice(0, Math.max(0, limit - 1))}…` : compact;\n}\n\nfunction contentText(content: unknown): string {\n\tif (typeof content === \"string\") return content;\n\tif (!Array.isArray(content)) return \"\";\n\treturn content\n\t\t.map((part) => {\n\t\t\tif (!part || typeof part !== \"object\") return \"\";\n\t\t\tconst typed = part as { type?: string; text?: string; thinking?: string; name?: string; arguments?: unknown };\n\t\t\tif (typed.type === \"text\") return typed.text || \"\";\n\t\t\tif (typed.type === \"thinking\") return `[thinking ${typed.thinking?.length ?? 0} chars]`;\n\t\t\tif (typed.type === \"toolCall\")\n\t\t\t\treturn `[toolCall ${typed.name || \"unknown\"} ${JSON.stringify(typed.arguments ?? {})}]`;\n\t\t\tif (typed.type === \"image\") return \"[image]\";\n\t\t\treturn \"\";\n\t\t})\n\t\t.filter(Boolean)\n\t\t.join(\"\\n\");\n}\n\nfunction messagePreview(message: AgentMessage): string {\n\tswitch (message.role) {\n\t\tcase \"assistant\":\n\t\tcase \"user\":\n\t\tcase \"toolResult\":\n\t\tcase \"custom\":\n\t\t\treturn contentText((message as { content?: unknown }).content);\n\t\tcase \"bashExecution\":\n\t\t\treturn `Ran ${message.command}\\n${message.output}`;\n\t\tcase \"branchSummary\":\n\t\tcase \"compactionSummary\":\n\t\t\treturn message.summary;\n\t\tdefault:\n\t\t\treturn \"\";\n\t}\n}\n\nfunction messageLabel(message: AgentMessage): string {\n\tif (message.role === \"assistant\") {\n\t\tconst toolCalls = message.content.filter((part) => part.type === \"toolCall\").length;\n\t\treturn toolCalls > 0 ? `assistant (${toolCalls} tool call${toolCalls === 1 ? \"\" : \"s\"})` : \"assistant\";\n\t}\n\tif (message.role === \"toolResult\") return `tool result: ${message.toolName}`;\n\tif (message.role === \"custom\") return `custom: ${message.customType}`;\n\tif (message.role === \"bashExecution\") return \"bash execution\";\n\tif (message.role === \"branchSummary\") return \"branch summary\";\n\tif (message.role === \"compactionSummary\") return \"compaction summary\";\n\treturn message.role;\n}\n\nfunction addRow(rows: AuditRow[], entry: SessionEntry, message: AgentMessage, kindOverride?: string) {\n\tconst preview = messagePreview(message);\n\trows.push({\n\t\tkind: kindOverride || entry.type,\n\t\trole: message.role,\n\t\tentryId: entry.id,\n\t\ttimestamp: entry.timestamp,\n\t\ttokens: estimateTokens(message),\n\t\tchars: preview.length,\n\t\tlabel: messageLabel(message),\n\t\tpreview: cap(preview),\n\t});\n}\n\nfunction messageFromEntry(entry: SessionEntry): AgentMessage | undefined {\n\tif (entry.type === \"message\") return entry.message;\n\tif (entry.type === \"custom_message\") {\n\t\treturn createCustomMessage(entry.customType, entry.content, entry.display, entry.details, entry.timestamp);\n\t}\n\tif (entry.type === \"branch_summary\" && entry.summary) {\n\t\treturn createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp);\n\t}\n\treturn undefined;\n}\n\nfunction latestCompaction(entries: SessionEntry[]): CompactionEntry | undefined {\n\tfor (let index = entries.length - 1; index >= 0; index--) {\n\t\tconst entry = entries[index];\n\t\tif (entry?.type === \"compaction\") return entry;\n\t}\n\treturn undefined;\n}\n\nfunction activeContextRows(entries: SessionEntry[]): AuditRow[] {\n\tconst rows: AuditRow[] = [];\n\tconst compaction = latestCompaction(entries);\n\tif (!compaction) {\n\t\tfor (const entry of entries) {\n\t\t\tconst message = messageFromEntry(entry);\n\t\t\tif (message) addRow(rows, entry, message);\n\t\t}\n\t\treturn rows;\n\t}\n\n\tconst compactionMessage = createCompactionSummaryMessage(\n\t\tcompaction.summary,\n\t\tcompaction.tokensBefore,\n\t\tcompaction.timestamp,\n\t);\n\taddRow(rows, compaction, compactionMessage, \"compaction\");\n\n\tconst compactionIndex = entries.findIndex((entry) => entry.id === compaction.id);\n\tlet foundFirstKept = false;\n\tfor (let index = 0; index < compactionIndex; index++) {\n\t\tconst entry = entries[index];\n\t\tif (entry.id === compaction.firstKeptEntryId) foundFirstKept = true;\n\t\tif (!foundFirstKept) continue;\n\t\tconst message = messageFromEntry(entry);\n\t\tif (message) addRow(rows, entry, message);\n\t}\n\tfor (let index = compactionIndex + 1; index < entries.length; index++) {\n\t\tconst entry = entries[index];\n\t\tconst message = messageFromEntry(entry);\n\t\tif (message) addRow(rows, entry, message);\n\t}\n\treturn rows;\n}\n\nfunction groupRows(rows: AuditRow[]): Array<[string, { count: number; tokens: number; chars: number }]> {\n\tconst groups = new Map<string, { count: number; tokens: number; chars: number }>();\n\tfor (const row of rows) {\n\t\tconst key = row.label;\n\t\tconst current = groups.get(key) ?? { count: 0, tokens: 0, chars: 0 };\n\t\tcurrent.count += 1;\n\t\tcurrent.tokens += row.tokens;\n\t\tcurrent.chars += row.chars;\n\t\tgroups.set(key, current);\n\t}\n\treturn [...groups.entries()].sort((a, b) => b[1].tokens - a[1].tokens);\n}\n\nexport function createCoreDiagnosticsToolDefinitions(\n\tgetActiveTools: () => string[],\n\tgetAllTools: () => ToolInfo[],\n): ToolDefinition[] {\n\treturn [\n\t\t{\n\t\t\tname: \"context_audit\",\n\t\t\tlabel: \"Context Audit\",\n\t\t\tdescription:\n\t\t\t\t\"Audit the current provider-visible context composition: model window usage, system prompt estimate, active tool schema estimate, active session message rows, and heaviest context contributors.\",\n\t\t\tpromptSnippet: \"Audit current loaded context composition before optimizing context usage.\",\n\t\t\tpromptGuidelines: [\n\t\t\t\t\"Use context_audit when the user asks what is consuming context, why the footer shows a high percentage, or which messages/tools/system prompt content are loaded.\",\n\t\t\t\t\"Keep output bounded; use query/minTokens/maxItems to narrow rather than dumping full context.\",\n\t\t\t\t\"Treat token counts as estimates except provider usage from ctx.getContextUsage, which is still model/provider dependent.\",\n\t\t\t],\n\t\t\tparameters: Type.Object(\n\t\t\t\t{\n\t\t\t\t\tmaxItems: Type.Optional(\n\t\t\t\t\t\tType.Number({ description: \"Maximum heaviest session-context rows to show. Default 40, max 200.\" }),\n\t\t\t\t\t),\n\t\t\t\t\tminTokens: Type.Optional(\n\t\t\t\t\t\tType.Number({\n\t\t\t\t\t\t\tdescription: \"Only show session-context rows with at least this many estimated tokens.\",\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t\tquery: Type.Optional(\n\t\t\t\t\t\tType.String({ description: \"Case-insensitive filter over row label and preview.\" }),\n\t\t\t\t\t),\n\t\t\t\t\tincludePreviews: Type.Optional(\n\t\t\t\t\t\tType.Boolean({ description: \"Include bounded row previews. Defaults true.\" }),\n\t\t\t\t\t),\n\t\t\t\t},\n\t\t\t\t{ additionalProperties: false },\n\t\t\t),\n\t\t\tasync execute(_toolCallId, params: ContextAuditParams, _signal, _onUpdate, ctx) {\n\t\t\t\tconst maxItems = Math.max(1, Math.min(MAX_MAX_ITEMS, Math.floor(params.maxItems ?? DEFAULT_MAX_ITEMS)));\n\t\t\t\tconst minTokens = Math.max(0, Math.floor(params.minTokens ?? 0));\n\t\t\t\tconst includePreviews = params.includePreviews !== false;\n\t\t\t\tconst query = params.query?.trim().toLowerCase();\n\n\t\t\t\tconst branch = ctx.sessionManager.getBranch();\n\t\t\t\tconst rows = activeContextRows(branch);\n\t\t\t\tconst contextUsage = ctx.getContextUsage();\n\t\t\t\tconst systemPrompt = ctx.getSystemPrompt?.() || \"\";\n\t\t\t\tconst activeTools = new Set(getActiveTools());\n\t\t\t\tconst allTools = getAllTools();\n\t\t\t\tconst activeToolInfos = allTools.filter((tool) => activeTools.has(tool.name));\n\t\t\t\tconst systemTokens = estimateTextTokens(systemPrompt);\n\t\t\t\tconst toolSchemaChars = JSON.stringify(\n\t\t\t\t\tactiveToolInfos.map((tool) => ({\n\t\t\t\t\t\tname: tool.name,\n\t\t\t\t\t\tdescription: tool.description,\n\t\t\t\t\t\tparameters: tool.parameters,\n\t\t\t\t\t\tpromptGuidelines: tool.promptGuidelines,\n\t\t\t\t\t})),\n\t\t\t\t).length;\n\t\t\t\tconst toolSchemaTokens = Math.ceil(toolSchemaChars / 4);\n\t\t\t\tconst rowTokenSum = rows.reduce((sum, row) => sum + row.tokens, 0);\n\t\t\t\tconst usageText = contextUsage\n\t\t\t\t\t? contextUsage.tokens === null || contextUsage.percent === null\n\t\t\t\t\t\t? `provider usage: unknown/${contextUsage.contextWindow} tokens (usually right after compaction)`\n\t\t\t\t\t\t: `provider usage: ${contextUsage.tokens}/${contextUsage.contextWindow} tokens (${contextUsage.percent.toFixed(1)}%)`\n\t\t\t\t\t: \"provider usage: unavailable (no active model/context window)\";\n\t\t\t\tconst providerTokens = contextUsage?.tokens ?? null;\n\t\t\t\tconst unattributed =\n\t\t\t\t\tproviderTokens === null\n\t\t\t\t\t\t? null\n\t\t\t\t\t\t: Math.max(0, providerTokens - systemTokens - toolSchemaTokens - rowTokenSum);\n\n\t\t\t\tlet filtered = rows.filter((row) => row.tokens >= minTokens);\n\t\t\t\tif (query) {\n\t\t\t\t\tfiltered = filtered.filter((row) => `${row.label}\\n${row.preview}`.toLowerCase().includes(query));\n\t\t\t\t}\n\t\t\t\tconst heaviest = [...filtered].sort((a, b) => b.tokens - a.tokens).slice(0, maxItems);\n\t\t\t\tconst groupLines = groupRows(rows)\n\t\t\t\t\t.slice(0, 12)\n\t\t\t\t\t.map(([label, group]) => `- ${label}: ${group.tokens} est tok across ${group.count} row(s)`);\n\t\t\t\tconst rowLines = heaviest.map((row, index) => {\n\t\t\t\t\tconst base = `${index + 1}. ${row.tokens} est tok · ${row.label} · ${row.entryId ?? \"no-entry\"}`;\n\t\t\t\t\treturn includePreviews\n\t\t\t\t\t\t? `${base}\\n ${cap(row.preview, MAX_PREVIEW_CHARS) || \"(no text preview)\"}`\n\t\t\t\t\t\t: base;\n\t\t\t\t});\n\n\t\t\t\tconst lines = [\n\t\t\t\t\t\"Context audit\",\n\t\t\t\t\tusageText,\n\t\t\t\t\t`active branch rows: ${rows.length}; session row estimate: ${rowTokenSum} tokens`,\n\t\t\t\t\t`system prompt estimate: ${systemTokens} tokens (${systemPrompt.length} chars)`,\n\t\t\t\t\t`active tool schema estimate: ${toolSchemaTokens} tokens across ${activeToolInfos.length} active tool(s)`,\n\t\t\t\t\tunattributed === null\n\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t: `provider-reported remainder not mapped by chars/4 rows: ${unattributed} tokens`,\n\t\t\t\t\t\"\",\n\t\t\t\t\t\"Largest groups:\",\n\t\t\t\t\t...(groupLines.length ? groupLines : [\"- none\"]),\n\t\t\t\t\t\"\",\n\t\t\t\t\t`Heaviest rows${query ? ` matching ${JSON.stringify(params.query)}` : \"\"}:`,\n\t\t\t\t\t...(rowLines.length ? rowLines : [\"- none\"]),\n\t\t\t\t].filter((line): line is string => line !== undefined);\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\" as const, text: lines.join(\"\\n\") }],\n\t\t\t\t\tdetails: {\n\t\t\t\t\t\tcontextUsage,\n\t\t\t\t\t\tsystemPrompt: {\n\t\t\t\t\t\t\tchars: systemPrompt.length,\n\t\t\t\t\t\t\testimatedTokens: systemTokens,\n\t\t\t\t\t\t\tpreview: cap(systemPrompt, MAX_PREVIEW_CHARS),\n\t\t\t\t\t\t},\n\t\t\t\t\t\tactiveTools: activeToolInfos.map((tool) => tool.name),\n\t\t\t\t\t\ttoolSchemaEstimate: { chars: toolSchemaChars, estimatedTokens: toolSchemaTokens },\n\t\t\t\t\t\trowTokenSum,\n\t\t\t\t\t\trows,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t},\n\t\t},\n\t];\n}\n"]}
@@ -196,6 +196,9 @@ export declare class DefaultPackageManager implements PackageManager {
196
196
  private getTargetMap;
197
197
  private addResource;
198
198
  private createAccumulator;
199
+ private getResourceProfileScanPath;
200
+ private collectEmbeddedResourceProfiles;
201
+ private applyResourceProfileFilters;
199
202
  private toResolvedPaths;
200
203
  private spawnCommand;
201
204
  private spawnCaptureCommand;