@oh-my-pi/pi-coding-agent 17.2.11 → 17.2.12

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 (152) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/{CHANGELOG-d9xenpn9.md → CHANGELOG-k9ghy5sn.md} +13 -0
  3. package/dist/cli.js +10795 -10791
  4. package/dist/types/advisor/runtime.d.ts +1 -1
  5. package/dist/types/config/custom-models.d.ts +31 -0
  6. package/dist/types/config/model-config-values.d.ts +19 -0
  7. package/dist/types/config/model-patch.d.ts +93 -0
  8. package/dist/types/config/model-provider-discovery.d.ts +51 -0
  9. package/dist/types/config/model-registry.d.ts +5 -52
  10. package/dist/types/config/settings.d.ts +5 -3
  11. package/dist/types/debug/raw-sse-buffer.d.ts +9 -0
  12. package/dist/types/discovery/agent-plugin-format.d.ts +6 -13
  13. package/dist/types/discovery/contained-path.d.ts +2 -3
  14. package/dist/types/eval/executor-base.d.ts +8 -2
  15. package/dist/types/eval/kernel-session-registry.d.ts +60 -0
  16. package/dist/types/export/share.d.ts +1 -1
  17. package/dist/types/lsp/diagnostics.d.ts +96 -0
  18. package/dist/types/lsp/index.d.ts +7 -128
  19. package/dist/types/lsp/servers.d.ts +72 -0
  20. package/dist/types/lsp/tool.d.ts +42 -0
  21. package/dist/types/lsp/workspace-diagnostics.d.ts +12 -0
  22. package/dist/types/lsp/writethrough.d.ts +33 -0
  23. package/dist/types/mcp/transports/header-policy.d.ts +2 -1
  24. package/dist/types/modes/components/agent-hub-projection.d.ts +2 -7
  25. package/dist/types/modes/components/agent-hub-renderer.d.ts +0 -7
  26. package/dist/types/modes/theme/color.d.ts +19 -0
  27. package/dist/types/modes/theme/loader.d.ts +19 -0
  28. package/dist/types/modes/theme/schema.d.ts +175 -0
  29. package/dist/types/modes/theme/symbols.d.ts +28 -0
  30. package/dist/types/modes/theme/theme-class.d.ts +244 -0
  31. package/dist/types/modes/theme/theme.d.ts +9 -280
  32. package/dist/types/modes/theme/tui-adapters.d.ts +13 -0
  33. package/dist/types/registry/agent-registry.d.ts +1 -3
  34. package/dist/types/secrets/index.d.ts +3 -1
  35. package/dist/types/secrets/message-transform.d.ts +40 -0
  36. package/dist/types/secrets/obfuscator.d.ts +0 -108
  37. package/dist/types/secrets/placeholder-scan.d.ts +95 -0
  38. package/dist/types/secrets/placeholder.d.ts +94 -0
  39. package/dist/types/secrets/replacement.d.ts +82 -0
  40. package/dist/types/session/agent-session-types.d.ts +6 -0
  41. package/dist/types/session/agent-session.d.ts +1 -1
  42. package/dist/types/session/session-handoff.d.ts +3 -3
  43. package/dist/types/session/session-manager.d.ts +32 -0
  44. package/dist/types/session/session-provider-boundary.d.ts +1 -1
  45. package/dist/types/session/turn-recovery.d.ts +2 -2
  46. package/dist/types/slash-commands/builtin-collaboration.d.ts +2 -0
  47. package/dist/types/slash-commands/builtin-completions.d.ts +36 -0
  48. package/dist/types/slash-commands/builtin-control.d.ts +2 -0
  49. package/dist/types/slash-commands/builtin-lifecycle.d.ts +3 -0
  50. package/dist/types/slash-commands/builtin-marketplace.d.ts +11 -0
  51. package/dist/types/slash-commands/builtin-modes.d.ts +5 -0
  52. package/dist/types/slash-commands/builtin-registry.d.ts +1 -1
  53. package/dist/types/slash-commands/builtin-session.d.ts +2 -0
  54. package/dist/types/tools/gh-common.d.ts +69 -0
  55. package/dist/types/tools/gh-pr-checkout.d.ts +84 -0
  56. package/dist/types/tools/gh-pr-diff.d.ts +102 -0
  57. package/dist/types/tools/gh-run-watch.d.ts +78 -0
  58. package/dist/types/tools/gh-search.d.ts +61 -0
  59. package/dist/types/tools/gh-types.d.ts +340 -0
  60. package/dist/types/tools/gh-view.d.ts +88 -0
  61. package/dist/types/tools/gh.d.ts +4 -201
  62. package/dist/types/tools/read-archive.d.ts +16 -0
  63. package/dist/types/tools/read-format.d.ts +104 -0
  64. package/dist/types/tools/read-path-resolution.d.ts +19 -0
  65. package/dist/types/tools/read-pdf-images.d.ts +12 -0
  66. package/dist/types/tools/read-renderer.d.ts +24 -0
  67. package/dist/types/tools/read-selector.d.ts +27 -0
  68. package/dist/types/tools/read-sqlite.d.ts +16 -0
  69. package/dist/types/tools/read-summary.d.ts +19 -0
  70. package/dist/types/tools/read.d.ts +1 -23
  71. package/dist/types/tools/shell-tokenize.d.ts +2 -1
  72. package/dist/types/utils/changelog.d.ts +0 -5
  73. package/package.json +13 -13
  74. package/src/advisor/runtime.ts +12 -7
  75. package/src/config/custom-models.ts +188 -0
  76. package/src/config/model-config-values.ts +128 -0
  77. package/src/config/model-patch.ts +252 -0
  78. package/src/config/model-provider-discovery.ts +132 -0
  79. package/src/config/model-registry.ts +64 -704
  80. package/src/config/settings.ts +7 -3
  81. package/src/debug/raw-sse-buffer.ts +20 -0
  82. package/src/discovery/agent-plugin-format.ts +7 -7
  83. package/src/discovery/contained-path.ts +2 -5
  84. package/src/edit/hashline/diff.ts +5 -1
  85. package/src/eval/executor-base.ts +39 -6
  86. package/src/eval/jl/executor.ts +82 -371
  87. package/src/eval/kernel-session-registry.ts +398 -0
  88. package/src/eval/py/executor.ts +53 -261
  89. package/src/eval/rb/executor.ts +36 -279
  90. package/src/export/share.ts +2 -1
  91. package/src/lsp/diagnostics.ts +516 -0
  92. package/src/lsp/index.ts +20 -2819
  93. package/src/lsp/servers.ts +296 -0
  94. package/src/lsp/tool.ts +1352 -0
  95. package/src/lsp/workspace-diagnostics.ts +170 -0
  96. package/src/lsp/writethrough.ts +561 -0
  97. package/src/mcp/transports/header-policy.ts +1 -1
  98. package/src/modes/components/agent-hub-projection.ts +2 -2
  99. package/src/modes/components/agent-hub-renderer.ts +3 -7
  100. package/src/modes/controllers/command-controller.ts +4 -1
  101. package/src/modes/theme/color.ts +133 -0
  102. package/src/modes/theme/loader.ts +178 -0
  103. package/src/modes/theme/schema.ts +263 -0
  104. package/src/modes/theme/symbols.ts +1000 -0
  105. package/src/modes/theme/theme-class.ts +611 -0
  106. package/src/modes/theme/theme.ts +27 -2453
  107. package/src/modes/theme/tui-adapters.ts +279 -0
  108. package/src/registry/agent-registry.ts +2 -2
  109. package/src/secrets/index.ts +6 -12
  110. package/src/secrets/message-transform.ts +287 -0
  111. package/src/secrets/obfuscator.ts +39 -1303
  112. package/src/secrets/placeholder-scan.ts +506 -0
  113. package/src/secrets/placeholder.ts +309 -0
  114. package/src/secrets/replacement.ts +216 -0
  115. package/src/session/agent-session-types.ts +6 -0
  116. package/src/session/agent-session.ts +113 -7
  117. package/src/session/indexed-session-storage.ts +7 -2
  118. package/src/session/session-advisors.ts +32 -34
  119. package/src/session/session-handoff.ts +39 -20
  120. package/src/session/session-manager.ts +67 -3
  121. package/src/session/session-provider-boundary.ts +3 -6
  122. package/src/session/turn-recovery.ts +21 -12
  123. package/src/slash-commands/builtin-collaboration.ts +504 -0
  124. package/src/slash-commands/builtin-completions.ts +291 -0
  125. package/src/slash-commands/builtin-control.ts +78 -0
  126. package/src/slash-commands/builtin-lifecycle.ts +506 -0
  127. package/src/slash-commands/builtin-marketplace.ts +567 -0
  128. package/src/slash-commands/builtin-modes.ts +518 -0
  129. package/src/slash-commands/builtin-registry.ts +21 -3000
  130. package/src/slash-commands/builtin-session.ts +592 -0
  131. package/src/task/executor.ts +17 -14
  132. package/src/tools/gh-common.ts +288 -0
  133. package/src/tools/gh-pr-checkout.ts +679 -0
  134. package/src/tools/gh-pr-diff.ts +473 -0
  135. package/src/tools/gh-run-watch.ts +1015 -0
  136. package/src/tools/gh-search.ts +500 -0
  137. package/src/tools/gh-types.ts +379 -0
  138. package/src/tools/gh-view.ts +612 -0
  139. package/src/tools/gh.ts +109 -3821
  140. package/src/tools/read-archive.ts +209 -0
  141. package/src/tools/read-format.ts +593 -0
  142. package/src/tools/read-path-resolution.ts +36 -0
  143. package/src/tools/read-pdf-images.ts +250 -0
  144. package/src/tools/read-renderer.ts +289 -0
  145. package/src/tools/read-selector.ts +84 -0
  146. package/src/tools/read-sqlite.ts +215 -0
  147. package/src/tools/read-summary.ts +199 -0
  148. package/src/tools/read.ts +77 -1820
  149. package/src/tools/shell-tokenize.ts +1 -1
  150. package/src/utils/changelog.ts +1 -1
  151. package/src/utils/title-generator.ts +3 -1
  152. package/src/web/search/providers/zai.ts +12 -3
