@oh-my-pi/pi-coding-agent 17.2.6 → 17.2.8

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 (162) hide show
  1. package/CHANGELOG.md +23 -1
  2. package/dist/{CHANGELOG-gs76k6wc.md → CHANGELOG-0b0w17se.md} +23 -1
  3. package/dist/cli.js +3850 -3887
  4. package/dist/types/advisor/advise-tool.d.ts +10 -4
  5. package/dist/types/autoresearch/tools/init-experiment.d.ts +19 -7
  6. package/dist/types/autoresearch/tools/log-experiment.d.ts +19 -11
  7. package/dist/types/autoresearch/tools/run-experiment.d.ts +4 -2
  8. package/dist/types/autoresearch/tools/update-notes.d.ts +5 -2
  9. package/dist/types/commit/agentic/tools/analyze-file.d.ts +5 -2
  10. package/dist/types/commit/agentic/tools/git-file-diff.d.ts +5 -2
  11. package/dist/types/commit/agentic/tools/git-hunk.d.ts +6 -2
  12. package/dist/types/commit/agentic/tools/git-overview.d.ts +5 -2
  13. package/dist/types/commit/agentic/tools/propose-changelog.d.ts +29 -7
  14. package/dist/types/commit/agentic/tools/propose-commit.d.ts +14 -4
  15. package/dist/types/commit/agentic/tools/recent-commits.d.ts +4 -2
  16. package/dist/types/commit/agentic/tools/schemas.d.ts +7 -3
  17. package/dist/types/commit/agentic/tools/split-commit.d.ts +37 -10
  18. package/dist/types/commit/changelog/generate.d.ts +13 -3
  19. package/dist/types/commit/shared-llm.d.ts +13 -4
  20. package/dist/types/config/config-file.d.ts +1 -1
  21. package/dist/types/config/models-config-schema-bundle.d.ts +1992 -981
  22. package/dist/types/config/models-config-schema.d.ts +1201 -580
  23. package/dist/types/config/models-config.d.ts +355 -371
  24. package/dist/types/edit/hashline/params.d.ts +4 -2
  25. package/dist/types/edit/modes/apply-patch.d.ts +4 -2
  26. package/dist/types/edit/modes/patch.d.ts +16 -5
  27. package/dist/types/edit/modes/replace.d.ts +8 -3
  28. package/dist/types/eval/bridge-timeout.d.ts +5 -2
  29. package/dist/types/eval/completion-bridge.d.ts +13 -0
  30. package/dist/types/eval/py/tool-bridge.d.ts +12 -0
  31. package/dist/types/extensibility/custom-commands/types.d.ts +4 -4
  32. package/dist/types/extensibility/custom-tools/types.d.ts +4 -4
  33. package/dist/types/extensibility/extensions/types.d.ts +4 -4
  34. package/dist/types/extensibility/hooks/types.d.ts +4 -4
  35. package/dist/types/extensibility/legacy-pi-ai-shim.d.ts +1 -1
  36. package/dist/types/extensibility/legacy-pi-coding-agent-shim.d.ts +1 -1
  37. package/dist/types/extensibility/legacy-typebox.d.ts +8 -0
  38. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +6 -13
  39. package/dist/types/goals/tools/goal-tool.d.ts +12 -4
  40. package/dist/types/lsp/index.d.ts +15 -5
  41. package/dist/types/lsp/types.d.ts +15 -5
  42. package/dist/types/security/contracts/schemas.d.ts +985 -409
  43. package/dist/types/security/publication.d.ts +92 -34
  44. package/dist/types/session/agent-session-types.d.ts +1 -1
  45. package/dist/types/session/session-entries.d.ts +1 -1
  46. package/dist/types/session/session-manager.d.ts +1 -1
  47. package/dist/types/task/types.d.ts +63 -18
  48. package/dist/types/tools/ask.d.ts +34 -8
  49. package/dist/types/tools/ast-edit.d.ts +16 -4
  50. package/dist/types/tools/ast-grep.d.ts +12 -4
  51. package/dist/types/tools/bash.d.ts +20 -11
  52. package/dist/types/tools/browser.d.ts +64 -20
  53. package/dist/types/tools/checkpoint.d.ts +16 -8
  54. package/dist/types/tools/computer.d.ts +1 -1
  55. package/dist/types/tools/debug.d.ts +118 -48
  56. package/dist/types/tools/eval.d.ts +11 -5
  57. package/dist/types/tools/gh.d.ts +74 -26
  58. package/dist/types/tools/glob.d.ts +16 -6
  59. package/dist/types/tools/grep.d.ts +18 -6
  60. package/dist/types/tools/hub/index.d.ts +116 -46
  61. package/dist/types/tools/image-gen.d.ts +25 -8
  62. package/dist/types/tools/inspect-image.d.ts +10 -4
  63. package/dist/types/tools/learn.d.ts +26 -8
  64. package/dist/types/tools/manage-skill.d.ts +16 -6
  65. package/dist/types/tools/memory-edit.d.ts +18 -6
  66. package/dist/types/tools/memory-recall.d.ts +8 -4
  67. package/dist/types/tools/memory-reflect.d.ts +10 -4
  68. package/dist/types/tools/memory-retain.d.ts +14 -4
  69. package/dist/types/tools/read.d.ts +8 -4
  70. package/dist/types/tools/security-scan.d.ts +82 -30
  71. package/dist/types/tools/todo.d.ts +30 -10
  72. package/dist/types/tools/tts.d.ts +12 -5
  73. package/dist/types/tools/vibe.d.ts +42 -18
  74. package/dist/types/tools/write.d.ts +10 -4
  75. package/dist/types/web/search/index.d.ts +20 -6
  76. package/package.json +13 -13
  77. package/scripts/legacy-pi-virtual-module.ts +2 -2
  78. package/src/advisor/advise-tool.ts +1 -1
  79. package/src/advisor/config.ts +1 -1
  80. package/src/autoresearch/tools/init-experiment.ts +1 -2
  81. package/src/autoresearch/tools/log-experiment.ts +1 -2
  82. package/src/autoresearch/tools/run-experiment.ts +1 -1
  83. package/src/autoresearch/tools/update-notes.ts +1 -1
  84. package/src/commit/agentic/tools/analyze-file.ts +1 -1
  85. package/src/commit/agentic/tools/git-file-diff.ts +1 -1
  86. package/src/commit/agentic/tools/git-hunk.ts +1 -1
  87. package/src/commit/agentic/tools/git-overview.ts +1 -1
  88. package/src/commit/agentic/tools/propose-changelog.ts +1 -1
  89. package/src/commit/agentic/tools/propose-commit.ts +1 -1
  90. package/src/commit/agentic/tools/recent-commits.ts +1 -1
  91. package/src/commit/agentic/tools/schemas.ts +1 -1
  92. package/src/commit/agentic/tools/split-commit.ts +1 -1
  93. package/src/commit/analysis/summary.ts +1 -1
  94. package/src/commit/changelog/generate.ts +1 -1
  95. package/src/config/config-file.ts +2 -2
  96. package/src/config/models-config-schema-bundle.ts +1 -8
  97. package/src/discovery/codex.ts +22 -9
  98. package/src/edit/hashline/params.ts +1 -1
  99. package/src/edit/modes/apply-patch.ts +1 -1
  100. package/src/edit/modes/patch.ts +1 -1
  101. package/src/edit/modes/replace.ts +2 -1
  102. package/src/eval/agent-bridge.ts +4 -2
  103. package/src/eval/bridge-timeout.ts +5 -2
  104. package/src/eval/completion-bridge.ts +3 -2
  105. package/src/eval/executor-base.ts +20 -1
  106. package/src/eval/js/context-manager.ts +94 -6
  107. package/src/eval/py/tool-bridge.ts +29 -9
  108. package/src/extensibility/custom-commands/loader.ts +3 -3
  109. package/src/extensibility/custom-commands/types.ts +4 -4
  110. package/src/extensibility/custom-tools/loader.ts +3 -3
  111. package/src/extensibility/custom-tools/types.ts +5 -4
  112. package/src/extensibility/extensions/loader.ts +3 -3
  113. package/src/extensibility/extensions/types.ts +5 -4
  114. package/src/extensibility/hooks/loader.ts +3 -3
  115. package/src/extensibility/hooks/types.ts +4 -4
  116. package/src/extensibility/legacy-pi-ai-shim.ts +1 -1
  117. package/src/extensibility/legacy-pi-coding-agent-shim.ts +2 -2
  118. package/src/extensibility/legacy-typebox.ts +101 -0
  119. package/src/extensibility/plugins/legacy-pi-compat.ts +13 -22
  120. package/src/goals/tools/goal-tool.ts +1 -1
  121. package/src/lsp/types.ts +1 -1
  122. package/src/modes/theme/theme.ts +3 -3
  123. package/src/security/contracts/schemas.ts +1 -5
  124. package/src/security/contracts/validation.ts +1 -1
  125. package/src/security/publication.ts +1 -1
  126. package/src/session/agent-session-types.ts +1 -1
  127. package/src/session/agent-session.ts +1 -2
  128. package/src/session/session-context.ts +3 -3
  129. package/src/session/session-entries.ts +1 -1
  130. package/src/session/session-manager.ts +1 -1
  131. package/src/slash-commands/builtin-registry.ts +3 -4
  132. package/src/task/types.ts +1 -1
  133. package/src/tools/ask.ts +1 -1
  134. package/src/tools/ast-edit.ts +1 -1
  135. package/src/tools/ast-grep.ts +1 -1
  136. package/src/tools/bash.ts +61 -3
  137. package/src/tools/browser.ts +1 -1
  138. package/src/tools/checkpoint.ts +1 -1
  139. package/src/tools/computer.ts +1 -1
  140. package/src/tools/debug.ts +1 -1
  141. package/src/tools/eval.ts +1 -1
  142. package/src/tools/gh.ts +1 -2
  143. package/src/tools/glob.ts +1 -1
  144. package/src/tools/grep.ts +1 -1
  145. package/src/tools/hub/index.ts +1 -1
  146. package/src/tools/image-gen.ts +1 -1
  147. package/src/tools/inspect-image.ts +1 -1
  148. package/src/tools/learn.ts +1 -1
  149. package/src/tools/manage-skill.ts +1 -1
  150. package/src/tools/memory-edit.ts +1 -1
  151. package/src/tools/memory-recall.ts +1 -1
  152. package/src/tools/memory-reflect.ts +1 -1
  153. package/src/tools/memory-retain.ts +1 -1
  154. package/src/tools/read.ts +1 -1
  155. package/src/tools/security-scan.ts +1 -1
  156. package/src/tools/todo.ts +1 -1
  157. package/src/tools/tts.ts +1 -1
  158. package/src/tools/vibe.ts +2 -1
  159. package/src/tools/write.ts +1 -1
  160. package/src/web/search/index.ts +2 -1
  161. package/dist/types/extensibility/typebox.d.ts +0 -181
  162. package/src/extensibility/typebox.ts +0 -958
