pi2dsh 0.12.3 → 0.13.0

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 (41) hide show
  1. package/README.md +82 -22
  2. package/README.zh.md +67 -19
  3. package/dist/{analyzer-2Nx5XYOA.mjs → analyzer-CXNbeBAe.mjs} +2 -2
  4. package/dist/{analyzer-2Nx5XYOA.mjs.map → analyzer-CXNbeBAe.mjs.map} +1 -1
  5. package/dist/cli.mjs +2 -2
  6. package/dist/client.js +604 -31
  7. package/dist/compat/pi-ai.d.mts +36 -1
  8. package/dist/compat/pi-ai.d.mts.map +1 -1
  9. package/dist/compat/pi-ai.mjs +2 -2
  10. package/dist/compat/pi-coding-agent.d.mts +2 -1411
  11. package/dist/compat/pi-coding-agent.mjs +1 -1
  12. package/dist/compat/pi-tui.mjs +1 -1
  13. package/dist/{oauth-bridge-CfyImWx4.mjs → credentials-oauth-BakY-0PA.mjs} +172 -13
  14. package/dist/credentials-oauth-BakY-0PA.mjs.map +1 -0
  15. package/dist/credentials-oauth.mjs +1 -89
  16. package/dist/host.mjs +4 -2
  17. package/dist/host.mjs.map +1 -1
  18. package/dist/index.mjs +3 -3
  19. package/dist/{mcp-config-Cjae0vot.mjs → mcp-config-CZepacin.mjs} +19 -19
  20. package/dist/mcp-config-CZepacin.mjs.map +1 -0
  21. package/dist/{pi-ai-Dyg4zyLZ.mjs → pi-ai-BA3V_J0V.mjs} +40 -2
  22. package/dist/{pi-ai-Dyg4zyLZ.mjs.map → pi-ai-BA3V_J0V.mjs.map} +1 -1
  23. package/dist/pi-coding-agent-B0PT23gE.d.mts +1412 -0
  24. package/dist/pi-coding-agent-B0PT23gE.d.mts.map +1 -0
  25. package/dist/{pi-coding-agent-CYnmeJEx.mjs → pi-coding-agent-D9skobb6.mjs} +0 -0
  26. package/dist/pi-coding-agent-D9skobb6.mjs.map +1 -0
  27. package/dist/{pi-tui-5CYLcj-_.mjs → pi-tui-DruSeKmd.mjs} +3 -3
  28. package/dist/pi-tui-DruSeKmd.mjs.map +1 -0
  29. package/dist/{runtime-B_Ig28og.mjs → runtime-B-SlR8mJ.mjs} +970 -75
  30. package/dist/runtime-B-SlR8mJ.mjs.map +1 -0
  31. package/dist/runtime.d.mts +600 -0
  32. package/dist/runtime.d.mts.map +1 -1
  33. package/dist/runtime.mjs +1 -1
  34. package/package.json +2 -1
  35. package/dist/compat/pi-coding-agent.d.mts.map +0 -1
  36. package/dist/credentials-oauth.mjs.map +0 -1
  37. package/dist/mcp-config-Cjae0vot.mjs.map +0 -1
  38. package/dist/oauth-bridge-CfyImWx4.mjs.map +0 -1
  39. package/dist/pi-coding-agent-CYnmeJEx.mjs.map +0 -1
  40. package/dist/pi-tui-5CYLcj-_.mjs.map +0 -1
  41. package/dist/runtime-B_Ig28og.mjs.map +0 -1
@@ -1,14 +1,568 @@
1
1
 
2
+ import { N as Theme, p as ExtensionRunner } from "./pi-coding-agent-B0PT23gE.mjs";
2
3
  import { a as GeneratedRuntimeManifest } from "./types-7IWJPPvS.mjs";
4
+ import { EventEmitter } from "node:events";
5
+ import { AsyncLocalStorage } from "node:async_hooks";
3
6
  import { ContentBlock } from "@deepseek-ai/dsh-llm";
4
7
  import { Context } from "@deepseek-ai/cordis";
