@oh-my-pi/pi-coding-agent 16.4.2 → 16.4.3

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 (122) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/cli.js +17514 -17799
  3. package/dist/types/advisor/config.d.ts +4 -3
  4. package/dist/types/commit/agentic/agent.d.ts +1 -0
  5. package/dist/types/config/settings-schema.d.ts +28 -0
  6. package/dist/types/extensibility/plugins/legacy-pi-compat.d.ts +10 -22
  7. package/dist/types/lsp/deferred-diagnostics.d.ts +11 -0
  8. package/dist/types/modes/components/move-overlay.d.ts +1 -1
  9. package/dist/types/modes/components/status-line/component.d.ts +3 -0
  10. package/dist/types/modes/components/status-line/types.d.ts +3 -0
  11. package/dist/types/modes/interactive-mode.d.ts +8 -0
  12. package/dist/types/modes/types.d.ts +2 -0
  13. package/dist/types/session/agent-session.d.ts +16 -0
  14. package/dist/types/task/executor.d.ts +31 -0
  15. package/dist/types/tools/__tests__/vibe-render.test.d.ts +1 -0
  16. package/dist/types/tools/browser/cmux/cmux-tab.d.ts +3 -1
  17. package/dist/types/tools/browser/cmux/rpc.d.ts +20 -0
  18. package/dist/types/tools/browser/run-output.d.ts +25 -0
  19. package/dist/types/tools/browser/tab-worker.d.ts +16 -0
  20. package/dist/types/tools/index.d.ts +1 -0
  21. package/dist/types/tools/vibe.d.ts +161 -0
  22. package/dist/types/utils/changelog.d.ts +35 -1
  23. package/dist/types/vibe/runtime.d.ts +124 -0
  24. package/dist/types/vibe/state.d.ts +4 -0
  25. package/dist/types/web/search/provider.d.ts +2 -0
  26. package/dist/types/web/search/providers/bing.d.ts +14 -0
  27. package/dist/types/web/search/providers/browser-headers.d.ts +9 -0
  28. package/dist/types/web/search/providers/browser-page.d.ts +32 -0
  29. package/dist/types/web/search/providers/ecosia.d.ts +14 -0
  30. package/dist/types/web/search/providers/google.d.ts +13 -0
  31. package/dist/types/web/search/providers/mojeek.d.ts +14 -0
  32. package/dist/types/web/search/providers/public.d.ts +37 -0
  33. package/dist/types/web/search/providers/startpage.d.ts +14 -0
  34. package/dist/types/web/search/providers/yahoo.d.ts +14 -0
  35. package/dist/types/web/search/types.d.ts +28 -0
  36. package/package.json +15 -18
  37. package/scripts/build-binary.ts +56 -73
  38. package/scripts/bundle-dist.ts +36 -40
  39. package/scripts/compile-binary.ts +68 -0
  40. package/scripts/generate-docs-index.ts +3 -93
  41. package/scripts/legacy-pi-virtual-module.ts +192 -0
  42. package/src/advisor/__tests__/advisor.test.ts +13 -0
  43. package/src/advisor/__tests__/config.test.ts +36 -0
  44. package/src/advisor/config.ts +11 -8
  45. package/src/commit/agentic/agent.ts +4 -0
  46. package/src/commit/agentic/index.ts +46 -21
  47. package/src/edit/index.ts +10 -76
  48. package/src/exec/non-interactive-env.ts +0 -1
  49. package/src/extensibility/plugins/legacy-pi-compat.ts +328 -162
  50. package/src/extensibility/plugins/legacy-pi-virtual-modules.d.ts +4 -0
  51. package/src/internal-urls/docs-index.ts +2 -1
  52. package/src/internal-urls/skill-protocol.ts +1 -1
  53. package/src/lsp/deferred-diagnostics.ts +66 -0
  54. package/src/main.ts +13 -13
  55. package/src/mcp/transports/stdio.test.ts +45 -1
  56. package/src/mcp/transports/stdio.ts +6 -3
  57. package/src/modes/acp/acp-agent.ts +65 -1
  58. package/src/modes/acp/acp-event-mapper.ts +5 -0
  59. package/src/modes/acp/acp-mode.ts +11 -0
  60. package/src/modes/components/__tests__/move-overlay.test.ts +16 -1
  61. package/src/modes/components/advisor-config.ts +15 -7
  62. package/src/modes/components/move-overlay.ts +2 -3
  63. package/src/modes/components/status-line/component.ts +6 -0
  64. package/src/modes/components/status-line/segments.ts +6 -0
  65. package/src/modes/components/status-line/types.ts +3 -0
  66. package/src/modes/controllers/command-controller.ts +8 -10
  67. package/src/modes/interactive-mode.ts +117 -1
  68. package/src/modes/types.ts +2 -0
  69. package/src/prompts/system/eager-task.md +2 -2
  70. package/src/prompts/system/system-prompt.md +9 -2
  71. package/src/prompts/system/vibe-mode-active.md +23 -0
  72. package/src/prompts/tools/browser.md +3 -3
  73. package/src/prompts/tools/grep.md +1 -1
  74. package/src/prompts/tools/vibe-kill.md +3 -0
  75. package/src/prompts/tools/vibe-list.md +3 -0
  76. package/src/prompts/tools/vibe-send.md +9 -0
  77. package/src/prompts/tools/vibe-spawn.md +10 -0
  78. package/src/prompts/tools/vibe-turn-result.md +19 -0
  79. package/src/prompts/tools/vibe-wait.md +8 -0
  80. package/src/sdk.ts +5 -0
  81. package/src/session/agent-session.ts +103 -13
  82. package/src/session/snapcompact-inline.ts +3 -19
  83. package/src/slash-commands/builtin-registry.ts +24 -8
  84. package/src/task/agents.ts +0 -2
  85. package/src/task/executor.ts +105 -0
  86. package/src/tools/__tests__/vibe-render.test.ts +210 -0
  87. package/src/tools/bash-skill-urls.ts +1 -1
  88. package/src/tools/browser/cmux/cmux-tab.ts +46 -48
  89. package/src/tools/browser/cmux/rpc.ts +50 -0
  90. package/src/tools/browser/run-output.ts +76 -0
  91. package/src/tools/browser/tab-worker.ts +264 -129
  92. package/src/tools/glob.ts +20 -6
  93. package/src/tools/index.ts +1 -0
  94. package/src/tools/read.ts +17 -9
  95. package/src/tools/renderers.ts +6 -0
  96. package/src/tools/vibe.ts +608 -0
  97. package/src/tools/write.ts +15 -2
  98. package/src/utils/changelog.ts +106 -9
  99. package/src/utils/git.ts +0 -1
  100. package/src/utils/title-generator.ts +70 -7
  101. package/src/vibe/runtime.ts +710 -0
  102. package/src/vibe/state.ts +4 -0
  103. package/src/web/search/index.ts +14 -6
  104. package/src/web/search/provider.ts +37 -1
  105. package/src/web/search/providers/bing.ts +197 -0
  106. package/src/web/search/providers/browser-headers.ts +92 -0
  107. package/src/web/search/providers/browser-page.ts +123 -0
  108. package/src/web/search/providers/duckduckgo.ts +13 -34
  109. package/src/web/search/providers/ecosia.ts +178 -0
  110. package/src/web/search/providers/google.ts +193 -0
  111. package/src/web/search/providers/mojeek.ts +206 -0
  112. package/src/web/search/providers/public.ts +201 -0
  113. package/src/web/search/providers/startpage.ts +213 -0
  114. package/src/web/search/providers/yahoo.ts +179 -0
  115. package/src/web/search/types.ts +35 -0
  116. package/dist/types/extensibility/plugins/legacy-pi-bundled-keys.d.ts +0 -10
  117. package/dist/types/extensibility/plugins/legacy-pi-bundled-registry.d.ts +0 -10
  118. package/scripts/generate-legacy-pi-bundled-registry.ts +0 -420
  119. package/src/extensibility/plugins/legacy-pi-bundled-keys.ts +0 -1011
  120. package/src/extensibility/plugins/legacy-pi-bundled-registry.ts +0 -3430
  121. package/src/internal-urls/docs-index.generated.txt +0 -2
  122. package/src/prompts/agents/plan.md +0 -47