@@ -7,6 +7,10 @@
7
7
  * - Register commands, keyboard shortcuts, and CLI flags
8
8
  * - Interact with the user via UI primitives
9
9
  */
10
+
11
+ import type { Type as arktype } from "@oh-my-pi/omptype";
12
+ import type * as TypeBox from "@oh-my-pi/omptype/typebox";
13
+ import type * as zod from "@oh-my-pi/omptype/zod";
10
14
  import type {
11
15
  AgentMessage,
12
16
  AgentToolResult,
@@ -36,8 +40,6 @@ import type {
36
40
  import type { OAuthCredentials, OAuthLoginCallbacks } from "@oh-my-pi/pi-ai/oauth/types";
37
41
  import type { AutocompleteItem, AutocompleteProvider, Component, EditorTheme, KeyId, TUI } from "@oh-my-pi/pi-tui";
38
42
  import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
39
- import type { Type as arktype } from "arktype";
40
- import type * as zod from "zod/v4";
41
43
  import type { KeybindingsManager } from "../../config/keybindings";
42
44
  import type { ModelRegistry } from "../../config/model-registry";
43
45
  import type { EditToolDetails } from "../../edit";
@@ -102,7 +104,6 @@ import type {
102
104
  TurnStartEvent,
103
105
  } from "../shared-events";
104
106
  import type { SlashCommandInfo } from "../slash-commands";
105
- import type * as TypeBox from "../typebox";
106
107
 
107
108
  export type { AppKeybinding, KeybindingsManager } from "../../config/keybindings";
108
109
  export type { ExecOptions, ExecResult } from "../../exec/exec";
@@ -1113,7 +1114,7 @@ export interface ExtensionAPI {
1113
1114
 
1114
1115
  /** Injected arktype module for arktype-authored extension tools (canonical going forward). */
1115
1116
  arktype: typeof arktype;
1116
- /** Injected zod/v4 module for canonical extension tool parameter schemas. */
1117
+ /** Injected omptype-backed zod facade for extension tool parameter schemas. */
1117
1118
  zod: typeof zod;
1118
1119
 
1119
1120
  /** Injected pi-coding-agent exports for accessing SDK utilities */
@@ -2,16 +2,16 @@
2
2
  * Hook loader - loads TypeScript hook modules using native Bun import.
3
3
  */
4
4
  import * as path from "node:path";
5
+ import * as arktype from "@oh-my-pi/omptype";
6
+ import * as zodModule from "@oh-my-pi/omptype/zod";
5
7
  import { logger } from "@oh-my-pi/pi-utils";
6
- import * as arktype from "arktype";
7
- import * as zodModule from "zod/v4";
8
8
  import { hookCapability } from "../../capability/hook";
9
9
  import type { Hook } from "../../discovery";
10
10
  import { loadCapability } from "../../discovery";
11
11
  // Runtime self-reference: dereference this namespace only inside loader functions to keep the index.ts cycle safe.
12
12
  import * as PiCodingAgent from "../../index";
13
13
  import type { CustomMessagePayload } from "../../session/messages";
14
- import * as typebox from "../typebox";
14
+ import * as typebox from "../legacy-typebox";
15
15
  import { resolvePath, withHostGuard } from "../utils";
16
16
  import { execCommand } from "./runner";
17
17
  import type { ExecOptions, HookAPI, HookFactory, HookMessageRenderer, RegisteredCommand } from "./types";
@@ -1,8 +1,9 @@
1
+ import type { Type } from "@oh-my-pi/omptype";
2
+ import type * as TypeBox from "@oh-my-pi/omptype/typebox";
3
+ import type * as zod from "@oh-my-pi/omptype/zod";
1
4
  import type { ImageContent, Message, Model, TextContent } from "@oh-my-pi/pi-ai";
2
5
  import type { Component, TUI } from "@oh-my-pi/pi-tui";
3
6
  import type { logger as PiLogger } from "@oh-my-pi/pi-utils";
4
- import type { Type } from "arktype";
5
- import type * as zod from "zod/v4";
6
7
  import type { ModelRegistry } from "../../config/model-registry";
7
8
  import type { EditToolDetails } from "../../edit";
8
9
  import type { ExecOptions, ExecResult } from "../../exec/exec";
@@ -43,7 +44,6 @@ import type {
43
44
  TurnEndEvent,
44
45
  TurnStartEvent,
45
46
  } from "../shared-events";
46
- import type * as TypeBox from "../typebox";
47
47
 
48
48
  // Re-export for backward compatibility
49
49
  export type { ExecOptions, ExecResult } from "../../exec/exec";
@@ -586,7 +586,7 @@ export interface HookAPI {
586
586
  typebox: typeof TypeBox;
587
587
  /** Injected arktype module for arktype-authored hooks. */
588
588
  arktype: typeof Type;
589
- /** Injected zod/v4 module for canonical hook validation. */
589
+ /** Injected omptype-backed zod facade for hook validation. */
590
590
  zod: typeof zod;
591
591
  /** Injected pi-coding-agent exports */
592
592
  pi: typeof PiCodingAgent;
@@ -37,7 +37,7 @@ import {
37
37
  getBundledProviders,
38
38
  modelsAreEqual,
39
39
  } from "@oh-my-pi/pi-catalog/models";
40
- import { type TSchema, Type } from "./typebox";
40
+ import { type TSchema, Type } from "./legacy-typebox";
41
41
 
42
42
  export interface StringEnumOptions<T extends string> {
43
43
  description?: string;
@@ -57,10 +57,10 @@ import { EventBus } from "../utils/event-bus";
57
57
  import { discoverExtensionPaths, loadExtensionFromFactory, loadExtensions } from "./extensions";
58
58
  import { ExtensionRuntime } from "./extensions/loader";
59
59
  import type { ExtensionFactory, ToolDefinition } from "./extensions/types";
60
+ import { Type } from "./legacy-typebox";
60
61
  import { getEnabledPlugins, resolvePluginExtensionPaths, type ScopedInstalledPlugin } from "./plugins/loader";
61
62
  import type { Skill } from "./skills";
62
63
  import { loadSkillsFromDir } from "./skills";
63
- import { Type } from "./typebox";
64
64
 
65
65
  const TOOL_DEFINITION_MARKER = "__isToolDefinition";
66
66
  const LEGACY_BUILTIN_TOOL_MARKER = "__ompLegacyBuiltinTool";
@@ -1434,4 +1434,4 @@ export { parseArgs } from "../cli/args";
1434
1434
  export * from "../index";
1435
1435
  export { formatBytes as formatSize } from "../tools/render-utils";
1436
1436
  export { copyToClipboard } from "../utils/clipboard";
1437
- export { Type } from "./typebox";
1437
+ export { Type } from "./legacy-typebox";
@@ -0,0 +1,101 @@
1
+ import {
2
+ type ObjectOpts,
3
+ Type as OmpType,
4
+ type TypeBuilder as OmpTypeBuilder,
5
+ type TUnsafe,
6
+ } from "@oh-my-pi/omptype/typebox";
7
+ import { upgradeJsonSchemaTo202012, validateJsonSchemaValue } from "@oh-my-pi/pi-ai/utils/schema";
8
+
9
+ export * from "@oh-my-pi/omptype/typebox";
10
+
11
+ const VALIDATION_FAILURE = Symbol("pi.typebox.validationFailure");
12
+
13
+ interface ValidationFailure {
14
+ message: string;
15
+ readonly [VALIDATION_FAILURE]: true;
16
+ }
17
+
18
+ interface SafeParseSuccess<T> {
19
+ success: true;
20
+ data: T;
21
+ }
22
+
23
+ interface SafeParseFailure {
24
+ success: false;
25
+ error: ValidationFailure;
26
+ }
27
+
28
+ type LegacyUnsafeSchema<T> = Record<string, unknown> &
29
+ TUnsafe<T> & {
30
+ __validator(data: unknown): T | ValidationFailure;
31
+ safeParse(input: unknown): SafeParseSuccess<T> | SafeParseFailure;
32
+ };
33
+
34
+ function defineHidden(target: object, key: PropertyKey, value: unknown): void {
35
+ Object.defineProperty(target, key, {
36
+ value,
37
+ writable: true,
38
+ configurable: true,
39
+ });
40
+ }
41
+
42
+ function unsafe<T = unknown>(jsonSchema: Record<string, unknown> = {}): LegacyUnsafeSchema<T> {
43
+ const schema = { ...jsonSchema } as LegacyUnsafeSchema<T>;
44
+ const upgradedSchema = upgradeJsonSchemaTo202012(jsonSchema);
45
+ const validate = (data: unknown): T | ValidationFailure => {
46
+ const result = validateJsonSchemaValue(upgradedSchema, data);
47
+ if (result.success) return data as T;
48
+ let message = "";
49
+ for (const issue of result.issues) {
50
+ if (message) message += "; ";
51
+ message += issue.path.length > 0 ? `${issue.path.join(".")}: ${issue.message}` : issue.message;
52
+ }
53
+ const failure = { message: message || "Invalid value" } as ValidationFailure;
54
+ defineHidden(failure, VALIDATION_FAILURE, true);
55
+ return failure;
56
+ };
57
+ defineHidden(schema, "__validator", validate);
58
+ defineHidden(schema, "safeParse", (input: unknown): SafeParseSuccess<T> | SafeParseFailure => {
59
+ const result = validate(input);
60
+ return typeof result === "object" && result !== null && VALIDATION_FAILURE in result
61
+ ? { success: false, error: result }
62
+ : { success: true, data: result as T };
63
+ });
64
+ return schema;
65
+ }
66
+
67
+ const object = ((properties: Record<string, unknown>, opts?: ObjectOpts) => {
68
+ let hasRawProperty = false;
69
+ for (const key in properties) {
70
+ if (typeof properties[key] !== "function") {
71
+ hasRawProperty = true;
72
+ break;
73
+ }
74
+ }
75
+ if (!hasRawProperty) return OmpType.Object(properties as Parameters<typeof OmpType.Object>[0], opts);
76
+
77
+ const propertySchemas: Record<string, unknown> = {};
78
+ const required: string[] = [];
79
+ for (const key in properties) {
80
+ const property = properties[key];
81
+ propertySchemas[key] =
82
+ typeof property === "function" && "toJsonSchema" in property
83
+ ? (property as { toJsonSchema(): Record<string, unknown> }).toJsonSchema()
84
+ : property;
85
+ required.push(key);
86
+ }
87
+ const document: Record<string, unknown> = { type: "object", properties: propertySchemas, required };
88
+ if (opts?.additionalProperties !== undefined) {
89
+ document.additionalProperties =
90
+ typeof opts.additionalProperties === "function"
91
+ ? opts.additionalProperties.toJsonSchema()
92
+ : opts.additionalProperties;
93
+ }
94
+ return unsafe(document);
95
+ }) as typeof OmpType.Object;
96
+
97
+ export const Type: OmpTypeBuilder = { ...OmpType, Object: object, Unsafe: unsafe } as unknown as OmpTypeBuilder;
98
+ export type TypeBuilder = OmpTypeBuilder;
99
+
100
+ const legacyTypeBox: { Type: OmpTypeBuilder } = { Type };
101
+ export default legacyTypeBox;
@@ -682,13 +682,11 @@ function clearLegacyPiResolutionCaches(): void {
682
682
  registerPluginCacheInvalidator(clearLegacyPiResolutionCaches);
683
683
  const PACKAGE_IMPORT_EXCLUDED = Symbol("packageImportExcluded");
684
684
 
685
- // Extensions that imported TypeBox directly used to resolve against a real
686
- // `@sinclair/typebox` or `typebox` install. The runtime dep was replaced with
687
- // the Zod-backed shim under `extensibility/typebox.ts`; plugins still importing
688
- // either public name are redirected to that shim so existing extensions keep
689
- // working without code changes. Submodules like `@sinclair/typebox/compiler`
690
- // are intentionally not remapped — those expose TypeBox-only APIs the shim does
691
- // not provide and plugins relying on them must vendor TypeBox directly.
685
+ // Extensions importing TypeBox directly are redirected to omptype's TypeBox
686
+ // facade, keeping legacy builders while producing callable omptype schemas at
687
+ // the tool wire boundary. Submodules such as `@sinclair/typebox/compiler` are
688
+ // intentionally not remapped: plugins relying on those TypeBox-only APIs must
689
+ // vendor TypeBox directly.
692
690
  const TYPEBOX_SPECIFIER_FILTER = /^(?:@sinclair\/typebox|typebox)$/;
693
691
 
694
692
  // Compat-shim path resolution. In compiled-binary mode every bundled surface
@@ -736,20 +734,13 @@ function sourceShimPath(file: string): string {
736
734
  }
737
735
 
738
736
  /**
739
- * Resolve the path the TypeBox compatibility shim ships at, then drop it when
740
- * the source file is missing.
737
+ * Resolve the coding-agent compatibility surface that composes omptype's
738
+ * TypeBox facade with legacy `Type.Unsafe`, then drop the remap when that
739
+ * entrypoint is missing.
741
740
  *
742
- * In compiled-binary mode the shim is served through the
743
- * `omp-legacy-pi-bundled:` virtual namespace (issue #3423) bunfs paths are
744
- * unreachable on Bun 1.3.14+, so the virtual specifier is always available and
745
- * needs no filesystem probe. In dev / source-link / installed-package mode the
746
- * shim is an on-disk source file; validation mirrors
747
- * `__validateLegacyPiPackageRootOverrides` (#2168): if the computed candidate
748
- * doesn't exist (e.g. an install that dropped the source — issue #3414),
749
- * `resolveTypeBoxSpecifier` returns `undefined` and
750
- * `rewriteLegacyExtensionSource` leaves bare `typebox` / `@sinclair/typebox`
751
- * specifiers alone, so Bun falls through to native resolution against the
752
- * extension's own `node_modules`.
741
+ * In compiled-binary mode the surface is served through the
742
+ * `omp-legacy-pi-bundled:` virtual namespace (issue #3423). Dev, source-link,
743
+ * and installed-package modes use the shipped source module.
753
744
  *
754
745
  * Exported for tests; production callers use `TYPEBOX_SHIM_PATH`.
755
746
  */
@@ -764,14 +755,14 @@ export function __resolveTypeBoxShimPath(
764
755
  return pathExistsSync(sourcePath) ? sourcePath : null;
765
756
  }
766
757
 
767
- const TYPEBOX_SHIM_PATH = __resolveTypeBoxShimPath(IS_COMPILED_BINARY, sourceShimPath("typebox.ts"));
758
+ const TYPEBOX_SHIM_PATH = __resolveTypeBoxShimPath(IS_COMPILED_BINARY, sourceShimPath("legacy-typebox.ts"));
768
759
 
769
760
  // Legacy extensions historically imported `Type` (and `Static`/`TSchema`) from
770
761
  // the package root of `@(scope)/pi-ai`. pi-ai 15.1.0 removed the runtime `Type`
771
762
  // export (see `packages/ai/CHANGELOG.md`), so the bare canonical specifier no
772
763
  // longer satisfies those imports. The override below redirects only the bare
773
764
  // pi-ai package root onto a sibling shim that re-exports the canonical surface
774
- // plus the borrowed `Type` runtime from the Zod-backed TypeBox shim. Subpath
765
+ // plus the borrowed `Type` runtime from the omptype TypeBox facade. Subpath
775
766
  // imports such as `@oh-my-pi/pi-ai/oauth` continue to resolve directly
776
767
  // against the bundled pi-ai package.
777
768
  const LEGACY_PI_AI_SHIM_PATH = IS_COMPILED_BINARY
@@ -1,8 +1,8 @@
1
+ import { type } from "@oh-my-pi/omptype";
1
2
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
3
  import type { Component } from "@oh-my-pi/pi-tui";
3
4
  import { Text } from "@oh-my-pi/pi-tui";
4
5
  import { formatNumber, prompt } from "@oh-my-pi/pi-utils";
5
- import { type } from "arktype";
6
6
  import type { RenderResultOptions } from "../../extensibility/custom-tools/types";
7
7
  import type { Theme, ThemeColor } from "../../modes/theme/theme";
8
8
  import goalDescription from "../../prompts/tools/goal.md" with { type: "text" };
package/src/lsp/types.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type } from "arktype";
1
+ import { type } from "@oh-my-pi/omptype";
2
2
  import { TOOL_TIMEOUTS } from "../tools/tool-timeouts";
3
3
 
4
4
  // =============================================================================
@@ -1,5 +1,6 @@
1
1
  import * as fs from "node:fs";
2
2
  import * as path from "node:path";
3
+ import { type } from "@oh-my-pi/omptype";
3
4
  import type { ThinkingLevel } from "@oh-my-pi/pi-agent-core";
4
5
  import type { Effort } from "@oh-my-pi/pi-ai";
5
6
  import {
@@ -19,7 +20,6 @@ import type {
19
20
  TerminalAppearance,
20
21
  } from "@oh-my-pi/pi-tui";
21
22
  import { adjustHsv, colorLuma, getCustomThemesDir, isEnoent, logger, relativeLuminance } from "@oh-my-pi/pi-utils";
22
- import { type } from "arktype";
23
23
  import chalk from "chalk";
24
24
  import { LRUCache } from "lru-cache/raw";
25
25
  // Embed theme JSON files at build time
@@ -1118,7 +1118,7 @@ const spinnerFramesSchema = type("unknown").narrow((value): value is SpinnerFram
1118
1118
  const themeJsonSchema = type({
1119
1119
  "$schema?": "string",
1120
1120
  name: "string",
1121
- "vars?": "Record<string, string | number>",
1121
+ "vars?": { "[string]": "string | number" },
1122
1122
  colors: themeColorsSchema,
1123
1123
  "export?": {
1124
1124
  "pageBg?": "string | number",
@@ -1127,7 +1127,7 @@ const themeJsonSchema = type({
1127
1127
  },
1128
1128
  "symbols?": {
1129
1129
  "preset?": "'unicode' | 'nerd' | 'ascii'",
1130
- "overrides?": "Record<string, string>",
1130
+ "overrides?": { "[string]": "string" },
1131
1131
  "spinnerFrames?": spinnerFramesSchema,
1132
1132
  },
1133
1133
  });
@@ -1,11 +1,7 @@
1
+ import { type } from "@oh-my-pi/omptype";
1
2
  import { once } from "@oh-my-pi/pi-utils";
2
- import { scope } from "arktype";
3
3
 
4
4
  export const getSecurityContractSchemas = once(() => {
5
- // Security schemas validate only during security scans, so lazy construction
6
- // with interpreted traversal avoids eager JIT startup tax without changing correctness.
7
- const { type } = scope({}, { jitless: true });
8
-
9
5
  const stringRecordSchema = type({ "[string]": "string" });
10
6
  const unknownRecordSchema = type({ "[string]": "unknown" });
11
7
 
@@ -1,4 +1,4 @@
1
- import { type } from "arktype";
1
+ import { type } from "@oh-my-pi/omptype";
2
2
  import { getSecurityContractSchemas } from "./schemas";
3
3
  import type { SecurityFinding, SecurityScan, SecurityScanBundle, SecurityScanPlan } from "./types";
4
4
 
@@ -1,4 +1,4 @@
1
- import { type } from "arktype";
1
+ import { type } from "@oh-my-pi/omptype";
2
2
  import type { ToolDefinition } from "../extensibility/extensions";
3
3
  import securityPublishDescription from "../prompts/tools/security-publish.md" with { type: "text" };
4
4
  import type {
@@ -389,7 +389,7 @@ export interface FreshSessionResult {
389
389
  closedProviderSessions: number;
390
390
  }
391
391
 
392
- /** Outcome of an in-place `/reset` conversation-context reset. */
392
+ /** Outcome of an in-place `/clear` conversation-context reset. */
393
393
  export interface ResetSessionContextResult {
394
394
  /** Number of live messages dropped from the model's context. */
395
395
  droppedCount: number;
@@ -3898,8 +3898,7 @@ export class AgentSession {
3898
3898
 
3899
3899
  // Record a durable boundary on the persisted branch. The collapsed live
3900
3900
  // transcript and the model-context rebuild start emission after the latest
3901
- // boundary, so a rebuild across a `/reset` (theme change, focus attach,
3902
- // /shake, resume) does not resurrect the pre-reset conversation. The
3901
+ // boundary, so a rebuild across a `/clear` (theme change, focus attach,
3903
3902
  // on-disk record and the plain `transcript:true` export path keep the full
3904
3903
  // pre-reset history.
3905
3904
  this.sessionManager.appendResetBoundary();
@@ -284,7 +284,7 @@ export function buildSessionContext(
284
284
 
285
285
  const injectedTtsrRules = Array.from(injectedTtsrRulesSet);
286
286
 
287
- // Index on the path of the latest `/reset` boundary, or -1 when none. The
287
+ // Index on the path of the latest `/clear` boundary, or -1 when none. The
288
288
  // collapsed live transcript and the model-context rebuild start emission
289
289
  // after it (see the emission branch below); the full-history export path
290
290
  // ignores it.
@@ -389,12 +389,12 @@ export function buildSessionContext(
389
389
  resetBoundaryIdx >= 0 &&
390
390
  resetBoundaryIdx > (compaction ? path.findIndex(e => e.type === "compaction" && e.id === compaction.id) : -1)
391
391
  ) {
392
- // A `/reset` boundary durably starts emission after it — for BOTH the
392
+ // A `/clear` boundary durably starts emission after it — for BOTH the
393
393
  // collapsed live transcript AND the model context (non-transcript) rebuild
394
394
  // that feeds agent.replaceMessages (resume, /shake, reload, image drop).
395
395
  // Without honoring it here, those model-context rebuilds walk the full
396
396
  // persisted branch and put the pre-reset turns back into the LLM context
397
- // even though `/reset` reported it empty. The full-history export path
397
+ // even though `/clear` reported it empty. The full-history export path
398
398
  // (`transcript && !collapseCompactedHistory`) is handled by the first
399
399
  // branch above and left untouched, so on-disk history stays recoverable.
400
400
  // When a compaction and a reset boundary interact, the later one on the
@@ -122,7 +122,7 @@ export interface BranchSummaryEntry<T = unknown> extends SessionEntryBase {
122
122
  }
123
123
 
124
124
  /**
125
- * Pure marker entry recorded by `/reset` (resetSessionContext). It carries no
125
+ * Pure marker entry recorded by `/clear` (resetSessionContext). It carries no
126
126
  * payload — its presence on the branch is a durable boundary the collapsed
127
127
  * live transcript and the model-context rebuild start emission after, so a
128
128
  * rebuild (theme change, focus attach, /shake, resume) does not resurrect the
@@ -2094,7 +2094,7 @@ export class SessionManager {
2094
2094
  }
2095
2095
 
2096
2096
  /**
2097
- * Append the durable conversation boundary recorded by `/reset`. The
2097
+ * Append the durable conversation boundary recorded by `/clear`. The
2098
2098
  * collapsed live transcript and the model-context rebuild start after the
2099
2099
  * latest one, while the full history stays on disk (the plain
2100
2100
  * `transcript:true` export walks it unchanged).
@@ -1691,7 +1691,6 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
1691
1691
  },
1692
1692
  {
1693
1693
  name: "new",
1694
- aliases: ["clear"],
1695
1694
  description: "Start a new session",
1696
1695
  handleTui: async (_command, runtime) => {
1697
1696
  runtime.ctx.editor.setText("");
@@ -1720,10 +1719,10 @@ const BUILTIN_SLASH_COMMAND_REGISTRY: ReadonlyArray<SlashCommandSpec> = [
1720
1719
  },
1721
1720
  },
1722
1721
  {
1723
- name: "reset",
1724
- description: "Reset the conversation context in place, keeping the session",
1722
+ name: "clear",
1723
+ description: "Clear the conversation context in place, keeping the session",
1725
1724
  getTuiAutocompleteDescription: runtime =>
1726
- runtime.ctx.session.isStreaming ? "Reset: unavailable while streaming" : "Reset: drop context, keep session",
1725
+ runtime.ctx.session.isStreaming ? "Clear: unavailable while streaming" : "Clear: drop context, keep session",
1727
1726
  handleTui: async (_command, runtime) => {
1728
1727
  runtime.ctx.editor.setText("");
1729
1728
  await runtime.ctx.handleResetContextCommand();
package/src/task/types.ts CHANGED
@@ -1,6 +1,6 @@
1
+ import { type BaseType, type } from "@oh-my-pi/omptype";
1
2
  import type { Usage } from "@oh-my-pi/pi-ai";
2
3
  import { $env } from "@oh-my-pi/pi-utils";
3
- import { type BaseType, type } from "arktype";
4
4
  import type { AgentSessionEvent } from "../session/agent-session";
5
5
  import type { ConfiguredThinkingLevel, TaskEffort } from "../thinking";
6
6
  import type { NestedRepoPatch } from "./worktree";
package/src/tools/ask.ts CHANGED
@@ -15,6 +15,7 @@
15
15
  * - Questions may time out and auto-select the recommended option (configurable, disabled in plan mode)
16
16
  */
17
17
 
18
+ import { type as arkType } from "@oh-my-pi/omptype";
18
19
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
19
20
  import type { ToolExample } from "@oh-my-pi/pi-ai";
20
21
  import {
@@ -30,7 +31,6 @@ import {
30
31
  visibleWidth,
31
32
  } from "@oh-my-pi/pi-tui";
32
33
  import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
33
- import { type as arkType } from "arktype";
34
34
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
35
35
  import type { ExtensionUISelectItem } from "../extensibility/extensions";
36
36
  import { getMarkdownTheme, type Theme, theme } from "../modes/theme/theme";
@@ -1,12 +1,12 @@
1
1
  import * as path from "node:path";
2
2
  import { formatHashlineHeader } from "@oh-my-pi/hashline";
3
+ import { type } from "@oh-my-pi/omptype";
3
4
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
4
5
  import type { ToolExample } from "@oh-my-pi/pi-ai";
5
6
  import { type AstReplaceChange, type AstReplaceFileChange, astEdit } from "@oh-my-pi/pi-natives";
6
7
  import type { Component } from "@oh-my-pi/pi-tui";
7
8
  import { replaceTabs, Text } from "@oh-my-pi/pi-tui";
8
9
  import { $envpos, prompt, untilAborted } from "@oh-my-pi/pi-utils";
9
- import { type } from "arktype";
10
10
  import { canonicalSnapshotKey, getFileSnapshotStore } from "../edit/file-snapshot-store";
11
11
  import { normalizeToLF } from "../edit/normalize";
12
12
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
@@ -1,12 +1,12 @@
1
1
  import * as path from "node:path";
2
2
  import { formatHashlineHeader } from "@oh-my-pi/hashline";
3
+ import { type } from "@oh-my-pi/omptype";
3
4
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
4
5
  import type { ToolExample } from "@oh-my-pi/pi-ai";
5
6
  import { type AstFindMatch, astGrep } from "@oh-my-pi/pi-natives";
6
7
  import type { Component } from "@oh-my-pi/pi-tui";
7
8
  import { Text } from "@oh-my-pi/pi-tui";
8
9
  import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
9
- import { type } from "arktype";
10
10
  import { recordFileSnapshot, recordSeenLinesFromBody } from "../edit/file-snapshot-store";
11
11
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
12
12
  import type { Theme } from "../modes/theme/theme";
package/src/tools/bash.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import * as fs from "node:fs";
2
+ import { type } from "@oh-my-pi/omptype";
2
3
  import type {
3
4
  AgentTool,
4
5
  AgentToolContext,
@@ -9,7 +10,6 @@ import type {
9
10
  import type { Component } from "@oh-my-pi/pi-tui";
10
11
  import { ImageProtocol, TERMINAL } from "@oh-my-pi/pi-tui";
11
12
  import { getProjectDir, isEnoent, logger, prompt } from "@oh-my-pi/pi-utils";
12
- import { type } from "arktype";
13
13
  import type { Settings } from "../config/settings";
14
14
  import { applyDirenvPreflight, type BashResult, executeBash } from "../exec/bash-executor";
15
15
  import type { RenderResultOptions } from "../extensibility/custom-tools/types";
@@ -58,7 +58,65 @@ export const BASH_DEFAULT_PREVIEW_LINES = DEFAULT_TERMINAL_PREVIEW_LINES;
58
58
 
59
59
  const BASH_ENV_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
60
60
  const DEFAULT_AUTO_BACKGROUND_THRESHOLD_MS = 60_000;
61
- const BASH_APPROVAL_SHELL_CONTROL_RE = /[\n\r;&|<>`$()]/u;
61
+ const BASH_APPROVAL_SHELL_CONTROL_CHARS: Record<string, true> = {
62
+ "\n": true,
63
+ "\r": true,
64
+ ";": true,
65
+ "&": true,
66
+ "|": true,
67
+ "<": true,
68
+ ">": true,
69
+ "`": true,
70
+ $: true,
71
+ "(": true,
72
+ ")": true,
73
+ };
74
+ const BASH_APPROVAL_REINTERPRETED_ARGUMENT_RE = /(?:^|[ \t])(?:-[^-]*[ce]|--(?:command|eval))(?:[= \t]|$)/u;
75
+
76
+ function hasBashApprovalShellControl(command: string): boolean {
77
+ let quote: "'" | '"' | undefined;
78
+ let hasReinterpretableShellControl = false;
79
+ for (let i = 0; i < command.length; i++) {
80
+ const ch = command[i];
81
+ if (quote === "'") {
82
+ if (ch === "'") {
83
+ quote = undefined;
84
+ } else if (Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, ch)) {
85
+ hasReinterpretableShellControl = true;
86
+ }
87
+ continue;
88
+ }
89
+ if (ch === "\\") {
90
+ const escaped = command[i + 1];
91
+ if (escaped && Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, escaped)) {
92
+ hasReinterpretableShellControl = true;
93
+ }
94
+ i++;
95
+ continue;
96
+ }
97
+ if (quote === '"') {
98
+ if (ch === '"') {
99
+ quote = undefined;
100
+ continue;
101
+ }
102
+ // Expansion is active inside double quotes even in the original line.
103
+ if (ch === "`" || ch === "$") return true;
104
+ // Other control characters are literal here but become executable if a
105
+ // `-c`/`-e` option reinterprets the argument through another shell.
106
+ if (Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, ch)) hasReinterpretableShellControl = true;
107
+ continue;
108
+ }
109
+ if (ch === "'" || ch === '"') {
110
+ quote = ch;
111
+ continue;
112
+ }
113
+ if (Object.hasOwn(BASH_APPROVAL_SHELL_CONTROL_CHARS, ch)) return true;
114
+ }
115
+ // Options such as `git -c alias.x='!...'` and `sh -c "..."` reinterpret
116
+ // otherwise literal quoted or escaped arguments as executable code.
117
+ return hasReinterpretableShellControl && BASH_APPROVAL_REINTERPRETED_ARGUMENT_RE.test(command);
118
+ }
119
+
62
120
  const BASH_PATTERN_APPROVAL_VALUES = new Set(["allow", "deny", "prompt"]);
63
121
 
64
122
  /**
@@ -218,7 +276,7 @@ function commandSegmentMatchesBashApprovalPattern(command: string, pattern: stri
218
276
  // `prompt` fire on any matching segment so they mean what they appear to.
219
277
  function bashApprovalRuleMatches(command: string, rule: BashApprovalPatternRule): boolean {
220
278
  if (rule.approval === "allow") {
221
- if (BASH_APPROVAL_SHELL_CONTROL_RE.test(command)) return false;
279
+ if (hasBashApprovalShellControl(command)) return false;
222
280
  return commandMatchesBashApprovalPattern(command, rule.match);
223
281
  }
224
282
  return commandSegmentMatchesBashApprovalPattern(command, rule.match);
@@ -1,7 +1,7 @@
1
+ import { type } from "@oh-my-pi/omptype";
1
2
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
3
  import type { ToolExample } from "@oh-my-pi/pi-ai";
3
4
  import { prompt, untilAborted } from "@oh-my-pi/pi-utils";
4
- import { type } from "arktype";
5
5
  import browserDescription from "../prompts/tools/browser.md" with { type: "text" };
6
6
  import type { ToolSession } from "../sdk";
7
7
  import { enforceInlineByteCap } from "../session/streaming-output";
@@ -1,6 +1,6 @@
1
+ import { type } from "@oh-my-pi/omptype";
1
2
  import type { AgentTool, AgentToolContext, AgentToolResult, AgentToolUpdateCallback } from "@oh-my-pi/pi-agent-core";
2
3
  import { prompt } from "@oh-my-pi/pi-utils";
3
- import { type } from "arktype";
4
4
  import checkpointDescription from "../prompts/tools/checkpoint.md" with { type: "text" };
5
5
  import rewindDescription from "../prompts/tools/rewind.md" with { type: "text" };
6
6
  import type { ToolSession } from ".";
@@ -1,3 +1,4 @@
1
+ import { type Type, type } from "@oh-my-pi/omptype";
1
2
  import type {
2
3
  AgentTool,
3
4
  AgentToolContext,
@@ -9,7 +10,6 @@ import type { Model } from "@oh-my-pi/pi-ai";
9
10
  import { isClaudeModelId } from "@oh-my-pi/pi-catalog/identity";
10
11
  import type { DesktopCapabilities } from "@oh-my-pi/pi-natives";
11
12
  import { once, prompt } from "@oh-my-pi/pi-utils";
12
- import { type Type, type } from "arktype";
13
13
  import { callSessionTool } from "../eval/js/tool-bridge";
14
14
  import computerDescription from "../prompts/tools/computer.md" with { type: "text" };
15
15
  import { enforceInlineByteCap } from "../session/streaming-output";
@@ -1,4 +1,5 @@
1
1
  import * as fs from "node:fs/promises";
2
+ import { type } from "@oh-my-pi/omptype";
2
3
  import type {
3
4
  AgentTool,
4
5
  AgentToolContext,
@@ -10,7 +11,6 @@ import type {
10
11
  import type { ToolExample } from "@oh-my-pi/pi-ai";
11
12
  import { type Component, Text } from "@oh-my-pi/pi-tui";
12
13
  import { isEnoent, prompt } from "@oh-my-pi/pi-utils";
13
- import { type } from "arktype";
14
14
  import {
15
15
  type DapBreakpointRecord,
16
16
  type DapCapabilities,