@agentdeck/bridge 1.0.8 → 1.0.9

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 (55) hide show
  1. package/dist/ask-gate.d.ts +113 -0
  2. package/dist/ask-gate.d.ts.map +1 -0
  3. package/dist/ask-gate.js +110 -0
  4. package/dist/ask-gate.js.map +1 -0
  5. package/dist/auth.d.ts +8 -0
  6. package/dist/auth.d.ts.map +1 -1
  7. package/dist/auth.js +15 -0
  8. package/dist/auth.js.map +1 -1
  9. package/dist/awaiting-overlay.d.ts +54 -6
  10. package/dist/awaiting-overlay.d.ts.map +1 -1
  11. package/dist/awaiting-overlay.js +109 -26
  12. package/dist/awaiting-overlay.js.map +1 -1
  13. package/dist/cli.d.ts.map +1 -1
  14. package/dist/cli.js +74 -4
  15. package/dist/cli.js.map +1 -1
  16. package/dist/daemon-server.d.ts.map +1 -1
  17. package/dist/daemon-server.js +238 -19
  18. package/dist/daemon-server.js.map +1 -1
  19. package/dist/daemon.js +1 -1
  20. package/dist/http-auth-gate.d.ts +40 -0
  21. package/dist/http-auth-gate.d.ts.map +1 -0
  22. package/dist/http-auth-gate.js +46 -0
  23. package/dist/http-auth-gate.js.map +1 -0
  24. package/dist/index.d.ts +3 -0
  25. package/dist/index.d.ts.map +1 -1
  26. package/dist/index.js +3 -2
  27. package/dist/index.js.map +1 -1
  28. package/dist/mdns.d.ts +7 -1
  29. package/dist/mdns.d.ts.map +1 -1
  30. package/dist/mdns.js +7 -3
  31. package/dist/mdns.js.map +1 -1
  32. package/dist/modules/mdns-module.d.ts.map +1 -1
  33. package/dist/modules/mdns-module.js +3 -1
  34. package/dist/modules/mdns-module.js.map +1 -1
  35. package/dist/observed-inject.d.ts +21 -5
  36. package/dist/observed-inject.d.ts.map +1 -1
  37. package/dist/observed-inject.js +85 -22
  38. package/dist/observed-inject.js.map +1 -1
  39. package/dist/observed-steering.d.ts +38 -0
  40. package/dist/observed-steering.d.ts.map +1 -1
  41. package/dist/observed-steering.js +53 -0
  42. package/dist/observed-steering.js.map +1 -1
  43. package/dist/passive-observer.d.ts +9 -0
  44. package/dist/passive-observer.d.ts.map +1 -1
  45. package/dist/passive-observer.js +90 -5
  46. package/dist/passive-observer.js.map +1 -1
  47. package/dist/permission-resolver.d.ts +11 -0
  48. package/dist/permission-resolver.d.ts.map +1 -1
  49. package/dist/permission-resolver.js +23 -3
  50. package/dist/permission-resolver.js.map +1 -1
  51. package/dist/session-registry.d.ts +23 -2
  52. package/dist/session-registry.d.ts.map +1 -1
  53. package/dist/session-registry.js +56 -5
  54. package/dist/session-registry.js.map +1 -1
  55. package/package.json +3 -3
