@timurproko/a1 0.2.6-dev.727 → 0.2.6-dev.734

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 (104) hide show
  1. package/dist/app/session-shell/clipboard-services.d.ts +19 -0
  2. package/dist/app/session-shell/clipboard-services.js +7 -0
  3. package/dist/app/session-shell/exit-notice.d.ts +9 -5
  4. package/dist/app/session-shell/exit-notice.js +5 -5
  5. package/dist/app/session-shell/index.d.ts +3 -1
  6. package/dist/app/session-shell/index.js +1 -0
  7. package/dist/app/session-shell/paste-preparation-client.d.ts +3 -0
  8. package/dist/app/session-shell/paste-preparation-client.js +5 -2
  9. package/dist/app/session-shell/path-chip-presentation.d.ts +10 -3
  10. package/dist/app/session-shell/path-chip-presentation.js +48 -6
  11. package/dist/app/session-shell/prompt-chips.js +30 -4
  12. package/dist/app/session-shell/quit-outro.d.ts +3 -1
  13. package/dist/app/session-shell/quit-outro.js +23 -8
  14. package/dist/app/session-shell/response-copy-transport.d.ts +6 -1
  15. package/dist/app/session-shell/response-copy-transport.js +8 -2
  16. package/dist/app/session-shell/session-shell-root.d.ts +20 -10
  17. package/dist/app/session-shell/session-shell-root.js +6 -6
  18. package/dist/app/session-shell/session-shell.d.ts +19 -21
  19. package/dist/app/session-shell/session-shell.js +656 -860
  20. package/dist/composition/owned-ui.d.ts +20 -2
  21. package/dist/composition/owned-ui.js +66 -35
  22. package/dist/composition/session-info-reference.d.ts +2 -2
  23. package/dist/composition/session-info-reference.js +2 -2
  24. package/dist/contracts/agent-engine/capability-ports.d.ts +1 -85
  25. package/dist/contracts/agent-engine/capability-ports.js +1 -35
  26. package/dist/contracts/agent-engine/index.d.ts +1 -7
  27. package/dist/contracts/agent-engine/index.js +0 -4
  28. package/dist/contracts/owned-ui/index.d.ts +5 -1
  29. package/dist/contracts/owned-ui/index.js +1 -0
  30. package/dist/contracts/owned-ui/model.d.ts +6 -0
  31. package/dist/contracts/owned-ui/session-backend.d.ts +119 -0
  32. package/dist/contracts/owned-ui/session-presenters.d.ts +55 -0
  33. package/dist/contracts/owned-ui/session-presenters.js +1 -0
  34. package/dist/contracts/owned-ui/session-workflows.d.ts +342 -0
  35. package/dist/contracts/owned-ui/session-workflows.js +30 -0
  36. package/dist/features/owned-ui/settings-app.js +35 -15
  37. package/dist/foundation/release/bootstrap.js +1 -2
  38. package/dist/foundation/release/release-gc.js +1 -1
  39. package/dist/foundation/release/update.js +0 -4
  40. package/dist/foundation/storage/control-store.js +0 -12
  41. package/dist/integrations/pi/components/components.js +0 -16
  42. package/dist/integrations/pi/components/index.d.ts +3 -3
  43. package/dist/integrations/pi/components/index.js +2 -2
  44. package/dist/integrations/pi/components/models-dialog.js +1 -30
  45. package/dist/integrations/pi/components/shell-editor-autocomplete.js +11 -9
  46. package/dist/integrations/pi/components/shell-extension-ui.d.ts +3 -3
  47. package/dist/integrations/pi/components/shell-extension-ui.js +6 -2
  48. package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -4
  49. package/dist/integrations/pi/components/shell-shared-facade.d.ts +21 -1
  50. package/dist/integrations/pi/components/shell-shared-facade.js +18 -2
  51. package/dist/integrations/pi/components/upstream/theme/theme.d.ts +5 -1
  52. package/dist/integrations/pi/components/upstream/theme/theme.js +20 -2
  53. package/dist/integrations/pi/engine/adapter.d.ts +44 -24
  54. package/dist/integrations/pi/engine/adapter.js +130 -22
  55. package/dist/integrations/pi/engine/command-dispatch.d.ts +2 -5
  56. package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -11
  57. package/dist/integrations/pi/engine/host-ports.d.ts +20 -0
  58. package/dist/integrations/pi/engine/host-ports.js +13 -0
  59. package/dist/integrations/pi/engine/host.d.ts +70 -0
  60. package/dist/integrations/pi/engine/host.js +147 -0
  61. package/dist/integrations/pi/engine/index.d.ts +8 -4
  62. package/dist/integrations/pi/engine/index.js +3 -1
  63. package/dist/integrations/pi/engine/resource-catalog.d.ts +4 -23
  64. package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -2
  65. package/dist/integrations/pi/engine/runtime-integration.js +12 -7
  66. package/dist/integrations/pi/engine/session-integration.d.ts +3 -8
  67. package/dist/integrations/pi/engine/session-integration.js +0 -49
  68. package/dist/integrations/pi/engine/session-runtime.d.ts +18 -3
  69. package/dist/integrations/pi/engine/session-runtime.js +18 -7
  70. package/dist/integrations/pi/engine/settings-bridge.d.ts +2 -2
  71. package/dist/integrations/pi/engine/settings-bridge.js +0 -2
  72. package/dist/integrations/pi/engine/settings-port.d.ts +2 -0
  73. package/dist/integrations/pi/engine/settings-port.js +3 -5
  74. package/dist/integrations/pi/engine/workflows.d.ts +33 -260
  75. package/dist/integrations/pi/engine/workflows.js +6 -28
  76. package/dist/integrations/pi/session-presenters/index.d.ts +2 -0
  77. package/dist/integrations/pi/session-presenters/index.js +1 -0
  78. package/dist/integrations/pi/session-presenters/presenters.d.ts +16 -0
  79. package/dist/integrations/pi/session-presenters/presenters.js +341 -0
  80. package/dist/integrations/pi/tui-runtime/adapter.js +0 -2
  81. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +7 -0
  82. package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +66 -1
  83. package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
  84. package/dist/integrations/pi/tui-runtime/index.js +1 -1
  85. package/dist/native/darwin-arm64/manifest.json +1 -1
  86. package/dist/native/linux-x64/manifest.json +1 -1
  87. package/dist/native/win32-x64/manifest.json +2 -2
  88. package/dist/native/win32-x64/process-guardian.exe +0 -0
  89. package/dist/ui/settings/declarations.d.ts +13 -1
  90. package/dist/ui/settings/declarations.js +12 -1
  91. package/dist/ui/settings/migrations.js +7 -0
  92. package/docs/architecture/boundaries.md +9 -1
  93. package/docs/architecture/project-structure.md +3 -2
  94. package/package.json +1 -1
  95. package/dist/contracts/agent-engine/model.d.ts +0 -78
  96. package/dist/contracts/agent-engine/model.js +0 -1
  97. package/dist/contracts/agent-engine/ports.d.ts +0 -18
  98. package/dist/contracts/agent-engine/serialization.d.ts +0 -7
  99. package/dist/contracts/agent-engine/serialization.js +0 -58
  100. package/dist/contracts/agent-engine/validation.d.ts +0 -5
  101. package/dist/contracts/agent-engine/validation.js +0 -128
  102. package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +0 -61
  103. package/dist/integrations/pi/components/upstream/theme/system-theme.js +0 -709
  104. /package/dist/contracts/{agent-engine/ports.js → owned-ui/session-backend.js} +0 -0