8
+ //#region src/capability.d.ts
9
+ type PackageHealthStatus = 'ok' | 'degraded' | 'unusable';
10
+ interface PackageHealth {
11
+ status: PackageHealthStatus;
12
+ /** Pi capability names this package has hit, in first-hit order. */
13
+ gaps: readonly string[];
14
+ }
15
+ interface CapabilityGapOptions {
16
+ /** The Pi capability, as the package sees it (e.g. "ctx.fork"). */
17
+ capability: string;
18
+ /** Why DSH has no mapping, in one sentence. */
19
+ reason: string;
20
+ /** What the caller can do about it, in one sentence. */
21
+ guidance: string;
22
+ /** The migrated package that hit the gap, when known. */
23
+ packageName?: string;
24
+ }
25
+ /**
26
+ * Host-level record of capability gaps, one instance per DSH host (it lives in
27
+ * SharedHostState). Emits ONE user-facing notice per (package, capability):
28
+ * repeated hits of the same gap change nothing the user needs to hear again.
29
+ */
30
+ declare class CapabilityLedger {
31
+ private readonly emit;
32
+ private readonly noticed;
33
+ private readonly packages;
34
+ constructor(emit: (message: string) => void);
35
+ /**
36
+ * Record a degraded capability: this feature of the package does not work on
37
+ * DSH, the rest of the package keeps working. Reported to the user once.
38
+ */
39
+ reportDegraded(options: CapabilityGapOptions): void;
40
+ /**
41
+ * Record a host-owned decision (e.g. shutdown): the host refused or absorbed
42
+ * the request through a channel Pi itself defines. Not a package defect, so
43
+ * package health stays untouched; the user still learns what happened, once.
44
+ */
45
+ reportHostDecision(options: CapabilityGapOptions): void;
46
+ /**
47
+ * Startup-time reference detection: the package's source imports a
48
+ * host-owned symbol that cannot work on DSH. Reported at mount so the user
49
+ * learns BEFORE any code path runs into it; health is untouched because an
50
+ * import alone proves nothing about usage — construction still fails
51
+ * structurally and marks the package then.
52
+ */
53
+ reportStartupReference(options: CapabilityGapOptions): void;
54
+ /**
55
+ * Record that a package could not even mount because its entry code needs a
56
+ * missing capability. The package is marked unusable for this run.
57
+ */
58
+ reportUnusable(options: CapabilityGapOptions): void;
59
+ healthOf(packageName: string): PackageHealth;
60
+ /** Every package with a recorded gap, for surfacing in mount summaries. */
61
+ snapshot(): ReadonlyMap<string, PackageHealth>;
62
+ private mark;
63
+ private notice;
64
+ }
65
+ //#endregion
66
+ //#region src/session-bridge.d.ts
67
+ type UnknownRecord$4 = Record<string, unknown>;
68
+ interface DshSessionLike {
69
+ id: string;
70
+ events: readonly UnknownRecord$4[] | (() => readonly UnknownRecord$4[]);
71
+ append?(type: string, data: unknown, opts?: unknown): unknown;
72
+ header?: UnknownRecord$4;
73
+ }
74
+ interface PiProjectedEntry {
75
+ type: string;
76
+ id: string;
77
+ parentId: string | null;
78
+ timestamp: string;
79
+ [key: string]: unknown;
80
+ }
81
+ declare class PiSessionBridge {
82
+ private readonly records;
83
+ private readonly loaded;
84
+ private sidecarPath;
85
+ load(sessionId: string): void;
86
+ private persist;
87
+ appendCustomEntry(sessionId: string, customType: string, data: unknown): string;
88
+ /**
89
+ * The custom entries a package appended to one session, oldest first.
90
+ *
91
+ * Addressed by id alone: the browser half asks for a session it is showing,
92
+ * and has no DSH session object to hand over.
93
+ * @param sessionId - session whose sidecar to read.
94
+ * @returns each custom entry with its type, data and id.
95
+ */
96
+ customEntries(sessionId: string): Array<{
97
+ id: string;
98
+ customType: string;
99
+ data: unknown;
100
+ timestamp: string;
101
+ }>;
102
+ appendBranchSummary(sessionId: string, summary: string, fromId: string): string;
103
+ appendLabel(sessionId: string, targetId: string, label: string | undefined): void;
104
+ setName(sessionId: string, name: string): void;
105
+ getName(sessionId: string): string | undefined;
106
+ labels(sessionId: string): Map<string, string>;
107
+ /**
108
+ * Project the DSH durable log plus sidecar records into Pi's entry-chain
109
+ * shape. DSH history is linear, so the projection is a single-branch tree:
110
+ * every entry's parent is its predecessor.
111
+ */
112
+ /**
113
+ * The seqs still on the model-visible surface, via DSH's own canonical fold.
114
+ * @param session - the session to project.
115
+ * @returns the visible seqs, or undefined when the fold cannot run (a
116
+ * projection built from a partial event list, e.g. in a test double) — in
117
+ * which case nothing is filtered out rather than everything.
118
+ */
119
+ visibleSeqs(session: DshSessionLike): Set<number> | undefined;
120
+ projectEntries(session: DshSessionLike): PiProjectedEntry[];
121
+ /** The exact 14-method surface Pi exposes as ctx.sessionManager. */
122
+ readonlySessionManager(session: DshSessionLike, cwd: string): UnknownRecord$4;
123
+ }
124
+ //#endregion
125
+ //#region src/subagent-bridge.d.ts
126
+ type UnknownRecord$3 = Record<string, unknown>;
127
+ type PiSessionEventHandler = (event: UnknownRecord$3) => void;
128
+ interface SubagentHost {
129
+ cordis: Context;
130
+ cwd(): string;
131
+ parentSessionId(): string | undefined;
132
+ /** The delegating parent's delegation depth (DSH's recursion budget); 0 for a top-level parent. */
133
+ parentDelegationDepth(): number;
134
+ piContentToDsh(content: unknown): Promise<ContentBlock[]>;
135
+ deliver(agent: UnknownRecord$3, message: unknown, mode: 'inject' | 'steer' | 'followup'): void;
136
+ messageFromSessionEvent(event: UnknownRecord$3): Promise<UnknownRecord$3 | undefined>;
137
+ messageSource: string;
138
+ /** The Pi package that asked for the child, used to label it in DSH's catalog. */
139
+ packageName?: string;
140
+ }
141
+ interface BeforeToolCallDecision {
142
+ block?: boolean;
143
+ reason?: string;
144
+ }
145
+ interface PiSubagentFacade {
146
+ beforeToolCall?: (context: {
147
+ toolCall: {
148
+ name: string;
149
+ id: string;
150
+ arguments: unknown;
151
+ };
152
+ }, signal: AbortSignal | undefined) => Promise<BeforeToolCallDecision | undefined> | BeforeToolCallDecision | undefined;
153
+ /** Pi's AgentState — the same object `session.state` returns. */
154
+ state?: UnknownRecord$3;
155
+ }
156
+ declare class PiBridgedAgentSession {
157
+ #private;
158
+ readonly agent: PiSubagentFacade;
159
+ readonly messages: UnknownRecord$3[];
160
+ constructor(host: SubagentHost, handle: {
161
+ agent: UnknownRecord$3;
162
+ dispose(): Promise<void>;
163
+ }, tools: unknown[]);
164
+ /** Pi's AgentState projection, shared by `session.state` and `session.agent.state`. */
165
+ get state(): UnknownRecord$3;
166
+ /**
167
+ * Whether one transcript entry is carried context rather than part of the
168
+ * exchange in this child session.
169
+ * @param message - an entry of {@link messages}.
170
+ * @returns true for a seeded transcript entry or a host runtime snapshot.
171
+ */
172
+ isCarriedContext(message: UnknownRecord$3): boolean;
173
+ subscribe(handler: PiSessionEventHandler): () => void;
174
+ prompt(text: string): Promise<void>;
175
+ steer(text: string): void;
176
+ abort(): void;
177
+ setSessionName(name: string): void;
178
+ getSessionName(): string;
179
+ getSessionStats(): UnknownRecord$3;
180
+ getAllTools(): unknown[];
181
+ getActiveToolNames(): string[];
182
+ setActiveToolsByName(names: string[]): void;
183
+ bindExtensions(_bindings?: UnknownRecord$3): Promise<void>;
184
+ dispose(): Promise<void>;
185
+ }
186
+ //#endregion
187
+ //#region src/browser-surfaces.d.ts
188
+ /** One side thread as the panel renders it. */
189
+ interface PanelThreadView {
190
+ /** The child session's id, stable for the life of the thread. */
191
+ id: string;
192
+ /** Human label, already the one DSH's catalog shows. */
193
+ label: string;
194
+ /** Pi package that opened it, when known. */
195
+ package?: string;
196
+ /** Whether the child is mid-turn. */
197
+ running: boolean;
198
+ messages: Array<{
199
+ role: string;
200
+ text: string;
201
+ }>;
202
+ }
203
+ interface TrackedThread {
204
+ id: string;
205
+ label: string;
206
+ package: string | undefined;
207
+ session: PiBridgedAgentSession;
208
+ }
209
+ /**
210
+ * Live side threads, keyed by the parent session they belong to.
211
+ *
212
+ * Host-level (one per engine instance, like the provider directory): the panel
213
+ * is one surface, however many Pi packages contribute threads to it.
214
+ */
215
+ declare class BrowserSurfaces {
216
+ #private;
217
+ /** Register one known image tool's exact DSH wire name. */
218
+ registerImageTool(name: string): void;
219
+ /** Exact wire names needing the generic Pi image-result browser view. */
220
+ imageToolNames(): string[];
221
+ /**
222
+ * Track one child session under its parent.
223
+ * @param parentSessionId - the session the panel floats over.
224
+ * @param thread - the child's identity and live session object.
225
+ * @returns a disposer that removes the thread from the panel.
226
+ */
227
+ track(parentSessionId: string, thread: TrackedThread): () => void;
228
+ /**
229
+ * The panel's view of one parent session.
230
+ * @param parentSessionId - session the browser is currently showing.
231
+ * @returns every side thread opened under it, oldest first.
232
+ */
233
+ snapshot(parentSessionId: string): PanelThreadView[];
234
+ /**
235
+ * Pi's `setStatus(key, text)`: one keyed status entry in the status bar.
236
+ * The key is the entry's identity; passing undefined removes that entry,
237
+ * exactly like Pi clears one status.
238
+ * @param sessionId - session the calling agent belongs to.
239
+ * @param packageName - Pi package making the call, when known.
240
+ * @param key - the status entry's key.
241
+ * @param text - the text to show, or undefined to remove the entry.
242
+ */
243
+ setStatus(sessionId: string, packageName: string | undefined, key: string, text: unknown): void;
244
+ /**
245
+ * Pi's `setWidget(key, content)`: one keyed widget. Only string arrays are
246
+ * recorded — anything else is ignored exactly like Pi's own rpc mode, where
247
+ * widgets are transmitted to a host as lines and factory content needs TUI
248
+ * access the host never provides.
249
+ * @param sessionId - session the calling agent belongs to.
250
+ * @param packageName - Pi package making the call, when known.
251
+ * @param key - the widget's key.
252
+ * @param content - the widget's lines, or undefined to remove the widget.
253
+ */
254
+ setWidget(sessionId: string, packageName: string | undefined, key: string, content: unknown, theme?: unknown): void;
255
+ /**
256
+ * Record one simple presentation call (working chrome, title, header,
257
+ * footer). The value is a string, a Pi component, a working-indicator
258
+ * options object, or a header/footer factory; each renders to text here so
259
+ * the browser half never runs Pi code.
260
+ * @param sessionId - session the calling agent belongs to.
261
+ * @param packageName - Pi package making the call, when known.
262
+ * @param key - which surface.
263
+ * @param value - the value the package passed; undefined clears it.
264
+ * @param theme - the bridge's headless theme, for factories that style with it.
265
+ */
266
+ setSurface(sessionId: string, packageName: string | undefined, key: SurfaceKey, value: unknown, theme?: unknown): void;
267
+ /**
268
+ * Pi's `setWorkingVisible`: hide the working chrome without forgetting it.
269
+ * @param sessionId - session the calling agent belongs to.
270
+ * @param packageName - Pi package making the call, when known.
271
+ * @param visible - whether the working chrome should show.
272
+ */
273
+ setWorkingVisible(sessionId: string, packageName: string | undefined, visible: boolean): void;
274
+ /**
275
+ * Register one package's custom-entry renderer.
276
+ *
277
+ * Pulled rather than pushed: a renderer's output depends on the session being
278
+ * looked at, and the package registers once at mount for every session it
279
+ * will ever be asked about.
280
+ * @param packageName - owning Pi package.
281
+ * @param source - called with the session id the browser is showing.
282
+ * @returns a disposer that unregisters the source.
283
+ */
284
+ trackEntries(packageName: string, source: EntrySource): () => void;
285
+ /**
286
+ * Custom entries every package renders for one session, in package order.
287
+ * @param sessionId - session the browser is showing.
288
+ * @returns rendered entries; a renderer that throws contributes nothing.
289
+ */
290
+ entries(sessionId: string): RenderedEntry[];
291
+ /**
292
+ * Ask the browser to put text in the composer.
293
+ *
294
+ * A revision rather than a flag: the seat applies a request once, and the
295
+ * next call — even with identical text — is a new request rather than a
296
+ * no-op, which is what a package retrying a paste means.
297
+ * @param sessionId - session whose composer to write.
298
+ * @param text - the full next draft.
299
+ */
300
+ requestDraft(sessionId: string, text: string): void;
301
+ /**
302
+ * The pending composer write for one session, if any.
303
+ * @param sessionId - session the browser is showing.
304
+ * @returns the request, or undefined when nothing is pending.
305
+ */
306
+ draftRequest(sessionId: string): DraftRequest | undefined;
307
+ /**
308
+ * Record what the composer actually holds, as reported by the browser.
309
+ * @param sessionId - session the report is about.
310
+ * @param text - the live draft.
311
+ */
312
+ reportDraft(sessionId: string, text: string): void;
313
+ /**
314
+ * The composer text for one session.
315
+ * @param sessionId - session to read.
316
+ * @returns the browser's last report, or the last requested text.
317
+ */
318
+ liveDraft(sessionId: string): string;
319
+ /**
320
+ * Register one package's completion provider.
321
+ * @param packageName - owning Pi package.
322
+ * @param source - asked with the trigger character and the typed query.
323
+ * @returns a disposer that unregisters the source.
324
+ */
325
+ trackCompletions(packageName: string, source: CompletionSource): () => void;
326
+ /**
327
+ * Completions every package offers for one trigger token.
328
+ * @param trigger - the trigger character the menu opened on.
329
+ * @param query - what the user has typed after it.
330
+ * @returns candidates in package order; a provider that throws contributes none.
331
+ */
332
+ completions(trigger: string, query: string): Promise<CompletionItem[]>;
333
+ /**
334
+ * What packages have put on screen for one session.
335
+ * @param sessionId - session the browser is showing.
336
+ * @returns one entry per package that has driven a surface, empties dropped.
337
+ */
338
+ surfaces(sessionId: string): SurfaceView[];
339
+ }
340
+ /**
341
+ * Presentation slots a Pi package can drive, in DSH's browser shell. The
342
+ * keyed surfaces (status, widget) live on {@link SurfaceView.statuses} and
343
+ * {@link SurfaceView.widgets}; the simple ones live in `values`.
344
+ */
345
+ type SurfaceKey = 'workingMessage' | 'workingIndicator' | 'hiddenThinkingLabel' | 'title' | 'header' | 'footer';
346
+ /** One package's presentation state for one session. */
347
+ interface SurfaceView {
348
+ package?: string;
349
+ /** Simple string surfaces: working chrome, transient title, header, footer. */
350
+ values: Partial<Record<SurfaceKey, string>>;
351
+ /** Pi's `setStatus` entries, keyed by the entry key. */
352
+ statuses: Record<string, string>;
353
+ /** Pi's `setWidget` entries, keyed by the widget key. */
354
+ widgets: Record<string, string>;
355
+ /** Pi's setWorkingVisible: false hides the working chrome without clearing it. */
356
+ workingVisible: boolean;
357
+ }
358
+ /** One custom entry a package rendered for the conversation. */
359
+ interface RenderedEntry {
360
+ id: string;
361
+ customType: string;
362
+ package?: string;
363
+ text: string;
364
+ }
365
+ /** One pending composer write, with the revision the browser acknowledges. */
366
+ interface DraftRequest {
367
+ text: string;
368
+ rev: number;
369
+ }
370
+ /** One completion a Pi provider offered for a trigger token. */
371
+ interface CompletionItem {
372
+ value: string;
373
+ label: string;
374
+ description?: string;
375
+ }
376
+ /** A package's completion provider, asked with the token the user is typing. */
377
+ type CompletionSource = (trigger: string, query: string) => Promise<CompletionItem[]>;
378
+ /** A package's renderer, pulled at snapshot time for the session on screen. */
379
+ type EntrySource = (sessionId: string) => RenderedEntry[];
380
+ //#endregion
381
+ //#region src/compat/vendor/pi-ai-credential-store.d.ts
382
+ /**
383
+ * Default in-memory credential store. Apps inject persistent stores.
384
+ * Keyed by `Provider.id`, one credential per provider; see `CredentialStore`.
385
+ * Writes are serialized per provider through a promise chain.
386
+ */
387
+ declare class InMemoryCredentialStore {
388
+ credentials: Map<any, any>;
389
+ chains: Map<any, any>;
390
+ /** Serialize tasks per provider id without releasing the chain before active work settles. */
391
+ enqueue(providerId: any, task: any, options: any): Promise<unknown>;
392
+ read(providerId: any, options: any): Promise<any>;
393
+ list(options: any): Promise<{
394
+ providerId: any;
395
+ type: any;
396
+ }[]>;
397
+ modify(providerId: any, fn: any, options: any): Promise<unknown>;
398
+ delete(providerId: any, options: any): Promise<unknown>;
399
+ }
400
+ //#endregion
401
+ //#region src/oauth-bridge.d.ts
402
+ type UnknownRecord$2 = Record<string, unknown>;
403
+ declare class FileCredentialStore extends InMemoryCredentialStore {
404
+ #private;
405
+ constructor(path: string);
406
+ get path(): string;
407
+ modify(providerId: string, fn: (current: unknown) => unknown, options?: UnknownRecord$2): Promise<unknown>;
408
+ delete(providerId: string, options?: UnknownRecord$2): Promise<void>;
409
+ }
410
+ //#endregion
411
+ //#region src/model-bridge.d.ts
412
+ type UnknownRecord$1 = Record<string, unknown>;
413
+ interface DshLlmLike {
414
+ listProviders(): Array<{
415
+ id: string;
416
+ name: string;
417
+ }>;
418
+ listModels(provider: string): Promise<UnknownRecord$1[]>;
419
+ resolveModelInfo(provider: string, model: string, signal?: AbortSignal): Promise<UnknownRecord$1>;
420
+ stream(options: UnknownRecord$1): AsyncIterable<UnknownRecord$1>;
421
+ }
422
+ /** A DSH catalog entry in Pi's Model shape. */
423
+ interface PiModelShape {
424
+ id: string;
425
+ name: string;
426
+ provider: string;
427
+ api: string;
428
+ input: Array<'text' | 'image'>;
429
+ reasoning: boolean;
430
+ contextWindow?: number;
431
+ maxTokens?: number;
432
+ [key: string]: unknown;
433
+ }
434
+ /**
435
+ * Cached projection of DSH's advisory model catalog as Pi Model objects.
436
+ * `refresh()` re-reads providers and models; the runtime subscribes it to
437
+ * `llm/adapters-updated`. Reads are synchronous (Pi's getAll contract).
438
+ */
439
+ declare class ModelCatalog {
440
+ #private;
441
+ constructor(llm: DshLlmLike | undefined);
442
+ get present(): boolean;
443
+ all(): PiModelShape[];
444
+ find(provider: string, modelId: string): PiModelShape | undefined;
445
+ refresh(): Promise<void>;
446
+ /** Exact-route metadata (context window, reasoning efforts), cached per route. */
447
+ resolve(provider: string, modelId: string): Promise<PiModelShape | undefined>;
448
+ }
449
+ //#endregion
450
+ //#region src/provider-adapter.d.ts
451
+ /**
452
+ * A registered route's disposer, plus the ability to announce it again.
453
+ *
454
+ * A package's model list is not always known when the route is registered:
455
+ * gateway discovery needs a credential, and a credential may only arrive later
456
+ * (a `/login` mid-session). DSH publishes `llm/adapters-updated` when a route
457
+ * set is committed, and every directory observer — the browser's model picker
458
+ * included — refreshes on exactly that event. So a later discovery needs the
459
+ * route ANNOUNCED again, or the models exist and nobody looks.
460
+ */
461
+ interface PiRouteHandle {
462
+ (): void;
463
+ /** Re-commit this route so directory observers re-read its models. */
464
+ reannounce?(): void;
465
+ }
466
+ //#endregion
5
467
  //#region src/runtime.d.ts
