agent-relay 2.1.3 → 2.1.5
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/bin/relay-pty-darwin-arm64 +0 -0
- package/bin/relay-pty-darwin-x64 +0 -0
- package/bin/relay-pty-linux-arm64 +0 -0
- package/bin/relay-pty-linux-x64 +0 -0
- package/dist/index.cjs +420 -184
- package/package.json +19 -19
- package/packages/api-types/package.json +1 -1
- package/packages/benchmark/package.json +4 -4
- package/packages/bridge/dist/cli-resolution.d.ts +32 -0
- package/packages/bridge/dist/cli-resolution.d.ts.map +1 -0
- package/packages/bridge/dist/cli-resolution.js +88 -0
- package/packages/bridge/dist/cli-resolution.js.map +1 -0
- package/packages/bridge/dist/index.d.ts +1 -0
- package/packages/bridge/dist/index.d.ts.map +1 -1
- package/packages/bridge/dist/index.js +2 -0
- package/packages/bridge/dist/index.js.map +1 -1
- package/packages/bridge/dist/spawner.d.ts.map +1 -1
- package/packages/bridge/dist/spawner.js +43 -17
- package/packages/bridge/dist/spawner.js.map +1 -1
- package/packages/bridge/package.json +8 -8
- package/packages/bridge/src/cli-resolution.test.ts +225 -0
- package/packages/bridge/src/cli-resolution.ts +100 -0
- package/packages/bridge/src/index.ts +9 -0
- package/packages/bridge/src/spawner.ts +44 -18
- package/packages/cli-tester/package.json +1 -1
- package/packages/config/package.json +2 -2
- package/packages/continuity/package.json +2 -2
- package/packages/daemon/package.json +12 -12
- package/packages/hooks/package.json +4 -4
- package/packages/mcp/package.json +3 -3
- package/packages/memory/package.json +2 -2
- package/packages/policy/package.json +2 -2
- package/packages/protocol/package.json +1 -1
- package/packages/resiliency/package.json +1 -1
- package/packages/sdk/package.json +2 -2
- package/packages/spawner/package.json +1 -1
- package/packages/state/package.json +1 -1
- package/packages/storage/package.json +2 -2
- package/packages/telemetry/package.json +1 -1
- package/packages/trajectory/package.json +2 -2
- package/packages/user-directory/package.json +2 -2
- package/packages/utils/package.json +2 -2
- package/packages/wrapper/dist/opencode-wrapper.d.ts +6 -2
- package/packages/wrapper/dist/opencode-wrapper.d.ts.map +1 -1
- package/packages/wrapper/dist/opencode-wrapper.js +34 -10
- package/packages/wrapper/dist/opencode-wrapper.js.map +1 -1
- package/packages/wrapper/dist/relay-pty-orchestrator.d.ts +22 -2
- package/packages/wrapper/dist/relay-pty-orchestrator.d.ts.map +1 -1
- package/packages/wrapper/dist/relay-pty-orchestrator.js +174 -4
- package/packages/wrapper/dist/relay-pty-orchestrator.js.map +1 -1
- package/packages/wrapper/dist/shared.d.ts.map +1 -1
- package/packages/wrapper/dist/shared.js +5 -0
- package/packages/wrapper/dist/shared.js.map +1 -1
- package/packages/wrapper/package.json +6 -6
- package/packages/wrapper/src/opencode-wrapper.ts +37 -9
- package/packages/wrapper/src/relay-pty-orchestrator.ts +197 -4
- package/packages/wrapper/src/shared.ts +5 -0
- package/relay-snippets/agent-relay-snippet.md +17 -5
package/dist/index.cjs
CHANGED
|
@@ -3147,13 +3147,13 @@ var init_logger = __esm({
|
|
|
3147
3147
|
});
|
|
3148
3148
|
|
|
3149
3149
|
// packages/config/dist/bridge-utils.js
|
|
3150
|
-
var
|
|
3150
|
+
var import_node_child_process9, import_node_util3, execAsync2;
|
|
3151
3151
|
var init_bridge_utils = __esm({
|
|
3152
3152
|
"packages/config/dist/bridge-utils.js"() {
|
|
3153
3153
|
"use strict";
|
|
3154
|
-
|
|
3154
|
+
import_node_child_process9 = require("node:child_process");
|
|
3155
3155
|
import_node_util3 = require("node:util");
|
|
3156
|
-
execAsync2 = (0, import_node_util3.promisify)(
|
|
3156
|
+
execAsync2 = (0, import_node_util3.promisify)(import_node_child_process9.exec);
|
|
3157
3157
|
}
|
|
3158
3158
|
});
|
|
3159
3159
|
|
|
@@ -7441,11 +7441,11 @@ var require_core = __commonJS({
|
|
|
7441
7441
|
Ajv2.ValidationError = validation_error_1.default;
|
|
7442
7442
|
Ajv2.MissingRefError = ref_error_1.default;
|
|
7443
7443
|
exports2.default = Ajv2;
|
|
7444
|
-
function checkOptions(checkOpts, options, msg,
|
|
7444
|
+
function checkOptions(checkOpts, options, msg, log8 = "error") {
|
|
7445
7445
|
for (const key in checkOpts) {
|
|
7446
7446
|
const opt = key;
|
|
7447
7447
|
if (opt in options)
|
|
7448
|
-
this.logger[
|
|
7448
|
+
this.logger[log8](`${msg}: option ${key}. ${checkOpts[opt]}`);
|
|
7449
7449
|
}
|
|
7450
7450
|
}
|
|
7451
7451
|
function getSchEnv(keyRef) {
|
|
@@ -20852,7 +20852,7 @@ var require_node = __commonJS({
|
|
|
20852
20852
|
var tty = require("tty");
|
|
20853
20853
|
var util2 = require("util");
|
|
20854
20854
|
exports2.init = init;
|
|
20855
|
-
exports2.log =
|
|
20855
|
+
exports2.log = log8;
|
|
20856
20856
|
exports2.formatArgs = formatArgs;
|
|
20857
20857
|
exports2.save = save;
|
|
20858
20858
|
exports2.load = load;
|
|
@@ -20987,7 +20987,7 @@ var require_node = __commonJS({
|
|
|
20987
20987
|
}
|
|
20988
20988
|
return (/* @__PURE__ */ new Date()).toISOString() + " ";
|
|
20989
20989
|
}
|
|
20990
|
-
function
|
|
20990
|
+
function log8(...args) {
|
|
20991
20991
|
return process.stderr.write(util2.formatWithOptions(exports2.inspectOpts, ...args) + "\n");
|
|
20992
20992
|
}
|
|
20993
20993
|
function save(namespaces) {
|
|
@@ -31619,13 +31619,13 @@ var channel_membership_store_exports = {};
|
|
|
31619
31619
|
__export(channel_membership_store_exports, {
|
|
31620
31620
|
CloudChannelMembershipStore: () => CloudChannelMembershipStore
|
|
31621
31621
|
});
|
|
31622
|
-
var
|
|
31622
|
+
var log7, CloudChannelMembershipStore;
|
|
31623
31623
|
var init_channel_membership_store = __esm({
|
|
31624
31624
|
"packages/daemon/dist/channel-membership-store.js"() {
|
|
31625
31625
|
"use strict";
|
|
31626
31626
|
init_esm();
|
|
31627
31627
|
init_logger();
|
|
31628
|
-
|
|
31628
|
+
log7 = createLogger2("channel-membership-store");
|
|
31629
31629
|
CloudChannelMembershipStore = class {
|
|
31630
31630
|
workspaceId;
|
|
31631
31631
|
pool;
|
|
@@ -31655,7 +31655,7 @@ var init_channel_membership_store = __esm({
|
|
|
31655
31655
|
member: row.member_id
|
|
31656
31656
|
})).filter((row) => Boolean(row.channel && row.member));
|
|
31657
31657
|
} catch (err) {
|
|
31658
|
-
|
|
31658
|
+
log7.error("Failed to load channel memberships from cloud DB", {
|
|
31659
31659
|
error: err instanceof Error ? err.message : String(err)
|
|
31660
31660
|
});
|
|
31661
31661
|
return [];
|
|
@@ -31678,7 +31678,7 @@ var init_channel_membership_store = __esm({
|
|
|
31678
31678
|
member: row.member_id
|
|
31679
31679
|
})).filter((row) => Boolean(row.channel && row.member));
|
|
31680
31680
|
} catch (err) {
|
|
31681
|
-
|
|
31681
|
+
log7.error("Failed to load channel memberships for agent from cloud DB", {
|
|
31682
31682
|
memberName,
|
|
31683
31683
|
error: err instanceof Error ? err.message : String(err)
|
|
31684
31684
|
});
|
|
@@ -31704,7 +31704,7 @@ var init_channel_membership_store = __esm({
|
|
|
31704
31704
|
ON CONFLICT (channel_id, member_id) DO NOTHING
|
|
31705
31705
|
`, [channelRowId, member]);
|
|
31706
31706
|
} catch (err) {
|
|
31707
|
-
|
|
31707
|
+
log7.error("Failed to add channel member in cloud DB", {
|
|
31708
31708
|
channel: normalized,
|
|
31709
31709
|
member,
|
|
31710
31710
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -31726,7 +31726,7 @@ var init_channel_membership_store = __esm({
|
|
|
31726
31726
|
try {
|
|
31727
31727
|
await this.pool.query("DELETE FROM channel_members WHERE channel_id = $1 AND member_id = $2", [channelRowId, member]);
|
|
31728
31728
|
} catch (err) {
|
|
31729
|
-
|
|
31729
|
+
log7.error("Failed to remove channel member in cloud DB", {
|
|
31730
31730
|
channel: normalized,
|
|
31731
31731
|
member,
|
|
31732
31732
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -31766,7 +31766,7 @@ var init_channel_membership_store = __esm({
|
|
|
31766
31766
|
LIMIT 1
|
|
31767
31767
|
`, [this.workspaceId, channelId]);
|
|
31768
31768
|
if (!result.rows[0]?.id) {
|
|
31769
|
-
|
|
31769
|
+
log7.warn("Channel not found in cloud DB for membership update", {
|
|
31770
31770
|
workspaceId: this.workspaceId,
|
|
31771
31771
|
channelId
|
|
31772
31772
|
});
|
|
@@ -31774,7 +31774,7 @@ var init_channel_membership_store = __esm({
|
|
|
31774
31774
|
}
|
|
31775
31775
|
return result.rows[0].id;
|
|
31776
31776
|
} catch (err) {
|
|
31777
|
-
|
|
31777
|
+
log7.error("Failed to look up channel row in cloud DB", {
|
|
31778
31778
|
channelId,
|
|
31779
31779
|
error: err instanceof Error ? err.message : String(err)
|
|
31780
31780
|
});
|
|
@@ -37398,6 +37398,7 @@ function createInjectionMetrics() {
|
|
|
37398
37398
|
}
|
|
37399
37399
|
function detectCliType(command) {
|
|
37400
37400
|
const cmdLower = command.toLowerCase();
|
|
37401
|
+
const cmdName = cmdLower.split(/[\s/\\]/).pop() || cmdLower;
|
|
37401
37402
|
if (cmdLower.includes("gemini"))
|
|
37402
37403
|
return "gemini";
|
|
37403
37404
|
if (cmdLower.includes("codex"))
|
|
@@ -37410,6 +37411,8 @@ function detectCliType(command) {
|
|
|
37410
37411
|
return "opencode";
|
|
37411
37412
|
if (cmdLower.includes("cursor"))
|
|
37412
37413
|
return "cursor";
|
|
37414
|
+
if (cmdName === "agent" || cmdName === "cursor-agent")
|
|
37415
|
+
return "cursor";
|
|
37413
37416
|
return "other";
|
|
37414
37417
|
}
|
|
37415
37418
|
function getDefaultRelayPrefix() {
|
|
@@ -43430,9 +43433,9 @@ var AgentHealthMonitor = class extends import_events.EventEmitter {
|
|
|
43430
43433
|
* Get memory and CPU usage for a process
|
|
43431
43434
|
*/
|
|
43432
43435
|
async getProcessUsage(pid) {
|
|
43433
|
-
const { execSync:
|
|
43436
|
+
const { execSync: execSync10 } = await import("child_process");
|
|
43434
43437
|
try {
|
|
43435
|
-
const output =
|
|
43438
|
+
const output = execSync10(`ps -o rss=,pcpu= -p ${pid}`, { encoding: "utf8" }).trim();
|
|
43436
43439
|
const [rss, cpu] = output.split(/\s+/);
|
|
43437
43440
|
return {
|
|
43438
43441
|
memory: parseInt(rss, 10) * 1024,
|
|
@@ -46306,6 +46309,54 @@ var __filename2 = (0, import_node_url2.fileURLToPath)(import_meta_url);
|
|
|
46306
46309
|
var __dirname2 = (0, import_node_path11.dirname)(__filename2);
|
|
46307
46310
|
var MAX_SOCKET_PATH_LENGTH = 107;
|
|
46308
46311
|
var MAX_OUTPUT_BUFFER_SIZE = 10 * 1024 * 1024;
|
|
46312
|
+
var ACTIVITY_VERIFICATION = {
|
|
46313
|
+
/** Time to wait for activity patterns after injection (ms) */
|
|
46314
|
+
TIMEOUT_MS: 5e3,
|
|
46315
|
+
/** How often to check for activity patterns (ms) */
|
|
46316
|
+
POLL_INTERVAL_MS: 200,
|
|
46317
|
+
/** Maximum retries when no activity is detected */
|
|
46318
|
+
MAX_RETRIES: 3,
|
|
46319
|
+
/** Delay between retries (ms) */
|
|
46320
|
+
RETRY_DELAY_MS: 500,
|
|
46321
|
+
/**
|
|
46322
|
+
* Patterns indicating the task was received and displayed.
|
|
46323
|
+
* These are the primary verification patterns.
|
|
46324
|
+
*/
|
|
46325
|
+
TASK_RECEIVED_PATTERNS: [
|
|
46326
|
+
/\[Pasted text #\d+/,
|
|
46327
|
+
// Claude Code shows "[Pasted text #1 +95 lines]"
|
|
46328
|
+
/› Relay message from/,
|
|
46329
|
+
// Codex shows "› Relay message from"
|
|
46330
|
+
/Relay message from \w+ \[[\w-]+\]/
|
|
46331
|
+
// Droid/Gemini shows "Relay message from Agent [id]:"
|
|
46332
|
+
],
|
|
46333
|
+
/**
|
|
46334
|
+
* Patterns indicating the CLI is thinking/processing.
|
|
46335
|
+
* Secondary verification - proves the CLI is active.
|
|
46336
|
+
*/
|
|
46337
|
+
THINKING_PATTERNS: [
|
|
46338
|
+
/\(.*esc to (?:interrupt|stop)\)/i,
|
|
46339
|
+
// All CLIs: "(esc to interrupt)" or "(Press ESC to stop)"
|
|
46340
|
+
/[✻✶✳✢·✽⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏]/,
|
|
46341
|
+
// Spinner characters (Claude + Droid)
|
|
46342
|
+
/Thinking\.\.\./,
|
|
46343
|
+
// Droid: "Thinking..."
|
|
46344
|
+
/Working/,
|
|
46345
|
+
// Codex: "Working"
|
|
46346
|
+
/Forming|Noodling|Manifesting/i
|
|
46347
|
+
// Claude Code thinking states
|
|
46348
|
+
],
|
|
46349
|
+
/**
|
|
46350
|
+
* Patterns indicating tool execution started.
|
|
46351
|
+
* Tertiary verification - proves the CLI is working.
|
|
46352
|
+
*/
|
|
46353
|
+
TOOL_EXECUTION_PATTERNS: [
|
|
46354
|
+
/⏺\s*(Bash|Read|Write|Edit|Glob|Grep|Task|WebFetch)/,
|
|
46355
|
+
// Claude Code tool markers
|
|
46356
|
+
/•\s*Running/
|
|
46357
|
+
// Codex: "• Running: command"
|
|
46358
|
+
]
|
|
46359
|
+
};
|
|
46309
46360
|
function hashWorkspaceId(workspaceId) {
|
|
46310
46361
|
return (0, import_node_crypto9.createHash)("sha256").update(workspaceId).digest("hex").slice(0, 12);
|
|
46311
46362
|
}
|
|
@@ -46328,6 +46379,7 @@ var RelayPtyOrchestrator = class extends BaseWrapper {
|
|
|
46328
46379
|
outputBuffer = "";
|
|
46329
46380
|
rawBuffer = "";
|
|
46330
46381
|
lastParsedLength = 0;
|
|
46382
|
+
bufferTrimCount = 0;
|
|
46331
46383
|
// Interactive mode (show output to terminal)
|
|
46332
46384
|
isInteractive = false;
|
|
46333
46385
|
// Injection state
|
|
@@ -46876,13 +46928,19 @@ Stderr: ${stderrBuffer.slice(0, 500)}` : "";
|
|
|
46876
46928
|
this.rawBuffer += data;
|
|
46877
46929
|
this.outputBuffer += data;
|
|
46878
46930
|
this.hasReceivedOutput = true;
|
|
46931
|
+
let buffersTrimmed = false;
|
|
46879
46932
|
if (this.rawBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
|
|
46880
46933
|
const trimAmount = this.rawBuffer.length - MAX_OUTPUT_BUFFER_SIZE;
|
|
46881
46934
|
this.rawBuffer = this.rawBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
|
|
46882
46935
|
this.lastParsedLength = Math.max(0, this.lastParsedLength - trimAmount);
|
|
46936
|
+
buffersTrimmed = true;
|
|
46883
46937
|
}
|
|
46884
46938
|
if (this.outputBuffer.length > MAX_OUTPUT_BUFFER_SIZE) {
|
|
46885
46939
|
this.outputBuffer = this.outputBuffer.slice(-MAX_OUTPUT_BUFFER_SIZE);
|
|
46940
|
+
buffersTrimmed = true;
|
|
46941
|
+
}
|
|
46942
|
+
if (buffersTrimmed) {
|
|
46943
|
+
this.bufferTrimCount += 1;
|
|
46886
46944
|
}
|
|
46887
46945
|
this.feedIdleDetectorOutput(data);
|
|
46888
46946
|
const indicator = this.formatUnreadIndicator();
|
|
@@ -48126,14 +48184,103 @@ Then output: \`->relay-file:spawn\`
|
|
|
48126
48184
|
this.relayPtyProcess.stdin.write(buffer);
|
|
48127
48185
|
}
|
|
48128
48186
|
/**
|
|
48129
|
-
*
|
|
48187
|
+
* Verify that the CLI shows activity after task injection.
|
|
48188
|
+
* Checks output for patterns indicating the task was received and processing started.
|
|
48189
|
+
*
|
|
48190
|
+
* This catches the race condition where PTY write succeeds but CLI wasn't ready
|
|
48191
|
+
* (the T-003 failure scenario where CLI showed bell characters instead of processing).
|
|
48192
|
+
*
|
|
48193
|
+
* @param outputBefore The output buffer content before injection
|
|
48194
|
+
* @returns Promise resolving to true if activity detected, false otherwise
|
|
48195
|
+
*/
|
|
48196
|
+
async verifyActivityAfterInjection(outputBefore) {
|
|
48197
|
+
const startTime = Date.now();
|
|
48198
|
+
const { TIMEOUT_MS, POLL_INTERVAL_MS, TASK_RECEIVED_PATTERNS, THINKING_PATTERNS, TOOL_EXECUTION_PATTERNS } = ACTIVITY_VERIFICATION;
|
|
48199
|
+
const trimCountBefore = this.bufferTrimCount;
|
|
48200
|
+
while (Date.now() - startTime < TIMEOUT_MS) {
|
|
48201
|
+
if (this.bufferTrimCount !== trimCountBefore) {
|
|
48202
|
+
this.log(` Activity verified: output buffer trimmed during verification (large output)`);
|
|
48203
|
+
return true;
|
|
48204
|
+
}
|
|
48205
|
+
const currentOutput = this.outputBuffer;
|
|
48206
|
+
const newOutput = currentOutput.slice(outputBefore.length);
|
|
48207
|
+
if (newOutput.length > 0) {
|
|
48208
|
+
const belCount = (newOutput.match(/\x07/g) || []).length;
|
|
48209
|
+
if (belCount > 10) {
|
|
48210
|
+
this.logError(` Input rejected: CLI produced ${belCount} BEL characters`);
|
|
48211
|
+
return false;
|
|
48212
|
+
}
|
|
48213
|
+
for (const pattern of TASK_RECEIVED_PATTERNS) {
|
|
48214
|
+
if (pattern.test(newOutput)) {
|
|
48215
|
+
this.log(` Activity verified: task received pattern matched`);
|
|
48216
|
+
return true;
|
|
48217
|
+
}
|
|
48218
|
+
}
|
|
48219
|
+
for (const pattern of THINKING_PATTERNS) {
|
|
48220
|
+
if (pattern.test(newOutput)) {
|
|
48221
|
+
this.log(` Activity verified: thinking pattern matched`);
|
|
48222
|
+
return true;
|
|
48223
|
+
}
|
|
48224
|
+
}
|
|
48225
|
+
for (const pattern of TOOL_EXECUTION_PATTERNS) {
|
|
48226
|
+
if (pattern.test(newOutput)) {
|
|
48227
|
+
this.log(` Activity verified: tool execution pattern matched`);
|
|
48228
|
+
return true;
|
|
48229
|
+
}
|
|
48230
|
+
}
|
|
48231
|
+
const meaningfulOutput = newOutput.replace(/[\x00-\x1f]/g, "");
|
|
48232
|
+
if (meaningfulOutput.length > 100) {
|
|
48233
|
+
this.log(` Activity verified: significant output growth (${meaningfulOutput.length} meaningful chars)`);
|
|
48234
|
+
return true;
|
|
48235
|
+
}
|
|
48236
|
+
}
|
|
48237
|
+
await sleep(POLL_INTERVAL_MS);
|
|
48238
|
+
}
|
|
48239
|
+
this.log(` No activity detected within ${TIMEOUT_MS}ms`);
|
|
48240
|
+
return false;
|
|
48241
|
+
}
|
|
48242
|
+
/**
|
|
48243
|
+
* Inject a task using the socket-based injection system with activity verification.
|
|
48130
48244
|
* This is the preferred method for spawned agent task delivery.
|
|
48131
48245
|
*
|
|
48246
|
+
* After socket confirms delivery, verifies the CLI shows activity (task received,
|
|
48247
|
+
* thinking indicators, or tool execution). Retries if no activity is detected.
|
|
48248
|
+
*
|
|
48132
48249
|
* @param task The task text to inject
|
|
48133
48250
|
* @param from The sender name (default: "spawner")
|
|
48134
|
-
* @returns Promise resolving to true if
|
|
48251
|
+
* @returns Promise resolving to true if task was delivered AND activity verified, false otherwise
|
|
48135
48252
|
*/
|
|
48136
48253
|
async injectTask(task, from = "spawner") {
|
|
48254
|
+
const { MAX_RETRIES, RETRY_DELAY_MS } = ACTIVITY_VERIFICATION;
|
|
48255
|
+
const STABILIZATION_DELAY_MS = 1500;
|
|
48256
|
+
this.log(` Waiting ${STABILIZATION_DELAY_MS}ms for CLI stabilization before task injection`);
|
|
48257
|
+
await sleep(STABILIZATION_DELAY_MS);
|
|
48258
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
48259
|
+
if (attempt > 0) {
|
|
48260
|
+
this.log(` Retry ${attempt}/${MAX_RETRIES} - waiting ${RETRY_DELAY_MS}ms before retry`);
|
|
48261
|
+
await sleep(RETRY_DELAY_MS);
|
|
48262
|
+
}
|
|
48263
|
+
const outputBefore = this.outputBuffer;
|
|
48264
|
+
const delivered = await this.performTaskInjection(task, from);
|
|
48265
|
+
if (!delivered) {
|
|
48266
|
+
this.logError(` Task delivery failed on attempt ${attempt + 1}`);
|
|
48267
|
+
continue;
|
|
48268
|
+
}
|
|
48269
|
+
const activityVerified = await this.verifyActivityAfterInjection(outputBefore);
|
|
48270
|
+
if (activityVerified) {
|
|
48271
|
+
this.log(` Task delivered and activity verified successfully`);
|
|
48272
|
+
return true;
|
|
48273
|
+
}
|
|
48274
|
+
this.logError(` Task delivered but no activity detected (attempt ${attempt + 1})`);
|
|
48275
|
+
}
|
|
48276
|
+
this.logError(` Task injection failed after ${MAX_RETRIES + 1} attempts - no CLI activity detected`);
|
|
48277
|
+
return false;
|
|
48278
|
+
}
|
|
48279
|
+
/**
|
|
48280
|
+
* Perform a single task injection attempt (without retry logic).
|
|
48281
|
+
* @returns true if the injection was sent successfully, false otherwise
|
|
48282
|
+
*/
|
|
48283
|
+
async performTaskInjection(task, from) {
|
|
48137
48284
|
if (!this.socket || !this.socketConnected) {
|
|
48138
48285
|
this.log(` Socket not connected for task injection, falling back to stdin write`);
|
|
48139
48286
|
try {
|
|
@@ -48386,6 +48533,12 @@ var openCodeApi = new OpenCodeApi();
|
|
|
48386
48533
|
|
|
48387
48534
|
// packages/wrapper/dist/opencode-wrapper.js
|
|
48388
48535
|
var import_node_child_process4 = require("node:child_process");
|
|
48536
|
+
var TASK_INJECTION = {
|
|
48537
|
+
/** Maximum retries when injection fails */
|
|
48538
|
+
MAX_RETRIES: 3,
|
|
48539
|
+
/** Delay between retries (ms) */
|
|
48540
|
+
RETRY_DELAY_MS: 500
|
|
48541
|
+
};
|
|
48389
48542
|
var OpenCodeWrapper = class extends BaseWrapper {
|
|
48390
48543
|
config;
|
|
48391
48544
|
// OpenCode API client
|
|
@@ -48641,19 +48794,32 @@ var OpenCodeWrapper = class extends BaseWrapper {
|
|
|
48641
48794
|
}
|
|
48642
48795
|
}
|
|
48643
48796
|
/**
|
|
48644
|
-
* Inject a task into the agent
|
|
48797
|
+
* Inject a task into the agent with retry logic.
|
|
48798
|
+
*
|
|
48799
|
+
* Retries on transient failures to match RelayPtyOrchestrator behavior.
|
|
48800
|
+
* This ensures consistent reliability across all wrapper types.
|
|
48801
|
+
*
|
|
48645
48802
|
* @param task - The task description to inject
|
|
48646
48803
|
* @param _from - The sender name (used for formatting)
|
|
48647
|
-
* @returns true if injection succeeded
|
|
48804
|
+
* @returns true if injection succeeded, false otherwise
|
|
48648
48805
|
*/
|
|
48649
48806
|
async injectTask(task, _from) {
|
|
48650
|
-
|
|
48651
|
-
|
|
48652
|
-
|
|
48653
|
-
|
|
48654
|
-
|
|
48655
|
-
|
|
48807
|
+
const { MAX_RETRIES, RETRY_DELAY_MS } = TASK_INJECTION;
|
|
48808
|
+
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
48809
|
+
if (attempt > 0) {
|
|
48810
|
+
console.log(`[OpenCodeWrapper] Retry ${attempt}/${MAX_RETRIES} - waiting ${RETRY_DELAY_MS}ms before retry`);
|
|
48811
|
+
await sleep(RETRY_DELAY_MS);
|
|
48812
|
+
}
|
|
48813
|
+
try {
|
|
48814
|
+
await this.performInjection(task);
|
|
48815
|
+
console.log(`[OpenCodeWrapper] Task delivered successfully${attempt > 0 ? ` (attempt ${attempt + 1})` : ""}`);
|
|
48816
|
+
return true;
|
|
48817
|
+
} catch (error2) {
|
|
48818
|
+
console.error(`[OpenCodeWrapper] Task delivery failed (attempt ${attempt + 1}/${MAX_RETRIES + 1}):`, error2);
|
|
48819
|
+
}
|
|
48656
48820
|
}
|
|
48821
|
+
console.error(`[OpenCodeWrapper] Task injection failed after ${MAX_RETRIES + 1} attempts`);
|
|
48822
|
+
return false;
|
|
48657
48823
|
}
|
|
48658
48824
|
/**
|
|
48659
48825
|
* Get output lines (for compatibility with spawner)
|
|
@@ -55172,9 +55338,55 @@ async function selectShadowCli(primaryCli, options) {
|
|
|
55172
55338
|
throw new Error("No shadow-capable CLI authenticated. Install Claude or OpenCode (codex) and try again.");
|
|
55173
55339
|
}
|
|
55174
55340
|
|
|
55341
|
+
// packages/bridge/dist/cli-resolution.js
|
|
55342
|
+
var import_node_child_process8 = require("node:child_process");
|
|
55343
|
+
init_logger();
|
|
55344
|
+
var log2 = createLogger2("cli-resolution");
|
|
55345
|
+
function commandExists2(cmd) {
|
|
55346
|
+
try {
|
|
55347
|
+
const whichCmd = process.platform === "win32" ? "where" : "which";
|
|
55348
|
+
(0, import_node_child_process8.execSync)(`${whichCmd} ${cmd}`, { stdio: "ignore" });
|
|
55349
|
+
return true;
|
|
55350
|
+
} catch {
|
|
55351
|
+
return false;
|
|
55352
|
+
}
|
|
55353
|
+
}
|
|
55354
|
+
var detectedCursorCli = null;
|
|
55355
|
+
function detectCursorCli() {
|
|
55356
|
+
if (detectedCursorCli !== null) {
|
|
55357
|
+
return detectedCursorCli;
|
|
55358
|
+
}
|
|
55359
|
+
if (commandExists2("agent")) {
|
|
55360
|
+
detectedCursorCli = "agent";
|
|
55361
|
+
log2.debug("Detected Cursor CLI: agent (newer version)");
|
|
55362
|
+
return "agent";
|
|
55363
|
+
}
|
|
55364
|
+
if (commandExists2("cursor-agent")) {
|
|
55365
|
+
detectedCursorCli = "cursor-agent";
|
|
55366
|
+
log2.debug("Detected Cursor CLI: cursor-agent (older version)");
|
|
55367
|
+
return "cursor-agent";
|
|
55368
|
+
}
|
|
55369
|
+
log2.debug("Cursor CLI not found (neither agent nor cursor-agent)");
|
|
55370
|
+
return null;
|
|
55371
|
+
}
|
|
55372
|
+
function resolveCli(rawCommand) {
|
|
55373
|
+
const cmdLower = rawCommand.toLowerCase();
|
|
55374
|
+
if (cmdLower === "cursor" || cmdLower === "cursor-agent") {
|
|
55375
|
+
const cursorCli = detectCursorCli();
|
|
55376
|
+
if (cursorCli) {
|
|
55377
|
+
return cursorCli;
|
|
55378
|
+
}
|
|
55379
|
+
return "agent";
|
|
55380
|
+
}
|
|
55381
|
+
if (cmdLower === "google") {
|
|
55382
|
+
return "gemini";
|
|
55383
|
+
}
|
|
55384
|
+
return rawCommand;
|
|
55385
|
+
}
|
|
55386
|
+
|
|
55175
55387
|
// packages/bridge/dist/spawner.js
|
|
55176
55388
|
var import_node_fs14 = __toESM(require("node:fs"), 1);
|
|
55177
|
-
var
|
|
55389
|
+
var import_node_child_process12 = require("node:child_process");
|
|
55178
55390
|
var import_node_path17 = __toESM(require("node:path"), 1);
|
|
55179
55391
|
var import_node_url3 = require("node:url");
|
|
55180
55392
|
|
|
@@ -63297,8 +63509,8 @@ var relayStatusSchema = external_exports.object({});
|
|
|
63297
63509
|
|
|
63298
63510
|
// packages/mcp/dist/tools/relay-logs.js
|
|
63299
63511
|
var import_node_util4 = require("node:util");
|
|
63300
|
-
var
|
|
63301
|
-
var execAsync3 = (0, import_node_util4.promisify)(
|
|
63512
|
+
var import_node_child_process10 = require("node:child_process");
|
|
63513
|
+
var execAsync3 = (0, import_node_util4.promisify)(import_node_child_process10.exec);
|
|
63302
63514
|
var relayLogsSchema = external_exports.object({
|
|
63303
63515
|
agent: external_exports.string().describe("Name of the agent to get logs for"),
|
|
63304
63516
|
lines: external_exports.number().optional().default(50).describe("Number of lines to retrieve (default: 50)")
|
|
@@ -63393,7 +63605,7 @@ var relayVoteSchema = external_exports.object({
|
|
|
63393
63605
|
var import_node_fs13 = require("node:fs");
|
|
63394
63606
|
var import_node_path16 = require("node:path");
|
|
63395
63607
|
var import_node_os9 = require("node:os");
|
|
63396
|
-
var
|
|
63608
|
+
var import_node_child_process11 = require("node:child_process");
|
|
63397
63609
|
|
|
63398
63610
|
// node_modules/smol-toml/dist/error.js
|
|
63399
63611
|
function getLineColFromPtr(string3, ptr) {
|
|
@@ -64301,7 +64513,7 @@ function getConfigPaths() {
|
|
|
64301
64513
|
}
|
|
64302
64514
|
function isUsingNvm() {
|
|
64303
64515
|
try {
|
|
64304
|
-
const nodePath = (0,
|
|
64516
|
+
const nodePath = (0, import_node_child_process11.execSync)("which node", { encoding: "utf-8" }).trim();
|
|
64305
64517
|
return nodePath.includes(".nvm");
|
|
64306
64518
|
} catch {
|
|
64307
64519
|
return false;
|
|
@@ -64309,14 +64521,14 @@ function isUsingNvm() {
|
|
|
64309
64521
|
}
|
|
64310
64522
|
function getNodePath() {
|
|
64311
64523
|
try {
|
|
64312
|
-
return (0,
|
|
64524
|
+
return (0, import_node_child_process11.execSync)("which node", { encoding: "utf-8" }).trim();
|
|
64313
64525
|
} catch {
|
|
64314
64526
|
return null;
|
|
64315
64527
|
}
|
|
64316
64528
|
}
|
|
64317
64529
|
function getGlobalMcpBinPath() {
|
|
64318
64530
|
try {
|
|
64319
|
-
const npmPrefix = (0,
|
|
64531
|
+
const npmPrefix = (0, import_node_child_process11.execSync)("npm prefix -g", { encoding: "utf-8" }).trim();
|
|
64320
64532
|
const binPath = (0, import_node_path16.join)(npmPrefix, "lib", "node_modules", "@agent-relay", "mcp", "dist", "bin.js");
|
|
64321
64533
|
if ((0, import_node_fs13.existsSync)(binPath)) {
|
|
64322
64534
|
return binPath;
|
|
@@ -64544,14 +64756,7 @@ function installMcpConfig(configPath, options = {}) {
|
|
|
64544
64756
|
// packages/bridge/dist/spawner.js
|
|
64545
64757
|
var __filename3 = (0, import_node_url3.fileURLToPath)(import_meta_url);
|
|
64546
64758
|
var __dirname3 = import_node_path17.default.dirname(__filename3);
|
|
64547
|
-
var
|
|
64548
|
-
var CLI_COMMAND_MAP = {
|
|
64549
|
-
cursor: "agent",
|
|
64550
|
-
// Cursor CLI installs as 'agent'
|
|
64551
|
-
google: "gemini"
|
|
64552
|
-
// Google provider uses 'gemini' CLI
|
|
64553
|
-
// Other providers use their name as the command (claude, codex, etc.)
|
|
64554
|
-
};
|
|
64759
|
+
var log3 = createLogger2("spawner");
|
|
64555
64760
|
function extractGhTokenFromHosts(content) {
|
|
64556
64761
|
const lines = content.split(/\r?\n/);
|
|
64557
64762
|
let inGithubSection = false;
|
|
@@ -64614,7 +64819,7 @@ function ensureMcpPermissions(projectRoot, cliType, debug = false) {
|
|
|
64614
64819
|
const config2 = configMap[effectiveCli];
|
|
64615
64820
|
if (!config2) {
|
|
64616
64821
|
if (debug)
|
|
64617
|
-
|
|
64822
|
+
log3.debug(`CLI ${cliType} uses flag-based permissions, skipping config setup`);
|
|
64618
64823
|
return;
|
|
64619
64824
|
}
|
|
64620
64825
|
const settingsPath = import_node_path17.default.join(config2.settingsDir, config2.settingsFile);
|
|
@@ -64634,7 +64839,7 @@ function ensureMcpPermissions(projectRoot, cliType, debug = false) {
|
|
|
64634
64839
|
if (config2.enableAllKey && settings[config2.enableAllKey] !== true) {
|
|
64635
64840
|
settings[config2.enableAllKey] = true;
|
|
64636
64841
|
if (debug)
|
|
64637
|
-
|
|
64842
|
+
log3.debug(`Setting ${config2.enableAllKey}: true`);
|
|
64638
64843
|
}
|
|
64639
64844
|
if (config2.permissionKey) {
|
|
64640
64845
|
const keyParts = config2.permissionKey.split(".");
|
|
@@ -64655,14 +64860,14 @@ function ensureMcpPermissions(projectRoot, cliType, debug = false) {
|
|
|
64655
64860
|
if (!allowList.includes(agentRelayPermission)) {
|
|
64656
64861
|
allowList.push(agentRelayPermission);
|
|
64657
64862
|
if (debug)
|
|
64658
|
-
|
|
64863
|
+
log3.debug(`Added MCP permission: ${agentRelayPermission}`);
|
|
64659
64864
|
}
|
|
64660
64865
|
}
|
|
64661
64866
|
import_node_fs14.default.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n");
|
|
64662
64867
|
if (debug)
|
|
64663
|
-
|
|
64868
|
+
log3.debug(`MCP permissions configured at ${settingsPath}`);
|
|
64664
64869
|
} catch (err) {
|
|
64665
|
-
|
|
64870
|
+
log3.warn("Failed to pre-configure MCP permissions", {
|
|
64666
64871
|
cli: cliType,
|
|
64667
64872
|
error: err instanceof Error ? err.message : String(err)
|
|
64668
64873
|
});
|
|
@@ -64712,9 +64917,9 @@ function hasRelayPtyBinary2() {
|
|
|
64712
64917
|
relayPtyBinaryChecked = true;
|
|
64713
64918
|
if (process.env.DEBUG_SPAWN === "1") {
|
|
64714
64919
|
if (relayPtyBinaryPath) {
|
|
64715
|
-
|
|
64920
|
+
log3.debug(`relay-pty binary found: ${relayPtyBinaryPath}`);
|
|
64716
64921
|
} else {
|
|
64717
|
-
|
|
64922
|
+
log3.debug("relay-pty binary not found, will use PtyWrapper fallback");
|
|
64718
64923
|
}
|
|
64719
64924
|
}
|
|
64720
64925
|
}
|
|
@@ -64743,7 +64948,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64743
64948
|
const effectiveTeamDir = options.teamDir ?? paths.teamDir;
|
|
64744
64949
|
this.agentsPath = import_node_path17.default.join(effectiveTeamDir, "connected-agents.json");
|
|
64745
64950
|
this.registryPath = import_node_path17.default.join(effectiveTeamDir, "agents.json");
|
|
64746
|
-
|
|
64951
|
+
log3.info(`AgentSpawner paths: projectRoot=${this.projectRoot} teamDir=${effectiveTeamDir} (explicit=${!!options.teamDir}) agentsPath=${this.agentsPath}`);
|
|
64747
64952
|
this.socketPath = options.socketPath ?? paths.socketPath;
|
|
64748
64953
|
this.logsDir = import_node_path17.default.join(effectiveTeamDir, "worker-logs");
|
|
64749
64954
|
this.workersPath = import_node_path17.default.join(effectiveTeamDir, "workers.json");
|
|
@@ -64758,7 +64963,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64758
64963
|
workspaceId: process.env.WORKSPACE_ID,
|
|
64759
64964
|
strictMode: process.env.AGENT_POLICY_STRICT === "1"
|
|
64760
64965
|
});
|
|
64761
|
-
|
|
64966
|
+
log3.info("Policy enforcement enabled");
|
|
64762
64967
|
}
|
|
64763
64968
|
}
|
|
64764
64969
|
/**
|
|
@@ -64800,7 +65005,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64800
65005
|
});
|
|
64801
65006
|
clearTimeout(timeoutId);
|
|
64802
65007
|
if (!response.ok) {
|
|
64803
|
-
|
|
65008
|
+
log3.warn(`Failed to fetch GH token from cloud: ${response.status} ${response.statusText}`);
|
|
64804
65009
|
return null;
|
|
64805
65010
|
}
|
|
64806
65011
|
const data = await response.json();
|
|
@@ -64808,9 +65013,9 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64808
65013
|
} catch (err) {
|
|
64809
65014
|
const message = err instanceof Error ? err.message : String(err);
|
|
64810
65015
|
if (message.includes("abort")) {
|
|
64811
|
-
|
|
65016
|
+
log3.info("Cloud API timeout (5s) - using local auth");
|
|
64812
65017
|
} else {
|
|
64813
|
-
|
|
65018
|
+
log3.warn("Failed to fetch GH token from cloud", { error: message });
|
|
64814
65019
|
}
|
|
64815
65020
|
return null;
|
|
64816
65021
|
}
|
|
@@ -64857,7 +65062,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64857
65062
|
return null;
|
|
64858
65063
|
}
|
|
64859
65064
|
return await new Promise((resolve5) => {
|
|
64860
|
-
(0,
|
|
65065
|
+
(0, import_node_child_process12.execFile)(ghPath, ["auth", "token", "--hostname", "github.com"], { timeout: 5e3 }, (err, stdout) => {
|
|
64861
65066
|
if (err) {
|
|
64862
65067
|
resolve5(null);
|
|
64863
65068
|
return;
|
|
@@ -64901,7 +65106,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64901
65106
|
* Called after the dashboard server starts and we know the actual port.
|
|
64902
65107
|
*/
|
|
64903
65108
|
setDashboardPort(port) {
|
|
64904
|
-
|
|
65109
|
+
log3.info(`Dashboard port set to ${port} - nested spawns now enabled`);
|
|
64905
65110
|
this.dashboardPort = port;
|
|
64906
65111
|
}
|
|
64907
65112
|
/**
|
|
@@ -64920,7 +65125,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64920
65125
|
*/
|
|
64921
65126
|
setCloudPersistence(handler) {
|
|
64922
65127
|
this.cloudPersistence = handler;
|
|
64923
|
-
|
|
65128
|
+
log3.info("Cloud persistence handler set");
|
|
64924
65129
|
}
|
|
64925
65130
|
/**
|
|
64926
65131
|
* Bind cloud persistence event handlers to a RelayPtyOrchestrator.
|
|
@@ -64933,14 +65138,14 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64933
65138
|
try {
|
|
64934
65139
|
await this.cloudPersistence.onSummary(name, event);
|
|
64935
65140
|
} catch (err) {
|
|
64936
|
-
|
|
65141
|
+
log3.error(`Cloud persistence summary error for ${name}`, { error: err instanceof Error ? err.message : String(err) });
|
|
64937
65142
|
}
|
|
64938
65143
|
};
|
|
64939
65144
|
const sessionEndListener = async (event) => {
|
|
64940
65145
|
try {
|
|
64941
65146
|
await this.cloudPersistence.onSessionEnd(name, event);
|
|
64942
65147
|
} catch (err) {
|
|
64943
|
-
|
|
65148
|
+
log3.error(`Cloud persistence session-end error for ${name}`, { error: err instanceof Error ? err.message : String(err) });
|
|
64944
65149
|
}
|
|
64945
65150
|
};
|
|
64946
65151
|
pty.on("summary", summaryListener);
|
|
@@ -64993,7 +65198,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
64993
65198
|
const maxAgents = parseInt(process.env.MAX_AGENTS ?? "", 10) || 1e4;
|
|
64994
65199
|
const currentAgentCount = this.activeWorkers.size;
|
|
64995
65200
|
if (currentAgentCount >= maxAgents) {
|
|
64996
|
-
|
|
65201
|
+
log3.warn(`Agent limit reached: ${currentAgentCount}/${maxAgents}`);
|
|
64997
65202
|
return {
|
|
64998
65203
|
success: false,
|
|
64999
65204
|
name,
|
|
@@ -65003,7 +65208,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
65003
65208
|
if (this.policyEnforcementEnabled && this.policyService && spawnerName) {
|
|
65004
65209
|
const decision = await this.policyService.canSpawn(spawnerName, name, cli);
|
|
65005
65210
|
if (!decision.allowed) {
|
|
65006
|
-
|
|
65211
|
+
log3.warn(`Policy blocked spawn: ${spawnerName} -> ${name}: ${decision.reason}`);
|
|
65007
65212
|
return {
|
|
65008
65213
|
success: false,
|
|
65009
65214
|
name,
|
|
@@ -65012,26 +65217,26 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
65012
65217
|
};
|
|
65013
65218
|
}
|
|
65014
65219
|
if (debug) {
|
|
65015
|
-
|
|
65220
|
+
log3.debug(`Policy allowed spawn: ${spawnerName} -> ${name} (source: ${decision.policySource})`);
|
|
65016
65221
|
}
|
|
65017
65222
|
}
|
|
65018
65223
|
try {
|
|
65019
65224
|
const cliParts = cli.split(" ");
|
|
65020
65225
|
const rawCommandName = cliParts[0];
|
|
65021
|
-
const commandName =
|
|
65226
|
+
const commandName = resolveCli(rawCommandName);
|
|
65022
65227
|
const args = cliParts.slice(1);
|
|
65023
65228
|
if (commandName !== rawCommandName && debug) {
|
|
65024
|
-
|
|
65229
|
+
log3.debug(`Mapped CLI '${rawCommandName}' -> '${commandName}'`);
|
|
65025
65230
|
}
|
|
65026
65231
|
const command = resolveCommand(commandName);
|
|
65027
65232
|
if (debug)
|
|
65028
|
-
|
|
65233
|
+
log3.debug(`Resolved '${commandName}' -> '${command}'`);
|
|
65029
65234
|
if (command === commandName && !commandName.startsWith("/")) {
|
|
65030
|
-
|
|
65235
|
+
log3.warn(`Could not resolve path for '${commandName}', spawn may fail`);
|
|
65031
65236
|
}
|
|
65032
65237
|
ensureMcpPermissions(this.projectRoot, commandName, debug);
|
|
65033
65238
|
const isClaudeCli = commandName.startsWith("claude");
|
|
65034
|
-
const isCursorCli = commandName === "agent" || rawCommandName === "cursor";
|
|
65239
|
+
const isCursorCli = commandName === "agent" || rawCommandName === "cursor" || rawCommandName === "cursor-agent";
|
|
65035
65240
|
if (!interactive) {
|
|
65036
65241
|
if (isClaudeCli && !args.includes("--dangerously-skip-permissions")) {
|
|
65037
65242
|
args.push("--dangerously-skip-permissions");
|
|
@@ -65041,7 +65246,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
65041
65246
|
}
|
|
65042
65247
|
} else {
|
|
65043
65248
|
if (debug)
|
|
65044
|
-
|
|
65249
|
+
log3.debug(`Interactive mode: skipping auto-accept flags for ${name}`);
|
|
65045
65250
|
}
|
|
65046
65251
|
if (isClaudeCli) {
|
|
65047
65252
|
const agentConfig = findAgentConfig(name, this.projectRoot);
|
|
@@ -65051,9 +65256,9 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
65051
65256
|
const configuredArgs = buildClaudeArgs(name, args, this.projectRoot);
|
|
65052
65257
|
args.length = 0;
|
|
65053
65258
|
args.push(...configuredArgs);
|
|
65054
|
-
|
|
65259
|
+
log3.info(`Agent ${name}: model=${effectiveModel}, cli=${cli}, variant=${cliVariant}`);
|
|
65055
65260
|
if (debug)
|
|
65056
|
-
|
|
65261
|
+
log3.debug(`Applied agent config for ${name}: ${args.join(" ")}`);
|
|
65057
65262
|
}
|
|
65058
65263
|
const isCodexCli = commandName.startsWith("codex");
|
|
65059
65264
|
const isGeminiCli = commandName === "gemini";
|
|
@@ -65079,12 +65284,12 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
65079
65284
|
});
|
|
65080
65285
|
if (result.success) {
|
|
65081
65286
|
if (debug)
|
|
65082
|
-
|
|
65287
|
+
log3.debug(`Auto-installed MCP config at ${projectMcpConfigPath}`);
|
|
65083
65288
|
} else {
|
|
65084
|
-
|
|
65289
|
+
log3.warn(`Failed to auto-install MCP config: ${result.error}`);
|
|
65085
65290
|
}
|
|
65086
65291
|
} catch (err) {
|
|
65087
|
-
|
|
65292
|
+
log3.warn("Failed to auto-install MCP config", {
|
|
65088
65293
|
error: err instanceof Error ? err.message : String(err)
|
|
65089
65294
|
});
|
|
65090
65295
|
}
|
|
@@ -65099,7 +65304,7 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
65099
65304
|
}
|
|
65100
65305
|
}
|
|
65101
65306
|
if (debug && hasMcp)
|
|
65102
|
-
|
|
65307
|
+
log3.debug(`MCP tools available for ${name} (MCP config found, socket ${relaySocket})`);
|
|
65103
65308
|
let relayInstructions = getRelayInstructions(name, { hasMcp, includeWorkflowConventions });
|
|
65104
65309
|
const agentConfigForRole = isClaudeCli ? findAgentConfig(name, this.projectRoot) : null;
|
|
65105
65310
|
if (agentConfigForRole?.role) {
|
|
@@ -65115,10 +65320,10 @@ var AgentSpawner = class _AgentSpawner {
|
|
|
65115
65320
|
|
|
65116
65321
|
${relayInstructions}`;
|
|
65117
65322
|
if (debug)
|
|
65118
|
-
|
|
65323
|
+
log3.debug(`Composed role prompt for ${name} (role: ${role})`);
|
|
65119
65324
|
}
|
|
65120
65325
|
} catch (err) {
|
|
65121
|
-
|
|
65326
|
+
log3.warn(`Failed to compose role prompt for ${name}: ${err.message}`);
|
|
65122
65327
|
}
|
|
65123
65328
|
}
|
|
65124
65329
|
}
|
|
@@ -65135,7 +65340,7 @@ ${relayInstructions}`;
|
|
|
65135
65340
|
args.unshift("login");
|
|
65136
65341
|
}
|
|
65137
65342
|
if (debug)
|
|
65138
|
-
|
|
65343
|
+
log3.debug(`Spawning ${name} with: ${command} ${args.join(" ")}`);
|
|
65139
65344
|
let agentCwd;
|
|
65140
65345
|
if (request.cwd && typeof request.cwd === "string") {
|
|
65141
65346
|
const resolvedCwd = import_node_path17.default.resolve(this.projectRoot, request.cwd);
|
|
@@ -65152,14 +65357,14 @@ ${relayInstructions}`;
|
|
|
65152
65357
|
} else {
|
|
65153
65358
|
agentCwd = this.projectRoot;
|
|
65154
65359
|
}
|
|
65155
|
-
|
|
65360
|
+
log3.info(`Spawning ${name}: dashboardPort=${this.dashboardPort || "none"} (${this.dashboardPort ? "nested spawns enabled" : "nested spawns disabled"})`);
|
|
65156
65361
|
let userEnv;
|
|
65157
65362
|
if (userId) {
|
|
65158
65363
|
try {
|
|
65159
65364
|
const userDirService = getUserDirectoryService();
|
|
65160
65365
|
userEnv = userDirService.getUserEnvironment(userId);
|
|
65161
65366
|
} catch (err) {
|
|
65162
|
-
|
|
65367
|
+
log3.warn("Failed to resolve user environment, using default", {
|
|
65163
65368
|
userId,
|
|
65164
65369
|
error: err instanceof Error ? err.message : String(err)
|
|
65165
65370
|
});
|
|
@@ -65176,7 +65381,7 @@ ${relayInstructions}`;
|
|
|
65176
65381
|
userEnv = mergedUserEnv;
|
|
65177
65382
|
}
|
|
65178
65383
|
if (debug)
|
|
65179
|
-
|
|
65384
|
+
log3.debug(`Socket path for ${name}: ${this.socketPath ?? "undefined"}`);
|
|
65180
65385
|
if (!hasRelayPtyBinary2()) {
|
|
65181
65386
|
const checkedPaths = getLastSearchPaths();
|
|
65182
65387
|
const tracedError = createTraceableError("relay-pty binary not found", {
|
|
@@ -65188,10 +65393,10 @@ ${relayInstructions}`;
|
|
|
65188
65393
|
totalPathsChecked: checkedPaths.length,
|
|
65189
65394
|
hint: "Set RELAY_PTY_BINARY env var to override, or reinstall: npm install agent-relay"
|
|
65190
65395
|
});
|
|
65191
|
-
|
|
65396
|
+
log3.error(tracedError.logMessage);
|
|
65192
65397
|
if (debug) {
|
|
65193
|
-
|
|
65194
|
-
checkedPaths.forEach((p, i) =>
|
|
65398
|
+
log3.debug("All paths checked for relay-pty binary:");
|
|
65399
|
+
checkedPaths.forEach((p, i) => log3.debug(` ${i + 1}. ${p}`));
|
|
65195
65400
|
}
|
|
65196
65401
|
return {
|
|
65197
65402
|
success: false,
|
|
@@ -65202,7 +65407,7 @@ ${relayInstructions}`;
|
|
|
65202
65407
|
}
|
|
65203
65408
|
const onExitHandler = (code) => {
|
|
65204
65409
|
if (debug)
|
|
65205
|
-
|
|
65410
|
+
log3.debug(`Worker ${name} exited with code ${code}`);
|
|
65206
65411
|
const worker = this.activeWorkers.get(name);
|
|
65207
65412
|
const agentId = worker?.pty?.getAgentId?.();
|
|
65208
65413
|
if (worker?.listeners) {
|
|
@@ -65212,7 +65417,7 @@ ${relayInstructions}`;
|
|
|
65212
65417
|
try {
|
|
65213
65418
|
this.saveWorkersMetadata();
|
|
65214
65419
|
} catch (err) {
|
|
65215
|
-
|
|
65420
|
+
log3.error("Failed to save metadata on exit", { error: err instanceof Error ? err.message : String(err) });
|
|
65216
65421
|
}
|
|
65217
65422
|
if (code !== 0 && code !== null && this.onAgentDeath) {
|
|
65218
65423
|
const crashError = createTraceableError("Agent crashed unexpectedly", {
|
|
@@ -65221,7 +65426,7 @@ ${relayInstructions}`;
|
|
|
65221
65426
|
cli,
|
|
65222
65427
|
agentId
|
|
65223
65428
|
});
|
|
65224
|
-
|
|
65429
|
+
log3.error(crashError.logMessage);
|
|
65225
65430
|
this.onAgentDeath({
|
|
65226
65431
|
name,
|
|
65227
65432
|
exitCode: code,
|
|
@@ -65233,7 +65438,7 @@ ${relayInstructions}`;
|
|
|
65233
65438
|
};
|
|
65234
65439
|
const onSpawnHandler = this.dashboardPort ? void 0 : async (workerName, workerCli, workerTask) => {
|
|
65235
65440
|
if (debug)
|
|
65236
|
-
|
|
65441
|
+
log3.debug(`Nested spawn: ${workerName}`);
|
|
65237
65442
|
await this.spawn({
|
|
65238
65443
|
name: workerName,
|
|
65239
65444
|
cli: workerCli,
|
|
@@ -65243,7 +65448,7 @@ ${relayInstructions}`;
|
|
|
65243
65448
|
};
|
|
65244
65449
|
const onReleaseHandler = this.dashboardPort ? void 0 : async (workerName) => {
|
|
65245
65450
|
if (debug)
|
|
65246
|
-
|
|
65451
|
+
log3.debug(`Release request: ${workerName}`);
|
|
65247
65452
|
await this.release(workerName);
|
|
65248
65453
|
};
|
|
65249
65454
|
if (isOpenCodeCli) {
|
|
@@ -65253,7 +65458,7 @@ ${relayInstructions}`;
|
|
|
65253
65458
|
const shouldUseHttpApi = serveAvailable || isCloudWorkspace2;
|
|
65254
65459
|
if (shouldUseHttpApi) {
|
|
65255
65460
|
if (debug)
|
|
65256
|
-
|
|
65461
|
+
log3.debug(`OpenCode: serve=${serveAvailable ? "available" : "will-auto-start"}, cloud=${isCloudWorkspace2}, using OpenCodeWrapper for ${name}`);
|
|
65257
65462
|
const openCodeConfig = {
|
|
65258
65463
|
name,
|
|
65259
65464
|
command,
|
|
@@ -65295,11 +65500,11 @@ ${relayInstructions}`;
|
|
|
65295
65500
|
if (this.onMarkSpawning) {
|
|
65296
65501
|
this.onMarkSpawning(name);
|
|
65297
65502
|
if (debug)
|
|
65298
|
-
|
|
65503
|
+
log3.debug(`Marked ${name} as spawning`);
|
|
65299
65504
|
}
|
|
65300
65505
|
await openCodeWrapper.start();
|
|
65301
65506
|
if (debug)
|
|
65302
|
-
|
|
65507
|
+
log3.debug(`OpenCodeWrapper started for ${name}, HTTP mode: ${openCodeWrapper.isHttpApiMode}`);
|
|
65303
65508
|
const registered2 = await this.waitForAgentRegistration(name, 3e4, 500);
|
|
65304
65509
|
if (!registered2) {
|
|
65305
65510
|
const tracedError = createTraceableError("Agent registration timeout", {
|
|
@@ -65308,7 +65513,7 @@ ${relayInstructions}`;
|
|
|
65308
65513
|
pid: openCodeWrapper.pid,
|
|
65309
65514
|
timeoutMs: 3e4
|
|
65310
65515
|
});
|
|
65311
|
-
|
|
65516
|
+
log3.error(tracedError.logMessage);
|
|
65312
65517
|
if (this.onClearSpawning) {
|
|
65313
65518
|
this.onClearSpawning(name);
|
|
65314
65519
|
}
|
|
@@ -65322,15 +65527,35 @@ ${relayInstructions}`;
|
|
|
65322
65527
|
}
|
|
65323
65528
|
if (task && task.trim()) {
|
|
65324
65529
|
const ready = await openCodeWrapper.waitUntilReadyForMessages(2e4, 100);
|
|
65530
|
+
let taskSent = false;
|
|
65325
65531
|
if (ready) {
|
|
65326
|
-
|
|
65532
|
+
taskSent = await openCodeWrapper.injectTask(task, spawnerName || "spawner");
|
|
65327
65533
|
if (!taskSent) {
|
|
65328
|
-
|
|
65534
|
+
log3.warn(`Failed to inject task for ${name} via OpenCodeWrapper`);
|
|
65329
65535
|
} else if (debug) {
|
|
65330
|
-
|
|
65536
|
+
log3.debug(`Task injected to ${name} via OpenCodeWrapper`);
|
|
65331
65537
|
}
|
|
65332
65538
|
} else {
|
|
65333
|
-
|
|
65539
|
+
log3.warn(`OpenCodeWrapper ${name} not ready for task injection`);
|
|
65540
|
+
}
|
|
65541
|
+
if (!taskSent) {
|
|
65542
|
+
const tracedError = createTraceableError("Task injection failed", {
|
|
65543
|
+
agentName: name,
|
|
65544
|
+
cli,
|
|
65545
|
+
taskLength: task.length,
|
|
65546
|
+
ready
|
|
65547
|
+
});
|
|
65548
|
+
log3.error(`CRITICAL: ${tracedError.logMessage}`);
|
|
65549
|
+
await openCodeWrapper.stop();
|
|
65550
|
+
if (this.onClearSpawning) {
|
|
65551
|
+
this.onClearSpawning(name);
|
|
65552
|
+
}
|
|
65553
|
+
return {
|
|
65554
|
+
success: false,
|
|
65555
|
+
name,
|
|
65556
|
+
error: tracedError.userMessage,
|
|
65557
|
+
errorId: tracedError.errorId
|
|
65558
|
+
};
|
|
65334
65559
|
}
|
|
65335
65560
|
}
|
|
65336
65561
|
const workerInfo2 = {
|
|
@@ -65349,7 +65574,7 @@ ${relayInstructions}`;
|
|
|
65349
65574
|
this.saveWorkersMetadata();
|
|
65350
65575
|
const teamInfo2 = team ? ` [team: ${team}]` : "";
|
|
65351
65576
|
const shadowInfo2 = request.shadowOf ? ` [shadow of: ${request.shadowOf}]` : "";
|
|
65352
|
-
|
|
65577
|
+
log3.info(`Spawned ${name} (${cli}) via OpenCodeWrapper${teamInfo2}${shadowInfo2} [HTTP mode: ${openCodeWrapper.isHttpApiMode}]`);
|
|
65353
65578
|
return {
|
|
65354
65579
|
success: true,
|
|
65355
65580
|
name,
|
|
@@ -65357,7 +65582,7 @@ ${relayInstructions}`;
|
|
|
65357
65582
|
};
|
|
65358
65583
|
}
|
|
65359
65584
|
if (debug)
|
|
65360
|
-
|
|
65585
|
+
log3.debug(`OpenCode: serve not available, not cloud workspace, falling back to RelayPtyOrchestrator for ${name}`);
|
|
65361
65586
|
}
|
|
65362
65587
|
const ptyConfig = {
|
|
65363
65588
|
name,
|
|
@@ -65391,7 +65616,7 @@ ${relayInstructions}`;
|
|
|
65391
65616
|
};
|
|
65392
65617
|
const pty = new RelayPtyOrchestrator(ptyConfig);
|
|
65393
65618
|
if (debug)
|
|
65394
|
-
|
|
65619
|
+
log3.debug(`Using RelayPtyOrchestrator for ${name}`);
|
|
65395
65620
|
const listeners = {};
|
|
65396
65621
|
const outputListener = (data) => {
|
|
65397
65622
|
const broadcast = global.__broadcastLogOutput;
|
|
@@ -65409,19 +65634,19 @@ ${relayInstructions}`;
|
|
|
65409
65634
|
if (this.onMarkSpawning) {
|
|
65410
65635
|
this.onMarkSpawning(name);
|
|
65411
65636
|
if (debug)
|
|
65412
|
-
|
|
65637
|
+
log3.debug(`Marked ${name} as spawning`);
|
|
65413
65638
|
}
|
|
65414
65639
|
await pty.start();
|
|
65415
65640
|
if (debug)
|
|
65416
|
-
|
|
65641
|
+
log3.debug(`PTY started, pid: ${pty.pid}`);
|
|
65417
65642
|
if (isCursorCli && interactive) {
|
|
65418
65643
|
await sleep2(1500);
|
|
65419
65644
|
if (debug)
|
|
65420
|
-
|
|
65645
|
+
log3.debug(`Sending initial keystroke for Cursor setup to bypass "Press any key" prompt`);
|
|
65421
65646
|
try {
|
|
65422
65647
|
await pty.write("\r");
|
|
65423
65648
|
} catch (err) {
|
|
65424
|
-
|
|
65649
|
+
log3.warn(`Failed to send initial keystroke for Cursor: ${err}`);
|
|
65425
65650
|
}
|
|
65426
65651
|
}
|
|
65427
65652
|
const registered = await this.waitForAgentRegistration(name, 3e4, 500);
|
|
@@ -65432,7 +65657,7 @@ ${relayInstructions}`;
|
|
|
65432
65657
|
pid: pty.pid,
|
|
65433
65658
|
timeoutMs: 3e4
|
|
65434
65659
|
});
|
|
65435
|
-
|
|
65660
|
+
log3.error(tracedError.logMessage);
|
|
65436
65661
|
if (this.onClearSpawning) {
|
|
65437
65662
|
this.onClearSpawning(name);
|
|
65438
65663
|
}
|
|
@@ -65454,12 +65679,12 @@ ${relayInstructions}`;
|
|
|
65454
65679
|
const orchestrator = pty;
|
|
65455
65680
|
const ready = await orchestrator.waitUntilReadyForMessages(2e4, 100);
|
|
65456
65681
|
if (!ready) {
|
|
65457
|
-
|
|
65682
|
+
log3.debug(`Attempt ${attempt}/${maxRetries}: ${name} not ready for messages within timeout`);
|
|
65458
65683
|
if (attempt < maxRetries) {
|
|
65459
65684
|
await sleep2(retryDelayMs);
|
|
65460
65685
|
continue;
|
|
65461
65686
|
}
|
|
65462
|
-
|
|
65687
|
+
log3.error(`${name} failed to become ready after ${maxRetries} attempts - task may be lost`);
|
|
65463
65688
|
break;
|
|
65464
65689
|
}
|
|
65465
65690
|
} else if ("waitUntilCliReady" in pty) {
|
|
@@ -65469,13 +65694,13 @@ ${relayInstructions}`;
|
|
|
65469
65694
|
if (success) {
|
|
65470
65695
|
taskSent = true;
|
|
65471
65696
|
if (debug)
|
|
65472
|
-
|
|
65697
|
+
log3.debug(`Task injected to ${name} (attempt ${attempt})`);
|
|
65473
65698
|
break;
|
|
65474
65699
|
} else {
|
|
65475
|
-
throw new Error("Task injection returned false");
|
|
65700
|
+
throw new Error("Task injection returned false - delivery failed");
|
|
65476
65701
|
}
|
|
65477
65702
|
} catch (err) {
|
|
65478
|
-
|
|
65703
|
+
log3.debug(`Attempt ${attempt}/${maxRetries}: Error injecting task for ${name}: ${err.message}`);
|
|
65479
65704
|
if (attempt < maxRetries) {
|
|
65480
65705
|
await sleep2(retryDelayMs);
|
|
65481
65706
|
}
|
|
@@ -65488,7 +65713,18 @@ ${relayInstructions}`;
|
|
|
65488
65713
|
attempts: maxRetries,
|
|
65489
65714
|
taskLength: task.length
|
|
65490
65715
|
});
|
|
65491
|
-
|
|
65716
|
+
log3.error(`CRITICAL: ${tracedError.logMessage}`);
|
|
65717
|
+
await pty.stop();
|
|
65718
|
+
this.activeWorkers.delete(name);
|
|
65719
|
+
if (this.onClearSpawning) {
|
|
65720
|
+
this.onClearSpawning(name);
|
|
65721
|
+
}
|
|
65722
|
+
return {
|
|
65723
|
+
success: false,
|
|
65724
|
+
name,
|
|
65725
|
+
error: tracedError.userMessage,
|
|
65726
|
+
errorId: tracedError.errorId
|
|
65727
|
+
};
|
|
65492
65728
|
}
|
|
65493
65729
|
}
|
|
65494
65730
|
const workerInfo = {
|
|
@@ -65508,7 +65744,7 @@ ${relayInstructions}`;
|
|
|
65508
65744
|
this.saveWorkersMetadata();
|
|
65509
65745
|
const teamInfo = team ? ` [team: ${team}]` : "";
|
|
65510
65746
|
const shadowInfo = request.shadowOf ? ` [shadow of: ${request.shadowOf}]` : "";
|
|
65511
|
-
|
|
65747
|
+
log3.info(`Spawned ${name} (${cli})${teamInfo}${shadowInfo} [pid: ${pty.pid}]`);
|
|
65512
65748
|
return {
|
|
65513
65749
|
success: true,
|
|
65514
65750
|
name,
|
|
@@ -65520,9 +65756,9 @@ ${relayInstructions}`;
|
|
|
65520
65756
|
cli,
|
|
65521
65757
|
task: task?.substring(0, 100)
|
|
65522
65758
|
}, err instanceof Error ? err : void 0);
|
|
65523
|
-
|
|
65759
|
+
log3.error(tracedError.logMessage);
|
|
65524
65760
|
if (debug)
|
|
65525
|
-
|
|
65761
|
+
log3.debug("Full error", { error: err?.stack || String(err) });
|
|
65526
65762
|
if (this.onClearSpawning) {
|
|
65527
65763
|
this.onClearSpawning(name);
|
|
65528
65764
|
}
|
|
@@ -65569,12 +65805,12 @@ ${relayInstructions}`;
|
|
|
65569
65805
|
preferredShadowCli: shadow.command
|
|
65570
65806
|
});
|
|
65571
65807
|
} catch (err) {
|
|
65572
|
-
|
|
65808
|
+
log3.warn(`Shadow CLI selection failed for ${shadow.name}: ${err.message}`);
|
|
65573
65809
|
}
|
|
65574
65810
|
if (debug) {
|
|
65575
65811
|
const mode = shadowSelection?.mode ?? "unknown";
|
|
65576
65812
|
const cli = shadowSelection?.command ?? shadow.command ?? primary.command ?? "claude";
|
|
65577
|
-
|
|
65813
|
+
log3.debug(`spawnWithShadow: primary=${primary.name}, shadow=${shadow.name}, mode=${mode}, cli=${cli}, speakOn=${speakOn.join(",")}`);
|
|
65578
65814
|
}
|
|
65579
65815
|
const primaryResult = await this.spawn({
|
|
65580
65816
|
name: primary.name,
|
|
@@ -65591,7 +65827,7 @@ ${relayInstructions}`;
|
|
|
65591
65827
|
}
|
|
65592
65828
|
await sleep2(1e3);
|
|
65593
65829
|
if (shadowSelection?.mode === "subagent") {
|
|
65594
|
-
|
|
65830
|
+
log3.info(`Shadow ${shadow.name} will run as ${shadowSelection.cli} subagent inside ${primary.name} (no separate process)`);
|
|
65595
65831
|
return {
|
|
65596
65832
|
success: true,
|
|
65597
65833
|
primary: primaryResult,
|
|
@@ -65602,7 +65838,7 @@ ${relayInstructions}`;
|
|
|
65602
65838
|
};
|
|
65603
65839
|
}
|
|
65604
65840
|
if (!shadowSelection) {
|
|
65605
|
-
|
|
65841
|
+
log3.warn(`No authenticated shadow CLI available; ${primary.name} will run without a shadow`);
|
|
65606
65842
|
return {
|
|
65607
65843
|
success: true,
|
|
65608
65844
|
primary: primaryResult,
|
|
@@ -65618,7 +65854,7 @@ ${relayInstructions}`;
|
|
|
65618
65854
|
shadowSpeakOn: speakOn
|
|
65619
65855
|
});
|
|
65620
65856
|
if (!shadowResult.success) {
|
|
65621
|
-
|
|
65857
|
+
log3.warn(`Shadow agent ${shadow.name} failed to spawn, primary ${primary.name} continues without shadow`);
|
|
65622
65858
|
return {
|
|
65623
65859
|
success: true,
|
|
65624
65860
|
// Primary succeeded, overall operation is partial success
|
|
@@ -65627,7 +65863,7 @@ ${relayInstructions}`;
|
|
|
65627
65863
|
error: `Shadow spawn failed: ${shadowResult.error}`
|
|
65628
65864
|
};
|
|
65629
65865
|
}
|
|
65630
|
-
|
|
65866
|
+
log3.info(`Spawned pair: ${primary.name} with shadow ${shadow.name} (speakOn: ${speakOn.join(",")})`);
|
|
65631
65867
|
return {
|
|
65632
65868
|
success: true,
|
|
65633
65869
|
primary: primaryResult,
|
|
@@ -65640,7 +65876,7 @@ ${relayInstructions}`;
|
|
|
65640
65876
|
async release(name) {
|
|
65641
65877
|
const worker = this.activeWorkers.get(name);
|
|
65642
65878
|
if (!worker) {
|
|
65643
|
-
|
|
65879
|
+
log3.debug(`Worker ${name} not found`);
|
|
65644
65880
|
return false;
|
|
65645
65881
|
}
|
|
65646
65882
|
try {
|
|
@@ -65651,10 +65887,10 @@ ${relayInstructions}`;
|
|
|
65651
65887
|
}
|
|
65652
65888
|
this.activeWorkers.delete(name);
|
|
65653
65889
|
this.saveWorkersMetadata();
|
|
65654
|
-
|
|
65890
|
+
log3.info(`Released ${name}`);
|
|
65655
65891
|
return true;
|
|
65656
65892
|
} catch (err) {
|
|
65657
|
-
|
|
65893
|
+
log3.error(`Failed to release ${name}: ${err.message}`);
|
|
65658
65894
|
this.unbindListeners(worker.pty, worker.listeners);
|
|
65659
65895
|
this.activeWorkers.delete(name);
|
|
65660
65896
|
this.saveWorkersMetadata();
|
|
@@ -65747,15 +65983,15 @@ ${relayInstructions}`;
|
|
|
65747
65983
|
const connected = this.isAgentConnected(name);
|
|
65748
65984
|
const recentlySeen = this.isAgentRecentlySeen(name);
|
|
65749
65985
|
if (pollCount <= 3 || pollCount % 10 === 0) {
|
|
65750
|
-
|
|
65986
|
+
log3.info(`Registration poll #${pollCount} for ${name}: connected=${connected} recentlySeen=${recentlySeen} agentsPath=${this.agentsPath}`);
|
|
65751
65987
|
}
|
|
65752
65988
|
if (connected && recentlySeen) {
|
|
65753
|
-
|
|
65989
|
+
log3.info(`Agent ${name} registered after ${pollCount} polls`);
|
|
65754
65990
|
return true;
|
|
65755
65991
|
}
|
|
65756
65992
|
await sleep2(pollIntervalMs);
|
|
65757
65993
|
}
|
|
65758
|
-
|
|
65994
|
+
log3.info(`Registration timeout for ${name} after ${pollCount} polls`);
|
|
65759
65995
|
return false;
|
|
65760
65996
|
}
|
|
65761
65997
|
isAgentRegistered(name) {
|
|
@@ -65765,12 +66001,12 @@ ${relayInstructions}`;
|
|
|
65765
66001
|
const debug = process.env.DEBUG_SPAWN === "1";
|
|
65766
66002
|
if (!this.agentsPath) {
|
|
65767
66003
|
if (debug)
|
|
65768
|
-
|
|
66004
|
+
log3.debug(`isAgentConnected(${name}): no agentsPath`);
|
|
65769
66005
|
return false;
|
|
65770
66006
|
}
|
|
65771
66007
|
if (!import_node_fs14.default.existsSync(this.agentsPath)) {
|
|
65772
66008
|
if (debug)
|
|
65773
|
-
|
|
66009
|
+
log3.debug(`isAgentConnected(${name}): file not found: ${this.agentsPath}`);
|
|
65774
66010
|
return false;
|
|
65775
66011
|
}
|
|
65776
66012
|
try {
|
|
@@ -65779,14 +66015,14 @@ ${relayInstructions}`;
|
|
|
65779
66015
|
const updatedAt = typeof raw?.updatedAt === "number" ? raw.updatedAt : 0;
|
|
65780
66016
|
const isFresh = Date.now() - updatedAt <= _AgentSpawner.ONLINE_THRESHOLD_MS;
|
|
65781
66017
|
if (debug) {
|
|
65782
|
-
|
|
66018
|
+
log3.debug(`isAgentConnected(${name}): path=${this.agentsPath} agents=${agents.join(",")} updatedAt=${updatedAt} isFresh=${isFresh}`);
|
|
65783
66019
|
}
|
|
65784
66020
|
if (!isFresh)
|
|
65785
66021
|
return false;
|
|
65786
66022
|
const lowerName = name.toLowerCase();
|
|
65787
66023
|
return agents.some((a) => typeof a === "string" && a.toLowerCase() === lowerName);
|
|
65788
66024
|
} catch (err) {
|
|
65789
|
-
|
|
66025
|
+
log3.error("Failed to read connected-agents.json", { error: err.message, path: this.agentsPath });
|
|
65790
66026
|
return false;
|
|
65791
66027
|
}
|
|
65792
66028
|
}
|
|
@@ -65804,7 +66040,7 @@ ${relayInstructions}`;
|
|
|
65804
66040
|
return false;
|
|
65805
66041
|
return Date.now() - new Date(agent.lastSeen).getTime() <= _AgentSpawner.ONLINE_THRESHOLD_MS;
|
|
65806
66042
|
} catch (err) {
|
|
65807
|
-
|
|
66043
|
+
log3.error("Failed to read agents.json", { error: err.message });
|
|
65808
66044
|
return false;
|
|
65809
66045
|
}
|
|
65810
66046
|
}
|
|
@@ -65825,7 +66061,7 @@ ${relayInstructions}`;
|
|
|
65825
66061
|
}));
|
|
65826
66062
|
import_node_fs14.default.writeFileSync(this.workersPath, JSON.stringify({ workers }, null, 2));
|
|
65827
66063
|
} catch (err) {
|
|
65828
|
-
|
|
66064
|
+
log3.error("Failed to save workers metadata", { error: err.message });
|
|
65829
66065
|
}
|
|
65830
66066
|
}
|
|
65831
66067
|
/**
|
|
@@ -70262,7 +70498,7 @@ async function createStorageAdapter(dbPath, config2) {
|
|
|
70262
70498
|
var import_node_fs21 = __toESM(require("node:fs"), 1);
|
|
70263
70499
|
var import_node_path24 = __toESM(require("node:path"), 1);
|
|
70264
70500
|
init_logger();
|
|
70265
|
-
var
|
|
70501
|
+
var log4 = createLogger2("registry");
|
|
70266
70502
|
var AgentRegistry = class {
|
|
70267
70503
|
registryPath;
|
|
70268
70504
|
agents = /* @__PURE__ */ new Map();
|
|
@@ -70385,7 +70621,7 @@ var AgentRegistry = class {
|
|
|
70385
70621
|
if (lastSeenTime < cutoff) {
|
|
70386
70622
|
this.agents.delete(name);
|
|
70387
70623
|
removed++;
|
|
70388
|
-
|
|
70624
|
+
log4.info("Pruned stale agent", { name, lastSeen: record2.lastSeen });
|
|
70389
70625
|
}
|
|
70390
70626
|
}
|
|
70391
70627
|
if (removed > 0) {
|
|
@@ -70442,7 +70678,7 @@ var AgentRegistry = class {
|
|
|
70442
70678
|
this.agents.set(record2.name, record2);
|
|
70443
70679
|
}
|
|
70444
70680
|
} catch (err) {
|
|
70445
|
-
|
|
70681
|
+
log4.error("Failed to load agents.json", { error: String(err) });
|
|
70446
70682
|
}
|
|
70447
70683
|
}
|
|
70448
70684
|
save() {
|
|
@@ -70452,7 +70688,7 @@ var AgentRegistry = class {
|
|
|
70452
70688
|
import_node_fs21.default.writeFileSync(tempPath, data, "utf-8");
|
|
70453
70689
|
import_node_fs21.default.renameSync(tempPath, this.registryPath);
|
|
70454
70690
|
} catch (err) {
|
|
70455
|
-
|
|
70691
|
+
log4.error("Failed to write agents.json", { error: String(err) });
|
|
70456
70692
|
}
|
|
70457
70693
|
}
|
|
70458
70694
|
};
|
|
@@ -70476,7 +70712,7 @@ var import_node_zlib = require("node:zlib");
|
|
|
70476
70712
|
var import_node_util5 = require("node:util");
|
|
70477
70713
|
init_logger();
|
|
70478
70714
|
var gzipAsync = (0, import_node_util5.promisify)(import_node_zlib.gzip);
|
|
70479
|
-
var
|
|
70715
|
+
var log5 = createLogger2("sync-queue");
|
|
70480
70716
|
var DEFAULT_SYNC_QUEUE_CONFIG = {
|
|
70481
70717
|
cloudUrl: "https://agent-relay.com",
|
|
70482
70718
|
apiKey: "",
|
|
@@ -70532,7 +70768,7 @@ var SyncQueue = class {
|
|
|
70532
70768
|
} else if (!this.flushTimer) {
|
|
70533
70769
|
this.flushTimer = setTimeout(() => {
|
|
70534
70770
|
this.flush().catch((err) => {
|
|
70535
|
-
|
|
70771
|
+
log5.error("Timer flush failed", { error: String(err) });
|
|
70536
70772
|
});
|
|
70537
70773
|
}, this.config.batchDelayMs);
|
|
70538
70774
|
}
|
|
@@ -70594,7 +70830,7 @@ var SyncQueue = class {
|
|
|
70594
70830
|
if (attempt < this.config.maxRetries - 1) {
|
|
70595
70831
|
const delay = this.config.retryDelayMs * Math.pow(2, attempt);
|
|
70596
70832
|
if (this.config.verbose) {
|
|
70597
|
-
|
|
70833
|
+
log5.warn(`Sync attempt ${attempt + 1} failed, retrying in ${delay}ms`, {
|
|
70598
70834
|
error: lastError.message
|
|
70599
70835
|
});
|
|
70600
70836
|
}
|
|
@@ -70602,7 +70838,7 @@ var SyncQueue = class {
|
|
|
70602
70838
|
}
|
|
70603
70839
|
}
|
|
70604
70840
|
}
|
|
70605
|
-
|
|
70841
|
+
log5.error("Sync failed after retries, spilling to disk", {
|
|
70606
70842
|
count: messages.length,
|
|
70607
70843
|
error: lastError?.message
|
|
70608
70844
|
});
|
|
@@ -70646,7 +70882,7 @@ var SyncQueue = class {
|
|
|
70646
70882
|
contentEncoding = "gzip";
|
|
70647
70883
|
if (this.config.verbose) {
|
|
70648
70884
|
const ratio = ((1 - body.length / payloadBytes) * 100).toFixed(1);
|
|
70649
|
-
|
|
70885
|
+
log5.info(`Compressed ${payloadBytes} \u2192 ${body.length} bytes (${ratio}% reduction)`);
|
|
70650
70886
|
}
|
|
70651
70887
|
} else {
|
|
70652
70888
|
body = payloadJson;
|
|
@@ -70687,11 +70923,11 @@ var SyncQueue = class {
|
|
|
70687
70923
|
await fs25.writeFile(filepath, JSON.stringify(messages));
|
|
70688
70924
|
this.stats.spilledFiles++;
|
|
70689
70925
|
if (this.config.verbose) {
|
|
70690
|
-
|
|
70926
|
+
log5.info(`Spilled ${messages.length} messages to ${filename}`);
|
|
70691
70927
|
}
|
|
70692
70928
|
await this.cleanupSpillFiles();
|
|
70693
70929
|
} catch (err) {
|
|
70694
|
-
|
|
70930
|
+
log5.error("Failed to spill to disk", { error: String(err) });
|
|
70695
70931
|
}
|
|
70696
70932
|
}
|
|
70697
70933
|
/**
|
|
@@ -70715,23 +70951,23 @@ var SyncQueue = class {
|
|
|
70715
70951
|
recovered += messages.length;
|
|
70716
70952
|
this.stats.spilledFiles = Math.max(0, this.stats.spilledFiles - 1);
|
|
70717
70953
|
if (this.config.verbose) {
|
|
70718
|
-
|
|
70954
|
+
log5.info(`Recovered ${messages.length} messages from ${file}`);
|
|
70719
70955
|
}
|
|
70720
70956
|
} else {
|
|
70721
70957
|
failed += messages.length;
|
|
70722
70958
|
}
|
|
70723
70959
|
} catch (err) {
|
|
70724
|
-
|
|
70960
|
+
log5.warn(`Failed to recover ${file}`, { error: String(err) });
|
|
70725
70961
|
failed++;
|
|
70726
70962
|
}
|
|
70727
70963
|
}
|
|
70728
70964
|
} catch (err) {
|
|
70729
70965
|
if (err.code !== "ENOENT") {
|
|
70730
|
-
|
|
70966
|
+
log5.error("Failed to scan spill directory", { error: String(err) });
|
|
70731
70967
|
}
|
|
70732
70968
|
}
|
|
70733
70969
|
if (recovered > 0) {
|
|
70734
|
-
|
|
70970
|
+
log5.info(`Recovered ${recovered} messages from spill files`);
|
|
70735
70971
|
}
|
|
70736
70972
|
return { recovered, failed };
|
|
70737
70973
|
}
|
|
@@ -70749,7 +70985,7 @@ var SyncQueue = class {
|
|
|
70749
70985
|
});
|
|
70750
70986
|
}
|
|
70751
70987
|
if (this.config.verbose) {
|
|
70752
|
-
|
|
70988
|
+
log5.info(`Cleaned up ${toDelete.length} old spill files`);
|
|
70753
70989
|
}
|
|
70754
70990
|
}
|
|
70755
70991
|
} catch {
|
|
@@ -70799,7 +71035,7 @@ var SyncQueue = class {
|
|
|
70799
71035
|
// packages/utils/dist/git-remote.js
|
|
70800
71036
|
var fs26 = __toESM(require("node:fs"), 1);
|
|
70801
71037
|
var path27 = __toESM(require("node:path"), 1);
|
|
70802
|
-
var
|
|
71038
|
+
var import_node_child_process13 = require("node:child_process");
|
|
70803
71039
|
function parseGitRemoteUrl(url) {
|
|
70804
71040
|
if (!url)
|
|
70805
71041
|
return null;
|
|
@@ -70819,7 +71055,7 @@ function getGitRemoteUrl(workingDirectory, remoteName = "origin") {
|
|
|
70819
71055
|
if (!fs26.existsSync(gitDir)) {
|
|
70820
71056
|
return null;
|
|
70821
71057
|
}
|
|
70822
|
-
const result = (0,
|
|
71058
|
+
const result = (0, import_node_child_process13.execSync)(`git remote get-url ${remoteName}`, {
|
|
70823
71059
|
cwd: workingDirectory,
|
|
70824
71060
|
encoding: "utf-8",
|
|
70825
71061
|
timeout: 5e3,
|
|
@@ -70872,7 +71108,7 @@ function getRepoFullNameFromPath(workingDirectory) {
|
|
|
70872
71108
|
}
|
|
70873
71109
|
|
|
70874
71110
|
// packages/daemon/dist/cloud-sync.js
|
|
70875
|
-
var
|
|
71111
|
+
var log6 = createLogger2("cloud-sync");
|
|
70876
71112
|
var CloudSyncService = class extends import_events7.EventEmitter {
|
|
70877
71113
|
config;
|
|
70878
71114
|
heartbeatTimer;
|
|
@@ -70907,7 +71143,7 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
70907
71143
|
this.projectDirectory = this.config.projectDirectory || process.cwd();
|
|
70908
71144
|
this.repoFullName = getRepoFullNameFromPath(this.projectDirectory);
|
|
70909
71145
|
if (this.repoFullName) {
|
|
70910
|
-
|
|
71146
|
+
log6.info("Detected git repository", { repoFullName: this.repoFullName });
|
|
70911
71147
|
}
|
|
70912
71148
|
if (this.config.useOptimizedSync && this.config.apiKey) {
|
|
70913
71149
|
this.syncQueue = new SyncQueue({
|
|
@@ -70940,19 +71176,19 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
70940
71176
|
*/
|
|
70941
71177
|
async start() {
|
|
70942
71178
|
if (!this.config.enabled || !this.config.apiKey) {
|
|
70943
|
-
|
|
70944
|
-
|
|
71179
|
+
log6.info("Disabled (no API key configured)");
|
|
71180
|
+
log6.info("Run `agent-relay cloud link` to connect to cloud");
|
|
70945
71181
|
return;
|
|
70946
71182
|
}
|
|
70947
|
-
|
|
71183
|
+
log6.info("Starting cloud sync", { url: this.config.cloudUrl });
|
|
70948
71184
|
if (this.syncQueue) {
|
|
70949
71185
|
const { recovered, failed } = await this.syncQueue.recoverSpilledMessages();
|
|
70950
71186
|
if (recovered > 0 || failed > 0) {
|
|
70951
|
-
|
|
71187
|
+
log6.info("Recovered spilled messages", { recovered, failed });
|
|
70952
71188
|
}
|
|
70953
71189
|
}
|
|
70954
71190
|
await this.sendHeartbeat();
|
|
70955
|
-
this.heartbeatTimer = setInterval(() => this.sendHeartbeat().catch((err) =>
|
|
71191
|
+
this.heartbeatTimer = setInterval(() => this.sendHeartbeat().catch((err) => log6.error("Heartbeat failed", { error: String(err) })), this.config.heartbeatInterval);
|
|
70956
71192
|
this.connected = true;
|
|
70957
71193
|
this.emit("connected");
|
|
70958
71194
|
}
|
|
@@ -70979,7 +71215,7 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
70979
71215
|
this.localAgents.set(agent.name, agent);
|
|
70980
71216
|
}
|
|
70981
71217
|
if (this.connected) {
|
|
70982
|
-
this.syncAgents().catch((err) =>
|
|
71218
|
+
this.syncAgents().catch((err) => log6.error("Agent sync failed", { error: String(err) }));
|
|
70983
71219
|
}
|
|
70984
71220
|
}
|
|
70985
71221
|
/**
|
|
@@ -71046,7 +71282,7 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71046
71282
|
}).finally(() => clearTimeout(timeoutId));
|
|
71047
71283
|
if (!response.ok) {
|
|
71048
71284
|
if (response.status === 401) {
|
|
71049
|
-
|
|
71285
|
+
log6.error("Invalid API key. Run `agent-relay cloud link` to re-authenticate.");
|
|
71050
71286
|
this.stop();
|
|
71051
71287
|
return;
|
|
71052
71288
|
}
|
|
@@ -71067,18 +71303,18 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71067
71303
|
} catch (error2) {
|
|
71068
71304
|
const errorMessage = String(error2);
|
|
71069
71305
|
if (error2 instanceof Error && error2.name === "AbortError") {
|
|
71070
|
-
|
|
71306
|
+
log6.error("Heartbeat timeout (10s)", { url: this.config.cloudUrl });
|
|
71071
71307
|
} else if (errorMessage.includes("fetch failed") || errorMessage.includes("ECONNREFUSED")) {
|
|
71072
|
-
|
|
71308
|
+
log6.error("Heartbeat network error - cloud server unreachable", {
|
|
71073
71309
|
url: this.config.cloudUrl,
|
|
71074
71310
|
error: errorMessage
|
|
71075
71311
|
});
|
|
71076
71312
|
} else if (errorMessage.includes("ENOTFOUND") || errorMessage.includes("getaddrinfo")) {
|
|
71077
|
-
|
|
71313
|
+
log6.error("Heartbeat DNS error - cannot resolve cloud server", {
|
|
71078
71314
|
url: this.config.cloudUrl
|
|
71079
71315
|
});
|
|
71080
71316
|
} else {
|
|
71081
|
-
|
|
71317
|
+
log6.error("Heartbeat error", { error: errorMessage });
|
|
71082
71318
|
}
|
|
71083
71319
|
this.emit("error", error2);
|
|
71084
71320
|
}
|
|
@@ -71168,14 +71404,14 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71168
71404
|
*/
|
|
71169
71405
|
setStorage(storage) {
|
|
71170
71406
|
this.storage = storage;
|
|
71171
|
-
|
|
71407
|
+
log6.info("Storage adapter configured for message sync");
|
|
71172
71408
|
}
|
|
71173
71409
|
/**
|
|
71174
71410
|
* Set the metrics provider for agent metrics sync
|
|
71175
71411
|
*/
|
|
71176
71412
|
setMetricsProvider(provider) {
|
|
71177
71413
|
this.metricsProvider = provider;
|
|
71178
|
-
|
|
71414
|
+
log6.info("Metrics provider configured for agent metrics sync");
|
|
71179
71415
|
}
|
|
71180
71416
|
/**
|
|
71181
71417
|
* Push agent metrics to cloud monitoring API.
|
|
@@ -71222,11 +71458,11 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71222
71458
|
}
|
|
71223
71459
|
const result = await response.json();
|
|
71224
71460
|
if (result.recorded > 0) {
|
|
71225
|
-
|
|
71461
|
+
log6.info(`Pushed ${result.recorded} agent metrics to cloud`);
|
|
71226
71462
|
}
|
|
71227
71463
|
return { recorded: result.recorded };
|
|
71228
71464
|
} catch (error2) {
|
|
71229
|
-
|
|
71465
|
+
log6.error("Failed to push agent metrics", { error: String(error2) });
|
|
71230
71466
|
return null;
|
|
71231
71467
|
}
|
|
71232
71468
|
}
|
|
@@ -71257,10 +71493,10 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71257
71493
|
throw new Error(`Session create failed: ${response.status}`);
|
|
71258
71494
|
}
|
|
71259
71495
|
const result = await response.json();
|
|
71260
|
-
|
|
71496
|
+
log6.info(`Created session ${result.sessionId.substring(0, 8)} for ${agentName}`);
|
|
71261
71497
|
return result.sessionId;
|
|
71262
71498
|
} catch (error2) {
|
|
71263
|
-
|
|
71499
|
+
log6.error("Failed to create session", { agentName, error: String(error2) });
|
|
71264
71500
|
return null;
|
|
71265
71501
|
}
|
|
71266
71502
|
}
|
|
@@ -71288,10 +71524,10 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71288
71524
|
throw new Error(`Summary add failed: ${response.status}`);
|
|
71289
71525
|
}
|
|
71290
71526
|
const result = await response.json();
|
|
71291
|
-
|
|
71527
|
+
log6.info(`Added summary for ${agentName}: ${summary.currentTask || "no task"}`);
|
|
71292
71528
|
return result.summaryId;
|
|
71293
71529
|
} catch (error2) {
|
|
71294
|
-
|
|
71530
|
+
log6.error("Failed to add summary", { sessionId, agentName, error: String(error2) });
|
|
71295
71531
|
return null;
|
|
71296
71532
|
}
|
|
71297
71533
|
}
|
|
@@ -71317,10 +71553,10 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71317
71553
|
if (!response.ok) {
|
|
71318
71554
|
throw new Error(`Session end failed: ${response.status}`);
|
|
71319
71555
|
}
|
|
71320
|
-
|
|
71556
|
+
log6.info(`Ended session ${sessionId.substring(0, 8)}: ${endMarker?.summary || "no summary"}`);
|
|
71321
71557
|
return true;
|
|
71322
71558
|
} catch (error2) {
|
|
71323
|
-
|
|
71559
|
+
log6.error("Failed to end session", { sessionId, error: String(error2) });
|
|
71324
71560
|
return false;
|
|
71325
71561
|
}
|
|
71326
71562
|
}
|
|
@@ -71409,11 +71645,11 @@ var CloudSyncService = class extends import_events7.EventEmitter {
|
|
|
71409
71645
|
this.lastMessageSyncTs = Math.max(...messages.map((m) => m.ts));
|
|
71410
71646
|
}
|
|
71411
71647
|
if (result.synced > 0) {
|
|
71412
|
-
|
|
71648
|
+
log6.info(`Synced ${result.synced} messages to cloud`, { duplicates: result.duplicates });
|
|
71413
71649
|
}
|
|
71414
71650
|
return result;
|
|
71415
71651
|
} catch (error2) {
|
|
71416
|
-
|
|
71652
|
+
log6.error("Message sync error", { error: String(error2) });
|
|
71417
71653
|
return { synced: 0, duplicates: 0 };
|
|
71418
71654
|
} finally {
|
|
71419
71655
|
this.messageSyncInProgress = false;
|
|
@@ -71438,7 +71674,7 @@ function createCloudPersistenceHandler(cloudSync, workspaceId) {
|
|
|
71438
71674
|
sessionId = newSessionId;
|
|
71439
71675
|
agentSessions.set(agentName, sessionId);
|
|
71440
71676
|
} else {
|
|
71441
|
-
|
|
71677
|
+
log6.warn(`Failed to create session for ${agentName}, skipping summary`);
|
|
71442
71678
|
return;
|
|
71443
71679
|
}
|
|
71444
71680
|
}
|
|
@@ -71450,7 +71686,7 @@ function createCloudPersistenceHandler(cloudSync, workspaceId) {
|
|
|
71450
71686
|
await cloudSync.endSession(sessionId, event.marker);
|
|
71451
71687
|
agentSessions.delete(agentName);
|
|
71452
71688
|
} else {
|
|
71453
|
-
|
|
71689
|
+
log6.warn(`No session found for ${agentName} on session-end`);
|
|
71454
71690
|
}
|
|
71455
71691
|
},
|
|
71456
71692
|
destroy() {
|
|
@@ -74347,15 +74583,15 @@ var Orchestrator = class extends import_events8.EventEmitter {
|
|
|
74347
74583
|
*/
|
|
74348
74584
|
getGitInfo(workspacePath) {
|
|
74349
74585
|
try {
|
|
74350
|
-
const { execSync:
|
|
74351
|
-
const branch =
|
|
74586
|
+
const { execSync: execSync10 } = require("child_process");
|
|
74587
|
+
const branch = execSync10("git branch --show-current", {
|
|
74352
74588
|
cwd: workspacePath,
|
|
74353
74589
|
encoding: "utf8",
|
|
74354
74590
|
stdio: ["pipe", "pipe", "pipe"]
|
|
74355
74591
|
}).trim();
|
|
74356
74592
|
let remote;
|
|
74357
74593
|
try {
|
|
74358
|
-
remote =
|
|
74594
|
+
remote = execSync10("git remote get-url origin", {
|
|
74359
74595
|
cwd: workspacePath,
|
|
74360
74596
|
encoding: "utf8",
|
|
74361
74597
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -76839,7 +77075,7 @@ function manageContext(compactor, messages) {
|
|
|
76839
77075
|
}
|
|
76840
77076
|
|
|
76841
77077
|
// packages/daemon/dist/cli-auth.js
|
|
76842
|
-
var
|
|
77078
|
+
var import_node_child_process14 = require("node:child_process");
|
|
76843
77079
|
var fs33 = __toESM(require("fs/promises"), 1);
|
|
76844
77080
|
var os15 = __toESM(require("os"), 1);
|
|
76845
77081
|
var import_node_path27 = require("node:path");
|
|
@@ -76956,7 +77192,7 @@ async function startCLIAuth(provider, options = {}) {
|
|
|
76956
77192
|
config2.command,
|
|
76957
77193
|
...args
|
|
76958
77194
|
];
|
|
76959
|
-
const proc = (0,
|
|
77195
|
+
const proc = (0, import_node_child_process14.spawn)(relayPtyPath, relayArgs, {
|
|
76960
77196
|
cwd: process.cwd(),
|
|
76961
77197
|
env: {
|
|
76962
77198
|
...process.env,
|
|
@@ -78198,11 +78434,11 @@ var HookRegistry = class {
|
|
|
78198
78434
|
};
|
|
78199
78435
|
|
|
78200
78436
|
// packages/trajectory/dist/integration.js
|
|
78201
|
-
var
|
|
78437
|
+
var import_node_child_process15 = require("node:child_process");
|
|
78202
78438
|
async function runTrail2(args) {
|
|
78203
78439
|
return new Promise((resolve5) => {
|
|
78204
78440
|
const trajectoryEnv = getTrajectoryEnvVars();
|
|
78205
|
-
const proc = (0,
|
|
78441
|
+
const proc = (0, import_node_child_process15.spawn)("trail", args, {
|
|
78206
78442
|
cwd: getProjectPaths().projectRoot,
|
|
78207
78443
|
env: { ...process.env, ...trajectoryEnv },
|
|
78208
78444
|
stdio: ["pipe", "pipe", "pipe"]
|
|
@@ -78473,7 +78709,7 @@ var TrajectoryIntegration2 = class {
|
|
|
78473
78709
|
*/
|
|
78474
78710
|
isTrailInstalledSync() {
|
|
78475
78711
|
try {
|
|
78476
|
-
(0,
|
|
78712
|
+
(0, import_node_child_process15.execSync)("which trail", { stdio: "pipe" });
|
|
78477
78713
|
return true;
|
|
78478
78714
|
} catch {
|
|
78479
78715
|
return false;
|