@@ -9,12 +9,12 @@ import { createWindowsNulCleanupExtension } from "./windows-filesystem-hygiene.j
9
9
  * pattern ..."), and pick the same initial model pinned Pi would pick — the
10
10
  * saved default when it is in scope, otherwise the first scoped model.
11
11
  */
12
- export async function resolveConfiguredModelScope(services) {
12
+ export async function resolveConfiguredModelScope(services, signal) {
13
13
  const patterns = services.settingsManager.getEnabledModels();
14
14
  if (!patterns || patterns.length === 0) {
15
15
  return { scopedModels: [], model: undefined, thinkingLevel: undefined, diagnostics: [] };
16
16
  }
17
- const { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics([...patterns], services.modelRuntime, { signal: AbortSignal.timeout(15_000) });
17
+ const { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics([...patterns], services.modelRuntime, { signal: signal === undefined ? AbortSignal.timeout(15_000) : AbortSignal.any([signal, AbortSignal.timeout(15_000)]) });
18
18
  let selected;
19
19
  if (scopedModels.length > 0) {
20
20
  const savedProvider = services.settingsManager.getDefaultProvider();
@@ -38,13 +38,14 @@ export async function createPiRuntimeServicesAfterTrust(options) {
38
38
  const createSettingsManager = options.preflightDependencies?.createSettingsManager
39
39
  ?? ((targetCwd, agentDir, projectTrusted) => SettingsManager.create(targetCwd, agentDir, { projectTrusted }));
40
40
  const createServices = options.preflightDependencies?.createServices ?? createAgentSessionServices;
41
+ const markPhase = options.markStartupPhase ?? defaultStartupPhaseMarker;
41
42
  const trust = await resolveTrust({
42
43
  cwd: options.cwd,
43
44
  agentDir: options.agentDir,
44
45
  ...(options.projectTrustPrompt === undefined ? {} : { prompt: options.projectTrustPrompt }),
45
46
  });
46
47
  const settingsManager = createSettingsManager(options.cwd, options.agentDir, trust.trusted);
47
- await markStartupPhase(process.env, "settings-loaded");
48
+ await markPhase("settings-loaded");
48
49
  const cleanupExtension = createWindowsNulCleanupExtension();
49
50
  const services = await createServices({
50
51
  cwd: options.cwd,
@@ -54,8 +55,8 @@ export async function createPiRuntimeServicesAfterTrust(options) {
54
55
  resourceLoaderOptions: { extensionFactories: [cleanupExtension] },
55
56
  }),
56
57
  });
57
- await markStartupPhase(process.env, "pi-services");
58
- await markStartupPhase(process.env, "resource-discovery");
58
+ await markPhase("pi-services");
59
+ await markPhase("resource-discovery");
59
60
  return { services, trust };
60
61
  }
61
62
  export async function createPiRuntimeIntegration(options) {
@@ -75,8 +76,9 @@ export async function createPiRuntimeIntegration(options) {
75
76
  agentDir: options.agentDir,
76
77
  ...(options.projectTrustPrompt === undefined ? {} : { projectTrustPrompt: options.projectTrustPrompt }),
77
78
  ...(options.preflightDependencies === undefined ? {} : { preflightDependencies: options.preflightDependencies }),
79
+ ...(options.markStartupPhase === undefined ? {} : { markStartupPhase: options.markStartupPhase }),
78
80
  });
79
- const modelScope = await resolveConfiguredModelScope(services);
81
+ const modelScope = await resolveConfiguredModelScope(services, options.signal);
80
82
  const hasExistingSession = targetSessionManager.buildSessionContext().messages.length > 0;
81
83
  const created = await createAgentSessionFromServices({
82
84
  services,
@@ -86,7 +88,7 @@ export async function createPiRuntimeIntegration(options) {
86
88
  ...(modelScope.thinkingLevel && !hasExistingSession ? { thinkingLevel: modelScope.thinkingLevel } : {}),
87
89
  ...(modelScope.scopedModels.length > 0 ? { scopedModels: [...modelScope.scopedModels] } : {}),
88
90
  });
89
- await markStartupPhase(process.env, "session-created");
91
+ await (options.markStartupPhase ?? defaultStartupPhaseMarker)("session-created");
90
92
  return {
91
93
  ...created,
92
94
  services,
@@ -102,6 +104,9 @@ export async function createPiRuntimeIntegration(options) {
102
104
  sessionManager,
103
105
  });
104
106
  }
107
+ function defaultStartupPhaseMarker(phase) {
108
+ return markStartupPhase(process.env, phase);
109
+ }
105
110
  export function bindPiRuntimeSession(runtime, rebind) {
106
111
  runtime.setRebindSession(rebind);
107
112
  return () => runtime.setRebindSession(undefined);
@@ -1,5 +1,4 @@
1
- import type { AgentSession, AgentSessionEvent, PromptOptions } from "../startup-public.js";
2
- import { type AgentCommandOutcome, type AgentEvent } from "../../../contracts/agent-engine/index.js";
1
+ import type { AgentSession, PromptOptions } from "../startup-public.js";
3
2
  type PiPromptImages = NonNullable<PromptOptions["images"]>;
4
3
  export interface PiDocumentedSessionCommands {
5
4
  readonly isStreaming: AgentSession["isStreaming"];
@@ -36,8 +35,9 @@ export type PiSessionCommand = {
36
35
  readonly excludeFromContext: boolean;
37
36
  readonly onChunk?: (chunk: string) => void;
38
37
  };
38
+ export type PiSessionCommandOutcome = "completed" | "rejected" | "failed" | "cancelled";
39
39
  export interface PiSessionCommandResult {
40
- readonly outcome: AgentCommandOutcome;
40
+ readonly outcome: PiSessionCommandOutcome;
41
41
  readonly value?: unknown;
42
42
  }
43
43
  /** Routes neutral session commands to Pi while preserving Pi streaming and retry semantics. */
@@ -59,9 +59,4 @@ export declare class PiSessionCommandIntegration {
59
59
  /** Forgets the attachments kept for queued messages; the queue itself was cleared by the caller. */
60
60
  forgetQueuedImages(): void;
61
61
  }
62
- export interface PiOrderedEventIntegration {
63
- dispose(): void;
64
- }
65
- export declare function subscribeToPiSessionEvents(session: Pick<AgentSession, "subscribe">, sessionId: string, emit: (event: AgentEvent) => void, malformed: (diagnostic: string) => void): PiOrderedEventIntegration;
66
- export declare function convertPiSessionEvent(event: AgentSessionEvent, sessionId: string, sequence: number): AgentEvent | null;
67
62
  export {};
@@ -1,4 +1,3 @@
1
- import { AGENT_ENGINE_CONTRACT_VERSION, } from "../../../contracts/agent-engine/index.js";
2
1
  /** Routes neutral session commands to Pi while preserving Pi streaming and retry semantics. */
3
2
  export class PiSessionCommandIntegration {
4
3
  #lastPrompt = null;
@@ -145,51 +144,3 @@ export class PiSessionCommandIntegration {
145
144
  return this.session.extensionRunner?.getCommand(name) !== undefined;
146
145
  }
147
146
  }
148
- export function subscribeToPiSessionEvents(session, sessionId, emit, malformed) {
149
- let sequence = 0;
150
- let disposed = false;
151
- const unsubscribe = session.subscribe(event => {
152
- if (disposed)
153
- return;
154
- sequence += 1;
155
- try {
156
- const converted = convertPiSessionEvent(event, sessionId, sequence);
157
- if (converted)
158
- emit(converted);
159
- }
160
- catch (error) {
161
- malformed(`Pi session event ${sequence} is malformed: ${error instanceof Error ? error.message : String(error)}`);
162
- }
163
- });
164
- return { dispose() { if (disposed)
165
- return; disposed = true; unsubscribe(); } };
166
- }
167
- export function convertPiSessionEvent(event, sessionId, sequence) {
168
- const base = { contractVersion: AGENT_ENGINE_CONTRACT_VERSION, sessionId, sequence };
169
- switch (event.type) {
170
- case "agent_start": return { ...base, type: "lifecycle", lifecycle: "busy", reason: null };
171
- case "agent_settled": return { ...base, type: "lifecycle", lifecycle: "ready", reason: null };
172
- case "agent_end": return event.willRetry ? null : { ...base, type: "lifecycle", lifecycle: "ready", reason: null };
173
- case "message_start":
174
- case "message_update":
175
- case "message_end":
176
- return { ...base, type: "content", content: toAgentMessage(event.message, event.type === "message_end" ? "final" : "streaming", sequence) };
177
- default: return null;
178
- }
179
- }
180
- function toAgentMessage(value, status, sequence) {
181
- if (!value || typeof value !== "object")
182
- throw new TypeError("message payload is not an object");
183
- const message = value;
184
- const role = message.role === "user" || message.role === "assistant" || message.role === "tool" || message.role === "system" ? message.role : "assistant";
185
- const source = Array.isArray(message.content) ? message.content : [];
186
- const text = source.flatMap(part => part && typeof part === "object" && typeof part.text === "string" ? [part.text] : []).join("");
187
- return {
188
- id: typeof message.id === "string" ? message.id : `message-${sequence}`,
189
- role,
190
- status,
191
- content: text.length > 0
192
- ? [{ kind: "text", text }]
193
- : [{ kind: "unknown", sourceType: "pi-message", payload: { role: String(message.role ?? "unknown") } }],
194
- };
195
- }
@@ -1,3 +1,4 @@
1
+ import { type PiStartupPhaseMarker } from "./runtime-integration.js";
1
2
  import { PiSessionCommandIntegration } from "./session-integration.js";
2
3
  import { type AgentSession, type AgentSessionRuntime, type AgentSessionServices } from "../startup-public.js";
3
4
  import type { PiProjectTrustPreflightPrompt } from "./project-trust-preflight.js";
@@ -13,6 +14,9 @@ export interface PiEngineRuntimeFactoryInput {
13
14
  readonly sessionSelection?: PiSessionSelection;
14
15
  readonly sessionForkPrompt?: PiSessionForkPrompt;
15
16
  readonly projectTrustPrompt?: PiProjectTrustPreflightPrompt;
17
+ /** The host's signal; runtime creation steps that wait on the network stop with it. */
18
+ readonly signal: AbortSignal;
19
+ readonly markStartupPhase: PiStartupPhaseMarker;
16
20
  }
17
21
  export type PiEngineRuntimeFactory = (input: PiEngineRuntimeFactoryInput) => Promise<AgentSessionRuntime>;
18
22
  export type PiEnginePackageUpdateProbe = (settingsManager: AgentSessionServices["settingsManager"]) => Promise<readonly string[]>;
@@ -32,7 +36,9 @@ export interface PiEngineRuntimeOptions {
32
36
  readonly projectTrustPrompt: PiProjectTrustPreflightPrompt | undefined;
33
37
  readonly createRuntime: PiEngineRuntimeFactory | undefined;
34
38
  readonly checkPackageUpdates: PiEnginePackageUpdateProbe | undefined;
35
- readonly announceStartupChangelog?: boolean;
39
+ /** Aborted by the host on disposal; a probe that resolves afterwards announces nothing. */
40
+ readonly signal: AbortSignal;
41
+ readonly markStartupPhase: PiStartupPhaseMarker;
36
42
  readonly pullRequestProbe?: PiPullRequestProbe;
37
43
  readonly pullRequestRefreshMs?: number;
38
44
  readonly repositoryContextPollMs?: number;
@@ -79,9 +85,12 @@ export declare class PiEngineRuntime {
79
85
  get pullRequest(): PiPullRequestIdentity | null;
80
86
  get sessionCommands(): PiSessionCommandIntegration | undefined;
81
87
  get started(): boolean;
82
- /** Create the runtime, bind its first session, and announce the changelog; startup failures propagate. */
88
+ /** Create the runtime and bind its first session; startup failures propagate. */
83
89
  start(): Promise<AgentSessionRuntime>;
84
- /** Probe extension packages for updates after startup and report them as an informational diagnostic. */
90
+ /**
91
+ * Probe extension packages for updates and report them as an informational diagnostic. The host
92
+ * calls this once per process, on the first session it creates.
93
+ */
85
94
  announcePackageUpdates(): Promise<void>;
86
95
  currentSessionFile(): string | null;
87
96
  currentSessionResumeMetadata(): PiSessionResumeMetadata | null;
@@ -96,4 +105,10 @@ export declare class PiEngineRuntime {
96
105
  deliverQueuedAfterCompaction(): void;
97
106
  /** Unsubscribe, stop observing compaction, and dispose the runtime; the session reference is kept for final reads. */
98
107
  dispose(): Promise<void>;
108
+ /**
109
+ * Announce pinned Pi's changelog since the last version this profile saw and record the current
110
+ * one. The host calls this once per process, on the first session it creates; the session must be
111
+ * empty, as in Pi's own startup.
112
+ */
113
+ announceChangelog(): Promise<void>;
99
114
  }
@@ -94,12 +94,14 @@ export class PiEngineRuntime {
94
94
  get started() {
95
95
  return this.#runtime !== undefined;
96
96
  }
97
- /** Create the runtime, bind its first session, and announce the changelog; startup failures propagate. */
97
+ /** Create the runtime and bind its first session; startup failures propagate. */
98
98
  async start() {
99
99
  const runtime = await this.#runtimeFactory({
100
100
  cwd: this.#cwd,
101
101
  agentDir: this.#options.agentDir,
102
102
  sessionId: this.#options.sessionId,
103
+ signal: this.#options.signal,
104
+ markStartupPhase: this.#options.markStartupPhase,
103
105
  ...(this.#options.sessionPath === undefined ? {} : { sessionPath: this.#options.sessionPath }),
104
106
  ...(this.#options.sessionSelection === undefined ? {} : { sessionSelection: this.#options.sessionSelection }),
105
107
  ...(this.#options.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: this.#options.sessionForkPrompt }),
@@ -122,16 +124,17 @@ export class PiEngineRuntime {
122
124
  this.#ports.diagnostic(diagnostic.type === "error" ? "error" : diagnostic.type === "warning" ? "warning" : "info", code, diagnostic.message, diagnostic.type !== "error");
123
125
  }
124
126
  this.bindSession(runtime.session);
125
- if (this.#options.announceStartupChangelog !== false)
126
- await this.#announceChangelog(runtime.services.settingsManager);
127
127
  this.#repositoryRefreshEnabled = true;
128
128
  this.#startRepositoryRefresh();
129
129
  return runtime;
130
130
  }
131
- /** Probe extension packages for updates after startup and report them as an informational diagnostic. */
131
+ /**
132
+ * Probe extension packages for updates and report them as an informational diagnostic. The host
133
+ * calls this once per process, on the first session it creates.
134
+ */
132
135
  async announcePackageUpdates() {
133
136
  const runtime = this.#runtime;
134
- if (process.env.PI_OFFLINE || runtime === undefined)
137
+ if (process.env.PI_OFFLINE || runtime === undefined || this.#options.signal.aborted)
135
138
  return;
136
139
  let updates;
137
140
  try {
@@ -140,7 +143,7 @@ export class PiEngineRuntime {
140
143
  catch {
141
144
  return;
142
145
  }
143
- if (this.#ports.disposed() || updates.length === 0)
146
+ if (this.#ports.disposed() || this.#options.signal.aborted || updates.length === 0)
144
147
  return;
145
148
  const packages = updates.map(name => `- ${name}`).join("\n");
146
149
  this.#ports.diagnostic("info", "package-updates", `Package updates are available. Run ${PRODUCT_IDENTITY.commandName} pi update --extensions\nPackages:\n${packages}`, true);
@@ -365,7 +368,13 @@ export class PiEngineRuntime {
365
368
  this.#ports.event(event);
366
369
  });
367
370
  }
368
- async #announceChangelog(settingsManager) {
371
+ /**
372
+ * Announce pinned Pi's changelog since the last version this profile saw and record the current
373
+ * one. The host calls this once per process, on the first session it creates; the session must be
374
+ * empty, as in Pi's own startup.
375
+ */
376
+ async announceChangelog() {
377
+ const settingsManager = this.#runtime?.services.settingsManager;
369
378
  if (!settingsManager || typeof settingsManager.getLastChangelogVersion !== "function"
370
379
  || typeof settingsManager.setLastChangelogVersion !== "function")
371
380
  return;
@@ -391,6 +400,8 @@ async function createDefaultPiRuntime(input) {
391
400
  return createPiRuntimeIntegration({
392
401
  cwd: input.cwd,
393
402
  agentDir: input.agentDir,
403
+ signal: input.signal,
404
+ markStartupPhase: input.markStartupPhase,
394
405
  ...(input.sessionPath === undefined ? {} : { sessionPath: input.sessionPath }),
395
406
  ...(input.sessionSelection === undefined ? {} : { sessionSelection: input.sessionSelection }),
396
407
  ...(input.sessionForkPrompt === undefined ? {} : { sessionForkPrompt: input.sessionForkPrompt }),
@@ -1,6 +1,7 @@
1
1
  import type { SettingsManager } from "../startup-public.js";
2
2
  import type { AgentJsonValue, AgentSettingApplicationBoundary, AgentSettingChangeOutcome, AgentSettingDescriptor, AgentSettingOwner, AgentSettingsPort } from "../../../contracts/agent-engine/index.js";
3
- export type PiSettingKey = "autoCompact" | "showImages" | "imageWidthCells" | "autoResizeImages" | "blockImages" | "enableSkillCommands" | "steeringMode" | "followUpMode" | "transport" | "httpIdleTimeoutMs" | "cacheWarmingMode" | "modelThinkingLevels" | "theme" | "hideThinkingBlock" | "mermaidRenderingMode" | "showCacheMissNotices" | "collapseChangelog" | "enableInstallTelemetry" | "quietStartup" | "defaultProjectTrust" | "doubleEscapeAction" | "treeFilterMode" | "showHardwareCursor" | "editorPaddingX" | "outputPad" | "autocompleteMaxVisible" | "clearOnShrink" | "showTerminalProgress" | "tuiMode" | "fullscreenExitOutput" | "fullscreenScrollbar" | "fullscreenCopyOnSelect" | "fullscreenWheelScrollLines" | "warnings";
3
+ import type { OwnedUiSessionSettingKey } from "../../../contracts/owned-ui/index.js";
4
+ export type PiSettingKey = OwnedUiSessionSettingKey;
4
5
  export type PiSettingVisualClass = "none" | "transcript" | "transcript-geometry" | "editor-menu" | "queue-transcript" | "status-error" | "retry-error" | "footer-transcript" | "markdown" | "transcript-notice" | "startup-transcript" | "startup-selector" | "selector" | "terminal-cursor" | "editor-geometry" | "menu-geometry" | "terminal-frame" | "terminal-status" | "hidden";
5
6
  export interface PiSettingVisualEvidence {
6
7
  /** Reviewed visual family; `none` still names the behavior that can emit styled diagnostics. */
@@ -105,7 +106,6 @@ export declare class PiSettingsBridge implements AgentSettingsPort {
105
106
  write: boolean;
106
107
  flush: boolean;
107
108
  };
108
- private readonly settings;
109
109
  constructor(settings: SettingsManager, providers?: PiSettingsProviders);
110
110
  bindOwner(owner: AgentSettingOwner, handlers: PiSettingOwnerHandlers): () => void;
111
111
  unbindOwner(owner: AgentSettingOwner): void;
@@ -294,9 +294,7 @@ export class PiSettingsBridge {
294
294
  #operations;
295
295
  #providers;
296
296
  #coordinator;
297
- settings;
298
297
  constructor(settings, providers = {}) {
299
- this.settings = settings;
300
298
  this.#providers = providers;
301
299
  const mapped = operations(settings, providers);
302
300
  this.#operations = new Map(mapped.map(operation => [operation.key, operation]));
@@ -15,6 +15,8 @@ export interface PiEngineSettingsPorts {
15
15
  requireSession(): AgentSession;
16
16
  /** The session's thinking level was written through the settings port; the adapter mirrors and publishes it. */
17
17
  thinkingLevelChanged(level: OwnedUiThinkingLevel): void;
18
+ /** The HTTP idle timeout was written through the settings port; the host re-installs the process dispatcher. */
19
+ httpPolicyChanged(timeoutMs: number): void;
18
20
  emitView(): void;
19
21
  }
20
22
  /**
@@ -1,4 +1,3 @@
1
- import { configureOwnedHttpDispatcher } from "./http-dispatcher.js";
2
1
  import { isRecord, readThinkingLevel, stringProperty } from "./message-values.js";
3
2
  import { collectionResult } from "./resource-catalog.js";
4
3
  import { MODEL_THINKING_DEFAULT, PiSettingsBridge } from "./settings-bridge.js";
@@ -49,7 +48,6 @@ export class PiEngineSettings {
49
48
  return null;
50
49
  if (this.#settingsIntegration === undefined || this.#settingsIntegrationManager !== settings) {
51
50
  this.#settingsIntegrationManager = settings;
52
- configureOwnedHttpDispatcher(settings.getHttpIdleTimeoutMs());
53
51
  this.#settingsIntegration = new PiSettingsBridge(settings, {
54
52
  ...(this.#availableThemes === null ? {} : { themes: this.#availableThemes }),
55
53
  models: () => this.#modelChoices(),
@@ -117,9 +115,9 @@ export class PiEngineSettings {
117
115
  httpIdleTimeoutMs: { apply: value => {
118
116
  if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0)
119
117
  throw new TypeError("HTTP idle timeout is invalid");
120
- // Invariant: provider streaming reads the manager per request; global fetch uses
121
- // the matching owned dispatcher and zero maps to disabled semantics.
122
- configureOwnedHttpDispatcher(value);
118
+ // Invariant: provider streaming reads the manager per request; the host gives global
119
+ // fetch the matching process-wide dispatcher, and zero maps to disabled semantics.
120
+ this.#ports.httpPolicyChanged(value);
123
121
  settings.setHttpIdleTimeoutMs(value);
124
122
  } },
125
123
  cacheWarmingMode: { apply: value => {