@@ -0,0 +1,113 @@
1
+ import type { PromptOption } from '@agentdeck/shared';
2
+ /**
3
+ * Decisions for the AskUserQuestion ask-gate — the rung that answers an
4
+ * observed session's question by holding its PreToolUse hook open.
5
+ *
6
+ * These live outside `daemon-server.ts` because both of them are easy to get
7
+ * subtly, silently wrong: one decides whether to make the user wait, the other
8
+ * decides whether to commit an irreversible answer on their behalf. Neither
9
+ * shows up in a stack trace when it misfires — the terminal just sits blank, or
10
+ * the agent proceeds with an option nobody chose.
11
+ */
12
+ /** What the passive observer knows about where an observed session is running. */
13
+ export interface AskGateHost {
14
+ /** Controlling terminal, when the session runs in a real one. */
15
+ tty?: string;
16
+ /** Owning GUI app, for app-hosted sessions with no tty. */
17
+ appName?: string;
18
+ }
19
+ export interface AskGateDecision {
20
+ hold: boolean;
21
+ reason: string;
22
+ }
23
+ /**
24
+ * Should this AskUserQuestion be held open for a device to answer?
25
+ *
26
+ * Holding costs whoever is sitting at that terminal the whole hold duration —
27
+ * their question picker does not appear until the hook returns. So it is only
28
+ * worth it when the daemon has no faster way to deliver the answer AND some
29
+ * device is actually showing the prompt.
30
+ *
31
+ * That second condition is why `observed` being absent means DON'T hold: the
32
+ * observer's roster is the only source of `observed:claude:*` rows, so a
33
+ * session it has not seen is a session no device has on screen. Holding there
34
+ * stalls a question with nobody to answer it — the precise inverse of the
35
+ * intent. It happens for real: a session younger than the 5s scan interval, or
36
+ * any `ps` failure, empties that roster.
37
+ */
38
+ export declare function askGateDecision(opts: {
39
+ enabled: boolean;
40
+ clientCount: number;
41
+ /** The session's observer row, or undefined if it has not been seen. */
42
+ observed: AskGateHost | undefined;
43
+ }): AskGateDecision;
44
+ /**
45
+ * Shortest echo that may be accepted as a device-truncated prefix.
46
+ *
47
+ * Only a bound on the collision risk below — not a device buffer size, which
48
+ * this side cannot know. The smallest real echo comes from the ESP32 knob:
49
+ * `SessionInfo.question` is 160 BYTES and the outbound frame budget trims it
50
+ * further, so ~38 characters of Hangul survive in the worst case. 24 sits under
51
+ * that with room to spare, and well above any question two groups could share.
52
+ */
53
+ export declare const ASK_ECHO_MIN_PREFIX = 24;
54
+ /**
55
+ * Does this echo name the question that is live?
56
+ *
57
+ * Exact match is the normal answer. The exception is structural, not sloppy:
58
+ * `MAX_QUESTION_LEN` caps a question at 120 CHARACTERS, which is up to 360
59
+ * bytes of Hangul/CJK, while a firmware surface holds it in a fixed BYTE
60
+ * buffer — so a Korean question reaches the device already cut short, and an
61
+ * `===` gate would reject every answer to one while passing every answer to an
62
+ * English one. A length-dependent failure is worse than no feature: it looks
63
+ * like a flaky device, not a contract.
64
+ *
65
+ * A prefix is safe here because of what the guard is for — catching a press
66
+ * aimed at the question a grouped prompt has already moved past. Two groups in
67
+ * one AskUserQuestion call would have to share `ASK_ECHO_MIN_PREFIX` leading
68
+ * characters AND differ only after the cut to slip through. Same reasoning as
69
+ * `resolveSessionIdPrefix` for the 31-char session ids devices report.
70
+ */
71
+ export declare function askEchoMatches(echo: string, question: string): boolean;
72
+ export type AskPressVerdict = {
73
+ ok: true;
74
+ label: string;
75
+ } | {
76
+ ok: false;
77
+ reason: string;
78
+ resync: boolean;
79
+ };
80
+ /** The overlay fields a press is validated against. */
81
+ export interface AskPressOverlay {
82
+ question?: string;
83
+ options?: PromptOption[];
84
+ toolUseId?: string;
85
+ }
86
+ /**
87
+ * Is this device press a valid answer to the question currently held open?
88
+ *
89
+ * Every rejection here is a press that would otherwise commit an answer the
90
+ * user did not give, so the checks are deliberately strict:
91
+ *
92
+ * - **The press must name the question it answers.** Not decoration: several
93
+ * device surfaces map a hardware "approve" key to `select_option(0)` as a
94
+ * stand-in for a yes/no gate (ESP32 `hudSendApprove`, NFC `approve` tags).
95
+ * Against a permission gate that is meaningful. Against a four-way question
96
+ * it is a guess, and this rung would submit it as the user's stated answer,
97
+ * irreversibly. A surface that renders the real options can name the one it
98
+ * is answering; a binary approve key cannot, which is exactly the line we
99
+ * want. `resync: false` — the sender has no question view to correct.
100
+ * - **The named question must be the live one.** A grouped prompt moves on as
101
+ * each question is answered, so an index pressed against the previous one
102
+ * would land in a different option list.
103
+ * - **The gate must own this overlay.** A malformed follow-up call can leave a
104
+ * previous prompt resident; answering that one would report the wrong
105
+ * question back to the agent.
106
+ */
107
+ export declare function askPressVerdict(opts: {
108
+ overlay: AskPressOverlay | undefined;
109
+ /** tool_use_id the gate was opened for. */
110
+ gateToolUseId?: string;
111
+ command: Record<string, unknown>;
112
+ }): AskPressVerdict;
113
+ //# sourceMappingURL=ask-gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-gate.d.ts","sourceRoot":"","sources":["../src/ask-gate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;;;;;;GASG;AAEH,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,iEAAiE;IACjE,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2DAA2D;IAC3D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,QAAQ,EAAE,WAAW,GAAG,SAAS,CAAC;CACnC,GAAG,eAAe,CAQlB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,KAAK,CAAC;AAEtC;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAKtE;AAED,MAAM,MAAM,eAAe,GACvB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAAC;AAEnD,uDAAuD;AACvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,OAAO,EAAE,eAAe,GAAG,SAAS,CAAC;IACrC,2CAA2C;IAC3C,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,GAAG,eAAe,CA0BlB"}
@@ -0,0 +1,110 @@
1
+ /**
2
+ * Should this AskUserQuestion be held open for a device to answer?
3
+ *
4
+ * Holding costs whoever is sitting at that terminal the whole hold duration —
5
+ * their question picker does not appear until the hook returns. So it is only
6
+ * worth it when the daemon has no faster way to deliver the answer AND some
7
+ * device is actually showing the prompt.
8
+ *
9
+ * That second condition is why `observed` being absent means DON'T hold: the
10
+ * observer's roster is the only source of `observed:claude:*` rows, so a
11
+ * session it has not seen is a session no device has on screen. Holding there
12
+ * stalls a question with nobody to answer it — the precise inverse of the
13
+ * intent. It happens for real: a session younger than the 5s scan interval, or
14
+ * any `ps` failure, empties that roster.
15
+ */
16
+ export function askGateDecision(opts) {
17
+ if (!opts.enabled)
18
+ return { hold: false, reason: 'disabled' };
19
+ if (opts.clientCount < 1)
20
+ return { hold: false, reason: 'no clients' };
21
+ if (!opts.observed)
22
+ return { hold: false, reason: 'session not on any device roster yet' };
23
+ if (opts.observed.tty || opts.observed.appName) {
24
+ return { hold: false, reason: 'terminal reachable — inject instead' };
25
+ }
26
+ return { hold: true, reason: 'no way to type into this session' };
27
+ }
28
+ /**
29
+ * Shortest echo that may be accepted as a device-truncated prefix.
30
+ *
31
+ * Only a bound on the collision risk below — not a device buffer size, which
32
+ * this side cannot know. The smallest real echo comes from the ESP32 knob:
33
+ * `SessionInfo.question` is 160 BYTES and the outbound frame budget trims it
34
+ * further, so ~38 characters of Hangul survive in the worst case. 24 sits under
35
+ * that with room to spare, and well above any question two groups could share.
36
+ */
37
+ export const ASK_ECHO_MIN_PREFIX = 24;
38
+ /**
39
+ * Does this echo name the question that is live?
40
+ *
41
+ * Exact match is the normal answer. The exception is structural, not sloppy:
42
+ * `MAX_QUESTION_LEN` caps a question at 120 CHARACTERS, which is up to 360
43
+ * bytes of Hangul/CJK, while a firmware surface holds it in a fixed BYTE
44
+ * buffer — so a Korean question reaches the device already cut short, and an
45
+ * `===` gate would reject every answer to one while passing every answer to an
46
+ * English one. A length-dependent failure is worse than no feature: it looks
47
+ * like a flaky device, not a contract.
48
+ *
49
+ * A prefix is safe here because of what the guard is for — catching a press
50
+ * aimed at the question a grouped prompt has already moved past. Two groups in
51
+ * one AskUserQuestion call would have to share `ASK_ECHO_MIN_PREFIX` leading
52
+ * characters AND differ only after the cut to slip through. Same reasoning as
53
+ * `resolveSessionIdPrefix` for the 31-char session ids devices report.
54
+ */
55
+ export function askEchoMatches(echo, question) {
56
+ if (echo === question)
57
+ return true;
58
+ return echo.length >= ASK_ECHO_MIN_PREFIX
59
+ && echo.length < question.length
60
+ && question.startsWith(echo);
61
+ }
62
+ /**
63
+ * Is this device press a valid answer to the question currently held open?
64
+ *
65
+ * Every rejection here is a press that would otherwise commit an answer the
66
+ * user did not give, so the checks are deliberately strict:
67
+ *
68
+ * - **The press must name the question it answers.** Not decoration: several
69
+ * device surfaces map a hardware "approve" key to `select_option(0)` as a
70
+ * stand-in for a yes/no gate (ESP32 `hudSendApprove`, NFC `approve` tags).
71
+ * Against a permission gate that is meaningful. Against a four-way question
72
+ * it is a guess, and this rung would submit it as the user's stated answer,
73
+ * irreversibly. A surface that renders the real options can name the one it
74
+ * is answering; a binary approve key cannot, which is exactly the line we
75
+ * want. `resync: false` — the sender has no question view to correct.
76
+ * - **The named question must be the live one.** A grouped prompt moves on as
77
+ * each question is answered, so an index pressed against the previous one
78
+ * would land in a different option list.
79
+ * - **The gate must own this overlay.** A malformed follow-up call can leave a
80
+ * previous prompt resident; answering that one would report the wrong
81
+ * question back to the agent.
82
+ */
83
+ export function askPressVerdict(opts) {
84
+ const { overlay, gateToolUseId, command } = opts;
85
+ if (command.type !== 'select_option') {
86
+ return { ok: false, reason: `ask-gate expects select_option, got ${String(command.type)}`, resync: false };
87
+ }
88
+ if (!overlay?.question) {
89
+ return { ok: false, reason: 'no question is open', resync: true };
90
+ }
91
+ if (gateToolUseId && overlay.toolUseId && gateToolUseId !== overlay.toolUseId) {
92
+ return { ok: false, reason: 'held gate belongs to a different tool call', resync: true };
93
+ }
94
+ const echo = typeof command.question === 'string' ? command.question : undefined;
95
+ if (!echo) {
96
+ return { ok: false, reason: 'answer did not name its question', resync: false };
97
+ }
98
+ if (!askEchoMatches(echo, overlay.question)) {
99
+ return { ok: false, reason: 'answers a question the prompt has moved past', resync: true };
100
+ }
101
+ if (typeof command.index !== 'number') {
102
+ return { ok: false, reason: 'no option index', resync: false };
103
+ }
104
+ const label = overlay.options?.find((o) => o.index === command.index)?.label;
105
+ if (!label) {
106
+ return { ok: false, reason: `option ${command.index} is not in the live list`, resync: true };
107
+ }
108
+ return { ok: true, label };
109
+ }
110
+ //# sourceMappingURL=ask-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask-gate.js","sourceRoot":"","sources":["../src/ask-gate.ts"],"names":[],"mappings":"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"}
package/dist/auth.d.ts CHANGED
@@ -2,6 +2,14 @@
2
2
  export declare function getOrCreateToken(): string;
