@buildautomaton/cli 0.1.5 → 0.1.7
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/dist/cli.js +1044 -318
- package/dist/cli.js.map +4 -4
- package/dist/index.js +1056 -334
- package/dist/index.js.map +4 -4
- package/package.json +3 -2
package/dist/cli.js
CHANGED
|
@@ -974,7 +974,7 @@ var require_command = __commonJS({
|
|
|
974
974
|
var EventEmitter2 = __require("node:events").EventEmitter;
|
|
975
975
|
var childProcess = __require("node:child_process");
|
|
976
976
|
var path25 = __require("node:path");
|
|
977
|
-
var
|
|
977
|
+
var fs21 = __require("node:fs");
|
|
978
978
|
var process2 = __require("node:process");
|
|
979
979
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
980
980
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1907,10 +1907,10 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1907
1907
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1908
1908
|
function findFile(baseDir, baseName) {
|
|
1909
1909
|
const localBin = path25.resolve(baseDir, baseName);
|
|
1910
|
-
if (
|
|
1910
|
+
if (fs21.existsSync(localBin)) return localBin;
|
|
1911
1911
|
if (sourceExt.includes(path25.extname(baseName))) return void 0;
|
|
1912
1912
|
const foundExt = sourceExt.find(
|
|
1913
|
-
(ext) =>
|
|
1913
|
+
(ext) => fs21.existsSync(`${localBin}${ext}`)
|
|
1914
1914
|
);
|
|
1915
1915
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1916
1916
|
return void 0;
|
|
@@ -1922,7 +1922,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1922
1922
|
if (this._scriptPath) {
|
|
1923
1923
|
let resolvedScriptPath;
|
|
1924
1924
|
try {
|
|
1925
|
-
resolvedScriptPath =
|
|
1925
|
+
resolvedScriptPath = fs21.realpathSync(this._scriptPath);
|
|
1926
1926
|
} catch (err) {
|
|
1927
1927
|
resolvedScriptPath = this._scriptPath;
|
|
1928
1928
|
}
|
|
@@ -7426,12 +7426,12 @@ var require_src2 = __commonJS({
|
|
|
7426
7426
|
function check2(path25, isFile, isDirectory) {
|
|
7427
7427
|
log2(`checking %s`, path25);
|
|
7428
7428
|
try {
|
|
7429
|
-
const
|
|
7430
|
-
if (
|
|
7429
|
+
const stat2 = fs_1.statSync(path25);
|
|
7430
|
+
if (stat2.isFile() && isFile) {
|
|
7431
7431
|
log2(`[OK] path represents a file`);
|
|
7432
7432
|
return true;
|
|
7433
7433
|
}
|
|
7434
|
-
if (
|
|
7434
|
+
if (stat2.isDirectory() && isDirectory) {
|
|
7435
7435
|
log2(`[OK] path represents a directory`);
|
|
7436
7436
|
return true;
|
|
7437
7437
|
}
|
|
@@ -25047,7 +25047,7 @@ var init_acp = __esm({
|
|
|
25047
25047
|
});
|
|
25048
25048
|
|
|
25049
25049
|
// src/cli.ts
|
|
25050
|
-
import * as
|
|
25050
|
+
import * as fs20 from "node:fs";
|
|
25051
25051
|
import * as path24 from "node:path";
|
|
25052
25052
|
|
|
25053
25053
|
// ../../node_modules/.pnpm/commander@12.1.0/node_modules/commander/esm.mjs
|
|
@@ -25179,13 +25179,31 @@ var wrapper_default = import_websocket.default;
|
|
|
25179
25179
|
|
|
25180
25180
|
// src/bridge/connection/create-ws-bridge.ts
|
|
25181
25181
|
import https from "node:https";
|
|
25182
|
+
|
|
25183
|
+
// src/net/apply-cli-outbound-network-prefs.ts
|
|
25184
|
+
import dns from "node:dns";
|
|
25185
|
+
var applied = false;
|
|
25186
|
+
function applyCliOutboundNetworkPreferences() {
|
|
25187
|
+
if (applied) return;
|
|
25188
|
+
applied = true;
|
|
25189
|
+
try {
|
|
25190
|
+
dns.setDefaultResultOrder("ipv4first");
|
|
25191
|
+
} catch {
|
|
25192
|
+
}
|
|
25193
|
+
}
|
|
25194
|
+
|
|
25195
|
+
// src/bridge/connection/create-ws-bridge.ts
|
|
25182
25196
|
var BRIDGE_AUTH_ERROR_HEADER = "x-bridge-auth-error";
|
|
25183
25197
|
var BRIDGE_AUTH_ERROR_TOKEN_INVALID = "token_invalid";
|
|
25184
25198
|
function createWsBridge(options) {
|
|
25185
25199
|
const { url: url2, onMessage, onOpen, onClose, onError: onError2, onAuthInvalid, clientPingIntervalMs } = options;
|
|
25186
|
-
|
|
25200
|
+
applyCliOutboundNetworkPreferences();
|
|
25201
|
+
const wsOptions = {
|
|
25202
|
+
perMessageDeflate: false,
|
|
25203
|
+
family: 4
|
|
25204
|
+
};
|
|
25187
25205
|
if (url2.startsWith("wss://")) {
|
|
25188
|
-
wsOptions.agent = new https.Agent({ rejectUnauthorized: false });
|
|
25206
|
+
wsOptions.agent = new https.Agent({ rejectUnauthorized: false, family: 4 });
|
|
25189
25207
|
}
|
|
25190
25208
|
const ws = new wrapper_default(url2, wsOptions);
|
|
25191
25209
|
let clientPingTimer = null;
|
|
@@ -25408,7 +25426,7 @@ function beginMainBridgeDeferredDisconnect(state, code, reason, log2, willReconn
|
|
|
25408
25426
|
});
|
|
25409
25427
|
}
|
|
25410
25428
|
function clearMainBridgeReconnectQuietOnOpen(state, log2) {
|
|
25411
|
-
clearReconnectQuietOnSuccessfulConnection(state.mainQuiet, log2, "
|
|
25429
|
+
clearReconnectQuietOnSuccessfulConnection(state.mainQuiet, log2, "Bridge connection restored.");
|
|
25412
25430
|
}
|
|
25413
25431
|
function scheduleMainBridgeReconnect(state, connect, log2) {
|
|
25414
25432
|
if (state.closedByUser || state.currentWs != null) return;
|
|
@@ -25445,7 +25463,7 @@ function clearFirehoseReconnectQuietOnOpen(ctx, log2) {
|
|
|
25445
25463
|
clearReconnectQuietOnSuccessfulConnection(
|
|
25446
25464
|
ctx.firehoseQuiet,
|
|
25447
25465
|
log2,
|
|
25448
|
-
|
|
25466
|
+
"Preview tunnel restored (local HTTP proxy and dev logs)."
|
|
25449
25467
|
);
|
|
25450
25468
|
}
|
|
25451
25469
|
|
|
@@ -30256,34 +30274,31 @@ function reportGitRepos(getWs, log2) {
|
|
|
30256
30274
|
|
|
30257
30275
|
// src/bridge/connection/close-bridge-connection.ts
|
|
30258
30276
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
30259
|
-
log2
|
|
30277
|
+
const say = log2 ?? logImmediate;
|
|
30278
|
+
say("Cleaning up connections\u2026");
|
|
30260
30279
|
await new Promise((resolve15) => setImmediate(resolve15));
|
|
30261
|
-
if (devServerManager) {
|
|
30262
|
-
log2?.("Requesting dev server processes to stop\u2026");
|
|
30263
|
-
await devServerManager.shutdownAllGraceful();
|
|
30264
|
-
}
|
|
30265
30280
|
state.closedByUser = true;
|
|
30266
30281
|
clearReconnectQuietTimer(state.mainQuiet);
|
|
30267
30282
|
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
30268
30283
|
if (state.reconnectTimeout != null) {
|
|
30269
|
-
|
|
30284
|
+
say("Cancelling bridge reconnect timer\u2026");
|
|
30270
30285
|
clearTimeout(state.reconnectTimeout);
|
|
30271
30286
|
state.reconnectTimeout = null;
|
|
30272
30287
|
}
|
|
30273
30288
|
if (state.firehoseReconnectTimeout != null) {
|
|
30274
|
-
|
|
30289
|
+
say("Cancelling preview tunnel reconnect timer\u2026");
|
|
30275
30290
|
clearTimeout(state.firehoseReconnectTimeout);
|
|
30276
30291
|
state.firehoseReconnectTimeout = null;
|
|
30277
30292
|
}
|
|
30278
30293
|
if (state.firehoseHandle) {
|
|
30279
|
-
|
|
30294
|
+
say("Closing preview tunnel (local HTTP proxy and dev logs)\u2026");
|
|
30280
30295
|
state.firehoseHandle.close();
|
|
30281
30296
|
state.firehoseHandle = null;
|
|
30282
30297
|
}
|
|
30283
|
-
|
|
30298
|
+
say("Disconnecting local agent\u2026");
|
|
30284
30299
|
acpManager.disconnect();
|
|
30285
30300
|
if (state.currentWs) {
|
|
30286
|
-
|
|
30301
|
+
say("Closing bridge connection to the cloud\u2026");
|
|
30287
30302
|
state.currentWs.removeAllListeners();
|
|
30288
30303
|
const wsState = state.currentWs.readyState;
|
|
30289
30304
|
if (wsState === 1 || wsState === 2) {
|
|
@@ -30296,12 +30311,295 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
|
|
|
30296
30311
|
}
|
|
30297
30312
|
state.currentWs = null;
|
|
30298
30313
|
}
|
|
30314
|
+
if (devServerManager) {
|
|
30315
|
+
say("Stopping local dev server processes\u2026");
|
|
30316
|
+
await devServerManager.shutdownAllGraceful();
|
|
30317
|
+
}
|
|
30318
|
+
say("Shutdown complete.");
|
|
30319
|
+
}
|
|
30320
|
+
|
|
30321
|
+
// ../types/dist/index.js
|
|
30322
|
+
init_zod();
|
|
30323
|
+
init_zod();
|
|
30324
|
+
init_zod();
|
|
30325
|
+
init_zod();
|
|
30326
|
+
init_zod();
|
|
30327
|
+
init_zod();
|
|
30328
|
+
init_zod();
|
|
30329
|
+
init_zod();
|
|
30330
|
+
init_zod();
|
|
30331
|
+
init_zod();
|
|
30332
|
+
init_zod();
|
|
30333
|
+
init_zod();
|
|
30334
|
+
var WorkItemStatusSchema = external_exports.enum(["backlog", "in-progress", "completed"]);
|
|
30335
|
+
var WorkItemProgressSchema = external_exports.object({
|
|
30336
|
+
remainingCriteria: external_exports.array(external_exports.string()).default([]),
|
|
30337
|
+
openQuestions: external_exports.array(external_exports.string()).default([]),
|
|
30338
|
+
assignedTo: external_exports.enum(["agent", "human-product", "human-expert"]).optional()
|
|
30339
|
+
});
|
|
30340
|
+
var ChangeSchema = external_exports.object({
|
|
30341
|
+
id: external_exports.string(),
|
|
30342
|
+
description: external_exports.string(),
|
|
30343
|
+
buildingBlockId: external_exports.string(),
|
|
30344
|
+
buildingBlockType: external_exports.enum(["function", "workflow", "connector", "ui-component", "app-fragment", "application", "project"]),
|
|
30345
|
+
action: external_exports.enum(["create", "update", "split", "combine"])
|
|
30346
|
+
});
|
|
30347
|
+
var CompletionCriterionSchema = external_exports.object({
|
|
30348
|
+
id: external_exports.string(),
|
|
30349
|
+
description: external_exports.string(),
|
|
30350
|
+
type: external_exports.enum(["write-code", "write-tests", "verify-tests", "other"]),
|
|
30351
|
+
verified: external_exports.boolean().default(false)
|
|
30352
|
+
});
|
|
30353
|
+
var WorkItemPrioritySchema = external_exports.enum(["low", "medium", "high", "critical"]);
|
|
30354
|
+
var IterationPhaseSchema = external_exports.enum(["analysis", "implementation", "verify", "reprioritize", "completed"]);
|
|
30355
|
+
var WorkItemDependencySchema = external_exports.object({
|
|
30356
|
+
type: external_exports.enum(["work-item"]),
|
|
30357
|
+
id: external_exports.string()
|
|
30358
|
+
});
|
|
30359
|
+
var WorkItemSchema = external_exports.object({
|
|
30360
|
+
id: external_exports.string(),
|
|
30361
|
+
sessionId: external_exports.string().optional(),
|
|
30362
|
+
summary: external_exports.string().optional(),
|
|
30363
|
+
description: external_exports.string(),
|
|
30364
|
+
status: WorkItemStatusSchema,
|
|
30365
|
+
buildingBlockId: external_exports.string().optional(),
|
|
30366
|
+
buildingBlockType: external_exports.enum(["function", "workflow", "connector", "ui-component", "app-fragment", "application", "project"]),
|
|
30367
|
+
changes: external_exports.array(ChangeSchema).default([]),
|
|
30368
|
+
completionCriteria: external_exports.array(CompletionCriterionSchema).default([]),
|
|
30369
|
+
priority: WorkItemPrioritySchema.default("medium"),
|
|
30370
|
+
dependencies: external_exports.array(WorkItemDependencySchema).default([]),
|
|
30371
|
+
assignedToUserId: external_exports.string().optional()
|
|
30372
|
+
});
|
|
30373
|
+
var UserWorkspaceProfileSchema = external_exports.object({
|
|
30374
|
+
id: external_exports.string(),
|
|
30375
|
+
workspaceId: external_exports.string(),
|
|
30376
|
+
userId: external_exports.string(),
|
|
30377
|
+
roleDescription: external_exports.string().optional(),
|
|
30378
|
+
expertiseAreas: external_exports.array(external_exports.string()),
|
|
30379
|
+
preferences: external_exports.record(external_exports.unknown()).optional(),
|
|
30380
|
+
learnings: external_exports.array(external_exports.string())
|
|
30381
|
+
});
|
|
30382
|
+
var WorkspaceOwnerInfoSchema = external_exports.object({
|
|
30383
|
+
ownerId: external_exports.string(),
|
|
30384
|
+
ownerName: external_exports.string().optional(),
|
|
30385
|
+
ownerEmail: external_exports.string().optional(),
|
|
30386
|
+
ownerProfilePictureUrl: external_exports.string().optional()
|
|
30387
|
+
});
|
|
30388
|
+
var WorkspaceRuntimeEntrySchema = external_exports.object({
|
|
30389
|
+
workspaceId: external_exports.string(),
|
|
30390
|
+
path: external_exports.string(),
|
|
30391
|
+
name: external_exports.string().optional(),
|
|
30392
|
+
owner: WorkspaceOwnerInfoSchema.optional(),
|
|
30393
|
+
isOwner: external_exports.boolean().optional()
|
|
30394
|
+
});
|
|
30395
|
+
var ProjectContextSchema = external_exports.object({
|
|
30396
|
+
projectId: external_exports.string(),
|
|
30397
|
+
context: external_exports.record(external_exports.unknown()).default({}),
|
|
30398
|
+
updatedAt: external_exports.string()
|
|
30399
|
+
});
|
|
30400
|
+
var WebSocketMessageTypeSchema = external_exports.enum([
|
|
30401
|
+
"plan-update",
|
|
30402
|
+
"work-item-update",
|
|
30403
|
+
"work-item-added",
|
|
30404
|
+
"work-item-removed",
|
|
30405
|
+
"project-processing-start",
|
|
30406
|
+
"project-processing-update",
|
|
30407
|
+
"project-processing-complete",
|
|
30408
|
+
"project-processing-error",
|
|
30409
|
+
"file-tool-request",
|
|
30410
|
+
"file-tool-response",
|
|
30411
|
+
"file-generated"
|
|
30412
|
+
]);
|
|
30413
|
+
var WebSocketMessageSchema = external_exports.object({
|
|
30414
|
+
type: WebSocketMessageTypeSchema,
|
|
30415
|
+
contextId: external_exports.string().optional(),
|
|
30416
|
+
data: external_exports.any().optional(),
|
|
30417
|
+
error: external_exports.string().optional()
|
|
30418
|
+
});
|
|
30419
|
+
var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
|
|
30420
|
+
var CheckpointSummarySchema = external_exports.object({
|
|
30421
|
+
id: external_exports.string(),
|
|
30422
|
+
kind: CheckpointKindSchema,
|
|
30423
|
+
/** ISO date for daily (YYYY-MM-DD), ISO week for weekly, null for overall */
|
|
30424
|
+
periodKey: external_exports.string().nullable(),
|
|
30425
|
+
summary: external_exports.string(),
|
|
30426
|
+
createdAt: external_exports.string(),
|
|
30427
|
+
updatedAt: external_exports.string()
|
|
30428
|
+
});
|
|
30429
|
+
var ThreadMetaSchema = external_exports.object({
|
|
30430
|
+
threadId: external_exports.string(),
|
|
30431
|
+
workspaceId: external_exports.string(),
|
|
30432
|
+
/** External source (e.g. slack, discord); null if internal-only */
|
|
30433
|
+
externalSource: external_exports.string().nullable(),
|
|
30434
|
+
/** Id in the external system (e.g. channel_id + thread_ts) */
|
|
30435
|
+
externalId: external_exports.string().nullable(),
|
|
30436
|
+
title: external_exports.string().optional(),
|
|
30437
|
+
createdAt: external_exports.string(),
|
|
30438
|
+
updatedAt: external_exports.string()
|
|
30439
|
+
});
|
|
30440
|
+
var ThreadMessageSchema = external_exports.object({
|
|
30441
|
+
messageId: external_exports.string(),
|
|
30442
|
+
threadId: external_exports.string(),
|
|
30443
|
+
/** Role: user, assistant, system */
|
|
30444
|
+
role: external_exports.enum(["user", "assistant", "system"]),
|
|
30445
|
+
content: external_exports.string(),
|
|
30446
|
+
/** Optional reference to a ContentItem (e.g. doc, Notion page) */
|
|
30447
|
+
contentItemId: external_exports.string().nullable(),
|
|
30448
|
+
/** External message id if synced from external chat */
|
|
30449
|
+
externalId: external_exports.string().nullable(),
|
|
30450
|
+
createdAt: external_exports.string(),
|
|
30451
|
+
updatedAt: external_exports.string()
|
|
30452
|
+
});
|
|
30453
|
+
var ThreadCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
30454
|
+
threadId: external_exports.string()
|
|
30455
|
+
});
|
|
30456
|
+
var ContentSourceSchema = external_exports.enum(["notion", "doc", "slack_thread", "other"]);
|
|
30457
|
+
var ContentItemMetaSchema = external_exports.object({
|
|
30458
|
+
contentId: external_exports.string(),
|
|
30459
|
+
workspaceId: external_exports.string(),
|
|
30460
|
+
source: ContentSourceSchema,
|
|
30461
|
+
/** Id in the external system (e.g. Notion page id, doc url) */
|
|
30462
|
+
externalId: external_exports.string(),
|
|
30463
|
+
/** If source is slack_thread, points to Thread DO id */
|
|
30464
|
+
threadId: external_exports.string().nullable(),
|
|
30465
|
+
title: external_exports.string().optional(),
|
|
30466
|
+
createdAt: external_exports.string(),
|
|
30467
|
+
updatedAt: external_exports.string()
|
|
30468
|
+
});
|
|
30469
|
+
var ContentStorageRefSchema = external_exports.object({
|
|
30470
|
+
storageKey: external_exports.string(),
|
|
30471
|
+
/** Optional: mime type or format hint */
|
|
30472
|
+
contentType: external_exports.string().optional()
|
|
30473
|
+
});
|
|
30474
|
+
var ContentCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
30475
|
+
contentId: external_exports.string()
|
|
30476
|
+
});
|
|
30477
|
+
var StoryMetaSchema = external_exports.object({
|
|
30478
|
+
storyId: external_exports.string(),
|
|
30479
|
+
workspaceId: external_exports.string(),
|
|
30480
|
+
title: external_exports.string(),
|
|
30481
|
+
/** feature | bug | epic */
|
|
30482
|
+
kind: external_exports.enum(["feature", "bug", "epic"]).default("feature"),
|
|
30483
|
+
createdAt: external_exports.string(),
|
|
30484
|
+
updatedAt: external_exports.string()
|
|
30485
|
+
});
|
|
30486
|
+
var StoryContentItemRefSchema = external_exports.object({
|
|
30487
|
+
id: external_exports.string(),
|
|
30488
|
+
storyId: external_exports.string(),
|
|
30489
|
+
contentItemId: external_exports.string(),
|
|
30490
|
+
/** Snapshot summary when added to story (or updated) */
|
|
30491
|
+
summary: external_exports.string(),
|
|
30492
|
+
orderIndex: external_exports.number().default(0),
|
|
30493
|
+
createdAt: external_exports.string(),
|
|
30494
|
+
updatedAt: external_exports.string()
|
|
30495
|
+
});
|
|
30496
|
+
var StoryCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
30497
|
+
storyId: external_exports.string()
|
|
30498
|
+
});
|
|
30499
|
+
var SessionMetaSchema = external_exports.object({
|
|
30500
|
+
sessionId: external_exports.string(),
|
|
30501
|
+
workspaceId: external_exports.string(),
|
|
30502
|
+
title: external_exports.string().optional(),
|
|
30503
|
+
createdAt: external_exports.string(),
|
|
30504
|
+
updatedAt: external_exports.string()
|
|
30505
|
+
});
|
|
30506
|
+
var SessionPromptSchema = external_exports.object({
|
|
30507
|
+
id: external_exports.string(),
|
|
30508
|
+
sessionId: external_exports.string(),
|
|
30509
|
+
/** text | resource */
|
|
30510
|
+
type: external_exports.enum(["text", "resource"]).default("text"),
|
|
30511
|
+
text: external_exports.string().optional(),
|
|
30512
|
+
resourceUri: external_exports.string().optional(),
|
|
30513
|
+
createdAt: external_exports.string()
|
|
30514
|
+
});
|
|
30515
|
+
var SessionResponseSchema = external_exports.object({
|
|
30516
|
+
id: external_exports.string(),
|
|
30517
|
+
sessionId: external_exports.string(),
|
|
30518
|
+
promptId: external_exports.string(),
|
|
30519
|
+
/** message | completion */
|
|
30520
|
+
kind: external_exports.enum(["message", "completion"]),
|
|
30521
|
+
content: external_exports.string().optional(),
|
|
30522
|
+
/** For completion: stopReason etc. */
|
|
30523
|
+
stopReason: external_exports.string().optional(),
|
|
30524
|
+
createdAt: external_exports.string()
|
|
30525
|
+
});
|
|
30526
|
+
var SessionToolCallSchema = external_exports.object({
|
|
30527
|
+
id: external_exports.string(),
|
|
30528
|
+
sessionId: external_exports.string(),
|
|
30529
|
+
promptId: external_exports.string(),
|
|
30530
|
+
name: external_exports.string(),
|
|
30531
|
+
params: external_exports.record(external_exports.unknown()).optional(),
|
|
30532
|
+
result: external_exports.record(external_exports.unknown()).optional(),
|
|
30533
|
+
createdAt: external_exports.string()
|
|
30534
|
+
});
|
|
30535
|
+
var SessionThreadRefSchema = external_exports.object({
|
|
30536
|
+
sessionId: external_exports.string(),
|
|
30537
|
+
threadId: external_exports.string(),
|
|
30538
|
+
addedAt: external_exports.string()
|
|
30539
|
+
});
|
|
30540
|
+
var ArtifactMetaSchema = external_exports.object({
|
|
30541
|
+
artifactId: external_exports.string(),
|
|
30542
|
+
workspaceId: external_exports.string(),
|
|
30543
|
+
/** Slug for permalink: /workspaces/:wid/artifacts/:slug */
|
|
30544
|
+
permalinkSlug: external_exports.string(),
|
|
30545
|
+
title: external_exports.string(),
|
|
30546
|
+
/** e.g. summary_report, build_log */
|
|
30547
|
+
type: external_exports.string().default("report"),
|
|
30548
|
+
/** Optional session that produced this artifact */
|
|
30549
|
+
sessionId: external_exports.string().nullable(),
|
|
30550
|
+
createdAt: external_exports.string(),
|
|
30551
|
+
updatedAt: external_exports.string()
|
|
30552
|
+
});
|
|
30553
|
+
var TemplateMetaSchema = external_exports.object({
|
|
30554
|
+
templateId: external_exports.string(),
|
|
30555
|
+
workspaceId: external_exports.string(),
|
|
30556
|
+
name: external_exports.string(),
|
|
30557
|
+
/** e.g. summary_report, build_log */
|
|
30558
|
+
artifactType: external_exports.string().optional(),
|
|
30559
|
+
createdAt: external_exports.string(),
|
|
30560
|
+
updatedAt: external_exports.string()
|
|
30561
|
+
});
|
|
30562
|
+
var GitRepoMetaSchema = external_exports.object({
|
|
30563
|
+
/** Stable id for the repo (e.g. hash of normalized canonical URL). Used for DO idFromName. */
|
|
30564
|
+
repoId: external_exports.string(),
|
|
30565
|
+
/** Canonical external URL (e.g. https://github.com/org/repo). Normalize before storing. */
|
|
30566
|
+
canonicalUrl: external_exports.string().url(),
|
|
30567
|
+
/** Optional workspace this repo was first linked in. */
|
|
30568
|
+
workspaceId: external_exports.string().nullable(),
|
|
30569
|
+
displayName: external_exports.string().optional(),
|
|
30570
|
+
createdAt: external_exports.string(),
|
|
30571
|
+
updatedAt: external_exports.string()
|
|
30572
|
+
});
|
|
30573
|
+
var LOCAL_AGENT_AUTH_ERROR_HINTS = {
|
|
30574
|
+
"kiro-acp": [/not logged in/i, /kiro-cli\s+login/i, /log in with kiro-cli/i],
|
|
30575
|
+
"cursor-cli": [/cursor_login/i, /authenticate.*cursor/i, /not logged in.*cursor/i, /run:\s*agent\s+login/i],
|
|
30576
|
+
"codex-acp": [
|
|
30577
|
+
/authentication failed/i,
|
|
30578
|
+
/not authenticated/i,
|
|
30579
|
+
/invalid.*api key/i,
|
|
30580
|
+
/sign in.*openai/i,
|
|
30581
|
+
/login.*openai/i,
|
|
30582
|
+
/unauthorized/i
|
|
30583
|
+
],
|
|
30584
|
+
"claude-code": [
|
|
30585
|
+
/ANTHROPIC_API_KEY/i,
|
|
30586
|
+
/not authenticated/i,
|
|
30587
|
+
/authentication failed/i,
|
|
30588
|
+
/claude\s+login/i,
|
|
30589
|
+
/please run.*claude.*login/i
|
|
30590
|
+
]
|
|
30591
|
+
};
|
|
30592
|
+
function localAgentErrorSuggestsAuth(agentType, errorText) {
|
|
30593
|
+
if (agentType == null || agentType === "" || errorText == null || !String(errorText).trim()) return false;
|
|
30594
|
+
const hints = LOCAL_AGENT_AUTH_ERROR_HINTS[agentType];
|
|
30595
|
+
if (!hints?.length) return false;
|
|
30596
|
+
return hints.some((re) => re.test(String(errorText)));
|
|
30299
30597
|
}
|
|
30300
30598
|
|
|
30301
30599
|
// src/git/session-git-queue.ts
|
|
30302
30600
|
import { execFile as execFile2 } from "node:child_process";
|
|
30601
|
+
import { readFile, stat } from "node:fs/promises";
|
|
30303
30602
|
import { promisify as promisify2 } from "node:util";
|
|
30304
|
-
import * as fs4 from "node:fs";
|
|
30305
30603
|
import * as path5 from "node:path";
|
|
30306
30604
|
|
|
30307
30605
|
// src/git/pre-turn-snapshot.ts
|
|
@@ -30416,11 +30714,11 @@ function snapshotFilePath(agentCwd, runId) {
|
|
|
30416
30714
|
// src/git/session-git-queue.ts
|
|
30417
30715
|
var execFileAsync2 = promisify2(execFile2);
|
|
30418
30716
|
var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
|
|
30419
|
-
function readWorkspaceFileAsUtf8(absPath) {
|
|
30717
|
+
async function readWorkspaceFileAsUtf8(absPath) {
|
|
30420
30718
|
try {
|
|
30421
|
-
const st =
|
|
30719
|
+
const st = await stat(absPath);
|
|
30422
30720
|
if (!st.isFile() || st.size > MAX_FULL_FILE_TEXT_BYTES) return void 0;
|
|
30423
|
-
return
|
|
30721
|
+
return await readFile(absPath, "utf8");
|
|
30424
30722
|
} catch {
|
|
30425
30723
|
return void 0;
|
|
30426
30724
|
}
|
|
@@ -30430,7 +30728,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
30430
30728
|
const filePath = snapshotFilePath(agentCwd, runId);
|
|
30431
30729
|
let data;
|
|
30432
30730
|
try {
|
|
30433
|
-
const raw =
|
|
30731
|
+
const raw = await readFile(filePath, "utf8");
|
|
30434
30732
|
data = JSON.parse(raw);
|
|
30435
30733
|
} catch (e) {
|
|
30436
30734
|
log2(
|
|
@@ -30474,7 +30772,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
30474
30772
|
if (!patchContent.trim()) continue;
|
|
30475
30773
|
const displayPath = multiRepo ? `${slug}/${rel}` : rel;
|
|
30476
30774
|
const absFile = path5.join(repo.path, rel);
|
|
30477
|
-
const newText = readWorkspaceFileAsUtf8(absFile);
|
|
30775
|
+
const newText = await readWorkspaceFileAsUtf8(absFile);
|
|
30478
30776
|
sendSessionUpdate({
|
|
30479
30777
|
type: "session_file_change",
|
|
30480
30778
|
sessionId,
|
|
@@ -30500,11 +30798,20 @@ async function sendPromptToAgent(options) {
|
|
|
30500
30798
|
promptId,
|
|
30501
30799
|
sessionId,
|
|
30502
30800
|
runId,
|
|
30801
|
+
agentType,
|
|
30503
30802
|
agentCwd,
|
|
30504
30803
|
sendResult,
|
|
30505
30804
|
sendSessionUpdate,
|
|
30506
30805
|
log: log2
|
|
30507
30806
|
} = options;
|
|
30807
|
+
function augmentAuthFields(errorText) {
|
|
30808
|
+
const err = errorText ?? "";
|
|
30809
|
+
const at = agentType ?? null;
|
|
30810
|
+
const evaluated = Boolean(at && err.trim());
|
|
30811
|
+
const suggestsAuth = evaluated && at ? localAgentErrorSuggestsAuth(at, err) : false;
|
|
30812
|
+
if (!suggestsAuth || !agentType) return {};
|
|
30813
|
+
return { agentAuthRequired: true, agentType };
|
|
30814
|
+
}
|
|
30508
30815
|
try {
|
|
30509
30816
|
const result = await handle.sendPrompt(promptText, {});
|
|
30510
30817
|
if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
|
|
@@ -30516,12 +30823,14 @@ async function sendPromptToAgent(options) {
|
|
|
30516
30823
|
log: log2
|
|
30517
30824
|
});
|
|
30518
30825
|
}
|
|
30826
|
+
const errStr = typeof result.error === "string" ? result.error : void 0;
|
|
30519
30827
|
sendResult({
|
|
30520
30828
|
type: "prompt_result",
|
|
30521
30829
|
id: promptId,
|
|
30522
30830
|
...sessionId ? { sessionId } : {},
|
|
30523
30831
|
...runId ? { runId } : {},
|
|
30524
|
-
...result
|
|
30832
|
+
...result,
|
|
30833
|
+
...augmentAuthFields(errStr)
|
|
30525
30834
|
});
|
|
30526
30835
|
if (!result.success) {
|
|
30527
30836
|
log2(`[Agent] ${result.error ?? "Error"}`);
|
|
@@ -30529,20 +30838,20 @@ async function sendPromptToAgent(options) {
|
|
|
30529
30838
|
} catch (err) {
|
|
30530
30839
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
30531
30840
|
log2(`[Agent] Send failed: ${errMsg}`);
|
|
30532
|
-
if (err instanceof Error && err.stack) log2(`[Agent] ${err.stack}`);
|
|
30533
30841
|
sendResult({
|
|
30534
30842
|
type: "prompt_result",
|
|
30535
30843
|
id: promptId,
|
|
30536
30844
|
...sessionId ? { sessionId } : {},
|
|
30537
30845
|
...runId ? { runId } : {},
|
|
30538
30846
|
success: false,
|
|
30539
|
-
error: errMsg
|
|
30847
|
+
error: errMsg,
|
|
30848
|
+
...augmentAuthFields(errMsg)
|
|
30540
30849
|
});
|
|
30541
30850
|
}
|
|
30542
30851
|
}
|
|
30543
30852
|
|
|
30544
30853
|
// src/acp/ensure-acp-client.ts
|
|
30545
|
-
import * as
|
|
30854
|
+
import * as fs4 from "node:fs";
|
|
30546
30855
|
import * as path9 from "node:path";
|
|
30547
30856
|
|
|
30548
30857
|
// src/error-message.ts
|
|
@@ -30555,49 +30864,293 @@ function errorMessage(err) {
|
|
|
30555
30864
|
return String(err);
|
|
30556
30865
|
}
|
|
30557
30866
|
|
|
30558
|
-
// src/acp/clients/acp-client.ts
|
|
30867
|
+
// src/acp/clients/claude-code-acp-client.ts
|
|
30868
|
+
var claude_code_acp_client_exports = {};
|
|
30869
|
+
__export(claude_code_acp_client_exports, {
|
|
30870
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE,
|
|
30871
|
+
buildClaudeCodeAcpSpawnCommand: () => buildClaudeCodeAcpSpawnCommand,
|
|
30872
|
+
createClaudeCodeAcpClient: () => createClaudeCodeAcpClient,
|
|
30873
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence
|
|
30874
|
+
});
|
|
30875
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
30876
|
+
import { promisify as promisify4 } from "node:util";
|
|
30877
|
+
|
|
30878
|
+
// src/acp/clients/detect-command-on-path.ts
|
|
30879
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
30880
|
+
import { promisify as promisify3 } from "node:util";
|
|
30881
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
30882
|
+
async function isCommandOnPath(command, timeoutMs = 4e3) {
|
|
30883
|
+
try {
|
|
30884
|
+
await execFileAsync3("which", [command], { timeout: timeoutMs });
|
|
30885
|
+
return true;
|
|
30886
|
+
} catch {
|
|
30887
|
+
return false;
|
|
30888
|
+
}
|
|
30889
|
+
}
|
|
30890
|
+
|
|
30891
|
+
// src/acp/clients/sdk-stdio-acp-client.ts
|
|
30559
30892
|
import { spawn as spawn2 } from "node:child_process";
|
|
30893
|
+
import { mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
30894
|
+
import { dirname } from "node:path";
|
|
30560
30895
|
import { Readable, Writable } from "node:stream";
|
|
30896
|
+
|
|
30897
|
+
// src/files/diff/unified-diff.ts
|
|
30898
|
+
function computeLineDiff(oldText, newText) {
|
|
30899
|
+
const oldLines = oldText.split("\n");
|
|
30900
|
+
const newLines = newText.split("\n");
|
|
30901
|
+
const m = oldLines.length;
|
|
30902
|
+
const n = newLines.length;
|
|
30903
|
+
const dp = Array(m + 1);
|
|
30904
|
+
for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
|
|
30905
|
+
for (let i2 = 1; i2 <= m; i2++) {
|
|
30906
|
+
for (let j2 = 1; j2 <= n; j2++) {
|
|
30907
|
+
if (oldLines[i2 - 1] === newLines[j2 - 1]) {
|
|
30908
|
+
dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
|
|
30909
|
+
} else {
|
|
30910
|
+
dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
30911
|
+
}
|
|
30912
|
+
}
|
|
30913
|
+
}
|
|
30914
|
+
const result = [];
|
|
30915
|
+
let i = m;
|
|
30916
|
+
let j = n;
|
|
30917
|
+
while (i > 0 || j > 0) {
|
|
30918
|
+
if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
|
|
30919
|
+
result.unshift({ type: "context", line: oldLines[i - 1] });
|
|
30920
|
+
i--;
|
|
30921
|
+
j--;
|
|
30922
|
+
} else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
|
|
30923
|
+
result.unshift({ type: "add", line: newLines[j - 1] });
|
|
30924
|
+
j--;
|
|
30925
|
+
} else {
|
|
30926
|
+
result.unshift({ type: "remove", line: oldLines[i - 1] });
|
|
30927
|
+
i--;
|
|
30928
|
+
}
|
|
30929
|
+
}
|
|
30930
|
+
return result;
|
|
30931
|
+
}
|
|
30932
|
+
function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
30933
|
+
const lines = computeLineDiff(oldText, newText);
|
|
30934
|
+
const out = [`--- ${filePath}`, `+++ ${filePath}`];
|
|
30935
|
+
for (const d of lines) {
|
|
30936
|
+
if (d.type === "add") out.push(`+${d.line}`);
|
|
30937
|
+
else if (d.type === "remove") out.push(`-${d.line}`);
|
|
30938
|
+
else out.push(` ${d.line}`);
|
|
30939
|
+
}
|
|
30940
|
+
return out.join("\n");
|
|
30941
|
+
}
|
|
30942
|
+
|
|
30943
|
+
// src/acp/safe-fs-path.ts
|
|
30944
|
+
import * as path6 from "node:path";
|
|
30945
|
+
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
30946
|
+
const trimmed2 = filePath.trim();
|
|
30947
|
+
if (!trimmed2) return null;
|
|
30948
|
+
const normalizedCwd = path6.resolve(cwd);
|
|
30949
|
+
const resolved = path6.isAbsolute(trimmed2) ? path6.normalize(trimmed2) : path6.resolve(normalizedCwd, trimmed2);
|
|
30950
|
+
const rel = path6.relative(normalizedCwd, resolved);
|
|
30951
|
+
if (rel.startsWith("..") || path6.isAbsolute(rel)) return null;
|
|
30952
|
+
return resolved;
|
|
30953
|
+
}
|
|
30954
|
+
function toDisplayPathRelativeToCwd(cwd, absolutePath) {
|
|
30955
|
+
const normalizedCwd = path6.resolve(cwd);
|
|
30956
|
+
const rel = path6.relative(normalizedCwd, path6.resolve(absolutePath));
|
|
30957
|
+
if (!rel || rel === "") return path6.basename(absolutePath);
|
|
30958
|
+
return rel.split(path6.sep).join("/");
|
|
30959
|
+
}
|
|
30960
|
+
|
|
30961
|
+
// src/acp/clients/agent-stderr-capture.ts
|
|
30962
|
+
var STDERR_CAPTURE_MAX = 48e3;
|
|
30963
|
+
function createStderrCapture(child) {
|
|
30964
|
+
const chunks = [];
|
|
30965
|
+
let total = 0;
|
|
30966
|
+
return {
|
|
30967
|
+
append(chunk) {
|
|
30968
|
+
try {
|
|
30969
|
+
process.stderr.write(chunk);
|
|
30970
|
+
} catch {
|
|
30971
|
+
}
|
|
30972
|
+
if (total >= STDERR_CAPTURE_MAX) return;
|
|
30973
|
+
const n = Math.min(chunk.length, STDERR_CAPTURE_MAX - total);
|
|
30974
|
+
if (n <= 0) return;
|
|
30975
|
+
chunks.push(n === chunk.length ? chunk : chunk.subarray(0, n));
|
|
30976
|
+
total += n;
|
|
30977
|
+
},
|
|
30978
|
+
getText() {
|
|
30979
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
30980
|
+
}
|
|
30981
|
+
};
|
|
30982
|
+
}
|
|
30983
|
+
function formatJsonRpcStyleError(err) {
|
|
30984
|
+
if (err instanceof Error) return err.message;
|
|
30985
|
+
if (err != null && typeof err === "object") {
|
|
30986
|
+
const o = err;
|
|
30987
|
+
const msg = typeof o.message === "string" ? o.message : null;
|
|
30988
|
+
const code = o.code != null ? String(o.code) : "";
|
|
30989
|
+
if (msg) return code ? `[${code}] ${msg}` : msg;
|
|
30990
|
+
}
|
|
30991
|
+
if (typeof err === "string") return err;
|
|
30992
|
+
try {
|
|
30993
|
+
return JSON.stringify(err);
|
|
30994
|
+
} catch {
|
|
30995
|
+
return String(err);
|
|
30996
|
+
}
|
|
30997
|
+
}
|
|
30998
|
+
function mergeErrorWithStderr(primary, stderrText) {
|
|
30999
|
+
const s = stderrText.trim();
|
|
31000
|
+
const p = (primary ?? "").trim();
|
|
31001
|
+
if (!s) return p;
|
|
31002
|
+
if (!p) return s;
|
|
31003
|
+
if (p.includes(s) || s.includes(p)) return p.length >= s.length ? p : s;
|
|
31004
|
+
return `${p}
|
|
31005
|
+
${s}`;
|
|
31006
|
+
}
|
|
31007
|
+
|
|
31008
|
+
// src/acp/clients/kiro-sdk-ext-notifications.ts
|
|
31009
|
+
function createKiroSdkExtNotificationHandler(options) {
|
|
31010
|
+
const { onSessionUpdate } = options;
|
|
31011
|
+
return async (method, params) => {
|
|
31012
|
+
if (method === "_kiro.dev/metadata") {
|
|
31013
|
+
const p = params && typeof params === "object" ? params : {};
|
|
31014
|
+
const pct = p.contextUsagePercentage;
|
|
31015
|
+
if (typeof pct !== "number" || !Number.isFinite(pct) || !onSessionUpdate) return;
|
|
31016
|
+
onSessionUpdate({
|
|
31017
|
+
sessionUpdate: "context_usage",
|
|
31018
|
+
contextUsagePercentage: pct
|
|
31019
|
+
});
|
|
31020
|
+
return;
|
|
31021
|
+
}
|
|
31022
|
+
};
|
|
31023
|
+
}
|
|
31024
|
+
|
|
31025
|
+
// src/acp/clients/sdk-stdio-ext-notifications.ts
|
|
31026
|
+
var noopExtNotification = async () => {
|
|
31027
|
+
};
|
|
31028
|
+
function createSdkStdioExtNotificationHandler(options) {
|
|
31029
|
+
const { backendAgentType, onSessionUpdate } = options;
|
|
31030
|
+
switch (backendAgentType) {
|
|
31031
|
+
case "kiro-acp":
|
|
31032
|
+
return createKiroSdkExtNotificationHandler({ onSessionUpdate });
|
|
31033
|
+
default:
|
|
31034
|
+
return noopExtNotification;
|
|
31035
|
+
}
|
|
31036
|
+
}
|
|
31037
|
+
|
|
31038
|
+
// src/acp/clients/sdk-stdio-acp-client.ts
|
|
30561
31039
|
function formatSpawnError(err, command) {
|
|
30562
31040
|
if (err.code === "ENOENT") {
|
|
30563
31041
|
return `Command "${command}" not found. Install the agent (e.g. Cursor CLI) or add it to PATH.`;
|
|
30564
31042
|
}
|
|
30565
31043
|
return err.message || String(err);
|
|
30566
31044
|
}
|
|
30567
|
-
function
|
|
30568
|
-
if (
|
|
30569
|
-
|
|
30570
|
-
|
|
30571
|
-
|
|
30572
|
-
|
|
30573
|
-
|
|
31045
|
+
function sliceFileContentRange(content, line, limit) {
|
|
31046
|
+
if (line == null && limit == null) return content;
|
|
31047
|
+
const lines = content.split("\n");
|
|
31048
|
+
const start = line != null && line > 0 ? line - 1 : 0;
|
|
31049
|
+
const end = limit != null && limit > 0 ? start + limit : lines.length;
|
|
31050
|
+
return lines.slice(start, end).join("\n");
|
|
31051
|
+
}
|
|
31052
|
+
function bridgePayloadFromSdkSessionNotification(params) {
|
|
31053
|
+
return { sessionId: params.sessionId, ...params.update };
|
|
30574
31054
|
}
|
|
30575
|
-
async function
|
|
30576
|
-
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
30577
|
-
const {
|
|
31055
|
+
async function createSdkStdioAcpClient(options) {
|
|
31056
|
+
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
31057
|
+
const {
|
|
31058
|
+
command,
|
|
31059
|
+
cwd = getBridgeWorkspaceDirectory(),
|
|
31060
|
+
backendAgentType,
|
|
31061
|
+
onSessionUpdate,
|
|
31062
|
+
onFileChange,
|
|
31063
|
+
killSubprocessAfterCancelMs,
|
|
31064
|
+
onAgentSubprocessExit
|
|
31065
|
+
} = options;
|
|
30578
31066
|
const isWindows = process.platform === "win32";
|
|
30579
31067
|
const child = spawn2(command[0], command.slice(1), {
|
|
30580
31068
|
cwd,
|
|
30581
|
-
stdio: ["pipe", "pipe", "
|
|
31069
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
30582
31070
|
env: process.env,
|
|
30583
31071
|
shell: isWindows
|
|
30584
31072
|
});
|
|
31073
|
+
const stderrCapture = createStderrCapture(child);
|
|
31074
|
+
child.once("close", (code, signal) => {
|
|
31075
|
+
onAgentSubprocessExit?.({ code, signal });
|
|
31076
|
+
});
|
|
30585
31077
|
return new Promise((resolve15, reject) => {
|
|
31078
|
+
let initSettled = false;
|
|
31079
|
+
const settleReject = (err) => {
|
|
31080
|
+
if (initSettled) return;
|
|
31081
|
+
initSettled = true;
|
|
31082
|
+
try {
|
|
31083
|
+
child.kill();
|
|
31084
|
+
} catch {
|
|
31085
|
+
}
|
|
31086
|
+
reject(err);
|
|
31087
|
+
};
|
|
31088
|
+
const settleResolve = (handle) => {
|
|
31089
|
+
if (initSettled) return;
|
|
31090
|
+
initSettled = true;
|
|
31091
|
+
resolve15(handle);
|
|
31092
|
+
};
|
|
30586
31093
|
child.on("error", (err) => {
|
|
30587
|
-
|
|
30588
|
-
|
|
31094
|
+
settleReject(new Error(formatSpawnError(err, command[0])));
|
|
31095
|
+
});
|
|
31096
|
+
child.stderr?.on("data", (chunk) => {
|
|
31097
|
+
stderrCapture.append(chunk);
|
|
31098
|
+
if (initSettled) return;
|
|
31099
|
+
const stderrText = stderrCapture.getText();
|
|
31100
|
+
if (backendAgentType && stderrText.trim() && localAgentErrorSuggestsAuth(backendAgentType, stderrText)) {
|
|
31101
|
+
settleReject(new Error(stderrText.trim()));
|
|
31102
|
+
}
|
|
30589
31103
|
});
|
|
30590
31104
|
(async () => {
|
|
30591
31105
|
try {
|
|
30592
31106
|
const writable = Writable.toWeb(child.stdin);
|
|
30593
31107
|
const readable = Readable.toWeb(child.stdout);
|
|
30594
31108
|
const stream = ndJsonStream2(writable, readable);
|
|
31109
|
+
const extNotification = createSdkStdioExtNotificationHandler({
|
|
31110
|
+
backendAgentType,
|
|
31111
|
+
onSessionUpdate
|
|
31112
|
+
});
|
|
30595
31113
|
const client = (_agent) => ({
|
|
30596
|
-
async requestPermission(
|
|
30597
|
-
|
|
31114
|
+
async requestPermission(params) {
|
|
31115
|
+
const opt = params?.options?.[0];
|
|
31116
|
+
if (opt && typeof opt.optionId === "string") {
|
|
31117
|
+
return { outcome: { outcome: "selected", optionId: opt.optionId } };
|
|
31118
|
+
}
|
|
31119
|
+
return { outcome: { outcome: "cancelled" } };
|
|
31120
|
+
},
|
|
31121
|
+
async readTextFile(params) {
|
|
31122
|
+
const abs = resolveSafePathUnderCwd(cwd, params.path);
|
|
31123
|
+
if (!abs) throw new Error("Invalid or disallowed path");
|
|
31124
|
+
try {
|
|
31125
|
+
let content = readFileSync2(abs, "utf8");
|
|
31126
|
+
content = sliceFileContentRange(content, params.line, params.limit);
|
|
31127
|
+
return { content };
|
|
31128
|
+
} catch (e) {
|
|
31129
|
+
if (e.code === "ENOENT") return { content: "" };
|
|
31130
|
+
throw e;
|
|
31131
|
+
}
|
|
31132
|
+
},
|
|
31133
|
+
async writeTextFile(params) {
|
|
31134
|
+
const abs = resolveSafePathUnderCwd(cwd, params.path);
|
|
31135
|
+
if (!abs) throw new Error("Invalid or disallowed path");
|
|
31136
|
+
let oldText = "";
|
|
31137
|
+
try {
|
|
31138
|
+
oldText = readFileSync2(abs, "utf8");
|
|
31139
|
+
} catch (e) {
|
|
31140
|
+
if (e.code !== "ENOENT") throw e;
|
|
31141
|
+
}
|
|
31142
|
+
mkdirSync2(dirname(abs), { recursive: true });
|
|
31143
|
+
writeFileSync2(abs, params.content, "utf8");
|
|
31144
|
+
const displayPath = toDisplayPathRelativeToCwd(cwd, abs);
|
|
31145
|
+
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, params.content);
|
|
31146
|
+
onFileChange?.({ path: displayPath, oldText, newText: params.content, patchContent });
|
|
31147
|
+
return {};
|
|
30598
31148
|
},
|
|
30599
31149
|
async sessionUpdate(params) {
|
|
30600
|
-
onSessionUpdate?.(params);
|
|
31150
|
+
onSessionUpdate?.(bridgePayloadFromSdkSessionNotification(params));
|
|
31151
|
+
},
|
|
31152
|
+
async extNotification(method, params) {
|
|
31153
|
+
await extNotification(method, params);
|
|
30601
31154
|
}
|
|
30602
31155
|
});
|
|
30603
31156
|
const connection = new ClientSideConnection2(client, stream);
|
|
@@ -30605,39 +31158,82 @@ async function createAcpClient(options) {
|
|
|
30605
31158
|
child.kill();
|
|
30606
31159
|
});
|
|
30607
31160
|
await connection.initialize({
|
|
30608
|
-
protocolVersion:
|
|
30609
|
-
|
|
31161
|
+
protocolVersion: PROTOCOL_VERSION2,
|
|
31162
|
+
clientCapabilities: {
|
|
31163
|
+
fs: { readTextFile: true, writeTextFile: true }
|
|
31164
|
+
},
|
|
30610
31165
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
30611
31166
|
});
|
|
30612
|
-
const newSessionRes = await connection.newSession({
|
|
31167
|
+
const newSessionRes = await connection.newSession({ cwd, mcpServers: [] });
|
|
30613
31168
|
const sessionId = newSessionRes.sessionId;
|
|
30614
|
-
|
|
31169
|
+
settleResolve({
|
|
30615
31170
|
sessionId,
|
|
30616
31171
|
async sendPrompt(prompt, _options) {
|
|
30617
31172
|
try {
|
|
30618
31173
|
const response = await connection.prompt({
|
|
30619
31174
|
sessionId,
|
|
30620
|
-
prompt: { type: "text", text: prompt }
|
|
31175
|
+
prompt: [{ type: "text", text: prompt }]
|
|
30621
31176
|
});
|
|
31177
|
+
await new Promise((r2) => setImmediate(r2));
|
|
30622
31178
|
const r = response;
|
|
30623
|
-
const
|
|
31179
|
+
const stopReason = (r?.stopReason ?? "").toLowerCase();
|
|
31180
|
+
const cancelled = stopReason === "cancelled";
|
|
31181
|
+
const refusal = stopReason === "refusal";
|
|
31182
|
+
const stderrAfter = stderrCapture.getText();
|
|
31183
|
+
const agentType = backendAgentType ?? null;
|
|
31184
|
+
const stderrEvaluated = Boolean(stderrAfter && agentType);
|
|
31185
|
+
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
|
|
31186
|
+
if (cancelled) {
|
|
31187
|
+
return {
|
|
31188
|
+
success: false,
|
|
31189
|
+
stopReason: r?.stopReason,
|
|
31190
|
+
output: r?.output,
|
|
31191
|
+
error: mergeErrorWithStderr("Stopped by user", stderrAfter)
|
|
31192
|
+
};
|
|
31193
|
+
}
|
|
31194
|
+
if (refusal) {
|
|
31195
|
+
return {
|
|
31196
|
+
success: false,
|
|
31197
|
+
stopReason: r?.stopReason,
|
|
31198
|
+
output: r?.output,
|
|
31199
|
+
error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
|
|
31200
|
+
};
|
|
31201
|
+
}
|
|
31202
|
+
if (stderrSuggestsAuth) {
|
|
31203
|
+
return {
|
|
31204
|
+
success: false,
|
|
31205
|
+
stopReason: r?.stopReason,
|
|
31206
|
+
output: r?.output,
|
|
31207
|
+
error: stderrAfter
|
|
31208
|
+
};
|
|
31209
|
+
}
|
|
30624
31210
|
return {
|
|
30625
|
-
success:
|
|
31211
|
+
success: true,
|
|
30626
31212
|
stopReason: r?.stopReason,
|
|
30627
|
-
output: r?.output
|
|
30628
|
-
...cancelled ? { error: "Stopped by user" } : {}
|
|
31213
|
+
output: r?.output
|
|
30629
31214
|
};
|
|
30630
31215
|
} catch (err) {
|
|
31216
|
+
await new Promise((r) => setImmediate(r));
|
|
31217
|
+
const stderrAfter = stderrCapture.getText();
|
|
31218
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
|
|
30631
31219
|
return {
|
|
30632
31220
|
success: false,
|
|
30633
|
-
error:
|
|
31221
|
+
error: merged
|
|
30634
31222
|
};
|
|
30635
31223
|
}
|
|
30636
31224
|
},
|
|
30637
31225
|
async cancel() {
|
|
30638
|
-
|
|
30639
|
-
|
|
30640
|
-
|
|
31226
|
+
try {
|
|
31227
|
+
await connection.cancel({ sessionId });
|
|
31228
|
+
} catch {
|
|
31229
|
+
}
|
|
31230
|
+
if (killSubprocessAfterCancelMs != null && killSubprocessAfterCancelMs >= 0) {
|
|
31231
|
+
const t = setTimeout(() => {
|
|
31232
|
+
if (child.exitCode == null && child.signalCode == null) {
|
|
31233
|
+
child.kill("SIGTERM");
|
|
31234
|
+
}
|
|
31235
|
+
}, killSubprocessAfterCancelMs);
|
|
31236
|
+
t.unref?.();
|
|
30641
31237
|
}
|
|
30642
31238
|
},
|
|
30643
31239
|
resolveRequest() {
|
|
@@ -30647,94 +31243,88 @@ async function createAcpClient(options) {
|
|
|
30647
31243
|
}
|
|
30648
31244
|
});
|
|
30649
31245
|
} catch (err) {
|
|
30650
|
-
|
|
30651
|
-
|
|
31246
|
+
if (initSettled) return;
|
|
31247
|
+
try {
|
|
31248
|
+
child.kill();
|
|
31249
|
+
} catch {
|
|
31250
|
+
}
|
|
31251
|
+
const stderrText = stderrCapture.getText();
|
|
31252
|
+
const base = formatJsonRpcStyleError(err);
|
|
31253
|
+
settleReject(new Error(mergeErrorWithStderr(base, stderrText)));
|
|
30652
31254
|
}
|
|
30653
31255
|
})();
|
|
30654
31256
|
});
|
|
30655
31257
|
}
|
|
30656
31258
|
|
|
31259
|
+
// src/acp/clients/claude-code-acp-client.ts
|
|
31260
|
+
var execFileAsync4 = promisify4(execFile4);
|
|
31261
|
+
var BACKEND_LOCAL_AGENT_TYPE = "claude-code";
|
|
31262
|
+
async function detectLocalAgentPresence() {
|
|
31263
|
+
if (await isCommandOnPath("claude")) return true;
|
|
31264
|
+
try {
|
|
31265
|
+
await execFileAsync4("npx", ["--yes", "@anthropic-ai/claude-code", "--version"], { timeout: 25e3 });
|
|
31266
|
+
return true;
|
|
31267
|
+
} catch {
|
|
31268
|
+
return false;
|
|
31269
|
+
}
|
|
31270
|
+
}
|
|
31271
|
+
function buildClaudeCodeAcpSpawnCommand(base, sessionMode) {
|
|
31272
|
+
if (!sessionMode) return [...base];
|
|
31273
|
+
const m = sessionMode.trim();
|
|
31274
|
+
if (m === "plan") return [...base, "--permission-mode", "plan"];
|
|
31275
|
+
return [...base];
|
|
31276
|
+
}
|
|
31277
|
+
async function createClaudeCodeAcpClient(options) {
|
|
31278
|
+
const command = buildClaudeCodeAcpSpawnCommand(options.command, options.sessionMode);
|
|
31279
|
+
return createSdkStdioAcpClient({
|
|
31280
|
+
...options,
|
|
31281
|
+
command,
|
|
31282
|
+
/** Claude-based agents sometimes ignore `session/cancel`; unblocks stop / stuck prompt. */
|
|
31283
|
+
killSubprocessAfterCancelMs: options.killSubprocessAfterCancelMs ?? 1e3
|
|
31284
|
+
});
|
|
31285
|
+
}
|
|
31286
|
+
|
|
30657
31287
|
// src/acp/clients/codex-acp-client.ts
|
|
31288
|
+
var codex_acp_client_exports = {};
|
|
31289
|
+
__export(codex_acp_client_exports, {
|
|
31290
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE2,
|
|
31291
|
+
DEFAULT_CODEX_ACP_COMMAND: () => DEFAULT_CODEX_ACP_COMMAND,
|
|
31292
|
+
buildCodexAcpSpawnCommand: () => buildCodexAcpSpawnCommand,
|
|
31293
|
+
createCodexAcpClient: () => createCodexAcpClient,
|
|
31294
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence2,
|
|
31295
|
+
isCodexAcpCommand: () => isCodexAcpCommand
|
|
31296
|
+
});
|
|
31297
|
+
var BACKEND_LOCAL_AGENT_TYPE2 = "codex-acp";
|
|
31298
|
+
async function detectLocalAgentPresence2() {
|
|
31299
|
+
return isCommandOnPath("codex");
|
|
31300
|
+
}
|
|
30658
31301
|
var DEFAULT_CODEX_ACP_COMMAND = ["npx", "--yes", "@zed-industries/codex-acp"];
|
|
30659
31302
|
function isCodexAcpCommand(command) {
|
|
30660
31303
|
const i = command.indexOf("@zed-industries/codex-acp");
|
|
30661
31304
|
return i >= 0 && (i === 0 || command[i - 1] === "npx" || command[i - 1] === "bunx");
|
|
30662
31305
|
}
|
|
31306
|
+
function buildCodexAcpSpawnCommand(base, _sessionMode) {
|
|
31307
|
+
return [...base];
|
|
31308
|
+
}
|
|
30663
31309
|
async function createCodexAcpClient(options) {
|
|
30664
|
-
const
|
|
30665
|
-
|
|
31310
|
+
const base = options.command?.length && options.command.some((a) => a.includes("codex-acp")) ? options.command : [...DEFAULT_CODEX_ACP_COMMAND];
|
|
31311
|
+
const command = buildCodexAcpSpawnCommand(base, options.sessionMode);
|
|
31312
|
+
return createSdkStdioAcpClient({ ...options, command });
|
|
30666
31313
|
}
|
|
30667
31314
|
|
|
30668
31315
|
// src/acp/clients/cursor-acp-client.ts
|
|
30669
|
-
|
|
30670
|
-
|
|
31316
|
+
var cursor_acp_client_exports = {};
|
|
31317
|
+
__export(cursor_acp_client_exports, {
|
|
31318
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE3,
|
|
31319
|
+
buildCursorAcpSpawnCommand: () => buildCursorAcpSpawnCommand,
|
|
31320
|
+
createCursorAcpClient: () => createCursorAcpClient,
|
|
31321
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence3
|
|
31322
|
+
});
|
|
31323
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
31324
|
+
import { dirname as dirname2 } from "node:path";
|
|
30671
31325
|
import { spawn as spawn3 } from "node:child_process";
|
|
30672
31326
|
import * as readline from "node:readline";
|
|
30673
31327
|
|
|
30674
|
-
// src/acp/safe-fs-path.ts
|
|
30675
|
-
import * as path6 from "node:path";
|
|
30676
|
-
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
30677
|
-
const trimmed2 = filePath.trim();
|
|
30678
|
-
if (!trimmed2) return null;
|
|
30679
|
-
const normalizedCwd = path6.resolve(cwd);
|
|
30680
|
-
const resolved = path6.isAbsolute(trimmed2) ? path6.normalize(trimmed2) : path6.resolve(normalizedCwd, trimmed2);
|
|
30681
|
-
const rel = path6.relative(normalizedCwd, resolved);
|
|
30682
|
-
if (rel.startsWith("..") || path6.isAbsolute(rel)) return null;
|
|
30683
|
-
return resolved;
|
|
30684
|
-
}
|
|
30685
|
-
function toDisplayPathRelativeToCwd(cwd, absolutePath) {
|
|
30686
|
-
const normalizedCwd = path6.resolve(cwd);
|
|
30687
|
-
const rel = path6.relative(normalizedCwd, path6.resolve(absolutePath));
|
|
30688
|
-
if (!rel || rel === "") return path6.basename(absolutePath);
|
|
30689
|
-
return rel.split(path6.sep).join("/");
|
|
30690
|
-
}
|
|
30691
|
-
|
|
30692
|
-
// src/files/diff/unified-diff.ts
|
|
30693
|
-
function computeLineDiff(oldText, newText) {
|
|
30694
|
-
const oldLines = oldText.split("\n");
|
|
30695
|
-
const newLines = newText.split("\n");
|
|
30696
|
-
const m = oldLines.length;
|
|
30697
|
-
const n = newLines.length;
|
|
30698
|
-
const dp = Array(m + 1);
|
|
30699
|
-
for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
|
|
30700
|
-
for (let i2 = 1; i2 <= m; i2++) {
|
|
30701
|
-
for (let j2 = 1; j2 <= n; j2++) {
|
|
30702
|
-
if (oldLines[i2 - 1] === newLines[j2 - 1]) {
|
|
30703
|
-
dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
|
|
30704
|
-
} else {
|
|
30705
|
-
dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
30706
|
-
}
|
|
30707
|
-
}
|
|
30708
|
-
}
|
|
30709
|
-
const result = [];
|
|
30710
|
-
let i = m;
|
|
30711
|
-
let j = n;
|
|
30712
|
-
while (i > 0 || j > 0) {
|
|
30713
|
-
if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
|
|
30714
|
-
result.unshift({ type: "context", line: oldLines[i - 1] });
|
|
30715
|
-
i--;
|
|
30716
|
-
j--;
|
|
30717
|
-
} else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
|
|
30718
|
-
result.unshift({ type: "add", line: newLines[j - 1] });
|
|
30719
|
-
j--;
|
|
30720
|
-
} else {
|
|
30721
|
-
result.unshift({ type: "remove", line: oldLines[i - 1] });
|
|
30722
|
-
i--;
|
|
30723
|
-
}
|
|
30724
|
-
}
|
|
30725
|
-
return result;
|
|
30726
|
-
}
|
|
30727
|
-
function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
30728
|
-
const lines = computeLineDiff(oldText, newText);
|
|
30729
|
-
const out = [`--- ${filePath}`, `+++ ${filePath}`];
|
|
30730
|
-
for (const d of lines) {
|
|
30731
|
-
if (d.type === "add") out.push(`+${d.line}`);
|
|
30732
|
-
else if (d.type === "remove") out.push(`-${d.line}`);
|
|
30733
|
-
else out.push(` ${d.line}`);
|
|
30734
|
-
}
|
|
30735
|
-
return out.join("\n");
|
|
30736
|
-
}
|
|
30737
|
-
|
|
30738
31328
|
// src/acp/format-session-update-kind-for-log.ts
|
|
30739
31329
|
var SESSION_UPDATE_KIND_LABELS = {
|
|
30740
31330
|
tool_call: "Tool call",
|
|
@@ -30772,16 +31362,31 @@ function sliceLinesByRange(content, line, limit) {
|
|
|
30772
31362
|
const end = limit != null && limit > 0 ? start + limit : lines.length;
|
|
30773
31363
|
return lines.slice(start, end).join("\n");
|
|
30774
31364
|
}
|
|
31365
|
+
function buildCursorAcpSpawnCommand(base, sessionMode) {
|
|
31366
|
+
if (!sessionMode) return [...base];
|
|
31367
|
+
const m = sessionMode.trim();
|
|
31368
|
+
if (m !== "ask" && m !== "plan") return [...base];
|
|
31369
|
+
return [...base, "--mode", m];
|
|
31370
|
+
}
|
|
30775
31371
|
async function createCursorAcpClient(options) {
|
|
30776
|
-
const
|
|
31372
|
+
const command = buildCursorAcpSpawnCommand(options.command, options.sessionMode);
|
|
31373
|
+
const {
|
|
31374
|
+
cwd = getBridgeWorkspaceDirectory(),
|
|
31375
|
+
backendAgentType,
|
|
31376
|
+
onSessionUpdate,
|
|
31377
|
+
onRequest,
|
|
31378
|
+
onFileChange
|
|
31379
|
+
} = options;
|
|
30777
31380
|
const dbgFs = process.env.BUILDAMATON_DEBUG_ACP_FS === "1";
|
|
30778
31381
|
const isWindows = process.platform === "win32";
|
|
30779
31382
|
const child = spawn3(command[0], command.slice(1), {
|
|
30780
31383
|
cwd,
|
|
30781
|
-
stdio: ["pipe", "pipe", "
|
|
31384
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
30782
31385
|
env: process.env,
|
|
30783
31386
|
shell: isWindows
|
|
30784
31387
|
});
|
|
31388
|
+
const stderrCapture = createStderrCapture(child);
|
|
31389
|
+
child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
|
|
30785
31390
|
return new Promise((resolve15, reject) => {
|
|
30786
31391
|
child.on("error", (err) => {
|
|
30787
31392
|
child.kill();
|
|
@@ -30905,8 +31510,8 @@ async function createCursorAcpClient(options) {
|
|
|
30905
31510
|
}
|
|
30906
31511
|
}
|
|
30907
31512
|
try {
|
|
30908
|
-
|
|
30909
|
-
|
|
31513
|
+
mkdirSync3(dirname2(abs), { recursive: true });
|
|
31514
|
+
writeFileSync3(abs, newText, "utf8");
|
|
30910
31515
|
} catch (e) {
|
|
30911
31516
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
30912
31517
|
return;
|
|
@@ -30965,17 +31570,52 @@ async function createCursorAcpClient(options) {
|
|
|
30965
31570
|
sessionId,
|
|
30966
31571
|
prompt: [{ type: "text", text: prompt }]
|
|
30967
31572
|
});
|
|
31573
|
+
await new Promise((r) => setImmediate(r));
|
|
30968
31574
|
const output = (result?.output ?? promptOutputBuffer) || void 0;
|
|
30969
|
-
const
|
|
31575
|
+
const stopReason = (result?.stopReason ?? "").toLowerCase();
|
|
31576
|
+
const cancelled = stopReason === "cancelled";
|
|
31577
|
+
const refusal = stopReason === "refusal";
|
|
31578
|
+
const stderrAfter = stderrCapture.getText();
|
|
31579
|
+
const agentType = backendAgentType ?? null;
|
|
31580
|
+
const stderrEvaluated = Boolean(stderrAfter && agentType);
|
|
31581
|
+
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
|
|
31582
|
+
if (cancelled) {
|
|
31583
|
+
return {
|
|
31584
|
+
success: false,
|
|
31585
|
+
stopReason: result?.stopReason,
|
|
31586
|
+
output: output || void 0,
|
|
31587
|
+
error: mergeErrorWithStderr("Stopped by user", stderrAfter)
|
|
31588
|
+
};
|
|
31589
|
+
}
|
|
31590
|
+
if (refusal) {
|
|
31591
|
+
return {
|
|
31592
|
+
success: false,
|
|
31593
|
+
stopReason: result?.stopReason,
|
|
31594
|
+
output: output || void 0,
|
|
31595
|
+
error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
|
|
31596
|
+
};
|
|
31597
|
+
}
|
|
31598
|
+
if (stderrSuggestsAuth) {
|
|
31599
|
+
return {
|
|
31600
|
+
success: false,
|
|
31601
|
+
stopReason: result?.stopReason,
|
|
31602
|
+
output: output || void 0,
|
|
31603
|
+
error: stderrAfter
|
|
31604
|
+
};
|
|
31605
|
+
}
|
|
30970
31606
|
return {
|
|
30971
|
-
success:
|
|
31607
|
+
success: true,
|
|
30972
31608
|
stopReason: result?.stopReason,
|
|
30973
|
-
output: output || void 0
|
|
30974
|
-
...cancelled ? { error: "Stopped by user" } : {}
|
|
31609
|
+
output: output || void 0
|
|
30975
31610
|
};
|
|
30976
31611
|
} catch (err) {
|
|
30977
|
-
|
|
30978
|
-
|
|
31612
|
+
await new Promise((r) => setImmediate(r));
|
|
31613
|
+
const stderrAfter = stderrCapture.getText();
|
|
31614
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
|
|
31615
|
+
return {
|
|
31616
|
+
success: false,
|
|
31617
|
+
error: merged
|
|
31618
|
+
};
|
|
30979
31619
|
}
|
|
30980
31620
|
},
|
|
30981
31621
|
async cancel() {
|
|
@@ -30994,38 +31634,120 @@ async function createCursorAcpClient(options) {
|
|
|
30994
31634
|
});
|
|
30995
31635
|
} catch (err) {
|
|
30996
31636
|
child.kill();
|
|
30997
|
-
|
|
31637
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrCapture.getText());
|
|
31638
|
+
reject(merged ? new Error(merged) : err instanceof Error ? err : new Error(String(err)));
|
|
30998
31639
|
}
|
|
30999
31640
|
})();
|
|
31000
31641
|
});
|
|
31001
31642
|
}
|
|
31643
|
+
var BACKEND_LOCAL_AGENT_TYPE3 = "cursor-cli";
|
|
31644
|
+
async function detectLocalAgentPresence3() {
|
|
31645
|
+
return isCommandOnPath("agent");
|
|
31646
|
+
}
|
|
31647
|
+
|
|
31648
|
+
// src/acp/clients/kiro-acp-client.ts
|
|
31649
|
+
var kiro_acp_client_exports = {};
|
|
31650
|
+
__export(kiro_acp_client_exports, {
|
|
31651
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE4,
|
|
31652
|
+
DEFAULT_KIRO_ACP_COMMAND: () => DEFAULT_KIRO_ACP_COMMAND,
|
|
31653
|
+
buildKiroAcpSpawnCommand: () => buildKiroAcpSpawnCommand,
|
|
31654
|
+
createKiroAcpClient: () => createKiroAcpClient,
|
|
31655
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence4,
|
|
31656
|
+
isKiroAcpCommand: () => isKiroAcpCommand
|
|
31657
|
+
});
|
|
31658
|
+
var BACKEND_LOCAL_AGENT_TYPE4 = "kiro-acp";
|
|
31659
|
+
async function detectLocalAgentPresence4() {
|
|
31660
|
+
return isCommandOnPath("kiro-cli");
|
|
31661
|
+
}
|
|
31662
|
+
var DEFAULT_KIRO_ACP_COMMAND = ["kiro-cli", "acp"];
|
|
31663
|
+
function isKiroAcpCommand(command) {
|
|
31664
|
+
if (command.length < 2) return false;
|
|
31665
|
+
if (command[command.length - 1] !== "acp") return false;
|
|
31666
|
+
return command.slice(0, -1).some(
|
|
31667
|
+
(a) => a === "kiro-cli" || /[/\\]kiro-cli(\.exe)?$/i.test(a)
|
|
31668
|
+
);
|
|
31669
|
+
}
|
|
31670
|
+
function buildKiroAcpSpawnCommand(base, _sessionMode) {
|
|
31671
|
+
return [...base];
|
|
31672
|
+
}
|
|
31673
|
+
async function createKiroAcpClient(options) {
|
|
31674
|
+
const base = options.command?.length && isKiroAcpCommand(options.command) ? options.command : [...DEFAULT_KIRO_ACP_COMMAND];
|
|
31675
|
+
const command = buildKiroAcpSpawnCommand(base, options.sessionMode);
|
|
31676
|
+
return createSdkStdioAcpClient({ ...options, command });
|
|
31677
|
+
}
|
|
31002
31678
|
|
|
31003
31679
|
// src/acp/resolve-agent-command.ts
|
|
31004
31680
|
var AGENT_TYPE_DEFAULT_COMMANDS = {
|
|
31005
|
-
|
|
31006
|
-
|
|
31007
|
-
|
|
31681
|
+
[BACKEND_LOCAL_AGENT_TYPE3]: ["agent", "acp"],
|
|
31682
|
+
[BACKEND_LOCAL_AGENT_TYPE2]: [...DEFAULT_CODEX_ACP_COMMAND],
|
|
31683
|
+
/** ACP stdio agent; `@anthropic-ai/claude-code` is the interactive CLI and does not speak ACP on stdout. */
|
|
31684
|
+
[BACKEND_LOCAL_AGENT_TYPE]: ["npx", "--yes", "@agentclientprotocol/claude-agent-acp"],
|
|
31685
|
+
/** [Kiro CLI ACP](https://kiro.dev/docs/cli/acp/) — use full path to `kiro-cli` in PATH if the IDE cannot find it. */
|
|
31686
|
+
[BACKEND_LOCAL_AGENT_TYPE4]: [...DEFAULT_KIRO_ACP_COMMAND]
|
|
31008
31687
|
};
|
|
31688
|
+
var AGENT_TYPE_DISPLAY_NAMES = {
|
|
31689
|
+
[BACKEND_LOCAL_AGENT_TYPE3]: "Cursor",
|
|
31690
|
+
[BACKEND_LOCAL_AGENT_TYPE2]: "Codex",
|
|
31691
|
+
[BACKEND_LOCAL_AGENT_TYPE]: "Claude Code",
|
|
31692
|
+
[BACKEND_LOCAL_AGENT_TYPE4]: "Kiro"
|
|
31693
|
+
};
|
|
31694
|
+
function getAgentTypeDisplayName(agentType) {
|
|
31695
|
+
if (agentType == null || agentType === "") return "Unknown agent";
|
|
31696
|
+
const known = AGENT_TYPE_DISPLAY_NAMES[agentType];
|
|
31697
|
+
if (known) return known;
|
|
31698
|
+
return agentType.split(/[-_]/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
31699
|
+
}
|
|
31009
31700
|
function useCursorAcp(agentType, command) {
|
|
31010
|
-
if (agentType ===
|
|
31701
|
+
if (agentType === BACKEND_LOCAL_AGENT_TYPE3) return true;
|
|
31011
31702
|
return command[0] === "agent" && command[1] === "acp";
|
|
31012
31703
|
}
|
|
31013
31704
|
function useCodexAcp(agentType, command) {
|
|
31014
|
-
if (agentType ===
|
|
31705
|
+
if (agentType === BACKEND_LOCAL_AGENT_TYPE2) return true;
|
|
31015
31706
|
return isCodexAcpCommand(command);
|
|
31016
31707
|
}
|
|
31708
|
+
function useKiroAcp(agentType, command) {
|
|
31709
|
+
if (agentType === BACKEND_LOCAL_AGENT_TYPE4) return true;
|
|
31710
|
+
return isKiroAcpCommand(command);
|
|
31711
|
+
}
|
|
31017
31712
|
function resolveAgentCommand(preferredAgentType) {
|
|
31018
31713
|
if (!preferredAgentType) return null;
|
|
31019
31714
|
const command = AGENT_TYPE_DEFAULT_COMMANDS[preferredAgentType];
|
|
31020
31715
|
if (!command?.length) return null;
|
|
31021
|
-
|
|
31022
|
-
|
|
31023
|
-
|
|
31716
|
+
if (useCursorAcp(preferredAgentType, command)) {
|
|
31717
|
+
return {
|
|
31718
|
+
command,
|
|
31719
|
+
label: preferredAgentType,
|
|
31720
|
+
createClient: createCursorAcpClient,
|
|
31721
|
+
spawnCommandForSession: (sessionMode) => buildCursorAcpSpawnCommand(command, sessionMode)
|
|
31722
|
+
};
|
|
31723
|
+
}
|
|
31724
|
+
if (useCodexAcp(preferredAgentType, command)) {
|
|
31725
|
+
return {
|
|
31726
|
+
command,
|
|
31727
|
+
label: preferredAgentType,
|
|
31728
|
+
createClient: createCodexAcpClient,
|
|
31729
|
+
spawnCommandForSession: (sessionMode) => buildCodexAcpSpawnCommand(command, sessionMode)
|
|
31730
|
+
};
|
|
31731
|
+
}
|
|
31732
|
+
if (useKiroAcp(preferredAgentType, command)) {
|
|
31733
|
+
return {
|
|
31734
|
+
command,
|
|
31735
|
+
label: preferredAgentType,
|
|
31736
|
+
createClient: createKiroAcpClient,
|
|
31737
|
+
spawnCommandForSession: (sessionMode) => buildKiroAcpSpawnCommand(command, sessionMode)
|
|
31738
|
+
};
|
|
31739
|
+
}
|
|
31740
|
+
return {
|
|
31741
|
+
command,
|
|
31742
|
+
label: preferredAgentType,
|
|
31743
|
+
createClient: createClaudeCodeAcpClient,
|
|
31744
|
+
spawnCommandForSession: (sessionMode) => buildClaudeCodeAcpSpawnCommand(command, sessionMode)
|
|
31745
|
+
};
|
|
31024
31746
|
}
|
|
31025
31747
|
|
|
31026
31748
|
// src/acp/session-file-change-path-kind.ts
|
|
31027
31749
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
31028
|
-
import { existsSync, statSync
|
|
31750
|
+
import { existsSync, statSync } from "node:fs";
|
|
31029
31751
|
|
|
31030
31752
|
// src/git/get-git-repo-root-sync.ts
|
|
31031
31753
|
import { execFileSync } from "node:child_process";
|
|
@@ -31134,7 +31856,7 @@ function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
|
|
|
31134
31856
|
const abs = tryWorkspaceDisplayToAbs(cwd, displayPath);
|
|
31135
31857
|
if (abs && existsSync(abs)) {
|
|
31136
31858
|
try {
|
|
31137
|
-
if (
|
|
31859
|
+
if (statSync(abs).isDirectory()) {
|
|
31138
31860
|
return { isDirectory: true, directoryRemoved: false };
|
|
31139
31861
|
}
|
|
31140
31862
|
return { isDirectory: false, directoryRemoved: false };
|
|
@@ -31680,7 +32402,8 @@ async function ensureAcpClient(options) {
|
|
|
31680
32402
|
state.lastAcpStartError = "No agent type: ensure the app sends agentType on prompts or agent_config for this bridge.";
|
|
31681
32403
|
return null;
|
|
31682
32404
|
}
|
|
31683
|
-
const
|
|
32405
|
+
const fullCmd = resolved.spawnCommandForSession(mode);
|
|
32406
|
+
const agentKey = `${resolved.label}::${fullCmd.join("\0")}`;
|
|
31684
32407
|
if (state.acpHandle && state.acpAgentKey !== agentKey) {
|
|
31685
32408
|
try {
|
|
31686
32409
|
state.acpHandle.disconnect();
|
|
@@ -31694,7 +32417,7 @@ async function ensureAcpClient(options) {
|
|
|
31694
32417
|
if (!state.acpStartPromise) {
|
|
31695
32418
|
let statOk = false;
|
|
31696
32419
|
try {
|
|
31697
|
-
const st =
|
|
32420
|
+
const st = fs4.statSync(targetCwd);
|
|
31698
32421
|
statOk = st.isDirectory();
|
|
31699
32422
|
if (!statOk) {
|
|
31700
32423
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
|
|
@@ -31707,8 +32430,6 @@ async function ensureAcpClient(options) {
|
|
|
31707
32430
|
if (!statOk) {
|
|
31708
32431
|
return null;
|
|
31709
32432
|
}
|
|
31710
|
-
const modeFlag = mode && ["ask", "plan"].includes(mode) ? ["--mode", mode] : [];
|
|
31711
|
-
const fullCmd = [...resolved.command, ...modeFlag];
|
|
31712
32433
|
const hooks = buildAcpSessionBridgeHooks({
|
|
31713
32434
|
routing,
|
|
31714
32435
|
getSendSessionUpdate: () => sendSessionUpdate,
|
|
@@ -31716,8 +32437,16 @@ async function ensureAcpClient(options) {
|
|
|
31716
32437
|
log: log2
|
|
31717
32438
|
});
|
|
31718
32439
|
state.acpStartPromise = resolved.createClient({
|
|
31719
|
-
command:
|
|
32440
|
+
command: resolved.command,
|
|
32441
|
+
sessionMode: mode,
|
|
31720
32442
|
cwd: targetCwd,
|
|
32443
|
+
backendAgentType: preferredAgentType,
|
|
32444
|
+
onAgentSubprocessExit: () => {
|
|
32445
|
+
state.acpHandle = null;
|
|
32446
|
+
state.acpStartPromise = null;
|
|
32447
|
+
state.acpAgentKey = null;
|
|
32448
|
+
state.lastAcpStartError = "Agent subprocess exited";
|
|
32449
|
+
},
|
|
31721
32450
|
...hooks
|
|
31722
32451
|
}).then((h) => {
|
|
31723
32452
|
state.lastAcpStartError = null;
|
|
@@ -31755,6 +32484,14 @@ async function createAcpManager(options) {
|
|
|
31755
32484
|
backendFallbackAgentType = agentType;
|
|
31756
32485
|
}
|
|
31757
32486
|
}
|
|
32487
|
+
function logPromptReceivedFromBridge(opts) {
|
|
32488
|
+
const { agentType, mode } = opts;
|
|
32489
|
+
const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
|
|
32490
|
+
const modeLabel = typeof mode === "string" && mode.trim() !== "" ? mode.trim() : "not set";
|
|
32491
|
+
log2(
|
|
32492
|
+
`[Agent] Prompt received (${getAgentTypeDisplayName(preferredForPrompt)}, mode: ${modeLabel})`
|
|
32493
|
+
);
|
|
32494
|
+
}
|
|
31758
32495
|
function handlePrompt(opts) {
|
|
31759
32496
|
const {
|
|
31760
32497
|
promptText,
|
|
@@ -31784,17 +32521,24 @@ async function createAcpManager(options) {
|
|
|
31784
32521
|
log: log2
|
|
31785
32522
|
});
|
|
31786
32523
|
if (!handle) {
|
|
32524
|
+
const errMsg = state.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
|
|
32525
|
+
const evaluated = Boolean(preferredForPrompt && errMsg.trim());
|
|
32526
|
+
const suggestsAuth = evaluated ? localAgentErrorSuggestsAuth(preferredForPrompt, errMsg) : false;
|
|
32527
|
+
const auth = suggestsAuth && preferredForPrompt ? { agentAuthRequired: true, agentType: preferredForPrompt } : {};
|
|
31787
32528
|
sendResult({
|
|
31788
32529
|
type: "prompt_result",
|
|
31789
32530
|
id: promptId,
|
|
31790
32531
|
...sessionId ? { sessionId } : {},
|
|
31791
32532
|
...runId ? { runId } : {},
|
|
31792
32533
|
success: false,
|
|
31793
|
-
error:
|
|
32534
|
+
error: errMsg,
|
|
32535
|
+
...auth
|
|
31794
32536
|
});
|
|
31795
32537
|
return;
|
|
31796
32538
|
}
|
|
31797
|
-
if (promptRouting.sessionId !== sessionId || promptRouting.runId !== runId)
|
|
32539
|
+
if (promptRouting.sessionId !== sessionId || promptRouting.runId !== runId) {
|
|
32540
|
+
return;
|
|
32541
|
+
}
|
|
31798
32542
|
if (runId && pendingCancelRunId === runId) {
|
|
31799
32543
|
pendingCancelRunId = void 0;
|
|
31800
32544
|
try {
|
|
@@ -31818,6 +32562,7 @@ async function createAcpManager(options) {
|
|
|
31818
32562
|
promptId,
|
|
31819
32563
|
sessionId,
|
|
31820
32564
|
runId,
|
|
32565
|
+
agentType: preferredForPrompt,
|
|
31821
32566
|
agentCwd: cwd,
|
|
31822
32567
|
sendResult,
|
|
31823
32568
|
sendSessionUpdate,
|
|
@@ -31835,6 +32580,7 @@ async function createAcpManager(options) {
|
|
|
31835
32580
|
if (promptRouting.runId !== runId) return false;
|
|
31836
32581
|
const handle = state.acpHandle;
|
|
31837
32582
|
if (handle?.cancel) {
|
|
32583
|
+
log2("[Agent] Stop requested");
|
|
31838
32584
|
try {
|
|
31839
32585
|
await handle.cancel();
|
|
31840
32586
|
return true;
|
|
@@ -31843,6 +32589,7 @@ async function createAcpManager(options) {
|
|
|
31843
32589
|
return false;
|
|
31844
32590
|
}
|
|
31845
32591
|
}
|
|
32592
|
+
log2("[Agent] Stop requested (agent still starting)");
|
|
31846
32593
|
pendingCancelRunId = runId;
|
|
31847
32594
|
return true;
|
|
31848
32595
|
}
|
|
@@ -31855,7 +32602,14 @@ async function createAcpManager(options) {
|
|
|
31855
32602
|
state.acpStartPromise = null;
|
|
31856
32603
|
state.acpAgentKey = null;
|
|
31857
32604
|
}
|
|
31858
|
-
return {
|
|
32605
|
+
return {
|
|
32606
|
+
setPreferredAgentType,
|
|
32607
|
+
logPromptReceivedFromBridge,
|
|
32608
|
+
handlePrompt,
|
|
32609
|
+
cancelRun,
|
|
32610
|
+
resolveRequest,
|
|
32611
|
+
disconnect
|
|
32612
|
+
};
|
|
31859
32613
|
}
|
|
31860
32614
|
|
|
31861
32615
|
// src/bridge/routing/handlers/auth-token.ts
|
|
@@ -31906,8 +32660,8 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
31906
32660
|
|
|
31907
32661
|
// src/acp/from-bridge/handle-bridge-prompt.ts
|
|
31908
32662
|
import * as path11 from "node:path";
|
|
31909
|
-
import { execFile as
|
|
31910
|
-
import { promisify as
|
|
32663
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
32664
|
+
import { promisify as promisify5 } from "node:util";
|
|
31911
32665
|
|
|
31912
32666
|
// src/git/bridge-queue-key.ts
|
|
31913
32667
|
import * as path10 from "node:path";
|
|
@@ -31965,10 +32719,10 @@ async function resolveBridgeQueueBindFields(options) {
|
|
|
31965
32719
|
}
|
|
31966
32720
|
|
|
31967
32721
|
// src/acp/from-bridge/handle-bridge-prompt.ts
|
|
31968
|
-
var
|
|
32722
|
+
var execFileAsync5 = promisify5(execFile5);
|
|
31969
32723
|
async function readGitBranch(cwd) {
|
|
31970
32724
|
try {
|
|
31971
|
-
const { stdout } = await
|
|
32725
|
+
const { stdout } = await execFileAsync5("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
|
|
31972
32726
|
const b = stdout.trim();
|
|
31973
32727
|
return b || null;
|
|
31974
32728
|
} catch {
|
|
@@ -31990,6 +32744,8 @@ function handleBridgePrompt(msg, deps) {
|
|
|
31990
32744
|
const sessionWorktreesEnabled = msg.sessionWorktreesEnabled === true;
|
|
31991
32745
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
31992
32746
|
const runId = typeof msg.runId === "string" ? msg.runId : void 0;
|
|
32747
|
+
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
32748
|
+
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
31993
32749
|
const sendResult = (result) => {
|
|
31994
32750
|
const s = getWs();
|
|
31995
32751
|
if (s) sendWsMessage(s, result);
|
|
@@ -32052,7 +32808,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
32052
32808
|
promptId: msg.id,
|
|
32053
32809
|
sessionId,
|
|
32054
32810
|
runId,
|
|
32055
|
-
mode
|
|
32811
|
+
mode,
|
|
32056
32812
|
agentType,
|
|
32057
32813
|
cwd: effectiveCwd,
|
|
32058
32814
|
sendResult,
|
|
@@ -32296,7 +33052,7 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
32296
33052
|
};
|
|
32297
33053
|
|
|
32298
33054
|
// src/files/list-dir.ts
|
|
32299
|
-
import
|
|
33055
|
+
import fs5 from "node:fs";
|
|
32300
33056
|
import path13 from "node:path";
|
|
32301
33057
|
|
|
32302
33058
|
// src/files/ensure-under-cwd.ts
|
|
@@ -32317,14 +33073,14 @@ function listDir(relativePath) {
|
|
|
32317
33073
|
return { error: "Path is outside working directory" };
|
|
32318
33074
|
}
|
|
32319
33075
|
try {
|
|
32320
|
-
const names =
|
|
33076
|
+
const names = fs5.readdirSync(resolved, { withFileTypes: true });
|
|
32321
33077
|
const entries = names.filter((d) => !d.name.startsWith(".")).map((d) => {
|
|
32322
33078
|
const entryPath = path13.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
32323
33079
|
const fullPath = path13.join(resolved, d.name);
|
|
32324
33080
|
let isDir = d.isDirectory();
|
|
32325
33081
|
if (d.isSymbolicLink()) {
|
|
32326
33082
|
try {
|
|
32327
|
-
const targetStat =
|
|
33083
|
+
const targetStat = fs5.statSync(fullPath);
|
|
32328
33084
|
isDir = targetStat.isDirectory();
|
|
32329
33085
|
} catch {
|
|
32330
33086
|
isDir = false;
|
|
@@ -32348,25 +33104,25 @@ function listDir(relativePath) {
|
|
|
32348
33104
|
}
|
|
32349
33105
|
|
|
32350
33106
|
// src/files/read-file.ts
|
|
32351
|
-
import
|
|
33107
|
+
import fs6 from "node:fs";
|
|
32352
33108
|
import { StringDecoder } from "node:string_decoder";
|
|
32353
33109
|
function resolveFilePath(relativePath) {
|
|
32354
33110
|
const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
|
|
32355
33111
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
32356
33112
|
let real;
|
|
32357
33113
|
try {
|
|
32358
|
-
real =
|
|
33114
|
+
real = fs6.realpathSync(resolved);
|
|
32359
33115
|
} catch {
|
|
32360
33116
|
real = resolved;
|
|
32361
33117
|
}
|
|
32362
|
-
const
|
|
32363
|
-
if (!
|
|
33118
|
+
const stat2 = fs6.statSync(real);
|
|
33119
|
+
if (!stat2.isFile()) return { error: "Not a file" };
|
|
32364
33120
|
return real;
|
|
32365
33121
|
}
|
|
32366
33122
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
32367
33123
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
32368
|
-
const fileSize =
|
|
32369
|
-
const fd =
|
|
33124
|
+
const fileSize = fs6.statSync(filePath).size;
|
|
33125
|
+
const fd = fs6.openSync(filePath, "r");
|
|
32370
33126
|
const bufSize = 64 * 1024;
|
|
32371
33127
|
const buf = Buffer.alloc(bufSize);
|
|
32372
33128
|
const decoder = new StringDecoder("utf8");
|
|
@@ -32379,7 +33135,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
32379
33135
|
let line0Accum = "";
|
|
32380
33136
|
try {
|
|
32381
33137
|
let bytesRead;
|
|
32382
|
-
while (!done && (bytesRead =
|
|
33138
|
+
while (!done && (bytesRead = fs6.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
32383
33139
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
32384
33140
|
partial2 = "";
|
|
32385
33141
|
let lineStart = 0;
|
|
@@ -32514,10 +33270,10 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
32514
33270
|
}
|
|
32515
33271
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
32516
33272
|
} finally {
|
|
32517
|
-
|
|
33273
|
+
fs6.closeSync(fd);
|
|
32518
33274
|
}
|
|
32519
33275
|
}
|
|
32520
|
-
function
|
|
33276
|
+
function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
32521
33277
|
try {
|
|
32522
33278
|
const result = resolveFilePath(relativePath);
|
|
32523
33279
|
if (typeof result === "object") return result;
|
|
@@ -32525,17 +33281,17 @@ function readFile(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
32525
33281
|
if (hasRange) {
|
|
32526
33282
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
32527
33283
|
}
|
|
32528
|
-
const
|
|
32529
|
-
const raw =
|
|
33284
|
+
const stat2 = fs6.statSync(result);
|
|
33285
|
+
const raw = fs6.readFileSync(result, "utf8");
|
|
32530
33286
|
const lines = raw.split(/\r?\n/);
|
|
32531
|
-
return { content: raw, totalLines: lines.length, size:
|
|
33287
|
+
return { content: raw, totalLines: lines.length, size: stat2.size };
|
|
32532
33288
|
} catch (err) {
|
|
32533
33289
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
32534
33290
|
}
|
|
32535
33291
|
}
|
|
32536
33292
|
|
|
32537
33293
|
// src/files/file-index.ts
|
|
32538
|
-
import
|
|
33294
|
+
import fs7 from "node:fs";
|
|
32539
33295
|
import path14 from "node:path";
|
|
32540
33296
|
import os2 from "node:os";
|
|
32541
33297
|
import crypto2 from "node:crypto";
|
|
@@ -32582,23 +33338,23 @@ function binarySearch(arr, x) {
|
|
|
32582
33338
|
function walkDir(dir, baseDir, out) {
|
|
32583
33339
|
let names;
|
|
32584
33340
|
try {
|
|
32585
|
-
names =
|
|
33341
|
+
names = fs7.readdirSync(dir);
|
|
32586
33342
|
} catch {
|
|
32587
33343
|
return;
|
|
32588
33344
|
}
|
|
32589
33345
|
for (const name of names) {
|
|
32590
33346
|
if (name.startsWith(".")) continue;
|
|
32591
33347
|
const full = path14.join(dir, name);
|
|
32592
|
-
let
|
|
33348
|
+
let stat2;
|
|
32593
33349
|
try {
|
|
32594
|
-
|
|
33350
|
+
stat2 = fs7.statSync(full);
|
|
32595
33351
|
} catch {
|
|
32596
33352
|
continue;
|
|
32597
33353
|
}
|
|
32598
33354
|
const relative4 = path14.relative(baseDir, full).replace(/\\/g, "/");
|
|
32599
|
-
if (
|
|
33355
|
+
if (stat2.isDirectory()) {
|
|
32600
33356
|
walkDir(full, baseDir, out);
|
|
32601
|
-
} else if (
|
|
33357
|
+
} else if (stat2.isFile()) {
|
|
32602
33358
|
out.push(relative4);
|
|
32603
33359
|
}
|
|
32604
33360
|
}
|
|
@@ -32622,8 +33378,8 @@ function buildFileIndex(cwd) {
|
|
|
32622
33378
|
const data = { version: INDEX_VERSION, paths, trigramIndex };
|
|
32623
33379
|
const indexPath = getIndexPath(resolved);
|
|
32624
33380
|
try {
|
|
32625
|
-
if (!
|
|
32626
|
-
|
|
33381
|
+
if (!fs7.existsSync(INDEX_DIR)) fs7.mkdirSync(INDEX_DIR, { recursive: true });
|
|
33382
|
+
fs7.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
32627
33383
|
} catch (e) {
|
|
32628
33384
|
console.error("[file-index] Failed to write index:", e);
|
|
32629
33385
|
}
|
|
@@ -32633,7 +33389,7 @@ function loadFileIndex(cwd) {
|
|
|
32633
33389
|
const resolved = path14.resolve(cwd);
|
|
32634
33390
|
const indexPath = getIndexPath(resolved);
|
|
32635
33391
|
try {
|
|
32636
|
-
const raw =
|
|
33392
|
+
const raw = fs7.readFileSync(indexPath, "utf8");
|
|
32637
33393
|
const parsed = JSON.parse(raw);
|
|
32638
33394
|
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
|
|
32639
33395
|
const obj = parsed;
|
|
@@ -32737,7 +33493,7 @@ function handleFileBrowserRequest(msg, socket) {
|
|
|
32737
33493
|
const endLine = typeof msg.endLine === "number" ? msg.endLine : void 0;
|
|
32738
33494
|
const lineOffset = typeof msg.lineOffset === "number" ? msg.lineOffset : void 0;
|
|
32739
33495
|
const lineChunkSize = typeof msg.lineChunkSize === "number" ? msg.lineChunkSize : void 0;
|
|
32740
|
-
const result =
|
|
33496
|
+
const result = readFile2(reqPath, startLine, endLine, lineOffset, lineChunkSize);
|
|
32741
33497
|
if ("error" in result) {
|
|
32742
33498
|
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
32743
33499
|
} else {
|
|
@@ -32772,7 +33528,7 @@ function handleFileBrowserSearchMessage(msg, { getWs }) {
|
|
|
32772
33528
|
}
|
|
32773
33529
|
|
|
32774
33530
|
// src/skills/discover-local-agent-skills.ts
|
|
32775
|
-
import
|
|
33531
|
+
import fs8 from "node:fs";
|
|
32776
33532
|
import path15 from "node:path";
|
|
32777
33533
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
32778
33534
|
function discoverLocalSkills(cwd) {
|
|
@@ -32780,22 +33536,22 @@ function discoverLocalSkills(cwd) {
|
|
|
32780
33536
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
32781
33537
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
32782
33538
|
const base = path15.join(cwd, rel);
|
|
32783
|
-
if (!
|
|
33539
|
+
if (!fs8.existsSync(base) || !fs8.statSync(base).isDirectory()) continue;
|
|
32784
33540
|
let entries = [];
|
|
32785
33541
|
try {
|
|
32786
|
-
entries =
|
|
33542
|
+
entries = fs8.readdirSync(base);
|
|
32787
33543
|
} catch {
|
|
32788
33544
|
continue;
|
|
32789
33545
|
}
|
|
32790
33546
|
for (const name of entries) {
|
|
32791
33547
|
const dir = path15.join(base, name);
|
|
32792
33548
|
try {
|
|
32793
|
-
if (!
|
|
33549
|
+
if (!fs8.statSync(dir).isDirectory()) continue;
|
|
32794
33550
|
} catch {
|
|
32795
33551
|
continue;
|
|
32796
33552
|
}
|
|
32797
33553
|
const skillMd = path15.join(dir, "SKILL.md");
|
|
32798
|
-
if (!
|
|
33554
|
+
if (!fs8.existsSync(skillMd)) continue;
|
|
32799
33555
|
const key = `${rel}/${name}`;
|
|
32800
33556
|
if (seenKeys.has(key)) continue;
|
|
32801
33557
|
seenKeys.add(key);
|
|
@@ -32808,10 +33564,10 @@ function discoverSkillLayoutRoots(cwd) {
|
|
|
32808
33564
|
const roots = [];
|
|
32809
33565
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
32810
33566
|
const base = path15.join(cwd, rel);
|
|
32811
|
-
if (!
|
|
33567
|
+
if (!fs8.existsSync(base) || !fs8.statSync(base).isDirectory()) continue;
|
|
32812
33568
|
let entries = [];
|
|
32813
33569
|
try {
|
|
32814
|
-
entries =
|
|
33570
|
+
entries = fs8.readdirSync(base);
|
|
32815
33571
|
} catch {
|
|
32816
33572
|
continue;
|
|
32817
33573
|
}
|
|
@@ -32819,11 +33575,11 @@ function discoverSkillLayoutRoots(cwd) {
|
|
|
32819
33575
|
for (const name of entries) {
|
|
32820
33576
|
const dir = path15.join(base, name);
|
|
32821
33577
|
try {
|
|
32822
|
-
if (!
|
|
33578
|
+
if (!fs8.statSync(dir).isDirectory()) continue;
|
|
32823
33579
|
} catch {
|
|
32824
33580
|
continue;
|
|
32825
33581
|
}
|
|
32826
|
-
if (!
|
|
33582
|
+
if (!fs8.existsSync(path15.join(dir, "SKILL.md"))) continue;
|
|
32827
33583
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
32828
33584
|
skills2.push({ name, relPath });
|
|
32829
33585
|
}
|
|
@@ -32843,7 +33599,7 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
32843
33599
|
}
|
|
32844
33600
|
|
|
32845
33601
|
// src/skills/install-remote-skills.ts
|
|
32846
|
-
import
|
|
33602
|
+
import fs9 from "node:fs";
|
|
32847
33603
|
import path16 from "node:path";
|
|
32848
33604
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
32849
33605
|
const installed = [];
|
|
@@ -32859,11 +33615,11 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
32859
33615
|
for (const f of item.files) {
|
|
32860
33616
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
32861
33617
|
const dest = path16.join(skillDir, f.path);
|
|
32862
|
-
|
|
33618
|
+
fs9.mkdirSync(path16.dirname(dest), { recursive: true });
|
|
32863
33619
|
if (f.text !== void 0) {
|
|
32864
|
-
|
|
33620
|
+
fs9.writeFileSync(dest, f.text, "utf8");
|
|
32865
33621
|
} else if (f.base64) {
|
|
32866
|
-
|
|
33622
|
+
fs9.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
32867
33623
|
}
|
|
32868
33624
|
}
|
|
32869
33625
|
installed.push({
|
|
@@ -32957,7 +33713,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
32957
33713
|
};
|
|
32958
33714
|
|
|
32959
33715
|
// src/bridge/routing/handlers/revert-turn-snapshot.ts
|
|
32960
|
-
import * as
|
|
33716
|
+
import * as fs10 from "node:fs";
|
|
32961
33717
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
32962
33718
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
32963
33719
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -32969,7 +33725,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
32969
33725
|
if (!s) return;
|
|
32970
33726
|
const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
|
|
32971
33727
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
32972
|
-
if (!
|
|
33728
|
+
if (!fs10.existsSync(file2)) {
|
|
32973
33729
|
sendWsMessage(s, {
|
|
32974
33730
|
type: "revert_turn_snapshot_result",
|
|
32975
33731
|
id,
|
|
@@ -33070,25 +33826,12 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
33070
33826
|
}
|
|
33071
33827
|
|
|
33072
33828
|
// src/bridge/routing/handle-bridge-message.ts
|
|
33073
|
-
var DEFERRED_INBOUND_TYPES = /* @__PURE__ */ new Set([
|
|
33074
|
-
"server_control",
|
|
33075
|
-
"prompt",
|
|
33076
|
-
"install_skills",
|
|
33077
|
-
"refresh_local_skills",
|
|
33078
|
-
"dev_servers_config"
|
|
33079
|
-
]);
|
|
33080
33829
|
function handleBridgeMessage(data, deps) {
|
|
33081
33830
|
const msg = data;
|
|
33082
|
-
|
|
33083
|
-
|
|
33084
|
-
|
|
33085
|
-
|
|
33086
|
-
setImmediate(() => {
|
|
33087
|
-
dispatchBridgeMessage(msg, deps);
|
|
33088
|
-
});
|
|
33089
|
-
return;
|
|
33090
|
-
}
|
|
33091
|
-
dispatchBridgeMessage(msg, deps);
|
|
33831
|
+
if (!deps.getWs()) return;
|
|
33832
|
+
setImmediate(() => {
|
|
33833
|
+
dispatchBridgeMessage(msg, deps);
|
|
33834
|
+
});
|
|
33092
33835
|
}
|
|
33093
33836
|
|
|
33094
33837
|
// src/worktrees/session-worktree-manager.ts
|
|
@@ -33096,7 +33839,7 @@ import * as path20 from "node:path";
|
|
|
33096
33839
|
import os4 from "node:os";
|
|
33097
33840
|
|
|
33098
33841
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
33099
|
-
import * as
|
|
33842
|
+
import * as fs12 from "node:fs";
|
|
33100
33843
|
import * as path18 from "node:path";
|
|
33101
33844
|
|
|
33102
33845
|
// src/git/worktree-add.ts
|
|
@@ -33106,7 +33849,7 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
|
33106
33849
|
}
|
|
33107
33850
|
|
|
33108
33851
|
// src/worktrees/worktree-layout-file.ts
|
|
33109
|
-
import * as
|
|
33852
|
+
import * as fs11 from "node:fs";
|
|
33110
33853
|
import * as path17 from "node:path";
|
|
33111
33854
|
import os3 from "node:os";
|
|
33112
33855
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
@@ -33123,8 +33866,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
33123
33866
|
function loadWorktreeLayout() {
|
|
33124
33867
|
try {
|
|
33125
33868
|
const p = defaultWorktreeLayoutPath();
|
|
33126
|
-
if (!
|
|
33127
|
-
const raw = JSON.parse(
|
|
33869
|
+
if (!fs11.existsSync(p)) return { launcherCwds: [] };
|
|
33870
|
+
const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
|
|
33128
33871
|
return normalizeLoadedLayout(raw);
|
|
33129
33872
|
} catch {
|
|
33130
33873
|
return { launcherCwds: [] };
|
|
@@ -33133,8 +33876,8 @@ function loadWorktreeLayout() {
|
|
|
33133
33876
|
function saveWorktreeLayout(layout) {
|
|
33134
33877
|
try {
|
|
33135
33878
|
const dir = path17.dirname(defaultWorktreeLayoutPath());
|
|
33136
|
-
|
|
33137
|
-
|
|
33879
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
33880
|
+
fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
33138
33881
|
} catch {
|
|
33139
33882
|
}
|
|
33140
33883
|
}
|
|
@@ -33171,13 +33914,13 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
33171
33914
|
}
|
|
33172
33915
|
const branch = `session-${sessionId}`;
|
|
33173
33916
|
const worktreePaths = [];
|
|
33174
|
-
|
|
33917
|
+
fs12.mkdirSync(agentMirrorRoot, { recursive: true });
|
|
33175
33918
|
for (const repo of repos) {
|
|
33176
33919
|
let rel = path18.relative(launcherResolved, repo.absolutePath);
|
|
33177
33920
|
if (rel.startsWith("..") || path18.isAbsolute(rel)) continue;
|
|
33178
33921
|
const relNorm = rel === "" ? "." : rel;
|
|
33179
33922
|
const wtPath = path18.join(agentMirrorRoot, relNorm, sessionId);
|
|
33180
|
-
|
|
33923
|
+
fs12.mkdirSync(path18.dirname(wtPath), { recursive: true });
|
|
33181
33924
|
try {
|
|
33182
33925
|
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
33183
33926
|
log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
|
|
@@ -33214,18 +33957,18 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
33214
33957
|
}
|
|
33215
33958
|
|
|
33216
33959
|
// src/worktrees/remove-session-worktrees.ts
|
|
33217
|
-
import * as
|
|
33960
|
+
import * as fs15 from "node:fs";
|
|
33218
33961
|
|
|
33219
33962
|
// src/git/worktree-remove.ts
|
|
33220
|
-
import * as
|
|
33963
|
+
import * as fs14 from "node:fs";
|
|
33221
33964
|
|
|
33222
33965
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
33223
|
-
import * as
|
|
33966
|
+
import * as fs13 from "node:fs";
|
|
33224
33967
|
import * as path19 from "node:path";
|
|
33225
33968
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
33226
33969
|
const gitDirFile = path19.join(wt, ".git");
|
|
33227
|
-
if (!
|
|
33228
|
-
const first2 =
|
|
33970
|
+
if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
|
|
33971
|
+
const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
|
|
33229
33972
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
33230
33973
|
if (!m) return "";
|
|
33231
33974
|
const gitWorktreePath = path19.resolve(wt, m[1].trim());
|
|
@@ -33239,7 +33982,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
33239
33982
|
if (mainRepo) {
|
|
33240
33983
|
await simpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
33241
33984
|
} else {
|
|
33242
|
-
|
|
33985
|
+
fs14.rmSync(worktreePath, { recursive: true, force: true });
|
|
33243
33986
|
}
|
|
33244
33987
|
}
|
|
33245
33988
|
|
|
@@ -33252,7 +33995,7 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
33252
33995
|
} catch (e) {
|
|
33253
33996
|
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
33254
33997
|
try {
|
|
33255
|
-
|
|
33998
|
+
fs15.rmSync(wt, { recursive: true, force: true });
|
|
33256
33999
|
} catch {
|
|
33257
34000
|
}
|
|
33258
34001
|
}
|
|
@@ -33524,7 +34267,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
33524
34267
|
}
|
|
33525
34268
|
|
|
33526
34269
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
33527
|
-
import
|
|
34270
|
+
import fs16 from "node:fs";
|
|
33528
34271
|
|
|
33529
34272
|
// src/dev-servers/manager/forward-pipe.ts
|
|
33530
34273
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -33560,7 +34303,7 @@ function wireDevServerChildProcess(d) {
|
|
|
33560
34303
|
d.setPollInterval(void 0);
|
|
33561
34304
|
return;
|
|
33562
34305
|
}
|
|
33563
|
-
|
|
34306
|
+
fs16.readFile(d.mergedLogPath, (err, buf) => {
|
|
33564
34307
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
33565
34308
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
33566
34309
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -33598,7 +34341,7 @@ ${errTail}` : ""}`);
|
|
|
33598
34341
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
33599
34342
|
};
|
|
33600
34343
|
if (mergedPath) {
|
|
33601
|
-
|
|
34344
|
+
fs16.readFile(mergedPath, (err, buf) => {
|
|
33602
34345
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
33603
34346
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
33604
34347
|
if (chunk.length > 0) {
|
|
@@ -33700,13 +34443,13 @@ function parseDevServerDefs(servers) {
|
|
|
33700
34443
|
}
|
|
33701
34444
|
|
|
33702
34445
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
33703
|
-
import
|
|
34446
|
+
import fs17 from "node:fs";
|
|
33704
34447
|
function isSpawnEbadf(e) {
|
|
33705
34448
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
33706
34449
|
}
|
|
33707
34450
|
function rmDirQuiet(dir) {
|
|
33708
34451
|
try {
|
|
33709
|
-
|
|
34452
|
+
fs17.rmSync(dir, { recursive: true, force: true });
|
|
33710
34453
|
} catch {
|
|
33711
34454
|
}
|
|
33712
34455
|
}
|
|
@@ -33714,7 +34457,7 @@ var cachedDevNullReadFd;
|
|
|
33714
34457
|
function devNullReadFd() {
|
|
33715
34458
|
if (cachedDevNullReadFd === void 0) {
|
|
33716
34459
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
33717
|
-
cachedDevNullReadFd =
|
|
34460
|
+
cachedDevNullReadFd = fs17.openSync(devPath, "r");
|
|
33718
34461
|
}
|
|
33719
34462
|
return cachedDevNullReadFd;
|
|
33720
34463
|
}
|
|
@@ -33788,15 +34531,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
33788
34531
|
|
|
33789
34532
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
33790
34533
|
import { spawn as spawn7 } from "node:child_process";
|
|
33791
|
-
import
|
|
34534
|
+
import fs18 from "node:fs";
|
|
33792
34535
|
import { tmpdir } from "node:os";
|
|
33793
34536
|
import path22 from "node:path";
|
|
33794
34537
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
33795
|
-
const tmpRoot =
|
|
34538
|
+
const tmpRoot = fs18.mkdtempSync(path22.join(tmpdir(), "ba-devsrv-log-"));
|
|
33796
34539
|
const logPath = path22.join(tmpRoot, "combined.log");
|
|
33797
34540
|
let logFd;
|
|
33798
34541
|
try {
|
|
33799
|
-
logFd =
|
|
34542
|
+
logFd = fs18.openSync(logPath, "a");
|
|
33800
34543
|
} catch {
|
|
33801
34544
|
rmDirQuiet(tmpRoot);
|
|
33802
34545
|
return null;
|
|
@@ -33815,7 +34558,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33815
34558
|
} else {
|
|
33816
34559
|
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
33817
34560
|
}
|
|
33818
|
-
|
|
34561
|
+
fs18.closeSync(logFd);
|
|
33819
34562
|
return {
|
|
33820
34563
|
proc,
|
|
33821
34564
|
pipedStdoutStderr: true,
|
|
@@ -33824,7 +34567,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33824
34567
|
};
|
|
33825
34568
|
} catch (e) {
|
|
33826
34569
|
try {
|
|
33827
|
-
|
|
34570
|
+
fs18.closeSync(logFd);
|
|
33828
34571
|
} catch {
|
|
33829
34572
|
}
|
|
33830
34573
|
rmDirQuiet(tmpRoot);
|
|
@@ -33835,22 +34578,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
33835
34578
|
|
|
33836
34579
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
33837
34580
|
import { spawn as spawn8 } from "node:child_process";
|
|
33838
|
-
import
|
|
34581
|
+
import fs19 from "node:fs";
|
|
33839
34582
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
33840
34583
|
import path23 from "node:path";
|
|
33841
34584
|
function shSingleQuote(s) {
|
|
33842
34585
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
33843
34586
|
}
|
|
33844
34587
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
33845
|
-
const tmpRoot =
|
|
34588
|
+
const tmpRoot = fs19.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33846
34589
|
const logPath = path23.join(tmpRoot, "combined.log");
|
|
33847
34590
|
const innerPath = path23.join(tmpRoot, "_cmd.sh");
|
|
33848
34591
|
const runnerPath = path23.join(tmpRoot, "_run.sh");
|
|
33849
34592
|
try {
|
|
33850
|
-
|
|
34593
|
+
fs19.writeFileSync(innerPath, `#!/bin/sh
|
|
33851
34594
|
${command}
|
|
33852
34595
|
`);
|
|
33853
|
-
|
|
34596
|
+
fs19.writeFileSync(
|
|
33854
34597
|
runnerPath,
|
|
33855
34598
|
`#!/bin/sh
|
|
33856
34599
|
cd ${shSingleQuote(cwd)}
|
|
@@ -33876,13 +34619,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
33876
34619
|
}
|
|
33877
34620
|
}
|
|
33878
34621
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
33879
|
-
const tmpRoot =
|
|
34622
|
+
const tmpRoot = fs19.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
33880
34623
|
const logPath = path23.join(tmpRoot, "combined.log");
|
|
33881
34624
|
const runnerPath = path23.join(tmpRoot, "_run.bat");
|
|
33882
34625
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
33883
34626
|
const com = process.env.ComSpec || "cmd.exe";
|
|
33884
34627
|
try {
|
|
33885
|
-
|
|
34628
|
+
fs19.writeFileSync(
|
|
33886
34629
|
runnerPath,
|
|
33887
34630
|
`@ECHO OFF\r
|
|
33888
34631
|
CD /D ${q(cwd)}\r
|
|
@@ -34236,7 +34979,9 @@ var DevServerManager = class {
|
|
|
34236
34979
|
async shutdownAllGraceful() {
|
|
34237
34980
|
const pairs = [...this.processes.entries()];
|
|
34238
34981
|
if (pairs.length === 0) return;
|
|
34239
|
-
this.log(
|
|
34982
|
+
this.log(
|
|
34983
|
+
`[dev-server] Stopping ${pairs.length} local dev server process${pairs.length === 1 ? "" : "es"}\u2026`
|
|
34984
|
+
);
|
|
34240
34985
|
await Promise.all(pairs.map(([serverId, proc]) => this.gracefulTerminateOrUnknown(serverId, proc)));
|
|
34241
34986
|
}
|
|
34242
34987
|
async gracefulTerminateOrUnknown(serverId, proc) {
|
|
@@ -34510,9 +35255,10 @@ var FIREHOSE_CLIENT_PING_MS = 25e3;
|
|
|
34510
35255
|
function connectFirehose(options) {
|
|
34511
35256
|
const { firehoseServerUrl, workspaceId, bridgeName, proxyPorts, log: log2, devServerManager, onOpen, onClose } = options;
|
|
34512
35257
|
const wsUrl = buildFirehoseCliWsUrl(firehoseServerUrl);
|
|
34513
|
-
|
|
35258
|
+
applyCliOutboundNetworkPreferences();
|
|
35259
|
+
const wsOptions = { perMessageDeflate: false, family: 4 };
|
|
34514
35260
|
if (wsUrl.startsWith("wss://")) {
|
|
34515
|
-
wsOptions.agent = new https2.Agent({ rejectUnauthorized: false });
|
|
35261
|
+
wsOptions.agent = new https2.Agent({ rejectUnauthorized: false, family: 4 });
|
|
34516
35262
|
}
|
|
34517
35263
|
const ws = new wrapper_default(wsUrl, wsOptions);
|
|
34518
35264
|
let clientPingTimer = null;
|
|
@@ -34548,16 +35294,14 @@ function connectFirehose(options) {
|
|
|
34548
35294
|
sendWsMessage(ws, { type: "identify", workspaceId, bridgeName, proxyPorts });
|
|
34549
35295
|
});
|
|
34550
35296
|
ws.on("message", (raw) => {
|
|
34551
|
-
|
|
34552
|
-
|
|
34553
|
-
|
|
34554
|
-
|
|
34555
|
-
|
|
34556
|
-
|
|
34557
|
-
|
|
34558
|
-
|
|
34559
|
-
}
|
|
34560
|
-
});
|
|
35297
|
+
if (Buffer.isBuffer(raw) && tryConsumeBinaryProxyBody(raw, deps)) {
|
|
35298
|
+
return;
|
|
35299
|
+
}
|
|
35300
|
+
try {
|
|
35301
|
+
const text = Buffer.isBuffer(raw) ? raw.toString("utf8") : String(raw);
|
|
35302
|
+
dispatchFirehoseJsonMessage(JSON.parse(text), deps);
|
|
35303
|
+
} catch {
|
|
35304
|
+
}
|
|
34561
35305
|
});
|
|
34562
35306
|
ws.on("close", (code, reason) => {
|
|
34563
35307
|
clearClientPing();
|
|
@@ -34603,6 +35347,9 @@ function createOnBridgeIdentified(opts) {
|
|
|
34603
35347
|
function attachFirehose(params) {
|
|
34604
35348
|
state.lastFirehoseParams = params;
|
|
34605
35349
|
clearFirehoseReconnectTimer();
|
|
35350
|
+
if (state.firehoseReconnectAttempt === 0) {
|
|
35351
|
+
logFn("Connecting to preview tunnel (local HTTP proxy and dev logs)\u2026");
|
|
35352
|
+
}
|
|
34606
35353
|
state.firehoseGeneration += 1;
|
|
34607
35354
|
const myGen = state.firehoseGeneration;
|
|
34608
35355
|
if (state.firehoseHandle) {
|
|
@@ -34621,8 +35368,8 @@ function createOnBridgeIdentified(opts) {
|
|
|
34621
35368
|
clearFirehoseReconnectQuietOnOpen({ firehoseQuiet: state.firehoseQuiet }, logFn);
|
|
34622
35369
|
const logOpenAsFirehoseReconnect = state.firehoseReconnectAttempt > 0;
|
|
34623
35370
|
state.firehoseReconnectAttempt = 0;
|
|
34624
|
-
if (logOpenAsFirehoseReconnect) {
|
|
34625
|
-
logFn("
|
|
35371
|
+
if (!logOpenAsFirehoseReconnect) {
|
|
35372
|
+
logFn("Connected to preview tunnel (local HTTP proxy and dev logs).");
|
|
34626
35373
|
}
|
|
34627
35374
|
},
|
|
34628
35375
|
onClose: (code, reason) => {
|
|
@@ -34690,47 +35437,19 @@ function createOnBridgeIdentified(opts) {
|
|
|
34690
35437
|
};
|
|
34691
35438
|
}
|
|
34692
35439
|
|
|
34693
|
-
// src/
|
|
34694
|
-
|
|
34695
|
-
|
|
34696
|
-
|
|
34697
|
-
|
|
34698
|
-
|
|
34699
|
-
|
|
34700
|
-
await execFileAsync4("which", ["agent"], { timeout: 4e3 });
|
|
34701
|
-
return true;
|
|
34702
|
-
} catch {
|
|
34703
|
-
return false;
|
|
34704
|
-
}
|
|
34705
|
-
},
|
|
34706
|
-
"codex-acp": async () => {
|
|
34707
|
-
try {
|
|
34708
|
-
await execFileAsync4("which", ["codex"], { timeout: 4e3 });
|
|
34709
|
-
return true;
|
|
34710
|
-
} catch {
|
|
34711
|
-
return false;
|
|
34712
|
-
}
|
|
34713
|
-
},
|
|
34714
|
-
"claude-code": async () => {
|
|
34715
|
-
try {
|
|
34716
|
-
await execFileAsync4("which", ["claude"], { timeout: 4e3 });
|
|
34717
|
-
return true;
|
|
34718
|
-
} catch {
|
|
34719
|
-
try {
|
|
34720
|
-
await execFileAsync4("npx", ["--yes", "@anthropic-ai/claude-code", "--version"], { timeout: 25e3 });
|
|
34721
|
-
return true;
|
|
34722
|
-
} catch {
|
|
34723
|
-
return false;
|
|
34724
|
-
}
|
|
34725
|
-
}
|
|
34726
|
-
}
|
|
34727
|
-
};
|
|
35440
|
+
// src/acp/detect-local-agent-types.ts
|
|
35441
|
+
var LOCAL_AGENT_ACP_MODULES = [
|
|
35442
|
+
cursor_acp_client_exports,
|
|
35443
|
+
codex_acp_client_exports,
|
|
35444
|
+
kiro_acp_client_exports,
|
|
35445
|
+
claude_code_acp_client_exports
|
|
35446
|
+
];
|
|
34728
35447
|
async function detectLocalAgentTypes() {
|
|
34729
35448
|
try {
|
|
34730
35449
|
const out = [];
|
|
34731
|
-
for (const
|
|
35450
|
+
for (const mod of LOCAL_AGENT_ACP_MODULES) {
|
|
34732
35451
|
try {
|
|
34733
|
-
if (await
|
|
35452
|
+
if (await mod.detectLocalAgentPresence()) out.push(mod.BACKEND_LOCAL_AGENT_TYPE);
|
|
34734
35453
|
} catch {
|
|
34735
35454
|
}
|
|
34736
35455
|
}
|
|
@@ -34820,8 +35539,8 @@ async function createBridgeConnection(options) {
|
|
|
34820
35539
|
clearMainBridgeReconnectQuietOnOpen(state, logFn);
|
|
34821
35540
|
state.reconnectAttempt = 0;
|
|
34822
35541
|
state.logBridgeOpenAsReconnect = false;
|
|
34823
|
-
if (logOpenAsPostRefreshReconnect) {
|
|
34824
|
-
logFn("
|
|
35542
|
+
if (!logOpenAsPostRefreshReconnect) {
|
|
35543
|
+
logFn("Connected to bridge service.");
|
|
34825
35544
|
}
|
|
34826
35545
|
const socket = getWs();
|
|
34827
35546
|
if (socket) {
|
|
@@ -34860,6 +35579,9 @@ async function createBridgeConnection(options) {
|
|
|
34860
35579
|
clearTimeout(state.reconnectTimeout);
|
|
34861
35580
|
state.reconnectTimeout = null;
|
|
34862
35581
|
}
|
|
35582
|
+
if (state.reconnectAttempt === 0) {
|
|
35583
|
+
logFn("Connecting to bridge service\u2026");
|
|
35584
|
+
}
|
|
34863
35585
|
const prev = state.currentWs;
|
|
34864
35586
|
if (prev) {
|
|
34865
35587
|
prev.removeAllListeners();
|
|
@@ -34932,15 +35654,17 @@ async function runBridge(options) {
|
|
|
34932
35654
|
onAuth: (_auth) => {
|
|
34933
35655
|
}
|
|
34934
35656
|
});
|
|
34935
|
-
const onSignal2 = (
|
|
34936
|
-
logImmediate(
|
|
35657
|
+
const onSignal2 = (kind) => {
|
|
35658
|
+
logImmediate(
|
|
35659
|
+
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|
|
35660
|
+
);
|
|
34937
35661
|
setImmediate(() => {
|
|
34938
35662
|
handle2.close();
|
|
34939
35663
|
process.exit(0);
|
|
34940
35664
|
});
|
|
34941
35665
|
};
|
|
34942
|
-
const onSigInt2 = () => onSignal2("
|
|
34943
|
-
const onSigTerm2 = () => onSignal2("
|
|
35666
|
+
const onSigInt2 = () => onSignal2("interrupt");
|
|
35667
|
+
const onSigTerm2 = () => onSignal2("stop");
|
|
34944
35668
|
process.on("SIGINT", onSigInt2);
|
|
34945
35669
|
process.on("SIGTERM", onSigTerm2);
|
|
34946
35670
|
const auth = await handle2.authPromise;
|
|
@@ -34989,16 +35713,18 @@ async function runBridge(options) {
|
|
|
34989
35713
|
});
|
|
34990
35714
|
}
|
|
34991
35715
|
});
|
|
34992
|
-
const onSignal = (
|
|
34993
|
-
logImmediate(
|
|
35716
|
+
const onSignal = (kind) => {
|
|
35717
|
+
logImmediate(
|
|
35718
|
+
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|
|
35719
|
+
);
|
|
34994
35720
|
setImmediate(() => {
|
|
34995
35721
|
void handle.close().then(() => {
|
|
34996
35722
|
process.exit(0);
|
|
34997
35723
|
});
|
|
34998
35724
|
});
|
|
34999
35725
|
};
|
|
35000
|
-
const onSigInt = () => onSignal("
|
|
35001
|
-
const onSigTerm = () => onSignal("
|
|
35726
|
+
const onSigInt = () => onSignal("interrupt");
|
|
35727
|
+
const onSigTerm = () => onSignal("stop");
|
|
35002
35728
|
process.on("SIGINT", onSigInt);
|
|
35003
35729
|
process.on("SIGTERM", onSigTerm);
|
|
35004
35730
|
}
|
|
@@ -35029,7 +35755,7 @@ async function main() {
|
|
|
35029
35755
|
if (opts.cwd && typeof opts.cwd === "string" && opts.cwd.trim()) {
|
|
35030
35756
|
const resolvedCwd = path24.resolve(process.cwd(), opts.cwd.trim());
|
|
35031
35757
|
try {
|
|
35032
|
-
const st =
|
|
35758
|
+
const st = fs20.statSync(resolvedCwd);
|
|
35033
35759
|
if (!st.isDirectory()) {
|
|
35034
35760
|
console.error(`--cwd is not a directory: ${resolvedCwd}`);
|
|
35035
35761
|
process.exit(1);
|