@thinkrun/cli 0.1.27
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 +349 -0
- package/dist/bin/thinkrun.d.ts +6 -0
- package/dist/bin/thinkrun.d.ts.map +1 -0
- package/dist/bin/thinkrun.js +124 -0
- package/dist/bin/thinkrun.js.map +1 -0
- package/dist/scripts/browse.sh +1107 -0
- package/dist/src/adapters/cloud.d.ts +79 -0
- package/dist/src/adapters/cloud.d.ts.map +1 -0
- package/dist/src/adapters/cloud.js +637 -0
- package/dist/src/adapters/cloud.js.map +1 -0
- package/dist/src/adapters/index.d.ts +47 -0
- package/dist/src/adapters/index.d.ts.map +1 -0
- package/dist/src/adapters/index.js +211 -0
- package/dist/src/adapters/index.js.map +1 -0
- package/dist/src/adapters/local-command-retry.d.ts +12 -0
- package/dist/src/adapters/local-command-retry.d.ts.map +1 -0
- package/dist/src/adapters/local-command-retry.js +224 -0
- package/dist/src/adapters/local-command-retry.js.map +1 -0
- package/dist/src/adapters/local.d.ts +136 -0
- package/dist/src/adapters/local.d.ts.map +1 -0
- package/dist/src/adapters/local.js +1273 -0
- package/dist/src/adapters/local.js.map +1 -0
- package/dist/src/adapters/types.d.ts +45 -0
- package/dist/src/adapters/types.d.ts.map +1 -0
- package/dist/src/adapters/types.js +6 -0
- package/dist/src/adapters/types.js.map +1 -0
- package/dist/src/commands/actions.d.ts +135 -0
- package/dist/src/commands/actions.d.ts.map +1 -0
- package/dist/src/commands/actions.js +2207 -0
- package/dist/src/commands/actions.js.map +1 -0
- package/dist/src/commands/agent-init.d.ts +16 -0
- package/dist/src/commands/agent-init.d.ts.map +1 -0
- package/dist/src/commands/agent-init.js +222 -0
- package/dist/src/commands/agent-init.js.map +1 -0
- package/dist/src/commands/analyze.d.ts +11 -0
- package/dist/src/commands/analyze.d.ts.map +1 -0
- package/dist/src/commands/analyze.js +238 -0
- package/dist/src/commands/analyze.js.map +1 -0
- package/dist/src/commands/cache.d.ts +6 -0
- package/dist/src/commands/cache.d.ts.map +1 -0
- package/dist/src/commands/cache.js +147 -0
- package/dist/src/commands/cache.js.map +1 -0
- package/dist/src/commands/cloud.d.ts +6 -0
- package/dist/src/commands/cloud.d.ts.map +1 -0
- package/dist/src/commands/cloud.js +332 -0
- package/dist/src/commands/cloud.js.map +1 -0
- package/dist/src/commands/config.d.ts +7 -0
- package/dist/src/commands/config.d.ts.map +1 -0
- package/dist/src/commands/config.js +208 -0
- package/dist/src/commands/config.js.map +1 -0
- package/dist/src/commands/doctor.d.ts +127 -0
- package/dist/src/commands/doctor.d.ts.map +1 -0
- package/dist/src/commands/doctor.js +684 -0
- package/dist/src/commands/doctor.js.map +1 -0
- package/dist/src/commands/evaluate-helpers.d.ts +6 -0
- package/dist/src/commands/evaluate-helpers.d.ts.map +1 -0
- package/dist/src/commands/evaluate-helpers.js +13 -0
- package/dist/src/commands/evaluate-helpers.js.map +1 -0
- package/dist/src/commands/install.d.ts +118 -0
- package/dist/src/commands/install.d.ts.map +1 -0
- package/dist/src/commands/install.js +975 -0
- package/dist/src/commands/install.js.map +1 -0
- package/dist/src/commands/release.d.ts +7 -0
- package/dist/src/commands/release.d.ts.map +1 -0
- package/dist/src/commands/release.js +123 -0
- package/dist/src/commands/release.js.map +1 -0
- package/dist/src/commands/reset-connection.d.ts +17 -0
- package/dist/src/commands/reset-connection.d.ts.map +1 -0
- package/dist/src/commands/reset-connection.js +141 -0
- package/dist/src/commands/reset-connection.js.map +1 -0
- package/dist/src/commands/session-debug.d.ts +23 -0
- package/dist/src/commands/session-debug.d.ts.map +1 -0
- package/dist/src/commands/session-debug.js +267 -0
- package/dist/src/commands/session-debug.js.map +1 -0
- package/dist/src/commands/setup.d.ts +53 -0
- package/dist/src/commands/setup.d.ts.map +1 -0
- package/dist/src/commands/setup.js +249 -0
- package/dist/src/commands/setup.js.map +1 -0
- package/dist/src/config/store.d.ts +39 -0
- package/dist/src/config/store.d.ts.map +1 -0
- package/dist/src/config/store.js +290 -0
- package/dist/src/config/store.js.map +1 -0
- package/dist/src/daemon/access.d.ts +53 -0
- package/dist/src/daemon/access.d.ts.map +1 -0
- package/dist/src/daemon/access.js +87 -0
- package/dist/src/daemon/access.js.map +1 -0
- package/dist/src/daemon/bridge-envelope.d.ts +96 -0
- package/dist/src/daemon/bridge-envelope.d.ts.map +1 -0
- package/dist/src/daemon/bridge-envelope.js +235 -0
- package/dist/src/daemon/bridge-envelope.js.map +1 -0
- package/dist/src/daemon/utils.d.ts +43 -0
- package/dist/src/daemon/utils.d.ts.map +1 -0
- package/dist/src/daemon/utils.js +134 -0
- package/dist/src/daemon/utils.js.map +1 -0
- package/dist/src/errors.d.ts +60 -0
- package/dist/src/errors.d.ts.map +1 -0
- package/dist/src/errors.js +87 -0
- package/dist/src/errors.js.map +1 -0
- package/dist/src/local-bridge-timing.d.ts +31 -0
- package/dist/src/local-bridge-timing.d.ts.map +1 -0
- package/dist/src/local-bridge-timing.js +41 -0
- package/dist/src/local-bridge-timing.js.map +1 -0
- package/dist/src/obstacle-recovery/classify-script.d.ts +16 -0
- package/dist/src/obstacle-recovery/classify-script.d.ts.map +1 -0
- package/dist/src/obstacle-recovery/classify-script.js +53 -0
- package/dist/src/obstacle-recovery/classify-script.js.map +1 -0
- package/dist/src/obstacle-recovery/obstacle-classifier.d.ts +21 -0
- package/dist/src/obstacle-recovery/obstacle-classifier.d.ts.map +1 -0
- package/dist/src/obstacle-recovery/obstacle-classifier.js +37 -0
- package/dist/src/obstacle-recovery/obstacle-classifier.js.map +1 -0
- package/dist/src/obstacle-recovery/state-fingerprint.d.ts +26 -0
- package/dist/src/obstacle-recovery/state-fingerprint.d.ts.map +1 -0
- package/dist/src/obstacle-recovery/state-fingerprint.js +85 -0
- package/dist/src/obstacle-recovery/state-fingerprint.js.map +1 -0
- package/dist/src/obstacle-recovery/types.d.ts +44 -0
- package/dist/src/obstacle-recovery/types.d.ts.map +1 -0
- package/dist/src/obstacle-recovery/types.js +16 -0
- package/dist/src/obstacle-recovery/types.js.map +1 -0
- package/dist/src/output/formatter.d.ts +55 -0
- package/dist/src/output/formatter.d.ts.map +1 -0
- package/dist/src/output/formatter.js +55 -0
- package/dist/src/output/formatter.js.map +1 -0
- package/dist/src/output/mode.d.ts +11 -0
- package/dist/src/output/mode.d.ts.map +1 -0
- package/dist/src/output/mode.js +16 -0
- package/dist/src/output/mode.js.map +1 -0
- package/dist/src/protected-flow/detector.d.ts +26 -0
- package/dist/src/protected-flow/detector.d.ts.map +1 -0
- package/dist/src/protected-flow/detector.js +75 -0
- package/dist/src/protected-flow/detector.js.map +1 -0
- package/dist/src/protected-flow/types.d.ts +24 -0
- package/dist/src/protected-flow/types.d.ts.map +1 -0
- package/dist/src/protected-flow/types.js +28 -0
- package/dist/src/protected-flow/types.js.map +1 -0
- package/dist/src/session/agent-identity.d.ts +65 -0
- package/dist/src/session/agent-identity.d.ts.map +1 -0
- package/dist/src/session/agent-identity.js +133 -0
- package/dist/src/session/agent-identity.js.map +1 -0
- package/dist/src/session/cli-session-sync.d.ts +72 -0
- package/dist/src/session/cli-session-sync.d.ts.map +1 -0
- package/dist/src/session/cli-session-sync.js +244 -0
- package/dist/src/session/cli-session-sync.js.map +1 -0
- package/dist/src/session/context.d.ts +24 -0
- package/dist/src/session/context.d.ts.map +1 -0
- package/dist/src/session/context.js +165 -0
- package/dist/src/session/context.js.map +1 -0
- package/dist/src/session/continuity.d.ts +33 -0
- package/dist/src/session/continuity.d.ts.map +1 -0
- package/dist/src/session/continuity.js +179 -0
- package/dist/src/session/continuity.js.map +1 -0
- package/dist/src/session/errors.d.ts +9 -0
- package/dist/src/session/errors.d.ts.map +1 -0
- package/dist/src/session/errors.js +31 -0
- package/dist/src/session/errors.js.map +1 -0
- package/dist/src/session/local-continuity.d.ts +16 -0
- package/dist/src/session/local-continuity.d.ts.map +1 -0
- package/dist/src/session/local-continuity.js +146 -0
- package/dist/src/session/local-continuity.js.map +1 -0
- package/dist/src/session/signal-handler.d.ts +24 -0
- package/dist/src/session/signal-handler.d.ts.map +1 -0
- package/dist/src/session/signal-handler.js +35 -0
- package/dist/src/session/signal-handler.js.map +1 -0
- package/dist/src/shared/local-recovery-policy.d.ts +40 -0
- package/dist/src/shared/local-recovery-policy.d.ts.map +1 -0
- package/dist/src/shared/local-recovery-policy.js +59 -0
- package/dist/src/shared/local-recovery-policy.js.map +1 -0
- package/dist/src/shared/recovery-state.d.ts +3 -0
- package/dist/src/shared/recovery-state.d.ts.map +1 -0
- package/dist/src/shared/recovery-state.js +9 -0
- package/dist/src/shared/recovery-state.js.map +1 -0
- package/dist/src/types.d.ts +131 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +5 -0
- package/dist/src/types.js.map +1 -0
- package/dist/src/utils.d.ts +50 -0
- package/dist/src/utils.d.ts.map +1 -0
- package/dist/src/utils.js +147 -0
- package/dist/src/utils.js.map +1 -0
- package/dist/src/working-location.d.ts +107 -0
- package/dist/src/working-location.d.ts.map +1 -0
- package/dist/src/working-location.js +651 -0
- package/dist/src/working-location.js.map +1 -0
- package/package.json +65 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bridge command envelope and delivery outcome enum (PRD 0086, Task 6.2).
|
|
3
|
+
*
|
|
4
|
+
* This module is shared between the daemon (Bun runtime) and the extension.
|
|
5
|
+
* It MUST NOT import Bun-specific APIs.
|
|
6
|
+
*
|
|
7
|
+
* Key invariant: replay decisions key on DeliveryOutcome values, NEVER on
|
|
8
|
+
* exception message strings.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* The only way to build a BridgeCommandEnvelope. `idempotency` is DERIVED from
|
|
12
|
+
* the policy table (a command is idempotent iff its replay policy is `queue`),
|
|
13
|
+
* so it cannot disagree with `commandType`.
|
|
14
|
+
*/
|
|
15
|
+
export function makeBridgeEnvelope(args) {
|
|
16
|
+
// The brand is a PHANTOM (type-only) property — never materialized at runtime.
|
|
17
|
+
// The `as` cast is the single sanctioned place that asserts it; callers can't
|
|
18
|
+
// reproduce this cast without referencing the module-private brand symbol.
|
|
19
|
+
return {
|
|
20
|
+
...args,
|
|
21
|
+
idempotency: getCommandPolicy(args.commandType).replay === 'queue' ? 'idempotent' : 'non-idempotent',
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Delivery outcome for a bridge command.
|
|
26
|
+
* All replay/retry logic must branch on these values — not on error strings.
|
|
27
|
+
*/
|
|
28
|
+
export var DeliveryOutcome;
|
|
29
|
+
(function (DeliveryOutcome) {
|
|
30
|
+
/** Command dispatched and executed successfully */
|
|
31
|
+
DeliveryOutcome["DELIVERED_SUCCESS"] = "DELIVERED_SUCCESS";
|
|
32
|
+
/** Command was dispatched but the page returned an error (e.g. ELEMENT_NOT_FOUND, SCRIPT_ERROR) */
|
|
33
|
+
DeliveryOutcome["DELIVERED_PAGE_ERROR"] = "DELIVERED_PAGE_ERROR";
|
|
34
|
+
/** Command was never delivered — transport layer failure (socket disconnected, timeout before send) */
|
|
35
|
+
DeliveryOutcome["NOT_DELIVERED_TRANSPORT_ERROR"] = "NOT_DELIVERED_TRANSPORT_ERROR";
|
|
36
|
+
/** Outcome is ambiguous — command may or may not have been executed (timeout after send) */
|
|
37
|
+
DeliveryOutcome["UNKNOWN_DELIVERY"] = "UNKNOWN_DELIVERY";
|
|
38
|
+
/** Command rejected because the transport is currently reconnecting */
|
|
39
|
+
DeliveryOutcome["REJECTED_RECONNECTING"] = "REJECTED_RECONNECTING";
|
|
40
|
+
})(DeliveryOutcome || (DeliveryOutcome = {}));
|
|
41
|
+
/**
|
|
42
|
+
* Per-command policy table.
|
|
43
|
+
*
|
|
44
|
+
* Design: policy as data — a plain const map, not a class.
|
|
45
|
+
* Default-deny: anything not listed falls back to neverReplay (fail safe).
|
|
46
|
+
*
|
|
47
|
+
* Idempotent reads → 'queue': safe to replay after reconnect.
|
|
48
|
+
* Mutations → 'failFast': outcome unknown after disconnect; caller must decide.
|
|
49
|
+
* evaluate → 'failFast': opaque script may mutate page state; NOT idempotent.
|
|
50
|
+
*/
|
|
51
|
+
export const BRIDGE_COMMAND_POLICY = {
|
|
52
|
+
// Idempotent reads — safe to replay
|
|
53
|
+
get_url: {
|
|
54
|
+
replay: 'queue',
|
|
55
|
+
timeoutMs: 10_000,
|
|
56
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
57
|
+
},
|
|
58
|
+
get_title: {
|
|
59
|
+
replay: 'queue',
|
|
60
|
+
timeoutMs: 10_000,
|
|
61
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
62
|
+
},
|
|
63
|
+
get_html: {
|
|
64
|
+
replay: 'queue',
|
|
65
|
+
timeoutMs: 30_000,
|
|
66
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
67
|
+
},
|
|
68
|
+
list_tabs: {
|
|
69
|
+
replay: 'queue',
|
|
70
|
+
timeoutMs: 10_000,
|
|
71
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
72
|
+
},
|
|
73
|
+
screenshot: {
|
|
74
|
+
replay: 'queue',
|
|
75
|
+
timeoutMs: 30_000,
|
|
76
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
77
|
+
},
|
|
78
|
+
snapshot: {
|
|
79
|
+
replay: 'queue',
|
|
80
|
+
timeoutMs: 30_000,
|
|
81
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
82
|
+
},
|
|
83
|
+
extract: {
|
|
84
|
+
replay: 'queue',
|
|
85
|
+
timeoutMs: 30_000,
|
|
86
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
87
|
+
},
|
|
88
|
+
get_session: {
|
|
89
|
+
replay: 'queue',
|
|
90
|
+
timeoutMs: 10_000,
|
|
91
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
92
|
+
},
|
|
93
|
+
get_console_logs: {
|
|
94
|
+
replay: 'queue',
|
|
95
|
+
timeoutMs: 10_000,
|
|
96
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
97
|
+
},
|
|
98
|
+
get_network_logs: {
|
|
99
|
+
replay: 'queue',
|
|
100
|
+
timeoutMs: 10_000,
|
|
101
|
+
retryHint: 'Safe to retry — idempotent read.',
|
|
102
|
+
},
|
|
103
|
+
wait: {
|
|
104
|
+
replay: 'queue',
|
|
105
|
+
timeoutMs: 60_000,
|
|
106
|
+
retryHint: 'Safe to retry — idempotent wait.',
|
|
107
|
+
},
|
|
108
|
+
wait_for_text: {
|
|
109
|
+
replay: 'queue',
|
|
110
|
+
timeoutMs: 60_000,
|
|
111
|
+
retryHint: 'Safe to retry — idempotent wait.',
|
|
112
|
+
},
|
|
113
|
+
// Mutations — outcome unknown after disconnect; do NOT replay automatically
|
|
114
|
+
navigate: {
|
|
115
|
+
replay: 'failFast',
|
|
116
|
+
timeoutMs: 30_000,
|
|
117
|
+
retryHint: 'Navigation may have completed before disconnect. Verify the page state before retrying.',
|
|
118
|
+
},
|
|
119
|
+
go_back: {
|
|
120
|
+
replay: 'failFast',
|
|
121
|
+
timeoutMs: 15_000,
|
|
122
|
+
retryHint: 'Navigation may have completed before disconnect. Verify the page state before retrying.',
|
|
123
|
+
},
|
|
124
|
+
go_forward: {
|
|
125
|
+
replay: 'failFast',
|
|
126
|
+
timeoutMs: 15_000,
|
|
127
|
+
retryHint: 'Navigation may have completed before disconnect. Verify the page state before retrying.',
|
|
128
|
+
},
|
|
129
|
+
click: {
|
|
130
|
+
replay: 'failFast',
|
|
131
|
+
timeoutMs: 15_000,
|
|
132
|
+
retryHint: 'Click may have been delivered. Verify the page state before retrying.',
|
|
133
|
+
},
|
|
134
|
+
type: {
|
|
135
|
+
replay: 'failFast',
|
|
136
|
+
timeoutMs: 30_000,
|
|
137
|
+
retryHint: 'Text may have been partially typed. Verify the page state before retrying.',
|
|
138
|
+
},
|
|
139
|
+
fill: {
|
|
140
|
+
replay: 'failFast',
|
|
141
|
+
timeoutMs: 15_000,
|
|
142
|
+
retryHint: 'Fill may have been partially applied. Verify the page state before retrying.',
|
|
143
|
+
},
|
|
144
|
+
press: {
|
|
145
|
+
replay: 'failFast',
|
|
146
|
+
timeoutMs: 15_000,
|
|
147
|
+
retryHint: 'Key press may have been delivered. Verify the page state before retrying.',
|
|
148
|
+
},
|
|
149
|
+
scroll: {
|
|
150
|
+
replay: 'failFast',
|
|
151
|
+
timeoutMs: 15_000,
|
|
152
|
+
retryHint: 'Scroll may have been applied. Verify the page state before retrying.',
|
|
153
|
+
},
|
|
154
|
+
hover: {
|
|
155
|
+
replay: 'failFast',
|
|
156
|
+
timeoutMs: 10_000,
|
|
157
|
+
retryHint: 'Hover may have been applied. Verify the page state before retrying.',
|
|
158
|
+
},
|
|
159
|
+
select: {
|
|
160
|
+
replay: 'failFast',
|
|
161
|
+
timeoutMs: 15_000,
|
|
162
|
+
retryHint: 'Selection may have been applied. Verify the page state before retrying.',
|
|
163
|
+
},
|
|
164
|
+
handle_dialog: {
|
|
165
|
+
replay: 'failFast',
|
|
166
|
+
timeoutMs: 15_000,
|
|
167
|
+
retryHint: 'Dialog interaction may have been applied. Verify the page state before retrying.',
|
|
168
|
+
},
|
|
169
|
+
clear_logs: {
|
|
170
|
+
replay: 'failFast',
|
|
171
|
+
timeoutMs: 10_000,
|
|
172
|
+
retryHint: 'Log clear may have been applied. Verify the page state before retrying.',
|
|
173
|
+
},
|
|
174
|
+
// evaluate: opaque script; may mutate page state — explicitly NOT idempotent
|
|
175
|
+
evaluate: {
|
|
176
|
+
replay: 'failFast',
|
|
177
|
+
timeoutMs: 30_000,
|
|
178
|
+
retryHint: 'Script execution outcome is unknown. Do not retry evaluate automatically; verify page state.',
|
|
179
|
+
},
|
|
180
|
+
};
|
|
181
|
+
/**
|
|
182
|
+
* The default policy applied when a commandType is not found in BRIDGE_COMMAND_POLICY.
|
|
183
|
+
* Conservative fail-safe: never replay unknown commands.
|
|
184
|
+
*/
|
|
185
|
+
/** Single source for the fallback timeout so default-policy and any future use can't diverge. */
|
|
186
|
+
export const DEFAULT_COMMAND_TIMEOUT_MS = 30_000;
|
|
187
|
+
const DEFAULT_POLICY = {
|
|
188
|
+
replay: 'neverReplay',
|
|
189
|
+
timeoutMs: DEFAULT_COMMAND_TIMEOUT_MS,
|
|
190
|
+
retryHint: 'Unknown command type. Cannot safely replay — fail fast.',
|
|
191
|
+
};
|
|
192
|
+
/**
|
|
193
|
+
* Returns the replay/timeout policy for the given commandType.
|
|
194
|
+
* Falls back to the default-deny policy for unlisted commands.
|
|
195
|
+
*/
|
|
196
|
+
export function getCommandPolicy(commandType) {
|
|
197
|
+
return BRIDGE_COMMAND_POLICY[commandType] ?? DEFAULT_POLICY;
|
|
198
|
+
}
|
|
199
|
+
// ============================================================================
|
|
200
|
+
// Failure → DeliveryOutcome mapping
|
|
201
|
+
// ============================================================================
|
|
202
|
+
/**
|
|
203
|
+
* Map an error code and send-state to the appropriate DeliveryOutcome.
|
|
204
|
+
*
|
|
205
|
+
* @param errorCode The `.code` property from the thrown Error.
|
|
206
|
+
* @param sentBeforeDisconnect Whether the WS send() had already been called before
|
|
207
|
+
* the disconnect was detected.
|
|
208
|
+
*/
|
|
209
|
+
export function mapFailureToOutcome(errorCode, sentBeforeDisconnect) {
|
|
210
|
+
switch (errorCode) {
|
|
211
|
+
case 'EXTENSION_NOT_CONNECTED':
|
|
212
|
+
return DeliveryOutcome.REJECTED_RECONNECTING;
|
|
213
|
+
case 'EXTENSION_DISCONNECTED':
|
|
214
|
+
return sentBeforeDisconnect
|
|
215
|
+
? DeliveryOutcome.UNKNOWN_DELIVERY
|
|
216
|
+
: DeliveryOutcome.REJECTED_RECONNECTING;
|
|
217
|
+
case 'REQUEST_TIMEOUT':
|
|
218
|
+
return sentBeforeDisconnect
|
|
219
|
+
? DeliveryOutcome.UNKNOWN_DELIVERY
|
|
220
|
+
: DeliveryOutcome.NOT_DELIVERED_TRANSPORT_ERROR;
|
|
221
|
+
case 'ECONNREFUSED':
|
|
222
|
+
case 'NATIVE_HOST_UNREACHABLE':
|
|
223
|
+
return DeliveryOutcome.NOT_DELIVERED_TRANSPORT_ERROR;
|
|
224
|
+
case 'ELEMENT_NOT_FOUND':
|
|
225
|
+
case 'SCRIPT_ERROR':
|
|
226
|
+
case 'NAVIGATION_FAILED':
|
|
227
|
+
case 'EVALUATE_FAILED':
|
|
228
|
+
case 'INVALID_SELECTOR':
|
|
229
|
+
case 'TAB_NOT_FOUND':
|
|
230
|
+
return DeliveryOutcome.DELIVERED_PAGE_ERROR;
|
|
231
|
+
default:
|
|
232
|
+
return DeliveryOutcome.UNKNOWN_DELIVERY;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
//# sourceMappingURL=bridge-envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge-envelope.js","sourceRoot":"","sources":["../../../src/daemon/bridge-envelope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure utility functions for the bridge daemon that do NOT require Bun types.
|
|
3
|
+
* These are safe to import from src/commands/ (which is tsc-compiled).
|
|
4
|
+
*
|
|
5
|
+
* daemon.ts (which uses Bun.serve) is excluded from tsc compilation — see
|
|
6
|
+
* tsconfig.json. This module provides the subset needed by doctor.ts.
|
|
7
|
+
*/
|
|
8
|
+
/** Semver of this daemon implementation */
|
|
9
|
+
export declare const DAEMON_VERSION = "0.1.0";
|
|
10
|
+
/**
|
|
11
|
+
* Protocol version for the bootstrap handshake.
|
|
12
|
+
* Increment when the WS contract or daemon.json shape changes.
|
|
13
|
+
*/
|
|
14
|
+
export declare const DAEMON_PROTOCOL_VERSION = 1;
|
|
15
|
+
export declare function getDiscoveryDir(): string;
|
|
16
|
+
export declare function getDaemonJsonPath(): string;
|
|
17
|
+
export interface DaemonConfig {
|
|
18
|
+
port: number;
|
|
19
|
+
token: string;
|
|
20
|
+
pid: number;
|
|
21
|
+
startedAt: string;
|
|
22
|
+
owner: 'daemon';
|
|
23
|
+
protocolVersion: number;
|
|
24
|
+
binaryVersion: string;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Returns true if a process with the given PID is currently running.
|
|
28
|
+
* On POSIX, signal 0 tests liveness without sending a real signal.
|
|
29
|
+
* Returns false on any error — conservative for stale detection.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isPidAlive(pid: number): boolean;
|
|
32
|
+
export declare function generateToken(): string;
|
|
33
|
+
export declare function writeDaemonConfigSync(config: DaemonConfig): void;
|
|
34
|
+
export declare function removeDaemonConfig(): void;
|
|
35
|
+
/**
|
|
36
|
+
* Read daemon.json with optional stale-file detection (PID liveness check).
|
|
37
|
+
*
|
|
38
|
+
* @param checkPid When true (default), validate the pid field against the OS.
|
|
39
|
+
* Dead PID → treats file as absent (stale).
|
|
40
|
+
*/
|
|
41
|
+
export declare function readDaemonConfig(checkPid?: boolean): DaemonConfig | null;
|
|
42
|
+
export declare function probeDaemonHealth(port: number): Promise<boolean>;
|
|
43
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/daemon/utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AASH,2CAA2C;AAC3C,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC;;;GAGG;AACH,eAAO,MAAM,uBAAuB,IAAI,CAAC;AAMzC,wBAAgB,eAAe,IAAI,MAAM,CAGxC;AAED,wBAAgB,iBAAiB,IAAI,MAAM,CAO1C;AAMD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,QAAQ,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;CACvB;AAMD;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAQ/C;AAMD,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAMD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAQhE;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAOzC;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,UAAO,GAAG,YAAY,GAAG,IAAI,CAwBrE;AAMD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWtE"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure utility functions for the bridge daemon that do NOT require Bun types.
|
|
3
|
+
* These are safe to import from src/commands/ (which is tsc-compiled).
|
|
4
|
+
*
|
|
5
|
+
* daemon.ts (which uses Bun.serve) is excluded from tsc compilation — see
|
|
6
|
+
* tsconfig.json. This module provides the subset needed by doctor.ts.
|
|
7
|
+
*/
|
|
8
|
+
import { mkdirSync, writeFileSync, chmodSync, existsSync, unlinkSync, readFileSync, renameSync } from 'fs';
|
|
9
|
+
import { join } from 'path';
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Protocol/version constants
|
|
12
|
+
// ============================================================================
|
|
13
|
+
/** Semver of this daemon implementation */
|
|
14
|
+
export const DAEMON_VERSION = '0.1.0';
|
|
15
|
+
/**
|
|
16
|
+
* Protocol version for the bootstrap handshake.
|
|
17
|
+
* Increment when the WS contract or daemon.json shape changes.
|
|
18
|
+
*/
|
|
19
|
+
export const DAEMON_PROTOCOL_VERSION = 1;
|
|
20
|
+
// ============================================================================
|
|
21
|
+
// Path helpers (dynamic — tests can override HOME via process.env)
|
|
22
|
+
// ============================================================================
|
|
23
|
+
export function getDiscoveryDir() {
|
|
24
|
+
const home = process.env.HOME || process.env.USERPROFILE || '/tmp';
|
|
25
|
+
return join(home, '.thinkrun');
|
|
26
|
+
}
|
|
27
|
+
export function getDaemonJsonPath() {
|
|
28
|
+
const current = join(getDiscoveryDir(), 'daemon.json');
|
|
29
|
+
const home = process.env.HOME || process.env.USERPROFILE || '/tmp';
|
|
30
|
+
const legacy = join(home, '.thinkbrowse', 'daemon.json');
|
|
31
|
+
if (existsSync(current))
|
|
32
|
+
return current;
|
|
33
|
+
if (existsSync(legacy))
|
|
34
|
+
return legacy;
|
|
35
|
+
return current;
|
|
36
|
+
}
|
|
37
|
+
// ============================================================================
|
|
38
|
+
// PID liveness check
|
|
39
|
+
// ============================================================================
|
|
40
|
+
/**
|
|
41
|
+
* Returns true if a process with the given PID is currently running.
|
|
42
|
+
* On POSIX, signal 0 tests liveness without sending a real signal.
|
|
43
|
+
* Returns false on any error — conservative for stale detection.
|
|
44
|
+
*/
|
|
45
|
+
export function isPidAlive(pid) {
|
|
46
|
+
if (process.platform === 'win32')
|
|
47
|
+
return false;
|
|
48
|
+
try {
|
|
49
|
+
process.kill(pid, 0);
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// ============================================================================
|
|
57
|
+
// Token generation
|
|
58
|
+
// ============================================================================
|
|
59
|
+
export function generateToken() {
|
|
60
|
+
const buf = new Uint8Array(32);
|
|
61
|
+
crypto.getRandomValues(buf);
|
|
62
|
+
return Array.from(buf)
|
|
63
|
+
.map((b) => b.toString(16).padStart(2, '0'))
|
|
64
|
+
.join('');
|
|
65
|
+
}
|
|
66
|
+
// ============================================================================
|
|
67
|
+
// Config file helpers
|
|
68
|
+
// ============================================================================
|
|
69
|
+
export function writeDaemonConfigSync(config) {
|
|
70
|
+
const discoveryDir = getDiscoveryDir();
|
|
71
|
+
const daemonJson = getDaemonJsonPath();
|
|
72
|
+
mkdirSync(discoveryDir, { recursive: true });
|
|
73
|
+
const tmp = `${daemonJson}.tmp`;
|
|
74
|
+
writeFileSync(tmp, JSON.stringify(config, null, 2), { encoding: 'utf-8', mode: 0o600 });
|
|
75
|
+
chmodSync(tmp, 0o600);
|
|
76
|
+
renameSync(tmp, daemonJson); // atomic on POSIX
|
|
77
|
+
}
|
|
78
|
+
export function removeDaemonConfig() {
|
|
79
|
+
const daemonJson = getDaemonJsonPath();
|
|
80
|
+
try {
|
|
81
|
+
if (existsSync(daemonJson))
|
|
82
|
+
unlinkSync(daemonJson);
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
// best effort on shutdown
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Read daemon.json with optional stale-file detection (PID liveness check).
|
|
90
|
+
*
|
|
91
|
+
* @param checkPid When true (default), validate the pid field against the OS.
|
|
92
|
+
* Dead PID → treats file as absent (stale).
|
|
93
|
+
*/
|
|
94
|
+
export function readDaemonConfig(checkPid = true) {
|
|
95
|
+
const daemonJson = getDaemonJsonPath();
|
|
96
|
+
try {
|
|
97
|
+
if (!existsSync(daemonJson))
|
|
98
|
+
return null;
|
|
99
|
+
const text = readFileSync(daemonJson, 'utf-8');
|
|
100
|
+
const parsed = JSON.parse(text);
|
|
101
|
+
if (parsed === null ||
|
|
102
|
+
typeof parsed !== 'object' ||
|
|
103
|
+
typeof parsed.port !== 'number' ||
|
|
104
|
+
typeof parsed.token !== 'string') {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
const cfg = parsed;
|
|
108
|
+
if (checkPid && typeof cfg.pid === 'number' && !isPidAlive(cfg.pid)) {
|
|
109
|
+
return null; // stale file — SIGKILL orphan
|
|
110
|
+
}
|
|
111
|
+
return cfg;
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
// ============================================================================
|
|
118
|
+
// Health probe
|
|
119
|
+
// ============================================================================
|
|
120
|
+
export async function probeDaemonHealth(port) {
|
|
121
|
+
const ctrl = new AbortController();
|
|
122
|
+
const timer = setTimeout(() => ctrl.abort(), 2_000);
|
|
123
|
+
try {
|
|
124
|
+
const res = await fetch(`http://127.0.0.1:${port}/health`, { signal: ctrl.signal });
|
|
125
|
+
return res.ok;
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
finally {
|
|
131
|
+
clearTimeout(timer);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/daemon/utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC3G,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,+EAA+E;AAC/E,6BAA6B;AAC7B,+EAA+E;AAE/E,2CAA2C;AAC3C,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC;AAEzC,+EAA+E;AAC/E,mEAAmE;AACnE,+EAA+E;AAE/E,MAAM,UAAU,eAAe;IAC7B,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,CAAC;IACnE,OAAO,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,iBAAiB;IAC/B,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,EAAE,EAAE,aAAa,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,MAAM,CAAC;IACnE,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,EAAE,aAAa,CAAC,CAAC;IACzD,IAAI,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IACxC,IAAI,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACtC,OAAO,OAAO,CAAC;AACjB,CAAC;AAgBD,+EAA+E;AAC/E,qBAAqB;AACrB,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;QAAE,OAAO,KAAK,CAAC;IAC/C,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,mBAAmB;AACnB,+EAA+E;AAE/E,MAAM,UAAU,aAAa;IAC3B,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IAC/B,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC;IAC5B,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;SACnB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;SAC3C,IAAI,CAAC,EAAE,CAAC,CAAC;AACd,CAAC;AAED,+EAA+E;AAC/E,sBAAsB;AACtB,+EAA+E;AAE/E,MAAM,UAAU,qBAAqB,CAAC,MAAoB;IACxD,MAAM,YAAY,GAAG,eAAe,EAAE,CAAC;IACvC,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IACvC,SAAS,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC7C,MAAM,GAAG,GAAG,GAAG,UAAU,MAAM,CAAC;IAChC,aAAa,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACxF,SAAS,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;IACtB,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,kBAAkB;AACjD,CAAC;AAED,MAAM,UAAU,kBAAkB;IAChC,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,IAAI,UAAU,CAAC,UAAU,CAAC;YAAE,UAAU,CAAC,UAAU,CAAC,CAAC;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,0BAA0B;IAC5B,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAQ,GAAG,IAAI;IAC9C,MAAM,UAAU,GAAG,iBAAiB,EAAE,CAAC;IACvC,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC;QACzC,MAAM,IAAI,GAAG,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAY,CAAC;QAC3C,IACE,MAAM,KAAK,IAAI;YACf,OAAO,MAAM,KAAK,QAAQ;YAC1B,OAAQ,MAAkC,CAAC,IAAI,KAAK,QAAQ;YAC5D,OAAQ,MAAkC,CAAC,KAAK,KAAK,QAAQ,EAC7D,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,MAAM,GAAG,GAAG,MAAsB,CAAC;QAEnC,IAAI,QAAQ,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACpE,OAAO,IAAI,CAAC,CAAC,8BAA8B;QAC7C,CAAC;QAED,OAAO,GAAG,CAAC;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,+EAA+E;AAC/E,eAAe;AACf,+EAA+E;AAE/E,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,IAAY;IAClD,MAAM,IAAI,GAAG,IAAI,eAAe,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;IACpD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,oBAAoB,IAAI,SAAS,EAAE,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACpF,OAAO,GAAG,CAAC,EAAE,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error classes for ThinkRun CLI
|
|
3
|
+
*/
|
|
4
|
+
export declare class ThinkRunError extends Error {
|
|
5
|
+
code: string;
|
|
6
|
+
suggestion?: string | undefined;
|
|
7
|
+
constructor(message: string, code: string, suggestion?: string | undefined);
|
|
8
|
+
}
|
|
9
|
+
export declare class ConfigError extends ThinkRunError {
|
|
10
|
+
constructor(message: string, suggestion?: string);
|
|
11
|
+
}
|
|
12
|
+
export declare class ApiError extends ThinkRunError {
|
|
13
|
+
statusCode?: number | undefined;
|
|
14
|
+
nativeCode?: string | undefined;
|
|
15
|
+
retryable?: boolean | undefined;
|
|
16
|
+
/** Billing / plan upgrade link when server returns INSUFFICIENT_SCOPE. */
|
|
17
|
+
upgradeUrl?: string | undefined;
|
|
18
|
+
/** Obstacle classification when an element-not-found error is enriched. */
|
|
19
|
+
obstacleType?: string;
|
|
20
|
+
/**
|
|
21
|
+
* PRD 0086 6.2b — daemon-supplied recovery signal on the local (daemon)
|
|
22
|
+
* transport. Set post-construction from the daemon's JSON error so a CLI
|
|
23
|
+
* caller can branch on the delivery outcome / replay policy instead of
|
|
24
|
+
* parsing error strings. Absent on cloud-transport errors. The replay
|
|
25
|
+
* DECISION that consumes these is tracked as FU-4.
|
|
26
|
+
*/
|
|
27
|
+
deliveryOutcome?: 'DELIVERED_SUCCESS' | 'DELIVERED_PAGE_ERROR' | 'NOT_DELIVERED_TRANSPORT_ERROR' | 'UNKNOWN_DELIVERY' | 'REJECTED_RECONNECTING';
|
|
28
|
+
/** Replay policy for this command. */
|
|
29
|
+
replayPolicy?: 'queue' | 'failFast' | 'neverReplay';
|
|
30
|
+
/**
|
|
31
|
+
* Policy-specific retry hint. NOTE the division of labor: `suggestion`
|
|
32
|
+
* (the ThinkRunError field) is the human-facing display hint; `retryHint`
|
|
33
|
+
* is for a PROGRAMMATIC retry decision (FU-4) and is not meant for direct
|
|
34
|
+
* display. A caller rendering errors should show `suggestion`, not both.
|
|
35
|
+
*/
|
|
36
|
+
retryHint?: string;
|
|
37
|
+
/**
|
|
38
|
+
* Positional args after `message`: optional HTTP status, suggestion, `nativeCode`,
|
|
39
|
+
* `retryable`, `upgradeUrl`. Callers must pass `retryable` before `upgradeUrl` when
|
|
40
|
+
* using positional form; no production callsite passes `retryable` today.
|
|
41
|
+
*/
|
|
42
|
+
constructor(message: string, statusCode?: number | undefined, suggestion?: string, nativeCode?: string | undefined, retryable?: boolean | undefined,
|
|
43
|
+
/** Billing / plan upgrade link when server returns INSUFFICIENT_SCOPE. */
|
|
44
|
+
upgradeUrl?: string | undefined);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* PRD 0086 B2 — API key lifecycle errors with distinct, diagnosable codes.
|
|
48
|
+
* MISSING: never configured. MALFORMED: stored value failed shape validation
|
|
49
|
+
* (quarantined). REJECTED: well-formed key refused by the server (401/403).
|
|
50
|
+
*/
|
|
51
|
+
export declare class ApiKeyError extends ApiError {
|
|
52
|
+
constructor(message: string, code: 'API_KEY_MISSING' | 'API_KEY_MALFORMED' | 'API_KEY_REJECTED', suggestion?: string, statusCode?: number);
|
|
53
|
+
}
|
|
54
|
+
export declare class SessionError extends ThinkRunError {
|
|
55
|
+
constructor(message: string, suggestion?: string);
|
|
56
|
+
}
|
|
57
|
+
export declare class ActionError extends ThinkRunError {
|
|
58
|
+
constructor(message: string, suggestion?: string);
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,qBAAa,aAAc,SAAQ,KAAK;IAG7B,IAAI,EAAE,MAAM;IACZ,UAAU,CAAC,EAAE,MAAM;gBAF1B,OAAO,EAAE,MAAM,EACR,IAAI,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,YAAA;CAK7B;AAED,qBAAa,WAAY,SAAQ,aAAa;gBAChC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAIjD;AAED,qBAAa,QAAS,SAAQ,aAAa;IAoChC,UAAU,CAAC,EAAE,MAAM;IAEnB,UAAU,CAAC,EAAE,MAAM;IACnB,SAAS,CAAC,EAAE,OAAO;IAC1B,0EAA0E;IACnE,UAAU,CAAC,EAAE,MAAM;IAxC5B,2EAA2E;IAC3E,YAAY,CAAC,EAAE,MAAM,CAAC;IAEtB;;;;;;OAMG;IAGH,eAAe,CAAC,EACZ,mBAAmB,GACnB,sBAAsB,GACtB,+BAA+B,GAC/B,kBAAkB,GAClB,uBAAuB,CAAC;IAC5B,sCAAsC;IACtC,YAAY,CAAC,EAAE,OAAO,GAAG,UAAU,GAAG,aAAa,CAAC;IACpD;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;;OAIG;gBAED,OAAO,EAAE,MAAM,EACR,UAAU,CAAC,EAAE,MAAM,YAAA,EAC1B,UAAU,CAAC,EAAE,MAAM,EACZ,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,SAAS,CAAC,EAAE,OAAO,YAAA;IAC1B,0EAA0E;IACnE,UAAU,CAAC,EAAE,MAAM,YAAA;CAK7B;AAED;;;;GAIG;AACH,qBAAa,WAAY,SAAQ,QAAQ;gBAErC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,iBAAiB,GAAG,mBAAmB,GAAG,kBAAkB,EAClE,UAAU,CAAC,EAAE,MAAM,EACnB,UAAU,CAAC,EAAE,MAAM;CAOtB;AAED,qBAAa,YAAa,SAAQ,aAAa;gBACjC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAIjD;AAED,qBAAa,WAAY,SAAQ,aAAa;gBAChC,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM;CAIjD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error classes for ThinkRun CLI
|
|
3
|
+
*/
|
|
4
|
+
export class ThinkRunError extends Error {
|
|
5
|
+
code;
|
|
6
|
+
suggestion;
|
|
7
|
+
constructor(message, code, suggestion) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.code = code;
|
|
10
|
+
this.suggestion = suggestion;
|
|
11
|
+
this.name = 'ThinkRunError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export class ConfigError extends ThinkRunError {
|
|
15
|
+
constructor(message, suggestion) {
|
|
16
|
+
super(message, 'CONFIG_ERROR', suggestion);
|
|
17
|
+
this.name = 'ConfigError';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class ApiError extends ThinkRunError {
|
|
21
|
+
statusCode;
|
|
22
|
+
nativeCode;
|
|
23
|
+
retryable;
|
|
24
|
+
upgradeUrl;
|
|
25
|
+
/** Obstacle classification when an element-not-found error is enriched. */
|
|
26
|
+
obstacleType;
|
|
27
|
+
/**
|
|
28
|
+
* PRD 0086 6.2b — daemon-supplied recovery signal on the local (daemon)
|
|
29
|
+
* transport. Set post-construction from the daemon's JSON error so a CLI
|
|
30
|
+
* caller can branch on the delivery outcome / replay policy instead of
|
|
31
|
+
* parsing error strings. Absent on cloud-transport errors. The replay
|
|
32
|
+
* DECISION that consumes these is tracked as FU-4.
|
|
33
|
+
*/
|
|
34
|
+
// String-literal unions (re-declared here, not imported) keep errors.ts free
|
|
35
|
+
// of a dependency on daemon/bridge-envelope while staying type-safe for FU-4.
|
|
36
|
+
deliveryOutcome;
|
|
37
|
+
/** Replay policy for this command. */
|
|
38
|
+
replayPolicy;
|
|
39
|
+
/**
|
|
40
|
+
* Policy-specific retry hint. NOTE the division of labor: `suggestion`
|
|
41
|
+
* (the ThinkRunError field) is the human-facing display hint; `retryHint`
|
|
42
|
+
* is for a PROGRAMMATIC retry decision (FU-4) and is not meant for direct
|
|
43
|
+
* display. A caller rendering errors should show `suggestion`, not both.
|
|
44
|
+
*/
|
|
45
|
+
retryHint;
|
|
46
|
+
/**
|
|
47
|
+
* Positional args after `message`: optional HTTP status, suggestion, `nativeCode`,
|
|
48
|
+
* `retryable`, `upgradeUrl`. Callers must pass `retryable` before `upgradeUrl` when
|
|
49
|
+
* using positional form; no production callsite passes `retryable` today.
|
|
50
|
+
*/
|
|
51
|
+
constructor(message, statusCode, suggestion, nativeCode, retryable,
|
|
52
|
+
/** Billing / plan upgrade link when server returns INSUFFICIENT_SCOPE. */
|
|
53
|
+
upgradeUrl) {
|
|
54
|
+
super(message, nativeCode ?? 'API_ERROR', suggestion);
|
|
55
|
+
this.statusCode = statusCode;
|
|
56
|
+
this.nativeCode = nativeCode;
|
|
57
|
+
this.retryable = retryable;
|
|
58
|
+
this.upgradeUrl = upgradeUrl;
|
|
59
|
+
this.name = 'ApiError';
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* PRD 0086 B2 — API key lifecycle errors with distinct, diagnosable codes.
|
|
64
|
+
* MISSING: never configured. MALFORMED: stored value failed shape validation
|
|
65
|
+
* (quarantined). REJECTED: well-formed key refused by the server (401/403).
|
|
66
|
+
*/
|
|
67
|
+
export class ApiKeyError extends ApiError {
|
|
68
|
+
constructor(message, code, suggestion, statusCode) {
|
|
69
|
+
// Extends ApiError so every existing `instanceof ApiError` guard catches
|
|
70
|
+
// key errors for free; `code` rides the nativeCode slot.
|
|
71
|
+
super(message, statusCode, suggestion, code);
|
|
72
|
+
this.name = 'ApiKeyError';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
export class SessionError extends ThinkRunError {
|
|
76
|
+
constructor(message, suggestion) {
|
|
77
|
+
super(message, 'SESSION_ERROR', suggestion);
|
|
78
|
+
this.name = 'SessionError';
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
export class ActionError extends ThinkRunError {
|
|
82
|
+
constructor(message, suggestion) {
|
|
83
|
+
super(message, 'ACTION_ERROR', suggestion);
|
|
84
|
+
this.name = 'ActionError';
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,OAAO,aAAc,SAAQ,KAAK;IAG7B;IACA;IAHT,YACE,OAAe,EACR,IAAY,EACZ,UAAmB;QAE1B,KAAK,CAAC,OAAO,CAAC,CAAC;QAHR,SAAI,GAAJ,IAAI,CAAQ;QACZ,eAAU,GAAV,UAAU,CAAS;QAG1B,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,aAAa;IAC5C,YAAY,OAAe,EAAE,UAAmB;QAC9C,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,QAAS,SAAQ,aAAa;IAoChC;IAEA;IACA;IAEA;IAxCT,2EAA2E;IAC3E,YAAY,CAAU;IAEtB;;;;;;OAMG;IACH,6EAA6E;IAC7E,8EAA8E;IAC9E,eAAe,CAKa;IAC5B,sCAAsC;IACtC,YAAY,CAAwC;IACpD;;;;;OAKG;IACH,SAAS,CAAU;IAEnB;;;;OAIG;IACH,YACE,OAAe,EACR,UAAmB,EAC1B,UAAmB,EACZ,UAAmB,EACnB,SAAmB;IAC1B,0EAA0E;IACnE,UAAmB;QAE1B,KAAK,CAAC,OAAO,EAAE,UAAU,IAAI,WAAW,EAAE,UAAU,CAAC,CAAC;QAP/C,eAAU,GAAV,UAAU,CAAS;QAEnB,eAAU,GAAV,UAAU,CAAS;QACnB,cAAS,GAAT,SAAS,CAAU;QAEnB,eAAU,GAAV,UAAU,CAAS;QAG1B,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED;;;;GAIG;AACH,MAAM,OAAO,WAAY,SAAQ,QAAQ;IACvC,YACE,OAAe,EACf,IAAkE,EAClE,UAAmB,EACnB,UAAmB;QAEnB,yEAAyE;QACzE,yDAAyD;QACzD,KAAK,CAAC,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;QAC7C,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,aAAa;IAC7C,YAAY,OAAe,EAAE,UAAmB;QAC9C,KAAK,CAAC,OAAO,EAAE,eAAe,EAAE,UAAU,CAAC,CAAC;QAC5C,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,WAAY,SAAQ,aAAa;IAC5C,YAAY,OAAe,EAAE,UAAmB;QAC9C,KAAK,CAAC,OAAO,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC;QAC3C,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared local-bridge timing contract.
|
|
3
|
+
*
|
|
4
|
+
* This file is the checked-in source of truth for the reconnect/retry numbers
|
|
5
|
+
* that have to fit together across the native host and both CLI entrypoints.
|
|
6
|
+
*
|
|
7
|
+
* Contract:
|
|
8
|
+
* - Native host keeps the HTTP bridge alive for 90s after extension disconnect.
|
|
9
|
+
* - Typed CLI requests stay responsive with a 10s routine timeout and a 30s
|
|
10
|
+
* health probe timeout.
|
|
11
|
+
* - The typed adapter gets at most one immediate replay after a route change
|
|
12
|
+
* or successful live revalidation (2 attempts total).
|
|
13
|
+
* - The shell wrapper only does short patient retries for safe observational
|
|
14
|
+
* reads: 3 attempts total with 1s then 2s delays (3s total backoff budget).
|
|
15
|
+
*
|
|
16
|
+
* The retry budgets are intentionally much smaller than the native-host grace
|
|
17
|
+
* window so a flapping bridge fails fast instead of being hidden behind long,
|
|
18
|
+
* contradictory patient retry loops.
|
|
19
|
+
*/
|
|
20
|
+
export declare const LOCAL_BRIDGE_RECONNECT_GRACE_MS = 90000;
|
|
21
|
+
export declare const LOCAL_BRIDGE_HEALTH_PROBE_TIMEOUT_MS = 30000;
|
|
22
|
+
export declare const LOCAL_BRIDGE_REQUEST_TIMEOUT_MS = 10000;
|
|
23
|
+
export declare const LOCAL_BRIDGE_TYPED_TRANSPORT_RECOVERY_ATTEMPTS = 2;
|
|
24
|
+
export declare const LOCAL_BRIDGE_TYPED_EXTENSION_REVALIDATION_DELAYS_MS: readonly [250, 500, 1000];
|
|
25
|
+
export declare const LOCAL_BRIDGE_TYPED_RECENT_DISCONNECT_GRACE_MS = 5000;
|
|
26
|
+
export declare const LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_MAX_ATTEMPTS = 3;
|
|
27
|
+
export declare const LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_INITIAL_DELAY_MS = 1000;
|
|
28
|
+
export declare const LOCAL_BRIDGE_SHELL_SAFE_READ_RETRY_BACKOFF_MULTIPLIER = 2;
|
|
29
|
+
export declare function getLocalBridgeShellSafeReadRetryDelaysMs(): number[];
|
|
30
|
+
export declare function getLocalBridgeShellSafeReadRetryBudgetMs(): number;
|
|
31
|
+
//# sourceMappingURL=local-bridge-timing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-bridge-timing.d.ts","sourceRoot":"","sources":["../../src/local-bridge-timing.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAEtD,eAAO,MAAM,oCAAoC,QAAS,CAAC;AAC3D,eAAO,MAAM,+BAA+B,QAAS,CAAC;AAEtD,eAAO,MAAM,8CAA8C,IAAI,CAAC;AAChE,eAAO,MAAM,mDAAmD,2BAA6B,CAAC;AAC9F,eAAO,MAAM,6CAA6C,OAAQ,CAAC;AAEnE,eAAO,MAAM,+CAA+C,IAAI,CAAC;AACjE,eAAO,MAAM,mDAAmD,OAAQ,CAAC;AACzE,eAAO,MAAM,qDAAqD,IAAI,CAAC;AAEvE,wBAAgB,wCAAwC,IAAI,MAAM,EAAE,CAQnE;AAED,wBAAgB,wCAAwC,IAAI,MAAM,CAEjE"}
|