3
3
  /** Check if a connection originates from this machine (localhost or own LAN IPs). */
4
4
  export declare function isLocalConnection(ip: string): boolean;
5
+ /**
6
+ * Replace the stored pairing token with a freshly generated one and return it.
7
+ * Every paired client (companion apps, provisioned ESP32 boards, remote
8
+ * workers) must be re-paired/re-provisioned afterwards — the caller owns
9
+ * telling the user that. Added for issue #145 so a leaked token can be
10
+ * retired without hand-editing the file.
11
+ */
12
+ export declare function rotateToken(): string;
5
13
  /** Validate a token string against the stored token. */
6
14
  export declare function validateToken(token: string): boolean;
7
15
  /** Build a ws:// URL with auth token for QR code pairing. */
@@ -1 +1 @@
1
- {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAaA,iDAAiD;AACjD,wBAAgB,gBAAgB,IAAI,MAAM,CA4BzC;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAYrD;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CASpD;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7C"}
1
+ {"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAaA,iDAAiD;AACjD,wBAAgB,gBAAgB,IAAI,MAAM,CA4BzC;AAED,qFAAqF;AACrF,wBAAgB,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAYrD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,IAAI,MAAM,CAOpC;AAED,wDAAwD;AACxD,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CASpD;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAI7C"}
package/dist/auth.js CHANGED
@@ -53,6 +53,21 @@ export function isLocalConnection(ip) {
53
53
  }
54
54
  return false;
55
55
  }