@@ -0,0 +1,124 @@
1
+ import type { AsyncJobManager } from "../async/job-manager.js";
2
+ import type { ToolSession } from "../tools/index.js";
3
+ /** The two worker CLI flavors the director drives. */
4
+ export type VibeCli = "fast" | "good";
5
+ /**
6
+ * CLI flavor → bundled agent type. This IS the model-tier mapping: `sonic`
7
+ * carries `model: "pi/smol"` (the configured fast/low-latency role) and `task`
8
+ * carries `model: "pi/task"` (inherits the session's strong model).
9
+ * Resolution goes through {@link resolveAgentModelPatterns} exactly like a
10
+ * `task` spawn, so `task.agentModelOverrides` and model-role settings apply.
11
+ */
12
+ export declare const VIBE_CLI_AGENT: Record<VibeCli, string>;
13
+ /** Worker session lifecycle as shown to the director. */
14
+ export type VibeSessionState = "starting" | "running" | "idle" | "dead";
15
+ /**
16
+ * Live per-session "screen" for rich rendering: what the worker is doing right
17
+ * now (tool trace, current tool, streamed text tail) plus roster metadata.
18
+ * Every string is already one-line sanitized.
19
+ */
20
+ export interface VibeScreenSnapshot {
21
+ id: string;
22
+ cli: VibeCli;
23
+ state: VibeSessionState;
24
+ model?: string;
25
+ turns: number;
26
+ queued: number;
27
+ /** Start of the in-flight turn, when running. */
28
+ turnStartedAt?: number;
29
+ /** Gist of the message that started the in-flight turn. */
30
+ turnMessage?: string;
31
+ currentTool?: string;
32
+ currentToolArgs?: string;
33
+ lastIntent?: string;
34
+ /** Completed tool calls of the in-flight turn, oldest first (tail). */
35
+ trace: string[];
36
+ /** Latest streamed worker text lines, oldest first. */
37
+ outputTail: string[];
38
+ lastActivity?: string;
39
+ lastActivityAt: number;
40
+ }
41
+ export interface VibeSpawnOutcome {
42
+ id: string;
43
+ jobId: string;
44
+ }
45
+ export interface VibeSendOutcome {
46
+ id: string;
47
+ /**
48
+ * - `turn`: a new background turn was started (`jobId` set).
49
+ * - `steered`: worker was mid-turn and streaming; delivered as steering.
50
+ * - `queued`: worker was mid-turn but not steerable; drained into the next turn.
51
+ */
52
+ mode: "turn" | "steered" | "queued";
53
+ jobId?: string;
54
+ }
55
+ export interface VibeKillOutcome {
56
+ id: string;
57
+ /** True when an in-flight turn job was cancelled along the way. */
58
+ cancelledTurn: boolean;
59
+ }
60
+ export interface VibeWaitOutcome {
61
+ /** Watched sessions whose snapshotted turn settled during (or before) the wait.
62
+ * May overlap `stillRunning` when a queued follow-up turn already started. */
63
+ settled: Array<{
64
+ id: string;
65
+ jobId: string;
66
+ status: "completed" | "failed" | "cancelled";
67
+ resultText: string;
68
+ }>;
69
+ /** Watched sessions with a turn in flight when the wait returned. */
70
+ stillRunning: string[];
71
+ timedOut: boolean;
72
+ }
73
+ /** Thrown from a turn job body so the job manager marks the job failed while carrying the formatted result. */
74
+ export declare class VibeTurnError extends Error {
75
+ }
76
+ /**
77
+ * Process-global registry of vibe worker sessions, scoped per owner agent id
78
+ * (same convention as AsyncJobManager owner filters). The interactive mode
79
+ * kills an owner's sessions on vibe-mode exit via {@link killAll}.
80
+ */
81
+ export declare class VibeSessionRegistry {
82
+ #private;
83
+ static global(): VibeSessionRegistry;
84
+ /** Reset the global registry. Test-only. */
85
+ static resetGlobalForTests(): void;
86
+ listIds(owner: string): string[];
87
+ /**
88
+ * Live screen snapshots for rich rendering (the "TV wall"): one entry per
89
+ * session in creation order, carrying the in-flight turn's trace, current
90
+ * tool, and streamed text tail. All strings are one-line sanitized here so
91
+ * renderers can print them verbatim.
92
+ */
93
+ screens(owner: string, ids?: string[]): VibeScreenSnapshot[];
94
+ /** Spawn a persistent worker session and start its first turn in the background. */
95
+ spawn(session: ToolSession, args: {
96
+ cli: VibeCli;
97
+ name?: string;
98
+ prompt: string;
99
+ }): Promise<VibeSpawnOutcome>;
100
+ /**
101
+ * Send a message to a worker. Mid-turn and streaming → steering; mid-turn
102
+ * otherwise → queued for the next turn; idle/parked → starts a new
103
+ * background turn immediately.
104
+ */
105
+ send(session: ToolSession, args: {
106
+ session: string;
107
+ message: string;
108
+ }): Promise<VibeSendOutcome>;
109
+ /**
110
+ * Block until one watched session's in-flight turn settles, the timeout
111
+ * elapses, or `signal` aborts — `job` poll semantics. Settled turns are
112
+ * acknowledged against the job manager so their results are not delivered
113
+ * a second time as async follow-ups.
114
+ */
115
+ wait(session: ToolSession, args: {
116
+ sessions?: string[];
117
+ timeoutMs?: number;
118
+ signal?: AbortSignal;
119
+ }): Promise<VibeWaitOutcome>;
120
+ /** Terminate a worker: cancel its in-flight turn and dispose + unregister its session. */
121
+ kill(session: ToolSession, id: string): Promise<VibeKillOutcome>;
122
+ /** Kill every session belonging to `owner` (vibe-mode exit / teardown). Returns the number killed. */
123
+ killAll(owner: string, manager?: AsyncJobManager): Promise<number>;
124
+ }
@@ -0,0 +1,4 @@
1
+ /** Vibe mode session-level state, mirroring {@link ../plan-mode/state.ts}. */
2
+ export interface VibeModeState {
3
+ enabled: boolean;
4
+ }
@@ -22,6 +22,8 @@ export declare function getSearchProvider(id: SearchProviderId): Promise<SearchP
22
22
  export declare function setPreferredSearchProvider(provider: SearchProviderId | "auto"): void;
