@oh-my-pi/pi-coding-agent 16.2.6 → 16.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (78) hide show
  1. package/CHANGELOG.md +46 -0
  2. package/dist/cli.js +2781 -2660
  3. package/dist/types/cli/bench-cli.d.ts +3 -3
  4. package/dist/types/commands/bench.d.ts +1 -1
  5. package/dist/types/config/service-tier.d.ts +39 -24
  6. package/dist/types/config/settings-schema.d.ts +92 -36
  7. package/dist/types/edit/hashline/filesystem.d.ts +1 -0
  8. package/dist/types/mcp/config-writer.d.ts +48 -0
  9. package/dist/types/mcp/types.d.ts +3 -0
  10. package/dist/types/session/agent-session.d.ts +33 -13
  11. package/dist/types/session/messages.d.ts +1 -1
  12. package/dist/types/session/session-context.d.ts +2 -7
  13. package/dist/types/session/session-entries.d.ts +2 -2
  14. package/dist/types/session/session-manager.d.ts +2 -2
  15. package/dist/types/session/settings-stream-fn.d.ts +2 -2
  16. package/dist/types/system-prompt.test.d.ts +1 -0
  17. package/dist/types/task/executor.d.ts +6 -6
  18. package/dist/types/task/types.d.ts +6 -0
  19. package/dist/types/task/worktree.d.ts +32 -6
  20. package/dist/types/tiny/title-client.d.ts +5 -1
  21. package/dist/types/tools/index.d.ts +3 -3
  22. package/dist/types/tools/output-schema-validator.d.ts +10 -0
  23. package/dist/types/utils/git.d.ts +17 -0
  24. package/package.json +12 -12
  25. package/src/cli/bench-cli.ts +19 -12
  26. package/src/cli/tiny-models-cli.ts +18 -4
  27. package/src/commands/bench.ts +3 -3
  28. package/src/config/mcp-schema.json +10 -1
  29. package/src/config/service-tier.ts +85 -56
  30. package/src/config/settings-schema.ts +81 -37
  31. package/src/config/settings.ts +47 -0
  32. package/src/discovery/builtin-rules/go-add-cleanup.md +32 -0
  33. package/src/discovery/builtin-rules/go-bench-loop.md +36 -0
  34. package/src/discovery/builtin-rules/go-exp-promoted.md +39 -0
  35. package/src/discovery/builtin-rules/go-ioutil.md +36 -0
  36. package/src/discovery/builtin-rules/go-join-hostport.md +29 -0
  37. package/src/discovery/builtin-rules/go-new-expr.md +44 -0
  38. package/src/discovery/builtin-rules/go-rand-v2.md +40 -0
  39. package/src/discovery/builtin-rules/go-range-int.md +45 -0
  40. package/src/discovery/builtin-rules/index.ts +16 -0
  41. package/src/edit/hashline/filesystem.ts +12 -0
  42. package/src/eval/agent-bridge.ts +4 -2
  43. package/src/internal-urls/docs-index.generated.txt +1 -1
  44. package/src/main.ts +1 -1
  45. package/src/mcp/config-writer.ts +121 -0
  46. package/src/mcp/config.ts +10 -6
  47. package/src/mcp/types.ts +3 -0
  48. package/src/modes/components/extensions/extension-dashboard.ts +46 -0
  49. package/src/modes/components/extensions/state-manager.ts +24 -3
  50. package/src/modes/controllers/event-controller.ts +7 -0
  51. package/src/modes/controllers/tool-args-reveal.ts +1 -1
  52. package/src/modes/utils/transcript-render-helpers.ts +2 -2
  53. package/src/prompts/tools/bash.md +1 -4
  54. package/src/sdk.ts +12 -11
  55. package/src/session/agent-session.ts +294 -82
  56. package/src/session/messages.ts +1 -1
  57. package/src/session/session-context.ts +17 -6
  58. package/src/session/session-entries.ts +2 -2
  59. package/src/session/session-manager.ts +9 -2
  60. package/src/session/settings-stream-fn.ts +12 -2
  61. package/src/slash-commands/builtin-registry.ts +2 -10
  62. package/src/system-prompt.test.ts +158 -0
  63. package/src/system-prompt.ts +69 -26
  64. package/src/task/executor.ts +23 -16
  65. package/src/task/index.ts +7 -5
  66. package/src/task/isolation-runner.ts +15 -1
  67. package/src/task/types.ts +6 -0
  68. package/src/task/worktree.ts +219 -38
  69. package/src/tiny/title-client.ts +19 -13
  70. package/src/tools/grep.ts +19 -1
  71. package/src/tools/index.ts +3 -3
  72. package/src/tools/irc.ts +9 -3
  73. package/src/tools/output-schema-validator.ts +38 -0
  74. package/src/tools/read.ts +28 -28
  75. package/src/tools/yield.ts +52 -15
  76. package/src/utils/file-mentions.ts +10 -1
  77. package/src/utils/git.ts +38 -0
  78. package/src/web/search/providers/duckduckgo.ts +17 -3
