@oh-my-pi/pi-coding-agent 16.2.5 → 16.2.7

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 (93) hide show
  1. package/CHANGELOG.md +41 -1
  2. package/dist/cli.js +3089 -3104
  3. package/dist/types/cli/bench-cli.d.ts +6 -1
  4. package/dist/types/commands/bench.d.ts +8 -0
  5. package/dist/types/config/model-discovery.d.ts +6 -1
  6. package/dist/types/config/service-tier.d.ts +39 -24
  7. package/dist/types/config/settings-schema.d.ts +37 -37
  8. package/dist/types/edit/index.d.ts +1 -0
  9. package/dist/types/edit/renderer.d.ts +4 -0
  10. package/dist/types/edit/snapshot-details.d.ts +33 -0
  11. package/dist/types/mcp/config-writer.d.ts +48 -0
  12. package/dist/types/mcp/oauth-flow.d.ts +4 -6
  13. package/dist/types/mcp/types.d.ts +3 -0
  14. package/dist/types/modes/controllers/tool-args-reveal.d.ts +9 -2
  15. package/dist/types/session/agent-session.d.ts +37 -13
  16. package/dist/types/session/messages.d.ts +1 -1
  17. package/dist/types/session/session-context.d.ts +2 -2
  18. package/dist/types/session/session-entries.d.ts +2 -2
  19. package/dist/types/session/session-manager.d.ts +5 -6
  20. package/dist/types/system-prompt.test.d.ts +1 -0
  21. package/dist/types/task/executor.d.ts +6 -6
  22. package/dist/types/task/types.d.ts +6 -0
  23. package/dist/types/task/worktree.d.ts +32 -6
  24. package/dist/types/tiny/title-client.d.ts +5 -1
  25. package/dist/types/tools/index.d.ts +3 -3
  26. package/dist/types/utils/git.d.ts +17 -0
  27. package/dist/types/web/search/providers/duckduckgo.d.ts +2 -2
  28. package/dist/types/web/search/types.d.ts +1 -1
  29. package/package.json +12 -12
  30. package/src/cli/args.ts +32 -1
  31. package/src/cli/bench-cli.ts +97 -22
  32. package/src/cli/tiny-models-cli.ts +18 -4
  33. package/src/cli/web-search-cli.ts +6 -1
  34. package/src/commands/bench.ts +10 -1
  35. package/src/config/mcp-schema.json +11 -2
  36. package/src/config/model-discovery.ts +66 -8
  37. package/src/config/model-registry.ts +13 -6
  38. package/src/config/service-tier.ts +85 -56
  39. package/src/config/settings-schema.ts +42 -36
  40. package/src/config/settings.ts +47 -0
  41. package/src/edit/hashline/execute.ts +15 -9
  42. package/src/edit/index.ts +19 -6
  43. package/src/edit/modes/patch.ts +3 -2
  44. package/src/edit/modes/replace.ts +3 -2
  45. package/src/edit/renderer.ts +4 -0
  46. package/src/edit/snapshot-details.ts +77 -0
  47. package/src/eval/agent-bridge.ts +4 -2
  48. package/src/extensibility/plugins/legacy-pi-compat.ts +2 -2
  49. package/src/internal-urls/docs-index.generated.txt +1 -1
  50. package/src/main.ts +1 -1
  51. package/src/mcp/config-writer.ts +121 -0
  52. package/src/mcp/config.ts +10 -6
  53. package/src/mcp/oauth-flow.ts +10 -8
  54. package/src/mcp/transports/stdio.ts +9 -17
  55. package/src/mcp/types.ts +3 -0
  56. package/src/modes/components/extensions/extension-dashboard.ts +46 -0
  57. package/src/modes/components/extensions/state-manager.ts +24 -3
  58. package/src/modes/controllers/event-controller.ts +24 -8
  59. package/src/modes/controllers/tool-args-reveal.ts +100 -22
  60. package/src/modes/utils/transcript-render-helpers.ts +2 -2
  61. package/src/prompts/bench.md +4 -10
  62. package/src/prompts/tools/irc.md +19 -29
  63. package/src/prompts/tools/job.md +8 -14
  64. package/src/prompts/tools/lsp.md +19 -30
  65. package/src/prompts/tools/task.md +42 -62
  66. package/src/sdk.ts +13 -11
  67. package/src/session/agent-session.ts +196 -76
  68. package/src/session/messages.ts +1 -1
  69. package/src/session/session-context.ts +4 -4
  70. package/src/session/session-entries.ts +2 -2
  71. package/src/session/session-listing.ts +9 -8
  72. package/src/session/session-loader.ts +98 -3
  73. package/src/session/session-manager.ts +43 -6
  74. package/src/slash-commands/builtin-registry.ts +2 -10
  75. package/src/subprocess/worker-client.ts +12 -4
  76. package/src/system-prompt.test.ts +158 -0
  77. package/src/system-prompt.ts +69 -26
  78. package/src/task/executor.ts +23 -16
  79. package/src/task/index.ts +7 -5
  80. package/src/task/isolation-runner.ts +15 -1
  81. package/src/task/types.ts +6 -0
  82. package/src/task/worktree.ts +219 -38
  83. package/src/tiny/title-client.ts +19 -13
  84. package/src/tools/index.ts +3 -3
  85. package/src/tools/irc.ts +9 -3
  86. package/src/tools/path-utils.ts +4 -2
  87. package/src/tools/read.ts +28 -28
  88. package/src/utils/file-mentions.ts +10 -1
  89. package/src/utils/git.ts +38 -0
  90. package/src/web/search/index.ts +14 -8
  91. package/src/web/search/providers/duckduckgo.ts +150 -78
  92. package/src/web/search/providers/gemini.ts +268 -185
  93. package/src/web/search/types.ts +1 -1
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, ApiKeyResolver, AssistantMessageEventStream, Context, Model, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
2
+ import type { Api, ApiKeyResolver, AssistantMessageEventStream, Context, Model, ServiceTierByFamily, SimpleStreamOptions } from "@oh-my-pi/pi-ai";
3
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";
@@ -10,7 +10,10 @@ export interface BenchCommandArgs {
10
10
  runs?: number;
11
11
  maxTokens?: number;
12
12
  prompt?: string;
13
+ /** Service-tier setting value (`none` omits); overrides the configured `serviceTier` setting. */
14
+ serviceTier?: string;
13
15
  json?: boolean;
16
+ par?: number;
14
17
  };