23
23
  /** Set providers that web search should never use, including fallbacks. */
24
24
  export declare function setExcludedSearchProviders(providers: readonly SearchProviderId[]): void;
25
+ /** `true` when settings exclude `id` from web search (auto chain and the Public Web fan-out). */
26
+ export declare function isSearchProviderExcluded(id: SearchProviderId): boolean;
25
27
  /**
26
28
  * Determine which providers are configured and currently available.
27
29
  * Each candidate is loaded (and its `isAvailable()` called) only as the chain
@@ -0,0 +1,14 @@
1
+ import type { AuthStorage } from "@oh-my-pi/pi-ai";
2
+ import type { SearchResponse } from "../../../web/search/types.js";
3
+ import type { SearchParams } from "./base.js";
4
+ import { SearchProvider } from "./base.js";
5
+ /** Execute a Bing web search via the server-rendered HTML results page. */
6
+ export declare function searchBing(params: SearchParams): Promise<SearchResponse>;
7
+ /** Search provider for Bing (no API key required). */
8
+ export declare class BingProvider extends SearchProvider {
9
+ readonly id = "bing";
10
+ readonly label = "Bing";
11
+ isAvailable(_authStorage: AuthStorage): boolean;
12
+ isExplicitlyAvailable(_authStorage: AuthStorage): boolean;
13
+ search(params: SearchParams): Promise<SearchResponse>;
14
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Build a fresh, internally consistent desktop navigation fingerprint for one HTTP request.
3
+ * By default, this randomizes across valid modern versions of Chrome, Firefox, Edge, and Safari
4
+ * using real-world traffic data. Set `randomized` to `false` when a fetch must preserve a
5
+ * stable Mac Chrome identity.
6
+ */
7
+ export declare function buildBrowserNavigationHeaders(options?: {
8
+ randomized?: boolean;
9
+ }): Record<string, string>;
@@ -0,0 +1,32 @@
1
+ import type { FetchImpl } from "@oh-my-pi/pi-ai";
2
+ import type { Page } from "puppeteer-core";
3
+ /** HTML plus the response status and final URL after redirects or browser navigation. */
4
+ export interface LoadedHtmlPage {
5
+ html: string;
6
+ status: number;
7
+ url: string;
8
+ }
9
+ interface BrowserFallbackOptions {
10
+ homeUrl?: string;
11
+ ready?: {
12
+ selector: string;
13
+ timeoutMs: number;
14
+ };
15
+ afterNavigation?: (page: Page, signal: AbortSignal) => Promise<void>;
16
+ shouldFallback: (page: LoadedHtmlPage) => boolean;
17
+ attempts?: number;
18
+ retryDelayMs?: number;
19
+ }
20
+ /** Controls a browser-profiled fetch and its optional headless-browser fallback. */
21
+ export interface BrowserFetchOptions {
22
+ fetch?: FetchImpl;
23
+ signal: AbortSignal;
24
+ randomizeHeaders?: boolean;
25
+ referer?: string;
26
+ init?: Omit<RequestInit, "headers" | "signal">;
27
+ headers?: Readonly<Record<string, string>>;
28
+ browser?: BrowserFallbackOptions;
29
+ }
30
+ /** Fetch with a fresh browser profile, escalating rejected production responses to the stealth browser. */
31
+ export declare function browserFetch(url: string, options: BrowserFetchOptions): Promise<LoadedHtmlPage>;
32
+ export {};
@@ -0,0 +1,14 @@
1
+ import type { AuthStorage } from "@oh-my-pi/pi-ai";
2
+ import type { SearchResponse } from "../../../web/search/types.js";
3
+ import type { SearchParams } from "./base.js";
4
+ import { SearchProvider } from "./base.js";
5
+ /** Execute an Ecosia web search and parse the server-rendered result page. */
6
+ export declare function searchEcosia(params: SearchParams): Promise<SearchResponse>;
7
+ /** Search provider for Ecosia (no API key required). */
8
+ export declare class EcosiaProvider extends SearchProvider {
9
+ readonly id = "ecosia";
10
+ readonly label = "Ecosia";
11
+ isAvailable(_authStorage: AuthStorage): boolean;
12
+ isExplicitlyAvailable(_authStorage: AuthStorage): boolean;
13
+ search(params: SearchParams): Promise<SearchResponse>;
14
+ }
@@ -0,0 +1,13 @@
1
+ import type { AuthStorage } from "@oh-my-pi/pi-ai";
2
+ import type { SearchResponse } from "../../../web/search/types.js";
3
+ import type { SearchParams } from "./base.js";
4
+ import { SearchProvider } from "./base.js";
5
+ /** Execute a Google web search with fetch-first loading and a headless-browser fallback. */
6
+ export declare function searchGoogle(params: SearchParams): Promise<SearchResponse>;
7
+ /** Fetch-first Google Search provider with a headless-browser fallback; no API key is required. */
8
+ export declare class GoogleProvider extends SearchProvider {
9
+ readonly id = "google";
10
+ readonly label = "Google";
11
+ isAvailable(_authStorage: AuthStorage): boolean;
12
+ search(params: SearchParams): Promise<SearchResponse>;
13
+ }
@@ -0,0 +1,14 @@
1
+ import type { AuthStorage } from "@oh-my-pi/pi-ai";
2
+ import type { SearchResponse } from "../../../web/search/types.js";
3
+ import type { SearchParams } from "./base.js";
4
+ import { SearchProvider } from "./base.js";
5
+ /** Execute a Mojeek web search against the standard HTML results page. */
6
+ export declare function searchMojeek(params: SearchParams): Promise<SearchResponse>;
7
+ /** Search provider for Mojeek (independent index, no API key required). */
8
+ export declare class MojeekProvider extends SearchProvider {
9
+ readonly id = "mojeek";
10
+ readonly label = "Mojeek";
11
+ isAvailable(_authStorage: AuthStorage): boolean;
12
+ isExplicitlyAvailable(_authStorage: AuthStorage): boolean;
13
+ search(params: SearchParams): Promise<SearchResponse>;
14
+ }
@@ -0,0 +1,37 @@
1
+ import type { AuthStorage } from "@oh-my-pi/pi-ai";
2
+ import type { SearchResponse } from "../types.js";
3
+ import type { SearchParams } from "./base.js";
4
+ import { SearchProvider } from "./base.js";
5
+ /** Deadline overrides — test seam; production callers use the defaults. */
6
+ export interface PublicWebDeadlines {
7
+ softMs?: number;
8
+ hardMs?: number;
9
+ }
10
+ /**
11
+ * Execute a web search against every credential-free engine in parallel and
12
+ * consolidate the results: URLs are deduplicated across engines, ranked by
13
+ * cross-engine consensus (how many engines returned them), then by best
14
+ * per-engine rank.
15
+ *
16
+ * The fan-out races three exits and returns at the earliest: every engine
17
+ * settled; the soft deadline elapsed with at least one success in hand; the
18
+ * hard deadline elapsed regardless. If the soft deadline fires before any
19
+ * engine has delivered, the aggregate keeps waiting (up to the hard cap) for
20
+ * the first success, so a slow field degrades to fewer engines rather than
21
+ * an empty answer. Stragglers are aborted once the race resolves. Individual
22
+ * engine failures (bot challenges, timeouts) are tolerated; the call fails
23
+ * only when every engine fails.
24
+ */
25
+ export declare function searchPublicWeb(params: SearchParams, deadlines?: PublicWebDeadlines): Promise<SearchResponse>;
26
+ /**
27
+ * Aggregate meta-provider over every credential-free engine. Explicit-only:
28
+ * the auto chain already walks the individual engines sequentially, so
29
+ * fanning out to all of them is a deliberate user choice, not a fallback.
30
+ */
31
+ export declare class PublicWebProvider extends SearchProvider {
32
+ readonly id = "public";
33
+ readonly label = "Public Web";
34
+ isAvailable(_authStorage: AuthStorage): boolean;
35
+ isExplicitlyAvailable(_authStorage: AuthStorage): boolean;
36
+ search(params: SearchParams): Promise<SearchResponse>;
37
+ }
@@ -0,0 +1,14 @@
1
+ import type { AuthStorage } from "@oh-my-pi/pi-ai";
2
+ import type { SearchResponse } from "../../../web/search/types.js";
3
+ import type { SearchParams } from "./base.js";
4
+ import { SearchProvider } from "./base.js";
5
+ /** Execute a Startpage web search via the homepage-token form flow. */
6
+ export declare function searchStartpage(params: SearchParams): Promise<SearchResponse>;
7
+ /** Search provider for Startpage (no API key required). */
8
+ export declare class StartpageProvider extends SearchProvider {
9
+ readonly id = "startpage";
10
+ readonly label = "Startpage";
11
+ isAvailable(_authStorage: AuthStorage): boolean;
12
+ isExplicitlyAvailable(_authStorage: AuthStorage): boolean;
13
+ search(params: SearchParams): Promise<SearchResponse>;
14
+ }
@@ -0,0 +1,14 @@
1
+ import type { AuthStorage } from "@oh-my-pi/pi-ai";
2
+ import type { SearchResponse } from "../../../web/search/types.js";
3
+ import type { SearchParams } from "./base.js";
4
+ import { SearchProvider } from "./base.js";
5
+ /** Execute a Yahoo web search via the server-rendered HTML results page. */
6
+ export declare function searchYahoo(params: SearchParams): Promise<SearchResponse>;
7
+ /** Search provider for Yahoo (no API key required). */
8
+ export declare class YahooProvider extends SearchProvider {
9
+ readonly id = "yahoo";
10
+ readonly label = "Yahoo";
11
+ isAvailable(_authStorage: AuthStorage): boolean;
12
+ isExplicitlyAvailable(_authStorage: AuthStorage): boolean;
13
+ search(params: SearchParams): Promise<SearchResponse>;
14
+ }
@@ -75,10 +75,38 @@ export declare const SEARCH_PROVIDER_OPTIONS: readonly [{
75
75
  readonly value: "searxng";
76
76
  readonly label: "SearXNG";
77
77
  readonly description: "Requires SEARXNG_ENDPOINT or searxng.endpoint";
78
+ }, {
79
+ readonly value: "startpage";
80
+ readonly label: "Startpage";
81
+ readonly description: "Credential-free scrape of Startpage (Google-backed) results; may be bot-challenged";
78
82
  }, {
79
83
  readonly value: "duckduckgo";
80
84
  readonly label: "DuckDuckGo";
81
85
  readonly description: "Credential-free best-effort fallback; may be bot-challenged on datacenter/shared-egress IPs";
86
+ }, {
87
+ readonly value: "bing";
88
+ readonly label: "Bing";
89
+ readonly description: "Credential-free HTML scrape of Bing results; may be bot-challenged";
90
+ }, {
91
+ readonly value: "yahoo";
92
+ readonly label: "Yahoo";
93
+ readonly description: "Credential-free HTML scrape of Yahoo (Bing-backed) results";
94
+ }, {
95
+ readonly value: "ecosia";
96
+ readonly label: "Ecosia";
97
+ readonly description: "Credential-free browser-backed scrape of Ecosia (Google-backed) results";
98
+ }, {
99
+ readonly value: "google";
100
+ readonly label: "Google";
101
+ readonly description: "Credential-free browser-backed fallback; slower and may be bot-challenged";
102
+ }, {
103
+ readonly value: "mojeek";
104
+ readonly label: "Mojeek";
105
+ readonly description: "Credential-free browser-backed scrape of Mojeek's independent index";
106
+ }, {
107
+ readonly value: "public";
108
+ readonly label: "Public Web";
109
+ readonly description: "Queries every credential-free engine in parallel and consolidates deduplicated results";
82
110
  }];
83
111
  /** Supported web search providers (every option except `auto`). */
84
112
  export type SearchProviderId = Exclude<(typeof SEARCH_PROVIDER_OPTIONS)[number]["value"], "auto">;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-coding-agent",
4
- "version": "16.4.2",
4
+ "version": "16.4.3",
5
5
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -32,41 +32,37 @@
32
32
  },