56
+ /**
57
+ * Replace the stored pairing token with a freshly generated one and return it.
58
+ * Every paired client (companion apps, provisioned ESP32 boards, remote
59
+ * workers) must be re-paired/re-provisioned afterwards — the caller owns
60
+ * telling the user that. Added for issue #145 so a leaked token can be
61
+ * retired without hand-editing the file.
62
+ */
63
+ export function rotateToken() {
64
+ const token = randomBytes(TOKEN_LENGTH / 2).toString('hex');
65
+ mkdirSync(AGENTDECK_DIR, { recursive: true });
66
+ writeFileSync(TOKEN_FILE, token + '\n', { mode: 0o600 });
67
+ cachedToken = token;
68
+ debug('auth', `Rotated auth token → ${TOKEN_FILE}`);
69
+ return token;
70
+ }
56
71
  /** Validate a token string against the stored token. */
57
72
  export function validateToken(token) {
58
73
  const stored = getOrCreateToken();
package/dist/auth.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -18,14 +18,41 @@ import type { PromptOption } from '@agentdeck/shared';
18
18
  * the `pushStateCache` TTL-map pattern in session-aggregator.ts.
19
19
  */
20
20
  export type AwaitingKind = 'permission' | 'option';
21
+ /** One question group of an AskUserQuestion call, already sanitized and
22
+ * re-indexed. A single call carries up to four; the overlay presents them one
23
+ * at a time (see `AwaitingEntry.groups`). */
24
+ export interface AskGroup {
25
+ question: string;
26
+ options: PromptOption[];
27
+ promptType?: 'multi_select';
28
+ }
21
29
  export interface AwaitingEntry {
22
30
  kind: AwaitingKind;
23
31
  state: 'awaiting_permission' | 'awaiting_option';
24
32
  question: string;
25
- /** Structured AskUserQuestion choices. Display-only for observed sessions:
26
- * no requestId means devices must direct the user back to the terminal. */
33
+ /** Structured AskUserQuestion choices for the ACTIVE group. Pressable only
34
+ * when the daemon can deliver the answer (terminal injection or a held
35
+ * ask-gate) — otherwise devices direct the user back to the terminal. */
27
36
  options?: PromptOption[];
28
37
  promptType?: 'multi_select';
38
+ /** Every valid question group from one AskUserQuestion call. Claude allows up
39
+ * to four, but SessionInfo carries a single question/options pair, so they
40
+ * are presented sequentially rather than flattened into one index space
41
+ * (which would let a press against group 1 select an option in group 2).
42
+ * `question`/`options`/`promptType` above always mirror `groups[activeGroup]`. */
43
+ groups?: AskGroup[];
44
+ activeGroup?: number;
45
+ /** How many question groups the tool call actually contained, INCLUDING any
46
+ * `groups` dropped as malformed. The terminal's own picker renders a form
47
+ * for all of them, so this — not `groups.length` — decides whether that form
48
+ * ends on a "Submit answers" confirmation someone has to press. */
49
+ rawGroupCount?: number;
50
+ /** Answers collected so far, one per resolved group. The held ask-gate turns
51
+ * these into the hook's decision reason when the last group is answered. */
52
+ answers?: Array<{
53
+ question: string;
54
+ label: string;
55
+ }>;
29
56
  /** Claude's stable tool call id. Option overlays resolve only when the
30
57
  * matching PostToolUse/PostToolUseFailure arrives (or a terminal lifecycle
31
58
  * event ends/supersedes the turn). Never expose this as requestId: that
@@ -43,14 +70,33 @@ export declare function setAwaitingOverlay(sessionId: string, question: string,
43
70
  * interaction instead of downgrading it to generic permission copy. */
44
71
  export declare function setPermissionNotificationOverlay(sessionId: string, question: string): boolean;
45
72
  /**
46
- * Lift a direct-Claude AskUserQuestion PreToolUse payload into a structured,
47
- * display-only option overlay. Claude supports one to four grouped questions,
48
- * while SessionInfo currently carries one question/options set; show the first
49
- * valid group rather than flattening unrelated groups into unsafe wire indices.
73
+ * Lift a direct-Claude AskUserQuestion PreToolUse payload into a structured
74
+ * option overlay. Claude supports one to four grouped questions while
75
+ * SessionInfo carries a single question/options pair, so ALL valid groups are
76
+ * kept here and presented one at a time (`advanceAskUserQuestionOverlay`)
77
+ * rather than flattened into one index space — flattening would let a press
78
+ * aimed at group 1 land on an option of group 2.
50
79
  * Returns false for malformed payloads so callers can preserve normal tool
51
80
  * processing instead of surfacing a dead prompt.
52
81
  */
53
82
  export declare function setAskUserQuestionOverlay(sessionId: string, toolUseId: string | undefined, toolInput: Record<string, unknown> | undefined): boolean;
83
+ /**
84
+ * Record the answer to the active question group and present the next one.
85
+ *
86
+ * Returns `'advanced'` when a further group is now showing (the caller must
87
+ * re-broadcast so devices swap to it), `'complete'` when that was the last
88
+ * group (the caller resolves the held ask-gate / waits for PostToolUse), or
89
+ * `'ignored'` when there is no active option overlay.
90
+ *
91
+ * `label` is the option text the user chose; it is kept so a held ask-gate can
92
+ * report every Q→A pair back to the agent.
93
+ */
94
+ export declare function advanceAskUserQuestionOverlay(sessionId: string, label?: string): 'advanced' | 'complete' | 'ignored';
95
+ /** Q→A pairs recorded so far for a pending AskUserQuestion (held ask-gate). */
96
+ export declare function getAskUserQuestionAnswers(sessionId: string): Array<{
97
+ question: string;
98
+ label: string;
99
+ }>;
54
100
  /** Returns the overlay entry if it exists and is still fresh (< TTL). Stale
55
101
  * entries are pruned on read. `updatedAt` is exposed so the observed-session
56
102
  * overlay can compare it against the session's transcript recency. */
@@ -84,6 +130,8 @@ export declare function applyAwaitingOverlayToObserved<T extends {
84
130
  requestId?: string;
85
131
  options?: PromptOption[];
86
132
  promptType?: string;
133
+ askGroupIndex?: number;
134
+ askGroupCount?: number;
87
135
  lastActivityAt?: number;
88
136
  }>(sessions: T[]): T[];
89
137
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"awaiting-overlay.d.ts","sourceRoot":"","sources":["../src/awaiting-overlay.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAGtD;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,YAAY,GAAG,YAAY,GAAG,QAAQ,CAAC;AAEnD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,YAAY,CAAC;IACnB,KAAK,EAAE,qBAAqB,GAAG,iBAAiB,CAAC;IACjD,QAAQ,EAAE,MAAM,CAAC;IACjB;gFAC4E;IAC5E,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B;;;uEAGmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;+DAE2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AA4BD,wBAAgB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAShG;AAED;;uEAEuE;AACvE,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAI7F;AAED;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,GAC7C,OAAO,CAkCT;AAED;;uEAEuE;AACvE,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,MAAM,GAChB,aAAa,GAAG,SAAS,CAW3B;AAED;;;2EAG2E;AAC3E,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED;gFACgF;AAChF,wBAAgB,2BAA2B,CACzC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,OAAO,CAOT;AAED,8BAA8B;AAC9B,wBAAgB,qBAAqB,IAAI,IAAI,CAE5C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,CAAC,SAAS;IACR,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB,EACD,QAAQ,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAyBpB;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAGnE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,wBAAwB,CACtC,gBAAgB,EAAE,MAAM,GAAG,SAAS,EACpC,OAAO,EAAE,MAAM,GACd,OAAO,CAKT;AAKD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,oBAAoB,CAAC,cAAc,EAAE,MAAM,GAAG,SAAS,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAY9F"}
1
+ {"version":3,"file":"awaiting-overlay.d.ts","sourceRoot":"","sources":["../src/awaiting-overlay.ts"],"names":[],"mappings":"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"}
@@ -40,25 +40,15 @@ export function setPermissionNotificationOverlay(sessionId, question) {
40
40
  setAwaitingOverlay(sessionId, question);
41
41
  return true;
42
42
  }
43
- /**
44
- * Lift a direct-Claude AskUserQuestion PreToolUse payload into a structured,
45
- * display-only option overlay. Claude supports one to four grouped questions,
46
- * while SessionInfo currently carries one question/options set; show the first
47
- * valid group rather than flattening unrelated groups into unsafe wire indices.
48
- * Returns false for malformed payloads so callers can preserve normal tool
49
- * processing instead of surfacing a dead prompt.
50
- */
51
- export function setAskUserQuestionOverlay(sessionId, toolUseId, toolInput) {
52
- if (typeof toolUseId !== 'string' || !toolUseId)
53
- return false;
54
- const rawQuestions = Array.isArray(toolInput?.questions) ? toolInput.questions : [];
55
- const first = rawQuestions.find((value) => isRecord(value) && typeof value.question === 'string' && value.question.trim().length > 0);
56
- if (!first)
57
- return false;
58
- const rawQuestion = first.question;
59
- if (typeof rawQuestion !== 'string')
60
- return false;
61
- const rawOptions = Array.isArray(first.options) ? first.options : [];
43
+ /** Sanitize one raw AskUserQuestion group. Returns undefined when the group has
44
+ * no usable question text or no labelled options. */
45
+ function parseAskGroup(raw) {
46
+ if (!isRecord(raw) || typeof raw.question !== 'string')
47
+ return undefined;
48
+ const question = raw.question.replace(/\s+/g, ' ').trim().slice(0, MAX_QUESTION_LEN);
49
+ if (!question)
50
+ return undefined;
51
+ const rawOptions = Array.isArray(raw.options) ? raw.options : [];
62
52
  const options = rawOptions.flatMap((value) => {
63
53
  if (!isRecord(value) || typeof value.label !== 'string')
64
54
  return [];
@@ -71,20 +61,100 @@ export function setAskUserQuestionOverlay(sessionId, toolUseId, toolInput) {
71
61
  }];
72
62
  }).map((option, index) => ({ ...option, index }));
73
63
  if (options.length === 0)
64
+ return undefined;
65
+ return {
66
+ question,
67
+ options,
68
+ ...(raw.multiSelect === true ? { promptType: 'multi_select' } : {}),
69
+ };
70
+ }
71
+ /** Copy a group's fields into the flat wire projection every surface renders. */
72
+ function projectGroup(entry, group) {
73
+ entry.question = group.question;
74
+ entry.options = group.options;
75
+ if (group.promptType)
76
+ entry.promptType = group.promptType;
77
+ else
78
+ delete entry.promptType;
79
+ }
80
+ /**
81
+ * Lift a direct-Claude AskUserQuestion PreToolUse payload into a structured
82
+ * option overlay. Claude supports one to four grouped questions while
83
+ * SessionInfo carries a single question/options pair, so ALL valid groups are
84
+ * kept here and presented one at a time (`advanceAskUserQuestionOverlay`)
85
+ * rather than flattened into one index space — flattening would let a press
86
+ * aimed at group 1 land on an option of group 2.
87
+ * Returns false for malformed payloads so callers can preserve normal tool
88
+ * processing instead of surfacing a dead prompt.
89
+ */
90
+ export function setAskUserQuestionOverlay(sessionId, toolUseId, toolInput) {
91
+ if (typeof toolUseId !== 'string' || !toolUseId)
74
92
  return false;
75
- const question = rawQuestion.replace(/\s+/g, ' ').trim().slice(0, MAX_QUESTION_LEN);
76
- const promptType = first.multiSelect === true ? 'multi_select' : undefined;
77
- overlay.set(sessionId, {
93
+ const rawQuestions = Array.isArray(toolInput?.questions) ? toolInput.questions : [];
94
+ const groups = rawQuestions
95
+ .map((raw) => parseAskGroup(raw))
96
+ .filter((group) => group !== undefined);
97
+ if (groups.length === 0)
98
+ return false;
99
+ const entry = {
78
100
  kind: 'option',
79
101
  state: 'awaiting_option',
80
- question,
81
- options,
82
- ...(promptType ? { promptType } : {}),
102
+ question: '',
103
+ groups,
104
+ activeGroup: 0,
105
+ rawGroupCount: rawQuestions.length,
106
+ answers: [],
83
107
  toolUseId,
84
108
  updatedAt: Date.now(),
85
- });
109
+ };
110
+ projectGroup(entry, groups[0]);
111
+ overlay.set(sessionId, entry);
86
112
  return true;
87
113
  }
114
+ /**
115
+ * Record the answer to the active question group and present the next one.
116
+ *
117
+ * Returns `'advanced'` when a further group is now showing (the caller must
118
+ * re-broadcast so devices swap to it), `'complete'` when that was the last
119
+ * group (the caller resolves the held ask-gate / waits for PostToolUse), or
120
+ * `'ignored'` when there is no active option overlay.
121
+ *
122
+ * `label` is the option text the user chose; it is kept so a held ask-gate can
123
+ * report every Q→A pair back to the agent.
124
+ */
125
+ export function advanceAskUserQuestionOverlay(sessionId, label) {
126
+ const entry = overlay.get(sessionId);
127
+ if (!entry || entry.kind !== 'option' || !entry.groups?.length)
128
+ return 'ignored';
129
+ const active = entry.activeGroup ?? 0;
130
+ // Already past the last group: report completion again but record nothing.
131
+ // A repeat press (a device that did not see the prompt close, a duplicate
132
+ // frame) would otherwise append another answer every time, growing the list
133
+ // without bound and reporting phantom answers back to the agent.
134
+ if (active >= entry.groups.length)
135
+ return 'complete';
136
+ entry.answers = [
137
+ ...(entry.answers ?? []),
138
+ { question: entry.groups[active]?.question ?? entry.question, label: label ?? '' },
139
+ ];
140
+ const next = active + 1;
141
+ if (next >= entry.groups.length) {
142
+ entry.activeGroup = next;
143
+ entry.updatedAt = Date.now();
144
+ return 'complete';
145
+ }
146
+ entry.activeGroup = next;
147
+ projectGroup(entry, entry.groups[next]);
148
+ entry.updatedAt = Date.now();
149
+ return 'advanced';
150
+ }
151
+ /** Q→A pairs recorded so far for a pending AskUserQuestion (held ask-gate). */
152
+ export function getAskUserQuestionAnswers(sessionId) {
153
+ const entry = overlay.get(sessionId);
154
+ if (!entry || entry.kind !== 'option')
155
+ return [];
156
+ return (entry.answers ?? []).map((a) => ({ ...a }));
157
+ }
88
158
  /** Returns the overlay entry if it exists and is still fresh (< TTL). Stale
89
159
  * entries are pruned on read. `updatedAt` is exposed so the observed-session
90
160
  * overlay can compare it against the session's transcript recency. */
@@ -99,6 +169,8 @@ export function getAwaitingOverlay(sessionId) {
99
169
  return {
100
170
  ...entry,
101
171
  options: entry.options?.map((option) => ({ ...option })),
172
+ groups: entry.groups?.map((group) => ({ ...group })),
173
+ answers: entry.answers?.map((answer) => ({ ...answer })),
102
174
  };
103
175
  }
104
176
  /** Unconditionally clear an overlay at an authoritative lifecycle boundary.
@@ -151,6 +223,9 @@ export function applyAwaitingOverlayToObserved(sessions) {
151
223
  clearAwaitingOverlay(uuid);
152
224
  return s;
153
225
  }
226
+ // Multi-group prompts advance one question at a time, so surfaces can show
227
+ // "Q 2/3". Single-group prompts omit the fields entirely (absent ⇒ one).
228
+ const multiGroup = (ov.groups?.length ?? 0) > 1;
154
229
  return {
155
230
  ...s,
156
231
  state: ov.state,
@@ -158,6 +233,14 @@ export function applyAwaitingOverlayToObserved(sessions) {
158
233
  requestId: ov.requestId,
159
234
  ...(ov.options ? { options: ov.options } : {}),
160
235
  ...(ov.promptType ? { promptType: ov.promptType } : {}),
236
+ ...(multiGroup
237
+ ? {
238
+ // Clamped: once the last group is answered the cursor sits one past
239
+ // the end, and "Q 4/3" is not a thing.
240
+ askGroupIndex: Math.min(ov.activeGroup ?? 0, ov.groups.length - 1),
241
+ askGroupCount: ov.groups.length,
242
+ }
243
+ : {}),
161
244
  };
162
245
  });
163
246
  }
@@ -1 +1 @@
1
- {"version":3,"file":"awaiting-overlay.js","sourceRoot":"","sources":["../src/awaiting-overlay.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"awaiting-overlay.js","sourceRoot":"","sources":["../src/awaiting-overlay.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAyP1D,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAM,CAAC;AAOtF;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AA+BD,gFAAgF;AAChF,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,aAAa,GAAG,WAAW,GAAG,UAAU,EAAE,MAAM,CAI5E,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAsBjE;AAKD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAyBV;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,OAAO,cAAc,EACtC,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,OAAO,cAAc,EACtC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,OAAO,EACvB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAER;AAID,QAAA,MAAM,OAAO,SAAgB,CAAC;AAgqE9B,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAwB,MAAM,WAAW,CAAC;AAyP1D,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAM,CAAC;AAOtF;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAElE;AA+BD,gFAAgF;AAChF,QAAA,MAAM,cAAc,EAAE,MAAM,CAAC,aAAa,GAAG,WAAW,GAAG,UAAU,EAAE,MAAM,CAI5E,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAsBjE;AAKD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,EAAE,CAyBV;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,OAAO,cAAc,EACtC,OAAO,EAAE,MAAM,EACf,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAIR;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,MAAM,OAAO,cAAc,EACtC,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,OAAO,EACvB,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,CAER;AAID,QAAA,MAAM,OAAO,SAAgB,CAAC;AAquE9B,wBAAsB,MAAM,CAAC,IAAI,GAAE,MAAM,EAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAMzE;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}