15
18
  }
16
19
  export interface BenchModelRegistry {
@@ -62,6 +65,8 @@ export interface BenchSummary {
62
65
  maxTokens: number;
63
66
  models: BenchModelReport[];
64
67
  failures: number;
68
+ /** Requested per-family service tiers, resolved per model before reaching the wire. */
69
+ serviceTierByFamily?: ServiceTierByFamily;
65
70
  }
66
71
  type BenchStreamSimple = (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;
67
72
  export interface BenchDependencies {
@@ -20,9 +20,17 @@ export default class Bench extends Command {
20
20
  prompt: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
21
21
  description: string;
22
22
  };
23
+ "service-tier": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
24
+ description: string;
25
+ options: readonly ["none", "auto", "default", "flex", "scale", "priority"];
26
+ };
23
27
  json: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
24
28
  description: string;
25
29
  };
30
+ par: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"integer"> & {
31
+ description: string;
32
+ default: number;
33
+ };
26
34
  };
27
35
  static examples: string[];
28
36
  run(): Promise<void>;
@@ -37,10 +37,14 @@ export interface DiscoveryContext {
37
37
  */
38
38
  getBearerApiKeyResolver(provider: string): Promise<ApiKey | undefined>;
39
39
  }
40
+ type LlamaCppDiscoveredModelRuntimeMetadata = {
41
+ contextWindow: number;
42
+ maxTokens: number;
43
+ };
40
44
  export declare function discoverModelsByProviderType(providerConfig: DiscoveryProviderConfig, ctx: DiscoveryContext): Promise<Model<Api>[]>;
41
45
  export declare function discoverOllamaModels(providerConfig: DiscoveryProviderConfig, ctx: DiscoveryContext): Promise<Model<Api>[]>;
42
46
  export declare function discoverLlamaCppModels(providerConfig: DiscoveryProviderConfig, ctx: DiscoveryContext): Promise<Model<Api>[]>;
43
- export declare function discoverLlamaCppModelContextWindow(model: Pick<Model<Api>, "provider" | "id" | "baseUrl" | "headers">, ctx: DiscoveryContext): Promise<number | undefined>;
47
+ export declare function discoverLlamaCppModelRuntimeMetadata(model: Pick<Model<Api>, "provider" | "id" | "baseUrl" | "headers">, ctx: DiscoveryContext): Promise<LlamaCppDiscoveredModelRuntimeMetadata | undefined>;
44
48
  export declare function discoverOpenAIModelsList(providerConfig: DiscoveryProviderConfig, ctx: DiscoveryContext): Promise<Model<Api>[]>;
45
49
  export declare function discoverLiteLLMModels(providerConfig: DiscoveryProviderConfig, ctx: DiscoveryContext): Promise<Model<Api>[]>;
46
50
  /**
@@ -61,3 +65,4 @@ export declare function discoverLiteLLMModels(providerConfig: DiscoveryProviderC
61
65
  export declare function discoverProxyModels(providerConfig: DiscoveryProviderConfig, ctx: DiscoveryContext): Promise<Model<Api>[]>;
62
66
  export declare function normalizeLiteLLMDiscoveryBaseUrl(baseUrl?: string): string;
63
67
  export declare function normalizeOpenAIModelsListBaseUrl(baseUrl?: string): string;
68
+ export {};
@@ -1,34 +1,49 @@
1
- import type { ServiceTier } from "@oh-my-pi/pi-ai";
1
+ import type { ServiceTier, ServiceTierByFamily } from "@oh-my-pi/pi-ai";
2
2
  import type { SubmenuOption } from "./settings-schema";
3
3
  /**
4
- * Service-tier setting values shared by every "Service Tier" setting. `"none"`
5
- * is the omit-the-parameter sentinel; the remaining values mirror
6
- * {@link ServiceTier}.
4
+ * Per-family service-tier setting values. `"none"` is the omit-the-parameter
5
+ * sentinel; the rest mirror the wire {@link ServiceTier} values each provider
6
+ * family actually realizes. OpenAI accepts the full set; Anthropic realizes
7
+ * only `priority` (fast mode); Google (Gemini API + Vertex) realizes
8
+ * `flex`/`priority`.
7
9
  */