33
33
  "scripts": {
34
34
  "build": "bun scripts/build-binary.ts",
35
- "check": "biome check . && bun run check:docs && bun run check:types",
36
- "check:docs": "bun scripts/generate-docs-index.ts --check",
35
+ "check": "biome check . && bun run check:types",
37
36
  "check:types": "tsgo -p tsconfig.json --noEmit",
38
37
  "lint": "biome lint .",
39
38
  "test": "bun ../../scripts/ci-test-ts.ts coding-agent-heavy --full",
40
39
  "fix": "biome check --write --unsafe . && bun run format-prompts",
41
40
  "fmt": "biome format --write . && bun run format-prompts",
42
41
  "format-prompts": "bun scripts/format-prompts.ts",
43
- "gen:docs": "bun scripts/generate-docs-index.ts --generate",
44
- "gen:docs:reset": "bun scripts/generate-docs-index.ts --reset",
45
42
  "gen:tool-views": "bun --cwd=../collab-web run gen:tool-views",
46
43
  "gen:bundle": "bun scripts/bundle-dist.ts",
47
44
  "gen:mupdf": "bun scripts/embed-mupdf-wasm.ts --generate",
48
45
  "gen:mupdf:reset": "bun scripts/embed-mupdf-wasm.ts --reset",
49
46
  "gen:native": "bun --cwd=../natives run gen:native",
50
47
  "gen:native:reset": "bun --cwd=../natives run gen:native:reset",
51
- "prepack": "bun run gen:docs && bun run gen:tool-views && bun run gen:bundle || ( bun run gen:docs:reset; exit 1 )",
52
- "postpack": "bun run gen:docs:reset",
48
+ "prepack": "bun run gen:tool-views && bun run gen:bundle",
53
49
  "bench:guard": "bun scripts/bench-guard.ts"
54
50
  },
