paseo-plugin-zcode-provider 0.0.0-stage → 0.2.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 (141) hide show
  1. package/LICENSE +21 -0
  2. package/NOTICE.md +29 -0
  3. package/README.md +112 -2
  4. package/client/account.tsx +827 -0
  5. package/client/diagnostics.tsx +379 -0
  6. package/client/runtime.tsx +296 -0
  7. package/client/settings.tsx +84 -0
  8. package/client/value.tsx +20 -0
  9. package/icon.svg +1 -0
  10. package/index.client.tsx +22 -0
  11. package/index.server.ts +39 -0
  12. package/package.json +77 -4
  13. package/paseo-plugin.json +6 -0
  14. package/server/account.ts +781 -0
  15. package/server/attachments.ts +150 -0
  16. package/server/build-info.ts +2 -0
  17. package/server/conversation.ts +319 -0
  18. package/server/diagnostics.ts +252 -0
  19. package/server/discovery/discover.ts +225 -0
  20. package/server/discovery/manifest.ts +36 -0
  21. package/server/discovery/types.ts +30 -0
  22. package/server/errors.ts +36 -0
  23. package/server/host/bridge.ts +490 -0
  24. package/server/host/schemas.ts +119 -0
  25. package/server/logger.ts +19 -0
  26. package/server/mapping.ts +270 -0
  27. package/server/models.ts +68 -0
  28. package/server/persistence.ts +146 -0
  29. package/server/presentation.ts +470 -0
  30. package/server/provider-status.ts +81 -0
  31. package/server/provider.ts +838 -0
  32. package/server/runtime/managed.ts +501 -0
  33. package/server/runtime/pins.ts +72 -0
  34. package/server/runtime-setup.ts +77 -0
  35. package/server/session-types.ts +49 -0
  36. package/server/session.ts +866 -0
  37. package/server/status.ts +89 -0
  38. package/server/timeline.ts +18 -0
  39. package/server/usage.ts +362 -0
  40. package/server/vendor/zcode/LICENSE +202 -0
  41. package/server/vendor/zcode/NOTICE.md +70 -0
  42. package/server/vendor/zcode/THIRD-PARTY-NOTICES.md +37 -0
  43. package/server/vendor/zcode/packages/model-option-map/src/compiler.ts +92 -0
  44. package/server/vendor/zcode/packages/model-option-map/src/evaluator.ts +214 -0
  45. package/server/vendor/zcode/packages/model-option-map/src/index.ts +5 -0
  46. package/server/vendor/zcode/packages/model-option-map/src/merge-patch.ts +97 -0
  47. package/server/vendor/zcode/packages/model-option-map/src/option-maps.ts +42 -0
  48. package/server/vendor/zcode/packages/model-option-map/src/parser.ts +240 -0
  49. package/server/vendor/zcode/packages/model-option-map/src/tokenizer.ts +141 -0
  50. package/server/vendor/zcode/packages/model-option-map/src/types.ts +36 -0
  51. package/server/vendor/zcode/packages/rpc/src/buffer.ts +88 -0
  52. package/server/vendor/zcode/packages/rpc/src/channelClient.ts +275 -0
  53. package/server/vendor/zcode/packages/rpc/src/channelServer.ts +283 -0
  54. package/server/vendor/zcode/packages/rpc/src/channels.shared.ts +66 -0
  55. package/server/vendor/zcode/packages/rpc/src/channels.ts +4 -0
  56. package/server/vendor/zcode/packages/rpc/src/delayedChannel.ts +17 -0
  57. package/server/vendor/zcode/packages/rpc/src/foundation.ts +260 -0
  58. package/server/vendor/zcode/packages/rpc/src/protocol.ts +397 -0
  59. package/server/vendor/zcode/packages/rpc/src/proxy-channel.ts +213 -0
  60. package/server/vendor/zcode/packages/rpc/src/serialization.ts +291 -0
  61. package/server/vendor/zcode/packages/shared/src/account-provider-state.ts +13 -0
  62. package/server/vendor/zcode/packages/shared/src/background-bash-output.ts +24 -0
  63. package/server/vendor/zcode/packages/shared/src/background-task-controls.ts +404 -0
  64. package/server/vendor/zcode/packages/shared/src/bash-output-display.ts +11 -0
  65. package/server/vendor/zcode/packages/shared/src/bots.ts +558 -0
  66. package/server/vendor/zcode/packages/shared/src/browser-use/backend.ts +80 -0
  67. package/server/vendor/zcode/packages/shared/src/browser-use/command-metadata.ts +170 -0
  68. package/server/vendor/zcode/packages/shared/src/browser-use/commands.ts +588 -0
  69. package/server/vendor/zcode/packages/shared/src/browser-use/result.ts +130 -0
  70. package/server/vendor/zcode/packages/shared/src/browser-use/snapshot.ts +77 -0
  71. package/server/vendor/zcode/packages/shared/src/command-types.ts +96 -0
  72. package/server/vendor/zcode/packages/shared/src/config-schema.ts +8 -0
  73. package/server/vendor/zcode/packages/shared/src/cuaAccessibilitySettings.ts +41 -0
  74. package/server/vendor/zcode/packages/shared/src/database-startup.ts +178 -0
  75. package/server/vendor/zcode/packages/shared/src/env.ts +63 -0
  76. package/server/vendor/zcode/packages/shared/src/execution-output-preview.ts +14 -0
  77. package/server/vendor/zcode/packages/shared/src/localTtft.ts +192 -0
  78. package/server/vendor/zcode/packages/shared/src/model-config.ts +123 -0
  79. package/server/vendor/zcode/packages/shared/src/model-execution.ts +23 -0
  80. package/server/vendor/zcode/packages/shared/src/model-provider-family.ts +171 -0
  81. package/server/vendor/zcode/packages/shared/src/model-provider-types.ts +81 -0
  82. package/server/vendor/zcode/packages/shared/src/model-selection.ts +60 -0
  83. package/server/vendor/zcode/packages/shared/src/oauth.ts +203 -0
  84. package/server/vendor/zcode/packages/shared/src/official-mcp-auth.ts +272 -0
  85. package/server/vendor/zcode/packages/shared/src/official-mcp-tool-error.ts +68 -0
  86. package/server/vendor/zcode/packages/shared/src/process-diagnostic.ts +42 -0
  87. package/server/vendor/zcode/packages/shared/src/protocol.ts +369 -0
  88. package/server/vendor/zcode/packages/shared/src/provider-family-connection-selection.ts +32 -0
  89. package/server/vendor/zcode/packages/shared/src/remoteAssetInstallMode.ts +11 -0
  90. package/server/vendor/zcode/packages/shared/src/remoteResourcePackages.ts +91 -0
  91. package/server/vendor/zcode/packages/shared/src/runtimeEnv.ts +315 -0
  92. package/server/vendor/zcode/packages/shared/src/settings-source.ts +10 -0
  93. package/server/vendor/zcode/packages/shared/src/usage-quota.ts +74 -0
  94. package/server/vendor/zcode/packages/shared/src/usage-stats.ts +462 -0
  95. package/server/vendor/zcode/packages/shared/src/validationAppSettings.ts +562 -0
  96. package/server/vendor/zcode/packages/shared/src/workspacePurpose.ts +2 -0
  97. package/server/vendor/zcode/packages/shared/src/wslUserValidation.ts +33 -0
  98. package/server/vendor/zcode/packages/shared/src/zcode-agent-policy.ts +25 -0
  99. package/server/vendor/zcode/packages/shared/src/zcode-media-policy.ts +10 -0
  100. package/server/vendor/zcode/packages/shared/src/zcode-protocol/index.ts +3720 -0
  101. package/server/vendor/zcode/packages/shared/src/zcode-protocol-legacy-types.ts +529 -0
  102. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.ts +218 -0
  103. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/attachment-ref.ts +14 -0
  104. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/command.ts +482 -0
  105. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/core.ts +100 -0
  106. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-workflow-display.ts +156 -0
  107. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/cuaPermission.ts +41 -0
  108. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/delta.ts +147 -0
  109. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/input-intent.ts +69 -0
  110. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.ts +432 -0
  111. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/session-config.ts +43 -0
  112. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index-workflow-activity.ts +195 -0
  113. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index.ts +85 -0
  114. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-import.ts +38 -0
  115. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-ref.ts +10 -0
  116. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.ts +509 -0
  117. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/submission.ts +5 -0
  118. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/toolDisplay.ts +264 -0
  119. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.ts +1152 -0
  120. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.ts +574 -0
  121. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-binary.ts +65 -0
  122. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-codec.ts +240 -0
  123. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-fault.ts +39 -0
  124. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire.ts +159 -0
  125. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-artifacts.ts +291 -0
  126. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-observation-display.ts +281 -0
  127. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-row-meta.ts +163 -0
  128. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-run-settings-command.ts +62 -0
  129. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs-delta.ts +517 -0
  130. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs.ts +512 -0
  131. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-config.ts +81 -0
  132. package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-hook-review.ts +210 -0
  133. package/server/vendor/zcode/packages/shared/src/zcode-task-mode-schema.ts +6 -0
  134. package/server/vendor/zcode/packages/shared/src/zcode-task-types-core.ts +1187 -0
  135. package/server/vendor/zcode/packages/shared/src/zcodeEndpoint.ts +296 -0
  136. package/server/vendor/zcode/provenance.json +405 -0
  137. package/shared/account.ts +201 -0
  138. package/shared/diagnostics.ts +52 -0
  139. package/shared/runtime-setup.ts +73 -0
  140. package/vendor/acp-registry/LICENSE +176 -0
  141. package/vendor/paseo/LICENSE +211 -0