8
- export declare const SERVICE_TIER_SETTING_VALUES: readonly ["none", "auto", "default", "flex", "scale", "priority", "openai-only", "claude-only"];
9
- export type ServiceTierSettingValue = (typeof SERVICE_TIER_SETTING_VALUES)[number];
10
- /** Variant value set for scoped service-tier settings (subagent/advisor) that can defer to the main agent. */
11
- export declare const SERVICE_TIER_INHERIT_SETTING_VALUES: readonly ["inherit", "none", "auto", "default", "flex", "scale", "priority", "openai-only", "claude-only"];
10
+ export declare const SERVICE_TIER_OPENAI_VALUES: readonly ["none", "auto", "default", "flex", "scale", "priority"];
11
+ export declare const SERVICE_TIER_ANTHROPIC_VALUES: readonly ["none", "priority"];
12
+ export declare const SERVICE_TIER_GOOGLE_VALUES: readonly ["none", "flex", "priority"];
13
+ export type ServiceTierOpenAISettingValue = (typeof SERVICE_TIER_OPENAI_VALUES)[number];
14
+ export type ServiceTierAnthropicSettingValue = (typeof SERVICE_TIER_ANTHROPIC_VALUES)[number];
15
+ export type ServiceTierGoogleSettingValue = (typeof SERVICE_TIER_GOOGLE_VALUES)[number];
16
+ /**
17
+ * Inherit-capable single value for the subagent/advisor tiers. The chosen tier
18
+ * is broadcast across families and applied to whichever family the spawned
19
+ * model belongs to (clamped to what that family realizes); `"inherit"` defers
20
+ * to the main agent's live per-family selection.
21
+ */
22
+ export declare const SERVICE_TIER_INHERIT_SETTING_VALUES: readonly ["inherit", "none", "auto", "default", "flex", "scale", "priority"];
12
23
  export type ServiceTierInheritSettingValue = (typeof SERVICE_TIER_INHERIT_SETTING_VALUES)[number];
13
- /** Submenu descriptions shared by the base `serviceTier` setting. */
14
- export declare const SERVICE_TIER_OPTIONS: ReadonlyArray<SubmenuOption<ServiceTierSettingValue>>;
15
- /** Submenu descriptions for inherit-capable service-tier settings. */
24
+ export declare const SERVICE_TIER_OPENAI_OPTIONS: ReadonlyArray<SubmenuOption<ServiceTierOpenAISettingValue>>;
25
+ export declare const SERVICE_TIER_ANTHROPIC_OPTIONS: ReadonlyArray<SubmenuOption<ServiceTierAnthropicSettingValue>>;
26
+ export declare const SERVICE_TIER_GOOGLE_OPTIONS: ReadonlyArray<SubmenuOption<ServiceTierGoogleSettingValue>>;
16
27
  export declare const SERVICE_TIER_INHERIT_OPTIONS: ReadonlyArray<SubmenuOption<ServiceTierInheritSettingValue>>;
28
+ /** Map a per-family setting value to a wire {@link ServiceTier}, or `undefined` to omit. */
29
+ export declare function serviceTierSettingToTier(value: string): ServiceTier | undefined;
30
+ /** Assemble the live per-family tier map from the three `tier.*` setting values. */
31
+ export declare function buildServiceTierByFamily(openai: string, anthropic: string, google: string): ServiceTierByFamily;
17
32
  /**
18
- * Resolve a service-tier setting value to the wire {@link ServiceTier} (or
19
- * `undefined` to omit). `"inherit"` defers to `inherited`; `"none"` omits.
33
+ * Broadcast a single chosen tier across families, clamped to what each family
34
+ * realizes: OpenAI takes any tier, Anthropic only `priority`, Google only
35
+ * `flex`/`priority`. Used by the subagent/advisor single-value settings and the
36
+ * `omp bench --service-tier` flag, which apply one tier to whatever family the
37
+ * target model belongs to.
20
38
  */
21
- export declare function resolveServiceTierSetting(value: string, inherited: ServiceTier | undefined): ServiceTier | undefined;
39
+ export declare function serviceTierForAllFamilies(tier: ServiceTier | undefined): ServiceTierByFamily;
22
40
  /**
23
- * Resolve the `serviceTier` *setting value* to stamp onto a subagent's settings
24
- * snapshot.
41
+ * Resolve a subagent/advisor service-tier setting to a per-family map.
25
42
  *
26
- * - A concrete `subagentSetting` (`"none"` or a tier) wins outright.
27
- * - `"inherit"` defers to the parent's live effective tier when the caller has a
28
- * live session (`inherited` passed as `ServiceTier | null`, where `null` means
29
- * the parent explicitly has no tiere.g. `/fast off`). When no live session
30
- * is available (`inherited === undefined`, e.g. cold subagent revive) it falls
31
- * back to the parent's configured `serviceTier` setting so behavior matches a
32
- * plain settings snapshot.
43
+ * - A concrete tier is broadcast across families (see
44
+ * {@link serviceTierForAllFamilies}).
45
+ * - `"none"` yields an empty map.
46
+ * - `"inherit"` defers to `inherited`the parent's live per-family tiers when
47
+ * a live session supplied them, else the empty map.
33
48
  */
34
- export declare function resolveSubagentServiceTier(subagentSetting: string, configuredTier: ServiceTierSettingValue, inherited: ServiceTier | null | undefined): ServiceTierSettingValue;
49
+ export declare function resolveSubagentServiceTier(setting: string, inherited: ServiceTierByFamily): ServiceTierByFamily;
@@ -1232,65 +1232,65 @@ export declare const SETTINGS_SCHEMA: {
1232
1232
  }];
1233
1233
  };
1234
1234
  };