@@ -1,5 +1,5 @@
1
1
  import type { ResolvedThinkingLevel } from "@oh-my-pi/pi-agent-core";
2
- import type { Api, ApiKeyResolver, AssistantMessageEventStream, Context, Model, ServiceTier, 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";
@@ -65,8 +65,8 @@ export interface BenchSummary {
65
65
  maxTokens: number;
66
66
  models: BenchModelReport[];
67
67
  failures: number;
68
- /** Requested service tier passed to every request; absent when none was requested. Scoped tiers (`openai-only`/`claude-only`) may be dropped per-provider downstream. */
69
- serviceTier?: ServiceTier;
68
+ /** Requested per-family service tiers, resolved per model before reaching the wire. */
69
+ serviceTierByFamily?: ServiceTierByFamily;
70
70
  }
71
71
  type BenchStreamSimple = (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;
72
72
  export interface BenchDependencies {
@@ -22,7 +22,7 @@ export default class Bench extends Command {
22
22
  };
23
23
  "service-tier": import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"string"> & {
24
24
  description: string;
25
- options: readonly ["none", "auto", "default", "flex", "scale", "priority", "openai-only", "claude-only"];
25
+ options: readonly ["none", "auto", "default", "flex", "scale", "priority"];
26
26
  };
27
27
  json: import("@oh-my-pi/pi-utils/cli").FlagDescriptor<"boolean"> & {
28
28
  description: string;
@@ -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";
@@ -4962,6 +4962,62 @@ export declare const SETTINGS_SCHEMA: {
4962
4962
  }];
4963
4963
  };
4964
4964
  };
4965
+ readonly "providers.streamFirstEventTimeoutSeconds": {
4966
+ readonly type: "number";
4967
+ readonly default: -1;
4968
+ readonly ui: {
4969
+ readonly tab: "providers";
4970
+ readonly group: "Timeouts";
4971
+ readonly label: "Stream First Event Timeout";
4972
+ readonly description: "Seconds to wait for the first model stream event; -1 uses provider/env defaults, 0 disables the watchdog";
4973
+ readonly options: readonly [{
4974
+ readonly value: "-1";
4975
+ readonly label: "Auto";
4976
+ readonly description: "Use provider defaults and PI_* timeout env vars";
4977
+ }, {
4978
+ readonly value: "0";
4979
+ readonly label: "Off";
4980
+ readonly description: "Disable first-event timeout";
4981
+ }, {
4982
+ readonly value: "300";
4983
+ readonly label: "5 minutes";
4984
+ }, {
4985
+ readonly value: "600";
4986
+ readonly label: "10 minutes";
4987
+ }, {
4988
+ readonly value: "1800";
4989
+ readonly label: "30 minutes";
4990
+ }];
4991
+ };
4992
+ };
4993
+ readonly "providers.streamIdleTimeoutSeconds": {
4994
+ readonly type: "number";
4995
+ readonly default: -1;
4996
+ readonly ui: {
4997
+ readonly tab: "providers";
4998
+ readonly group: "Timeouts";
4999
+ readonly label: "Stream Idle Timeout";
5000
+ readonly description: "Seconds a model stream may stay silent between events; -1 uses provider/env defaults, 0 disables the watchdog";
5001
+ readonly options: readonly [{
5002
+ readonly value: "-1";
5003
+ readonly label: "Auto";
5004
+ readonly description: "Use provider defaults and PI_* timeout env vars";
5005
+ }, {
5006
+ readonly value: "0";
5007
+ readonly label: "Off";
5008
+ readonly description: "Disable idle timeout";
5009
+ }, {
5010
+ readonly value: "300";
5011
+ readonly label: "5 minutes";
5012
+ }, {
5013
+ readonly value: "600";
5014
+ readonly label: "10 minutes";
5015
+ }, {
5016
+ readonly value: "1800";
5017
+ readonly label: "30 minutes";
5018
+ }];
5019
+ };
5020
+ };
4965
5021
  readonly "providers.openrouterVariant": {
4966
5022
  readonly type: "enum";
4967
5023
  readonly values: readonly ["default", "nitro", "floor", "online", "exacto"];
@@ -34,6 +34,7 @@ export declare class HashlineFilesystem extends Filesystem {
34
34
  canonicalPath(relativePath: string): string;
35
35
  allowTagPathRecovery(authoredPath: string, resolvedPath: string): boolean;
36
36
  readText(relativePath: string): Promise<string>;
37
+ readBinary(relativePath: string): Promise<Uint8Array | undefined>;
37
38
  preflightWrite(relativePath: string, options?: PreflightWriteOptions): Promise<void>;
38
39
  delete(relativePath: string): Promise<void>;
39
40
  move(fromRelative: string, toRelative: string, content?: string): Promise<void>;
@@ -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>;
@@ -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 {
@@ -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 */
@@ -546,7 +548,8 @@ export declare class AgentSession {
546
548
  get isAutoThinking(): boolean;
547
549
  /** The level `auto` resolved to for the current turn (undefined until classified). */
548
550
  autoResolvedThinkingLevel(): Effort | undefined;
549
- get serviceTier(): ServiceTier | undefined;
551
+ /** Live per-family service tiers (OpenAI / Anthropic / Google). */
552
+ get serviceTierByFamily(): ServiceTierByFamily;
550
553
  /** Whether agent is currently streaming a response */
551
554
  get isStreaming(): boolean;
552
555
  get isAborting(): boolean;
@@ -919,23 +922,29 @@ export declare class AgentSession {
919
922
  */
920
923
  cycleThinkingLevel(): ConfiguredThinkingLevel | undefined;
921
924
  /**
922
- * True when *any* fast-mode-granting service tier is configured, regardless
923
- * of whether the active model's provider actually realizes it. Used by the
924
- * toggle (`/fast on|off`) so re-toggling a scoped tier (`openai-only`,
925
- * `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).
926
929
  *
927
- * For "is fast mode actually applied to the next request?" use
928
- * {@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.
929
932
  */
930
933
  isFastModeEnabled(): boolean;
931
934
  /**
932
- * True when the configured `serviceTier` resolves to `"priority"` for the
933
- * *currently selected model's provider*. Returns false for scoped tiers
934
- * that don't match (e.g. `"openai-only"` on an anthropic model) and when
935
- * 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.
936
939
  */
937
940
  isFastModeActive(): boolean;
938
- 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
+ */
939
948
  setFastMode(enabled: boolean): void;
940
949
  toggleFastMode(): boolean;
941
950
  /**
@@ -1102,6 +1111,17 @@ export declare class AgentSession {
1102
1111
  get isEvalRunning(): boolean;
1103
1112
  /** Whether there are pending Python messages waiting to be flushed */
1104
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[];
1105
1125
  /**
1106
1126
  * Deliver an IRC message into this session (recipient side; called by the
1107
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 */
@@ -41,9 +41,4 @@ export interface BuildSessionContextOptions {
41
41
  /** In transcript mode, elide entries replaced by the latest compaction. */
42
42
  collapseCompactedHistory?: boolean;
43
43
  }
44
- /**
45
- * Build the session context from entries using tree traversal.
46
- * If leafId is provided, walks from that entry to root.
47
- * Handles compaction and branch summaries along the path.
48
- */
49
44
  export declare function buildSessionContext(entries: SessionEntry[], leafId?: string | null, byId?: Map<string, SessionEntry>, options?: BuildSessionContextOptions): SessionContext;
@@ -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";
@@ -1,4 +1,4 @@
1
- import type { ImageContent, Message, MessageAttribution, ServiceTier, TextContent } from "@oh-my-pi/pi-ai";
1
+ import type { ImageContent, Message, MessageAttribution, ServiceTierByFamily, TextContent } from "@oh-my-pi/pi-ai";
2
2
  import { ArtifactManager } from "./artifacts";
3
3
  import { type BlobPutOptions, type BlobPutResult } from "./blob-store";
4
4
  import { type BashExecutionMessage, type CustomMessage, type FileMentionMessage, type HookMessage, type PythonExecutionMessage } from "./messages";
@@ -141,7 +141,7 @@ export declare class SessionManager {
141
141
  appendMessage(message: Message | CustomMessage | HookMessage | BashExecutionMessage | PythonExecutionMessage | FileMentionMessage): string;
142
142
  /** Append a thinking level change as child of current leaf, then advance leaf. Returns entry id. */
143
143
  appendThinkingLevelChange(thinkingLevel?: string, configured?: string): string;
144
- appendServiceTierChange(serviceTier: ServiceTier | null): string;
144
+ appendServiceTierChange(serviceTier: ServiceTierByFamily | null): string;
145
145
  appendModeChange(mode: string, data?: Record<string, unknown>): string;
146
146
  /**
147
147
  * Append a model change as a child of the current leaf, then advance the leaf.
@@ -2,8 +2,8 @@
2
2
  * Settings-aware stream wrapper shared by the main agent (sdk.ts) and the
3
3
  * advisor agent (AgentSession.#buildAdvisorRuntime).
4
4
  *
5
- * Reads OpenRouter / Antigravity routing variants, Responses-family text
6
- * verbosity, per-provider in-flight caps, and the loop guard out of `Settings`
5
+ * verbosity, stream watchdog budgets, per-provider in-flight caps, and the loop
6
+ * guard out of `Settings`
7
7
  * per request, layering them onto whatever options the caller passed. Before
8
8
  * this helper existed, advisor turns called bare `streamSimple` while the main
9
9
  * turn went through an inline closure that read these settings — so an advisor on
@@ -0,0 +1 @@
1
+ export {};
@@ -4,7 +4,7 @@
4
4
  * Runs each subagent on the main thread and forwards AgentEvents for progress tracking.
5
5
  */
6
6
  import type { AgentTelemetryConfig, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
7
- import type { ServiceTier } from "@oh-my-pi/pi-ai";
7
+ import type { ServiceTierByFamily } from "@oh-my-pi/pi-ai";
8
8
  import type { Rule } from "../capability/rule";
9
9
  import { ModelRegistry } from "../config/model-registry";
10
10
  import type { PromptTemplate } from "../config/prompt-templates";
@@ -123,12 +123,12 @@ export interface ExecutorOptions {
123
123
  modelRegistry?: ModelRegistry;
124
124
  settings?: Settings;
125
125
  /**
126
- * Parent session's live effective service tier, the source of truth for a
127
- * subagent whose `serviceTierSubagent` is `"inherit"`. `null` = the parent
126
+ * Parent session's live per-family service tiers, the source of truth for a
127
+ * subagent whose `tier.subagent` is `"inherit"`. `null` = the parent
128
128
  * explicitly has no tier (e.g. `/fast off`); omitted = no live session, so
129
- * inherit falls back to the configured `serviceTier` setting.
129
+ * inherit falls back to the subagent's configured `tier.*` settings.
130
130
  */
131
- parentServiceTier?: ServiceTier | null;
131
+ parentServiceTier?: ServiceTierByFamily | null;
132
132
  /** Override local:// protocol options so subagent shares parent's local:// root */
133
133
  localProtocolOptions?: LocalProtocolOptions;
134
134
  /**
@@ -191,7 +191,7 @@ export declare function finalizeSubprocessOutput(args: FinalizeSubprocessOutputA
191
191
  * Create proxy tools that reuse the parent's MCP connections.
192
192
  */
193
193
  export declare function createMCPProxyTools(mcpManager: MCPManager): CustomTool[];
194
- export declare function createSubagentSettings(baseSettings: Settings, overrides?: Partial<Record<SettingPath, unknown>>, inheritedServiceTier?: ServiceTier | null): Settings;
194
+ export declare function createSubagentSettings(baseSettings: Settings, overrides?: Partial<Record<SettingPath, unknown>>, inheritedServiceTier?: ServiceTierByFamily | null): Settings;
195
195
  export declare function finalizeSubagentLifecycle(args: {
196
196
  id: string;
197
197
  session: AgentSession;
@@ -334,6 +334,12 @@ export interface SingleResult {
334
334
  patchPath?: string;
335
335
  /** Branch name for isolated branch-mode output */
336
336
  branchName?: string;
337
+ /**
338
+ * Baseline commit SHA the task branch was created from. Passed to
339
+ * `mergeTaskBranches` so cherry-pick uses the inclusive range
340
+ * `branchBaseSha..branchName` and preserves every agent commit's message.
341
+ */
342
+ branchBaseSha?: string;
337
343
  /** Nested repo patches to apply after parent merge */
338
344
  nestedPatches?: NestedRepoPatch[];
339
345
  /** Data extracted by registered subprocess tool handlers (keyed by tool name) */