@@ -0,0 +1,490 @@
1
+ import { spawn, type ChildProcessWithoutNullStreams } from "node:child_process";
2
+ import { once } from "node:events";
3
+ import { z } from "zod";
4
+ import {
5
+ CancellationTokenSource,
6
+ Emitter,
7
+ } from "../vendor/zcode/packages/rpc/src/foundation.js";
8
+ import { VSBuffer } from "../vendor/zcode/packages/rpc/src/buffer.js";
9
+ import { SocketProtocol } from "../vendor/zcode/packages/rpc/src/protocol.js";
10
+ import { ChannelClient } from "../vendor/zcode/packages/rpc/src/channelClient.js";
11
+ import {
12
+ helloMessageSchema,
13
+ conversationTopicWireCandidateSchema,
14
+ type ConversationTopicWireCandidate,
15
+ v4ConversationSubscribeResultSchema,
16
+ } from "../vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.js";
17
+ import {
18
+ assertRuntimeSupported,
19
+ runtimeEnvironment,
20
+ } from "../discovery/discover.js";
21
+ import type { DiscoveredRuntime } from "../discovery/types.js";
22
+ import { AdapterError } from "../errors.js";
23
+ import {
24
+ diagnosticError,
25
+ runtimeDiagnostic,
26
+ type RuntimeDiagnostic,
27
+ } from "../diagnostics.js";
28
+ import type { Logger } from "../logger.js";
29
+ import { PROVIDER_VERSION } from "../build-info.js";
30
+
31
+ export type SettingsChannel =
32
+ | "oauth"
33
+ | "setting"
34
+ | "provider-settings"
35
+ | "usage-stats";
36
+
37
+ export interface HostSubscription {
38
+ readonly id: string;
39
+ dispose(): Promise<void>;
40
+ }
41
+ export interface HostBridge {
42
+ readonly diagnostic: RuntimeDiagnostic;
43
+ onFailure(listener: (error: AdapterError) => void): () => void;
44
+ request<Schema extends z.ZodType>(
45
+ method: string,
46
+ params: unknown,
47
+ resultSchema: Schema,
48
+ timeoutMs?: number,
49
+ diagnosticContext?: {
50
+ readonly sessionId: string;
51
+ readonly inputId: string;
52
+ },
53
+ ): Promise<z.output<Schema>>;
54
+ subscribe(
55
+ target: { workspacePath: string; sessionId: string },
56
+ handler: (frame: ConversationTopicWireCandidate) => Promise<void> | void,
57
+ ): Promise<HostSubscription>;
58
+ close(): Promise<void>;
59
+ }
60
+ const nativeViewSchema = z.object({
61
+ revision: z.number(),
62
+ providers: z.array(
63
+ z.object({
64
+ providerId: z.string(),
65
+ providerName: z.string(),
66
+ models: z.array(
67
+ z.object({
68
+ modelId: z.string(),
69
+ config: z.object({
70
+ optionSpecs: z.object({
71
+ reasoningLevel: z.object({ values: z.array(z.string()) }),
72
+ }),
73
+ }),
74
+ }),
75
+ ),
76
+ }),
77
+ ),
78
+ preferredSelection: z.unknown().optional(),
79
+ effectiveSelection: z.unknown().optional(),
80
+ selectionIssue: z.unknown().optional(),
81
+ });
82
+ function projectModelSelection(value: unknown) {
83
+ const view = nativeViewSchema.parse(value);
84
+ const { providers, ...selection } = view;
85
+ return {
86
+ ...selection,
87
+ models: view.providers.flatMap((provider) =>
88
+ provider.models.map((model) => ({
89
+ ref: { providerId: provider.providerId, modelId: model.modelId },
90
+ label: model.modelId,
91
+ providerLabel: provider.providerName,
92
+ reasoningLevels: model.config.optionSpecs.reasoningLevel.values,
93
+ })),
94
+ ),
95
+ };
96
+ }
97
+ export class ZCodeHostBridge implements HostBridge {
98
+ private readonly failures = new Set<(error: AdapterError) => void>();
99
+ private failure?: AdapterError;
100
+ private closing?: Promise<void>;
101
+ private readonly exited: Promise<void>;
102
+ private client?: ChannelClient;
103
+ private protocol?: SocketProtocol;
104
+ private readonly ready: Promise<void>;
105
+ private readonly subscriptions = new Set<HostSubscription>();
106
+ private constructor(
107
+ private readonly child: ChildProcessWithoutNullStreams,
108
+ private readonly runtime: DiscoveredRuntime,
109
+ private readonly logger: Logger,
110
+ ) {
111
+ this.exited = new Promise((resolve) => {
112
+ child.once("error", () => resolve());
113
+ child.once("exit", (code) => {
114
+ resolve();
115
+ if (!this.closing)
116
+ this.fail(
117
+ new AdapterError(
118
+ "NATIVE_EXITED",
119
+ "ZCode Server exited",
120
+ {},
121
+ {},
122
+ { ...this.diagnostic, exitCode: code ?? 1 },
123
+ ),
124
+ );
125
+ });
126
+ });
127
+ child.stderr.resume(); // Never log raw native output: it may contain credentials or prompts.
128
+ child.stdin.on("error", () =>
129
+ this.fail(new AdapterError("NATIVE_EXITED", "ZCode Server input closed")),
130
+ );
131
+ this.ready = this.initialize();
132
+ void this.ready.catch((error) => this.fail(error));
133
+ }
134
+ static start(
135
+ runtime: DiscoveredRuntime,
136
+ logger: Logger,
137
+ environment: NodeJS.ProcessEnv = process.env,
138
+ workspace = runtime.paths.installRoot,
139
+ ): ZCodeHostBridge {
140
+ assertRuntimeSupported(runtime);
141
+ const child = spawn(runtime.paths.executable, [runtime.paths.serverEntry], {
142
+ cwd: workspace,
143
+ env: {
144
+ ...runtimeEnvironment(environment),
145
+ ZCODE_SERVICE_AUTHORITY_MODE: "standalone-server",
146
+ ZCODE_AGENT_SERVER_COMMAND: runtime.paths.executable,
147
+ ZCODE_AGENT_SERVER_ARGS_JSON: JSON.stringify([
148
+ runtime.paths.cliEntry,
149
+ "app-server",
150
+ "--stdio",
151
+ ]),
152
+ },
153
+ stdio: ["pipe", "pipe", "pipe"],
154
+ windowsHide: true,
155
+ });
156
+ return new ZCodeHostBridge(child, runtime, logger);
157
+ }
158
+ private async initialize(): Promise<void> {
159
+ const hello = await new Promise<unknown>((resolve, reject) => {
160
+ let buffer = Buffer.alloc(0);
161
+ const timer = setTimeout(
162
+ () =>
163
+ finish(
164
+ new AdapterError(
165
+ "NATIVE_TIMEOUT",
166
+ "ZCode Server handshake timed out",
167
+ ),
168
+ ),
169
+ 10_000,
170
+ );
171
+ const exit = () =>
172
+ finish(
173
+ new AdapterError(
174
+ "NATIVE_EXITED",
175
+ "ZCode Server exited before handshake",
176
+ ),
177
+ );
178
+ const finish = (error?: unknown, value?: unknown) => {
179
+ clearTimeout(timer);
180
+ this.child.stdout.off("data", data);
181
+ this.child.off("exit", exit);
182
+ this.child.off("error", finish);
183
+ error ? reject(error) : resolve(value);
184
+ };
185
+ const data = (chunk: Buffer) => {
186
+ buffer = Buffer.concat([buffer, chunk]);
187
+ if (buffer.length > 64 * 1024) {
188
+ finish(
189
+ new AdapterError(
190
+ "NATIVE_PROTOCOL_ERROR",
191
+ "ZCode Server handshake is too large",
192
+ ),
193
+ );
194
+ return;
195
+ }
196
+ const end = buffer.indexOf(10);
197
+ if (end < 0) return;
198
+ this.child.stdout.pause();
199
+ try {
200
+ const parsed = JSON.parse(buffer.subarray(0, end).toString("utf8"));
201
+ finish(undefined, parsed);
202
+ if (buffer.length > end + 1)
203
+ this.child.stdout.unshift(buffer.subarray(end + 1));
204
+ } catch {
205
+ finish(
206
+ new AdapterError(
207
+ "NATIVE_PROTOCOL_ERROR",
208
+ "Invalid ZCode Server handshake",
209
+ ),
210
+ );
211
+ }
212
+ };
213
+ this.child.stdout.on("data", data);
214
+ this.child.once("exit", exit);
215
+ this.child.once("error", finish);
216
+ });
217
+ const checked = z
218
+ .object({
219
+ type: z.literal("zcode-hello"),
220
+ version: z.literal(this.runtime.identity.appVersion),
221
+ platform: z.string(),
222
+ arch: z.string(),
223
+ pid: z.number().int().positive(),
224
+ })
225
+ .parse(hello);
226
+ if (
227
+ `${checked.platform}-${checked.arch}` !==
228
+ this.runtime.identity.platform ||
229
+ checked.pid !== this.child.pid
230
+ )
231
+ throw new AdapterError(
232
+ "NATIVE_PROTOCOL_ERROR",
233
+ "ZCode Server runtime identity changed",
234
+ );
235
+ const onData = new Emitter<VSBuffer>(),
236
+ onClose = new Emitter<void>(),
237
+ onEnd = new Emitter<void>();
238
+ this.protocol = new SocketProtocol({
239
+ onData: onData.event,
240
+ onClose: onClose.event,
241
+ onEnd: onEnd.event,
242
+ write: (buffer) => {
243
+ if (!this.child.stdin.writable) throw new Error("Server input closed");
244
+ this.child.stdin.write(Buffer.from(buffer.buffer));
245
+ },
246
+ end: () => this.child.stdin.end(),
247
+ drain: async () => {
248
+ if (this.child.stdin.writableNeedDrain)
249
+ await once(this.child.stdin, "drain");
250
+ },
251
+ dispose: () => {
252
+ onData.dispose();
253
+ onClose.dispose();
254
+ onEnd.dispose();
255
+ },
256
+ });
257
+ this.client = new ChannelClient(this.protocol);
258
+ this.child.stdout.on("data", (chunk) => {
259
+ try {
260
+ onData.fire(VSBuffer.wrap(chunk));
261
+ } catch (error) {
262
+ this.fail(error);
263
+ }
264
+ });
265
+ this.child.stdout.resume();
266
+ this.child.stdin.write(
267
+ JSON.stringify({
268
+ type: "zcode-hello-ack",
269
+ version: PROVIDER_VERSION,
270
+ clientId: "paseo-zcode-provider",
271
+ }) + "\n",
272
+ );
273
+ const v4 = helloMessageSchema.parse(
274
+ await this.call("zcode-agent", "helloConversationV4", [], 10_000),
275
+ );
276
+ if (
277
+ v4.clientMode !== "desktop-continuous" ||
278
+ v4.capabilities.independentPlanState !== true
279
+ )
280
+ throw new AdapterError(
281
+ "UNSUPPORTED_ZCODE",
282
+ "ZCode V4 conversation contract is unsupported",
283
+ );
284
+ await this.call(
285
+ "zcode-agent",
286
+ "initializeConversationV4",
287
+ [
288
+ {
289
+ kind: "clientHello",
290
+ protocolVersion: 3,
291
+ clientId: "paseo-zcode-provider",
292
+ appVersion: PROVIDER_VERSION,
293
+ },
294
+ ],
295
+ 10_000,
296
+ );
297
+ await this.call(
298
+ "zcode-agent",
299
+ "syncAppRuntimePreferences",
300
+ [{ askUserQuestionAutoResolutionEnabled: false }],
301
+ 10_000,
302
+ );
303
+ }
304
+ get diagnostic(): RuntimeDiagnostic {
305
+ return runtimeDiagnostic(this.runtime);
306
+ }
307
+ onFailure(listener: (error: AdapterError) => void): () => void {
308
+ this.failures.add(listener);
309
+ if (this.failure) listener(this.failure);
310
+ return () => this.failures.delete(listener);
311
+ }
312
+ private fail(error: unknown): void {
313
+ if (this.failure || this.closing) return;
314
+ this.failure = diagnosticError(error, {
315
+ ...this.diagnostic,
316
+ stage: "transport",
317
+ });
318
+ this.client?.dispose();
319
+ for (const listener of this.failures) listener(this.failure);
320
+ void this.close();
321
+ }
322
+ private async call(
323
+ channel: string,
324
+ method: string,
325
+ args: readonly unknown[],
326
+ timeoutMs: number,
327
+ ): Promise<unknown> {
328
+ if (!this.client)
329
+ throw new AdapterError("NATIVE_EXITED", "ZCode RPC is unavailable");
330
+ const cancellation = new CancellationTokenSource();
331
+ let timer: ReturnType<typeof setTimeout> | undefined;
332
+ try {
333
+ return await Promise.race([
334
+ this.client.getChannel(channel).call(method, args, cancellation.token),
335
+ new Promise<never>((_, reject) => {
336
+ timer = setTimeout(() => {
337
+ reject(new AdapterError("NATIVE_TIMEOUT", "ZCode RPC timed out"));
338
+ cancellation.cancel();
339
+ }, timeoutMs);
340
+ }),
341
+ ]);
342
+ } finally {
343
+ clearTimeout(timer);
344
+ cancellation.dispose();
345
+ }
346
+ }
347
+ private async ensureOpen(): Promise<void> {
348
+ await this.ready;
349
+ if (this.failure) throw this.failure;
350
+ if (this.closing)
351
+ throw new AdapterError("NATIVE_EXITED", "ZCode Server is closing");
352
+ }
353
+ async request<Schema extends z.ZodType>(
354
+ method: string,
355
+ params: unknown,
356
+ resultSchema: Schema,
357
+ timeoutMs = 30_000,
358
+ ): Promise<z.output<Schema>> {
359
+ try {
360
+ await this.ensureOpen();
361
+ const args = params === undefined ? [] : [params];
362
+ let result: unknown;
363
+ if (method === "readModelSelection")
364
+ result = projectModelSelection(
365
+ await this.call("model-selection", "getView", args, timeoutMs),
366
+ );
367
+ else
368
+ result = await this.call(
369
+ method === "getEntitlementSnapshot" ||
370
+ method === "getCodingPlanResetStatus"
371
+ ? "usage-stats"
372
+ : "zcode-agent",
373
+ method,
374
+ args,
375
+ timeoutMs,
376
+ );
377
+ return resultSchema.parse(result);
378
+ } catch (error) {
379
+ throw diagnosticError(error, {
380
+ ...this.diagnostic,
381
+ stage: "request",
382
+ operation: method,
383
+ });
384
+ }
385
+ }
386
+ /** Calls an official account or settings service with positional arguments. */
387
+ async invoke<Schema extends z.ZodType>(
388
+ channel: SettingsChannel,
389
+ method: string,
390
+ args: readonly unknown[],
391
+ resultSchema: Schema,
392
+ timeoutMs = 30_000,
393
+ ): Promise<z.output<Schema>> {
394
+ try {
395
+ await this.ensureOpen();
396
+ return resultSchema.parse(
397
+ await this.call(channel, method, args, timeoutMs),
398
+ );
399
+ } catch (error) {
400
+ throw diagnosticError(error, {
401
+ ...this.diagnostic,
402
+ stage: "request",
403
+ operation: `${channel}.${method}`,
404
+ });
405
+ }
406
+ }
407
+ async subscribe(
408
+ target: { workspacePath: string; sessionId: string },
409
+ handler: (frame: ConversationTopicWireCandidate) => Promise<void> | void,
410
+ ): Promise<HostSubscription> {
411
+ await this.ready;
412
+ let disposed = false;
413
+ const listener = this.client!.getChannel("zcode-agent").listen(
414
+ "onDynamicConversationFrame",
415
+ target,
416
+ )((value: unknown) => {
417
+ if (disposed) return;
418
+ try {
419
+ const frame = conversationTopicWireCandidateSchema.parse(value);
420
+ if (frame.topic === `conversation/${target.sessionId}`)
421
+ Promise.resolve(handler(frame)).catch((error) => this.fail(error));
422
+ } catch (error) {
423
+ this.fail(error);
424
+ }
425
+ });
426
+ try {
427
+ const result = await this.request(
428
+ "subscribeConversationV4",
429
+ target,
430
+ v4ConversationSubscribeResultSchema,
431
+ );
432
+ const subscription: HostSubscription = {
433
+ id: result.ack.subscriptionId,
434
+ dispose: async () => {
435
+ if (disposed) return;
436
+ disposed = true;
437
+ listener.dispose();
438
+ this.subscriptions.delete(subscription);
439
+ if (!this.closing && !this.failure)
440
+ await this.request(
441
+ "unsubscribeConversationV4",
442
+ {
443
+ workspacePath: target.workspacePath,
444
+ subscriptionId: subscription.id,
445
+ },
446
+ z.void(),
447
+ );
448
+ },
449
+ };
450
+ this.subscriptions.add(subscription);
451
+ return subscription;
452
+ } catch (error) {
453
+ disposed = true;
454
+ listener.dispose();
455
+ throw error;
456
+ }
457
+ }
458
+ close(): Promise<void> {
459
+ this.closing ??= Promise.resolve().then(() => this.closeInternal());
460
+ return this.closing;
461
+ }
462
+ private async closeInternal(): Promise<void> {
463
+ this.failures.clear();
464
+ for (const subscription of this.subscriptions) await subscription.dispose();
465
+ this.client?.dispose();
466
+ this.protocol?.dispose();
467
+ this.child.stdin.end();
468
+ if (await waitForExit(this.exited, 6_000)) return;
469
+ this.child.kill("SIGTERM");
470
+ if (await waitForExit(this.exited, 5_000)) return;
471
+ this.child.kill("SIGKILL");
472
+ await this.exited;
473
+ }
474
+ }
475
+ async function waitForExit(
476
+ exited: Promise<void>,
477
+ ms: number,
478
+ ): Promise<boolean> {
479
+ let timer: ReturnType<typeof setTimeout> | undefined;
480
+ try {
481
+ return await Promise.race([
482
+ exited.then(() => true),
483
+ new Promise<false>((r) => {
484
+ timer = setTimeout(() => r(false), ms);
485
+ }),
486
+ ]);
487
+ } finally {
488
+ clearTimeout(timer);
489
+ }
490
+ }
@@ -0,0 +1,119 @@
1
+ import { z } from "zod";
2
+
3
+ export const InitializeResultSchema = z
4
+ .object({
5
+ available: z.boolean(),
6
+ workspaceKey: z.string().min(1).optional(),
7
+ protocolName: z.string().optional(),
8
+ protocolVersion: z.number().int().optional(),
9
+ transportKind: z.string().optional(),
10
+ reason: z.string().optional(),
11
+ reasonCode: z.string().optional(),
12
+ })
13
+ .passthrough();
14
+
15
+ export const ModelSelectionSchema = z
16
+ .object({
17
+ providerId: z.string().min(1),
18
+ modelId: z.string().min(1),
19
+ options: z
20
+ .object({ reasoningLevel: z.string().min(1).optional() })
21
+ .strict()
22
+ .optional(),
23
+ })
24
+ .strict();
25
+
26
+ const ModelOptionSchema = z
27
+ .object({
28
+ ref: ModelSelectionSchema,
29
+ label: z.string().min(1),
30
+ providerLabel: z.string().optional(),
31
+ reasoningLevels: z.array(z.string().min(1)).min(1).optional(),
32
+ })
33
+ .passthrough();
34
+
35
+ const ThoughtLevelOptionSchema = z
36
+ .object({ value: z.string().min(1), label: z.string().min(1) })
37
+ .passthrough();
38
+
39
+ export const SessionSettingsSchema = z
40
+ .object({
41
+ model: z
42
+ .object({
43
+ current: ModelSelectionSchema.optional(),
44
+ available: z.array(ModelOptionSchema),
45
+ })
46
+ .passthrough(),
47
+ thoughtLevel: z
48
+ .object({
49
+ enabled: z.boolean(),
50
+ current: z.string().optional(),
51
+ defaultLevel: z.string().optional(),
52
+ available: z.array(ThoughtLevelOptionSchema),
53
+ })
54
+ .passthrough(),
55
+ mode: z.object({ current: z.string().min(1) }).passthrough(),
56
+ })
57
+ .passthrough();
58
+
59
+ export const WorkspacePresentationSchema = z
60
+ .object({
61
+ workspace: z.object({ workspacePath: z.string().min(1) }).passthrough(),
62
+ mode: z.string().min(1),
63
+ })
64
+ .passthrough();
65
+
66
+ export const ModelSelectionViewSchema = z
67
+ .object({
68
+ revision: z.number().int().nonnegative(),
69
+ models: z.array(
70
+ ModelOptionSchema.extend({
71
+ reasoningLevels: z.array(z.string().min(1)).min(1),
72
+ }),
73
+ ),
74
+ preferredSelection: ModelSelectionSchema.optional(),
75
+ effectiveSelection: ModelSelectionSchema.nullable().optional(),
76
+ selectionIssue: z.string().optional(),
77
+ })
78
+ .strict();
79
+
80
+ export const SessionSnapshotSchema = z
81
+ .object({
82
+ session: z
83
+ .object({
84
+ sessionId: z.string().min(1),
85
+ status: z.string(),
86
+ workspace: z.object({ workspacePath: z.string().min(1) }).passthrough(),
87
+ title: z.string().optional(),
88
+ updatedAt: z.number().optional(),
89
+ })
90
+ .passthrough(),
91
+ settings: SessionSettingsSchema,
92
+ slashCommands: z.array(
93
+ z
94
+ .object({
95
+ name: z.string().min(1),
96
+ description: z.string(),
97
+ inputHint: z.string().optional(),
98
+ })
99
+ .passthrough(),
100
+ ),
101
+ })
102
+ .strip();
103
+
104
+ export const SessionListSchema = z.array(
105
+ z
106
+ .object({
107
+ sessionId: z.string().min(1),
108
+ workspace: z.object({ workspacePath: z.string().min(1) }).passthrough(),
109
+ title: z.string().optional(),
110
+ updatedAt: z.number().optional(),
111
+ })
112
+ .passthrough(),
113
+ );
114
+
115
+ export type SessionSnapshot = z.infer<typeof SessionSnapshotSchema>;
116
+ export type SessionSettings = z.infer<typeof SessionSettingsSchema>;
117
+ export type ModelOption = z.infer<typeof ModelOptionSchema>;
118
+ export type ModelSelection = z.infer<typeof ModelSelectionSchema>;
119
+ export type ModelSelectionView = z.infer<typeof ModelSelectionViewSchema>;
@@ -0,0 +1,19 @@
1
+ export interface Logger {
2
+ log(
3
+ level: "debug" | "info" | "warn" | "error",
4
+ event: string,
5
+ data?: Record<string, unknown>,
6
+ ): void;
7
+ error(event: string, error: unknown, data?: Record<string, unknown>): void;
8
+ }
9
+
10
+ // Native payloads and error messages may contain credentials or prompts. Never log them.
11
+ export const logger: Logger = {
12
+ log(level, event) {
13
+ if (level !== "debug") console.error(`[zcode:${level}] ${event}`);
14
+ },
15
+ error(event, error) {
16
+ console.error(`[zcode:error] ${event}\n${formatDiagnostic(error)}`);
17
+ },
18
+ };
19
+ import { formatDiagnostic } from "./diagnostics.js";