6
468
  type UnknownRecord = Record<string, unknown>;
469
+ type PiHandler = (event: UnknownRecord, context: UnknownRecord) => unknown | Promise<unknown>;
470
+ declare function isKnownImageTool(packageName: string, toolName: string): boolean;
7
471
  interface RuntimeOptions {
8
472
  rootUrl: URL;
9
473
  manifest: GeneratedRuntimeManifest;
10
474
  config?: UnknownRecord;
11
475
  }
476
+ interface PiTool {
477
+ name: string;
478
+ label?: string;
479
+ description: string;
480
+ parameters: unknown;
481
+ /** Pi: one line for the system prompt's "Available tools" list. */
482
+ promptSnippet?: string;
483
+ /** Pi: guideline bullets that apply while this tool is active. */
484
+ promptGuidelines?: string[];
485
+ executionMode?: 'parallel' | 'sequential';
486
+ prepareArguments?: (args: unknown) => unknown;
487
+ execute(toolCallId: string, args: unknown, signal: AbortSignal | undefined, onUpdate: ((result: unknown) => void) | undefined, context: UnknownRecord): Promise<unknown>;
488
+ }
489
+ interface PiCommand {
490
+ name: string;
491
+ description: string;
492
+ argumentHint?: string;
493
+ handler(args: string, context: UnknownRecord): unknown | Promise<unknown>;
494
+ }
495
+ interface RuntimeState {
496
+ packageName: string;
497
+ handlers: Map<string, PiHandler[]>;
498
+ tools: Map<string, PiTool>;
499
+ runner: ExtensionRunner;
500
+ toolDisposers: Map<string, () => void>;
501
+ toolRestrictions: WeakMap<object, () => void>;
502
+ pendingActiveTools?: string[];
503
+ commands: Map<string, PiCommand>;
504
+ commandDisposers: Map<string, () => void>;
505
+ flags: Map<string, boolean | string | undefined>;
506
+ notifications: string[];
507
+ activeAgents: Set<UnknownRecord>;
508
+ disposedAgents: WeakSet<object>;
509
+ currentSystemPrompt: string;
510
+ messageSource: string;
511
+ eventBus: EventEmitter;
512
+ agentScope: AsyncLocalStorage<UnknownRecord | undefined>;
513
+ bridge: PiSessionBridge;
514
+ theme: Theme;
515
+ shortcuts: Map<string, UnknownRecord>;
516
+ messageRenderers: Map<string, unknown>;
517
+ entryRenderers: Map<string, unknown>;
518
+ markdownTransformer?: unknown;
519
+ providers: Map<string, UnknownRecord>;
520
+ autocompleteProviders: unknown[];
521
+ editorComponentFactory?: unknown;
522
+ editorBuffers: WeakMap<object, string>;
523
+ toolsExpanded: boolean;
524
+ modelOverrides: WeakMap<object, {
525
+ provider?: string;
526
+ model?: string;
527
+ }>;
528
+ thinkingLevels: WeakMap<object, string>;
529
+ turnSystemPromptOverrides: WeakMap<object, string>;
530
+ /**
531
+ * The single ordered stream for projections that must keep durable-log
532
+ * order. Several of them now await the attachment service (Pi's content
533
+ * blocks carry image bytes inline), and the subscribers that feed them are
534
+ * synchronous — without one shared chain a tool result with an image can be
535
+ * announced after the turn that produced it has already ended.
536
+ */
537
+ projection: Promise<unknown>;
538
+ /**
539
+ * Pi's `terminate` hint, accumulated across the current tool batch. Pi stops
540
+ * the loop only when EVERY finalized call in the batch asked for it, and a
541
+ * single call cannot know that — so the calls record here and the next step
542
+ * boundary reads the verdict.
543
+ */
544
+ terminateBatch: WeakMap<object, {
545
+ calls: number;
546
+ terminating: number;
547
+ }>;
548
+ /** Pi's turnIndex: reset when a DSH turn opens, incremented after each step. */
549
+ piTurnIndex: WeakMap<object, number>;
550
+ /** Messages DSH claimed for the step that is about to be assembled. */
551
+ claimedForStep: WeakMap<object, UnknownRecord[]>;
552
+ /** The turn each agent's before_agent_start has already fired for. */
553
+ promptedTurn: WeakMap<object, number>;
554
+ /** Custom messages a before_agent_start handler returned, awaiting the step. */
555
+ pendingInjections: WeakMap<object, UnknownRecord[]>;
556
+ globalThinkingLevel: string;
557
+ argMutations: WeakMap<object, unknown>;
558
+ streamingTexts: Map<string, string>;
559
+ lastLoggedModels: WeakMap<object, string>;
560
+ modelCatalog?: ModelCatalog;
561
+ companionRoutes: Map<string, string>;
562
+ providerRouteDisposers: Map<string, PiRouteHandle>;
563
+ publishedOAuthKeys: Map<string, string>;
564
+ shared: SharedHostState;
565
+ }
12
566
  declare function textBlocks(content: unknown): Array<{
13
567
  type: 'text';
14
568
  text: string;
@@ -47,6 +601,31 @@ declare function compactionReason(data: UnknownRecord): 'manual' | 'threshold' |
47
601
  * @param content - the DSH blocks to project.
48
602
  */
49
603
  declare function dshToPiContent(ctx: Context, content: readonly ContentBlock[]): Promise<Array<UnknownRecord>>;
604
+ interface SharedHostState {
605
+ companionRoutes: Map<string, string>;
606
+ providerRouteDisposers: Map<string, PiRouteHandle>;
607
+ publishedOAuthKeys: Map<string, string>;
608
+ providers: Map<string, UnknownRecord>;
609
+ modelCatalog?: ModelCatalog;
610
+ catalogSubscribed?: boolean;
611
+ loginRegistered?: boolean;
612
+ oauthRefreshHooked?: boolean;
613
+ companionSweepSubscribed?: boolean;
614
+ oauthStore?: FileCredentialStore;
615
+ capabilityLedger?: CapabilityLedger;
616
+ packageRemounts?: Map<string, () => Promise<void>>;
617
+ browserSurfaces?: BrowserSurfaces;
618
+ browserSurfacesRouted?: boolean;
619
+ activeLogin?: ActiveLogin | undefined;
620
+ }
621
+ interface ActiveLogin {
622
+ providerName: string;
623
+ controller: AbortController;
624
+ /** Settles when the flow has released its callback port. */
625
+ finished: Promise<void>;
626
+ /** Short links this flow published, retired when it ends. */
627
+ published: string[];
628
+ }
50
629
  /** Companion configuration: default (auto), `false` (off), or an explicit narrow map. */
51
630
  type VisionCompanionsConfig = false | Record<string, readonly string[]> | undefined;
52
631
  /**
@@ -67,16 +646,37 @@ type VisionCompanionsConfig = false | Record<string, readonly string[]> | undefi
67
646
  * (companionRoutes). Idempotent per host.
68
647
  */
69
648
  declare function registerVisionCompanions(ctx: Context, config: VisionCompanionsConfig): void;
649
+ /**
650
+ * Turn what the user answered into one of the offered options.
651
+ * @param answer - the label, a differently-cased label, or a 1-based position.
652
+ * @param offered - the options as they were shown, in order.
653
+ * @returns the matching option, or undefined when nothing matches.
654
+ */
655
+ declare function resolveOfferedChoice(answer: string, offered: readonly string[]): string | undefined;
656
+ /**
657
+ * Cancel the login already in flight, if any, and wait for it to let go.
658
+ *
659
+ * Waiting matters: the next flow binds the same fixed callback port, and Pi's
660
+ * flow answers a taken port by silently degrading to a listener that never
661
+ * receives a code. Starting the new flow before the old one has closed
662
+ * reproduces exactly that.
663
+ * @param state - the mounting package's state, holding the shared host state.
664
+ * @returns the cancelled provider's name, or undefined when nothing was running.
665
+ */
666
+ declare function supersedeActiveLogin(state: RuntimeState): Promise<string | undefined>;
70
667
  declare function splitArguments(input: string): string[];
71
668
  declare function expandPrompt(text: string, rawInput: string): string;
72
669
  declare function applyPiPackage(ctx: Context, options: RuntimeOptions): Promise<void>;
73
670
  declare const runtimeInternals: {
74
671
  compactionReason: typeof compactionReason;
672
+ resolveOfferedChoice: typeof resolveOfferedChoice;
75
673
  dshToPiContent: typeof dshToPiContent;
76
674
  expandPrompt: typeof expandPrompt;
675
+ isKnownImageTool: typeof isKnownImageTool;
77
676
  isSubagentOrigin: typeof isSubagentOrigin;
78
677
  normalizeToolResult: typeof normalizeToolResult;
79
678
  splitArguments: typeof splitArguments;
679
+ supersedeActiveLogin: typeof supersedeActiveLogin;
80
680
  textBlocks: typeof textBlocks;
81
681
  };
82
682
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/runtime.ts"],"mappings":";;;;;KAuCK,gBAAgB;UAGX;EACR,SAAS;EACT,UAAU;EACV,SAAS;;iBAkLF,WAAW,mBAAmB;EAAQ;EAAc;;iBAcpD,oBAAoB,kBAAkB;iBAuH/B,oBAAoB;EAAoB,QAAQ;EAAe;;iBA8EtE,iBAAiB,SAAS;;;;;;;;;;;;;;;;iBAquB1B,iBAAiB,MAAM;;;;;;;;;;;;iBAgBjB,eAAe,KAAK,SAAS,kBAAkB,iBAAiB,QAAQ,MAAM;;KA+tBjF,iCAAiC;;;;;;;;;;;;;;;;;;iBAmB7B,yBAAyB,KAAK,SAAS,QAAQ;iBAo6BtD,eAAe;iBA+Bf,aAAa,cAAc;iBA2Id,eAAe,KAAK,SAAS,SAAS,iBAAiB;cAqMhE"}
1
+ {"version":3,"file":"runtime.d.mts","names":[],"sources":["../src/capability.ts","../src/session-bridge.ts","../src/subagent-bridge.ts","../src/browser-surfaces.ts","../src/compat/vendor/pi-ai-credential-store.ts","../src/oauth-bridge.ts","../src/model-bridge.ts","../src/provider-adapter.ts","../src/runtime.ts"],"mappings":"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"}
package/dist/runtime.mjs CHANGED
@@ -1,3 +1,3 @@
1
1
 
2
- import { i as runtimeInternals, n as normalizeToolSchema, r as registerVisionCompanions, t as applyPiPackage } from "./runtime-B_Ig28og.mjs";
2
+ import { i as runtimeInternals, n as normalizeToolSchema, r as registerVisionCompanions, t as applyPiPackage } from "./runtime-B-SlR8mJ.mjs";
3
3
  export { applyPiPackage, normalizeToolSchema, registerVisionCompanions, runtimeInternals };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi2dsh",
3
- "version": "0.12.3",
3
+ "version": "0.13.0",
4
4
  "description": "Bridge the Pi and DeepSeek Harness ecosystems: a general Pi Host ABI that runs unmodified Pi extensions as native DSH plugins, plus per-package conversion and MCP config translation.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -52,6 +52,7 @@
52
52
  "prepare": "tsdown",
53
53
  "test": "pnpm build && vitest run",
54
54
  "test:community": "pnpm build && node scripts/verify-community.mjs --generate community/runtime-results.json",
55
+ "test:codex-image": "pnpm build && node scripts/verify-codex-image-gen-e2e.mjs",
55
56
  "test:coverage": "pnpm build && vitest run --coverage",
56
57
  "test:dsh": "pnpm build && vitest run tests/dsh-runtime.spec.ts",
57
58
  "test:examples": "pnpm build && node scripts/verify-examples-e2e.mjs",