@@ -442,11 +442,15 @@ export class Settings {
442
442
  }
443
443
 
444
444
  /**
445
- * Create an isolated instance for testing.
446
- * Does not affect the global singleton.
445
+ * Create an in-memory settings instance without affecting the global singleton.
446
+ * A supplied storage handle remains shared for runtime data while setting overrides stay non-persistent.
447
447
  */
448
- static isolated(overrides: Partial<Record<SettingPath, unknown>> = {}): Settings {
448
+ static isolated(
449
+ overrides: Partial<Record<SettingPath, unknown>> = {},
450
+ options: { storage?: AgentStorage | null } = {},
451
+ ): Settings {
449
452
  const instance = new Settings({ inMemory: true, overrides });
453
+ instance.#storage = options.storage ?? null;
450
454
  instance.#rebuildMerged();
451
455
  return instance;
452
456
  }
@@ -335,6 +335,26 @@ export class RawSseDebugBuffer {
335
335
  return body.length > 0 ? `${dropped}${body}` : dropped;
336
336
  }
337
337
 
338
+ /**
339
+ * Drop every retained record and reset accounting. Called from
340
+ * {@link AgentSession} teardown so a disposed (e.g. parked subagent) session
341
+ * stops pinning captured wire frames — each trimmed record holds a
342
+ * `slice()` of its parent SSE frame, which under JSC keeps the whole
343
+ * multi-MB frame alive. Notifies subscribers so a live debug viewer redraws
344
+ * empty.
345
+ */
346
+ clear(): void {
347
+ this.#records = [];
348
+ this.#recordChars = [];
349
+ this.#head = 0;
350
+ this.#totalChars = 0;
351
+ this.#droppedRecords = 0;
352
+ this.#droppedChars = 0;
353
+ this.#totalEvents = 0;
354
+ this.#lastUpdatedAt = undefined;
355
+ this.#emit();
356
+ }
357
+
338
358
  #append(record: RawSseDebugRecord, chars: number): void {
339
359
  this.#records.push(record);
340
360
  this.#recordChars.push(chars);
@@ -74,13 +74,13 @@ export interface AgentPluginManifest {
74
74
  * - `invalid` — the document targets Agent Plugins but violates the closed schema
75
75
  * fatally; the plugin must be rejected and none of its components loaded (spec §5.2).
76
76
  */
77
- export type AgentPluginManifestResult =
77
+ type AgentPluginManifestResult =
78
78
  | { status: "none" }
79
79
  | { status: "valid"; manifest: AgentPluginManifest; warnings: string[] }
80
80
  | { status: "invalid"; reason: string };
81
81
 
82
82
  /** Enforce the plugin `name` constraints from spec §5.5. */
83
- export function isValidAgentPluginName(name: string): boolean {
83
+ function isValidAgentPluginName(name: string): boolean {
84
84
  if (name.length < 1 || name.length > 64) return false;
85
85
  if (!/^[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?$/.test(name)) return false;
86
86
  return !name.includes("--") && !name.includes("..");
@@ -240,14 +240,14 @@ export function parseAgentPluginManifest(raw: string): AgentPluginManifestResult
240
240
  * (spec §9.2). Single non-recursive pass; replacement text is never rescanned,
241
241
  * and no other placeholder or environment-variable expansion is performed.
242
242
  */
243
- export function expandAgentPluginPlaceholders(value: string, pluginRoot: string, pluginData: string): string {
243
+ function expandAgentPluginPlaceholders(value: string, pluginRoot: string, pluginData: string): string {
244
244
  return value.replace(/\$\{PLUGIN_(ROOT|DATA)\}/g, (_match, which: string) =>
245
245
  which === "ROOT" ? pluginRoot : pluginData,
246
246
  );
247
247
  }
248
248
 
249
249
  /** A validated `mcp.json` server entry, resolved to launch-ready values. */
250
- export interface AgentPluginMcpServer {
250
+ interface AgentPluginMcpServer {
251
251
  name: string;
252
252
  transport: "stdio" | "http" | "sse";
253
253
  /** Absolute path for `./`-relative commands; bare executable token otherwise. */
@@ -268,11 +268,11 @@ export interface AgentPluginMcpServer {
268
268
  * - `ok` — the document is valid; individually invalid server entries are
269
269
  * skipped with a warning (spec §7.2.2 rule 3).
270
270
  */
271
- export type AgentPluginMcpResult =
271
+ type AgentPluginMcpResult =
272
272
  | { status: "disabled"; reason: string }
273
273
  | { status: "ok"; servers: AgentPluginMcpServer[]; warnings: string[] };
274
274
 
275
- export interface AgentPluginMcpOptions {
275
+ interface AgentPluginMcpOptions {
276
276
  /** Filesystem-resolved plugin root. */
277
277
  pluginRoot: string;
278
278
  /** Client-managed persistent data directory for this plugin (spec §9.1). */
@@ -488,7 +488,7 @@ export async function parseAgentPluginMcp(raw: string, options: AgentPluginMcpOp
488
488
  * - `invalid` — the root claims Agent Plugins conformance but its manifest is
489
489
  * fatally invalid; no component may be discovered or executed (spec §11.3).
490
490
  */
491
- export type AgentPluginRootStatus =
491
+ type AgentPluginRootStatus =
492
492
  | { kind: "none" }
493
493
  | { kind: "standard"; manifest: AgentPluginManifest; warnings: string[]; realRoot: string }
494
494
  | { kind: "invalid"; reason: string };
@@ -14,7 +14,7 @@ import * as fs from "node:fs";
14
14
  import * as path from "node:path";
15
15
 
16
16
  /** Lexical containment: `target` is `base` itself or a descendant of it. */
17
- export function isContained(base: string, target: string): boolean {
17
+ function isContained(base: string, target: string): boolean {
18
18
  const relative = path.relative(base, target);
19
19
  return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
20
20
  }
@@ -29,10 +29,7 @@ export async function realpathIfExists(p: string): Promise<string | null> {
29
29
  }
30
30
 
31
31
  /** Outcome of resolving a fixed package path without reading it. */
32
- export type ContainedPathResolution =
33
- | { status: "missing" }
34
- | { status: "outside" }
35
- | { status: "ok"; realPath: string };
32
+ type ContainedPathResolution = { status: "missing" } | { status: "outside" } | { status: "ok"; realPath: string };
36
33
 
37
34
  /**
38
35
  * Resolve a fixed package path WITHOUT reading it: symlinks and equivalent
@@ -225,7 +225,11 @@ function applyPreviewEdits(args: {
225
225
  // previews stay lenient — a mid-typed op transiently violating sequencing
226
226
  // must not flash an error frame.
227
227
  if (!options.streaming) validateClipboardSequence(resolved, clipboard);
228
- const applyOptions = { clipboard, ...(options.streaming ? { onEmptyPaste: "drop" as const } : {}) };
228
+ const applyOptions = {
229
+ clipboard,
230
+ path: absolutePath,
231
+ ...(options.streaming ? { onEmptyPaste: "drop" as const } : {}),
232
+ };
229
233
  if (options.skipHashValidation || expected === undefined || liveMatches) {
230
234
  return applyEdits(normalized, resolved, applyOptions);
231
235
  }
@@ -116,9 +116,13 @@ export async function waitForPromiseWithCancellation<T>(
116
116
  promise: Promise<T>,
117
117
  options: { signal?: AbortSignal; deadlineMs?: number },
118
118
  cancelledErrorClass: CancelledErrorClass,
119
+ timedOutResolver?: (error: unknown, signal?: AbortSignal) => boolean,
119
120
  ): Promise<T> {
120
121
  if (options.signal?.aborted) {
121
- throw new cancelledErrorClass(isTimedOutCancellation(options.signal.reason, cancelledErrorClass, options.signal));
122
+ throw new cancelledErrorClass(
123
+ timedOutResolver?.(options.signal.reason, options.signal) ??
124
+ isTimedOutCancellation(options.signal.reason, cancelledErrorClass, options.signal),
125
+ );
122
126
  }
123
127
  const remainingMs = getRemainingTimeoutMs(options.deadlineMs);
124
128
  if (remainingMs !== undefined && remainingMs <= 0) {
@@ -139,7 +143,8 @@ export async function waitForPromiseWithCancellation<T>(
139
143
  finish(() =>
140
144
  reject(
141
145
  new cancelledErrorClass(
142
- isTimedOutCancellation(options.signal?.reason, cancelledErrorClass, options.signal),
146
+ timedOutResolver?.(options.signal?.reason, options.signal) ??
147
+ isTimedOutCancellation(options.signal?.reason, cancelledErrorClass, options.signal),
143
148
  ),
144
149
  ),
145
150
  );
@@ -276,9 +281,32 @@ interface ManagedKernelEnvOptions {
276
281
  bridge?: { url: string; token: string };
277
282
  localRoots?: Record<string, string>;
278
283
  }
284
+ interface ManagedKernelEnvPolicy {
285
+ sparse?: boolean;
286
+ }
279
287
 
280
- export function buildManagedKernelEnvPatch(options: ManagedKernelEnvOptions): Record<string, string | null> {
288
+ export function buildManagedKernelEnvPatch(options: ManagedKernelEnvOptions): Record<string, string | null>;
289
+ export function buildManagedKernelEnvPatch(
290
+ options: ManagedKernelEnvOptions,
291
+ policy: { sparse: true },
292
+ ): Record<string, string | undefined>;
293
+ export function buildManagedKernelEnvPatch(
294
+ options: ManagedKernelEnvOptions,
295
+ policy?: ManagedKernelEnvPolicy,
296
+ ): KernelEnvPatch {
281
297
  const localRoots = options.localRoots;
298
+ if (policy?.sparse) {
299
+ const patch: Record<string, string | undefined> = {};
300
+ if (options.sessionFile) patch.PI_SESSION_FILE = options.sessionFile;
301
+ if (options.artifactsDir) patch.PI_ARTIFACTS_DIR = options.artifactsDir;
302
+ if (options.bridge) {
303
+ patch.PI_TOOL_BRIDGE_URL = options.bridge.url;
304
+ patch.PI_TOOL_BRIDGE_TOKEN = options.bridge.token;
305
+ patch.PI_TOOL_BRIDGE_SESSION = options.bridgeSessionId ?? "";
306
+ }
307
+ if (localRoots) patch.PI_EVAL_LOCAL_ROOTS = JSON.stringify(localRoots);
308
+ return patch;
309
+ }
282
310
  return {
283
311
  PI_SESSION_FILE: options.sessionFile ?? null,
284
312
  PI_ARTIFACTS_DIR: options.artifactsDir ?? null,
@@ -289,13 +317,18 @@ export function buildManagedKernelEnvPatch(options: ManagedKernelEnvOptions): Re
289
317
  };
290
318
  }
291
319
 
292
- export function buildManagedKernelEnv(options: ManagedKernelEnvOptions): Record<string, string> | undefined {
293
- const patch = buildManagedKernelEnvPatch(options);
320
+ export function buildManagedKernelEnv(
321
+ options: ManagedKernelEnvOptions,
322
+ policy?: ManagedKernelEnvPolicy,
323
+ ): Record<string, string> | undefined {
324
+ const patch = policy?.sparse
325
+ ? buildManagedKernelEnvPatch(options, { sparse: true })
326
+ : buildManagedKernelEnvPatch(options);
294
327
  const env: Record<string, string> = {};
295
328
  let hasKeys = false;
296
329
  for (const key of MANAGED_KERNEL_ENV_KEYS) {
297
330
  const value = patch[key];
298
- if (value !== null) {
331
+ if (typeof value === "string") {
299
332
  env[key] = value;
300
333
  hasKeys = true;
301
334
  }