@caupulican/pi-adaptative 0.81.43 → 0.84.1

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 (37) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/config.d.ts +1 -1
  3. package/dist/config.d.ts.map +1 -1
  4. package/dist/config.js +1 -1
  5. package/dist/config.js.map +1 -1
  6. package/dist/core/agent-paths.d.ts +1 -1
  7. package/dist/core/agent-paths.d.ts.map +1 -1
  8. package/dist/core/agent-paths.js +1 -1
  9. package/dist/core/agent-paths.js.map +1 -1
  10. package/dist/core/doctor.d.ts +5 -5
  11. package/dist/core/doctor.d.ts.map +1 -1
  12. package/dist/core/doctor.js +16 -20
  13. package/dist/core/doctor.js.map +1 -1
  14. package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -1
  15. package/dist/core/secrets/credential-exposure-guard.js +32 -0
  16. package/dist/core/secrets/credential-exposure-guard.js.map +1 -1
  17. package/dist/core/system-prompt.d.ts.map +1 -1
  18. package/dist/core/system-prompt.js +1 -0
  19. package/dist/core/system-prompt.js.map +1 -1
  20. package/dist/modes/interactive/interactive-mode.js +3 -3
  21. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  22. package/dist/utils/tools-manager.d.ts +6 -1
  23. package/dist/utils/tools-manager.d.ts.map +1 -1
  24. package/dist/utils/tools-manager.js +59 -2
  25. package/dist/utils/tools-manager.js.map +1 -1
  26. package/docs/development.md +1 -1
  27. package/docs/windows.md +2 -2
  28. package/docs/work-directory.md +1 -1
  29. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  30. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  31. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  32. package/examples/extensions/sandbox/package-lock.json +2 -2
  33. package/examples/extensions/sandbox/package.json +1 -1
  34. package/examples/extensions/with-deps/package-lock.json +2 -2
  35. package/examples/extensions/with-deps/package.json +1 -1
  36. package/npm-shrinkwrap.json +23 -23
  37. package/package.json +5 -5
