@oh-my-pi/pi-coding-agent 16.1.0 → 16.1.2
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.
- package/CHANGELOG.md +36 -1
- package/dist/cli.js +3134 -3158
- package/dist/types/cli/bench-cli.d.ts +2 -1
- package/dist/types/config/settings-schema.d.ts +28 -37
- package/dist/types/lsp/types.d.ts +5 -3
- package/dist/types/main.d.ts +2 -0
- package/dist/types/modes/components/assistant-message.d.ts +12 -0
- package/dist/types/modes/components/cache-invalidation-marker.d.ts +7 -2
- package/dist/types/modes/components/welcome.d.ts +1 -1
- package/dist/types/sdk.d.ts +19 -2
- package/dist/types/session/auth-broker-config.d.ts +33 -6
- package/dist/types/system-prompt.d.ts +5 -1
- package/dist/types/task/executor.d.ts +10 -0
- package/dist/types/tools/find.d.ts +0 -2
- package/dist/types/tools/search.d.ts +3 -3
- package/package.json +12 -12
- package/scripts/measure-prompt-tokens.ts +63 -0
- package/src/cli/bench-cli.ts +64 -3
- package/src/cli/startup-cwd.ts +3 -13
- package/src/config/settings-schema.ts +34 -37
- package/src/config/settings.ts +40 -0
- package/src/cursor.ts +1 -1
- package/src/debug/raw-sse-buffer.ts +31 -10
- package/src/eval/py/prelude.py +1 -1
- package/src/export/html/tool-views.generated.js +1 -1
- package/src/extensibility/extensions/runner.ts +8 -2
- package/src/internal-urls/docs-index.generated.txt +1 -1
- package/src/lsp/client.ts +9 -9
- package/src/lsp/types.ts +6 -3
- package/src/main.ts +29 -9
- package/src/modes/components/assistant-message.ts +86 -0
- package/src/modes/components/cache-invalidation-marker.ts +12 -2
- package/src/modes/components/settings-defs.ts +7 -0
- package/src/modes/components/tips.txt +2 -1
- package/src/modes/components/welcome.ts +86 -8
- package/src/modes/controllers/event-controller.ts +1 -1
- package/src/prompts/system/personalities/default.md +8 -16
- package/src/prompts/system/system-prompt.md +101 -115
- package/src/prompts/tools/ast-edit.md +10 -12
- package/src/prompts/tools/ast-grep.md +14 -18
- package/src/prompts/tools/bash.md +19 -21
- package/src/prompts/tools/browser.md +24 -24
- package/src/prompts/tools/checkpoint.md +0 -1
- package/src/prompts/tools/debug.md +11 -15
- package/src/prompts/tools/eval.md +27 -27
- package/src/prompts/tools/find.md +6 -10
- package/src/prompts/tools/github.md +11 -15
- package/src/prompts/tools/goal.md +0 -7
- package/src/prompts/tools/inspect-image.md +0 -1
- package/src/prompts/tools/irc.md +15 -24
- package/src/prompts/tools/job.md +5 -8
- package/src/prompts/tools/learn.md +2 -2
- package/src/prompts/tools/lsp.md +27 -30
- package/src/prompts/tools/manage-skill.md +4 -4
- package/src/prompts/tools/read.md +21 -23
- package/src/prompts/tools/replace.md +0 -1
- package/src/prompts/tools/resolve.md +4 -9
- package/src/prompts/tools/rewind.md +1 -1
- package/src/prompts/tools/search.md +8 -10
- package/src/prompts/tools/task.md +33 -38
- package/src/prompts/tools/todo.md +14 -18
- package/src/prompts/tools/web-search.md +0 -4
- package/src/prompts/tools/write.md +1 -1
- package/src/sdk.ts +49 -102
- package/src/session/agent-session.ts +23 -12
- package/src/session/auth-broker-config.ts +36 -76
- package/src/session/session-history-format.ts +1 -1
- package/src/session/session-manager.ts +33 -6
- package/src/system-prompt.ts +28 -8
- package/src/task/executor.ts +57 -0
- package/src/task/index.ts +15 -1
- package/src/tools/browser.ts +1 -1
- package/src/tools/eval.ts +1 -1
- package/src/tools/find.ts +4 -17
- package/src/tools/memory-edit.ts +1 -1
- package/src/tools/search.ts +5 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ResolvedThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
|
2
2
|
import type { Api, ApiKeyResolver, AssistantMessageEventStream, Context, Model, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
|
|
3
|
-
import type
|
|
3
|
+
import { type CanonicalModelVariant } from "@oh-my-pi/pi-catalog/identity";
|
|
4
4
|
import type { ApiKeyResolverModel } from "../config/api-key-resolver";
|
|
5
5
|
import { type CanonicalModelQueryOptions } from "../config/model-registry";
|
|
6
6
|
import { Settings } from "../config/settings";
|
|
@@ -20,6 +20,7 @@ export interface BenchModelRegistry {
|
|
|
20
20
|
resolveCanonicalModel?(canonicalId: string, options?: CanonicalModelQueryOptions): Model<Api> | undefined;
|
|
21
21
|
getCanonicalVariants?(canonicalId: string, options?: CanonicalModelQueryOptions): CanonicalModelVariant[];
|
|
22
22
|
getCanonicalId?(model: Model<Api>): string | undefined;
|
|
23
|
+
hasConfiguredAuth?(model: Model<Api>): boolean;
|
|
23
24
|
}
|
|
24
25
|
export interface BenchRuntime {
|
|
25
26
|
modelRegistry: BenchModelRegistry;
|
|
@@ -138,44 +138,32 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
138
138
|
readonly description: "Automatically resume the most recent session in the current directory";
|
|
139
139
|
};
|
|
140
140
|
};
|
|
141
|
-
readonly "power.
|
|
142
|
-
readonly type: "
|
|
143
|
-
readonly
|
|
144
|
-
readonly
|
|
145
|
-
readonly tab: "interaction";
|
|
146
|
-
readonly group: "Power (macOS)";
|
|
147
|
-
readonly label: "Prevent Idle Sleep";
|
|
148
|
-
readonly description: "Keep the system awake while a session is open (caffeinate -i)";
|
|
149
|
-
};
|
|
150
|
-
};
|
|
151
|
-
readonly "power.preventSystemSleep": {
|
|
152
|
-
readonly type: "boolean";
|
|
153
|
-
readonly default: false;
|
|
154
|
-
readonly ui: {
|
|
155
|
-
readonly tab: "interaction";
|
|
156
|
-
readonly group: "Power (macOS)";
|
|
157
|
-
readonly label: "Prevent System Sleep on AC";
|
|
158
|
-
readonly description: "Block all system sleep while on AC power (caffeinate -s)";
|
|
159
|
-
};
|
|
160
|
-
};
|
|
161
|
-
readonly "power.declareUserActive": {
|
|
162
|
-
readonly type: "boolean";
|
|
163
|
-
readonly default: false;
|
|
164
|
-
readonly ui: {
|
|
165
|
-
readonly tab: "interaction";
|
|
166
|
-
readonly group: "Power (macOS)";
|
|
167
|
-
readonly label: "Declare User Active";
|
|
168
|
-
readonly description: "Keep the display lit and treat the user as active (caffeinate -u)";
|
|
169
|
-
};
|
|
170
|
-
};
|
|
171
|
-
readonly "power.preventDisplaySleep": {
|
|
172
|
-
readonly type: "boolean";
|
|
173
|
-
readonly default: false;
|
|
141
|
+
readonly "power.sleepPrevention": {
|
|
142
|
+
readonly type: "enum";
|
|
143
|
+
readonly values: readonly ["off", "idle", "display", "system"];
|
|
144
|
+
readonly default: "idle";
|
|
174
145
|
readonly ui: {
|
|
175
146
|
readonly tab: "interaction";
|
|
176
147
|
readonly group: "Power (macOS)";
|
|
177
|
-
readonly label: "
|
|
178
|
-
readonly description: "
|
|
148
|
+
readonly label: "Sleep Prevention";
|
|
149
|
+
readonly description: "Prevent macOS sleep during active sessions. Each level is cumulative — it adds the flags of all lower levels.";
|
|
150
|
+
readonly options: readonly [{
|
|
151
|
+
readonly value: "off";
|
|
152
|
+
readonly label: "Off";
|
|
153
|
+
readonly description: "Do not prevent any sleep";
|
|
154
|
+
}, {
|
|
155
|
+
readonly value: "idle";
|
|
156
|
+
readonly label: "Prevent Idle Sleep";
|
|
157
|
+
readonly description: "Keep the system awake while a session is open (caffeinate -i)";
|
|
158
|
+
}, {
|
|
159
|
+
readonly value: "display";
|
|
160
|
+
readonly label: "Prevent Display Sleep";
|
|
161
|
+
readonly description: "Also keep the display from idle-sleeping (caffeinate -i -d)";
|
|
162
|
+
}, {
|
|
163
|
+
readonly value: "system";
|
|
164
|
+
readonly label: "Prevent System Sleep";
|
|
165
|
+
readonly description: "Also block all system sleep on AC and declare the user active (caffeinate -i -d -s -u)";
|
|
166
|
+
}];
|
|
179
167
|
};
|
|
180
168
|
};
|
|
181
169
|
readonly "advisor.enabled": {
|
|
@@ -196,6 +184,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
196
184
|
readonly group: "Advisor";
|
|
197
185
|
readonly label: "Advisor for Subagents";
|
|
198
186
|
readonly description: "Also enable the advisor on spawned task/eval subagents.";
|
|
187
|
+
readonly condition: "advisorEnabled";
|
|
199
188
|
};
|
|
200
189
|
};
|
|
201
190
|
readonly "advisor.syncBacklog": {
|
|
@@ -207,6 +196,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
207
196
|
readonly group: "Advisor";
|
|
208
197
|
readonly label: "Advisor Sync Backlog";
|
|
209
198
|
readonly description: "Pause the main agent for up to 30 seconds if the advisor falls behind by this many turns. Off disables catch-up delays.";
|
|
199
|
+
readonly condition: "advisorEnabled";
|
|
210
200
|
};
|
|
211
201
|
};
|
|
212
202
|
readonly "advisor.immuneTurns": {
|
|
@@ -238,6 +228,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
238
228
|
readonly value: "5";
|
|
239
229
|
readonly label: "5 turns";
|
|
240
230
|
}];
|
|
231
|
+
readonly condition: "advisorEnabled";
|
|
241
232
|
};
|
|
242
233
|
};
|
|
243
234
|
readonly shellPath: {
|
|
@@ -821,7 +812,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
821
812
|
};
|
|
822
813
|
readonly "display.cacheMissMarker": {
|
|
823
814
|
readonly type: "boolean";
|
|
824
|
-
readonly default:
|
|
815
|
+
readonly default: false;
|
|
825
816
|
readonly ui: {
|
|
826
817
|
readonly tab: "appearance";
|
|
827
818
|
readonly group: "Display";
|
|
@@ -883,7 +874,7 @@ export declare const SETTINGS_SCHEMA: {
|
|
|
883
874
|
};
|
|
884
875
|
readonly inlineToolDescriptors: {
|
|
885
876
|
readonly type: "boolean";
|
|
886
|
-
readonly default:
|
|
877
|
+
readonly default: false;
|
|
887
878
|
readonly ui: {
|
|
888
879
|
readonly tab: "model";
|
|
889
880
|
readonly group: "Prompt";
|
|
@@ -259,7 +259,7 @@ export interface LspClient {
|
|
|
259
259
|
diagnostics: Map<string, PublishedDiagnostics>;
|
|
260
260
|
diagnosticsVersion: number;
|
|
261
261
|
openFiles: Map<string, OpenFile>;
|
|
262
|
-
pendingRequests: Map<number, PendingRequest>;
|
|
262
|
+
pendingRequests: Map<number | string, PendingRequest>;
|
|
263
263
|
messageBuffer: Uint8Array;
|
|
264
264
|
isReading: boolean;
|
|
265
265
|
/** Lifecycle state: "connecting" until initialize completes, then "ready"; "error" on init failure or reader death. */
|
|
@@ -275,15 +275,17 @@ export interface LspClient {
|
|
|
275
275
|
/** Call to signal that project loading has completed */
|
|
276
276
|
resolveProjectLoaded: () => void;
|
|
277
277
|
}
|
|
278
|
+
/** JSON-RPC request/response identifier accepted by LSP peers. */
|
|
279
|
+
export type LspJsonRpcId = number | string;
|
|
278
280
|
export interface LspJsonRpcRequest {
|
|
279
281
|
jsonrpc: "2.0";
|
|
280
|
-
id:
|
|
282
|
+
id: LspJsonRpcId;
|
|
281
283
|
method: string;
|
|
282
284
|
params: unknown;
|
|
283
285
|
}
|
|
284
286
|
export interface LspJsonRpcResponse {
|
|
285
287
|
jsonrpc: "2.0";
|
|
286
|
-
id?:
|
|
288
|
+
id?: LspJsonRpcId;
|
|
287
289
|
result?: unknown;
|
|
288
290
|
error?: {
|
|
289
291
|
code: number;
|
package/dist/types/main.d.ts
CHANGED
|
@@ -54,6 +54,8 @@ export declare class SessionResolutionError extends Error {
|
|
|
54
54
|
}
|
|
55
55
|
/** Resolves CLI session flags into an existing, forked, in-memory, or cancelled session manager. */
|
|
56
56
|
export declare function createSessionManager(parsed: Args, cwd: string, activeSettings?: Settings, askToForkSession?: SessionPrompt, askToMoveSession?: SessionPrompt): Promise<SessionManager | undefined>;
|
|
57
|
+
/** Apply resolved CLI/discovered prompt files without bypassing system prompt templates. */
|
|
58
|
+
export declare function applyResolvedSystemPromptInputs(options: CreateAgentSessionOptions, resolvedSystemPrompt: string | undefined, resolvedAppendPrompt: string | undefined): void;
|
|
57
59
|
interface RunRootCommandDependencies {
|
|
58
60
|
createAgentSession?: typeof createAgentSession;
|
|
59
61
|
discoverAuthStorage?: typeof discoverAuthStorage;
|
|
@@ -28,6 +28,18 @@ export declare class AssistantMessageComponent extends Container {
|
|
|
28
28
|
*/
|
|
29
29
|
setErrorPinned(pinned: boolean): void;
|
|
30
30
|
isTranscriptBlockFinalized(): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether this still-live block's scrolled-off rows may be committed to
|
|
33
|
+
* immutable native scrollback (the {@link TranscriptContainer} durable-
|
|
34
|
+
* snapshot path). Reflowing Markdown — a streaming mermaid diagram or a GFM
|
|
35
|
+
* table — re-lays-out its body as source arrives (the diagram reshapes, the
|
|
36
|
+
* table re-aligns its columns), so committing an intermediate layout strands
|
|
37
|
+
* a stale fragment in native scrollback that only a full repaint (Ctrl+L) can
|
|
38
|
+
* clear. While such content is still streaming the block therefore stays
|
|
39
|
+
* wholly in the repaintable live region and commits once, at its final
|
|
40
|
+
* layout, when the turn finalizes.
|
|
41
|
+
*/
|
|
42
|
+
isTranscriptBlockCommitStable(): boolean;
|
|
31
43
|
getTranscriptBlockVersion(): number;
|
|
32
44
|
markTranscriptBlockFinalized(): void;
|
|
33
45
|
setToolResultImages(toolCallId: string, images: ImageContent[]): void;
|
|
@@ -13,8 +13,13 @@ export interface CacheInvalidation {
|
|
|
13
13
|
* request reads nothing from cache and re-pays for the whole prompt. We detect
|
|
14
14
|
* that as: the previous turn cached a meaningful prefix, yet this turn's
|
|
15
15
|
* `cacheRead` collapsed to zero while it still reprocessed a non-trivial prompt.
|
|
16
|
-
* Returns `undefined` (no marker) for the first turn, tiny contexts,
|
|
17
|
-
* that reused any cache
|
|
16
|
+
* Returns `undefined` (no marker) for the first turn, tiny contexts, turns
|
|
17
|
+
* that reused any cache, and — crucially — turns on providers with *implicit*
|
|
18
|
+
* best-effort caching. Only an explicit, prefix-controlled cache (Anthropic /
|
|
19
|
+
* Bedrock `cache_control`) re-creates the prefix on a cold turn (`cacheWrite >
|
|
20
|
+
* 0`); implicit caches (Google / OpenAI / Fireworks) report `cacheWrite: 0` and
|
|
21
|
+
* drop `cacheRead` to zero intermittently as routine propagation noise that
|
|
22
|
+
* self-heals the next turn, so flagging it would be a false positive.
|
|
18
23
|
*/
|
|
19
24
|
export declare function detectCacheInvalidation(prev: Usage | undefined, current: Usage): CacheInvalidation | undefined;
|
|
20
25
|
/**
|
|
@@ -9,7 +9,7 @@ export declare const WELCOME_SESSION_SLOTS = 4;
|
|
|
9
9
|
* the box height is constant regardless of how many servers a project has.
|
|
10
10
|
*/
|
|
11
11
|
export declare const WELCOME_LSP_SLOTS = 4;
|
|
12
|
-
export declare function renderWelcomeTip(tip: string, boxWidth: number): string[];
|
|
12
|
+
export declare function renderWelcomeTip(tip: string, boxWidth: number, phase?: number): string[];
|
|
13
13
|
export interface RecentSession {
|
|
14
14
|
name: string;
|
|
15
15
|
timeAgo: string;
|
package/dist/types/sdk.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ import { MCPManager, type MCPToolsLoadResult } from "./mcp";
|
|
|
18
18
|
import type { MnemopiSessionState } from "./mnemopi/state";
|
|
19
19
|
import { AgentRegistry } from "./registry/agent-registry";
|
|
20
20
|
import { AgentSession } from "./session/agent-session";
|
|
21
|
-
import { AuthStorage } from "./session/auth-storage";
|
|
21
|
+
import type { AuthStorage } from "./session/auth-storage";
|
|
22
22
|
import { SessionManager } from "./session/session-manager";
|
|
23
23
|
import { type BuildSystemPromptResult } from "./system-prompt";
|
|
24
24
|
import { type ConfiguredThinkingLevel } from "./thinking";
|
|
@@ -48,8 +48,12 @@ export interface CreateAgentSessionOptions {
|
|
|
48
48
|
model: Model;
|
|
49
49
|
thinkingLevel?: ThinkingLevel;
|
|
50
50
|
}>;
|
|
51
|
-
/**
|
|
51
|
+
/** Provider-facing system prompt override. Replaces the fully rendered default blocks. */
|
|
52
52
|
systemPrompt?: string | string[] | ((defaultPrompt: string[]) => string | string[]);
|
|
53
|
+
/** Already-loaded custom prompt text rendered through the bundled custom system prompt template. */
|
|
54
|
+
customSystemPrompt?: string;
|
|
55
|
+
/** Already-loaded text appended through the bundled system prompt templates. */
|
|
56
|
+
appendSystemPrompt?: string;
|
|
53
57
|
/** Optional provider-facing session identifier for prompt caches and sticky auth selection.
|
|
54
58
|
* Keeps persisted session files isolated while reusing provider-side caches. */
|
|
55
59
|
providerSessionId?: string;
|
|
@@ -179,6 +183,15 @@ export interface CreateAgentSessionOptions {
|
|
|
179
183
|
* `@opentelemetry/api` package returns a no-op tracer in that case.
|
|
180
184
|
*/
|
|
181
185
|
telemetry?: AgentTelemetryConfig;
|
|
186
|
+
/**
|
|
187
|
+
* Fired once, when the agent loop hands its first request to the provider
|
|
188
|
+
* transport (i.e. the `streamFn` wrapper is first invoked). Used to measure
|
|
189
|
+
* subagent launch latency — the boundary between "session built" and "model
|
|
190
|
+
* call dispatched". This is the loop's dispatch point, slightly before the
|
|
191
|
+
* actual provider HTTP call (per-request prep, identical across all
|
|
192
|
+
* requests, follows it), which is the right granularity for launch timing.
|
|
193
|
+
*/
|
|
194
|
+
onFirstChatDispatch?: () => void;
|
|
182
195
|
/** Whether to auto-approve all tool calls (--auto-approve CLI flag). Default: false */
|
|
183
196
|
autoApprove?: boolean;
|
|
184
197
|
}
|
|
@@ -222,6 +235,9 @@ export { BashTool, BUILTIN_TOOLS, createTools, EditTool, EvalTool, FindTool, HID
|
|
|
222
235
|
* the client receives access tokens with `refresh = "__remote__"` and calls
|
|
223
236
|
* back into the broker through the {@link AuthStorageOptions.refreshOAuthCredential}
|
|
224
237
|
* override to re-mint access tokens when needed.
|
|
238
|
+
*
|
|
239
|
+
* Delegates to {@link ./session/auth-broker-config} so the TUI and the catalog
|
|
240
|
+
* generator share the same credential-discovery logic.
|
|
225
241
|
*/
|
|
226
242
|
export declare function discoverAuthStorage(agentDir?: string): Promise<AuthStorage>;
|
|
227
243
|
/**
|
|
@@ -287,6 +303,7 @@ export interface BuildSystemPromptOptions {
|
|
|
287
303
|
content: string;
|
|
288
304
|
}>;
|
|
289
305
|
cwd?: string;
|
|
306
|
+
customPrompt?: string;
|
|
290
307
|
appendPrompt?: string;
|
|
291
308
|
inlineToolDescriptors?: boolean;
|
|
292
309
|
}
|
|
@@ -1,9 +1,27 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Resolve auth-broker connection configuration for the local omp client.
|
|
3
|
+
*
|
|
4
|
+
* This is a thin coding-agent wrapper around the shared resolver in
|
|
5
|
+
* `@oh-my-pi/pi-ai/auth-broker/discover` that preserves the process-lifetime
|
|
6
|
+
* memoization expected by the CLI and injects the full `resolveConfigValue`
|
|
7
|
+
* (including `!command` config indirection) from coding-agent's config layer.
|
|
8
|
+
*
|
|
9
|
+
* Precedence (highest first):
|
|
10
|
+
* 1. `OMP_AUTH_BROKER_URL` / `OMP_AUTH_BROKER_TOKEN` env vars.
|
|
11
|
+
* 2. `auth.broker.url` / `auth.broker.token` in `~/.omp/agent/config.yml`
|
|
12
|
+
* (hidden from the settings UI; `!command` resolution supported).
|
|
13
|
+
* 3. Token file `~/.omp/auth-broker.token` (paired with URL from env or config).
|
|
14
|
+
*
|
|
15
|
+
* Returns null when no broker URL is configured — caller falls back to the
|
|
16
|
+
* local SQLite store.
|
|
17
|
+
*
|
|
18
|
+
* Reads config.yml directly (instead of going through `Settings.init`) because
|
|
19
|
+
* `discoverAuthStorage` runs before the settings singleton is initialized in
|
|
20
|
+
* `runRootCommand`, and we want hand-edited config entries to be honoured at
|
|
21
|
+
* boot without forcing a startup reorder.
|
|
22
|
+
*/
|
|
23
|
+
import { type AuthBrokerClientConfig, type DiscoverAuthStorageOptions, discoverAuthStorage as discoverAuthStorageShared, getAuthBrokerTokenFilePath } from "@oh-my-pi/pi-ai/auth-broker/discover";
|
|
24
|
+
export { type AuthBrokerClientConfig, getAuthBrokerTokenFilePath };
|
|
7
25
|
/**
|
|
8
26
|
* Read broker configuration. Returns null when the URL is missing
|
|
9
27
|
* (broker disabled — local store is used). Throws when URL is set but no
|
|
@@ -15,3 +33,12 @@ export declare function getAuthBrokerTokenFilePath(): string;
|
|
|
15
33
|
* retried. Concurrent callers share one in-flight resolution.
|
|
16
34
|
*/
|
|
17
35
|
export declare function resolveAuthBrokerConfig(): Promise<AuthBrokerClientConfig | null>;
|
|
36
|
+
/**
|
|
37
|
+
* Create an AuthStorage instance, using the broker when configured and falling
|
|
38
|
+
* back to the local SQLite store otherwise. Delegates to the shared resolver in
|
|
39
|
+
* pi-ai so the CLI, subagents, and the catalog generator all see the same
|
|
40
|
+
* credentials.
|
|
41
|
+
*
|
|
42
|
+
* Default `agentDir` is the current configured agent directory.
|
|
43
|
+
*/
|
|
44
|
+
export declare function discoverAuthStorage(agentDir?: string, options?: Omit<DiscoverAuthStorageOptions, "agentDir" | "configValueResolver">): ReturnType<typeof discoverAuthStorageShared>;
|
|
@@ -48,13 +48,17 @@ export declare function buildSystemPromptToolMetadata(tools: Map<string, AgentTo
|
|
|
48
48
|
export interface BuildSystemPromptOptions {
|
|
49
49
|
/** Custom system prompt (replaces default). */
|
|
50
50
|
customPrompt?: string;
|
|
51
|
+
/** Already-loaded custom system prompt text; bypasses path resolution. */
|
|
52
|
+
resolvedCustomPrompt?: string;
|
|
51
53
|
/** Tools to include in prompt. */
|
|
52
54
|
tools?: Map<string, SystemPromptToolMetadata>;
|
|
53
55
|
/** Tool names to include in prompt. */
|
|
54
56
|
toolNames?: string[];
|
|
55
57
|
/** Text to append to system prompt. */
|
|
56
58
|
appendSystemPrompt?: string;
|
|
57
|
-
/**
|
|
59
|
+
/** Already-loaded append prompt text; bypasses path resolution. */
|
|
60
|
+
resolvedAppendSystemPrompt?: string;
|
|
61
|
+
/** Inline full tool descriptors in the system prompt. Default: false */
|
|
58
62
|
inlineToolDescriptors?: boolean;
|
|
59
63
|
/**
|
|
60
64
|
* Whether provider-native tool calling is active (no owned/in-band syntax).
|
|
@@ -83,6 +83,16 @@ export interface ExecutorOptions {
|
|
|
83
83
|
enableLsp?: boolean;
|
|
84
84
|
signal?: AbortSignal;
|
|
85
85
|
onProgress?: (progress: AgentProgress) => void;
|
|
86
|
+
/**
|
|
87
|
+
* Epochs (ms, `Date.now()`) bracketing the concurrency-semaphore wait:
|
|
88
|
+
* `invokedAt` is stamped at the spawn boundary before `acquire()`,
|
|
89
|
+
* `acquiredAt` immediately after. {@link runSubprocess} reports true queue
|
|
90
|
+
* wait (`acquiredAt - invokedAt`) and pre-run setup (`startTime - acquiredAt`)
|
|
91
|
+
* separately in the launch-timing debug log. Undefined for callers that
|
|
92
|
+
* bypass the semaphore path.
|
|
93
|
+
*/
|
|
94
|
+
invokedAt?: number;
|
|
95
|
+
acquiredAt?: number;
|
|
86
96
|
sessionFile?: string | null;
|
|
87
97
|
persistArtifacts?: boolean;
|
|
88
98
|
artifactsDir?: string;
|
|
@@ -11,7 +11,6 @@ declare const findSchema: import("arktype/internal/variants/object.ts").ObjectTy
|
|
|
11
11
|
hidden?: boolean | undefined;
|
|
12
12
|
gitignore?: boolean | undefined;
|
|
13
13
|
limit?: number | undefined;
|
|
14
|
-
timeout?: number | undefined;
|
|
15
14
|
}, {}>;
|
|
16
15
|
export type FindToolInput = typeof findSchema.infer;
|
|
17
16
|
export interface FindToolDetails {
|
|
@@ -70,7 +69,6 @@ export declare class FindTool implements AgentTool<typeof findSchema, FindToolDe
|
|
|
70
69
|
hidden?: boolean | undefined;
|
|
71
70
|
gitignore?: boolean | undefined;
|
|
72
71
|
limit?: number | undefined;
|
|
73
|
-
timeout?: number | undefined;
|
|
74
72
|
}, {}>;
|
|
75
73
|
readonly examples: readonly ToolExample<typeof findSchema.infer>[];
|
|
76
74
|
readonly strict = true;
|
|
@@ -8,7 +8,7 @@ import type { OutputMeta } from "./output-meta";
|
|
|
8
8
|
declare const searchSchema: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
9
9
|
pattern: string;
|
|
10
10
|
paths?: string | string[] | undefined;
|
|
11
|
-
|
|
11
|
+
case?: boolean | undefined;
|
|
12
12
|
gitignore?: boolean | undefined;
|
|
13
13
|
skip?: number | null | undefined;
|
|
14
14
|
}, {}>;
|
|
@@ -67,7 +67,7 @@ export declare class SearchTool implements AgentTool<typeof searchSchema, Search
|
|
|
67
67
|
readonly parameters: import("arktype/internal/variants/object.ts").ObjectType<{
|
|
68
68
|
pattern: string;
|
|
69
69
|
paths?: string | string[] | undefined;
|
|
70
|
-
|
|
70
|
+
case?: boolean | undefined;
|
|
71
71
|
gitignore?: boolean | undefined;
|
|
72
72
|
skip?: number | null | undefined;
|
|
73
73
|
}, {}>;
|
|
@@ -78,7 +78,7 @@ export declare class SearchTool implements AgentTool<typeof searchSchema, Search
|
|
|
78
78
|
interface SearchRenderArgs {
|
|
79
79
|
pattern: string;
|
|
80
80
|
paths?: string | string[];
|
|
81
|
-
|
|
81
|
+
case?: boolean;
|
|
82
82
|
gitignore?: boolean;
|
|
83
83
|
skip?: number;
|
|
84
84
|
}
|
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.1.
|
|
4
|
+
"version": "16.1.2",
|
|
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",
|
|
@@ -48,17 +48,17 @@
|
|
|
48
48
|
"@agentclientprotocol/sdk": "0.25.0",
|
|
49
49
|
"@babel/parser": "^7.29.7",
|
|
50
50
|
"@mozilla/readability": "^0.6.0",
|
|
51
|
-
"@oh-my-pi/hashline": "16.1.
|
|
52
|
-
"@oh-my-pi/omp-stats": "16.1.
|
|
53
|
-
"@oh-my-pi/pi-agent-core": "16.1.
|
|
54
|
-
"@oh-my-pi/pi-ai": "16.1.
|
|
55
|
-
"@oh-my-pi/pi-catalog": "16.1.
|
|
56
|
-
"@oh-my-pi/pi-mnemopi": "16.1.
|
|
57
|
-
"@oh-my-pi/pi-natives": "16.1.
|
|
58
|
-
"@oh-my-pi/pi-tui": "16.1.
|
|
59
|
-
"@oh-my-pi/pi-utils": "16.1.
|
|
60
|
-
"@oh-my-pi/pi-wire": "16.1.
|
|
61
|
-
"@oh-my-pi/snapcompact": "16.1.
|
|
51
|
+
"@oh-my-pi/hashline": "16.1.2",
|
|
52
|
+
"@oh-my-pi/omp-stats": "16.1.2",
|
|
53
|
+
"@oh-my-pi/pi-agent-core": "16.1.2",
|
|
54
|
+
"@oh-my-pi/pi-ai": "16.1.2",
|
|
55
|
+
"@oh-my-pi/pi-catalog": "16.1.2",
|
|
56
|
+
"@oh-my-pi/pi-mnemopi": "16.1.2",
|
|
57
|
+
"@oh-my-pi/pi-natives": "16.1.2",
|
|
58
|
+
"@oh-my-pi/pi-tui": "16.1.2",
|
|
59
|
+
"@oh-my-pi/pi-utils": "16.1.2",
|
|
60
|
+
"@oh-my-pi/pi-wire": "16.1.2",
|
|
61
|
+
"@oh-my-pi/snapcompact": "16.1.2",
|
|
62
62
|
"@opentelemetry/api": "^1.9.1",
|
|
63
63
|
"@opentelemetry/context-async-hooks": "^2.7.1",
|
|
64
64
|
"@opentelemetry/exporter-trace-otlp-proto": "^0.218.0",
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { countTokens } from "@oh-my-pi/pi-agent-core";
|
|
2
|
+
import { Settings } from "@oh-my-pi/pi-coding-agent/config/settings";
|
|
3
|
+
import { estimateToolSchemaTokens } from "@oh-my-pi/pi-coding-agent/modes/utils/context-usage";
|
|
4
|
+
import { buildSystemPrompt } from "@oh-my-pi/pi-coding-agent/system-prompt";
|
|
5
|
+
import { createTools, type Tool, type ToolSession } from "@oh-my-pi/pi-coding-agent/tools";
|
|
6
|
+
|
|
7
|
+
function bytes(s: string): number {
|
|
8
|
+
return Buffer.byteLength(s, "utf-8");
|
|
9
|
+
}
|
|
10
|
+
function est(s: string): number {
|
|
11
|
+
return (bytes(s) + 3) >> 2;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
await Settings.init({ inMemory: true, cwd: process.cwd() });
|
|
15
|
+
const settings = Settings.isolated({});
|
|
16
|
+
|
|
17
|
+
const session: ToolSession = {
|
|
18
|
+
cwd: process.cwd(),
|
|
19
|
+
hasUI: false,
|
|
20
|
+
getSessionFile: () => null,
|
|
21
|
+
getSessionSpawns: () => "*",
|
|
22
|
+
settings,
|
|
23
|
+
} as ToolSession;
|
|
24
|
+
|
|
25
|
+
const tools = await createTools(session);
|
|
26
|
+
const toolsMap = new Map<string, Tool>(tools.map(t => [t.name, t]));
|
|
27
|
+
|
|
28
|
+
console.log(`active tools (${tools.length}): ${tools.map(t => t.name).join(", ")}\n`);
|
|
29
|
+
|
|
30
|
+
const rows: Array<{ name: string; descBytes: number; tok: number; schemaTok: number }> = [];
|
|
31
|
+
for (const t of tools) {
|
|
32
|
+
const tok = estimateToolSchemaTokens([t as never]);
|
|
33
|
+
const descBytes = bytes(t.description ?? "");
|
|
34
|
+
const descTok = est(t.description ?? "");
|
|
35
|
+
rows.push({ name: t.name, descBytes, tok, schemaTok: tok - descTok });
|
|
36
|
+
}
|
|
37
|
+
rows.sort((a, b) => b.tok - a.tok);
|
|
38
|
+
|
|
39
|
+
const totalTok = estimateToolSchemaTokens(tools as never);
|
|
40
|
+
console.log("per-tool tokens (sorted): name | total tok | desc bytes | ~schema tok");
|
|
41
|
+
for (const r of rows) {
|
|
42
|
+
console.log(
|
|
43
|
+
` ${r.name.padEnd(20)} ${String(r.tok).padStart(6)} ${String(r.descBytes).padStart(7)} ${String(r.schemaTok).padStart(6)}`,
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
console.log(`\nTOOLS TOTAL tokens: ${totalTok}\n`);
|
|
47
|
+
|
|
48
|
+
const built = await buildSystemPrompt({
|
|
49
|
+
tools: toolsMap as never,
|
|
50
|
+
toolNames: tools.map(t => t.name),
|
|
51
|
+
inlineToolDescriptors: false,
|
|
52
|
+
nativeTools: true,
|
|
53
|
+
cwd: process.cwd(),
|
|
54
|
+
skills: [],
|
|
55
|
+
contextFiles: [],
|
|
56
|
+
workspaceTree: { rootPath: process.cwd(), rendered: "", truncated: false, totalLines: 0, agentsMdFiles: [] },
|
|
57
|
+
});
|
|
58
|
+
const parts = built.systemPrompt;
|
|
59
|
+
const part0 = parts[0] ?? "";
|
|
60
|
+
const rest = parts.slice(1).join("\n");
|
|
61
|
+
console.log(`system prompt parts: ${parts.length}`);
|
|
62
|
+
console.log(`SYSTEM PROMPT tokens (part0, no skills): ${countTokens(part0)} (bytes=${bytes(part0)})`);
|
|
63
|
+
console.log(`SYSTEM CONTEXT tokens (parts[1..]): ${countTokens(rest)} (bytes=${bytes(rest)})`);
|
package/src/cli/bench-cli.ts
CHANGED
|
@@ -11,7 +11,7 @@ import type {
|
|
|
11
11
|
SimpleStreamOptions,
|
|
12
12
|
} from "@oh-my-pi/pi-ai";
|
|
13
13
|
import { streamSimple } from "@oh-my-pi/pi-ai";
|
|
14
|
-
import type
|
|
14
|
+
import { buildModelProviderPriorityRank, type CanonicalModelVariant } from "@oh-my-pi/pi-catalog/identity";
|
|
15
15
|
import { replaceTabs, truncateToWidth } from "@oh-my-pi/pi-tui";
|
|
16
16
|
import { formatDuration, getProjectDir } from "@oh-my-pi/pi-utils";
|
|
17
17
|
import chalk from "chalk";
|
|
@@ -50,6 +50,7 @@ export interface BenchModelRegistry {
|
|
|
50
50
|
resolveCanonicalModel?(canonicalId: string, options?: CanonicalModelQueryOptions): Model<Api> | undefined;
|
|
51
51
|
getCanonicalVariants?(canonicalId: string, options?: CanonicalModelQueryOptions): CanonicalModelVariant[];
|
|
52
52
|
getCanonicalId?(model: Model<Api>): string | undefined;
|
|
53
|
+
hasConfiguredAuth?(model: Model<Api>): boolean;
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
export interface BenchRuntime {
|
|
@@ -346,6 +347,56 @@ interface BenchTarget {
|
|
|
346
347
|
thinking: ResolvedThinkingLevel | undefined;
|
|
347
348
|
}
|
|
348
349
|
|
|
350
|
+
/** Highest-priority provider variant: native/OAuth transports outrank mirrors. */
|
|
351
|
+
function pickHighestPriorityProvider(models: Model<Api>[], providerOrder?: readonly string[]): Model<Api> | undefined {
|
|
352
|
+
if (models.length <= 1) return models[0];
|
|
353
|
+
const priority = buildModelProviderPriorityRank(providerOrder);
|
|
354
|
+
return [...models].sort((a, b) => {
|
|
355
|
+
const aRank = priority.get(a.provider.toLowerCase()) ?? Number.POSITIVE_INFINITY;
|
|
356
|
+
const bRank = priority.get(b.provider.toLowerCase()) ?? Number.POSITIVE_INFINITY;
|
|
357
|
+
return aRank - bRank;
|
|
358
|
+
})[0];
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Bench resolves selectors against the entire catalog (credentials are ignored),
|
|
363
|
+
* so an ambiguous id shared by several providers can land on one the user never
|
|
364
|
+
* authenticated. For non-pinned selectors, redirect to an equivalent model under
|
|
365
|
+
* a provider with configured auth. An explicit `provider/id` selector is honored
|
|
366
|
+
* verbatim — even unauthenticated — so forced benchmarking keeps working.
|
|
367
|
+
*/
|
|
368
|
+
function resolveAuthenticatedAlternative(
|
|
369
|
+
selector: string,
|
|
370
|
+
model: Model<Api>,
|
|
371
|
+
modelRegistry: BenchModelRegistry,
|
|
372
|
+
providerOrder?: readonly string[],
|
|
373
|
+
): Model<Api> | undefined {
|
|
374
|
+
if (!modelRegistry.hasConfiguredAuth) return undefined;
|
|
375
|
+
// A pinned `provider/...` selector is authoritative; never redirect off it.
|
|
376
|
+
if (selector.trim().toLowerCase().startsWith(`${model.provider.toLowerCase()}/`)) return undefined;
|
|
377
|
+
if (modelRegistry.hasConfiguredAuth(model)) return undefined;
|
|
378
|
+
|
|
379
|
+
const seen = new Set<string>();
|
|
380
|
+
const authenticated: Model<Api>[] = [];
|
|
381
|
+
const consider = (candidate: Model<Api>): void => {
|
|
382
|
+
const key = `${candidate.provider}/${candidate.id}`;
|
|
383
|
+
if (seen.has(key)) return;
|
|
384
|
+
seen.add(key);
|
|
385
|
+
if (modelRegistry.hasConfiguredAuth?.(candidate)) authenticated.push(candidate);
|
|
386
|
+
};
|
|
387
|
+
// Canonical variants link the same logical model across providers even when
|
|
388
|
+
// ids differ (e.g. fireworks `gpt-oss-20b` <-> openrouter `openai/gpt-oss-20b`).
|
|
389
|
+
const canonicalId = modelRegistry.getCanonicalId?.(model);
|
|
390
|
+
if (canonicalId) {
|
|
391
|
+
for (const variant of modelRegistry.getCanonicalVariants?.(canonicalId) ?? []) consider(variant.model);
|
|
392
|
+
}
|
|
393
|
+
// Same-id fallback for entries outside the canonical index.
|
|
394
|
+
for (const candidate of modelRegistry.getAll()) {
|
|
395
|
+
if (candidate.id === model.id) consider(candidate);
|
|
396
|
+
}
|
|
397
|
+
return pickHighestPriorityProvider(authenticated, providerOrder);
|
|
398
|
+
}
|
|
399
|
+
|
|
349
400
|
function resolveBenchModels(
|
|
350
401
|
selectors: string[],
|
|
351
402
|
modelRegistry: BenchModelRegistry,
|
|
@@ -366,10 +417,20 @@ function resolveBenchModels(
|
|
|
366
417
|
continue;
|
|
367
418
|
}
|
|
368
419
|
if (result.warning) writeStderr(`${chalk.yellow(`Warning: ${result.warning}`)}\n`);
|
|
420
|
+
let model = result.model;
|
|
421
|
+
const authenticated = resolveAuthenticatedAlternative(selector, model, modelRegistry, preferences.providerOrder);
|
|
422
|
+
if (authenticated) {
|
|
423
|
+
writeStderr(
|
|
424
|
+
`${chalk.yellow(
|
|
425
|
+
`Warning: no credentials for "${model.provider}"; benchmarking ${formatModelString(authenticated)} instead. Pin "${formatModelString(model)}" to force it.`,
|
|
426
|
+
)}\n`,
|
|
427
|
+
);
|
|
428
|
+
model = authenticated;
|
|
429
|
+
}
|
|
369
430
|
resolved.push({
|
|
370
431
|
selector,
|
|
371
|
-
model
|
|
372
|
-
thinking: resolveThinkingLevelForModel(
|
|
432
|
+
model,
|
|
433
|
+
thinking: resolveThinkingLevelForModel(model, result.thinkingLevel),
|
|
373
434
|
});
|
|
374
435
|
}
|
|
375
436
|
if (errors.length > 0) {
|
package/src/cli/startup-cwd.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
1
|
import * as os from "node:os";
|
|
3
2
|
import * as path from "node:path";
|
|
4
|
-
import { getProjectDir, normalizePathForComparison, setProjectDir } from "@oh-my-pi/pi-utils";
|
|
3
|
+
import { directoryExists, getProjectDir, normalizePathForComparison, setProjectDir } from "@oh-my-pi/pi-utils";
|
|
5
4
|
import type { Args } from "./args";
|
|
6
5
|
|
|
7
6
|
async function maybeAutoChdir(parsed: Args): Promise<void> {
|
|
@@ -22,19 +21,10 @@ async function maybeAutoChdir(parsed: Args): Promise<void> {
|
|
|
22
21
|
return;
|
|
23
22
|
}
|
|
24
23
|
|
|
25
|
-
const isDirectory = async (p: string) => {
|
|
26
|
-
try {
|
|
27
|
-
const s = await fs.stat(p);
|
|
28
|
-
return s.isDirectory();
|
|
29
|
-
} catch {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
|
|
34
24
|
const candidates = [path.join(home, "tmp"), "/tmp", "/var/tmp"];
|
|
35
25
|
for (const candidate of candidates) {
|
|
36
26
|
try {
|
|
37
|
-
if (!(await
|
|
27
|
+
if (!(await directoryExists(candidate))) {
|
|
38
28
|
continue;
|
|
39
29
|
}
|
|
40
30
|
setProjectDir(candidate);
|
|
@@ -46,7 +36,7 @@ async function maybeAutoChdir(parsed: Args): Promise<void> {
|
|
|
46
36
|
|
|
47
37
|
try {
|
|
48
38
|
const fallback = os.tmpdir();
|
|
49
|
-
if (fallback && normalizePath(fallback) !== cwd && (await
|
|
39
|
+
if (fallback && normalizePath(fallback) !== cwd && (await directoryExists(fallback))) {
|
|
50
40
|
setProjectDir(fallback);
|
|
51
41
|
}
|
|
52
42
|
} catch {
|