paseo-plugin-zcode-provider 0.4.2 → 0.4.3
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/README.md +1 -0
- package/package.json +1 -1
- package/server/build-info.ts +1 -1
- package/server/presentation.ts +7 -1
- package/server/provider.ts +4 -6
- package/server/session.ts +34 -1
package/README.md
CHANGED
|
@@ -81,6 +81,7 @@ The source baseline is `3c5b227649371507ddc4eb46ac5133afe6db1cab` (ZCode 3.16.2,
|
|
|
81
81
|
- Models and reasoning options come from ZCode. Editing modes are `build`, `edit`, `guarded` and `yolo`; `settings.plan_mode` is independent. `guarded` (ZCode's Autonomous mode, Server 3.15.1 or later) runs tools without approval but asks once, each time, before a command that ZCode's safety rules consider risky; it is not offered on older runtimes.
|
|
82
82
|
- Text, thoughts, tools, subagent progress, usage and history use V4 snapshots and deltas. Tool output is marked when ZCode truncates it. Usage is cumulative; repeated snapshots do not add it again.
|
|
83
83
|
- Text submitted during generation uses native guidance. Attachments use the native queue. Paseo reports one run across these native turns and completes it only after all accepted input has been consumed and foreground work has ended.
|
|
84
|
+
- Paseo sends every message typed in the app during a run as a steer that asks to clear pending permissions. The plugin queues it first, then declines pending permissions, questions and Plan approvals with their deny action until ZCode reads the message, including requests opened in the meantime. Requests that appear after it is read are left to the user. Declining a Plan approval in Plan mode ends ZCode's turn; the message then starts the next native turn in the same Paseo run (ADR 22).
|
|
84
85
|
- Acceptance is reported once, after the native acknowledgement. Unknown delivery results are never automatically resent. Stop identifies the current native execution, disables automatic queue execution and removes pending input. A new explicit run enables the queue again.
|
|
85
86
|
- As in ZCode Desktop, successful hooks are not shown. A finished hook invocation appears once, as a notification, only when a hook was blocked, failed, timed out or was cancelled; context compaction also appears once, when it ends. Paseo appends every notification it receives, so progress is not reported.
|
|
86
87
|
- Native permission IDs, option values, questions and Plan approval retain their meanings. Question auto-resolution is disabled for each owned Server. Workspace hook trust is reviewed through the official CLI; it is not represented as “allow once.”
|
package/package.json
CHANGED
package/server/build-info.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Generated from package.json by npm prepare / prebuild.
|
|
2
|
-
export const PROVIDER_VERSION = "0.4.
|
|
2
|
+
export const PROVIDER_VERSION = "0.4.3";
|
package/server/presentation.ts
CHANGED
|
@@ -233,6 +233,8 @@ export function usage(state: ConversationSnapshot): ProviderUsage {
|
|
|
233
233
|
export interface PresentedInteraction {
|
|
234
234
|
request: ProviderPermissionRequest;
|
|
235
235
|
answer(response: ProviderPermissionResponse): Record<string, unknown>;
|
|
236
|
+
/** Native answer of the first deny action, without interrupting. */
|
|
237
|
+
decline: Record<string, unknown>;
|
|
236
238
|
}
|
|
237
239
|
export function presentInteraction(
|
|
238
240
|
interaction: PendingInteraction,
|
|
@@ -262,7 +264,8 @@ export function presentInteraction(
|
|
|
262
264
|
variant: behavior === "allow" ? "primary" : "danger",
|
|
263
265
|
};
|
|
264
266
|
});
|
|
265
|
-
|
|
267
|
+
const deny = actions.find((a) => a.behavior === "deny");
|
|
268
|
+
if (!deny)
|
|
266
269
|
throw new AdapterError(
|
|
267
270
|
"NATIVE_PROTOCOL_ERROR",
|
|
268
271
|
"ZCode permission has no deny option",
|
|
@@ -299,6 +302,7 @@ export function presentInteraction(
|
|
|
299
302
|
);
|
|
300
303
|
return { optionId: action.id };
|
|
301
304
|
},
|
|
305
|
+
decline: { optionId: deny.id },
|
|
302
306
|
};
|
|
303
307
|
}
|
|
304
308
|
if (p.sensitive)
|
|
@@ -414,6 +418,7 @@ export function presentInteraction(
|
|
|
414
418
|
},
|
|
415
419
|
};
|
|
416
420
|
},
|
|
421
|
+
decline: { action: "decline" },
|
|
417
422
|
};
|
|
418
423
|
}
|
|
419
424
|
return {
|
|
@@ -445,6 +450,7 @@ export function presentInteraction(
|
|
|
445
450
|
content: answerContent(record(response.updatedInput?.answers)),
|
|
446
451
|
};
|
|
447
452
|
},
|
|
453
|
+
decline: { action: "decline" },
|
|
448
454
|
};
|
|
449
455
|
}
|
|
450
456
|
|
package/server/provider.ts
CHANGED
|
@@ -220,7 +220,9 @@ export class ZCodeConnection implements ProviderConnection {
|
|
|
220
220
|
if (input.type === "session.prompt") {
|
|
221
221
|
const promptEntry = entry ?? this.sessions.get(input.sessionId);
|
|
222
222
|
if (promptEntry?.messages.get(input.prompt.clientMessageId)) return;
|
|
223
|
-
|
|
223
|
+
// The input was not admitted. Paseo's interrupt-and-replace fallback
|
|
224
|
+
// for an unavailable steer resends it with the same ID.
|
|
225
|
+
promptEntry?.messages.delete(input.prompt.clientMessageId);
|
|
224
226
|
this.emit({
|
|
225
227
|
type: "session.prompt_result",
|
|
226
228
|
sessionId: input.sessionId,
|
|
@@ -374,11 +376,6 @@ export class ZCodeConnection implements ProviderConnection {
|
|
|
374
376
|
switch (input.type) {
|
|
375
377
|
case "session.prompt": {
|
|
376
378
|
const prompt = input.prompt.input;
|
|
377
|
-
if (input.prompt.clearPendingPermissions)
|
|
378
|
-
throw new AdapterError(
|
|
379
|
-
"INTERACTION_UNSUPPORTED",
|
|
380
|
-
"Steering does not resolve pending ZCode permissions",
|
|
381
|
-
);
|
|
382
379
|
if (input.prompt.delivery === "steer" && !entry.native.hasActiveTurn())
|
|
383
380
|
throw new AdapterError(
|
|
384
381
|
"SESSION_BUSY",
|
|
@@ -439,6 +436,7 @@ export class ZCodeConnection implements ProviderConnection {
|
|
|
439
436
|
{
|
|
440
437
|
clientMessageId: input.prompt.clientMessageId,
|
|
441
438
|
delivery: input.prompt.delivery,
|
|
439
|
+
clearPendingPermissions: input.prompt.clearPendingPermissions,
|
|
442
440
|
beforeSend: async () => {
|
|
443
441
|
if (!entry.submitted) {
|
|
444
442
|
await this.persistenceStore.save(
|
package/server/session.ts
CHANGED
|
@@ -55,6 +55,8 @@ interface Admission {
|
|
|
55
55
|
accepted: boolean;
|
|
56
56
|
consumed: boolean;
|
|
57
57
|
productTurnId?: string;
|
|
58
|
+
/** Paseo's clearPendingPermissions: decline interactions until consumed. */
|
|
59
|
+
releasesInteractions?: boolean;
|
|
58
60
|
}
|
|
59
61
|
interface Run {
|
|
60
62
|
id: string;
|
|
@@ -286,6 +288,7 @@ export class ZCodeSession {
|
|
|
286
288
|
});
|
|
287
289
|
}
|
|
288
290
|
}
|
|
291
|
+
this.releaseInteractions();
|
|
289
292
|
if (
|
|
290
293
|
this.state.workspaceHookAdmission ||
|
|
291
294
|
this.state.pendingInteractions.some(
|
|
@@ -323,6 +326,29 @@ export class ZCodeSession {
|
|
|
323
326
|
}
|
|
324
327
|
this.maybeComplete();
|
|
325
328
|
}
|
|
329
|
+
/**
|
|
330
|
+
* ZCode reads a steer only after every tool call of the model step settles,
|
|
331
|
+
* so a parked turn never reads it. While an accepted steer that asked to clear
|
|
332
|
+
* permissions is unread, decline each pending interaction, including requests
|
|
333
|
+
* opened after an earlier decline.
|
|
334
|
+
*/
|
|
335
|
+
private releaseInteractions(): void {
|
|
336
|
+
const run = this.active;
|
|
337
|
+
if (
|
|
338
|
+
!run ||
|
|
339
|
+
run.cancelled ||
|
|
340
|
+
![...run.inputs.values()].some(
|
|
341
|
+
(i) => i.releasesInteractions && i.accepted && !i.consumed,
|
|
342
|
+
)
|
|
343
|
+
)
|
|
344
|
+
return;
|
|
345
|
+
for (const [id, interaction] of this.pending) {
|
|
346
|
+
if (this.answering.has(id)) continue;
|
|
347
|
+
this.resolveInteraction(id, interaction.decline).catch((error) =>
|
|
348
|
+
this.runtimeFailed(diagnosticError(error, this.bridge.diagnostic)),
|
|
349
|
+
);
|
|
350
|
+
}
|
|
351
|
+
}
|
|
326
352
|
private maybeComplete(): void {
|
|
327
353
|
const run = this.active;
|
|
328
354
|
if (
|
|
@@ -537,6 +563,7 @@ export class ZCodeSession {
|
|
|
537
563
|
options?: {
|
|
538
564
|
clientMessageId: string;
|
|
539
565
|
delivery?: "auto" | "steer";
|
|
566
|
+
clearPendingPermissions?: boolean;
|
|
540
567
|
beforeSend?: () => Promise<void>;
|
|
541
568
|
},
|
|
542
569
|
): Promise<{ turnId: string }> {
|
|
@@ -634,6 +661,7 @@ export class ZCodeSession {
|
|
|
634
661
|
);
|
|
635
662
|
this.assertOpen();
|
|
636
663
|
input.accepted = true;
|
|
664
|
+
input.releasesInteractions = options?.clearPendingPermissions === true;
|
|
637
665
|
if (options?.clientMessageId)
|
|
638
666
|
this.emit({
|
|
639
667
|
type: "prompt_accepted",
|
|
@@ -701,7 +729,12 @@ export class ZCodeSession {
|
|
|
701
729
|
"SESSION_NOT_FOUND",
|
|
702
730
|
"ZCode interaction is no longer pending",
|
|
703
731
|
);
|
|
704
|
-
|
|
732
|
+
await this.resolveInteraction(id, pending.answer(response));
|
|
733
|
+
}
|
|
734
|
+
private async resolveInteraction(
|
|
735
|
+
id: string,
|
|
736
|
+
answer: Record<string, unknown>,
|
|
737
|
+
): Promise<void> {
|
|
705
738
|
this.answering.add(id);
|
|
706
739
|
try {
|
|
707
740
|
await this.control("resolveInteraction", { interactionId: id, answer });
|