@@ -1 +1 @@
1
- {"version":3,"file":"credential-exposure-guard.d.ts","sourceRoot":"","sources":["../../../src/core/secrets/credential-exposure-guard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,2BAA2B,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAoCrD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CA8BpG;AA+FD,yFAAyF;AACzF,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,WAAW,GACjB,MAAM,GAAG,SAAS,CAqDpB;AAuCD,wGAAwG;AACxG,wBAAgB,mCAAmC,CAAC,WAAW,SAAS,OAAO,EAAE,QAAQ,EACxF,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,QAAQ,CAAC,EACtC,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,WAAW,GACjB,SAAS,CAAC,WAAW,EAAE,QAAQ,CAAC,CAqBlC"}
1
+ {"version":3,"file":"credential-exposure-guard.d.ts","sourceRoot":"","sources":["../../../src/core/secrets/credential-exposure-guard.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,2BAA2B,CAAC;AAC5E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAIvC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAsCrD,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,WAAW,GAAG,OAAO,CA8BpG;AAyHD,yFAAyF;AACzF,wBAAgB,yBAAyB,CACxC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,EACb,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,WAAW,GACjB,MAAM,GAAG,SAAS,CAwDpB;AAuCD,wGAAwG;AACxG,wBAAgB,mCAAmC,CAAC,WAAW,SAAS,OAAO,EAAE,QAAQ,EACxF,IAAI,EAAE,SAAS,CAAC,WAAW,EAAE,QAAQ,CAAC,EACtC,GAAG,EAAE,MAAM,EACX,KAAK,CAAC,EAAE,WAAW,GACjB,SAAS,CAAC,WAAW,EAAE,QAAQ,CAAC,CAqBlC"}
@@ -26,6 +26,8 @@ const PYTHON_INSPECTION_RE = /\b(?:open|read_text|read_bytes)\b/;
26
26
  const QUOTED_TEXT_RE = /(["'])([^"'\\]*(?:\\.[^"'\\]*)*)\1/g;
27
27
  const MAX_REDACTED_DETAIL_DEPTH = 8;
28
28
  const MAX_REDACTED_DETAIL_NODES = 10_000;
29
+ const JQ_OPTIONS_WITH_ONE_OPERAND = new Set(["-L", "--indent"]);
30
+ const JQ_OPTIONS_WITH_TWO_OPERANDS = new Set(["--arg", "--argjson", "--rawfile", "--slurpfile"]);
29
31
  function isRecord(value) {
30
32
  return typeof value === "object" && value !== null && !Array.isArray(value);
31
33
  }
@@ -75,6 +77,11 @@ function shellCredentialRisk(command, cwd, vault) {
75
77
  const assessInvocation = (invocation, readsPipe) => {
76
78
  for (let commandIndex = 0; commandIndex < invocation.length; commandIndex++) {
77
79
  const toolName = (invocation[commandIndex].split(/[\\/]/u).at(-1) ?? "").toLowerCase().replace(/\.exe$/u, "");
80
+ if (toolName === "jq") {
81
+ const filter = jqFilterFromArgs(invocation.slice(commandIndex + 1));
82
+ if (filter && jqFilterReadsProcessEnvironment(filter))
83
+ return "process_environment";
84
+ }
78
85
  if (!SHELL_INSPECTION_COMMANDS.has(toolName))
79
86
  continue;
80
87
  const args = invocation.slice(commandIndex + 1);
@@ -126,6 +133,28 @@ function shellCredentialRisk(command, cwd, vault) {
126
133
  }
127
134
  return assessInvocation(invocation, readsPipe);
128
135
  }
136
+ function jqFilterFromArgs(args) {
137
+ for (let index = 0; index < args.length; index++) {
138
+ const token = args[index];
139
+ if (token === "--")
140
+ return args[index + 1];
141
+ if (JQ_OPTIONS_WITH_TWO_OPERANDS.has(token)) {
142
+ index += 2;
143
+ continue;
144
+ }
145
+ if (JQ_OPTIONS_WITH_ONE_OPERAND.has(token)) {
146
+ index++;
147
+ continue;
148
+ }
149
+ if (token.startsWith("-"))
150
+ continue;
151
+ return token;
152
+ }
153
+ return undefined;
154
+ }
155
+ function jqFilterReadsProcessEnvironment(filter) {
156
+ return /(?:^|[\s|,(:;[])(?:env|\$ENV)(?=$|[\s|),.;[\]}])/u.test(filter);
157
+ }
129
158
  function isCredentialSafeGlob(glob) {
130
159
  if (/(?:^|[\\/])?\.env(?:\.|\*|$)/i.test(glob))
131
160
  return false;
@@ -192,6 +221,9 @@ export function credentialToolBlockReason(toolName, args, cwd, vault) {
192
221
  if (shellRisk === "broad_search") {
193
222
  return "Credential-safe shell search requires a narrow non-dotenv file glob (for example -g '*.ts') or one explicit regular file. Refine the rg/grep command before retrying.";
194
223
  }
224
+ if (shellRisk === "process_environment") {
225
+ return "Direct jq projection of the process environment is blocked because it can expose credentials. Query bounded JSON inputs instead.";
226
+ }
195
227
  if (SHELL_SECRET_READ_RE.test(command) || shellRisk === "credential_path") {
196
228
  return "Direct shell inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming command normally.";
197
229
  }
@@ -1 +1 @@
1
- {"version":3,"file":"credential-exposure-guard.js","sourceRoot":"","sources":["../../../src/core/secrets/credential-exposure-guard.ts"],"names":[],"mappings":"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","sourcesContent":["import { realpathSync, statSync } from \"node:fs\";\nimport { basename, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { AgentTool, AgentToolResult } from \"@caupulican/pi-agent-core\";\nimport type { TSchema } from \"typebox\";\nimport { redactKnownSecrets } from \"../security/secret-text.ts\";\nimport { parseShellSearchInvocationScope, type ShellContentSearchTool } from \"../tools/search-command-guard.ts\";\nimport { tokenizeShellCommand } from \"../tools/shell-command-parser.ts\";\nimport type { SecretVault } from \"./secret-vault.ts\";\n\nconst DIRECT_PATH_TOOLS = new Set([\"read\", \"edit\", \"write\", \"ls\"]);\nconst SHELL_INSPECTION_COMMANDS = new Set([\n\t\"cat\",\n\t\"head\",\n\t\"tail\",\n\t\"less\",\n\t\"more\",\n\t\"sed\",\n\t\"awk\",\n\t\"grep\",\n\t\"rg\",\n\t\"ripgrep\",\n\t\"type\",\n\t\"get-content\",\n\t\"select-string\",\n\t\"source\",\n]);\nconst SHELL_SECRET_READ_RE =\n\t/\\b(?:cat|head|tail|less|more|sed|awk|grep|rg|type|get-content|select-string|source)\\b[^\\n;&|]*(?:^|[\\\\/])?\\.env(?:\\.[A-Za-z0-9._-]+)?\\b/i;\nconst PYTHON_SECRET_READ_RE = /\\b(?:open|read_text|read_bytes)\\s*\\([^\\n)]*(?:^|[\\\\/])?\\.env(?:\\.[A-Za-z0-9._-]+)?\\b/i;\nconst PYTHON_INSPECTION_RE = /\\b(?:open|read_text|read_bytes)\\b/;\nconst QUOTED_TEXT_RE = /([\"'])([^\"'\\\\]*(?:\\\\.[^\"'\\\\]*)*)\\1/g;\nconst MAX_REDACTED_DETAIL_DEPTH = 8;\nconst MAX_REDACTED_DETAIL_NODES = 10_000;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isInside(root: string, target: string): boolean {\n\tconst fromRoot = relative(root, target);\n\treturn fromRoot === \"\" || (!fromRoot.startsWith(`..${sep}`) && fromRoot !== \"..\" && !isAbsolute(fromRoot));\n}\n\nexport function isProtectedCredentialPath(rawPath: string, cwd: string, vault?: SecretVault): boolean {\n\tconst resolved = resolve(cwd, rawPath);\n\tconst candidates = [resolved];\n\ttry {\n\t\tconst canonical = realpathSync.native(resolved);\n\t\tif (canonical !== resolved) candidates.push(canonical);\n\t} catch {\n\t\t// Nonexistent write targets still receive the lexical filename check.\n\t}\n\tconst vaultPaths = vault ? [resolve(vault.vaultPath)] : [];\n\tconst materializedRoots = vault ? [resolve(vault.materializedDir)] : [];\n\tif (vault) {\n\t\ttry {\n\t\t\tvaultPaths.push(realpathSync.native(vault.vaultPath));\n\t\t} catch {\n\t\t\t// A not-yet-created vault still retains its lexical protected path.\n\t\t}\n\t\ttry {\n\t\t\tmaterializedRoots.push(realpathSync.native(vault.materializedDir));\n\t\t} catch {\n\t\t\t// A not-yet-created materialization directory still retains its lexical protected root.\n\t\t}\n\t}\n\treturn candidates.some((candidate) => {\n\t\tif (vault && (vaultPaths.includes(candidate) || materializedRoots.some((root) => isInside(root, candidate)))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fileName = basename(candidate);\n\t\treturn fileName === \".env\" || fileName.startsWith(\".env.\") || fileName.endsWith(\".env\");\n\t});\n}\n\nfunction shellCredentialRisk(\n\tcommand: string,\n\tcwd: string,\n\tvault?: SecretVault,\n): \"broad_search\" | \"credential_path\" | undefined {\n\tconst shellTokens = tokenizeShellCommand(command);\n\tif (!shellTokens) return /\\b(?:grep|rg)\\b/iu.test(command) ? \"broad_search\" : undefined;\n\n\tconst assessInvocation = (\n\t\tinvocation: string[],\n\t\treadsPipe: boolean,\n\t): \"broad_search\" | \"credential_path\" | undefined => {\n\t\tfor (let commandIndex = 0; commandIndex < invocation.length; commandIndex++) {\n\t\t\tconst toolName = (invocation[commandIndex].split(/[\\\\/]/u).at(-1) ?? \"\").toLowerCase().replace(/\\.exe$/u, \"\");\n\t\t\tif (!SHELL_INSPECTION_COMMANDS.has(toolName)) continue;\n\t\t\tconst args = invocation.slice(commandIndex + 1);\n\t\t\tconst searchTool: ShellContentSearchTool | undefined =\n\t\t\t\ttoolName === \"rg\" || toolName === \"ripgrep\" ? \"rg\" : toolName === \"grep\" ? \"grep\" : undefined;\n\t\t\tif (searchTool) {\n\t\t\t\tconst scope = parseShellSearchInvocationScope(searchTool, args, readsPipe);\n\t\t\t\tif (scope.targets.some((target) => target !== \"-\" && isProtectedCredentialPath(target, cwd, vault))) {\n\t\t\t\t\treturn \"credential_path\";\n\t\t\t\t}\n\t\t\t\tconst hasSafeGlob =\n\t\t\t\t\tscope.positiveGlobs.length > 0 && scope.positiveGlobs.every((glob) => isCredentialSafeGlob(glob));\n\t\t\t\tconst hasOnlyExplicitFiles =\n\t\t\t\t\tscope.targets.length > 0 &&\n\t\t\t\t\tscope.targets.every((target) => target === \"-\" || isExistingRegularFile(target, cwd));\n\t\t\t\tif (!scope.metaOnly && !scope.readsStdin && !hasSafeGlob && !hasOnlyExplicitFiles) return \"broad_search\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const token of args) {\n\t\t\t\tif (!token || token.startsWith(\"-\") || token === \".\") continue;\n\t\t\t\tif (isProtectedCredentialPath(token, cwd, vault)) return \"credential_path\";\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tlet invocation: string[] = [];\n\tlet skipRedirectTarget = false;\n\tlet readsPipe = false;\n\tfor (const token of shellTokens) {\n\t\tif (token.kind === \"arg\") {\n\t\t\tif (skipRedirectTarget) skipRedirectTarget = false;\n\t\t\telse invocation.push(token.value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (token.kind === \"redirect\") {\n\t\t\t// Descriptor duplication (`2>&1`) has no following path operand. Other\n\t\t\t// redirects do, and that target must never count as search scope.\n\t\t\tskipRedirectTarget = !/^\\d*[<>]&[\\d-]+$/u.test(token.value);\n\t\t\tcontinue;\n\t\t}\n\t\tconst risk = assessInvocation(invocation, readsPipe);\n\t\tif (risk) return risk;\n\t\tinvocation = [];\n\t\tskipRedirectTarget = false;\n\t\treadsPipe = token.kind === \"pipe\";\n\t}\n\treturn assessInvocation(invocation, readsPipe);\n}\n\nfunction isCredentialSafeGlob(glob: string): boolean {\n\tif (/(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(glob)) return false;\n\tconst filePattern = glob.replace(/\\\\/g, \"/\").split(\"/\").at(-1) ?? \"\";\n\tconst suffix = filePattern.match(/\\.([A-Za-z0-9_-]+)$/)?.[1]?.toLowerCase();\n\treturn suffix !== undefined && suffix !== \"env\";\n}\n\nfunction isExistingRegularFile(rawPath: string, cwd: string): boolean {\n\ttry {\n\t\treturn statSync(resolve(cwd, rawPath)).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction pythonInspectsCredentialPath(code: string, cwd: string, vault?: SecretVault): boolean {\n\tif (!PYTHON_INSPECTION_RE.test(code)) return false;\n\tQUOTED_TEXT_RE.lastIndex = 0;\n\tfor (const match of code.matchAll(QUOTED_TEXT_RE)) {\n\t\tconst candidate = match[2]?.replace(/\\\\([\\\\\"'])/g, \"$1\");\n\t\tif (candidate && isProtectedCredentialPath(candidate, cwd, vault)) return true;\n\t}\n\treturn false;\n}\n\nfunction directPathFromArgs(args: unknown): string | undefined {\n\tif (!isRecord(args)) return undefined;\n\treturn typeof args.path === \"string\" ? args.path : undefined;\n}\n\n/** Stable model-facing refusal for direct inspection/mutation of credential material. */\nexport function credentialToolBlockReason(\n\ttoolName: string,\n\targs: unknown,\n\tcwd: string,\n\tvault?: SecretVault,\n): string | undefined {\n\tif (toolName === \"secret_store\" || !isRecord(args)) return undefined;\n\tif (DIRECT_PATH_TOOLS.has(toolName)) {\n\t\tconst path = directPathFromArgs(args);\n\t\tif (path && isProtectedCredentialPath(path, cwd, vault)) {\n\t\t\treturn \"Credential file access is model-blind. Use secret_store to edit or materialize the bound profile, then run the consuming application without inspecting the dotenv file.\";\n\t\t}\n\t}\n\tif (toolName === \"grep\") {\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tconst glob = typeof args.glob === \"string\" ? args.glob : undefined;\n\t\tif (\n\t\t\t(path && isProtectedCredentialPath(path, cwd, vault)) ||\n\t\t\t(glob && /(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(glob))\n\t\t) {\n\t\t\treturn \"Credential dotenv files are excluded from model-facing search. Use secret_store metadata instead.\";\n\t\t}\n\t\tif (!(path && isExistingRegularFile(path, cwd)) && !(glob && isCredentialSafeGlob(glob))) {\n\t\t\treturn \"Credential-safe grep requires one explicit regular file or a narrow non-dotenv file glob (for example *.ts). Refine the search instead of scanning a directory without a file filter.\";\n\t\t}\n\t}\n\tif (toolName === \"find\") {\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tconst pattern = typeof args.pattern === \"string\" ? args.pattern : undefined;\n\t\tif (\n\t\t\t(path && isProtectedCredentialPath(path, cwd, vault)) ||\n\t\t\t(pattern && /(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(pattern))\n\t\t) {\n\t\t\treturn \"Credential dotenv files are excluded from model-facing discovery. Use secret_store list instead.\";\n\t\t}\n\t}\n\tif (toolName === \"bash\" || toolName === \"powershell\" || toolName === \"run_process\") {\n\t\tconst command = typeof args.command === \"string\" ? args.command : \"\";\n\t\tconst shellRisk = shellCredentialRisk(command, cwd, vault);\n\t\tif (shellRisk === \"broad_search\") {\n\t\t\treturn \"Credential-safe shell search requires a narrow non-dotenv file glob (for example -g '*.ts') or one explicit regular file. Refine the rg/grep command before retrying.\";\n\t\t}\n\t\tif (SHELL_SECRET_READ_RE.test(command) || shellRisk === \"credential_path\") {\n\t\t\treturn \"Direct shell inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming command normally.\";\n\t\t}\n\t}\n\tif (toolName === \"python\") {\n\t\tconst code = typeof args.code === \"string\" ? args.code : \"\";\n\t\tconst scriptPath = typeof args.scriptPath === \"string\" ? args.scriptPath : undefined;\n\t\tif (\n\t\t\tPYTHON_SECRET_READ_RE.test(code) ||\n\t\t\tpythonInspectsCredentialPath(code, cwd, vault) ||\n\t\t\t(scriptPath !== undefined && isProtectedCredentialPath(scriptPath, cwd, vault))\n\t\t) {\n\t\t\treturn \"Direct Python inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming program normally.\";\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction redactResult<T>(result: AgentToolResult<T>, vault?: SecretVault): AgentToolResult<T> {\n\tconst redact = (text: string) => (vault ? vault.redactSensitiveText(text) : redactKnownSecrets(text));\n\tconst budget = { nodes: 0 };\n\treturn {\n\t\t...result,\n\t\tcontent: result.content.map((block) => (block.type === \"text\" ? { ...block, text: redact(block.text) } : block)),\n\t\tdetails: redactStructuredDetails(result.details, redact, budget) as T,\n\t};\n}\n\nfunction redactStructuredDetails(\n\tvalue: unknown,\n\tredact: (text: string) => string,\n\tbudget: { nodes: number },\n\tdepth = 0,\n): unknown {\n\tif (typeof value === \"string\") return redact(value);\n\tif (value === null || typeof value !== \"object\") return value;\n\tbudget.nodes++;\n\tif (depth >= MAX_REDACTED_DETAIL_DEPTH || budget.nodes > MAX_REDACTED_DETAIL_NODES) {\n\t\treturn \"[DETAIL OMITTED AT CREDENTIAL BOUNDARY]\";\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => redactStructuredDetails(entry, redact, budget, depth + 1));\n\t}\n\tlet prototype: object | null;\n\ttry {\n\t\tprototype = Object.getPrototypeOf(value);\n\t} catch {\n\t\treturn \"[UNREADABLE DETAIL OMITTED AT CREDENTIAL BOUNDARY]\";\n\t}\n\tif (prototype !== Object.prototype && prototype !== null) return value;\n\treturn Object.fromEntries(\n\t\tObject.entries(value).map(([key, entry]) => [key, redactStructuredDetails(entry, redact, budget, depth + 1)]),\n\t);\n}\n\n/** Apply the same path refusal and output redaction to foreground, extension, scout, and lane tools. */\nexport function wrapToolWithCredentialExposureGuard<TParameters extends TSchema, TDetails>(\n\ttool: AgentTool<TParameters, TDetails>,\n\tcwd: string,\n\tvault?: SecretVault,\n): AgentTool<TParameters, TDetails> {\n\treturn {\n\t\t...tool,\n\t\tasync execute(toolCallId, params, signal, onUpdate) {\n\t\t\tconst refusal = credentialToolBlockReason(tool.name, params, cwd, vault);\n\t\t\tif (refusal) throw new Error(refusal);\n\t\t\tconst safeUpdate = onUpdate\n\t\t\t\t? (partial: AgentToolResult<TDetails>) => {\n\t\t\t\t\t\tonUpdate(redactResult(partial, vault));\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\t\ttry {\n\t\t\t\treturn redactResult(await tool.execute(toolCallId, params, signal, safeUpdate), vault);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tthrow new Error(vault ? vault.redactSensitiveText(error.message) : redactKnownSecrets(error.message));\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Credential-safe tool execution failed without retaining raw error output.\");\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"credential-exposure-guard.js","sourceRoot":"","sources":["../../../src/core/secrets/credential-exposure-guard.ts"],"names":[],"mappings":"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","sourcesContent":["import { realpathSync, statSync } from \"node:fs\";\nimport { basename, isAbsolute, relative, resolve, sep } from \"node:path\";\nimport type { AgentTool, AgentToolResult } from \"@caupulican/pi-agent-core\";\nimport type { TSchema } from \"typebox\";\nimport { redactKnownSecrets } from \"../security/secret-text.ts\";\nimport { parseShellSearchInvocationScope, type ShellContentSearchTool } from \"../tools/search-command-guard.ts\";\nimport { tokenizeShellCommand } from \"../tools/shell-command-parser.ts\";\nimport type { SecretVault } from \"./secret-vault.ts\";\n\nconst DIRECT_PATH_TOOLS = new Set([\"read\", \"edit\", \"write\", \"ls\"]);\nconst SHELL_INSPECTION_COMMANDS = new Set([\n\t\"cat\",\n\t\"head\",\n\t\"tail\",\n\t\"less\",\n\t\"more\",\n\t\"sed\",\n\t\"awk\",\n\t\"grep\",\n\t\"rg\",\n\t\"ripgrep\",\n\t\"type\",\n\t\"get-content\",\n\t\"select-string\",\n\t\"source\",\n]);\nconst SHELL_SECRET_READ_RE =\n\t/\\b(?:cat|head|tail|less|more|sed|awk|grep|rg|type|get-content|select-string|source)\\b[^\\n;&|]*(?:^|[\\\\/])?\\.env(?:\\.[A-Za-z0-9._-]+)?\\b/i;\nconst PYTHON_SECRET_READ_RE = /\\b(?:open|read_text|read_bytes)\\s*\\([^\\n)]*(?:^|[\\\\/])?\\.env(?:\\.[A-Za-z0-9._-]+)?\\b/i;\nconst PYTHON_INSPECTION_RE = /\\b(?:open|read_text|read_bytes)\\b/;\nconst QUOTED_TEXT_RE = /([\"'])([^\"'\\\\]*(?:\\\\.[^\"'\\\\]*)*)\\1/g;\nconst MAX_REDACTED_DETAIL_DEPTH = 8;\nconst MAX_REDACTED_DETAIL_NODES = 10_000;\nconst JQ_OPTIONS_WITH_ONE_OPERAND = new Set([\"-L\", \"--indent\"]);\nconst JQ_OPTIONS_WITH_TWO_OPERANDS = new Set([\"--arg\", \"--argjson\", \"--rawfile\", \"--slurpfile\"]);\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isInside(root: string, target: string): boolean {\n\tconst fromRoot = relative(root, target);\n\treturn fromRoot === \"\" || (!fromRoot.startsWith(`..${sep}`) && fromRoot !== \"..\" && !isAbsolute(fromRoot));\n}\n\nexport function isProtectedCredentialPath(rawPath: string, cwd: string, vault?: SecretVault): boolean {\n\tconst resolved = resolve(cwd, rawPath);\n\tconst candidates = [resolved];\n\ttry {\n\t\tconst canonical = realpathSync.native(resolved);\n\t\tif (canonical !== resolved) candidates.push(canonical);\n\t} catch {\n\t\t// Nonexistent write targets still receive the lexical filename check.\n\t}\n\tconst vaultPaths = vault ? [resolve(vault.vaultPath)] : [];\n\tconst materializedRoots = vault ? [resolve(vault.materializedDir)] : [];\n\tif (vault) {\n\t\ttry {\n\t\t\tvaultPaths.push(realpathSync.native(vault.vaultPath));\n\t\t} catch {\n\t\t\t// A not-yet-created vault still retains its lexical protected path.\n\t\t}\n\t\ttry {\n\t\t\tmaterializedRoots.push(realpathSync.native(vault.materializedDir));\n\t\t} catch {\n\t\t\t// A not-yet-created materialization directory still retains its lexical protected root.\n\t\t}\n\t}\n\treturn candidates.some((candidate) => {\n\t\tif (vault && (vaultPaths.includes(candidate) || materializedRoots.some((root) => isInside(root, candidate)))) {\n\t\t\treturn true;\n\t\t}\n\t\tconst fileName = basename(candidate);\n\t\treturn fileName === \".env\" || fileName.startsWith(\".env.\") || fileName.endsWith(\".env\");\n\t});\n}\n\nfunction shellCredentialRisk(\n\tcommand: string,\n\tcwd: string,\n\tvault?: SecretVault,\n): \"broad_search\" | \"credential_path\" | \"process_environment\" | undefined {\n\tconst shellTokens = tokenizeShellCommand(command);\n\tif (!shellTokens) return /\\b(?:grep|rg)\\b/iu.test(command) ? \"broad_search\" : undefined;\n\n\tconst assessInvocation = (\n\t\tinvocation: string[],\n\t\treadsPipe: boolean,\n\t): \"broad_search\" | \"credential_path\" | \"process_environment\" | undefined => {\n\t\tfor (let commandIndex = 0; commandIndex < invocation.length; commandIndex++) {\n\t\t\tconst toolName = (invocation[commandIndex].split(/[\\\\/]/u).at(-1) ?? \"\").toLowerCase().replace(/\\.exe$/u, \"\");\n\t\t\tif (toolName === \"jq\") {\n\t\t\t\tconst filter = jqFilterFromArgs(invocation.slice(commandIndex + 1));\n\t\t\t\tif (filter && jqFilterReadsProcessEnvironment(filter)) return \"process_environment\";\n\t\t\t}\n\t\t\tif (!SHELL_INSPECTION_COMMANDS.has(toolName)) continue;\n\t\t\tconst args = invocation.slice(commandIndex + 1);\n\t\t\tconst searchTool: ShellContentSearchTool | undefined =\n\t\t\t\ttoolName === \"rg\" || toolName === \"ripgrep\" ? \"rg\" : toolName === \"grep\" ? \"grep\" : undefined;\n\t\t\tif (searchTool) {\n\t\t\t\tconst scope = parseShellSearchInvocationScope(searchTool, args, readsPipe);\n\t\t\t\tif (scope.targets.some((target) => target !== \"-\" && isProtectedCredentialPath(target, cwd, vault))) {\n\t\t\t\t\treturn \"credential_path\";\n\t\t\t\t}\n\t\t\t\tconst hasSafeGlob =\n\t\t\t\t\tscope.positiveGlobs.length > 0 && scope.positiveGlobs.every((glob) => isCredentialSafeGlob(glob));\n\t\t\t\tconst hasOnlyExplicitFiles =\n\t\t\t\t\tscope.targets.length > 0 &&\n\t\t\t\t\tscope.targets.every((target) => target === \"-\" || isExistingRegularFile(target, cwd));\n\t\t\t\tif (!scope.metaOnly && !scope.readsStdin && !hasSafeGlob && !hasOnlyExplicitFiles) return \"broad_search\";\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tfor (const token of args) {\n\t\t\t\tif (!token || token.startsWith(\"-\") || token === \".\") continue;\n\t\t\t\tif (isProtectedCredentialPath(token, cwd, vault)) return \"credential_path\";\n\t\t\t}\n\t\t}\n\t\treturn undefined;\n\t};\n\n\tlet invocation: string[] = [];\n\tlet skipRedirectTarget = false;\n\tlet readsPipe = false;\n\tfor (const token of shellTokens) {\n\t\tif (token.kind === \"arg\") {\n\t\t\tif (skipRedirectTarget) skipRedirectTarget = false;\n\t\t\telse invocation.push(token.value);\n\t\t\tcontinue;\n\t\t}\n\t\tif (token.kind === \"redirect\") {\n\t\t\t// Descriptor duplication (`2>&1`) has no following path operand. Other\n\t\t\t// redirects do, and that target must never count as search scope.\n\t\t\tskipRedirectTarget = !/^\\d*[<>]&[\\d-]+$/u.test(token.value);\n\t\t\tcontinue;\n\t\t}\n\t\tconst risk = assessInvocation(invocation, readsPipe);\n\t\tif (risk) return risk;\n\t\tinvocation = [];\n\t\tskipRedirectTarget = false;\n\t\treadsPipe = token.kind === \"pipe\";\n\t}\n\treturn assessInvocation(invocation, readsPipe);\n}\n\nfunction jqFilterFromArgs(args: string[]): string | undefined {\n\tfor (let index = 0; index < args.length; index++) {\n\t\tconst token = args[index];\n\t\tif (token === \"--\") return args[index + 1];\n\t\tif (JQ_OPTIONS_WITH_TWO_OPERANDS.has(token)) {\n\t\t\tindex += 2;\n\t\t\tcontinue;\n\t\t}\n\t\tif (JQ_OPTIONS_WITH_ONE_OPERAND.has(token)) {\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (token.startsWith(\"-\")) continue;\n\t\treturn token;\n\t}\n\treturn undefined;\n}\n\nfunction jqFilterReadsProcessEnvironment(filter: string): boolean {\n\treturn /(?:^|[\\s|,(:;[])(?:env|\\$ENV)(?=$|[\\s|),.;[\\]}])/u.test(filter);\n}\n\nfunction isCredentialSafeGlob(glob: string): boolean {\n\tif (/(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(glob)) return false;\n\tconst filePattern = glob.replace(/\\\\/g, \"/\").split(\"/\").at(-1) ?? \"\";\n\tconst suffix = filePattern.match(/\\.([A-Za-z0-9_-]+)$/)?.[1]?.toLowerCase();\n\treturn suffix !== undefined && suffix !== \"env\";\n}\n\nfunction isExistingRegularFile(rawPath: string, cwd: string): boolean {\n\ttry {\n\t\treturn statSync(resolve(cwd, rawPath)).isFile();\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction pythonInspectsCredentialPath(code: string, cwd: string, vault?: SecretVault): boolean {\n\tif (!PYTHON_INSPECTION_RE.test(code)) return false;\n\tQUOTED_TEXT_RE.lastIndex = 0;\n\tfor (const match of code.matchAll(QUOTED_TEXT_RE)) {\n\t\tconst candidate = match[2]?.replace(/\\\\([\\\\\"'])/g, \"$1\");\n\t\tif (candidate && isProtectedCredentialPath(candidate, cwd, vault)) return true;\n\t}\n\treturn false;\n}\n\nfunction directPathFromArgs(args: unknown): string | undefined {\n\tif (!isRecord(args)) return undefined;\n\treturn typeof args.path === \"string\" ? args.path : undefined;\n}\n\n/** Stable model-facing refusal for direct inspection/mutation of credential material. */\nexport function credentialToolBlockReason(\n\ttoolName: string,\n\targs: unknown,\n\tcwd: string,\n\tvault?: SecretVault,\n): string | undefined {\n\tif (toolName === \"secret_store\" || !isRecord(args)) return undefined;\n\tif (DIRECT_PATH_TOOLS.has(toolName)) {\n\t\tconst path = directPathFromArgs(args);\n\t\tif (path && isProtectedCredentialPath(path, cwd, vault)) {\n\t\t\treturn \"Credential file access is model-blind. Use secret_store to edit or materialize the bound profile, then run the consuming application without inspecting the dotenv file.\";\n\t\t}\n\t}\n\tif (toolName === \"grep\") {\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tconst glob = typeof args.glob === \"string\" ? args.glob : undefined;\n\t\tif (\n\t\t\t(path && isProtectedCredentialPath(path, cwd, vault)) ||\n\t\t\t(glob && /(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(glob))\n\t\t) {\n\t\t\treturn \"Credential dotenv files are excluded from model-facing search. Use secret_store metadata instead.\";\n\t\t}\n\t\tif (!(path && isExistingRegularFile(path, cwd)) && !(glob && isCredentialSafeGlob(glob))) {\n\t\t\treturn \"Credential-safe grep requires one explicit regular file or a narrow non-dotenv file glob (for example *.ts). Refine the search instead of scanning a directory without a file filter.\";\n\t\t}\n\t}\n\tif (toolName === \"find\") {\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tconst pattern = typeof args.pattern === \"string\" ? args.pattern : undefined;\n\t\tif (\n\t\t\t(path && isProtectedCredentialPath(path, cwd, vault)) ||\n\t\t\t(pattern && /(?:^|[\\\\/])?\\.env(?:\\.|\\*|$)/i.test(pattern))\n\t\t) {\n\t\t\treturn \"Credential dotenv files are excluded from model-facing discovery. Use secret_store list instead.\";\n\t\t}\n\t}\n\tif (toolName === \"bash\" || toolName === \"powershell\" || toolName === \"run_process\") {\n\t\tconst command = typeof args.command === \"string\" ? args.command : \"\";\n\t\tconst shellRisk = shellCredentialRisk(command, cwd, vault);\n\t\tif (shellRisk === \"broad_search\") {\n\t\t\treturn \"Credential-safe shell search requires a narrow non-dotenv file glob (for example -g '*.ts') or one explicit regular file. Refine the rg/grep command before retrying.\";\n\t\t}\n\t\tif (shellRisk === \"process_environment\") {\n\t\t\treturn \"Direct jq projection of the process environment is blocked because it can expose credentials. Query bounded JSON inputs instead.\";\n\t\t}\n\t\tif (SHELL_SECRET_READ_RE.test(command) || shellRisk === \"credential_path\") {\n\t\t\treturn \"Direct shell inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming command normally.\";\n\t\t}\n\t}\n\tif (toolName === \"python\") {\n\t\tconst code = typeof args.code === \"string\" ? args.code : \"\";\n\t\tconst scriptPath = typeof args.scriptPath === \"string\" ? args.scriptPath : undefined;\n\t\tif (\n\t\t\tPYTHON_SECRET_READ_RE.test(code) ||\n\t\t\tpythonInspectsCredentialPath(code, cwd, vault) ||\n\t\t\t(scriptPath !== undefined && isProtectedCredentialPath(scriptPath, cwd, vault))\n\t\t) {\n\t\t\treturn \"Direct Python inspection of credential dotenv files is blocked. Use secret_store, then run the credential-consuming program normally.\";\n\t\t}\n\t}\n\treturn undefined;\n}\n\nfunction redactResult<T>(result: AgentToolResult<T>, vault?: SecretVault): AgentToolResult<T> {\n\tconst redact = (text: string) => (vault ? vault.redactSensitiveText(text) : redactKnownSecrets(text));\n\tconst budget = { nodes: 0 };\n\treturn {\n\t\t...result,\n\t\tcontent: result.content.map((block) => (block.type === \"text\" ? { ...block, text: redact(block.text) } : block)),\n\t\tdetails: redactStructuredDetails(result.details, redact, budget) as T,\n\t};\n}\n\nfunction redactStructuredDetails(\n\tvalue: unknown,\n\tredact: (text: string) => string,\n\tbudget: { nodes: number },\n\tdepth = 0,\n): unknown {\n\tif (typeof value === \"string\") return redact(value);\n\tif (value === null || typeof value !== \"object\") return value;\n\tbudget.nodes++;\n\tif (depth >= MAX_REDACTED_DETAIL_DEPTH || budget.nodes > MAX_REDACTED_DETAIL_NODES) {\n\t\treturn \"[DETAIL OMITTED AT CREDENTIAL BOUNDARY]\";\n\t}\n\tif (Array.isArray(value)) {\n\t\treturn value.map((entry) => redactStructuredDetails(entry, redact, budget, depth + 1));\n\t}\n\tlet prototype: object | null;\n\ttry {\n\t\tprototype = Object.getPrototypeOf(value);\n\t} catch {\n\t\treturn \"[UNREADABLE DETAIL OMITTED AT CREDENTIAL BOUNDARY]\";\n\t}\n\tif (prototype !== Object.prototype && prototype !== null) return value;\n\treturn Object.fromEntries(\n\t\tObject.entries(value).map(([key, entry]) => [key, redactStructuredDetails(entry, redact, budget, depth + 1)]),\n\t);\n}\n\n/** Apply the same path refusal and output redaction to foreground, extension, scout, and lane tools. */\nexport function wrapToolWithCredentialExposureGuard<TParameters extends TSchema, TDetails>(\n\ttool: AgentTool<TParameters, TDetails>,\n\tcwd: string,\n\tvault?: SecretVault,\n): AgentTool<TParameters, TDetails> {\n\treturn {\n\t\t...tool,\n\t\tasync execute(toolCallId, params, signal, onUpdate) {\n\t\t\tconst refusal = credentialToolBlockReason(tool.name, params, cwd, vault);\n\t\t\tif (refusal) throw new Error(refusal);\n\t\t\tconst safeUpdate = onUpdate\n\t\t\t\t? (partial: AgentToolResult<TDetails>) => {\n\t\t\t\t\t\tonUpdate(redactResult(partial, vault));\n\t\t\t\t\t}\n\t\t\t\t: undefined;\n\t\t\ttry {\n\t\t\t\treturn redactResult(await tool.execute(toolCallId, params, signal, safeUpdate), vault);\n\t\t\t} catch (error) {\n\t\t\t\tif (error instanceof Error) {\n\t\t\t\t\tthrow new Error(vault ? vault.redactSensitiveText(error.message) : redactKnownSecrets(error.message));\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Credential-safe tool execution failed without retaining raw error output.\");\n\t\t\t}\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAyB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACxC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD,4EAA4E;IAC5E,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;CACzB;AAoDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAkK3E"}
1
+ {"version":3,"file":"system-prompt.d.ts","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAyB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAEhE,MAAM,WAAW,wBAAwB;IACxC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,0DAA0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,qFAAqF;IACrF,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC5B,uCAAuC;IACvC,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,yBAAyB;IACzB,GAAG,EAAE,MAAM,CAAC;IACZ,sDAAsD;IACtD,YAAY,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD,4EAA4E;IAC5E,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjB,8CAA8C;IAC9C,UAAU,CAAC,EAAE,SAAS,EAAE,CAAC;CACzB;AAoDD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,wBAAwB,GAAG,MAAM,CAqK3E"}
@@ -137,6 +137,7 @@ export function buildSystemPrompt(options) {
137
137
  }
138
138
  if (hasBash || hasGrep || hasFind) {
139
139
  addGuideline("Keep searches bounded and purposeful: discover paths first, pass an explicit root and filters, prefer rg over broad find, and raise command timeouts only for a justified scoped search");
140
+ addGuideline("Use rg for text candidate filtering and jq for bounded JSON projection; parse only selected records natively for exact semantic verification, and avoid slurping full datasets or building large shell pipelines");
140
141
  }
141
142
  if (hasPython) {
142
143
  addGuideline("Prefer the python tool for bounded Python snippets and scripts when Python is clearer than shell pipelines; use read/edit/write for small exact source edits");
@@ -1 +1 @@
1
- {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { getExtensionDescription, getExtensionDisplayName } from \"./extension-metadata.ts\";\nimport type { Extension } from \"./extensions/types.ts\";\nimport { escapePromptXml } from \"./prompt-markup.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write, context_audit] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Eagerly loaded project/agent instruction files. */\n\tcontextFiles?: Array<{ path: string; content?: string }>;\n\t/** Discovered skills; startup prompt lists only lazy-loadable locations. */\n\tskills?: Skill[];\n\t/** Discovered extensions currently active. */\n\textensions?: Extension[];\n}\n\nconst PI_ADAPTATIVE_CORE_SECTION = `\n\nOPERATING POSTURE\n\n- Treat a clear outcome expressed in normal conversation as a goal; never require a slash command. Persist progress and evidence; resume after compaction until done or stopped.\n- Avoid scope creep; ask before expanding the goal.\n- Verify uncertainty from authoritative sources. Prefer simple proven solutions; strengthen architecture only for real ownership, lifecycle, performance, or failure needs.\n- Store durable facts in memory, specialization in skills, and behavior in source. Shard oversized memory into indexed topics; discard noise.\n- Choose autonomously. Delegate bounded work to lightweight subagents while the parent owns integration; workers execute their assignment.\n- Move work expected to exceed 15 seconds into managed background execution when available. Require event-driven completion, a bounded handoff, and owner notification; never poll.\n- Ask before credentials, destructive actions, or ungranted publication. Source-filter context and tool output; keep it bounded and evidence-focused; show file paths clearly.\n\nN+2 ARCHITECTURE\n\nApply these language-agnostic principles through direct facilities of the active language and runtime:\n\n1. Group Lifetimes: Put overlapping lifetimes in one bounded arena, pool, ring, chunk store, flat collection, or equivalent owner. Avoid per-item churn; recycle in batches.\n\n2. Valid Defaults: Give data, handles, states, and resources a safe zero/default state without hidden allocation. One system owns activation.\n\n3. Stubs and Boundaries: Internal lookups return benign stubs, sentinels, or defaults. Validate trust and external boundaries once; report failure explicitly.\n\n4. Flat Ownership: Prefer contiguous or chunked data, stable IDs, compact indexes, tables, buffers, and batches over pointer graphs, needless dispatch, fallbacks, or micro-wrappers.\n\n5. Linear Bounds: Never concatenate growing prefixes, prepend repeatedly, rescan consumed input, serialize unchanged history, or rebuild full state for incremental work. Keep bounded parts and materialize the needed window once.\n\nENGINEERING WORKFLOW\n\n- Map flow, lifetimes, boundaries, hot paths, and the authoritative owner; give each invariant and policy one mandatory path.\n- Baseline performance work with a focused regression; reject unproven latency, allocation, or retention costs.\n- Use Detect → Verify → Score → Gate: reproduce with a negative control, fix the lowest owner, then run focused and proportionate broader checks.\n- Scanner, fuzzer, log, static-analysis, and model findings remain candidates until reproduced. Never weaken tests or claim success with incomplete probes.`;\n\nfunction formatContextFilesForPrompt(contextFiles: Array<{ path: string; content?: string }>): string {\n\tif (contextFiles.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\"\\n\\n<project_context>\", \"\", \"Project-specific instructions and guidelines:\", \"\"];\n\n\tfor (const { path, content } of contextFiles) {\n\t\tlines.push(`<project_instructions path=\"${escapePromptXml(path)}\">`);\n\t\tlines.push(content ?? \"\");\n\t\tlines.push(\"</project_instructions>\", \"\");\n\t}\n\n\tlines.push(\"</project_context>\");\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Build the system prompt with tools, guidelines, and context.\n *\n * CACHE-STABILITY INVARIANT: providers treat the returned string as ONE prompt-cache block (a\n * single cache breakpoint covering the whole system prompt). The caller (SystemPromptBuilder /\n * AgentSession, see `_rebuildSystemPrompt` in agent-session.ts) rebuilds it only when the TOOL\n * SURFACE changes — never per turn. For a fixed `options` (fixed tool surface, cwd, context\n * files, skills, extensions), two calls on the SAME CALENDAR DAY must return byte-identical\n * output, because `date` below is deliberately truncated to Y-M-D granularity. Do NOT widen it\n * to a timestamp (HH:MM:SS) or otherwise fold in any per-turn-volatile field (turn counters,\n * elapsed time, random ids, etc.) — that would cache-bust this entire block on EVERY turn instead\n * of once per calendar day, defeating provider prompt caching (cost + latency regression on every\n * request). Pinned by test/system-prompt-stability.test.ts.\n */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = cwd;\n\tconst promptCwd = resolvedCwd.replace(/\\\\/g, \"/\");\n\n\t// Day-granularity only (see cache-stability invariant on buildSystemPrompt above): this must\n\t// stay stable across every call within a calendar day, not just within a single turn.\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\n\tconst activeTools = selectedTools || [\"read\", \"bash\", \"python\", \"edit\", \"write\"];\n\tconst visibleTools = activeTools.filter((name) => !!toolSnippets?.[name]);\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tprompt += PI_ADAPTATIVE_CORE_SECTION;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\tprompt += formatContextFilesForPrompt(contextFiles);\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Append extensions section\n\t\tconst extensions = options.extensions ?? [];\n\t\tif (extensions.length > 0) {\n\t\t\tprompt += formatExtensionsForPrompt(extensions, visibleTools);\n\t\t}\n\n\t\t// Add date and working directory last (day-granularity `date` only; see the\n\t\t// cache-stability invariant on buildSystemPrompt above — do not add a per-turn timestamp).\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = activeTools.includes(\"bash\");\n\tconst hasPython = activeTools.includes(\"python\");\n\tconst hasPowerShell = activeTools.includes(\"powershell\");\n\tconst hasGrep = activeTools.includes(\"grep\");\n\tconst hasFind = activeTools.includes(\"find\");\n\tconst hasLs = activeTools.includes(\"ls\");\n\tconst hasRead = activeTools.includes(\"read\");\n\tconst hasReadOnlyTools = hasRead || hasGrep || hasFind || hasLs;\n\n\t// File exploration guidelines\n\tif (hasPowerShell && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use powershell for shell commands on Windows; prefer rg for search and Get-ChildItem for listing\");\n\t} else if (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\tif (hasBash || hasGrep || hasFind) {\n\t\taddGuideline(\n\t\t\t\"Keep searches bounded and purposeful: discover paths first, pass an explicit root and filters, prefer rg over broad find, and raise command timeouts only for a justified scoped search\",\n\t\t);\n\t}\n\tif (hasPython) {\n\t\taddGuideline(\n\t\t\t\"Prefer the python tool for bounded Python snippets and scripts when Python is clearer than shell pipelines; use read/edit/write for small exact source edits\",\n\t\t);\n\t}\n\tif (hasReadOnlyTools) {\n\t\taddGuideline(\n\t\t\t\"Issue independent read-only tool calls together in one assistant turn to avoid unnecessary model round trips. Keep dependent calls, mutations, and stateful commands ordered\",\n\t\t);\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\tconst toolGuidelinesSection = guidelines.length > 0 ? `\\n\\nTOOL GUIDELINES\\n\\n${guidelines}` : \"\";\n\n\tlet prompt = `You are Pi-Adaptative, a self-evolving assistant. Autonomously complete and deliver the user’s goals and vision within granted authority. Preserve continuity across long sessions and compaction, and remain accountable for the integrated result.\n\nAvailable tools:\n${toolsList}\n\nAdditional custom tools, skills, extensions, profiles, and agents may be available depending on the active environment. Use only capabilities present in the active tool surface.${PI_ADAPTATIVE_CORE_SECTION}${toolGuidelinesSection}\n\nPI-ADAPTATIVE DOCUMENTATION\n\nOnly when asked about Pi-Adaptative, read the relevant files completely from:\n- Main documentation: ${readmePath}\n- Additional documentation: ${docsPath}\n- Examples: ${examplesPath}\n\nResolve \\`docs/...\\` and \\`examples/...\\` from those roots and follow relevant Markdown cross-references before implementing.`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\tprompt += formatContextFilesForPrompt(contextFiles);\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Append extensions section\n\tconst activeExtensions = options.extensions ?? [];\n\tif (activeExtensions.length > 0) {\n\t\tprompt += formatExtensionsForPrompt(activeExtensions, visibleTools);\n\t}\n\n\t// Add date and working directory last (day-granularity `date` only; see the\n\t// cache-stability invariant on buildSystemPrompt above — do not add a per-turn timestamp).\n\tprompt += `\\nCurrent date: ${date}`;\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n\nfunction formatExtensionsForPrompt(extensions: Extension[], visibleTools: string[]): string {\n\tif (extensions.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\"\\n\\nThe following extensions are currently loaded and active:\", \"\", \"<active_extensions>\"];\n\tlet added = 0;\n\n\tfor (const ext of extensions) {\n\t\tconst name = getExtensionDisplayName(ext.path);\n\t\tconst description = getExtensionDescription(ext.path);\n\n\t\tconst tools = Array.from(ext.tools.keys()).filter((t) => visibleTools.includes(t));\n\t\tconst commands = Array.from(ext.commands.keys());\n\n\t\t// Skip extension listing if it has no visible tools, commands, or description\n\t\tif (tools.length === 0 && commands.length === 0 && !description) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tlines.push(\" <extension>\");\n\t\tlines.push(` <name>${escapePromptXml(name)}</name>`);\n\t\tif (description) {\n\t\t\tlines.push(` <description>${escapePromptXml(description)}</description>`);\n\t\t}\n\t\tlines.push(` <path>${escapePromptXml(ext.path)}</path>`);\n\n\t\tif (tools.length > 0) {\n\t\t\tlines.push(` <registered_tools>${tools.map(escapePromptXml).join(\", \")}</registered_tools>`);\n\t\t}\n\t\tif (commands.length > 0) {\n\t\t\tlines.push(` <registered_commands>${commands.map(escapePromptXml).join(\", \")}</registered_commands>`);\n\t\t}\n\t\tlines.push(\" </extension>\");\n\t\tadded++;\n\t}\n\n\tif (added === 0) {\n\t\treturn \"\";\n\t}\n\n\tlines.push(\"</active_extensions>\");\n\treturn lines.join(\"\\n\");\n}\n"]}
1
+ {"version":3,"file":"system-prompt.js","sourceRoot":"","sources":["../../src/core/system-prompt.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * System prompt construction and project context loading\n */\n\nimport { getDocsPath, getExamplesPath, getReadmePath } from \"../config.ts\";\nimport { getExtensionDescription, getExtensionDisplayName } from \"./extension-metadata.ts\";\nimport type { Extension } from \"./extensions/types.ts\";\nimport { escapePromptXml } from \"./prompt-markup.ts\";\nimport { formatSkillsForPrompt, type Skill } from \"./skills.ts\";\n\nexport interface BuildSystemPromptOptions {\n\t/** Custom system prompt (replaces default). */\n\tcustomPrompt?: string;\n\t/** Tools to include in prompt. Default: [read, bash, edit, write, context_audit] */\n\tselectedTools?: string[];\n\t/** Optional one-line tool snippets keyed by tool name. */\n\ttoolSnippets?: Record<string, string>;\n\t/** Additional guideline bullets appended to the default system prompt guidelines. */\n\tpromptGuidelines?: string[];\n\t/** Text to append to system prompt. */\n\tappendSystemPrompt?: string;\n\t/** Working directory. */\n\tcwd: string;\n\t/** Eagerly loaded project/agent instruction files. */\n\tcontextFiles?: Array<{ path: string; content?: string }>;\n\t/** Discovered skills; startup prompt lists only lazy-loadable locations. */\n\tskills?: Skill[];\n\t/** Discovered extensions currently active. */\n\textensions?: Extension[];\n}\n\nconst PI_ADAPTATIVE_CORE_SECTION = `\n\nOPERATING POSTURE\n\n- Treat a clear outcome expressed in normal conversation as a goal; never require a slash command. Persist progress and evidence; resume after compaction until done or stopped.\n- Avoid scope creep; ask before expanding the goal.\n- Verify uncertainty from authoritative sources. Prefer simple proven solutions; strengthen architecture only for real ownership, lifecycle, performance, or failure needs.\n- Store durable facts in memory, specialization in skills, and behavior in source. Shard oversized memory into indexed topics; discard noise.\n- Choose autonomously. Delegate bounded work to lightweight subagents while the parent owns integration; workers execute their assignment.\n- Move work expected to exceed 15 seconds into managed background execution when available. Require event-driven completion, a bounded handoff, and owner notification; never poll.\n- Ask before credentials, destructive actions, or ungranted publication. Source-filter context and tool output; keep it bounded and evidence-focused; show file paths clearly.\n\nN+2 ARCHITECTURE\n\nApply these language-agnostic principles through direct facilities of the active language and runtime:\n\n1. Group Lifetimes: Put overlapping lifetimes in one bounded arena, pool, ring, chunk store, flat collection, or equivalent owner. Avoid per-item churn; recycle in batches.\n\n2. Valid Defaults: Give data, handles, states, and resources a safe zero/default state without hidden allocation. One system owns activation.\n\n3. Stubs and Boundaries: Internal lookups return benign stubs, sentinels, or defaults. Validate trust and external boundaries once; report failure explicitly.\n\n4. Flat Ownership: Prefer contiguous or chunked data, stable IDs, compact indexes, tables, buffers, and batches over pointer graphs, needless dispatch, fallbacks, or micro-wrappers.\n\n5. Linear Bounds: Never concatenate growing prefixes, prepend repeatedly, rescan consumed input, serialize unchanged history, or rebuild full state for incremental work. Keep bounded parts and materialize the needed window once.\n\nENGINEERING WORKFLOW\n\n- Map flow, lifetimes, boundaries, hot paths, and the authoritative owner; give each invariant and policy one mandatory path.\n- Baseline performance work with a focused regression; reject unproven latency, allocation, or retention costs.\n- Use Detect → Verify → Score → Gate: reproduce with a negative control, fix the lowest owner, then run focused and proportionate broader checks.\n- Scanner, fuzzer, log, static-analysis, and model findings remain candidates until reproduced. Never weaken tests or claim success with incomplete probes.`;\n\nfunction formatContextFilesForPrompt(contextFiles: Array<{ path: string; content?: string }>): string {\n\tif (contextFiles.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\"\\n\\n<project_context>\", \"\", \"Project-specific instructions and guidelines:\", \"\"];\n\n\tfor (const { path, content } of contextFiles) {\n\t\tlines.push(`<project_instructions path=\"${escapePromptXml(path)}\">`);\n\t\tlines.push(content ?? \"\");\n\t\tlines.push(\"</project_instructions>\", \"\");\n\t}\n\n\tlines.push(\"</project_context>\");\n\treturn lines.join(\"\\n\");\n}\n\n/**\n * Build the system prompt with tools, guidelines, and context.\n *\n * CACHE-STABILITY INVARIANT: providers treat the returned string as ONE prompt-cache block (a\n * single cache breakpoint covering the whole system prompt). The caller (SystemPromptBuilder /\n * AgentSession, see `_rebuildSystemPrompt` in agent-session.ts) rebuilds it only when the TOOL\n * SURFACE changes — never per turn. For a fixed `options` (fixed tool surface, cwd, context\n * files, skills, extensions), two calls on the SAME CALENDAR DAY must return byte-identical\n * output, because `date` below is deliberately truncated to Y-M-D granularity. Do NOT widen it\n * to a timestamp (HH:MM:SS) or otherwise fold in any per-turn-volatile field (turn counters,\n * elapsed time, random ids, etc.) — that would cache-bust this entire block on EVERY turn instead\n * of once per calendar day, defeating provider prompt caching (cost + latency regression on every\n * request). Pinned by test/system-prompt-stability.test.ts.\n */\nexport function buildSystemPrompt(options: BuildSystemPromptOptions): string {\n\tconst {\n\t\tcustomPrompt,\n\t\tselectedTools,\n\t\ttoolSnippets,\n\t\tpromptGuidelines,\n\t\tappendSystemPrompt,\n\t\tcwd,\n\t\tcontextFiles: providedContextFiles,\n\t\tskills: providedSkills,\n\t} = options;\n\tconst resolvedCwd = cwd;\n\tconst promptCwd = resolvedCwd.replace(/\\\\/g, \"/\");\n\n\t// Day-granularity only (see cache-stability invariant on buildSystemPrompt above): this must\n\t// stay stable across every call within a calendar day, not just within a single turn.\n\tconst now = new Date();\n\tconst year = now.getFullYear();\n\tconst month = String(now.getMonth() + 1).padStart(2, \"0\");\n\tconst day = String(now.getDate()).padStart(2, \"0\");\n\tconst date = `${year}-${month}-${day}`;\n\n\tconst appendSection = appendSystemPrompt ? `\\n\\n${appendSystemPrompt}` : \"\";\n\n\tconst contextFiles = providedContextFiles ?? [];\n\tconst skills = providedSkills ?? [];\n\n\tconst activeTools = selectedTools || [\"read\", \"bash\", \"python\", \"edit\", \"write\"];\n\tconst visibleTools = activeTools.filter((name) => !!toolSnippets?.[name]);\n\n\tif (customPrompt) {\n\t\tlet prompt = customPrompt;\n\n\t\tprompt += PI_ADAPTATIVE_CORE_SECTION;\n\n\t\tif (appendSection) {\n\t\t\tprompt += appendSection;\n\t\t}\n\n\t\tprompt += formatContextFilesForPrompt(contextFiles);\n\n\t\t// Append skills section (only if read tool is available)\n\t\tconst customPromptHasRead = !selectedTools || selectedTools.includes(\"read\");\n\t\tif (customPromptHasRead && skills.length > 0) {\n\t\t\tprompt += formatSkillsForPrompt(skills);\n\t\t}\n\n\t\t// Append extensions section\n\t\tconst extensions = options.extensions ?? [];\n\t\tif (extensions.length > 0) {\n\t\t\tprompt += formatExtensionsForPrompt(extensions, visibleTools);\n\t\t}\n\n\t\t// Add date and working directory last (day-granularity `date` only; see the\n\t\t// cache-stability invariant on buildSystemPrompt above — do not add a per-turn timestamp).\n\t\tprompt += `\\nCurrent date: ${date}`;\n\t\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\t\treturn prompt;\n\t}\n\n\t// Get absolute paths to documentation and examples\n\tconst readmePath = getReadmePath();\n\tconst docsPath = getDocsPath();\n\tconst examplesPath = getExamplesPath();\n\n\t// Build tools list based on selected tools.\n\t// A tool appears in Available tools only when the caller provides a one-line snippet.\n\tconst toolsList =\n\t\tvisibleTools.length > 0 ? visibleTools.map((name) => `- ${name}: ${toolSnippets![name]}`).join(\"\\n\") : \"(none)\";\n\n\t// Build guidelines based on which tools are actually available\n\tconst guidelinesList: string[] = [];\n\tconst guidelinesSet = new Set<string>();\n\tconst addGuideline = (guideline: string): void => {\n\t\tif (guidelinesSet.has(guideline)) {\n\t\t\treturn;\n\t\t}\n\t\tguidelinesSet.add(guideline);\n\t\tguidelinesList.push(guideline);\n\t};\n\n\tconst hasBash = activeTools.includes(\"bash\");\n\tconst hasPython = activeTools.includes(\"python\");\n\tconst hasPowerShell = activeTools.includes(\"powershell\");\n\tconst hasGrep = activeTools.includes(\"grep\");\n\tconst hasFind = activeTools.includes(\"find\");\n\tconst hasLs = activeTools.includes(\"ls\");\n\tconst hasRead = activeTools.includes(\"read\");\n\tconst hasReadOnlyTools = hasRead || hasGrep || hasFind || hasLs;\n\n\t// File exploration guidelines\n\tif (hasPowerShell && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use powershell for shell commands on Windows; prefer rg for search and Get-ChildItem for listing\");\n\t} else if (hasBash && !hasGrep && !hasFind && !hasLs) {\n\t\taddGuideline(\"Use bash for file operations like ls, rg, find\");\n\t}\n\tif (hasBash || hasGrep || hasFind) {\n\t\taddGuideline(\n\t\t\t\"Keep searches bounded and purposeful: discover paths first, pass an explicit root and filters, prefer rg over broad find, and raise command timeouts only for a justified scoped search\",\n\t\t);\n\t\taddGuideline(\n\t\t\t\"Use rg for text candidate filtering and jq for bounded JSON projection; parse only selected records natively for exact semantic verification, and avoid slurping full datasets or building large shell pipelines\",\n\t\t);\n\t}\n\tif (hasPython) {\n\t\taddGuideline(\n\t\t\t\"Prefer the python tool for bounded Python snippets and scripts when Python is clearer than shell pipelines; use read/edit/write for small exact source edits\",\n\t\t);\n\t}\n\tif (hasReadOnlyTools) {\n\t\taddGuideline(\n\t\t\t\"Issue independent read-only tool calls together in one assistant turn to avoid unnecessary model round trips. Keep dependent calls, mutations, and stateful commands ordered\",\n\t\t);\n\t}\n\n\tfor (const guideline of promptGuidelines ?? []) {\n\t\tconst normalized = guideline.trim();\n\t\tif (normalized.length > 0) {\n\t\t\taddGuideline(normalized);\n\t\t}\n\t}\n\n\tconst guidelines = guidelinesList.map((g) => `- ${g}`).join(\"\\n\");\n\tconst toolGuidelinesSection = guidelines.length > 0 ? `\\n\\nTOOL GUIDELINES\\n\\n${guidelines}` : \"\";\n\n\tlet prompt = `You are Pi-Adaptative, a self-evolving assistant. Autonomously complete and deliver the user’s goals and vision within granted authority. Preserve continuity across long sessions and compaction, and remain accountable for the integrated result.\n\nAvailable tools:\n${toolsList}\n\nAdditional custom tools, skills, extensions, profiles, and agents may be available depending on the active environment. Use only capabilities present in the active tool surface.${PI_ADAPTATIVE_CORE_SECTION}${toolGuidelinesSection}\n\nPI-ADAPTATIVE DOCUMENTATION\n\nOnly when asked about Pi-Adaptative, read the relevant files completely from:\n- Main documentation: ${readmePath}\n- Additional documentation: ${docsPath}\n- Examples: ${examplesPath}\n\nResolve \\`docs/...\\` and \\`examples/...\\` from those roots and follow relevant Markdown cross-references before implementing.`;\n\n\tif (appendSection) {\n\t\tprompt += appendSection;\n\t}\n\n\tprompt += formatContextFilesForPrompt(contextFiles);\n\n\t// Append skills section (only if read tool is available)\n\tif (hasRead && skills.length > 0) {\n\t\tprompt += formatSkillsForPrompt(skills);\n\t}\n\n\t// Append extensions section\n\tconst activeExtensions = options.extensions ?? [];\n\tif (activeExtensions.length > 0) {\n\t\tprompt += formatExtensionsForPrompt(activeExtensions, visibleTools);\n\t}\n\n\t// Add date and working directory last (day-granularity `date` only; see the\n\t// cache-stability invariant on buildSystemPrompt above — do not add a per-turn timestamp).\n\tprompt += `\\nCurrent date: ${date}`;\n\tprompt += `\\nCurrent working directory: ${promptCwd}`;\n\n\treturn prompt;\n}\n\nfunction formatExtensionsForPrompt(extensions: Extension[], visibleTools: string[]): string {\n\tif (extensions.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\"\\n\\nThe following extensions are currently loaded and active:\", \"\", \"<active_extensions>\"];\n\tlet added = 0;\n\n\tfor (const ext of extensions) {\n\t\tconst name = getExtensionDisplayName(ext.path);\n\t\tconst description = getExtensionDescription(ext.path);\n\n\t\tconst tools = Array.from(ext.tools.keys()).filter((t) => visibleTools.includes(t));\n\t\tconst commands = Array.from(ext.commands.keys());\n\n\t\t// Skip extension listing if it has no visible tools, commands, or description\n\t\tif (tools.length === 0 && commands.length === 0 && !description) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tlines.push(\" <extension>\");\n\t\tlines.push(` <name>${escapePromptXml(name)}</name>`);\n\t\tif (description) {\n\t\t\tlines.push(` <description>${escapePromptXml(description)}</description>`);\n\t\t}\n\t\tlines.push(` <path>${escapePromptXml(ext.path)}</path>`);\n\n\t\tif (tools.length > 0) {\n\t\t\tlines.push(` <registered_tools>${tools.map(escapePromptXml).join(\", \")}</registered_tools>`);\n\t\t}\n\t\tif (commands.length > 0) {\n\t\t\tlines.push(` <registered_commands>${commands.map(escapePromptXml).join(\", \")}</registered_commands>`);\n\t\t}\n\t\tlines.push(\" </extension>\");\n\t\tadded++;\n\t}\n\n\tif (added === 0) {\n\t\treturn \"\";\n\t}\n\n\tlines.push(\"</active_extensions>\");\n\treturn lines.join(\"\\n\");\n}\n"]}
@@ -368,9 +368,9 @@ export class InteractiveMode {
368
368
  this.registerSignalHandlers();
369
369
  // Load changelog (only show new entries, skip for resumed sessions)
370
370
  this.changelogMarkdown = this.getChangelogForDisplay();
371
- // Ensure fd and rg are available (downloads if missing, adds to PATH via getBinDir)
372
- // Both are needed: fd for autocomplete, rg for grep tool and bash commands
373
- const [fdPath] = await Promise.all([ensureTool("fd"), ensureTool("rg")]);
371
+ // Ensure the shared discovery/projection binaries are available and on PATH.
372
+ // fd feeds autocomplete; rg and jq keep source/JSON filtering outside V8.
373
+ const [fdPath] = await Promise.all([ensureTool("fd"), ensureTool("rg"), ensureTool("jq")]);
374
374
  this.fdPath = fdPath;
375
375
  if (this.session.scopedModels.length > 0 && (this.options.verbose || !this.settingsManager.getQuietStartup())) {
376
376
  const modelList = this.session.scopedModels