@kibitzsh/kibitz 0.0.3 → 0.0.4

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.
@@ -1,453 +1,441 @@
1
1
  "use strict";
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __export = (target, all) => {
9
- for (var name in all)
10
- __defProp(target, name, { get: all[name], enumerable: true });
11
- };
12
- var __copyProps = (to, from, except, desc) => {
13
- if (from && typeof from === "object" || typeof from === "function") {
14
- for (let key of __getOwnPropNames(from))
15
- if (!__hasOwnProp.call(to, key) && key !== except)
16
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
- }
18
- return to;
19
- };
20
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
- // If the importer is in node compatibility mode or this is not an ESM
22
- // file that has been converted to a CommonJS file using a Babel-
23
- // compatible transform (i.e. "__esModule" has not been set), then set
24
- // "default" to the CommonJS "module.exports" for node compatibility.
25
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
- mod
27
- ));
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
-
30
- // src/core/session-dispatch.ts
31
- var session_dispatch_exports = {};
32
- __export(session_dispatch_exports, {
33
- SessionDispatchService: () => SessionDispatchService,
34
- buildExistingDispatchCommand: () => buildExistingDispatchCommand,
35
- buildInteractiveDispatchCommand: () => buildInteractiveDispatchCommand,
36
- resolveDispatchCommand: () => resolveDispatchCommand
37
- });
38
- module.exports = __toCommonJS(session_dispatch_exports);
39
- var import_events = require("events");
40
- var import_child_process2 = require("child_process");
41
- var fs2 = __toESM(require("fs"));
42
- var path2 = __toESM(require("path"));
43
-
44
- // src/core/platform-support.ts
45
- var import_child_process = require("child_process");
46
- var fs = __toESM(require("fs"));
47
- var path = __toESM(require("path"));
48
- function getProviderCliCommand(provider, platform = process.platform) {
49
- return platform === "win32" ? `${provider}.cmd` : provider;
50
- }
51
- function resolveCmdNodeScript(cmdPath) {
52
- if (!String(cmdPath || "").toLowerCase().endsWith(".cmd")) return null;
53
- try {
54
- const content = fs.readFileSync(cmdPath, "utf8");
55
- const match = content.match(/%dp0%\\(.+?\.js)/i);
56
- if (!match) return null;
57
- const scriptPath = path.join(path.dirname(cmdPath), match[1]);
58
- return fs.existsSync(scriptPath) ? scriptPath : null;
59
- } catch {
60
- return null;
61
- }
62
- }
63
- function findCommandPath(command, platform = process.platform) {
64
- try {
65
- if (platform === "win32") {
66
- const out2 = (0, import_child_process.execSync)(`where ${command}`, {
67
- encoding: "utf8",
68
- timeout: 5e3,
69
- stdio: ["ignore", "pipe", "ignore"]
70
- }).trim();
71
- const first = out2.split(/\r?\n/).map((line) => line.trim()).find(Boolean);
72
- return first || void 0;
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
73
7
  }
74
- const out = (0, import_child_process.execFileSync)("which", [command], {
75
- encoding: "utf8",
76
- timeout: 5e3,
77
- stdio: ["ignore", "pipe", "ignore"]
78
- }).trim();
79
- return out || void 0;
80
- } catch {
81
- return void 0;
82
- }
83
- }
84
-
85
- // src/core/session-dispatch.ts
86
- var SessionDispatchService = class extends import_events.EventEmitter {
87
- constructor(options) {
88
- super();
89
- this.options = options;
90
- }
91
- async dispatch(request) {
92
- const prompt = String(request.prompt || "").trim();
93
- if (!prompt) {
94
- this.emitStatus("failed", request.target, "Prompt cannot be empty");
95
- return;
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SessionDispatchService = void 0;
37
+ exports.buildExistingDispatchCommand = buildExistingDispatchCommand;
38
+ exports.buildInteractiveDispatchCommand = buildInteractiveDispatchCommand;
39
+ exports.resolveDispatchCommand = resolveDispatchCommand;
40
+ const events_1 = require("events");
41
+ const child_process_1 = require("child_process");
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ const platform_support_1 = require("./platform-support");
45
+ class SessionDispatchService extends events_1.EventEmitter {
46
+ options;
47
+ constructor(options) {
48
+ super();
49
+ this.options = options;
96
50
  }
97
- this.emitStatus("queued", request.target, `Queued for ${describeTarget(request.target)}`);
98
- if (request.target.kind === "existing") {
99
- await this.dispatchExistingSession(request.target, prompt);
100
- return;
51
+ async dispatch(request) {
52
+ const prompt = String(request.prompt || '').trim();
53
+ if (!prompt) {
54
+ this.emitStatus('failed', request.target, 'Prompt cannot be empty');
55
+ return;
56
+ }
57
+ this.emitStatus('queued', request.target, `Queued for ${describeTarget(request.target)}`);
58
+ if (request.target.kind === 'existing') {
59
+ await this.dispatchExistingSession(request.target, prompt);
60
+ return;
61
+ }
62
+ const provider = request.target.kind === 'new-codex' ? 'codex' : 'claude';
63
+ this.emitStatus('started', request.target, `Starting new ${provider} session`);
64
+ try {
65
+ if (request.origin === 'vscode') {
66
+ if (!this.options.launchInteractiveSession) {
67
+ throw new Error('Interactive launcher is not available in VS Code mode');
68
+ }
69
+ await this.options.launchInteractiveSession(provider, prompt);
70
+ }
71
+ else {
72
+ await runInteractiveInTerminal(provider, prompt);
73
+ }
74
+ this.emitStatus('sent', request.target, `Started new ${provider} session`);
75
+ }
76
+ catch (error) {
77
+ this.emitStatus('failed', request.target, normalizeError(error));
78
+ }
101
79
  }
102
- const provider = request.target.kind === "new-codex" ? "codex" : "claude";
103
- this.emitStatus("started", request.target, `Starting new ${provider} session`);
104
- try {
105
- if (request.origin === "vscode") {
106
- if (!this.options.launchInteractiveSession) {
107
- throw new Error("Interactive launcher is not available in VS Code mode");
80
+ async dispatchExistingSession(target, prompt) {
81
+ const targetSessionId = String(target.sessionId || '').trim().toLowerCase();
82
+ const targetAgent = target.agent;
83
+ if (!targetSessionId || (targetAgent !== 'claude' && targetAgent !== 'codex')) {
84
+ this.emitStatus('failed', target, 'Missing target session or provider');
85
+ return;
86
+ }
87
+ const active = this.options.getActiveSessions();
88
+ const activeMatch = active.find((session) => {
89
+ return session.agent === targetAgent && session.id.toLowerCase() === targetSessionId;
90
+ });
91
+ if (!activeMatch) {
92
+ this.emitStatus('failed', target, `Selected ${describeProvider(targetAgent)} session is not active`);
93
+ return;
94
+ }
95
+ const targetLabel = describeTarget(target);
96
+ this.emitStatus('started', target, `Dispatching to ${targetLabel}`);
97
+ try {
98
+ const command = buildExistingDispatchCommand(target, prompt);
99
+ const dispatchCwd = deriveDispatchCwdForSession(activeMatch);
100
+ const beforeDispatch = captureSessionFileSnapshot(activeMatch.filePath);
101
+ const handle = await startBackgroundCommand(command, { cwd: dispatchCwd });
102
+ const dispatchOutcome = await runWithTimeout(waitForDispatchAcknowledgement(activeMatch.filePath, prompt, beforeDispatch, handle.completion), 20_000, 'Dispatch timed out waiting for target session update');
103
+ // If process exited before prompt was observed, enforce full verification.
104
+ if (dispatchOutcome === 'process-complete') {
105
+ verifyExistingDispatchDelivery(activeMatch.filePath, prompt, beforeDispatch);
106
+ }
107
+ // Keep completion promise observed to avoid unhandled rejections after early ack.
108
+ void handle.completion.catch(() => undefined);
109
+ this.emitStatus('sent', target, `Prompt sent to ${targetLabel}`);
110
+ }
111
+ catch (error) {
112
+ this.emitStatus('failed', target, normalizeError(error));
108
113
  }
109
- await this.options.launchInteractiveSession(provider, prompt);
110
- } else {
111
- await runInteractiveInTerminal(provider, prompt);
112
- }
113
- this.emitStatus("sent", request.target, `Started new ${provider} session`);
114
- } catch (error) {
115
- this.emitStatus("failed", request.target, normalizeError(error));
116
114
  }
117
- }
118
- async dispatchExistingSession(target, prompt) {
119
- const targetSessionId = String(target.sessionId || "").trim().toLowerCase();
120
- const targetAgent = target.agent;
121
- if (!targetSessionId || targetAgent !== "claude" && targetAgent !== "codex") {
122
- this.emitStatus("failed", target, "Missing target session or provider");
123
- return;
115
+ emitStatus(state, target, message) {
116
+ const status = {
117
+ state,
118
+ message,
119
+ target,
120
+ timestamp: Date.now(),
121
+ };
122
+ this.emit('status', status);
124
123
  }
125
- const active = this.options.getActiveSessions();
126
- const activeMatch = active.find((session) => {
127
- return session.agent === targetAgent && session.id.toLowerCase() === targetSessionId;
128
- });
129
- if (!activeMatch) {
130
- this.emitStatus("failed", target, `Selected ${describeProvider(targetAgent)} session is not active`);
131
- return;
124
+ }
125
+ exports.SessionDispatchService = SessionDispatchService;
126
+ function buildExistingDispatchCommand(target, prompt, platform = process.platform) {
127
+ if (target.kind !== 'existing') {
128
+ throw new Error(`Expected existing target, got "${target.kind}"`);
132
129
  }
133
- const targetLabel = describeTarget(target);
134
- this.emitStatus("started", target, `Dispatching to ${targetLabel}`);
135
- try {
136
- const command = buildExistingDispatchCommand(target, prompt);
137
- const dispatchCwd = deriveDispatchCwdForSession(activeMatch);
138
- const beforeDispatch = captureSessionFileSnapshot(activeMatch.filePath);
139
- const handle = await startBackgroundCommand(command, { cwd: dispatchCwd });
140
- const dispatchOutcome = await runWithTimeout(
141
- waitForDispatchAcknowledgement(
142
- activeMatch.filePath,
143
- prompt,
144
- beforeDispatch,
145
- handle.completion
146
- ),
147
- 2e4,
148
- "Dispatch timed out waiting for target session update"
149
- );
150
- if (dispatchOutcome === "process-complete") {
151
- verifyExistingDispatchDelivery(activeMatch.filePath, prompt, beforeDispatch);
152
- }
153
- void handle.completion.catch(() => void 0);
154
- this.emitStatus("sent", target, `Prompt sent to ${targetLabel}`);
155
- } catch (error) {
156
- this.emitStatus("failed", target, normalizeError(error));
130
+ const sessionId = String(target.sessionId || '').trim();
131
+ const agent = target.agent;
132
+ if (!sessionId || (agent !== 'claude' && agent !== 'codex')) {
133
+ throw new Error('Missing existing-session target details');
134
+ }
135
+ if (agent === 'codex') {
136
+ return {
137
+ provider: 'codex',
138
+ command: (0, platform_support_1.getProviderCliCommand)('codex', platform),
139
+ args: ['exec', 'resume', '--json', '--skip-git-repo-check', sessionId, prompt],
140
+ };
157
141
  }
158
- }
159
- emitStatus(state, target, message) {
160
- const status = {
161
- state,
162
- message,
163
- target,
164
- timestamp: Date.now()
165
- };
166
- this.emit("status", status);
167
- }
168
- };
169
- function buildExistingDispatchCommand(target, prompt, platform = process.platform) {
170
- if (target.kind !== "existing") {
171
- throw new Error(`Expected existing target, got "${target.kind}"`);
172
- }
173
- const sessionId = String(target.sessionId || "").trim();
174
- const agent = target.agent;
175
- if (!sessionId || agent !== "claude" && agent !== "codex") {
176
- throw new Error("Missing existing-session target details");
177
- }
178
- if (agent === "codex") {
179
142
  return {
180
- provider: "codex",
181
- command: getProviderCliCommand("codex", platform),
182
- args: ["exec", "resume", "--json", "--skip-git-repo-check", sessionId, prompt]
143
+ provider: 'claude',
144
+ command: (0, platform_support_1.getProviderCliCommand)('claude', platform),
145
+ args: ['-p', prompt, '--verbose', '--output-format', 'stream-json', '--resume', sessionId],
183
146
  };
184
- }
185
- return {
186
- provider: "claude",
187
- command: getProviderCliCommand("claude", platform),
188
- args: ["-p", prompt, "--verbose", "--output-format", "stream-json", "--resume", sessionId]
189
- };
190
147
  }
191
148
  function buildInteractiveDispatchCommand(provider, prompt, platform = process.platform) {
192
- return {
193
- provider,
194
- command: getProviderCliCommand(provider, platform),
195
- args: [prompt]
196
- };
149
+ return {
150
+ provider,
151
+ command: (0, platform_support_1.getProviderCliCommand)(provider, platform),
152
+ args: [prompt],
153
+ };
197
154
  }
198
155
  function resolveDispatchCommand(command, platform = process.platform) {
199
- const pathHint = findCommandPath(command.command, platform);
200
- if (!pathHint) {
201
- throw new Error(`CLI not found: ${command.command}`);
202
- }
203
- if (platform === "win32") {
204
- const nodeScript = resolveCmdNodeScript(pathHint);
205
- if (nodeScript) {
206
- return {
207
- command: process.execPath,
208
- args: [nodeScript, ...command.args],
209
- shell: false
210
- };
156
+ const pathHint = (0, platform_support_1.findCommandPath)(command.command, platform);
157
+ if (!pathHint) {
158
+ throw new Error(`CLI not found: ${command.command}`);
159
+ }
160
+ if (platform === 'win32') {
161
+ const nodeScript = (0, platform_support_1.resolveCmdNodeScript)(pathHint);
162
+ if (nodeScript) {
163
+ return {
164
+ command: process.execPath,
165
+ args: [nodeScript, ...command.args],
166
+ shell: false,
167
+ };
168
+ }
169
+ if (pathHint.toLowerCase().endsWith('.cmd')) {
170
+ return {
171
+ command: pathHint,
172
+ args: command.args,
173
+ shell: true,
174
+ };
175
+ }
211
176
  }
212
- if (pathHint.toLowerCase().endsWith(".cmd")) {
213
- return {
177
+ return {
214
178
  command: pathHint,
215
179
  args: command.args,
216
- shell: true
217
- };
218
- }
219
- }
220
- return {
221
- command: pathHint,
222
- args: command.args,
223
- shell: false
224
- };
180
+ shell: false,
181
+ };
225
182
  }
226
183
  async function waitForDispatchAcknowledgement(filePath, prompt, before, completion) {
227
- let completionState = 0;
228
- let completionError = null;
229
- completion.then(() => {
230
- completionState = 1;
231
- }).catch((error) => {
232
- completionState = 2;
233
- completionError = error instanceof Error ? error : new Error(String(error || "Dispatch failed"));
234
- });
235
- while (true) {
236
- if (completionState === 2) {
237
- throw completionError || new Error("Dispatch failed");
238
- }
239
- if (hasSessionUpdateWithPrompt(filePath, prompt, before)) {
240
- return "prompt-observed";
241
- }
242
- if (completionState === 1) {
243
- return "process-complete";
244
- }
245
- await sleepMs(120);
246
- }
247
- }
248
- async function startBackgroundCommand(command, options = {}) {
249
- const resolved = resolveDispatchCommand(command);
250
- return await new Promise((resolve, reject) => {
251
- const child = (0, import_child_process2.spawn)(resolved.command, resolved.args, {
252
- stdio: ["ignore", "ignore", "pipe"],
253
- shell: resolved.shell,
254
- windowsHide: true,
255
- ...options.cwd ? { cwd: options.cwd } : {}
184
+ let completionState = 0; // 0: running, 1: success, 2: failed
185
+ let completionError = null;
186
+ completion.then(() => {
187
+ completionState = 1;
188
+ }).catch((error) => {
189
+ completionState = 2;
190
+ completionError = error instanceof Error ? error : new Error(String(error || 'Dispatch failed'));
256
191
  });
257
- let stderr = "";
258
- let spawned = false;
259
- let launchSettled = false;
260
- const failLaunch = (error) => {
261
- if (launchSettled) return;
262
- launchSettled = true;
263
- reject(error);
264
- };
265
- const completion = new Promise((resolveCompletion, rejectCompletion) => {
266
- child.on("error", (error) => {
267
- if (!spawned) {
268
- failLaunch(error);
269
- return;
192
+ while (true) {
193
+ if (completionState === 2) {
194
+ throw completionError || new Error('Dispatch failed');
270
195
  }
271
- rejectCompletion(error);
272
- });
273
- child.on("close", (code) => {
274
- if (code === 0) {
275
- resolveCompletion();
276
- return;
196
+ if (hasSessionUpdateWithPrompt(filePath, prompt, before)) {
197
+ return 'prompt-observed';
277
198
  }
278
- const normalized = String(stderr || "").trim();
279
- if (looksLikeUnsupportedFlags(normalized)) {
280
- rejectCompletion(new Error("Provider CLI does not support required resume flags. Update the CLI version."));
281
- return;
199
+ if (completionState === 1) {
200
+ return 'process-complete';
282
201
  }
283
- rejectCompletion(new Error(normalized || `Dispatch exited with code ${code}`));
284
- });
285
- });
286
- child.stderr?.on("data", (data) => {
287
- stderr += data.toString();
288
- });
289
- child.on("spawn", () => {
290
- spawned = true;
291
- if (launchSettled) return;
292
- launchSettled = true;
293
- resolve({ completion });
202
+ await sleepMs(120);
203
+ }
204
+ }
205
+ async function startBackgroundCommand(command, options = {}) {
206
+ const resolved = resolveDispatchCommand(command);
207
+ return await new Promise((resolve, reject) => {
208
+ const child = (0, child_process_1.spawn)(resolved.command, resolved.args, {
209
+ stdio: ['ignore', 'ignore', 'pipe'],
210
+ shell: resolved.shell,
211
+ windowsHide: true,
212
+ ...(options.cwd ? { cwd: options.cwd } : {}),
213
+ });
214
+ let stderr = '';
215
+ let spawned = false;
216
+ let launchSettled = false;
217
+ const failLaunch = (error) => {
218
+ if (launchSettled)
219
+ return;
220
+ launchSettled = true;
221
+ reject(error);
222
+ };
223
+ const completion = new Promise((resolveCompletion, rejectCompletion) => {
224
+ child.on('error', (error) => {
225
+ if (!spawned) {
226
+ failLaunch(error);
227
+ return;
228
+ }
229
+ rejectCompletion(error);
230
+ });
231
+ child.on('close', (code) => {
232
+ if (code === 0) {
233
+ resolveCompletion();
234
+ return;
235
+ }
236
+ const normalized = String(stderr || '').trim();
237
+ if (looksLikeUnsupportedFlags(normalized)) {
238
+ rejectCompletion(new Error('Provider CLI does not support required resume flags. Update the CLI version.'));
239
+ return;
240
+ }
241
+ rejectCompletion(new Error(normalized || `Dispatch exited with code ${code}`));
242
+ });
243
+ });
244
+ child.stderr?.on('data', (data) => {
245
+ stderr += data.toString();
246
+ });
247
+ child.on('spawn', () => {
248
+ spawned = true;
249
+ if (launchSettled)
250
+ return;
251
+ launchSettled = true;
252
+ resolve({ completion });
253
+ });
294
254
  });
295
- });
296
255
  }
297
256
  async function runInteractiveInTerminal(provider, prompt) {
298
- const command = buildInteractiveDispatchCommand(provider, prompt);
299
- const resolved = resolveDispatchCommand(command);
300
- await new Promise((resolve, reject) => {
301
- const child = (0, import_child_process2.spawn)(resolved.command, resolved.args, {
302
- stdio: "inherit",
303
- shell: resolved.shell,
304
- windowsHide: false
257
+ const command = buildInteractiveDispatchCommand(provider, prompt);
258
+ const resolved = resolveDispatchCommand(command);
259
+ await new Promise((resolve, reject) => {
260
+ const child = (0, child_process_1.spawn)(resolved.command, resolved.args, {
261
+ stdio: 'inherit',
262
+ shell: resolved.shell,
263
+ windowsHide: false,
264
+ });
265
+ child.on('error', (error) => reject(error));
266
+ child.on('close', (code) => {
267
+ if (code === 0)
268
+ resolve();
269
+ else
270
+ reject(new Error(`Interactive session exited with code ${code}`));
271
+ });
305
272
  });
306
- child.on("error", (error) => reject(error));
307
- child.on("close", (code) => {
308
- if (code === 0) resolve();
309
- else reject(new Error(`Interactive session exited with code ${code}`));
310
- });
311
- });
312
273
  }
313
274
  function describeTarget(target) {
314
- if (target.kind === "new-codex") return "new codex session";
315
- if (target.kind === "new-claude") return "new claude session";
316
- const provider = describeProvider(target.agent);
317
- const project = cleanTargetLabel(target.projectName, 24);
318
- const sessionTitle = cleanTargetLabel(target.sessionTitle, 44);
319
- if (project && sessionTitle) return `${provider} session (${project} \u203A ${sessionTitle})`;
320
- if (sessionTitle) return `${provider} session (${sessionTitle})`;
321
- if (project) return `${provider} session (${project})`;
322
- return `${provider} session`;
275
+ if (target.kind === 'new-codex')
276
+ return 'new codex session';
277
+ if (target.kind === 'new-claude')
278
+ return 'new claude session';
279
+ const provider = describeProvider(target.agent);
280
+ const project = cleanTargetLabel(target.projectName, 24);
281
+ const sessionTitle = cleanTargetLabel(target.sessionTitle, 44);
282
+ if (project && sessionTitle)
283
+ return `${provider} session (${project} › ${sessionTitle})`;
284
+ if (sessionTitle)
285
+ return `${provider} session (${sessionTitle})`;
286
+ if (project)
287
+ return `${provider} session (${project})`;
288
+ return `${provider} session`;
323
289
  }
324
290
  function describeProvider(agent) {
325
- return String(agent || "").toLowerCase() === "claude" ? "Claude" : "Codex";
291
+ return String(agent || '').toLowerCase() === 'claude' ? 'Claude' : 'Codex';
326
292
  }
327
293
  function cleanTargetLabel(value, max) {
328
- const text = String(value || "").replace(/\s+/g, " ").trim();
329
- if (!text) return "";
330
- if (/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(text)) return "";
331
- if (text.length <= max) return text;
332
- if (max <= 3) return text.slice(0, max);
333
- return `${text.slice(0, max - 3).trimEnd()}...`;
294
+ const text = String(value || '').replace(/\s+/g, ' ').trim();
295
+ if (!text)
296
+ return '';
297
+ if (/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(text))
298
+ return '';
299
+ if (text.length <= max)
300
+ return text;
301
+ if (max <= 3)
302
+ return text.slice(0, max);
303
+ return `${text.slice(0, max - 3).trimEnd()}...`;
334
304
  }
335
305
  function looksLikeUnsupportedFlags(stderr) {
336
- const normalized = String(stderr || "").toLowerCase();
337
- if (!normalized) return false;
338
- return normalized.includes("unknown option") || normalized.includes("unknown flag") || normalized.includes("unrecognized option") || normalized.includes("did you mean");
306
+ const normalized = String(stderr || '').toLowerCase();
307
+ if (!normalized)
308
+ return false;
309
+ return normalized.includes('unknown option')
310
+ || normalized.includes('unknown flag')
311
+ || normalized.includes('unrecognized option')
312
+ || normalized.includes('did you mean');
339
313
  }
340
314
  function normalizeError(error) {
341
- if (error instanceof Error && error.message) return error.message;
342
- return String(error || "Dispatch failed");
315
+ if (error instanceof Error && error.message)
316
+ return error.message;
317
+ return String(error || 'Dispatch failed');
343
318
  }
344
319
  function captureSessionFileSnapshot(filePath) {
345
- try {
346
- const stat = fs2.statSync(filePath);
347
- return {
348
- exists: true,
349
- size: stat.size,
350
- mtimeMs: stat.mtimeMs
351
- };
352
- } catch {
353
- return {
354
- exists: false,
355
- size: 0,
356
- mtimeMs: 0
357
- };
358
- }
320
+ try {
321
+ const stat = fs.statSync(filePath);
322
+ return {
323
+ exists: true,
324
+ size: stat.size,
325
+ mtimeMs: stat.mtimeMs,
326
+ };
327
+ }
328
+ catch {
329
+ return {
330
+ exists: false,
331
+ size: 0,
332
+ mtimeMs: 0,
333
+ };
334
+ }
359
335
  }
360
336
  function verifyExistingDispatchDelivery(filePath, prompt, before) {
361
- if (!hasSessionFileChanged(filePath, before)) {
362
- throw new Error("Target session did not update after dispatch");
363
- }
364
- const promptSignature = firstPromptSignature(prompt);
365
- if (promptSignature.length < 4) return;
366
- const tail = readSessionTailSinceOffset(filePath, before.size);
367
- if (!tail) {
368
- throw new Error("Target session updated but prompt text was not found");
369
- }
370
- if (!tail.toLowerCase().includes(promptSignature.toLowerCase())) {
371
- throw new Error("Prompt text was not found in target session update");
372
- }
337
+ if (!hasSessionFileChanged(filePath, before)) {
338
+ throw new Error('Target session did not update after dispatch');
339
+ }
340
+ const promptSignature = firstPromptSignature(prompt);
341
+ if (promptSignature.length < 4)
342
+ return;
343
+ const tail = readSessionTailSinceOffset(filePath, before.size);
344
+ if (!tail) {
345
+ throw new Error('Target session updated but prompt text was not found');
346
+ }
347
+ if (!tail.toLowerCase().includes(promptSignature.toLowerCase())) {
348
+ throw new Error('Prompt text was not found in target session update');
349
+ }
373
350
  }
374
351
  function hasSessionUpdateWithPrompt(filePath, prompt, before) {
375
- if (!hasSessionFileChanged(filePath, before)) return false;
376
- const promptSignature = firstPromptSignature(prompt);
377
- if (promptSignature.length < 4) return true;
378
- const tail = readSessionTailSinceOffset(filePath, before.size);
379
- if (!tail) return false;
380
- return tail.toLowerCase().includes(promptSignature.toLowerCase());
352
+ if (!hasSessionFileChanged(filePath, before))
353
+ return false;
354
+ const promptSignature = firstPromptSignature(prompt);
355
+ if (promptSignature.length < 4)
356
+ return true;
357
+ const tail = readSessionTailSinceOffset(filePath, before.size);
358
+ if (!tail)
359
+ return false;
360
+ return tail.toLowerCase().includes(promptSignature.toLowerCase());
381
361
  }
382
362
  function hasSessionFileChanged(filePath, before) {
383
- const after = captureSessionFileSnapshot(filePath);
384
- if (!after.exists) {
385
- throw new Error("Target session file is not accessible after dispatch");
386
- }
387
- return after.size > before.size || after.mtimeMs > before.mtimeMs;
363
+ const after = captureSessionFileSnapshot(filePath);
364
+ if (!after.exists) {
365
+ throw new Error('Target session file is not accessible after dispatch');
366
+ }
367
+ return after.size > before.size || after.mtimeMs > before.mtimeMs;
388
368
  }
389
369
  function firstPromptSignature(prompt) {
390
- const lines = String(prompt || "").split(/\r?\n/g).map((line) => line.trim()).filter(Boolean);
391
- const first = lines[0] || String(prompt || "").trim();
392
- return first.slice(0, 160);
370
+ const lines = String(prompt || '')
371
+ .split(/\r?\n/g)
372
+ .map((line) => line.trim())
373
+ .filter(Boolean);
374
+ const first = lines[0] || String(prompt || '').trim();
375
+ return first.slice(0, 160);
393
376
  }
394
377
  function readSessionTailSinceOffset(filePath, previousSize) {
395
- try {
396
- const stat = fs2.statSync(filePath);
397
- const maxBytes = 1024 * 512;
398
- const start = Math.max(0, previousSize - 2048);
399
- const desiredStart = stat.size - start > maxBytes ? Math.max(0, stat.size - maxBytes) : start;
400
- const length = Math.max(0, stat.size - desiredStart);
401
- if (length === 0) return "";
402
- const fd = fs2.openSync(filePath, "r");
403
378
  try {
404
- const buf = Buffer.alloc(length);
405
- fs2.readSync(fd, buf, 0, length, desiredStart);
406
- return buf.toString("utf8");
407
- } finally {
408
- fs2.closeSync(fd);
379
+ const stat = fs.statSync(filePath);
380
+ const maxBytes = 1024 * 512;
381
+ const start = Math.max(0, previousSize - 2048);
382
+ const desiredStart = stat.size - start > maxBytes
383
+ ? Math.max(0, stat.size - maxBytes)
384
+ : start;
385
+ const length = Math.max(0, stat.size - desiredStart);
386
+ if (length === 0)
387
+ return '';
388
+ const fd = fs.openSync(filePath, 'r');
389
+ try {
390
+ const buf = Buffer.alloc(length);
391
+ fs.readSync(fd, buf, 0, length, desiredStart);
392
+ return buf.toString('utf8');
393
+ }
394
+ finally {
395
+ fs.closeSync(fd);
396
+ }
397
+ }
398
+ catch {
399
+ return '';
409
400
  }
410
- } catch {
411
- return "";
412
- }
413
401
  }
414
402
  async function runWithTimeout(promise, timeoutMs, message) {
415
- return await new Promise((resolve, reject) => {
416
- const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
417
- promise.then((value) => {
418
- clearTimeout(timer);
419
- resolve(value);
420
- }).catch((error) => {
421
- clearTimeout(timer);
422
- reject(error);
403
+ return await new Promise((resolve, reject) => {
404
+ const timer = setTimeout(() => reject(new Error(message)), timeoutMs);
405
+ promise.then((value) => {
406
+ clearTimeout(timer);
407
+ resolve(value);
408
+ }).catch((error) => {
409
+ clearTimeout(timer);
410
+ reject(error);
411
+ });
423
412
  });
424
- });
425
413
  }
426
414
  async function sleepMs(ms) {
427
- await new Promise((resolve) => setTimeout(resolve, ms));
415
+ await new Promise((resolve) => setTimeout(resolve, ms));
428
416
  }
429
417
  function deriveDispatchCwdForSession(session) {
430
- if (session.agent !== "claude") return void 0;
431
- return decodeClaudeProjectPathFromSessionFile(session.filePath);
418
+ if (session.agent !== 'claude')
419
+ return undefined;
420
+ return decodeClaudeProjectPathFromSessionFile(session.filePath);
432
421
  }
433
422
  function decodeClaudeProjectPathFromSessionFile(filePath) {
434
- if (!filePath) return void 0;
435
- const projectDir = path2.basename(path2.dirname(filePath));
436
- if (!projectDir) return void 0;
437
- const parts = projectDir.split("-").filter(Boolean);
438
- if (parts.length === 0) return void 0;
439
- if (parts.length >= 2 && /^[A-Za-z]$/.test(parts[0])) {
440
- const windowsPath = `${parts[0]}:\\${parts.slice(1).join("\\")}`;
441
- if (fs2.existsSync(windowsPath)) return windowsPath;
442
- }
443
- const unixPath = `/${parts.join("/")}`;
444
- if (fs2.existsSync(unixPath)) return unixPath;
445
- return void 0;
423
+ if (!filePath)
424
+ return undefined;
425
+ const projectDir = path.basename(path.dirname(filePath));
426
+ if (!projectDir)
427
+ return undefined;
428
+ const parts = projectDir.split('-').filter(Boolean);
429
+ if (parts.length === 0)
430
+ return undefined;
431
+ if (parts.length >= 2 && /^[A-Za-z]$/.test(parts[0])) {
432
+ const windowsPath = `${parts[0]}:\\${parts.slice(1).join('\\')}`;
433
+ if (fs.existsSync(windowsPath))
434
+ return windowsPath;
435
+ }
436
+ const unixPath = `/${parts.join('/')}`;
437
+ if (fs.existsSync(unixPath))
438
+ return unixPath;
439
+ return undefined;
446
440
  }
447
- // Annotate the CommonJS export names for ESM import in node:
448
- 0 && (module.exports = {
449
- SessionDispatchService,
450
- buildExistingDispatchCommand,
451
- buildInteractiveDispatchCommand,
452
- resolveDispatchCommand
453
- });
441
+ //# sourceMappingURL=session-dispatch.js.map