1235
- readonly serviceTier: {
1235
+ readonly "tier.openai": {
1236
1236
  readonly type: "enum";
1237
- readonly values: readonly ["none", "auto", "default", "flex", "scale", "priority", "openai-only", "claude-only"];
1237
+ readonly values: readonly ["none", "auto", "default", "flex", "scale", "priority"];
1238
1238
  readonly default: "none";
1239
1239
  readonly ui: {
1240
1240
  readonly tab: "model";
1241
1241
  readonly group: "Sampling";
1242
- readonly label: "Service Tier";
1243
- readonly description: 'Processing priority hint (none = omit). OpenAI accepts the tier values directly; Anthropic realizes `priority` as `speed: "fast"` on supported Opus models. Scoped values target one family.';
1244
- readonly options: readonly SubmenuOption<"auto" | "claude-only" | "default" | "flex" | "none" | "openai-only" | "priority" | "scale">[];
1242
+ readonly label: "Service Tier — OpenAI";
1243
+ readonly description: "Processing tier for OpenAI / OpenAI-Codex requests, and OpenAI-family models routed via OpenRouter (none = omit). Sent as `service_tier`.";
1244
+ readonly options: readonly SubmenuOption<"auto" | "default" | "flex" | "none" | "priority" | "scale">[];
1245
1245
  };
1246
1246
  };
1247
- readonly serviceTierSubagent: {
1247
+ readonly "tier.anthropic": {
1248
1248
  readonly type: "enum";
1249
- readonly values: readonly ["inherit", "none", "auto", "default", "flex", "scale", "priority", "openai-only", "claude-only"];
1250
- readonly default: "inherit";
1249
+ readonly values: readonly ["none", "priority"];
1250
+ readonly default: "none";
1251
1251
  readonly ui: {
1252
1252
  readonly tab: "model";
1253
1253
  readonly group: "Sampling";
1254
- readonly label: "Service Tier - Subagent";
1255
- readonly description: "Service Tier for spawned task/eval subagents. Inherit = match the main agent's live tier (tracks /fast); pick a value to scope subagents independently.";
1256
- readonly options: readonly SubmenuOption<"auto" | "claude-only" | "default" | "flex" | "inherit" | "none" | "openai-only" | "priority" | "scale">[];
1254
+ readonly label: "Service Tier Anthropic";
1255
+ readonly description: 'Processing tier for Claude requests. `priority` realizes fast mode (`speed: "fast"`) on supported direct Anthropic models; ignored on Bedrock/Vertex Claude and via OpenRouter.';
1256
+ readonly options: readonly SubmenuOption<"none" | "priority">[];
1257
1257
  };
1258
1258
  };
1259
- readonly serviceTierAdvisor: {
1259
+ readonly "tier.google": {
1260
1260
  readonly type: "enum";
1261
- readonly values: readonly ["inherit", "none", "auto", "default", "flex", "scale", "priority", "openai-only", "claude-only"];
1261
+ readonly values: readonly ["none", "flex", "priority"];
1262
1262
  readonly default: "none";
1263
1263
  readonly ui: {
1264
1264
  readonly tab: "model";
1265
1265
  readonly group: "Sampling";
1266
- readonly label: "Service Tier - Advisor";
1267
- readonly description: "Service Tier for the advisor model. None = standard processing; Inherit = match the main agent's live tier; pick a value (e.g. Priority) to run the advisor on a faster serving path.";
1268
- readonly options: readonly SubmenuOption<"auto" | "claude-only" | "default" | "flex" | "inherit" | "none" | "openai-only" | "priority" | "scale">[];
1269
- readonly condition: "advisorEnabled";
1266
+ readonly label: "Service Tier Google";
1267
+ readonly description: "Processing tier for Gemini (Google AI Studio + Vertex) requests, and Google-family models routed via OpenRouter (none = omit). Sent as the top-level `serviceTier` field.";
1268
+ readonly options: readonly SubmenuOption<"flex" | "none" | "priority">[];
1270
1269
  };
1271
1270
  };
1272
- readonly fastModeScope: {
1271
+ readonly "tier.subagent": {
1273
1272
  readonly type: "enum";
1274
- readonly values: readonly ["both", "openai", "claude"];
1275
- readonly default: "both";
1273
+ readonly values: readonly ["inherit", "none", "auto", "default", "flex", "scale", "priority"];
1274
+ readonly default: "inherit";
1276
1275
  readonly ui: {
1277
1276
  readonly tab: "model";
1278
1277
  readonly group: "Sampling";
1279
- readonly label: "Fast Mode Scope";
1280
- readonly description: 'Which providers `/fast on` (and the fast-mode toggle) target. "both" = priority on every supported provider; "openai"/"claude" scope it to one family (mirrors serviceTier openai-only/claude-only).';
1281
- readonly options: readonly [{
1282
- readonly value: "both";
1283
- readonly label: "Both";
1284
- readonly description: "Priority on every supported provider";
1285
- }, {
1286
- readonly value: "openai";
1287
- readonly label: "OpenAI only";
1288
- readonly description: "Priority on OpenAI/OpenAI-Codex requests; ignored elsewhere";
1289
- }, {
1290
- readonly value: "claude";
1291
- readonly label: "Claude only";
1292
- readonly description: "Anthropic fast mode on direct Claude requests; ignored elsewhere";
1293
- }];
1278
+ readonly label: "Service Tier — Subagent";
1279
+ readonly description: "Service Tier for spawned task/eval subagents. Inherit = match the main agent's live per-family tiers (tracks /fast); pick a value to apply it to whichever family the subagent's model belongs to.";
1280
+ readonly options: readonly SubmenuOption<"auto" | "default" | "flex" | "inherit" | "none" | "priority" | "scale">[];
1281
+ };
1282
+ };
1283
+ readonly "tier.advisor": {
1284
+ readonly type: "enum";
1285
+ readonly values: readonly ["inherit", "none", "auto", "default", "flex", "scale", "priority"];
1286
+ readonly default: "none";
1287
+ readonly ui: {
1288
+ readonly tab: "model";
1289
+ readonly group: "Sampling";
1290
+ readonly label: "Service Tier — Advisor";
1291
+ readonly description: "Service Tier for the advisor model. None = standard processing; Inherit = match the main agent's live per-family tiers; pick a value to apply it to the advisor model's family.";
1292
+ readonly options: readonly SubmenuOption<"auto" | "default" | "flex" | "inherit" | "none" | "priority" | "scale">[];
1293
+ readonly condition: "advisorEnabled";
1294
1294
  };
1295
1295
  };
1296
1296
  readonly "retry.enabled": {
@@ -2228,7 +2228,7 @@ export declare const SETTINGS_SCHEMA: {
2228
2228
  };
2229
2229
  readonly "snapcompact.shape": {
2230
2230
  readonly type: "enum";
2231
- readonly values: readonly ["auto", ...("11on16-bw" | "5x8-bw" | "5x8-sent" | "6x12-dim" | "6x6u-bw" | "6x6u-sent" | "8on16-bw" | "8on22-bw" | "8x13-bw" | "8x8r-bw" | "8x8r-sent" | "8x8u-bw" | "8x8u-sent" | "doc-8on16-bw" | "doc-8on16-sent" | "doc-8on16-sent-dim")[]];
2231
+ readonly values: readonly ["auto", ...("11on16-bw" | "5x8-bw" | "5x8-sent" | "6x12-dim" | "6x6u-bw" | "6x6u-sent" | "8on16-bw" | "8on22-bw" | "8x13-bw" | "8x8r-bw" | "8x8r-sent" | "8x8u-bw" | "8x8u-sent" | "doc-8on16-bw" | "doc-8on16-sent" | "doc-8on16-sent-dim" | "silver16-bw")[]];
2232
2232
  readonly default: "auto";
2233
2233
  readonly ui: {
2234
2234
  readonly tab: "context";
@@ -4494,7 +4494,7 @@ export declare const SETTINGS_SCHEMA: {
4494
4494
  }, {
4495
4495
  readonly value: "duckduckgo";
4496
4496
  readonly label: "DuckDuckGo";
4497
- readonly description: "Uses DuckDuckGo Instant Answer API (no API key)";
4497
+ readonly description: "Scrapes the DuckDuckGo HTML frontend (no API key)";
4498
4498
  }];
4499
4499
  };
4500
4500
  };
@@ -18,6 +18,7 @@ export * from "./modes/patch";
18
18
  export * from "./modes/replace";
19
19
  export * from "./normalize";
20
20
  export * from "./renderer";
21
+ export * from "./snapshot-details";
21
22
  export * from "./streaming";
22
23
  type TInput = typeof replaceEditSchema | typeof patchEditSchema | typeof hashlineEditParamsSchema | typeof applyPatchSchema;
23
24
  type HashlineParams = typeof hashlineEditParamsSchema.infer;
@@ -29,6 +29,8 @@ export interface EditToolPerFileResult {
29
29
  oldText?: string;
30
30
  /** Source-of-truth content after the edit; `undefined` for delete operations. */
31
31
  newText?: string;
32
+ /** True when {@link pruneOversizedEditSnapshots} dropped `oldText`/`newText` from this entry. Aggregators check this to suppress misleading combined snapshots when at least one entry of a multi-entry single-path edit was pruned. */
33
+ snapshotsPruned?: boolean;
32
34
  /** Pre-move source path; set only when the edit moved/renamed the file. The header renders `sourcePath → path`. */
33
35
  sourcePath?: string;
34
36
  }
@@ -53,6 +55,8 @@ export interface EditToolDetails {
53
55
  oldText?: string;
54
56
  /** Source-of-truth content after the edit; `undefined` for delete operations. */
55
57
  newText?: string;
58
+ /** True when {@link pruneOversizedEditSnapshots} dropped `oldText`/`newText` from this entry. Aggregators check this to suppress misleading combined snapshots when at least one entry of a multi-entry single-path edit was pruned. */
59
+ snapshotsPruned?: boolean;
56
60
  /** Pre-move source path; set only when the edit moved/renamed the file. The header renders `sourcePath → path`. */
57
61
  sourcePath?: string;
58
62
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Bound the size of the `oldText` / `newText` snapshots that edit-tool results
3
+ * carry in `details`. These fields hold the full pre/post file content; for
4
+ * large files they balloon the per-turn JSONL line and the session file
5
+ * (300 KB+ each on the cases reported in #3786) without paying for any LLM
6
+ * context (provider serializers send only `content`, never `details`).
7
+ *
8
+ * Only consumer of the raw snapshots is the ACP event mapper, which builds a
9
+ * `diff` ToolCallContent for ACP clients (Zed). When the snapshots are pruned
10
+ * the mapper returns `undefined` for that file and the text content still
11
+ * flows — diff visualization degrades gracefully for over-threshold edits.
12
+ */
13
+ import type { EditToolDetails, EditToolPerFileResult } from "./renderer";
14
+ /**
15
+ * Combined `oldText` + `newText` character budget for a single edit-tool
16
+ * result. Applies both per-entry (one file at a time) and as an aggregate
17
+ * across `perFileResults` (so a many-small-files batch can't accumulate
18
+ * unbounded snapshot bytes — see #3787 review).
19
+ *
20
+ * Picked so typical code-file edits keep ACP diff visualization while
21
+ * pathological cases (large generated files, full-file rewrites, or
22
+ * many-file batches) drop the raw snapshots before they hit the
23
+ * session JSONL.
24
+ */
25
+ export declare const MAX_EDIT_SNAPSHOT_TEXT_CHARS = 32768;
26
+ /**
27
+ * Prune oversized `oldText` / `newText` from an edit-tool details payload,
28
+ * recursing into `perFileResults` when present. Per-file overload comes first
29
+ * so the more specific shape (required `path`) wins overload resolution at
30
+ * the per-file call sites.
31
+ */
32
+ export declare function pruneOversizedEditSnapshots(details: EditToolPerFileResult): EditToolPerFileResult;
33
+ export declare function pruneOversizedEditSnapshots(details: EditToolDetails): EditToolDetails;
@@ -51,3 +51,51 @@ export declare function readDisabledServers(filePath: string): Promise<string[]>
51
51
  * Add or remove a server name from the disabled servers list.
52
52
  */
53
53
  export declare function setServerDisabled(filePath: string, name: string, disabled: boolean): Promise<void>;
54
+ /**
55
+ * Read the user-level force-enable list (allowlist that overrides a
56
+ * non-writable source config's `enabled: false`).
57
+ */
58
+ export declare function readEnabledServers(filePath: string): Promise<string[]>;
59
+ /**
60
+ * Add or remove a server name from the user-level force-enable list.
61
+ * The list overrides a discovered server's `enabled: false` flag but does
62
+ * NOT override the `disabledServers` denylist.
63
+ */
64
+ export declare function setServerForceEnabled(filePath: string, name: string, force: boolean): Promise<void>;
65
+ /** Paths and target state for toggling one MCP server across known config files. */
66
+ export interface SetMcpServerEnabledOptions {
67
+ userPath: string;
68
+ projectPath: string;
69
+ /**
70
+ * Absolute path to the loaded row's source mcp.json. Provide ONLY for
71
+ * formats this codebase owns (native `.omp/mcp.json` and `mcp-json`
72
+ * `mcp.json`/`.mcp.json`). Tool-owned configs (opencode.json, claude.json,
73
+ * settings.json …) MUST be omitted; we never mutate another tool's file.
74
+ */
75
+ sourcePath?: string;
76
+ name: string;
77
+ enabled: boolean;
78
+ }
79
+ /**
80
+ * Flip a server's enabled/disabled state regardless of where it lives.
81
+ *
82
+ * Resolution order, mirroring `/mcp enable` / `/mcp disable` plus the dashboard
83
+ * fix for non-writable source configs:
84
+ *
85
+ * - Server found in `sourcePath` (writable) → write `enabled` on that entry.
86
+ * - Else server in project mcp.json → write `enabled` there.
87
+ * - Else server in user mcp.json → write `enabled` there.
88
+ * - Else (server defined in a tool-owned source like opencode.json, OR a
89
+ * purely discovered server):
90
+ * - Disable → add to the user-level `disabledServers` denylist.
91
+ * - Enable → add to the user-level `enabledServers` allowlist so the
92
+ * dashboard / runtime override the non-writable source's
93
+ * `enabled: false` flag.
94
+ *
95
+ * Cleanup invariants — on every call:
96
+ * - Re-enable clears any stale denylist entry so a server disabled via
97
+ * `/mcp disable` and re-enabled here doesn't stay suppressed.
98
+ * - Disable clears any stale allowlist entry so re-disabling a
99
+ * force-enabled server actually takes effect.
100
+ */
101
+ export declare function setMcpServerEnabled(options: SetMcpServerEnabledOptions): Promise<void>;
@@ -59,12 +59,10 @@ export interface MCPOAuthConfig {
59
59
  /** OAuth scopes (space-separated) */
60
60
  scopes?: string;
61
61
  /**
62
- * `prompt` parameter for the authorization request. Defaults to `"consent"`
63
- * so the provider always shows its authorize screen instead of silently
64
- * re-approving the browser's current session without it, reauthorizing to
65
- * switch accounts/workspaces is impossible once a session cookie exists
66
- * (RFC 6749 §3.1 requires servers to ignore the param when unsupported).
67
- * Set to `""` to omit the parameter entirely.
62
+ * `prompt` parameter for the authorization request. By default the parameter
63
+ * is omitted, matching the reference MCP SDK, except for `offline_access`
64
+ * requests where OIDC Core requires `prompt=consent` to issue refresh-token
65
+ * access. Set to `""` to omit the parameter entirely.
68
66
  */
69
67
  prompt?: string;
70
68
  /** Exact redirect URI to advertise to the provider */
@@ -88,7 +88,10 @@ export declare const MCP_CONFIG_SCHEMA_URL = "https://raw.githubusercontent.com/
88
88
  export interface MCPConfigFile {
89
89
  $schema?: string;
90
90
  mcpServers?: Record<string, MCPServerConfig>;
91
+ /** Names to hide regardless of any source `enabled` flag. Highest precedence. */
91
92
  disabledServers?: string[];
93
+ /** Names to force-enable when a non-writable source reports `enabled: false`. */
94
+ enabledServers?: string[];
92
95
  }
93
96
  /** MCP implementation info */
94
97
  export interface MCPImplementation {
@@ -6,13 +6,20 @@ type ToolArgsRevealControllerOptions = {
6
6
  getSmoothStreaming(): boolean;
7
7
  requestRender(): void;
8
8
  };
9
+ type ToolArgsRevealTarget = {
10
+ rawInput: boolean;
11
+ exposeRawPartialJson: boolean;
12
+ fullArgs: Record<string, unknown>;
13
+ };
9
14
  /**
10
15
  * Paces streamed tool-call arguments the same way StreamingRevealController
11
16
  * paces assistant text: providers that deliver `partialJson` in large batches
12
17
  * (or throttle their partial parses) would otherwise make write/edit/bash
13
18
  * streaming previews jump in chunks. Each pending tool call reveals its raw
14
19
  * argument stream at the shared 30fps cadence with the same adaptive
15
- * catch-up step, re-parsing the revealed prefix per frame.
20
+ * catch-up step. JSON prefixes are parsed only when enough new bytes arrive to
21
+ * change renderer-visible fields, while raw-prefix consumers still receive
22
+ * fresh `__partialJson` on every reveal frame.
16
23
  *
17
24
  * Reveal units are UTF-16 code units of the raw stream, not graphemes —
18
25
  * the prefix goes through a JSON parser rather than straight to the screen,
@@ -26,7 +33,7 @@ export declare class ToolArgsRevealController {
26
33
  * args to render right now. With smoothing disabled the full target passes
27
34
  * through in the caller's legacy shape (`{ ...args, __partialJson }`).
28
35
  */
29
- setTarget(id: string, partialJson: string, rawInput: boolean, fullArgs: Record<string, unknown>): Record<string, unknown>;
36
+ setTarget(id: string, partialJson: string, target: ToolArgsRevealTarget): Record<string, unknown>;
30
37
  /** Attach the component future ticks push frames into. */
31
38
  bind(id: string, component: ToolArgsRevealComponent): void;
32
39
  /** Final arguments arrived (the JSON closed): drop the reveal so the
@@ -15,7 +15,7 @@
15
15
  import type { InMemorySnapshotStore } from "@oh-my-pi/hashline";
16
16
  import { Agent, type AgentEvent, type AgentMessage, type AgentState, type AgentTool, type StreamFn, ThinkingLevel, type ToolChoiceDirective } from "@oh-my-pi/pi-agent-core";
17
17
  import { type CompactionResult, type ShakeConfig } from "@oh-my-pi/pi-agent-core/compaction";
18
- import type { AssistantMessage, Context, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ResetCreditAccountStatus, ResetCreditRedeemOutcome, ResetCreditTarget, ServiceTier, SimpleStreamOptions, TextContent, ToolChoice, UsageReport } from "@oh-my-pi/pi-ai";
18
+ import type { AssistantMessage, Context, ImageContent, Message, MessageAttribution, Model, ProviderSessionState, ResetCreditAccountStatus, ResetCreditRedeemOutcome, ResetCreditTarget, ServiceTier, ServiceTierByFamily, ServiceTierFamily, SimpleStreamOptions, TextContent, ToolChoice, UsageReport } from "@oh-my-pi/pi-ai";
19
19
  import { Effort } from "@oh-my-pi/pi-ai";
20
20
  import { type AdvisorConfig } from "../advisor";
21
21
  import { type AsyncJob, type AsyncJobDeliveryState, AsyncJobManager } from "../async";
@@ -141,6 +141,8 @@ export interface AgentSessionConfig {
141
141
  }>;
142
142
  /** Initial session thinking selector. */
143
143
  thinkingLevel?: ConfiguredThinkingLevel;
144
+ /** Initial per-family service tiers (OpenAI / Anthropic / Google) for the live session. */
145
+ serviceTierByFamily?: ServiceTierByFamily;
144
146
  /** Prompt templates for expansion */
145
147
  promptTemplates?: PromptTemplate[];
146
148
  /** File-based slash commands for expansion */
@@ -184,6 +186,8 @@ export interface AgentSessionConfig {
184
186
  * main agent. Defaults to plain `streamSimple` when omitted.
185
187
  */
186
188
  advisorStreamFn?: StreamFn;
189
+ /** Hint that OpenAI Codex requests should prefer websocket transport when supported. */
190
+ preferWebsockets?: boolean;
187
191
  /** Provider payload hook used by the active session request path */
188
192
  onPayload?: SimpleStreamOptions["onPayload"];
189
193
  /** Provider response hook used by the active session request path */
@@ -470,6 +474,8 @@ export declare class AgentSession {
470
474
  setSessionSwitchReconciler(reconciler: (() => Promise<void>) | null): void;
471
475
  /** Provider-scoped mutable state store for transport/session caches. */
472
476
  get providerSessionState(): Map<string, ProviderSessionState>;
477
+ /** Hint forwarded to provider calls that support websocket transport. */
478
+ get preferWebsockets(): boolean | undefined;
473
479
  getHindsightSessionState(): HindsightSessionState | undefined;
474
480
  setHindsightSessionState(state: HindsightSessionState | undefined): HindsightSessionState | undefined;
475
481
  getMnemopiSessionState(): MnemopiSessionState | undefined;
@@ -542,7 +548,8 @@ export declare class AgentSession {
542
548
  get isAutoThinking(): boolean;
543
549
  /** The level `auto` resolved to for the current turn (undefined until classified). */
544
550
  autoResolvedThinkingLevel(): Effort | undefined;
545
- get serviceTier(): ServiceTier | undefined;
551
+ /** Live per-family service tiers (OpenAI / Anthropic / Google). */
552
+ get serviceTierByFamily(): ServiceTierByFamily;
546
553
  /** Whether agent is currently streaming a response */
547
554
  get isStreaming(): boolean;
548
555
  get isAborting(): boolean;
@@ -915,23 +922,29 @@ export declare class AgentSession {
915
922
  */
916
923
  cycleThinkingLevel(): ConfiguredThinkingLevel | undefined;
917
924
  /**
918
- * True when *any* fast-mode-granting service tier is configured, regardless
919
- * of whether the active model's provider actually realizes it. Used by the
920
- * toggle (`/fast on|off`) so re-toggling a scoped tier (`openai-only`,
921
- * `claude-only`) doesn't silently broaden it to unscoped `priority`.
925
+ * True when the currently selected model's family is set to `priority` — the
926
+ * `/fast` on/off state for the active model. Returns false when no model is
927
+ * selected or the model exposes no service-tier family (e.g. Fireworks, which
928
+ * has its own Providers Fireworks Tier toggle).
922
929
  *
923
- * For "is fast mode actually applied to the next request?" use
924
- * {@link isFastModeActive} instead — that one respects the model's provider.
930
+ * For "is priority actually applied to the next request?" use
931
+ * {@link isFastModeActive} instead.
925
932
  */
926
933
  isFastModeEnabled(): boolean;
927
934
  /**
928
- * True when the configured `serviceTier` resolves to `"priority"` for the
929
- * *currently selected model's provider*. Returns false for scoped tiers
930
- * that don't match (e.g. `"openai-only"` on an anthropic model) and when
931
- * no model is selected.
935
+ * True when `priority` is actually realized on the wire for the currently
936
+ * selected model (OpenAI/Google `service_tier`, direct Anthropic fast mode,
937
+ * or Fireworks priority). Returns false for tiers the active model can't
938
+ * realize and when no model is selected.
932
939
  */
933
940
  isFastModeActive(): boolean;
934
- setServiceTier(serviceTier: ServiceTier | undefined): void;
941
+ /** Set one family's tier (or clear it with `undefined`); persists the change. */
942
+ setServiceTierFamily(family: ServiceTierFamily, tier: ServiceTier | undefined): void;
943
+ /**
944
+ * `/fast on|off` targets the family of the currently selected model: it sets
945
+ * (or clears) that family's `priority` tier. Models without a service-tier
946
+ * family (Fireworks, or providers with no tier knob) have nothing to toggle.
947
+ */
935
948
  setFastMode(enabled: boolean): void;
936
949
  toggleFastMode(): boolean;
937
950
  /**
@@ -1098,6 +1111,17 @@ export declare class AgentSession {
1098
1111
  get isEvalRunning(): boolean;
1099
1112
  /** Whether there are pending Python messages waiting to be flushed */
1100
1113
  get hasPendingPythonMessages(): boolean;
1114
+ /**
1115
+ * Surfaces (and consumes) IRC incoming asides that have reached this running
1116
+ * session but have not yet been folded into the next model step.
1117
+ *
1118
+ * The inbox tool injects the formatted body into the tool result, so the
1119
+ * model sees it once via the result. Leaving the record in
1120
+ * {@link #pendingIrcAsides} would let the aside provider deliver it a second
1121
+ * time at the next step boundary — including on `peek`, which is why peek
1122
+ * also drains here.
1123
+ */
1124
+ drainPendingIrcInboxMessages(agentId: string): IrcMessage[];
1101
1125
  /**
1102
1126
  * Deliver an IRC message into this session (recipient side; called by the
1103
1127
  * IrcBus). Emits the `irc_message` session event for UI cards and injects
@@ -184,7 +184,7 @@ export interface FileMentionMessage {
184
184
  /** File size in bytes, if known. */
185
185
  byteSize?: number;
186
186
  /** Why the file contents were omitted from auto-read. */
187
- skippedReason?: "tooLarge";
187
+ skippedReason?: "tooLarge" | "binary";
188
188
  image?: ImageContent;
189
189
  }>;
190
190
  timestamp: number;
@@ -1,12 +1,12 @@
1
1
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
2
- import type { ServiceTier } from "@oh-my-pi/pi-ai";
2
+ import { type ServiceTierByFamily } from "@oh-my-pi/pi-ai";
3
3
  import { type CompactionEntry, type SessionEntry } from "./session-entries";
4
4
  export interface SessionContext {
5
5
  messages: AgentMessage[];
6
6
  thinkingLevel?: string;
7
7
  /** Configured thinking selector (`"auto"` or a concrete level) from the latest change. */
8
8
  configuredThinkingLevel?: string;
9
- serviceTier?: ServiceTier;
9
+ serviceTier?: ServiceTierByFamily;
10
10
  /** Model roles: { default: "provider/modelId", small: "provider/modelId", ... } */
11
11
  models: Record<string, string>;
12
12
  /** Names of TTSR rules that have been injected this session */
@@ -1,5 +1,5 @@
1
1
  import type { AgentMessage } from "@oh-my-pi/pi-agent-core";
2
- import type { ImageContent, MessageAttribution, ServiceTier, TextContent } from "@oh-my-pi/pi-ai";
2
+ import type { ImageContent, MessageAttribution, ServiceTierByFamily, TextContent } from "@oh-my-pi/pi-ai";
3
3
  export declare const CURRENT_SESSION_VERSION = 3;
4
4
  export declare const SESSION_TITLE_SLOT_BYTES = 256;
5
5
  export declare const SESSION_TITLE_SLOT_ENTRY_TYPE = "title";
@@ -59,7 +59,7 @@ export interface ModelChangeEntry extends SessionEntryBase {
59
59
  }
60
60
  export interface ServiceTierChangeEntry extends SessionEntryBase {
61
61
  type: "service_tier_change";
62
- serviceTier: ServiceTier | null;
62
+ serviceTier: ServiceTierByFamily | null;
63
63
  }
64
64
  export interface CompactionEntry<T = unknown> extends SessionEntryBase {
65
65
  type: "compaction";