55
51
  "dependencies": {
56
52
  "@agentclientprotocol/sdk": "0.25.0",
57
53
  "@babel/parser": "^7.29.7",
58
54
  "@mozilla/readability": "^0.6.0",
59
- "@oh-my-pi/hashline": "16.4.2",
60
- "@oh-my-pi/omp-stats": "16.4.2",
61
- "@oh-my-pi/pi-agent-core": "16.4.2",
62
- "@oh-my-pi/pi-ai": "16.4.2",
63
- "@oh-my-pi/pi-catalog": "16.4.2",
64
- "@oh-my-pi/pi-mnemopi": "16.4.2",
65
- "@oh-my-pi/pi-natives": "16.4.2",
66
- "@oh-my-pi/pi-tui": "16.4.2",
67
- "@oh-my-pi/pi-utils": "16.4.2",
68
- "@oh-my-pi/pi-wire": "16.4.2",
69
- "@oh-my-pi/snapcompact": "16.4.2",
55
+ "@oh-my-pi/hashline": "16.4.3",
56
+ "@oh-my-pi/omp-stats": "16.4.3",
57
+ "@oh-my-pi/pi-agent-core": "16.4.3",
58
+ "@oh-my-pi/pi-ai": "16.4.3",
59
+ "@oh-my-pi/pi-catalog": "16.4.3",
60
+ "@oh-my-pi/pi-mnemopi": "16.4.3",
61
+ "@oh-my-pi/pi-natives": "16.4.3",
62
+ "@oh-my-pi/pi-tui": "16.4.3",
63
+ "@oh-my-pi/pi-utils": "16.4.3",
64
+ "@oh-my-pi/pi-wire": "16.4.3",
65
+ "@oh-my-pi/snapcompact": "16.4.3",
70
66
  "@opentelemetry/api": "^1.9.1",
71
67
  "@opentelemetry/context-async-hooks": "^2.7.1",
72
68
  "@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
@@ -81,6 +77,7 @@
81
77
  "diff": "^9.0.0",
82
78
  "fast-xml-parser": "^5.9.0",
83
79
  "handlebars": "^4.7.9",
80
+ "header-generator": "^2.1.82",
84
81
  "linkedom": "^0.18.12",
85
82
  "lru-cache": "11.5.1",
86
83
  "mammoth": "^1.12.0",
@@ -2,17 +2,41 @@
2
2
 
3
3
  import { createRequire } from "node:module";
4
4
  import * as path from "node:path";
5
+ import { compileCodingAgent } from "./compile-binary";
5
6
 
6
7
  const packageDir = path.join(import.meta.dir, "..");
7
8
  const repoRoot = path.join(packageDir, "..", "..");
8
- // Optional cross-compile target, e.g. CROSS_TARGET=linux-arm64 → bun build
9
- // --target=bun-linux-arm64, embeds the matching native, outputs dist/omp-<target>.
10
- const crossTarget = Bun.env.CROSS_TARGET || null;
11
- const [crossPlatform, crossArch] = crossTarget ? crossTarget.split("-") : [null, null];
12
- // x64 uses the baseline bun runtime so it runs under Rosetta / pre-AVX2 CPUs
13
- // (the modern bun-linux-x64 target SIGILLs under Apple-Silicon Rosetta).
14
- const bunTarget = crossTarget ? (crossTarget === "linux-x64" ? "bun-linux-x64-baseline" : `bun-${crossTarget}`) : null;
15
- const outName = crossTarget ? `omp-${crossTarget}` : "omp";
9
+
10
+ interface CrossBuild {
11
+ readonly id: string;
12
+ readonly platform: string;
13
+ readonly arch: string;
14
+ readonly target: Bun.Build.CompileTarget;
15
+ }
16
+
17
+ function resolveCrossBuild(value: string | undefined): CrossBuild | null {
18
+ switch (value) {
19
+ case undefined:
20
+ case "":
21
+ return null;
22
+ case "darwin-arm64":
23
+ return { id: value, platform: "darwin", arch: "arm64", target: "bun-darwin-arm64" };
24
+ case "darwin-x64":
25
+ return { id: value, platform: "darwin", arch: "x64", target: "bun-darwin-x64" };
26
+ case "linux-arm64":
27
+ return { id: value, platform: "linux", arch: "arm64", target: "bun-linux-arm64" };
28
+ case "linux-x64":
29
+ return { id: value, platform: "linux", arch: "x64", target: "bun-linux-x64-baseline" };
30
+ case "win32-x64":
31
+ case "windows-x64":
32
+ return { id: value, platform: "win32", arch: "x64", target: "bun-windows-x64-modern" };
33
+ default:
34
+ throw new Error(`Unsupported CROSS_TARGET: ${value}`);
35
+ }
36
+ }
37
+
38
+ const crossBuild = resolveCrossBuild(Bun.env.CROSS_TARGET);
39
+ const outName = crossBuild ? `omp-${crossBuild.id}` : "omp";
16
40
  const outputPath = path.join(packageDir, "dist", outName);
17
41
 
18
42
  // Transformers.js is an optional, native-heavy dependency that is never bundled
@@ -20,12 +44,19 @@ const outputPath = path.join(packageDir, "dist", outName);
20
44
  // on first use. The `catalog:` spec cannot be resolved from inside the compiled
21
45
  // bunfs (issue #1763), so embed the concrete installed version here for the
22
46
  // worker to pin its runtime install against.
23
- const transformersVersion = (
24
- createRequire(import.meta.url)("@huggingface/transformers/package.json") as { version: string }
25
- ).version;
47
+ const transformersManifest: unknown = createRequire(import.meta.url)("@huggingface/transformers/package.json");
48
+ if (
49
+ typeof transformersManifest !== "object" ||
50
+ transformersManifest === null ||
51
+ !("version" in transformersManifest) ||
52
+ typeof transformersManifest.version !== "string"
53
+ ) {
54
+ throw new Error("@huggingface/transformers package manifest has no string version");
55
+ }
56
+ const transformersVersion = transformersManifest.version;
26
57
 
27
58
  function shouldAdhocSignDarwinBinary(): boolean {
28
- return process.platform === "darwin" && !crossTarget;
59
+ return process.platform === "darwin" && !crossBuild;
29
60
  }
30
61
 
31
62
  async function runCommand(
@@ -50,73 +81,26 @@ async function main(): Promise<void> {
50
81
  // placeholders (stats client archive, docs index) even on failure.
51
82
  try {
52
83
  await runCommand(["bun", "--cwd=../stats", "run", "gen:stats"]);
53
- await runCommand(["bun", "run", "gen:docs"]);
54
- // `legacy-pi-bundled-registry.ts` static-imports
55
- // `@oh-my-pi/pi-coding-agent/export/html` (one of pi-coding-agent's
56
- // named subpath exports, see scripts/generate-legacy-pi-bundled-registry.ts),
57
- // whose source pulls in `tool-views.generated.js`. The root
58
- // `package.json` "prepare" lifecycle hook builds that file on
59
- // `bun install`, but a clean binary build that skips install hooks
60
- // would `bun build --compile` against the registry entry and fail
61
- // resolving the missing generated bundle. Rebuilding the tool views
62
- // here makes the compile self-contained and matches what `prepack`
63
- // does for the npm bundle.
84
+ // The in-memory legacy Pi virtual module reaches the coding-agent
85
+ // `export/html` subpath, whose source imports `tool-views.generated.js`.
86
+ // Rebuild it before compilation so clean checkouts that skipped install
87
+ // hooks still contain that generated bundle.
64
88
  await runCommand(["bun", "--cwd=../collab-web", "run", "gen:tool-views"]);
65
89
  await runCommand(
66
90
  ["bun", "--cwd=../natives", "run", "gen:native"],
67
- crossTarget
68
- ? { ...Bun.env, TARGET_PLATFORM: crossPlatform as string, TARGET_ARCH: crossArch as string }
69
- : Bun.env,
91
+ crossBuild ? { ...Bun.env, TARGET_PLATFORM: crossBuild.platform, TARGET_ARCH: crossBuild.arch } : Bun.env,
70
92
  );
71
93
  await runCommand(["bun", "run", "gen:mupdf"]);
72
- // Regenerate the bundled-pi registry + key set before the compile so any
73
- // new pi-* subpath export added under `packages/*/package.json` is served
74
- // from the host's in-process copy. Without this, `bun build --compile`
75
- // would freeze whatever the committed registry happened to enumerate at
76
- // the time of the last manual `--generate`, and a new subpath added
77
- // since then would crash extension validation with `Cannot find module`
78
- // (issue #3442). The generator also normalizes formatting, so the diff
79
- // against the committed copy stays clean.
80
- await runCommand(["bun", "scripts/generate-legacy-pi-bundled-registry.ts", "--generate"]);
81
94
  try {
82
- const buildEnv = shouldAdhocSignDarwinBinary() ? { ...Bun.env, BUN_NO_CODESIGN_MACHO_BINARY: "1" } : Bun.env;
83
- await runCommand(
84
- [
85
- "bun",
86
- "build",
87
- "--compile",
88
- ...(bunTarget ? ["--target", bunTarget] : []),
89
- "--no-compile-autoload-bunfig",
90
- "--no-compile-autoload-dotenv",
91
- "--no-compile-autoload-tsconfig",
92
- "--no-compile-autoload-package-json",
93
- "--keep-names",
94
- "--define",
95
- 'process.env.PI_COMPILED="true"',
96
- "--define",
97
- `process.env.PI_TINY_TRANSFORMERS_VERSION=${JSON.stringify(transformersVersion)}`,
98
- "--external",
99
- "fastembed",
100
- "--external",
101
- "onnxruntime-node",
102
- "--root",
103
- ".",
104
- "./packages/coding-agent/src/cli.ts",
105
- // Legacy pi-* extension compat surfaces (host packages + shims)
106
- // were previously listed as explicit `--compile` entries so the
107
- // rewrite path could emit `/$bunfs/root/...` URLs against them.
108
- // Bun 1.3.14 made bunfs files unreachable at runtime (issue
109
- // #3423), so `legacy-pi-compat.ts` now serves them through a
110
- // virtual namespace backed by `legacy-pi-bundled-registry.ts`,
111
- // which static-imports each surface — the bundler already
112
- // includes them via the main module graph, so no `--compile`
113
- // extras are required.
114
- "--outfile",
115
- `packages/coding-agent/dist/${outName}`,
116
- ],
117
- buildEnv,
95
+ await compileCodingAgent({
118
96
  repoRoot,
119
- );
97
+ entrypoint: path.join(packageDir, "src", "cli.ts"),
98
+ outfile: outputPath,
99
+ transformersVersion,
100
+ target: crossBuild?.target,
101
+ external: ["fastembed", "onnxruntime-node"],
102
+ skipBuiltinCodesign: shouldAdhocSignDarwinBinary(),
103
+ });
120
104
 
121
105
  // Bun 1.3.12 emits a truncated Mach-O signature on darwin builds.
122
106
  if (shouldAdhocSignDarwinBinary()) {
@@ -128,7 +112,6 @@ async function main(): Promise<void> {
128
112
  }
129
113
  } finally {
130
114
  await runCommand(["bun", "--cwd=../stats", "run", "gen:stats:reset"]);
131
- await runCommand(["bun", "run", "gen:docs:reset"]);
132
115
  }
133
116
  }
134
117