paseo-plugin-zcode-provider 0.0.0-stage → 0.1.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.
- package/LICENSE +21 -0
- package/NOTICE.md +29 -0
- package/README.md +98 -2
- package/client/diagnostics.tsx +397 -0
- package/client/setup.tsx +347 -0
- package/icon.svg +1 -0
- package/index.client.tsx +22 -0
- package/index.server.ts +21 -0
- package/package.json +75 -4
- package/paseo-plugin.json +6 -0
- package/server/attachments.ts +150 -0
- package/server/build-info.ts +2 -0
- package/server/conversation.ts +319 -0
- package/server/diagnostics.ts +235 -0
- package/server/discovery/discover.ts +225 -0
- package/server/discovery/manifest.ts +36 -0
- package/server/discovery/types.ts +30 -0
- package/server/errors.ts +36 -0
- package/server/host/bridge.ts +463 -0
- package/server/host/schemas.ts +119 -0
- package/server/logger.ts +19 -0
- package/server/mapping.ts +270 -0
- package/server/models.ts +68 -0
- package/server/persistence.ts +146 -0
- package/server/presentation.ts +428 -0
- package/server/provider.ts +831 -0
- package/server/runtime/managed.ts +501 -0
- package/server/runtime/pins.ts +72 -0
- package/server/runtime-setup.ts +102 -0
- package/server/session-types.ts +49 -0
- package/server/session.ts +866 -0
- package/server/status.ts +89 -0
- package/server/timeline.ts +18 -0
- package/server/vendor/zcode/LICENSE +202 -0
- package/server/vendor/zcode/NOTICE.md +70 -0
- package/server/vendor/zcode/THIRD-PARTY-NOTICES.md +37 -0
- package/server/vendor/zcode/packages/model-option-map/src/compiler.ts +92 -0
- package/server/vendor/zcode/packages/model-option-map/src/evaluator.ts +214 -0
- package/server/vendor/zcode/packages/model-option-map/src/index.ts +5 -0
- package/server/vendor/zcode/packages/model-option-map/src/merge-patch.ts +97 -0
- package/server/vendor/zcode/packages/model-option-map/src/option-maps.ts +42 -0
- package/server/vendor/zcode/packages/model-option-map/src/parser.ts +240 -0
- package/server/vendor/zcode/packages/model-option-map/src/tokenizer.ts +141 -0
- package/server/vendor/zcode/packages/model-option-map/src/types.ts +36 -0
- package/server/vendor/zcode/packages/rpc/src/buffer.ts +88 -0
- package/server/vendor/zcode/packages/rpc/src/channelClient.ts +275 -0
- package/server/vendor/zcode/packages/rpc/src/channelServer.ts +283 -0
- package/server/vendor/zcode/packages/rpc/src/channels.shared.ts +66 -0
- package/server/vendor/zcode/packages/rpc/src/channels.ts +4 -0
- package/server/vendor/zcode/packages/rpc/src/delayedChannel.ts +17 -0
- package/server/vendor/zcode/packages/rpc/src/foundation.ts +260 -0
- package/server/vendor/zcode/packages/rpc/src/protocol.ts +397 -0
- package/server/vendor/zcode/packages/rpc/src/proxy-channel.ts +213 -0
- package/server/vendor/zcode/packages/rpc/src/serialization.ts +291 -0
- package/server/vendor/zcode/packages/shared/src/account-provider-state.ts +13 -0
- package/server/vendor/zcode/packages/shared/src/background-bash-output.ts +24 -0
- package/server/vendor/zcode/packages/shared/src/background-task-controls.ts +404 -0
- package/server/vendor/zcode/packages/shared/src/bash-output-display.ts +11 -0
- package/server/vendor/zcode/packages/shared/src/bots.ts +558 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/backend.ts +80 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/command-metadata.ts +170 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/commands.ts +588 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/result.ts +130 -0
- package/server/vendor/zcode/packages/shared/src/browser-use/snapshot.ts +77 -0
- package/server/vendor/zcode/packages/shared/src/command-types.ts +96 -0
- package/server/vendor/zcode/packages/shared/src/config-schema.ts +8 -0
- package/server/vendor/zcode/packages/shared/src/cuaAccessibilitySettings.ts +41 -0
- package/server/vendor/zcode/packages/shared/src/database-startup.ts +178 -0
- package/server/vendor/zcode/packages/shared/src/env.ts +63 -0
- package/server/vendor/zcode/packages/shared/src/execution-output-preview.ts +14 -0
- package/server/vendor/zcode/packages/shared/src/localTtft.ts +192 -0
- package/server/vendor/zcode/packages/shared/src/model-config.ts +123 -0
- package/server/vendor/zcode/packages/shared/src/model-execution.ts +23 -0
- package/server/vendor/zcode/packages/shared/src/model-provider-family.ts +171 -0
- package/server/vendor/zcode/packages/shared/src/model-provider-types.ts +81 -0
- package/server/vendor/zcode/packages/shared/src/model-selection.ts +60 -0
- package/server/vendor/zcode/packages/shared/src/oauth.ts +203 -0
- package/server/vendor/zcode/packages/shared/src/official-mcp-auth.ts +272 -0
- package/server/vendor/zcode/packages/shared/src/official-mcp-tool-error.ts +68 -0
- package/server/vendor/zcode/packages/shared/src/process-diagnostic.ts +42 -0
- package/server/vendor/zcode/packages/shared/src/protocol.ts +369 -0
- package/server/vendor/zcode/packages/shared/src/provider-family-connection-selection.ts +32 -0
- package/server/vendor/zcode/packages/shared/src/remoteAssetInstallMode.ts +11 -0
- package/server/vendor/zcode/packages/shared/src/remoteResourcePackages.ts +91 -0
- package/server/vendor/zcode/packages/shared/src/runtimeEnv.ts +315 -0
- package/server/vendor/zcode/packages/shared/src/settings-source.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/usage-quota.ts +74 -0
- package/server/vendor/zcode/packages/shared/src/usage-stats.ts +462 -0
- package/server/vendor/zcode/packages/shared/src/validationAppSettings.ts +562 -0
- package/server/vendor/zcode/packages/shared/src/workspacePurpose.ts +2 -0
- package/server/vendor/zcode/packages/shared/src/wslUserValidation.ts +33 -0
- package/server/vendor/zcode/packages/shared/src/zcode-agent-policy.ts +25 -0
- package/server/vendor/zcode/packages/shared/src/zcode-media-policy.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol/index.ts +3720 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-legacy-types.ts +529 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.ts +218 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/attachment-ref.ts +14 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/command.ts +482 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/core.ts +100 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/create-workflow-display.ts +156 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/cuaPermission.ts +41 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/delta.ts +147 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/input-intent.ts +69 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.ts +432 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/session-config.ts +43 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index-workflow-activity.ts +195 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/sessions-index.ts +85 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-import.ts +38 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/shared-context-ref.ts +10 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.ts +509 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/submission.ts +5 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/toolDisplay.ts +264 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.ts +1152 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.ts +574 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-binary.ts +65 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-codec.ts +240 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-fault.ts +39 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/wire.ts +159 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-artifacts.ts +291 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-observation-display.ts +281 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-row-meta.ts +163 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-run-settings-command.ts +62 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs-delta.ts +517 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workflow-runs.ts +512 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-config.ts +81 -0
- package/server/vendor/zcode/packages/shared/src/zcode-protocol-v4/workspace-hook-review.ts +210 -0
- package/server/vendor/zcode/packages/shared/src/zcode-task-mode-schema.ts +6 -0
- package/server/vendor/zcode/packages/shared/src/zcode-task-types-core.ts +1187 -0
- package/server/vendor/zcode/packages/shared/src/zcodeEndpoint.ts +296 -0
- package/server/vendor/zcode/provenance.json +405 -0
- package/shared/diagnostics.ts +52 -0
- package/shared/runtime-setup.ts +75 -0
- package/vendor/acp-registry/LICENSE +176 -0
- package/vendor/paseo/LICENSE +211 -0
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { applyConversationDeltas } from "./vendor/zcode/packages/shared/src/zcode-protocol-v4/apply.js";
|
|
3
|
+
import { TopicWireFrameAssembler } from "./vendor/zcode/packages/shared/src/zcode-protocol-v4/wire-assembler.js";
|
|
4
|
+
import {
|
|
5
|
+
commandAckSchema,
|
|
6
|
+
parseCommandEnvelope,
|
|
7
|
+
} from "./vendor/zcode/packages/shared/src/zcode-protocol-v4/command.js";
|
|
8
|
+
import {
|
|
9
|
+
conversationTopicFrameSchema,
|
|
10
|
+
v4ConversationResyncResultSchema,
|
|
11
|
+
v4ConversationRowsRangeResultSchema,
|
|
12
|
+
type ConversationTopicFrame,
|
|
13
|
+
type ConversationTopicWireCandidate,
|
|
14
|
+
} from "./vendor/zcode/packages/shared/src/zcode-protocol-v4/transport.js";
|
|
15
|
+
import type { ConversationSnapshot } from "./vendor/zcode/packages/shared/src/zcode-protocol-v4/snapshot.js";
|
|
16
|
+
import type { ConversationRow } from "./vendor/zcode/packages/shared/src/zcode-protocol-v4/rows.js";
|
|
17
|
+
import type { HostBridge, HostSubscription } from "./host/bridge.js";
|
|
18
|
+
import { AdapterError } from "./errors.js";
|
|
19
|
+
export type ConversationState = ConversationSnapshot;
|
|
20
|
+
|
|
21
|
+
/** One authoritative V4 state. No legacy session events participate in it. */
|
|
22
|
+
export class Conversation {
|
|
23
|
+
state?: ConversationSnapshot;
|
|
24
|
+
private subscription?: HostSubscription;
|
|
25
|
+
private readonly assembler = new TopicWireFrameAssembler(
|
|
26
|
+
conversationTopicFrameSchema,
|
|
27
|
+
);
|
|
28
|
+
private expiry?: ReturnType<typeof setTimeout>;
|
|
29
|
+
private recovery?: Promise<void>;
|
|
30
|
+
private recovering = false;
|
|
31
|
+
private hydrating = false;
|
|
32
|
+
private readonly waiters = new Set<() => void>();
|
|
33
|
+
private closed = false;
|
|
34
|
+
private readonly listeners = new Set<() => void>();
|
|
35
|
+
private failure?: unknown;
|
|
36
|
+
constructor(
|
|
37
|
+
private readonly bridge: HostBridge,
|
|
38
|
+
private readonly workspacePath: string,
|
|
39
|
+
private readonly sessionId: string,
|
|
40
|
+
private readonly onFailure: (error: unknown) => void,
|
|
41
|
+
) {}
|
|
42
|
+
async open(): Promise<void> {
|
|
43
|
+
const early: ConversationTopicWireCandidate[] = [];
|
|
44
|
+
this.subscription = await this.bridge.subscribe(
|
|
45
|
+
{ workspacePath: this.workspacePath, sessionId: this.sessionId },
|
|
46
|
+
(frame) => {
|
|
47
|
+
if (this.subscription) this.accept(frame);
|
|
48
|
+
else early.push(frame);
|
|
49
|
+
},
|
|
50
|
+
);
|
|
51
|
+
for (const frame of early) this.accept(frame);
|
|
52
|
+
await this.waitFor(() => this.state !== undefined && !this.recovering);
|
|
53
|
+
await this.loadHistory();
|
|
54
|
+
}
|
|
55
|
+
subscribe(listener: () => void): () => void {
|
|
56
|
+
this.listeners.add(listener);
|
|
57
|
+
return () => this.listeners.delete(listener);
|
|
58
|
+
}
|
|
59
|
+
private changed(): void {
|
|
60
|
+
for (const waiter of this.waiters) waiter();
|
|
61
|
+
if (!this.hydrating) for (const listener of this.listeners) listener();
|
|
62
|
+
}
|
|
63
|
+
private fail(error: unknown): void {
|
|
64
|
+
if (this.failure || this.closed) return;
|
|
65
|
+
this.failure = error;
|
|
66
|
+
this.changed();
|
|
67
|
+
this.onFailure(error);
|
|
68
|
+
}
|
|
69
|
+
accept(wire: ConversationTopicWireCandidate): void {
|
|
70
|
+
if (
|
|
71
|
+
this.closed ||
|
|
72
|
+
wire.subscriptionId !== this.subscription?.id ||
|
|
73
|
+
wire.topic !== `conversation/${this.sessionId}`
|
|
74
|
+
)
|
|
75
|
+
return;
|
|
76
|
+
for (const event of this.assembler.accept(wire)) {
|
|
77
|
+
if (event.kind === "fault") {
|
|
78
|
+
if (event.fault.deliveryKind === "recovery")
|
|
79
|
+
this.fail(
|
|
80
|
+
new AdapterError(
|
|
81
|
+
"NATIVE_PROTOCOL_ERROR",
|
|
82
|
+
"ZCode recovery frame is invalid",
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
else this.resync();
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
if (this.recovering && event.deliveryKind !== "recovery") continue;
|
|
89
|
+
this.apply(event.frame, event.deliveryKind === "recovery");
|
|
90
|
+
}
|
|
91
|
+
this.scheduleExpiry();
|
|
92
|
+
}
|
|
93
|
+
private apply(frame: ConversationTopicFrame, recovery: boolean): void {
|
|
94
|
+
if (frame.payload.kind === "snapshot") {
|
|
95
|
+
const snapshot = frame.payload.snapshot;
|
|
96
|
+
if (
|
|
97
|
+
snapshot.sessionId !== this.sessionId ||
|
|
98
|
+
snapshot.seq !== frame.toSeq ||
|
|
99
|
+
frame.fromSeq !== 0
|
|
100
|
+
) {
|
|
101
|
+
this.resync();
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
if (
|
|
105
|
+
this.state &&
|
|
106
|
+
!recovery &&
|
|
107
|
+
(snapshot.logEpoch !== this.state.logEpoch ||
|
|
108
|
+
snapshot.seq < this.state.seq)
|
|
109
|
+
) {
|
|
110
|
+
this.resync();
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
this.state = snapshot;
|
|
114
|
+
this.recovering = false;
|
|
115
|
+
} else {
|
|
116
|
+
if (!this.state || frame.fromSeq !== this.state.seq) {
|
|
117
|
+
this.resync();
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (frame.toSeq < frame.fromSeq) {
|
|
121
|
+
this.resync();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
this.state = {
|
|
125
|
+
...applyConversationDeltas(this.state, frame.payload.deltas),
|
|
126
|
+
seq: frame.toSeq,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
this.changed();
|
|
130
|
+
}
|
|
131
|
+
private scheduleExpiry(): void {
|
|
132
|
+
clearTimeout(this.expiry);
|
|
133
|
+
const expiry = this.assembler.nextExpiryAt;
|
|
134
|
+
if (expiry === null) return;
|
|
135
|
+
this.expiry = setTimeout(
|
|
136
|
+
() => {
|
|
137
|
+
if (this.assembler.expire().length) this.resync();
|
|
138
|
+
this.scheduleExpiry();
|
|
139
|
+
},
|
|
140
|
+
Math.max(1, expiry - Date.now()),
|
|
141
|
+
);
|
|
142
|
+
this.expiry.unref();
|
|
143
|
+
}
|
|
144
|
+
private resync(): void {
|
|
145
|
+
if (this.closed || this.recovery) return;
|
|
146
|
+
this.recovering = true;
|
|
147
|
+
this.hydrating = true;
|
|
148
|
+
this.recovery = (async () => {
|
|
149
|
+
await this.bridge.request(
|
|
150
|
+
"resyncConversationV4",
|
|
151
|
+
{
|
|
152
|
+
workspacePath: this.workspacePath,
|
|
153
|
+
subscriptionId: this.subscription!.id,
|
|
154
|
+
base: null,
|
|
155
|
+
forceSnapshot: true,
|
|
156
|
+
},
|
|
157
|
+
v4ConversationResyncResultSchema,
|
|
158
|
+
);
|
|
159
|
+
await this.waitFor(() => !this.recovering);
|
|
160
|
+
await this.loadHistory();
|
|
161
|
+
})()
|
|
162
|
+
.catch((error) => this.fail(error))
|
|
163
|
+
.finally(() => {
|
|
164
|
+
this.recovery = undefined;
|
|
165
|
+
this.hydrating = false;
|
|
166
|
+
this.changed();
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
async loadHistory(): Promise<void> {
|
|
170
|
+
for (let attempt = 0; attempt < 3; attempt++) {
|
|
171
|
+
const base = this.state!;
|
|
172
|
+
let beforeRowId: number | undefined;
|
|
173
|
+
const rows = new Map<number, ConversationRow>();
|
|
174
|
+
let consistent = true;
|
|
175
|
+
do {
|
|
176
|
+
const page = await this.bridge.request(
|
|
177
|
+
"conversationRowsRangeV4",
|
|
178
|
+
{
|
|
179
|
+
workspacePath: this.workspacePath,
|
|
180
|
+
sessionId: this.sessionId,
|
|
181
|
+
limit: 200,
|
|
182
|
+
...(beforeRowId === undefined ? {} : { beforeRowId }),
|
|
183
|
+
},
|
|
184
|
+
v4ConversationRowsRangeResultSchema,
|
|
185
|
+
);
|
|
186
|
+
if (
|
|
187
|
+
page.atLogEpoch !== base.logEpoch ||
|
|
188
|
+
page.atRevision !== base.revision ||
|
|
189
|
+
page.atSeq !== base.seq ||
|
|
190
|
+
this.state?.logEpoch !== base.logEpoch ||
|
|
191
|
+
this.state?.seq !== base.seq
|
|
192
|
+
) {
|
|
193
|
+
consistent = false;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
for (const row of page.rows) rows.set(row.rowId, row);
|
|
197
|
+
if (!page.hasMore) break;
|
|
198
|
+
const next = page.rows[0]?.rowId;
|
|
199
|
+
if (
|
|
200
|
+
next === undefined ||
|
|
201
|
+
(beforeRowId !== undefined && next >= beforeRowId)
|
|
202
|
+
)
|
|
203
|
+
throw new AdapterError(
|
|
204
|
+
"NATIVE_PROTOCOL_ERROR",
|
|
205
|
+
"ZCode history cursor did not advance",
|
|
206
|
+
);
|
|
207
|
+
beforeRowId = next;
|
|
208
|
+
} while (!this.closed);
|
|
209
|
+
if (this.closed) return;
|
|
210
|
+
if (consistent) {
|
|
211
|
+
this.state = {
|
|
212
|
+
...base,
|
|
213
|
+
rows: {
|
|
214
|
+
...base.rows,
|
|
215
|
+
window: [...rows.values()].sort((a, b) => a.rowId - b.rowId),
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
this.changed();
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
throw new AdapterError(
|
|
223
|
+
"NATIVE_PROTOCOL_ERROR",
|
|
224
|
+
"ZCode history changed during pagination; no mixed history was published",
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
get idle(): boolean {
|
|
228
|
+
const c = this.state?.control;
|
|
229
|
+
return (
|
|
230
|
+
!!c &&
|
|
231
|
+
!this.recovering &&
|
|
232
|
+
!this.hydrating &&
|
|
233
|
+
!c.canStop &&
|
|
234
|
+
c.activeWorks.length === 0 &&
|
|
235
|
+
c.phase !== "running" &&
|
|
236
|
+
c.phase !== "prewarming" &&
|
|
237
|
+
this.state!.queue.items.length === 0
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
waitFor(predicate: () => boolean): Promise<void> {
|
|
241
|
+
if (this.failure) return Promise.reject(this.failure);
|
|
242
|
+
if (predicate()) return Promise.resolve();
|
|
243
|
+
return new Promise((resolve, reject) => {
|
|
244
|
+
const timer = setTimeout(() => {
|
|
245
|
+
off();
|
|
246
|
+
reject(
|
|
247
|
+
new AdapterError(
|
|
248
|
+
"NATIVE_TIMEOUT",
|
|
249
|
+
"ZCode did not confirm the requested state",
|
|
250
|
+
),
|
|
251
|
+
);
|
|
252
|
+
}, 30_000);
|
|
253
|
+
const off = () => this.waiters.delete(check);
|
|
254
|
+
const check = () => {
|
|
255
|
+
if (this.failure || this.closed || predicate()) {
|
|
256
|
+
clearTimeout(timer);
|
|
257
|
+
off();
|
|
258
|
+
this.failure
|
|
259
|
+
? reject(this.failure)
|
|
260
|
+
: this.closed
|
|
261
|
+
? reject(new AdapterError("NATIVE_EXITED", "Conversation closed"))
|
|
262
|
+
: resolve();
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
this.waiters.add(check);
|
|
266
|
+
check();
|
|
267
|
+
});
|
|
268
|
+
}
|
|
269
|
+
async close(): Promise<void> {
|
|
270
|
+
this.closed = true;
|
|
271
|
+
clearTimeout(this.expiry);
|
|
272
|
+
this.assembler.clear();
|
|
273
|
+
this.changed();
|
|
274
|
+
await this.subscription?.dispose();
|
|
275
|
+
this.listeners.clear();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
export async function conversationCommand(
|
|
279
|
+
bridge: HostBridge,
|
|
280
|
+
workspacePath: string,
|
|
281
|
+
sessionId: string,
|
|
282
|
+
type: string,
|
|
283
|
+
payload: unknown,
|
|
284
|
+
options: { commandId?: string; revision?: number } = {},
|
|
285
|
+
) {
|
|
286
|
+
const commandId = options.commandId ?? randomUUID();
|
|
287
|
+
const envelope = {
|
|
288
|
+
commandId,
|
|
289
|
+
clientId: "paseo-zcode-provider",
|
|
290
|
+
sessionId,
|
|
291
|
+
type,
|
|
292
|
+
payload,
|
|
293
|
+
issuedAt: Date.now(),
|
|
294
|
+
...(options.revision === undefined
|
|
295
|
+
? {}
|
|
296
|
+
: { baseRevision: options.revision }),
|
|
297
|
+
};
|
|
298
|
+
const validated = parseCommandEnvelope(envelope);
|
|
299
|
+
if (!validated.ok)
|
|
300
|
+
throw new AdapterError(
|
|
301
|
+
"NATIVE_PROTOCOL_ERROR",
|
|
302
|
+
"Invalid ZCode command",
|
|
303
|
+
{},
|
|
304
|
+
{ cause: validated.error },
|
|
305
|
+
);
|
|
306
|
+
const ack = await bridge.request(
|
|
307
|
+
"sendConversationCommandV4",
|
|
308
|
+
{ workspacePath, envelope },
|
|
309
|
+
commandAckSchema,
|
|
310
|
+
60_000,
|
|
311
|
+
{ sessionId, inputId: commandId },
|
|
312
|
+
);
|
|
313
|
+
if (ack.commandId !== commandId)
|
|
314
|
+
throw new AdapterError(
|
|
315
|
+
"NATIVE_PROTOCOL_ERROR",
|
|
316
|
+
"ZCode acknowledged a different command",
|
|
317
|
+
);
|
|
318
|
+
return ack;
|
|
319
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { valid } from "semver";
|
|
3
|
+
import { PROVIDER_VERSION as providerVersion } from "./build-info.js";
|
|
4
|
+
import { AdapterError, type ZCodeErrorCode } from "./errors.js";
|
|
5
|
+
import type { DiscoveredRuntime } from "./discovery/types.js";
|
|
6
|
+
|
|
7
|
+
const stages = [
|
|
8
|
+
"discovery",
|
|
9
|
+
"version",
|
|
10
|
+
"host-inspection",
|
|
11
|
+
"smoke",
|
|
12
|
+
"host-start",
|
|
13
|
+
"request",
|
|
14
|
+
"response",
|
|
15
|
+
"notification",
|
|
16
|
+
"transport",
|
|
17
|
+
"session",
|
|
18
|
+
] as const;
|
|
19
|
+
const checks = [
|
|
20
|
+
"bundle-metadata",
|
|
21
|
+
"minimum-version",
|
|
22
|
+
"host-entry",
|
|
23
|
+
"host-imports",
|
|
24
|
+
"host-path",
|
|
25
|
+
"rpc-module-load",
|
|
26
|
+
"rpc-missing",
|
|
27
|
+
"rpc-ambiguous",
|
|
28
|
+
"host-inspection-result",
|
|
29
|
+
"cli-smoke",
|
|
30
|
+
"native-envelope",
|
|
31
|
+
"native-result",
|
|
32
|
+
"native-event",
|
|
33
|
+
"native-error",
|
|
34
|
+
"native-exit",
|
|
35
|
+
"request-timeout",
|
|
36
|
+
"request-write",
|
|
37
|
+
] as const;
|
|
38
|
+
const operations = new Set([
|
|
39
|
+
"initialize",
|
|
40
|
+
"readWorkspacePresentation",
|
|
41
|
+
"readModelSelection",
|
|
42
|
+
"createSession",
|
|
43
|
+
"resumeSession",
|
|
44
|
+
"listSessions",
|
|
45
|
+
"readSession",
|
|
46
|
+
"closeSession",
|
|
47
|
+
"disposeWorkspace",
|
|
48
|
+
"cancelGeneration",
|
|
49
|
+
"respondStructuredInput",
|
|
50
|
+
"respondPermission",
|
|
51
|
+
"getEntitlementSnapshot",
|
|
52
|
+
"getCodingPlanResetStatus",
|
|
53
|
+
"helloConversationV4",
|
|
54
|
+
"initializeConversationV4",
|
|
55
|
+
"syncAppRuntimePreferences",
|
|
56
|
+
"sendConversationCommandV4",
|
|
57
|
+
"subscribeConversationV4",
|
|
58
|
+
"unsubscribeConversationV4",
|
|
59
|
+
"resyncConversationV4",
|
|
60
|
+
"conversationRowsRangeV4",
|
|
61
|
+
"attachmentBeginV4",
|
|
62
|
+
"attachmentChunkV4",
|
|
63
|
+
"attachmentCommitV4",
|
|
64
|
+
"attachmentAbortV4",
|
|
65
|
+
"event",
|
|
66
|
+
"catalog",
|
|
67
|
+
"session.create",
|
|
68
|
+
"session.resume",
|
|
69
|
+
"session.list",
|
|
70
|
+
"session.prompt",
|
|
71
|
+
"session.configure",
|
|
72
|
+
"session.close",
|
|
73
|
+
"session.cancel",
|
|
74
|
+
"session.permission.respond",
|
|
75
|
+
"session.open",
|
|
76
|
+
"session.interrupt",
|
|
77
|
+
"session.permission",
|
|
78
|
+
]);
|
|
79
|
+
// Paths from record/map keys can contain user data. Only fixed schema field names are reportable.
|
|
80
|
+
const schemaFields = new Set([
|
|
81
|
+
"id",
|
|
82
|
+
"type",
|
|
83
|
+
"method",
|
|
84
|
+
"params",
|
|
85
|
+
"result",
|
|
86
|
+
"error",
|
|
87
|
+
"code",
|
|
88
|
+
"message",
|
|
89
|
+
"subscriptionId",
|
|
90
|
+
"event",
|
|
91
|
+
"sessionId",
|
|
92
|
+
"turnId",
|
|
93
|
+
"seq",
|
|
94
|
+
"payload",
|
|
95
|
+
"kind",
|
|
96
|
+
"delta",
|
|
97
|
+
"status",
|
|
98
|
+
"models",
|
|
99
|
+
"settings",
|
|
100
|
+
"mode",
|
|
101
|
+
"current",
|
|
102
|
+
"thoughtLevel",
|
|
103
|
+
"model",
|
|
104
|
+
"provider",
|
|
105
|
+
"providers",
|
|
106
|
+
"options",
|
|
107
|
+
"request",
|
|
108
|
+
"workspacePath",
|
|
109
|
+
"sessions",
|
|
110
|
+
"items",
|
|
111
|
+
"usage",
|
|
112
|
+
"data",
|
|
113
|
+
"name",
|
|
114
|
+
"role",
|
|
115
|
+
"content",
|
|
116
|
+
"requestId",
|
|
117
|
+
"toolCallId",
|
|
118
|
+
]);
|
|
119
|
+
|
|
120
|
+
export interface RuntimeDiagnostic {
|
|
121
|
+
readonly appVersion?: string;
|
|
122
|
+
readonly cliVersion?: string;
|
|
123
|
+
readonly platform?: string;
|
|
124
|
+
readonly stage?: (typeof stages)[number];
|
|
125
|
+
readonly operation?: string;
|
|
126
|
+
readonly check?: (typeof checks)[number];
|
|
127
|
+
readonly serverSha256?: string;
|
|
128
|
+
readonly cliSha256?: string;
|
|
129
|
+
readonly nativeCode?: number;
|
|
130
|
+
readonly exitCode?: number;
|
|
131
|
+
readonly validation?: readonly { path: string; code: string }[];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export function runtimeDiagnostic(
|
|
135
|
+
runtime: DiscoveredRuntime,
|
|
136
|
+
): RuntimeDiagnostic {
|
|
137
|
+
return {
|
|
138
|
+
appVersion: runtime.identity.appVersion,
|
|
139
|
+
cliVersion: runtime.identity.cliVersion,
|
|
140
|
+
platform: runtime.identity.platform,
|
|
141
|
+
serverSha256: runtime.identity.serverSha256,
|
|
142
|
+
cliSha256: runtime.identity.cliSha256,
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function diagnosticError(
|
|
147
|
+
error: unknown,
|
|
148
|
+
context: RuntimeDiagnostic,
|
|
149
|
+
defaultCode: ZCodeErrorCode = "NATIVE_PROTOCOL_ERROR",
|
|
150
|
+
): AdapterError {
|
|
151
|
+
const diagnostic = {
|
|
152
|
+
...context,
|
|
153
|
+
...(error instanceof AdapterError ? error.diagnostic : {}),
|
|
154
|
+
};
|
|
155
|
+
const cause = error instanceof AdapterError ? error.cause : error;
|
|
156
|
+
if (cause instanceof z.ZodError) {
|
|
157
|
+
diagnostic.validation = cause.issues.slice(0, 10).map((issue) => ({
|
|
158
|
+
path: issue.path
|
|
159
|
+
.map((part) =>
|
|
160
|
+
typeof part === "number"
|
|
161
|
+
? "[]"
|
|
162
|
+
: schemaFields.has(String(part))
|
|
163
|
+
? String(part)
|
|
164
|
+
: "*",
|
|
165
|
+
)
|
|
166
|
+
.join("."),
|
|
167
|
+
code: issue.code,
|
|
168
|
+
}));
|
|
169
|
+
}
|
|
170
|
+
return new AdapterError(
|
|
171
|
+
error instanceof AdapterError ? error.code : defaultCode,
|
|
172
|
+
error instanceof AdapterError ? error.message : "ZCode operation failed",
|
|
173
|
+
error instanceof AdapterError ? error.details : {},
|
|
174
|
+
{ cause: error },
|
|
175
|
+
diagnostic,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export function formatDiagnostic(error: unknown): string {
|
|
180
|
+
const context = error instanceof AdapterError ? error.diagnostic : undefined;
|
|
181
|
+
const result: Record<string, unknown> = {
|
|
182
|
+
providerVersion,
|
|
183
|
+
code: error instanceof AdapterError ? error.code : "NATIVE_PROTOCOL_ERROR",
|
|
184
|
+
};
|
|
185
|
+
if (context) {
|
|
186
|
+
for (const key of ["appVersion", "cliVersion"] as const) {
|
|
187
|
+
const value = context[key];
|
|
188
|
+
if (value && valid(value)) result[key] = valid(value);
|
|
189
|
+
}
|
|
190
|
+
if (
|
|
191
|
+
context.platform &&
|
|
192
|
+
/^(darwin|linux|win32)-(arm64|x64|ia32)$/u.test(context.platform)
|
|
193
|
+
)
|
|
194
|
+
result.platform = context.platform;
|
|
195
|
+
if (context.stage && stages.includes(context.stage))
|
|
196
|
+
result.stage = context.stage;
|
|
197
|
+
if (context.check && checks.includes(context.check))
|
|
198
|
+
result.check = context.check;
|
|
199
|
+
if (context.operation && operations.has(context.operation))
|
|
200
|
+
result.operation = context.operation;
|
|
201
|
+
for (const key of ["serverSha256", "cliSha256"] as const) {
|
|
202
|
+
if (/^[a-f0-9]{64}$/u.test(context[key] ?? ""))
|
|
203
|
+
result[key] = context[key];
|
|
204
|
+
}
|
|
205
|
+
for (const key of ["nativeCode", "exitCode"] as const) {
|
|
206
|
+
if (Number.isSafeInteger(context[key])) result[key] = context[key];
|
|
207
|
+
}
|
|
208
|
+
if (context.validation)
|
|
209
|
+
result.validation = context.validation.slice(0, 10).map((issue) => ({
|
|
210
|
+
path: issue.path
|
|
211
|
+
.split(".")
|
|
212
|
+
.slice(0, 20)
|
|
213
|
+
.map((part) =>
|
|
214
|
+
schemaFields.has(part) || part === "[]" || part === "" ? part : "*",
|
|
215
|
+
)
|
|
216
|
+
.join("."),
|
|
217
|
+
code: [
|
|
218
|
+
"invalid_type",
|
|
219
|
+
"too_big",
|
|
220
|
+
"too_small",
|
|
221
|
+
"invalid_format",
|
|
222
|
+
"not_multiple_of",
|
|
223
|
+
"unrecognized_keys",
|
|
224
|
+
"invalid_union",
|
|
225
|
+
"invalid_key",
|
|
226
|
+
"invalid_element",
|
|
227
|
+
"invalid_value",
|
|
228
|
+
"custom",
|
|
229
|
+
].includes(issue.code)
|
|
230
|
+
? issue.code
|
|
231
|
+
: "custom",
|
|
232
|
+
}));
|
|
233
|
+
}
|
|
234
|
+
return JSON.stringify(result, null, 2);
|
|
235
|
+
}
|