@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/index.js
CHANGED
|
@@ -21966,12 +21966,12 @@ var require_src2 = __commonJS({
|
|
|
21966
21966
|
function check2(path24, isFile, isDirectory) {
|
|
21967
21967
|
log2(`checking %s`, path24);
|
|
21968
21968
|
try {
|
|
21969
|
-
const
|
|
21970
|
-
if (
|
|
21969
|
+
const stat2 = fs_1.statSync(path24);
|
|
21970
|
+
if (stat2.isFile() && isFile) {
|
|
21971
21971
|
log2(`[OK] path represents a file`);
|
|
21972
21972
|
return true;
|
|
21973
21973
|
}
|
|
21974
|
-
if (
|
|
21974
|
+
if (stat2.isDirectory() && isDirectory) {
|
|
21975
21975
|
log2(`[OK] path represents a directory`);
|
|
21976
21976
|
return true;
|
|
21977
21977
|
}
|
|
@@ -22061,14 +22061,30 @@ var import_websocket = __toESM(require_websocket(), 1);
|
|
|
22061
22061
|
var import_websocket_server = __toESM(require_websocket_server(), 1);
|
|
22062
22062
|
var wrapper_default = import_websocket.default;
|
|
22063
22063
|
|
|
22064
|
+
// src/net/apply-cli-outbound-network-prefs.ts
|
|
22065
|
+
import dns from "node:dns";
|
|
22066
|
+
var applied = false;
|
|
22067
|
+
function applyCliOutboundNetworkPreferences() {
|
|
22068
|
+
if (applied) return;
|
|
22069
|
+
applied = true;
|
|
22070
|
+
try {
|
|
22071
|
+
dns.setDefaultResultOrder("ipv4first");
|
|
22072
|
+
} catch {
|
|
22073
|
+
}
|
|
22074
|
+
}
|
|
22075
|
+
|
|
22064
22076
|
// src/bridge/connection/create-ws-bridge.ts
|
|
22065
22077
|
var BRIDGE_AUTH_ERROR_HEADER = "x-bridge-auth-error";
|
|
22066
22078
|
var BRIDGE_AUTH_ERROR_TOKEN_INVALID = "token_invalid";
|
|
22067
22079
|
function createWsBridge(options) {
|
|
22068
22080
|
const { url: url2, onMessage, onOpen, onClose, onError: onError2, onAuthInvalid, clientPingIntervalMs } = options;
|
|
22069
|
-
|
|
22081
|
+
applyCliOutboundNetworkPreferences();
|
|
22082
|
+
const wsOptions = {
|
|
22083
|
+
perMessageDeflate: false,
|
|
22084
|
+
family: 4
|
|
22085
|
+
};
|
|
22070
22086
|
if (url2.startsWith("wss://")) {
|
|
22071
|
-
wsOptions.agent = new https.Agent({ rejectUnauthorized: false });
|
|
22087
|
+
wsOptions.agent = new https.Agent({ rejectUnauthorized: false, family: 4 });
|
|
22072
22088
|
}
|
|
22073
22089
|
const ws = new wrapper_default(url2, wsOptions);
|
|
22074
22090
|
let clientPingTimer = null;
|
|
@@ -22132,10 +22148,336 @@ function sendWsMessage(ws, payload) {
|
|
|
22132
22148
|
}
|
|
22133
22149
|
}
|
|
22134
22150
|
|
|
22135
|
-
//
|
|
22151
|
+
// ../types/dist/index.js
|
|
22152
|
+
init_zod();
|
|
22153
|
+
init_zod();
|
|
22154
|
+
init_zod();
|
|
22155
|
+
init_zod();
|
|
22156
|
+
init_zod();
|
|
22157
|
+
init_zod();
|
|
22158
|
+
init_zod();
|
|
22159
|
+
init_zod();
|
|
22160
|
+
init_zod();
|
|
22161
|
+
init_zod();
|
|
22162
|
+
init_zod();
|
|
22163
|
+
init_zod();
|
|
22164
|
+
var WorkItemStatusSchema = external_exports.enum(["backlog", "in-progress", "completed"]);
|
|
22165
|
+
var WorkItemProgressSchema = external_exports.object({
|
|
22166
|
+
remainingCriteria: external_exports.array(external_exports.string()).default([]),
|
|
22167
|
+
openQuestions: external_exports.array(external_exports.string()).default([]),
|
|
22168
|
+
assignedTo: external_exports.enum(["agent", "human-product", "human-expert"]).optional()
|
|
22169
|
+
});
|
|
22170
|
+
var ChangeSchema = external_exports.object({
|
|
22171
|
+
id: external_exports.string(),
|
|
22172
|
+
description: external_exports.string(),
|
|
22173
|
+
buildingBlockId: external_exports.string(),
|
|
22174
|
+
buildingBlockType: external_exports.enum(["function", "workflow", "connector", "ui-component", "app-fragment", "application", "project"]),
|
|
22175
|
+
action: external_exports.enum(["create", "update", "split", "combine"])
|
|
22176
|
+
});
|
|
22177
|
+
var CompletionCriterionSchema = external_exports.object({
|
|
22178
|
+
id: external_exports.string(),
|
|
22179
|
+
description: external_exports.string(),
|
|
22180
|
+
type: external_exports.enum(["write-code", "write-tests", "verify-tests", "other"]),
|
|
22181
|
+
verified: external_exports.boolean().default(false)
|
|
22182
|
+
});
|
|
22183
|
+
var WorkItemPrioritySchema = external_exports.enum(["low", "medium", "high", "critical"]);
|
|
22184
|
+
var IterationPhaseSchema = external_exports.enum(["analysis", "implementation", "verify", "reprioritize", "completed"]);
|
|
22185
|
+
var WorkItemDependencySchema = external_exports.object({
|
|
22186
|
+
type: external_exports.enum(["work-item"]),
|
|
22187
|
+
id: external_exports.string()
|
|
22188
|
+
});
|
|
22189
|
+
var WorkItemSchema = external_exports.object({
|
|
22190
|
+
id: external_exports.string(),
|
|
22191
|
+
sessionId: external_exports.string().optional(),
|
|
22192
|
+
summary: external_exports.string().optional(),
|
|
22193
|
+
description: external_exports.string(),
|
|
22194
|
+
status: WorkItemStatusSchema,
|
|
22195
|
+
buildingBlockId: external_exports.string().optional(),
|
|
22196
|
+
buildingBlockType: external_exports.enum(["function", "workflow", "connector", "ui-component", "app-fragment", "application", "project"]),
|
|
22197
|
+
changes: external_exports.array(ChangeSchema).default([]),
|
|
22198
|
+
completionCriteria: external_exports.array(CompletionCriterionSchema).default([]),
|
|
22199
|
+
priority: WorkItemPrioritySchema.default("medium"),
|
|
22200
|
+
dependencies: external_exports.array(WorkItemDependencySchema).default([]),
|
|
22201
|
+
assignedToUserId: external_exports.string().optional()
|
|
22202
|
+
});
|
|
22203
|
+
var UserWorkspaceProfileSchema = external_exports.object({
|
|
22204
|
+
id: external_exports.string(),
|
|
22205
|
+
workspaceId: external_exports.string(),
|
|
22206
|
+
userId: external_exports.string(),
|
|
22207
|
+
roleDescription: external_exports.string().optional(),
|
|
22208
|
+
expertiseAreas: external_exports.array(external_exports.string()),
|
|
22209
|
+
preferences: external_exports.record(external_exports.unknown()).optional(),
|
|
22210
|
+
learnings: external_exports.array(external_exports.string())
|
|
22211
|
+
});
|
|
22212
|
+
var WorkspaceOwnerInfoSchema = external_exports.object({
|
|
22213
|
+
ownerId: external_exports.string(),
|
|
22214
|
+
ownerName: external_exports.string().optional(),
|
|
22215
|
+
ownerEmail: external_exports.string().optional(),
|
|
22216
|
+
ownerProfilePictureUrl: external_exports.string().optional()
|
|
22217
|
+
});
|
|
22218
|
+
var WorkspaceRuntimeEntrySchema = external_exports.object({
|
|
22219
|
+
workspaceId: external_exports.string(),
|
|
22220
|
+
path: external_exports.string(),
|
|
22221
|
+
name: external_exports.string().optional(),
|
|
22222
|
+
owner: WorkspaceOwnerInfoSchema.optional(),
|
|
22223
|
+
isOwner: external_exports.boolean().optional()
|
|
22224
|
+
});
|
|
22225
|
+
var ProjectContextSchema = external_exports.object({
|
|
22226
|
+
projectId: external_exports.string(),
|
|
22227
|
+
context: external_exports.record(external_exports.unknown()).default({}),
|
|
22228
|
+
updatedAt: external_exports.string()
|
|
22229
|
+
});
|
|
22230
|
+
var WebSocketMessageTypeSchema = external_exports.enum([
|
|
22231
|
+
"plan-update",
|
|
22232
|
+
"work-item-update",
|
|
22233
|
+
"work-item-added",
|
|
22234
|
+
"work-item-removed",
|
|
22235
|
+
"project-processing-start",
|
|
22236
|
+
"project-processing-update",
|
|
22237
|
+
"project-processing-complete",
|
|
22238
|
+
"project-processing-error",
|
|
22239
|
+
"file-tool-request",
|
|
22240
|
+
"file-tool-response",
|
|
22241
|
+
"file-generated"
|
|
22242
|
+
]);
|
|
22243
|
+
var WebSocketMessageSchema = external_exports.object({
|
|
22244
|
+
type: WebSocketMessageTypeSchema,
|
|
22245
|
+
contextId: external_exports.string().optional(),
|
|
22246
|
+
data: external_exports.any().optional(),
|
|
22247
|
+
error: external_exports.string().optional()
|
|
22248
|
+
});
|
|
22249
|
+
var CheckpointKindSchema = external_exports.enum(["daily", "weekly", "overall"]);
|
|
22250
|
+
var CheckpointSummarySchema = external_exports.object({
|
|
22251
|
+
id: external_exports.string(),
|
|
22252
|
+
kind: CheckpointKindSchema,
|
|
22253
|
+
/** ISO date for daily (YYYY-MM-DD), ISO week for weekly, null for overall */
|
|
22254
|
+
periodKey: external_exports.string().nullable(),
|
|
22255
|
+
summary: external_exports.string(),
|
|
22256
|
+
createdAt: external_exports.string(),
|
|
22257
|
+
updatedAt: external_exports.string()
|
|
22258
|
+
});
|
|
22259
|
+
var ThreadMetaSchema = external_exports.object({
|
|
22260
|
+
threadId: external_exports.string(),
|
|
22261
|
+
workspaceId: external_exports.string(),
|
|
22262
|
+
/** External source (e.g. slack, discord); null if internal-only */
|
|
22263
|
+
externalSource: external_exports.string().nullable(),
|
|
22264
|
+
/** Id in the external system (e.g. channel_id + thread_ts) */
|
|
22265
|
+
externalId: external_exports.string().nullable(),
|
|
22266
|
+
title: external_exports.string().optional(),
|
|
22267
|
+
createdAt: external_exports.string(),
|
|
22268
|
+
updatedAt: external_exports.string()
|
|
22269
|
+
});
|
|
22270
|
+
var ThreadMessageSchema = external_exports.object({
|
|
22271
|
+
messageId: external_exports.string(),
|
|
22272
|
+
threadId: external_exports.string(),
|
|
22273
|
+
/** Role: user, assistant, system */
|
|
22274
|
+
role: external_exports.enum(["user", "assistant", "system"]),
|
|
22275
|
+
content: external_exports.string(),
|
|
22276
|
+
/** Optional reference to a ContentItem (e.g. doc, Notion page) */
|
|
22277
|
+
contentItemId: external_exports.string().nullable(),
|
|
22278
|
+
/** External message id if synced from external chat */
|
|
22279
|
+
externalId: external_exports.string().nullable(),
|
|
22280
|
+
createdAt: external_exports.string(),
|
|
22281
|
+
updatedAt: external_exports.string()
|
|
22282
|
+
});
|
|
22283
|
+
var ThreadCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
22284
|
+
threadId: external_exports.string()
|
|
22285
|
+
});
|
|
22286
|
+
var ContentSourceSchema = external_exports.enum(["notion", "doc", "slack_thread", "other"]);
|
|
22287
|
+
var ContentItemMetaSchema = external_exports.object({
|
|
22288
|
+
contentId: external_exports.string(),
|
|
22289
|
+
workspaceId: external_exports.string(),
|
|
22290
|
+
source: ContentSourceSchema,
|
|
22291
|
+
/** Id in the external system (e.g. Notion page id, doc url) */
|
|
22292
|
+
externalId: external_exports.string(),
|
|
22293
|
+
/** If source is slack_thread, points to Thread DO id */
|
|
22294
|
+
threadId: external_exports.string().nullable(),
|
|
22295
|
+
title: external_exports.string().optional(),
|
|
22296
|
+
createdAt: external_exports.string(),
|
|
22297
|
+
updatedAt: external_exports.string()
|
|
22298
|
+
});
|
|
22299
|
+
var ContentStorageRefSchema = external_exports.object({
|
|
22300
|
+
storageKey: external_exports.string(),
|
|
22301
|
+
/** Optional: mime type or format hint */
|
|
22302
|
+
contentType: external_exports.string().optional()
|
|
22303
|
+
});
|
|
22304
|
+
var ContentCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
22305
|
+
contentId: external_exports.string()
|
|
22306
|
+
});
|
|
22307
|
+
var StoryMetaSchema = external_exports.object({
|
|
22308
|
+
storyId: external_exports.string(),
|
|
22309
|
+
workspaceId: external_exports.string(),
|
|
22310
|
+
title: external_exports.string(),
|
|
22311
|
+
/** feature | bug | epic */
|
|
22312
|
+
kind: external_exports.enum(["feature", "bug", "epic"]).default("feature"),
|
|
22313
|
+
createdAt: external_exports.string(),
|
|
22314
|
+
updatedAt: external_exports.string()
|
|
22315
|
+
});
|
|
22316
|
+
var StoryContentItemRefSchema = external_exports.object({
|
|
22317
|
+
id: external_exports.string(),
|
|
22318
|
+
storyId: external_exports.string(),
|
|
22319
|
+
contentItemId: external_exports.string(),
|
|
22320
|
+
/** Snapshot summary when added to story (or updated) */
|
|
22321
|
+
summary: external_exports.string(),
|
|
22322
|
+
orderIndex: external_exports.number().default(0),
|
|
22323
|
+
createdAt: external_exports.string(),
|
|
22324
|
+
updatedAt: external_exports.string()
|
|
22325
|
+
});
|
|
22326
|
+
var StoryCheckpointSummarySchema = CheckpointSummarySchema.extend({
|
|
22327
|
+
storyId: external_exports.string()
|
|
22328
|
+
});
|
|
22329
|
+
var SessionMetaSchema = external_exports.object({
|
|
22330
|
+
sessionId: external_exports.string(),
|
|
22331
|
+
workspaceId: external_exports.string(),
|
|
22332
|
+
title: external_exports.string().optional(),
|
|
22333
|
+
createdAt: external_exports.string(),
|
|
22334
|
+
updatedAt: external_exports.string()
|
|
22335
|
+
});
|
|
22336
|
+
var SessionPromptSchema = external_exports.object({
|
|
22337
|
+
id: external_exports.string(),
|
|
22338
|
+
sessionId: external_exports.string(),
|
|
22339
|
+
/** text | resource */
|
|
22340
|
+
type: external_exports.enum(["text", "resource"]).default("text"),
|
|
22341
|
+
text: external_exports.string().optional(),
|
|
22342
|
+
resourceUri: external_exports.string().optional(),
|
|
22343
|
+
createdAt: external_exports.string()
|
|
22344
|
+
});
|
|
22345
|
+
var SessionResponseSchema = external_exports.object({
|
|
22346
|
+
id: external_exports.string(),
|
|
22347
|
+
sessionId: external_exports.string(),
|
|
22348
|
+
promptId: external_exports.string(),
|
|
22349
|
+
/** message | completion */
|
|
22350
|
+
kind: external_exports.enum(["message", "completion"]),
|
|
22351
|
+
content: external_exports.string().optional(),
|
|
22352
|
+
/** For completion: stopReason etc. */
|
|
22353
|
+
stopReason: external_exports.string().optional(),
|
|
22354
|
+
createdAt: external_exports.string()
|
|
22355
|
+
});
|
|
22356
|
+
var SessionToolCallSchema = external_exports.object({
|
|
22357
|
+
id: external_exports.string(),
|
|
22358
|
+
sessionId: external_exports.string(),
|
|
22359
|
+
promptId: external_exports.string(),
|
|
22360
|
+
name: external_exports.string(),
|
|
22361
|
+
params: external_exports.record(external_exports.unknown()).optional(),
|
|
22362
|
+
result: external_exports.record(external_exports.unknown()).optional(),
|
|
22363
|
+
createdAt: external_exports.string()
|
|
22364
|
+
});
|
|
22365
|
+
var SessionThreadRefSchema = external_exports.object({
|
|
22366
|
+
sessionId: external_exports.string(),
|
|
22367
|
+
threadId: external_exports.string(),
|
|
22368
|
+
addedAt: external_exports.string()
|
|
22369
|
+
});
|
|
22370
|
+
var ArtifactMetaSchema = external_exports.object({
|
|
22371
|
+
artifactId: external_exports.string(),
|
|
22372
|
+
workspaceId: external_exports.string(),
|
|
22373
|
+
/** Slug for permalink: /workspaces/:wid/artifacts/:slug */
|
|
22374
|
+
permalinkSlug: external_exports.string(),
|
|
22375
|
+
title: external_exports.string(),
|
|
22376
|
+
/** e.g. summary_report, build_log */
|
|
22377
|
+
type: external_exports.string().default("report"),
|
|
22378
|
+
/** Optional session that produced this artifact */
|
|
22379
|
+
sessionId: external_exports.string().nullable(),
|
|
22380
|
+
createdAt: external_exports.string(),
|
|
22381
|
+
updatedAt: external_exports.string()
|
|
22382
|
+
});
|
|
22383
|
+
var TemplateMetaSchema = external_exports.object({
|
|
22384
|
+
templateId: external_exports.string(),
|
|
22385
|
+
workspaceId: external_exports.string(),
|
|
22386
|
+
name: external_exports.string(),
|
|
22387
|
+
/** e.g. summary_report, build_log */
|
|
22388
|
+
artifactType: external_exports.string().optional(),
|
|
22389
|
+
createdAt: external_exports.string(),
|
|
22390
|
+
updatedAt: external_exports.string()
|
|
22391
|
+
});
|
|
22392
|
+
var GitRepoMetaSchema = external_exports.object({
|
|
22393
|
+
/** Stable id for the repo (e.g. hash of normalized canonical URL). Used for DO idFromName. */
|
|
22394
|
+
repoId: external_exports.string(),
|
|
22395
|
+
/** Canonical external URL (e.g. https://github.com/org/repo). Normalize before storing. */
|
|
22396
|
+
canonicalUrl: external_exports.string().url(),
|
|
22397
|
+
/** Optional workspace this repo was first linked in. */
|
|
22398
|
+
workspaceId: external_exports.string().nullable(),
|
|
22399
|
+
displayName: external_exports.string().optional(),
|
|
22400
|
+
createdAt: external_exports.string(),
|
|
22401
|
+
updatedAt: external_exports.string()
|
|
22402
|
+
});
|
|
22403
|
+
var LOCAL_AGENT_AUTH_ERROR_HINTS = {
|
|
22404
|
+
"kiro-acp": [/not logged in/i, /kiro-cli\s+login/i, /log in with kiro-cli/i],
|
|
22405
|
+
"cursor-cli": [/cursor_login/i, /authenticate.*cursor/i, /not logged in.*cursor/i, /run:\s*agent\s+login/i],
|
|
22406
|
+
"codex-acp": [
|
|
22407
|
+
/authentication failed/i,
|
|
22408
|
+
/not authenticated/i,
|
|
22409
|
+
/invalid.*api key/i,
|
|
22410
|
+
/sign in.*openai/i,
|
|
22411
|
+
/login.*openai/i,
|
|
22412
|
+
/unauthorized/i
|
|
22413
|
+
],
|
|
22414
|
+
"claude-code": [
|
|
22415
|
+
/ANTHROPIC_API_KEY/i,
|
|
22416
|
+
/not authenticated/i,
|
|
22417
|
+
/authentication failed/i,
|
|
22418
|
+
/claude\s+login/i,
|
|
22419
|
+
/please run.*claude.*login/i
|
|
22420
|
+
]
|
|
22421
|
+
};
|
|
22422
|
+
function localAgentErrorSuggestsAuth(agentType, errorText) {
|
|
22423
|
+
if (agentType == null || agentType === "" || errorText == null || !String(errorText).trim()) return false;
|
|
22424
|
+
const hints = LOCAL_AGENT_AUTH_ERROR_HINTS[agentType];
|
|
22425
|
+
if (!hints?.length) return false;
|
|
22426
|
+
return hints.some((re) => re.test(String(errorText)));
|
|
22427
|
+
}
|
|
22428
|
+
|
|
22429
|
+
// src/acp/clients/sdk-stdio-acp-client.ts
|
|
22136
22430
|
import { spawn } from "node:child_process";
|
|
22431
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
22432
|
+
import { dirname } from "node:path";
|
|
22137
22433
|
import { Readable, Writable } from "node:stream";
|
|
22138
22434
|
|
|
22435
|
+
// src/files/diff/unified-diff.ts
|
|
22436
|
+
function computeLineDiff(oldText, newText) {
|
|
22437
|
+
const oldLines = oldText.split("\n");
|
|
22438
|
+
const newLines = newText.split("\n");
|
|
22439
|
+
const m = oldLines.length;
|
|
22440
|
+
const n = newLines.length;
|
|
22441
|
+
const dp = Array(m + 1);
|
|
22442
|
+
for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
|
|
22443
|
+
for (let i2 = 1; i2 <= m; i2++) {
|
|
22444
|
+
for (let j2 = 1; j2 <= n; j2++) {
|
|
22445
|
+
if (oldLines[i2 - 1] === newLines[j2 - 1]) {
|
|
22446
|
+
dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
|
|
22447
|
+
} else {
|
|
22448
|
+
dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
22449
|
+
}
|
|
22450
|
+
}
|
|
22451
|
+
}
|
|
22452
|
+
const result = [];
|
|
22453
|
+
let i = m;
|
|
22454
|
+
let j = n;
|
|
22455
|
+
while (i > 0 || j > 0) {
|
|
22456
|
+
if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
|
|
22457
|
+
result.unshift({ type: "context", line: oldLines[i - 1] });
|
|
22458
|
+
i--;
|
|
22459
|
+
j--;
|
|
22460
|
+
} else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
|
|
22461
|
+
result.unshift({ type: "add", line: newLines[j - 1] });
|
|
22462
|
+
j--;
|
|
22463
|
+
} else {
|
|
22464
|
+
result.unshift({ type: "remove", line: oldLines[i - 1] });
|
|
22465
|
+
i--;
|
|
22466
|
+
}
|
|
22467
|
+
}
|
|
22468
|
+
return result;
|
|
22469
|
+
}
|
|
22470
|
+
function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
22471
|
+
const lines = computeLineDiff(oldText, newText);
|
|
22472
|
+
const out = [`--- ${filePath}`, `+++ ${filePath}`];
|
|
22473
|
+
for (const d of lines) {
|
|
22474
|
+
if (d.type === "add") out.push(`+${d.line}`);
|
|
22475
|
+
else if (d.type === "remove") out.push(`-${d.line}`);
|
|
22476
|
+
else out.push(` ${d.line}`);
|
|
22477
|
+
}
|
|
22478
|
+
return out.join("\n");
|
|
22479
|
+
}
|
|
22480
|
+
|
|
22139
22481
|
// src/files/cwd/bridge-workspace-directory.ts
|
|
22140
22482
|
import * as path from "node:path";
|
|
22141
22483
|
var bridgeWorkspaceDirectory = null;
|
|
@@ -22146,47 +22488,217 @@ function getBridgeWorkspaceDirectory() {
|
|
|
22146
22488
|
return bridgeWorkspaceDirectory;
|
|
22147
22489
|
}
|
|
22148
22490
|
|
|
22149
|
-
// src/acp/
|
|
22491
|
+
// src/acp/safe-fs-path.ts
|
|
22492
|
+
import * as path2 from "node:path";
|
|
22493
|
+
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
22494
|
+
const trimmed2 = filePath.trim();
|
|
22495
|
+
if (!trimmed2) return null;
|
|
22496
|
+
const normalizedCwd = path2.resolve(cwd);
|
|
22497
|
+
const resolved = path2.isAbsolute(trimmed2) ? path2.normalize(trimmed2) : path2.resolve(normalizedCwd, trimmed2);
|
|
22498
|
+
const rel = path2.relative(normalizedCwd, resolved);
|
|
22499
|
+
if (rel.startsWith("..") || path2.isAbsolute(rel)) return null;
|
|
22500
|
+
return resolved;
|
|
22501
|
+
}
|
|
22502
|
+
function toDisplayPathRelativeToCwd(cwd, absolutePath) {
|
|
22503
|
+
const normalizedCwd = path2.resolve(cwd);
|
|
22504
|
+
const rel = path2.relative(normalizedCwd, path2.resolve(absolutePath));
|
|
22505
|
+
if (!rel || rel === "") return path2.basename(absolutePath);
|
|
22506
|
+
return rel.split(path2.sep).join("/");
|
|
22507
|
+
}
|
|
22508
|
+
|
|
22509
|
+
// src/acp/clients/agent-stderr-capture.ts
|
|
22510
|
+
var STDERR_CAPTURE_MAX = 48e3;
|
|
22511
|
+
function createStderrCapture(child) {
|
|
22512
|
+
const chunks = [];
|
|
22513
|
+
let total = 0;
|
|
22514
|
+
return {
|
|
22515
|
+
append(chunk) {
|
|
22516
|
+
try {
|
|
22517
|
+
process.stderr.write(chunk);
|
|
22518
|
+
} catch {
|
|
22519
|
+
}
|
|
22520
|
+
if (total >= STDERR_CAPTURE_MAX) return;
|
|
22521
|
+
const n = Math.min(chunk.length, STDERR_CAPTURE_MAX - total);
|
|
22522
|
+
if (n <= 0) return;
|
|
22523
|
+
chunks.push(n === chunk.length ? chunk : chunk.subarray(0, n));
|
|
22524
|
+
total += n;
|
|
22525
|
+
},
|
|
22526
|
+
getText() {
|
|
22527
|
+
return Buffer.concat(chunks).toString("utf8").trim();
|
|
22528
|
+
}
|
|
22529
|
+
};
|
|
22530
|
+
}
|
|
22531
|
+
function formatJsonRpcStyleError(err) {
|
|
22532
|
+
if (err instanceof Error) return err.message;
|
|
22533
|
+
if (err != null && typeof err === "object") {
|
|
22534
|
+
const o = err;
|
|
22535
|
+
const msg = typeof o.message === "string" ? o.message : null;
|
|
22536
|
+
const code = o.code != null ? String(o.code) : "";
|
|
22537
|
+
if (msg) return code ? `[${code}] ${msg}` : msg;
|
|
22538
|
+
}
|
|
22539
|
+
if (typeof err === "string") return err;
|
|
22540
|
+
try {
|
|
22541
|
+
return JSON.stringify(err);
|
|
22542
|
+
} catch {
|
|
22543
|
+
return String(err);
|
|
22544
|
+
}
|
|
22545
|
+
}
|
|
22546
|
+
function mergeErrorWithStderr(primary, stderrText) {
|
|
22547
|
+
const s = stderrText.trim();
|
|
22548
|
+
const p = (primary ?? "").trim();
|
|
22549
|
+
if (!s) return p;
|
|
22550
|
+
if (!p) return s;
|
|
22551
|
+
if (p.includes(s) || s.includes(p)) return p.length >= s.length ? p : s;
|
|
22552
|
+
return `${p}
|
|
22553
|
+
${s}`;
|
|
22554
|
+
}
|
|
22555
|
+
|
|
22556
|
+
// src/acp/clients/kiro-sdk-ext-notifications.ts
|
|
22557
|
+
function createKiroSdkExtNotificationHandler(options) {
|
|
22558
|
+
const { onSessionUpdate } = options;
|
|
22559
|
+
return async (method, params) => {
|
|
22560
|
+
if (method === "_kiro.dev/metadata") {
|
|
22561
|
+
const p = params && typeof params === "object" ? params : {};
|
|
22562
|
+
const pct = p.contextUsagePercentage;
|
|
22563
|
+
if (typeof pct !== "number" || !Number.isFinite(pct) || !onSessionUpdate) return;
|
|
22564
|
+
onSessionUpdate({
|
|
22565
|
+
sessionUpdate: "context_usage",
|
|
22566
|
+
contextUsagePercentage: pct
|
|
22567
|
+
});
|
|
22568
|
+
return;
|
|
22569
|
+
}
|
|
22570
|
+
};
|
|
22571
|
+
}
|
|
22572
|
+
|
|
22573
|
+
// src/acp/clients/sdk-stdio-ext-notifications.ts
|
|
22574
|
+
var noopExtNotification = async () => {
|
|
22575
|
+
};
|
|
22576
|
+
function createSdkStdioExtNotificationHandler(options) {
|
|
22577
|
+
const { backendAgentType, onSessionUpdate } = options;
|
|
22578
|
+
switch (backendAgentType) {
|
|
22579
|
+
case "kiro-acp":
|
|
22580
|
+
return createKiroSdkExtNotificationHandler({ onSessionUpdate });
|
|
22581
|
+
default:
|
|
22582
|
+
return noopExtNotification;
|
|
22583
|
+
}
|
|
22584
|
+
}
|
|
22585
|
+
|
|
22586
|
+
// src/acp/clients/sdk-stdio-acp-client.ts
|
|
22150
22587
|
function formatSpawnError(err, command) {
|
|
22151
22588
|
if (err.code === "ENOENT") {
|
|
22152
22589
|
return `Command "${command}" not found. Install the agent (e.g. Cursor CLI) or add it to PATH.`;
|
|
22153
22590
|
}
|
|
22154
22591
|
return err.message || String(err);
|
|
22155
22592
|
}
|
|
22156
|
-
function
|
|
22157
|
-
if (
|
|
22158
|
-
|
|
22159
|
-
|
|
22160
|
-
|
|
22161
|
-
|
|
22162
|
-
|
|
22593
|
+
function sliceFileContentRange(content, line, limit) {
|
|
22594
|
+
if (line == null && limit == null) return content;
|
|
22595
|
+
const lines = content.split("\n");
|
|
22596
|
+
const start = line != null && line > 0 ? line - 1 : 0;
|
|
22597
|
+
const end = limit != null && limit > 0 ? start + limit : lines.length;
|
|
22598
|
+
return lines.slice(start, end).join("\n");
|
|
22599
|
+
}
|
|
22600
|
+
function bridgePayloadFromSdkSessionNotification(params) {
|
|
22601
|
+
return { sessionId: params.sessionId, ...params.update };
|
|
22163
22602
|
}
|
|
22164
|
-
async function
|
|
22165
|
-
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
22166
|
-
const {
|
|
22603
|
+
async function createSdkStdioAcpClient(options) {
|
|
22604
|
+
const { ClientSideConnection: ClientSideConnection2, ndJsonStream: ndJsonStream2, PROTOCOL_VERSION: PROTOCOL_VERSION2 } = await Promise.resolve().then(() => (init_acp(), acp_exports));
|
|
22605
|
+
const {
|
|
22606
|
+
command,
|
|
22607
|
+
cwd = getBridgeWorkspaceDirectory(),
|
|
22608
|
+
backendAgentType,
|
|
22609
|
+
onSessionUpdate,
|
|
22610
|
+
onFileChange,
|
|
22611
|
+
killSubprocessAfterCancelMs,
|
|
22612
|
+
onAgentSubprocessExit
|
|
22613
|
+
} = options;
|
|
22167
22614
|
const isWindows = process.platform === "win32";
|
|
22168
22615
|
const child = spawn(command[0], command.slice(1), {
|
|
22169
22616
|
cwd,
|
|
22170
|
-
stdio: ["pipe", "pipe", "
|
|
22617
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
22171
22618
|
env: process.env,
|
|
22172
22619
|
shell: isWindows
|
|
22173
22620
|
});
|
|
22621
|
+
const stderrCapture = createStderrCapture(child);
|
|
22622
|
+
child.once("close", (code, signal) => {
|
|
22623
|
+
onAgentSubprocessExit?.({ code, signal });
|
|
22624
|
+
});
|
|
22174
22625
|
return new Promise((resolve14, reject) => {
|
|
22626
|
+
let initSettled = false;
|
|
22627
|
+
const settleReject = (err) => {
|
|
22628
|
+
if (initSettled) return;
|
|
22629
|
+
initSettled = true;
|
|
22630
|
+
try {
|
|
22631
|
+
child.kill();
|
|
22632
|
+
} catch {
|
|
22633
|
+
}
|
|
22634
|
+
reject(err);
|
|
22635
|
+
};
|
|
22636
|
+
const settleResolve = (handle) => {
|
|
22637
|
+
if (initSettled) return;
|
|
22638
|
+
initSettled = true;
|
|
22639
|
+
resolve14(handle);
|
|
22640
|
+
};
|
|
22175
22641
|
child.on("error", (err) => {
|
|
22176
|
-
|
|
22177
|
-
|
|
22642
|
+
settleReject(new Error(formatSpawnError(err, command[0])));
|
|
22643
|
+
});
|
|
22644
|
+
child.stderr?.on("data", (chunk) => {
|
|
22645
|
+
stderrCapture.append(chunk);
|
|
22646
|
+
if (initSettled) return;
|
|
22647
|
+
const stderrText = stderrCapture.getText();
|
|
22648
|
+
if (backendAgentType && stderrText.trim() && localAgentErrorSuggestsAuth(backendAgentType, stderrText)) {
|
|
22649
|
+
settleReject(new Error(stderrText.trim()));
|
|
22650
|
+
}
|
|
22178
22651
|
});
|
|
22179
22652
|
(async () => {
|
|
22180
22653
|
try {
|
|
22181
22654
|
const writable = Writable.toWeb(child.stdin);
|
|
22182
22655
|
const readable = Readable.toWeb(child.stdout);
|
|
22183
22656
|
const stream = ndJsonStream2(writable, readable);
|
|
22657
|
+
const extNotification = createSdkStdioExtNotificationHandler({
|
|
22658
|
+
backendAgentType,
|
|
22659
|
+
onSessionUpdate
|
|
22660
|
+
});
|
|
22184
22661
|
const client = (_agent) => ({
|
|
22185
|
-
async requestPermission(
|
|
22186
|
-
|
|
22662
|
+
async requestPermission(params) {
|
|
22663
|
+
const opt = params?.options?.[0];
|
|
22664
|
+
if (opt && typeof opt.optionId === "string") {
|
|
22665
|
+
return { outcome: { outcome: "selected", optionId: opt.optionId } };
|
|
22666
|
+
}
|
|
22667
|
+
return { outcome: { outcome: "cancelled" } };
|
|
22668
|
+
},
|
|
22669
|
+
async readTextFile(params) {
|
|
22670
|
+
const abs = resolveSafePathUnderCwd(cwd, params.path);
|
|
22671
|
+
if (!abs) throw new Error("Invalid or disallowed path");
|
|
22672
|
+
try {
|
|
22673
|
+
let content = readFileSync(abs, "utf8");
|
|
22674
|
+
content = sliceFileContentRange(content, params.line, params.limit);
|
|
22675
|
+
return { content };
|
|
22676
|
+
} catch (e) {
|
|
22677
|
+
if (e.code === "ENOENT") return { content: "" };
|
|
22678
|
+
throw e;
|
|
22679
|
+
}
|
|
22680
|
+
},
|
|
22681
|
+
async writeTextFile(params) {
|
|
22682
|
+
const abs = resolveSafePathUnderCwd(cwd, params.path);
|
|
22683
|
+
if (!abs) throw new Error("Invalid or disallowed path");
|
|
22684
|
+
let oldText = "";
|
|
22685
|
+
try {
|
|
22686
|
+
oldText = readFileSync(abs, "utf8");
|
|
22687
|
+
} catch (e) {
|
|
22688
|
+
if (e.code !== "ENOENT") throw e;
|
|
22689
|
+
}
|
|
22690
|
+
mkdirSync(dirname(abs), { recursive: true });
|
|
22691
|
+
writeFileSync(abs, params.content, "utf8");
|
|
22692
|
+
const displayPath = toDisplayPathRelativeToCwd(cwd, abs);
|
|
22693
|
+
const patchContent = editSnippetToUnifiedDiff(displayPath, oldText, params.content);
|
|
22694
|
+
onFileChange?.({ path: displayPath, oldText, newText: params.content, patchContent });
|
|
22695
|
+
return {};
|
|
22187
22696
|
},
|
|
22188
22697
|
async sessionUpdate(params) {
|
|
22189
|
-
onSessionUpdate?.(params);
|
|
22698
|
+
onSessionUpdate?.(bridgePayloadFromSdkSessionNotification(params));
|
|
22699
|
+
},
|
|
22700
|
+
async extNotification(method, params) {
|
|
22701
|
+
await extNotification(method, params);
|
|
22190
22702
|
}
|
|
22191
22703
|
});
|
|
22192
22704
|
const connection = new ClientSideConnection2(client, stream);
|
|
@@ -22194,39 +22706,82 @@ async function createAcpClient(options) {
|
|
|
22194
22706
|
child.kill();
|
|
22195
22707
|
});
|
|
22196
22708
|
await connection.initialize({
|
|
22197
|
-
protocolVersion:
|
|
22198
|
-
|
|
22709
|
+
protocolVersion: PROTOCOL_VERSION2,
|
|
22710
|
+
clientCapabilities: {
|
|
22711
|
+
fs: { readTextFile: true, writeTextFile: true }
|
|
22712
|
+
},
|
|
22199
22713
|
clientInfo: { name: "buildautomaton-cli", version: "0.1.0" }
|
|
22200
22714
|
});
|
|
22201
|
-
const newSessionRes = await connection.newSession({
|
|
22715
|
+
const newSessionRes = await connection.newSession({ cwd, mcpServers: [] });
|
|
22202
22716
|
const sessionId = newSessionRes.sessionId;
|
|
22203
|
-
|
|
22717
|
+
settleResolve({
|
|
22204
22718
|
sessionId,
|
|
22205
22719
|
async sendPrompt(prompt, _options) {
|
|
22206
22720
|
try {
|
|
22207
22721
|
const response = await connection.prompt({
|
|
22208
22722
|
sessionId,
|
|
22209
|
-
prompt: { type: "text", text: prompt }
|
|
22723
|
+
prompt: [{ type: "text", text: prompt }]
|
|
22210
22724
|
});
|
|
22725
|
+
await new Promise((r2) => setImmediate(r2));
|
|
22211
22726
|
const r = response;
|
|
22212
|
-
const
|
|
22727
|
+
const stopReason = (r?.stopReason ?? "").toLowerCase();
|
|
22728
|
+
const cancelled = stopReason === "cancelled";
|
|
22729
|
+
const refusal = stopReason === "refusal";
|
|
22730
|
+
const stderrAfter = stderrCapture.getText();
|
|
22731
|
+
const agentType = backendAgentType ?? null;
|
|
22732
|
+
const stderrEvaluated = Boolean(stderrAfter && agentType);
|
|
22733
|
+
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
|
|
22734
|
+
if (cancelled) {
|
|
22735
|
+
return {
|
|
22736
|
+
success: false,
|
|
22737
|
+
stopReason: r?.stopReason,
|
|
22738
|
+
output: r?.output,
|
|
22739
|
+
error: mergeErrorWithStderr("Stopped by user", stderrAfter)
|
|
22740
|
+
};
|
|
22741
|
+
}
|
|
22742
|
+
if (refusal) {
|
|
22743
|
+
return {
|
|
22744
|
+
success: false,
|
|
22745
|
+
stopReason: r?.stopReason,
|
|
22746
|
+
output: r?.output,
|
|
22747
|
+
error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
|
|
22748
|
+
};
|
|
22749
|
+
}
|
|
22750
|
+
if (stderrSuggestsAuth) {
|
|
22751
|
+
return {
|
|
22752
|
+
success: false,
|
|
22753
|
+
stopReason: r?.stopReason,
|
|
22754
|
+
output: r?.output,
|
|
22755
|
+
error: stderrAfter
|
|
22756
|
+
};
|
|
22757
|
+
}
|
|
22213
22758
|
return {
|
|
22214
|
-
success:
|
|
22759
|
+
success: true,
|
|
22215
22760
|
stopReason: r?.stopReason,
|
|
22216
|
-
output: r?.output
|
|
22217
|
-
...cancelled ? { error: "Stopped by user" } : {}
|
|
22761
|
+
output: r?.output
|
|
22218
22762
|
};
|
|
22219
22763
|
} catch (err) {
|
|
22764
|
+
await new Promise((r) => setImmediate(r));
|
|
22765
|
+
const stderrAfter = stderrCapture.getText();
|
|
22766
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
|
|
22220
22767
|
return {
|
|
22221
22768
|
success: false,
|
|
22222
|
-
error:
|
|
22769
|
+
error: merged
|
|
22223
22770
|
};
|
|
22224
22771
|
}
|
|
22225
22772
|
},
|
|
22226
22773
|
async cancel() {
|
|
22227
|
-
|
|
22228
|
-
|
|
22229
|
-
|
|
22774
|
+
try {
|
|
22775
|
+
await connection.cancel({ sessionId });
|
|
22776
|
+
} catch {
|
|
22777
|
+
}
|
|
22778
|
+
if (killSubprocessAfterCancelMs != null && killSubprocessAfterCancelMs >= 0) {
|
|
22779
|
+
const t = setTimeout(() => {
|
|
22780
|
+
if (child.exitCode == null && child.signalCode == null) {
|
|
22781
|
+
child.kill("SIGTERM");
|
|
22782
|
+
}
|
|
22783
|
+
}, killSubprocessAfterCancelMs);
|
|
22784
|
+
t.unref?.();
|
|
22230
22785
|
}
|
|
22231
22786
|
},
|
|
22232
22787
|
resolveRequest() {
|
|
@@ -22236,8 +22791,14 @@ async function createAcpClient(options) {
|
|
|
22236
22791
|
}
|
|
22237
22792
|
});
|
|
22238
22793
|
} catch (err) {
|
|
22239
|
-
|
|
22240
|
-
|
|
22794
|
+
if (initSettled) return;
|
|
22795
|
+
try {
|
|
22796
|
+
child.kill();
|
|
22797
|
+
} catch {
|
|
22798
|
+
}
|
|
22799
|
+
const stderrText = stderrCapture.getText();
|
|
22800
|
+
const base = formatJsonRpcStyleError(err);
|
|
22801
|
+
settleReject(new Error(mergeErrorWithStderr(base, stderrText)));
|
|
22241
22802
|
}
|
|
22242
22803
|
})();
|
|
22243
22804
|
});
|
|
@@ -22540,11 +23101,11 @@ function logImmediate(line) {
|
|
|
22540
23101
|
|
|
22541
23102
|
// src/config.ts
|
|
22542
23103
|
import fs from "node:fs";
|
|
22543
|
-
import
|
|
23104
|
+
import path3 from "node:path";
|
|
22544
23105
|
import os from "node:os";
|
|
22545
23106
|
function getConfigPath() {
|
|
22546
|
-
const dir =
|
|
22547
|
-
return
|
|
23107
|
+
const dir = path3.join(os.homedir(), ".buildautomaton");
|
|
23108
|
+
return path3.join(dir, "config.json");
|
|
22548
23109
|
}
|
|
22549
23110
|
function normalizeApiUrl(url2) {
|
|
22550
23111
|
return url2.replace(/\/$/, "");
|
|
@@ -22560,7 +23121,7 @@ function readRawConfig() {
|
|
|
22560
23121
|
}
|
|
22561
23122
|
function writeConfigForApi(apiUrl, auth) {
|
|
22562
23123
|
const p = getConfigPath();
|
|
22563
|
-
const dir =
|
|
23124
|
+
const dir = path3.dirname(p);
|
|
22564
23125
|
const key = normalizeApiUrl(apiUrl);
|
|
22565
23126
|
const prev = readRawConfig() ?? {};
|
|
22566
23127
|
const servers = { ...prev.servers ?? {}, [key]: { ...auth } };
|
|
@@ -22755,7 +23316,7 @@ function beginMainBridgeDeferredDisconnect(state, code, reason, log2, willReconn
|
|
|
22755
23316
|
});
|
|
22756
23317
|
}
|
|
22757
23318
|
function clearMainBridgeReconnectQuietOnOpen(state, log2) {
|
|
22758
|
-
clearReconnectQuietOnSuccessfulConnection(state.mainQuiet, log2, "
|
|
23319
|
+
clearReconnectQuietOnSuccessfulConnection(state.mainQuiet, log2, "Bridge connection restored.");
|
|
22759
23320
|
}
|
|
22760
23321
|
function scheduleMainBridgeReconnect(state, connect, log2) {
|
|
22761
23322
|
if (state.closedByUser || state.currentWs != null) return;
|
|
@@ -22792,7 +23353,7 @@ function clearFirehoseReconnectQuietOnOpen(ctx, log2) {
|
|
|
22792
23353
|
clearReconnectQuietOnSuccessfulConnection(
|
|
22793
23354
|
ctx.firehoseQuiet,
|
|
22794
23355
|
log2,
|
|
22795
|
-
|
|
23356
|
+
"Preview tunnel restored (local HTTP proxy and dev logs)."
|
|
22796
23357
|
);
|
|
22797
23358
|
}
|
|
22798
23359
|
|
|
@@ -22943,7 +23504,7 @@ function buildBridgeUrl(apiUrl, workspaceId, authToken) {
|
|
|
22943
23504
|
|
|
22944
23505
|
// src/git/discover-repos.ts
|
|
22945
23506
|
import * as fs2 from "node:fs";
|
|
22946
|
-
import * as
|
|
23507
|
+
import * as path4 from "node:path";
|
|
22947
23508
|
|
|
22948
23509
|
// ../../node_modules/.pnpm/simple-git@3.32.3/node_modules/simple-git/dist/esm/index.js
|
|
22949
23510
|
var import_file_exists = __toESM(require_dist(), 1);
|
|
@@ -22952,7 +23513,7 @@ var import_promise_deferred = __toESM(require_dist2(), 1);
|
|
|
22952
23513
|
var import_promise_deferred2 = __toESM(require_dist2(), 1);
|
|
22953
23514
|
import { Buffer as Buffer2 } from "node:buffer";
|
|
22954
23515
|
import { spawn as spawn3 } from "child_process";
|
|
22955
|
-
import { normalize } from "node:path";
|
|
23516
|
+
import { normalize as normalize2 } from "node:path";
|
|
22956
23517
|
import { EventEmitter } from "node:events";
|
|
22957
23518
|
var __defProp2 = Object.defineProperty;
|
|
22958
23519
|
var __getOwnPropDesc2 = Object.getOwnPropertyDescriptor;
|
|
@@ -26255,7 +26816,7 @@ var init_branch = __esm2({
|
|
|
26255
26816
|
});
|
|
26256
26817
|
function toPath(input) {
|
|
26257
26818
|
const path24 = input.trim().replace(/^["']|["']$/g, "");
|
|
26258
|
-
return path24 &&
|
|
26819
|
+
return path24 && normalize2(path24);
|
|
26259
26820
|
}
|
|
26260
26821
|
var parseCheckIgnore;
|
|
26261
26822
|
var init_CheckIgnore = __esm2({
|
|
@@ -27530,7 +28091,7 @@ async function isGitRepoDirectory(dirPath) {
|
|
|
27530
28091
|
// src/git/discover-repos.ts
|
|
27531
28092
|
async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
|
|
27532
28093
|
const result = [];
|
|
27533
|
-
const cwdResolved =
|
|
28094
|
+
const cwdResolved = path4.resolve(cwd);
|
|
27534
28095
|
if (await isGitRepoDirectory(cwdResolved)) {
|
|
27535
28096
|
const remoteUrl = await getRemoteOriginUrl(cwdResolved);
|
|
27536
28097
|
result.push({ absolutePath: cwdResolved, remoteUrl });
|
|
@@ -27543,7 +28104,7 @@ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
|
|
|
27543
28104
|
}
|
|
27544
28105
|
for (const ent of entries) {
|
|
27545
28106
|
if (!ent.isDirectory()) continue;
|
|
27546
|
-
const childPath =
|
|
28107
|
+
const childPath = path4.join(cwdResolved, ent.name);
|
|
27547
28108
|
if (await isGitRepoDirectory(childPath)) {
|
|
27548
28109
|
const remoteUrl = await getRemoteOriginUrl(childPath);
|
|
27549
28110
|
result.push({ absolutePath: childPath, remoteUrl });
|
|
@@ -27552,11 +28113,11 @@ async function discoverGitRepos(cwd = getBridgeWorkspaceDirectory()) {
|
|
|
27552
28113
|
return result;
|
|
27553
28114
|
}
|
|
27554
28115
|
async function discoverGitReposUnderRoot(rootAbs) {
|
|
27555
|
-
const root =
|
|
28116
|
+
const root = path4.resolve(rootAbs);
|
|
27556
28117
|
const roots = [];
|
|
27557
28118
|
async function walk(dir) {
|
|
27558
28119
|
if (await isGitRepoDirectory(dir)) {
|
|
27559
|
-
roots.push(
|
|
28120
|
+
roots.push(path4.resolve(dir));
|
|
27560
28121
|
return;
|
|
27561
28122
|
}
|
|
27562
28123
|
let entries;
|
|
@@ -27567,7 +28128,7 @@ async function discoverGitReposUnderRoot(rootAbs) {
|
|
|
27567
28128
|
}
|
|
27568
28129
|
for (const ent of entries) {
|
|
27569
28130
|
if (!ent.isDirectory() || ent.name === ".git") continue;
|
|
27570
|
-
await walk(
|
|
28131
|
+
await walk(path4.join(dir, ent.name));
|
|
27571
28132
|
}
|
|
27572
28133
|
}
|
|
27573
28134
|
await walk(root);
|
|
@@ -27603,34 +28164,31 @@ function reportGitRepos(getWs, log2) {
|
|
|
27603
28164
|
|
|
27604
28165
|
// src/bridge/connection/close-bridge-connection.ts
|
|
27605
28166
|
async function closeBridgeConnection(state, acpManager, devServerManager, log2) {
|
|
27606
|
-
log2
|
|
28167
|
+
const say = log2 ?? logImmediate;
|
|
28168
|
+
say("Cleaning up connections\u2026");
|
|
27607
28169
|
await new Promise((resolve14) => setImmediate(resolve14));
|
|
27608
|
-
if (devServerManager) {
|
|
27609
|
-
log2?.("Requesting dev server processes to stop\u2026");
|
|
27610
|
-
await devServerManager.shutdownAllGraceful();
|
|
27611
|
-
}
|
|
27612
28170
|
state.closedByUser = true;
|
|
27613
28171
|
clearReconnectQuietTimer(state.mainQuiet);
|
|
27614
28172
|
clearReconnectQuietTimer(state.firehoseQuiet);
|
|
27615
28173
|
if (state.reconnectTimeout != null) {
|
|
27616
|
-
|
|
28174
|
+
say("Cancelling bridge reconnect timer\u2026");
|
|
27617
28175
|
clearTimeout(state.reconnectTimeout);
|
|
27618
28176
|
state.reconnectTimeout = null;
|
|
27619
28177
|
}
|
|
27620
28178
|
if (state.firehoseReconnectTimeout != null) {
|
|
27621
|
-
|
|
28179
|
+
say("Cancelling preview tunnel reconnect timer\u2026");
|
|
27622
28180
|
clearTimeout(state.firehoseReconnectTimeout);
|
|
27623
28181
|
state.firehoseReconnectTimeout = null;
|
|
27624
28182
|
}
|
|
27625
28183
|
if (state.firehoseHandle) {
|
|
27626
|
-
|
|
28184
|
+
say("Closing preview tunnel (local HTTP proxy and dev logs)\u2026");
|
|
27627
28185
|
state.firehoseHandle.close();
|
|
27628
28186
|
state.firehoseHandle = null;
|
|
27629
28187
|
}
|
|
27630
|
-
|
|
28188
|
+
say("Disconnecting local agent\u2026");
|
|
27631
28189
|
acpManager.disconnect();
|
|
27632
28190
|
if (state.currentWs) {
|
|
27633
|
-
|
|
28191
|
+
say("Closing bridge connection to the cloud\u2026");
|
|
27634
28192
|
state.currentWs.removeAllListeners();
|
|
27635
28193
|
const wsState = state.currentWs.readyState;
|
|
27636
28194
|
if (wsState === 1 || wsState === 2) {
|
|
@@ -27643,22 +28201,27 @@ async function closeBridgeConnection(state, acpManager, devServerManager, log2)
|
|
|
27643
28201
|
}
|
|
27644
28202
|
state.currentWs = null;
|
|
27645
28203
|
}
|
|
28204
|
+
if (devServerManager) {
|
|
28205
|
+
say("Stopping local dev server processes\u2026");
|
|
28206
|
+
await devServerManager.shutdownAllGraceful();
|
|
28207
|
+
}
|
|
28208
|
+
say("Shutdown complete.");
|
|
27646
28209
|
}
|
|
27647
28210
|
|
|
27648
28211
|
// src/git/session-git-queue.ts
|
|
27649
28212
|
import { execFile as execFile2 } from "node:child_process";
|
|
28213
|
+
import { readFile, stat } from "node:fs/promises";
|
|
27650
28214
|
import { promisify as promisify2 } from "node:util";
|
|
27651
|
-
import * as
|
|
27652
|
-
import * as path5 from "node:path";
|
|
28215
|
+
import * as path6 from "node:path";
|
|
27653
28216
|
|
|
27654
28217
|
// src/git/pre-turn-snapshot.ts
|
|
27655
28218
|
import * as fs3 from "node:fs";
|
|
27656
|
-
import * as
|
|
28219
|
+
import * as path5 from "node:path";
|
|
27657
28220
|
import { execFile } from "node:child_process";
|
|
27658
28221
|
import { promisify } from "node:util";
|
|
27659
28222
|
var execFileAsync = promisify(execFile);
|
|
27660
28223
|
function snapshotsDirForCwd(agentCwd) {
|
|
27661
|
-
return
|
|
28224
|
+
return path5.join(agentCwd, ".buildautomaton", "snapshots");
|
|
27662
28225
|
}
|
|
27663
28226
|
async function gitStashCreate(repoRoot, log2) {
|
|
27664
28227
|
try {
|
|
@@ -27687,7 +28250,7 @@ async function gitRun(repoRoot, args, log2, label) {
|
|
|
27687
28250
|
async function resolveSnapshotRepoRoots(options) {
|
|
27688
28251
|
const { worktreePaths, fallbackCwd, log: log2 } = options;
|
|
27689
28252
|
if (worktreePaths?.length) {
|
|
27690
|
-
const uniq = [...new Set(worktreePaths.map((p) =>
|
|
28253
|
+
const uniq = [...new Set(worktreePaths.map((p) => path5.resolve(p)))];
|
|
27691
28254
|
return uniq;
|
|
27692
28255
|
}
|
|
27693
28256
|
try {
|
|
@@ -27719,7 +28282,7 @@ async function capturePreTurnSnapshot(options) {
|
|
|
27719
28282
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
27720
28283
|
repos
|
|
27721
28284
|
};
|
|
27722
|
-
const filePath =
|
|
28285
|
+
const filePath = path5.join(dir, `${runId}.json`);
|
|
27723
28286
|
try {
|
|
27724
28287
|
fs3.writeFileSync(filePath, JSON.stringify(payload, null, 2), "utf8");
|
|
27725
28288
|
} catch (e) {
|
|
@@ -27757,17 +28320,17 @@ async function applyPreTurnSnapshot(filePath, log2) {
|
|
|
27757
28320
|
return { ok: true };
|
|
27758
28321
|
}
|
|
27759
28322
|
function snapshotFilePath(agentCwd, runId) {
|
|
27760
|
-
return
|
|
28323
|
+
return path5.join(snapshotsDirForCwd(agentCwd), `${runId}.json`);
|
|
27761
28324
|
}
|
|
27762
28325
|
|
|
27763
28326
|
// src/git/session-git-queue.ts
|
|
27764
28327
|
var execFileAsync2 = promisify2(execFile2);
|
|
27765
28328
|
var MAX_FULL_FILE_TEXT_BYTES = 512 * 1024;
|
|
27766
|
-
function readWorkspaceFileAsUtf8(absPath) {
|
|
28329
|
+
async function readWorkspaceFileAsUtf8(absPath) {
|
|
27767
28330
|
try {
|
|
27768
|
-
const st =
|
|
28331
|
+
const st = await stat(absPath);
|
|
27769
28332
|
if (!st.isFile() || st.size > MAX_FULL_FILE_TEXT_BYTES) return void 0;
|
|
27770
|
-
return
|
|
28333
|
+
return await readFile(absPath, "utf8");
|
|
27771
28334
|
} catch {
|
|
27772
28335
|
return void 0;
|
|
27773
28336
|
}
|
|
@@ -27777,7 +28340,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
27777
28340
|
const filePath = snapshotFilePath(agentCwd, runId);
|
|
27778
28341
|
let data;
|
|
27779
28342
|
try {
|
|
27780
|
-
const raw =
|
|
28343
|
+
const raw = await readFile(filePath, "utf8");
|
|
27781
28344
|
data = JSON.parse(raw);
|
|
27782
28345
|
} catch (e) {
|
|
27783
28346
|
log2(
|
|
@@ -27806,7 +28369,7 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
27806
28369
|
continue;
|
|
27807
28370
|
}
|
|
27808
28371
|
const lines = namesRaw.split("\n").map((l) => l.trim()).filter(Boolean);
|
|
27809
|
-
const slug =
|
|
28372
|
+
const slug = path6.basename(repo.path).replace(/[^\w.-]+/g, "_") || "repo";
|
|
27810
28373
|
for (const rel of lines) {
|
|
27811
28374
|
if (rel.includes("..")) continue;
|
|
27812
28375
|
try {
|
|
@@ -27820,8 +28383,8 @@ async function collectTurnGitDiffFromPreTurnSnapshot(options) {
|
|
|
27820
28383
|
);
|
|
27821
28384
|
if (!patchContent.trim()) continue;
|
|
27822
28385
|
const displayPath = multiRepo ? `${slug}/${rel}` : rel;
|
|
27823
|
-
const absFile =
|
|
27824
|
-
const newText = readWorkspaceFileAsUtf8(absFile);
|
|
28386
|
+
const absFile = path6.join(repo.path, rel);
|
|
28387
|
+
const newText = await readWorkspaceFileAsUtf8(absFile);
|
|
27825
28388
|
sendSessionUpdate({
|
|
27826
28389
|
type: "session_file_change",
|
|
27827
28390
|
sessionId,
|
|
@@ -27847,11 +28410,20 @@ async function sendPromptToAgent(options) {
|
|
|
27847
28410
|
promptId,
|
|
27848
28411
|
sessionId,
|
|
27849
28412
|
runId,
|
|
28413
|
+
agentType,
|
|
27850
28414
|
agentCwd,
|
|
27851
28415
|
sendResult,
|
|
27852
28416
|
sendSessionUpdate,
|
|
27853
28417
|
log: log2
|
|
27854
28418
|
} = options;
|
|
28419
|
+
function augmentAuthFields(errorText) {
|
|
28420
|
+
const err = errorText ?? "";
|
|
28421
|
+
const at = agentType ?? null;
|
|
28422
|
+
const evaluated = Boolean(at && err.trim());
|
|
28423
|
+
const suggestsAuth = evaluated && at ? localAgentErrorSuggestsAuth(at, err) : false;
|
|
28424
|
+
if (!suggestsAuth || !agentType) return {};
|
|
28425
|
+
return { agentAuthRequired: true, agentType };
|
|
28426
|
+
}
|
|
27855
28427
|
try {
|
|
27856
28428
|
const result = await handle.sendPrompt(promptText, {});
|
|
27857
28429
|
if (sessionId && runId && sendSessionUpdate && agentCwd && result.success) {
|
|
@@ -27863,12 +28435,14 @@ async function sendPromptToAgent(options) {
|
|
|
27863
28435
|
log: log2
|
|
27864
28436
|
});
|
|
27865
28437
|
}
|
|
28438
|
+
const errStr = typeof result.error === "string" ? result.error : void 0;
|
|
27866
28439
|
sendResult({
|
|
27867
28440
|
type: "prompt_result",
|
|
27868
28441
|
id: promptId,
|
|
27869
28442
|
...sessionId ? { sessionId } : {},
|
|
27870
28443
|
...runId ? { runId } : {},
|
|
27871
|
-
...result
|
|
28444
|
+
...result,
|
|
28445
|
+
...augmentAuthFields(errStr)
|
|
27872
28446
|
});
|
|
27873
28447
|
if (!result.success) {
|
|
27874
28448
|
log2(`[Agent] ${result.error ?? "Error"}`);
|
|
@@ -27876,20 +28450,20 @@ async function sendPromptToAgent(options) {
|
|
|
27876
28450
|
} catch (err) {
|
|
27877
28451
|
const errMsg = err instanceof Error ? err.message : String(err);
|
|
27878
28452
|
log2(`[Agent] Send failed: ${errMsg}`);
|
|
27879
|
-
if (err instanceof Error && err.stack) log2(`[Agent] ${err.stack}`);
|
|
27880
28453
|
sendResult({
|
|
27881
28454
|
type: "prompt_result",
|
|
27882
28455
|
id: promptId,
|
|
27883
28456
|
...sessionId ? { sessionId } : {},
|
|
27884
28457
|
...runId ? { runId } : {},
|
|
27885
28458
|
success: false,
|
|
27886
|
-
error: errMsg
|
|
28459
|
+
error: errMsg,
|
|
28460
|
+
...augmentAuthFields(errMsg)
|
|
27887
28461
|
});
|
|
27888
28462
|
}
|
|
27889
28463
|
}
|
|
27890
28464
|
|
|
27891
28465
|
// src/acp/ensure-acp-client.ts
|
|
27892
|
-
import * as
|
|
28466
|
+
import * as fs4 from "node:fs";
|
|
27893
28467
|
import * as path9 from "node:path";
|
|
27894
28468
|
|
|
27895
28469
|
// src/error-message.ts
|
|
@@ -27902,87 +28476,99 @@ function errorMessage(err) {
|
|
|
27902
28476
|
return String(err);
|
|
27903
28477
|
}
|
|
27904
28478
|
|
|
28479
|
+
// src/acp/clients/claude-code-acp-client.ts
|
|
28480
|
+
var claude_code_acp_client_exports = {};
|
|
28481
|
+
__export(claude_code_acp_client_exports, {
|
|
28482
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE,
|
|
28483
|
+
buildClaudeCodeAcpSpawnCommand: () => buildClaudeCodeAcpSpawnCommand,
|
|
28484
|
+
createClaudeCodeAcpClient: () => createClaudeCodeAcpClient,
|
|
28485
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence
|
|
28486
|
+
});
|
|
28487
|
+
import { execFile as execFile4 } from "node:child_process";
|
|
28488
|
+
import { promisify as promisify4 } from "node:util";
|
|
28489
|
+
|
|
28490
|
+
// src/acp/clients/detect-command-on-path.ts
|
|
28491
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
28492
|
+
import { promisify as promisify3 } from "node:util";
|
|
28493
|
+
var execFileAsync3 = promisify3(execFile3);
|
|
28494
|
+
async function isCommandOnPath(command, timeoutMs = 4e3) {
|
|
28495
|
+
try {
|
|
28496
|
+
await execFileAsync3("which", [command], { timeout: timeoutMs });
|
|
28497
|
+
return true;
|
|
28498
|
+
} catch {
|
|
28499
|
+
return false;
|
|
28500
|
+
}
|
|
28501
|
+
}
|
|
28502
|
+
|
|
28503
|
+
// src/acp/clients/claude-code-acp-client.ts
|
|
28504
|
+
var execFileAsync4 = promisify4(execFile4);
|
|
28505
|
+
var BACKEND_LOCAL_AGENT_TYPE = "claude-code";
|
|
28506
|
+
async function detectLocalAgentPresence() {
|
|
28507
|
+
if (await isCommandOnPath("claude")) return true;
|
|
28508
|
+
try {
|
|
28509
|
+
await execFileAsync4("npx", ["--yes", "@anthropic-ai/claude-code", "--version"], { timeout: 25e3 });
|
|
28510
|
+
return true;
|
|
28511
|
+
} catch {
|
|
28512
|
+
return false;
|
|
28513
|
+
}
|
|
28514
|
+
}
|
|
28515
|
+
function buildClaudeCodeAcpSpawnCommand(base, sessionMode) {
|
|
28516
|
+
if (!sessionMode) return [...base];
|
|
28517
|
+
const m = sessionMode.trim();
|
|
28518
|
+
if (m === "plan") return [...base, "--permission-mode", "plan"];
|
|
28519
|
+
return [...base];
|
|
28520
|
+
}
|
|
28521
|
+
async function createClaudeCodeAcpClient(options) {
|
|
28522
|
+
const command = buildClaudeCodeAcpSpawnCommand(options.command, options.sessionMode);
|
|
28523
|
+
return createSdkStdioAcpClient({
|
|
28524
|
+
...options,
|
|
28525
|
+
command,
|
|
28526
|
+
/** Claude-based agents sometimes ignore `session/cancel`; unblocks stop / stuck prompt. */
|
|
28527
|
+
killSubprocessAfterCancelMs: options.killSubprocessAfterCancelMs ?? 1e3
|
|
28528
|
+
});
|
|
28529
|
+
}
|
|
28530
|
+
|
|
27905
28531
|
// src/acp/clients/codex-acp-client.ts
|
|
28532
|
+
var codex_acp_client_exports = {};
|
|
28533
|
+
__export(codex_acp_client_exports, {
|
|
28534
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE2,
|
|
28535
|
+
DEFAULT_CODEX_ACP_COMMAND: () => DEFAULT_CODEX_ACP_COMMAND,
|
|
28536
|
+
buildCodexAcpSpawnCommand: () => buildCodexAcpSpawnCommand,
|
|
28537
|
+
createCodexAcpClient: () => createCodexAcpClient,
|
|
28538
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence2,
|
|
28539
|
+
isCodexAcpCommand: () => isCodexAcpCommand
|
|
28540
|
+
});
|
|
28541
|
+
var BACKEND_LOCAL_AGENT_TYPE2 = "codex-acp";
|
|
28542
|
+
async function detectLocalAgentPresence2() {
|
|
28543
|
+
return isCommandOnPath("codex");
|
|
28544
|
+
}
|
|
27906
28545
|
var DEFAULT_CODEX_ACP_COMMAND = ["npx", "--yes", "@zed-industries/codex-acp"];
|
|
27907
28546
|
function isCodexAcpCommand(command) {
|
|
27908
28547
|
const i = command.indexOf("@zed-industries/codex-acp");
|
|
27909
28548
|
return i >= 0 && (i === 0 || command[i - 1] === "npx" || command[i - 1] === "bunx");
|
|
27910
28549
|
}
|
|
28550
|
+
function buildCodexAcpSpawnCommand(base, _sessionMode) {
|
|
28551
|
+
return [...base];
|
|
28552
|
+
}
|
|
27911
28553
|
async function createCodexAcpClient(options) {
|
|
27912
|
-
const
|
|
27913
|
-
|
|
28554
|
+
const base = options.command?.length && options.command.some((a) => a.includes("codex-acp")) ? options.command : [...DEFAULT_CODEX_ACP_COMMAND];
|
|
28555
|
+
const command = buildCodexAcpSpawnCommand(base, options.sessionMode);
|
|
28556
|
+
return createSdkStdioAcpClient({ ...options, command });
|
|
27914
28557
|
}
|
|
27915
28558
|
|
|
27916
28559
|
// src/acp/clients/cursor-acp-client.ts
|
|
27917
|
-
|
|
27918
|
-
|
|
28560
|
+
var cursor_acp_client_exports = {};
|
|
28561
|
+
__export(cursor_acp_client_exports, {
|
|
28562
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE3,
|
|
28563
|
+
buildCursorAcpSpawnCommand: () => buildCursorAcpSpawnCommand,
|
|
28564
|
+
createCursorAcpClient: () => createCursorAcpClient,
|
|
28565
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence3
|
|
28566
|
+
});
|
|
28567
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "node:fs";
|
|
28568
|
+
import { dirname as dirname2 } from "node:path";
|
|
27919
28569
|
import { spawn as spawn4 } from "node:child_process";
|
|
27920
28570
|
import * as readline from "node:readline";
|
|
27921
28571
|
|
|
27922
|
-
// src/acp/safe-fs-path.ts
|
|
27923
|
-
import * as path6 from "node:path";
|
|
27924
|
-
function resolveSafePathUnderCwd(cwd, filePath) {
|
|
27925
|
-
const trimmed2 = filePath.trim();
|
|
27926
|
-
if (!trimmed2) return null;
|
|
27927
|
-
const normalizedCwd = path6.resolve(cwd);
|
|
27928
|
-
const resolved = path6.isAbsolute(trimmed2) ? path6.normalize(trimmed2) : path6.resolve(normalizedCwd, trimmed2);
|
|
27929
|
-
const rel = path6.relative(normalizedCwd, resolved);
|
|
27930
|
-
if (rel.startsWith("..") || path6.isAbsolute(rel)) return null;
|
|
27931
|
-
return resolved;
|
|
27932
|
-
}
|
|
27933
|
-
function toDisplayPathRelativeToCwd(cwd, absolutePath) {
|
|
27934
|
-
const normalizedCwd = path6.resolve(cwd);
|
|
27935
|
-
const rel = path6.relative(normalizedCwd, path6.resolve(absolutePath));
|
|
27936
|
-
if (!rel || rel === "") return path6.basename(absolutePath);
|
|
27937
|
-
return rel.split(path6.sep).join("/");
|
|
27938
|
-
}
|
|
27939
|
-
|
|
27940
|
-
// src/files/diff/unified-diff.ts
|
|
27941
|
-
function computeLineDiff(oldText, newText) {
|
|
27942
|
-
const oldLines = oldText.split("\n");
|
|
27943
|
-
const newLines = newText.split("\n");
|
|
27944
|
-
const m = oldLines.length;
|
|
27945
|
-
const n = newLines.length;
|
|
27946
|
-
const dp = Array(m + 1);
|
|
27947
|
-
for (let i2 = 0; i2 <= m; i2++) dp[i2] = Array(n + 1).fill(0);
|
|
27948
|
-
for (let i2 = 1; i2 <= m; i2++) {
|
|
27949
|
-
for (let j2 = 1; j2 <= n; j2++) {
|
|
27950
|
-
if (oldLines[i2 - 1] === newLines[j2 - 1]) {
|
|
27951
|
-
dp[i2][j2] = dp[i2 - 1][j2 - 1] + 1;
|
|
27952
|
-
} else {
|
|
27953
|
-
dp[i2][j2] = Math.max(dp[i2 - 1][j2], dp[i2][j2 - 1]);
|
|
27954
|
-
}
|
|
27955
|
-
}
|
|
27956
|
-
}
|
|
27957
|
-
const result = [];
|
|
27958
|
-
let i = m;
|
|
27959
|
-
let j = n;
|
|
27960
|
-
while (i > 0 || j > 0) {
|
|
27961
|
-
if (i > 0 && j > 0 && oldLines[i - 1] === newLines[j - 1]) {
|
|
27962
|
-
result.unshift({ type: "context", line: oldLines[i - 1] });
|
|
27963
|
-
i--;
|
|
27964
|
-
j--;
|
|
27965
|
-
} else if (j > 0 && (i === 0 || dp[i][j - 1] >= dp[i - 1][j])) {
|
|
27966
|
-
result.unshift({ type: "add", line: newLines[j - 1] });
|
|
27967
|
-
j--;
|
|
27968
|
-
} else {
|
|
27969
|
-
result.unshift({ type: "remove", line: oldLines[i - 1] });
|
|
27970
|
-
i--;
|
|
27971
|
-
}
|
|
27972
|
-
}
|
|
27973
|
-
return result;
|
|
27974
|
-
}
|
|
27975
|
-
function editSnippetToUnifiedDiff(filePath, oldText, newText) {
|
|
27976
|
-
const lines = computeLineDiff(oldText, newText);
|
|
27977
|
-
const out = [`--- ${filePath}`, `+++ ${filePath}`];
|
|
27978
|
-
for (const d of lines) {
|
|
27979
|
-
if (d.type === "add") out.push(`+${d.line}`);
|
|
27980
|
-
else if (d.type === "remove") out.push(`-${d.line}`);
|
|
27981
|
-
else out.push(` ${d.line}`);
|
|
27982
|
-
}
|
|
27983
|
-
return out.join("\n");
|
|
27984
|
-
}
|
|
27985
|
-
|
|
27986
28572
|
// src/acp/format-session-update-kind-for-log.ts
|
|
27987
28573
|
var SESSION_UPDATE_KIND_LABELS = {
|
|
27988
28574
|
tool_call: "Tool call",
|
|
@@ -28020,16 +28606,31 @@ function sliceLinesByRange(content, line, limit) {
|
|
|
28020
28606
|
const end = limit != null && limit > 0 ? start + limit : lines.length;
|
|
28021
28607
|
return lines.slice(start, end).join("\n");
|
|
28022
28608
|
}
|
|
28609
|
+
function buildCursorAcpSpawnCommand(base, sessionMode) {
|
|
28610
|
+
if (!sessionMode) return [...base];
|
|
28611
|
+
const m = sessionMode.trim();
|
|
28612
|
+
if (m !== "ask" && m !== "plan") return [...base];
|
|
28613
|
+
return [...base, "--mode", m];
|
|
28614
|
+
}
|
|
28023
28615
|
async function createCursorAcpClient(options) {
|
|
28024
|
-
const
|
|
28616
|
+
const command = buildCursorAcpSpawnCommand(options.command, options.sessionMode);
|
|
28617
|
+
const {
|
|
28618
|
+
cwd = getBridgeWorkspaceDirectory(),
|
|
28619
|
+
backendAgentType,
|
|
28620
|
+
onSessionUpdate,
|
|
28621
|
+
onRequest,
|
|
28622
|
+
onFileChange
|
|
28623
|
+
} = options;
|
|
28025
28624
|
const dbgFs = process.env.BUILDAMATON_DEBUG_ACP_FS === "1";
|
|
28026
28625
|
const isWindows = process.platform === "win32";
|
|
28027
28626
|
const child = spawn4(command[0], command.slice(1), {
|
|
28028
28627
|
cwd,
|
|
28029
|
-
stdio: ["pipe", "pipe", "
|
|
28628
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
28030
28629
|
env: process.env,
|
|
28031
28630
|
shell: isWindows
|
|
28032
28631
|
});
|
|
28632
|
+
const stderrCapture = createStderrCapture(child);
|
|
28633
|
+
child.stderr?.on("data", (chunk) => stderrCapture.append(chunk));
|
|
28033
28634
|
return new Promise((resolve14, reject) => {
|
|
28034
28635
|
child.on("error", (err) => {
|
|
28035
28636
|
child.kill();
|
|
@@ -28153,8 +28754,8 @@ async function createCursorAcpClient(options) {
|
|
|
28153
28754
|
}
|
|
28154
28755
|
}
|
|
28155
28756
|
try {
|
|
28156
|
-
|
|
28157
|
-
|
|
28757
|
+
mkdirSync3(dirname2(abs), { recursive: true });
|
|
28758
|
+
writeFileSync3(abs, newText, "utf8");
|
|
28158
28759
|
} catch (e) {
|
|
28159
28760
|
respondJsonRpcError(id, -32e3, e instanceof Error ? e.message : String(e));
|
|
28160
28761
|
return;
|
|
@@ -28213,17 +28814,52 @@ async function createCursorAcpClient(options) {
|
|
|
28213
28814
|
sessionId,
|
|
28214
28815
|
prompt: [{ type: "text", text: prompt }]
|
|
28215
28816
|
});
|
|
28817
|
+
await new Promise((r) => setImmediate(r));
|
|
28216
28818
|
const output = (result?.output ?? promptOutputBuffer) || void 0;
|
|
28217
|
-
const
|
|
28819
|
+
const stopReason = (result?.stopReason ?? "").toLowerCase();
|
|
28820
|
+
const cancelled = stopReason === "cancelled";
|
|
28821
|
+
const refusal = stopReason === "refusal";
|
|
28822
|
+
const stderrAfter = stderrCapture.getText();
|
|
28823
|
+
const agentType = backendAgentType ?? null;
|
|
28824
|
+
const stderrEvaluated = Boolean(stderrAfter && agentType);
|
|
28825
|
+
const stderrSuggestsAuth = stderrEvaluated ? localAgentErrorSuggestsAuth(agentType, stderrAfter) : false;
|
|
28826
|
+
if (cancelled) {
|
|
28827
|
+
return {
|
|
28828
|
+
success: false,
|
|
28829
|
+
stopReason: result?.stopReason,
|
|
28830
|
+
output: output || void 0,
|
|
28831
|
+
error: mergeErrorWithStderr("Stopped by user", stderrAfter)
|
|
28832
|
+
};
|
|
28833
|
+
}
|
|
28834
|
+
if (refusal) {
|
|
28835
|
+
return {
|
|
28836
|
+
success: false,
|
|
28837
|
+
stopReason: result?.stopReason,
|
|
28838
|
+
output: output || void 0,
|
|
28839
|
+
error: mergeErrorWithStderr("The agent refused the request.", stderrAfter)
|
|
28840
|
+
};
|
|
28841
|
+
}
|
|
28842
|
+
if (stderrSuggestsAuth) {
|
|
28843
|
+
return {
|
|
28844
|
+
success: false,
|
|
28845
|
+
stopReason: result?.stopReason,
|
|
28846
|
+
output: output || void 0,
|
|
28847
|
+
error: stderrAfter
|
|
28848
|
+
};
|
|
28849
|
+
}
|
|
28218
28850
|
return {
|
|
28219
|
-
success:
|
|
28851
|
+
success: true,
|
|
28220
28852
|
stopReason: result?.stopReason,
|
|
28221
|
-
output: output || void 0
|
|
28222
|
-
...cancelled ? { error: "Stopped by user" } : {}
|
|
28853
|
+
output: output || void 0
|
|
28223
28854
|
};
|
|
28224
28855
|
} catch (err) {
|
|
28225
|
-
|
|
28226
|
-
|
|
28856
|
+
await new Promise((r) => setImmediate(r));
|
|
28857
|
+
const stderrAfter = stderrCapture.getText();
|
|
28858
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrAfter);
|
|
28859
|
+
return {
|
|
28860
|
+
success: false,
|
|
28861
|
+
error: merged
|
|
28862
|
+
};
|
|
28227
28863
|
}
|
|
28228
28864
|
},
|
|
28229
28865
|
async cancel() {
|
|
@@ -28242,38 +28878,120 @@ async function createCursorAcpClient(options) {
|
|
|
28242
28878
|
});
|
|
28243
28879
|
} catch (err) {
|
|
28244
28880
|
child.kill();
|
|
28245
|
-
|
|
28881
|
+
const merged = mergeErrorWithStderr(formatJsonRpcStyleError(err), stderrCapture.getText());
|
|
28882
|
+
reject(merged ? new Error(merged) : err instanceof Error ? err : new Error(String(err)));
|
|
28246
28883
|
}
|
|
28247
28884
|
})();
|
|
28248
28885
|
});
|
|
28249
28886
|
}
|
|
28887
|
+
var BACKEND_LOCAL_AGENT_TYPE3 = "cursor-cli";
|
|
28888
|
+
async function detectLocalAgentPresence3() {
|
|
28889
|
+
return isCommandOnPath("agent");
|
|
28890
|
+
}
|
|
28891
|
+
|
|
28892
|
+
// src/acp/clients/kiro-acp-client.ts
|
|
28893
|
+
var kiro_acp_client_exports = {};
|
|
28894
|
+
__export(kiro_acp_client_exports, {
|
|
28895
|
+
BACKEND_LOCAL_AGENT_TYPE: () => BACKEND_LOCAL_AGENT_TYPE4,
|
|
28896
|
+
DEFAULT_KIRO_ACP_COMMAND: () => DEFAULT_KIRO_ACP_COMMAND,
|
|
28897
|
+
buildKiroAcpSpawnCommand: () => buildKiroAcpSpawnCommand,
|
|
28898
|
+
createKiroAcpClient: () => createKiroAcpClient,
|
|
28899
|
+
detectLocalAgentPresence: () => detectLocalAgentPresence4,
|
|
28900
|
+
isKiroAcpCommand: () => isKiroAcpCommand
|
|
28901
|
+
});
|
|
28902
|
+
var BACKEND_LOCAL_AGENT_TYPE4 = "kiro-acp";
|
|
28903
|
+
async function detectLocalAgentPresence4() {
|
|
28904
|
+
return isCommandOnPath("kiro-cli");
|
|
28905
|
+
}
|
|
28906
|
+
var DEFAULT_KIRO_ACP_COMMAND = ["kiro-cli", "acp"];
|
|
28907
|
+
function isKiroAcpCommand(command) {
|
|
28908
|
+
if (command.length < 2) return false;
|
|
28909
|
+
if (command[command.length - 1] !== "acp") return false;
|
|
28910
|
+
return command.slice(0, -1).some(
|
|
28911
|
+
(a) => a === "kiro-cli" || /[/\\]kiro-cli(\.exe)?$/i.test(a)
|
|
28912
|
+
);
|
|
28913
|
+
}
|
|
28914
|
+
function buildKiroAcpSpawnCommand(base, _sessionMode) {
|
|
28915
|
+
return [...base];
|
|
28916
|
+
}
|
|
28917
|
+
async function createKiroAcpClient(options) {
|
|
28918
|
+
const base = options.command?.length && isKiroAcpCommand(options.command) ? options.command : [...DEFAULT_KIRO_ACP_COMMAND];
|
|
28919
|
+
const command = buildKiroAcpSpawnCommand(base, options.sessionMode);
|
|
28920
|
+
return createSdkStdioAcpClient({ ...options, command });
|
|
28921
|
+
}
|
|
28250
28922
|
|
|
28251
28923
|
// src/acp/resolve-agent-command.ts
|
|
28252
28924
|
var AGENT_TYPE_DEFAULT_COMMANDS = {
|
|
28253
|
-
|
|
28254
|
-
|
|
28255
|
-
|
|
28925
|
+
[BACKEND_LOCAL_AGENT_TYPE3]: ["agent", "acp"],
|
|
28926
|
+
[BACKEND_LOCAL_AGENT_TYPE2]: [...DEFAULT_CODEX_ACP_COMMAND],
|
|
28927
|
+
/** ACP stdio agent; `@anthropic-ai/claude-code` is the interactive CLI and does not speak ACP on stdout. */
|
|
28928
|
+
[BACKEND_LOCAL_AGENT_TYPE]: ["npx", "--yes", "@agentclientprotocol/claude-agent-acp"],
|
|
28929
|
+
/** [Kiro CLI ACP](https://kiro.dev/docs/cli/acp/) — use full path to `kiro-cli` in PATH if the IDE cannot find it. */
|
|
28930
|
+
[BACKEND_LOCAL_AGENT_TYPE4]: [...DEFAULT_KIRO_ACP_COMMAND]
|
|
28256
28931
|
};
|
|
28932
|
+
var AGENT_TYPE_DISPLAY_NAMES = {
|
|
28933
|
+
[BACKEND_LOCAL_AGENT_TYPE3]: "Cursor",
|
|
28934
|
+
[BACKEND_LOCAL_AGENT_TYPE2]: "Codex",
|
|
28935
|
+
[BACKEND_LOCAL_AGENT_TYPE]: "Claude Code",
|
|
28936
|
+
[BACKEND_LOCAL_AGENT_TYPE4]: "Kiro"
|
|
28937
|
+
};
|
|
28938
|
+
function getAgentTypeDisplayName(agentType) {
|
|
28939
|
+
if (agentType == null || agentType === "") return "Unknown agent";
|
|
28940
|
+
const known = AGENT_TYPE_DISPLAY_NAMES[agentType];
|
|
28941
|
+
if (known) return known;
|
|
28942
|
+
return agentType.split(/[-_]/).filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1).toLowerCase()).join(" ");
|
|
28943
|
+
}
|
|
28257
28944
|
function useCursorAcp(agentType, command) {
|
|
28258
|
-
if (agentType ===
|
|
28945
|
+
if (agentType === BACKEND_LOCAL_AGENT_TYPE3) return true;
|
|
28259
28946
|
return command[0] === "agent" && command[1] === "acp";
|
|
28260
28947
|
}
|
|
28261
28948
|
function useCodexAcp(agentType, command) {
|
|
28262
|
-
if (agentType ===
|
|
28949
|
+
if (agentType === BACKEND_LOCAL_AGENT_TYPE2) return true;
|
|
28263
28950
|
return isCodexAcpCommand(command);
|
|
28264
28951
|
}
|
|
28952
|
+
function useKiroAcp(agentType, command) {
|
|
28953
|
+
if (agentType === BACKEND_LOCAL_AGENT_TYPE4) return true;
|
|
28954
|
+
return isKiroAcpCommand(command);
|
|
28955
|
+
}
|
|
28265
28956
|
function resolveAgentCommand(preferredAgentType) {
|
|
28266
28957
|
if (!preferredAgentType) return null;
|
|
28267
28958
|
const command = AGENT_TYPE_DEFAULT_COMMANDS[preferredAgentType];
|
|
28268
28959
|
if (!command?.length) return null;
|
|
28269
|
-
|
|
28270
|
-
|
|
28271
|
-
|
|
28960
|
+
if (useCursorAcp(preferredAgentType, command)) {
|
|
28961
|
+
return {
|
|
28962
|
+
command,
|
|
28963
|
+
label: preferredAgentType,
|
|
28964
|
+
createClient: createCursorAcpClient,
|
|
28965
|
+
spawnCommandForSession: (sessionMode) => buildCursorAcpSpawnCommand(command, sessionMode)
|
|
28966
|
+
};
|
|
28967
|
+
}
|
|
28968
|
+
if (useCodexAcp(preferredAgentType, command)) {
|
|
28969
|
+
return {
|
|
28970
|
+
command,
|
|
28971
|
+
label: preferredAgentType,
|
|
28972
|
+
createClient: createCodexAcpClient,
|
|
28973
|
+
spawnCommandForSession: (sessionMode) => buildCodexAcpSpawnCommand(command, sessionMode)
|
|
28974
|
+
};
|
|
28975
|
+
}
|
|
28976
|
+
if (useKiroAcp(preferredAgentType, command)) {
|
|
28977
|
+
return {
|
|
28978
|
+
command,
|
|
28979
|
+
label: preferredAgentType,
|
|
28980
|
+
createClient: createKiroAcpClient,
|
|
28981
|
+
spawnCommandForSession: (sessionMode) => buildKiroAcpSpawnCommand(command, sessionMode)
|
|
28982
|
+
};
|
|
28983
|
+
}
|
|
28984
|
+
return {
|
|
28985
|
+
command,
|
|
28986
|
+
label: preferredAgentType,
|
|
28987
|
+
createClient: createClaudeCodeAcpClient,
|
|
28988
|
+
spawnCommandForSession: (sessionMode) => buildClaudeCodeAcpSpawnCommand(command, sessionMode)
|
|
28989
|
+
};
|
|
28272
28990
|
}
|
|
28273
28991
|
|
|
28274
28992
|
// src/acp/session-file-change-path-kind.ts
|
|
28275
28993
|
import { execFileSync as execFileSync3 } from "node:child_process";
|
|
28276
|
-
import { existsSync, statSync
|
|
28994
|
+
import { existsSync, statSync } from "node:fs";
|
|
28277
28995
|
|
|
28278
28996
|
// src/git/get-git-repo-root-sync.ts
|
|
28279
28997
|
import { execFileSync } from "node:child_process";
|
|
@@ -28382,7 +29100,7 @@ function getSessionFileChangeDirectoryFlags(cwd, displayPath) {
|
|
|
28382
29100
|
const abs = tryWorkspaceDisplayToAbs(cwd, displayPath);
|
|
28383
29101
|
if (abs && existsSync(abs)) {
|
|
28384
29102
|
try {
|
|
28385
|
-
if (
|
|
29103
|
+
if (statSync(abs).isDirectory()) {
|
|
28386
29104
|
return { isDirectory: true, directoryRemoved: false };
|
|
28387
29105
|
}
|
|
28388
29106
|
return { isDirectory: false, directoryRemoved: false };
|
|
@@ -28928,7 +29646,8 @@ async function ensureAcpClient(options) {
|
|
|
28928
29646
|
state.lastAcpStartError = "No agent type: ensure the app sends agentType on prompts or agent_config for this bridge.";
|
|
28929
29647
|
return null;
|
|
28930
29648
|
}
|
|
28931
|
-
const
|
|
29649
|
+
const fullCmd = resolved.spawnCommandForSession(mode);
|
|
29650
|
+
const agentKey = `${resolved.label}::${fullCmd.join("\0")}`;
|
|
28932
29651
|
if (state.acpHandle && state.acpAgentKey !== agentKey) {
|
|
28933
29652
|
try {
|
|
28934
29653
|
state.acpHandle.disconnect();
|
|
@@ -28942,7 +29661,7 @@ async function ensureAcpClient(options) {
|
|
|
28942
29661
|
if (!state.acpStartPromise) {
|
|
28943
29662
|
let statOk = false;
|
|
28944
29663
|
try {
|
|
28945
|
-
const st =
|
|
29664
|
+
const st = fs4.statSync(targetCwd);
|
|
28946
29665
|
statOk = st.isDirectory();
|
|
28947
29666
|
if (!statOk) {
|
|
28948
29667
|
state.lastAcpStartError = `Agent cwd is not a directory: ${targetCwd}`;
|
|
@@ -28955,8 +29674,6 @@ async function ensureAcpClient(options) {
|
|
|
28955
29674
|
if (!statOk) {
|
|
28956
29675
|
return null;
|
|
28957
29676
|
}
|
|
28958
|
-
const modeFlag = mode && ["ask", "plan"].includes(mode) ? ["--mode", mode] : [];
|
|
28959
|
-
const fullCmd = [...resolved.command, ...modeFlag];
|
|
28960
29677
|
const hooks = buildAcpSessionBridgeHooks({
|
|
28961
29678
|
routing,
|
|
28962
29679
|
getSendSessionUpdate: () => sendSessionUpdate,
|
|
@@ -28964,8 +29681,16 @@ async function ensureAcpClient(options) {
|
|
|
28964
29681
|
log: log2
|
|
28965
29682
|
});
|
|
28966
29683
|
state.acpStartPromise = resolved.createClient({
|
|
28967
|
-
command:
|
|
29684
|
+
command: resolved.command,
|
|
29685
|
+
sessionMode: mode,
|
|
28968
29686
|
cwd: targetCwd,
|
|
29687
|
+
backendAgentType: preferredAgentType,
|
|
29688
|
+
onAgentSubprocessExit: () => {
|
|
29689
|
+
state.acpHandle = null;
|
|
29690
|
+
state.acpStartPromise = null;
|
|
29691
|
+
state.acpAgentKey = null;
|
|
29692
|
+
state.lastAcpStartError = "Agent subprocess exited";
|
|
29693
|
+
},
|
|
28969
29694
|
...hooks
|
|
28970
29695
|
}).then((h) => {
|
|
28971
29696
|
state.lastAcpStartError = null;
|
|
@@ -29003,6 +29728,14 @@ async function createAcpManager(options) {
|
|
|
29003
29728
|
backendFallbackAgentType = agentType;
|
|
29004
29729
|
}
|
|
29005
29730
|
}
|
|
29731
|
+
function logPromptReceivedFromBridge(opts) {
|
|
29732
|
+
const { agentType, mode } = opts;
|
|
29733
|
+
const preferredForPrompt = agentType ?? backendFallbackAgentType ?? null;
|
|
29734
|
+
const modeLabel = typeof mode === "string" && mode.trim() !== "" ? mode.trim() : "not set";
|
|
29735
|
+
log2(
|
|
29736
|
+
`[Agent] Prompt received (${getAgentTypeDisplayName(preferredForPrompt)}, mode: ${modeLabel})`
|
|
29737
|
+
);
|
|
29738
|
+
}
|
|
29006
29739
|
function handlePrompt(opts) {
|
|
29007
29740
|
const {
|
|
29008
29741
|
promptText,
|
|
@@ -29032,17 +29765,24 @@ async function createAcpManager(options) {
|
|
|
29032
29765
|
log: log2
|
|
29033
29766
|
});
|
|
29034
29767
|
if (!handle) {
|
|
29768
|
+
const errMsg = state.lastAcpStartError || "No agent configured. Register local agents on this bridge in the app.";
|
|
29769
|
+
const evaluated = Boolean(preferredForPrompt && errMsg.trim());
|
|
29770
|
+
const suggestsAuth = evaluated ? localAgentErrorSuggestsAuth(preferredForPrompt, errMsg) : false;
|
|
29771
|
+
const auth = suggestsAuth && preferredForPrompt ? { agentAuthRequired: true, agentType: preferredForPrompt } : {};
|
|
29035
29772
|
sendResult({
|
|
29036
29773
|
type: "prompt_result",
|
|
29037
29774
|
id: promptId,
|
|
29038
29775
|
...sessionId ? { sessionId } : {},
|
|
29039
29776
|
...runId ? { runId } : {},
|
|
29040
29777
|
success: false,
|
|
29041
|
-
error:
|
|
29778
|
+
error: errMsg,
|
|
29779
|
+
...auth
|
|
29042
29780
|
});
|
|
29043
29781
|
return;
|
|
29044
29782
|
}
|
|
29045
|
-
if (promptRouting.sessionId !== sessionId || promptRouting.runId !== runId)
|
|
29783
|
+
if (promptRouting.sessionId !== sessionId || promptRouting.runId !== runId) {
|
|
29784
|
+
return;
|
|
29785
|
+
}
|
|
29046
29786
|
if (runId && pendingCancelRunId === runId) {
|
|
29047
29787
|
pendingCancelRunId = void 0;
|
|
29048
29788
|
try {
|
|
@@ -29066,6 +29806,7 @@ async function createAcpManager(options) {
|
|
|
29066
29806
|
promptId,
|
|
29067
29807
|
sessionId,
|
|
29068
29808
|
runId,
|
|
29809
|
+
agentType: preferredForPrompt,
|
|
29069
29810
|
agentCwd: cwd,
|
|
29070
29811
|
sendResult,
|
|
29071
29812
|
sendSessionUpdate,
|
|
@@ -29083,6 +29824,7 @@ async function createAcpManager(options) {
|
|
|
29083
29824
|
if (promptRouting.runId !== runId) return false;
|
|
29084
29825
|
const handle = state.acpHandle;
|
|
29085
29826
|
if (handle?.cancel) {
|
|
29827
|
+
log2("[Agent] Stop requested");
|
|
29086
29828
|
try {
|
|
29087
29829
|
await handle.cancel();
|
|
29088
29830
|
return true;
|
|
@@ -29091,6 +29833,7 @@ async function createAcpManager(options) {
|
|
|
29091
29833
|
return false;
|
|
29092
29834
|
}
|
|
29093
29835
|
}
|
|
29836
|
+
log2("[Agent] Stop requested (agent still starting)");
|
|
29094
29837
|
pendingCancelRunId = runId;
|
|
29095
29838
|
return true;
|
|
29096
29839
|
}
|
|
@@ -29103,7 +29846,14 @@ async function createAcpManager(options) {
|
|
|
29103
29846
|
state.acpStartPromise = null;
|
|
29104
29847
|
state.acpAgentKey = null;
|
|
29105
29848
|
}
|
|
29106
|
-
return {
|
|
29849
|
+
return {
|
|
29850
|
+
setPreferredAgentType,
|
|
29851
|
+
logPromptReceivedFromBridge,
|
|
29852
|
+
handlePrompt,
|
|
29853
|
+
cancelRun,
|
|
29854
|
+
resolveRequest,
|
|
29855
|
+
disconnect
|
|
29856
|
+
};
|
|
29107
29857
|
}
|
|
29108
29858
|
|
|
29109
29859
|
// src/bridge/routing/handlers/auth-token.ts
|
|
@@ -29154,8 +29904,8 @@ var handleAgentConfigMessage = (msg, deps) => {
|
|
|
29154
29904
|
|
|
29155
29905
|
// src/acp/from-bridge/handle-bridge-prompt.ts
|
|
29156
29906
|
import * as path11 from "node:path";
|
|
29157
|
-
import { execFile as
|
|
29158
|
-
import { promisify as
|
|
29907
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
29908
|
+
import { promisify as promisify5 } from "node:util";
|
|
29159
29909
|
|
|
29160
29910
|
// src/git/bridge-queue-key.ts
|
|
29161
29911
|
import * as path10 from "node:path";
|
|
@@ -29213,10 +29963,10 @@ async function resolveBridgeQueueBindFields(options) {
|
|
|
29213
29963
|
}
|
|
29214
29964
|
|
|
29215
29965
|
// src/acp/from-bridge/handle-bridge-prompt.ts
|
|
29216
|
-
var
|
|
29966
|
+
var execFileAsync5 = promisify5(execFile5);
|
|
29217
29967
|
async function readGitBranch(cwd) {
|
|
29218
29968
|
try {
|
|
29219
|
-
const { stdout } = await
|
|
29969
|
+
const { stdout } = await execFileAsync5("git", ["branch", "--show-current"], { cwd, maxBuffer: 64 * 1024 });
|
|
29220
29970
|
const b = stdout.trim();
|
|
29221
29971
|
return b || null;
|
|
29222
29972
|
} catch {
|
|
@@ -29238,6 +29988,8 @@ function handleBridgePrompt(msg, deps) {
|
|
|
29238
29988
|
const sessionWorktreesEnabled = msg.sessionWorktreesEnabled === true;
|
|
29239
29989
|
const agentType = typeof msg.agentType === "string" && msg.agentType.trim() ? msg.agentType.trim() : void 0;
|
|
29240
29990
|
const runId = typeof msg.runId === "string" ? msg.runId : void 0;
|
|
29991
|
+
const mode = typeof msg.mode === "string" && msg.mode.trim() ? msg.mode.trim() : void 0;
|
|
29992
|
+
acpManager.logPromptReceivedFromBridge({ agentType, mode });
|
|
29241
29993
|
const sendResult = (result) => {
|
|
29242
29994
|
const s = getWs();
|
|
29243
29995
|
if (s) sendWsMessage(s, result);
|
|
@@ -29300,7 +30052,7 @@ function handleBridgePrompt(msg, deps) {
|
|
|
29300
30052
|
promptId: msg.id,
|
|
29301
30053
|
sessionId,
|
|
29302
30054
|
runId,
|
|
29303
|
-
mode
|
|
30055
|
+
mode,
|
|
29304
30056
|
agentType,
|
|
29305
30057
|
cwd: effectiveCwd,
|
|
29306
30058
|
sendResult,
|
|
@@ -29370,7 +30122,7 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
29370
30122
|
};
|
|
29371
30123
|
|
|
29372
30124
|
// src/files/list-dir.ts
|
|
29373
|
-
import
|
|
30125
|
+
import fs5 from "node:fs";
|
|
29374
30126
|
import path13 from "node:path";
|
|
29375
30127
|
|
|
29376
30128
|
// src/files/ensure-under-cwd.ts
|
|
@@ -29391,14 +30143,14 @@ function listDir(relativePath) {
|
|
|
29391
30143
|
return { error: "Path is outside working directory" };
|
|
29392
30144
|
}
|
|
29393
30145
|
try {
|
|
29394
|
-
const names =
|
|
30146
|
+
const names = fs5.readdirSync(resolved, { withFileTypes: true });
|
|
29395
30147
|
const entries = names.filter((d) => !d.name.startsWith(".")).map((d) => {
|
|
29396
30148
|
const entryPath = path13.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
29397
30149
|
const fullPath = path13.join(resolved, d.name);
|
|
29398
30150
|
let isDir = d.isDirectory();
|
|
29399
30151
|
if (d.isSymbolicLink()) {
|
|
29400
30152
|
try {
|
|
29401
|
-
const targetStat =
|
|
30153
|
+
const targetStat = fs5.statSync(fullPath);
|
|
29402
30154
|
isDir = targetStat.isDirectory();
|
|
29403
30155
|
} catch {
|
|
29404
30156
|
isDir = false;
|
|
@@ -29422,25 +30174,25 @@ function listDir(relativePath) {
|
|
|
29422
30174
|
}
|
|
29423
30175
|
|
|
29424
30176
|
// src/files/read-file.ts
|
|
29425
|
-
import
|
|
30177
|
+
import fs6 from "node:fs";
|
|
29426
30178
|
import { StringDecoder } from "node:string_decoder";
|
|
29427
30179
|
function resolveFilePath(relativePath) {
|
|
29428
30180
|
const resolved = ensureUnderCwd(relativePath, getBridgeWorkspaceDirectory());
|
|
29429
30181
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
29430
30182
|
let real;
|
|
29431
30183
|
try {
|
|
29432
|
-
real =
|
|
30184
|
+
real = fs6.realpathSync(resolved);
|
|
29433
30185
|
} catch {
|
|
29434
30186
|
real = resolved;
|
|
29435
30187
|
}
|
|
29436
|
-
const
|
|
29437
|
-
if (!
|
|
30188
|
+
const stat2 = fs6.statSync(real);
|
|
30189
|
+
if (!stat2.isFile()) return { error: "Not a file" };
|
|
29438
30190
|
return real;
|
|
29439
30191
|
}
|
|
29440
30192
|
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
29441
30193
|
function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
29442
|
-
const fileSize =
|
|
29443
|
-
const fd =
|
|
30194
|
+
const fileSize = fs6.statSync(filePath).size;
|
|
30195
|
+
const fd = fs6.openSync(filePath, "r");
|
|
29444
30196
|
const bufSize = 64 * 1024;
|
|
29445
30197
|
const buf = Buffer.alloc(bufSize);
|
|
29446
30198
|
const decoder = new StringDecoder("utf8");
|
|
@@ -29453,7 +30205,7 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
29453
30205
|
let line0Accum = "";
|
|
29454
30206
|
try {
|
|
29455
30207
|
let bytesRead;
|
|
29456
|
-
while (!done && (bytesRead =
|
|
30208
|
+
while (!done && (bytesRead = fs6.readSync(fd, buf, 0, bufSize, null)) > 0) {
|
|
29457
30209
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
29458
30210
|
partial2 = "";
|
|
29459
30211
|
let lineStart = 0;
|
|
@@ -29588,10 +30340,10 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
29588
30340
|
}
|
|
29589
30341
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
29590
30342
|
} finally {
|
|
29591
|
-
|
|
30343
|
+
fs6.closeSync(fd);
|
|
29592
30344
|
}
|
|
29593
30345
|
}
|
|
29594
|
-
function
|
|
30346
|
+
function readFile2(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
29595
30347
|
try {
|
|
29596
30348
|
const result = resolveFilePath(relativePath);
|
|
29597
30349
|
if (typeof result === "object") return result;
|
|
@@ -29599,17 +30351,17 @@ function readFile(relativePath, startLine, endLine, lineOffset, lineChunkSize =
|
|
|
29599
30351
|
if (hasRange) {
|
|
29600
30352
|
return readFileRange(result, startLine, endLine, lineOffset, lineChunkSize);
|
|
29601
30353
|
}
|
|
29602
|
-
const
|
|
29603
|
-
const raw =
|
|
30354
|
+
const stat2 = fs6.statSync(result);
|
|
30355
|
+
const raw = fs6.readFileSync(result, "utf8");
|
|
29604
30356
|
const lines = raw.split(/\r?\n/);
|
|
29605
|
-
return { content: raw, totalLines: lines.length, size:
|
|
30357
|
+
return { content: raw, totalLines: lines.length, size: stat2.size };
|
|
29606
30358
|
} catch (err) {
|
|
29607
30359
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
29608
30360
|
}
|
|
29609
30361
|
}
|
|
29610
30362
|
|
|
29611
30363
|
// src/files/file-index.ts
|
|
29612
|
-
import
|
|
30364
|
+
import fs7 from "node:fs";
|
|
29613
30365
|
import path14 from "node:path";
|
|
29614
30366
|
import os2 from "node:os";
|
|
29615
30367
|
import crypto2 from "node:crypto";
|
|
@@ -29656,23 +30408,23 @@ function binarySearch(arr, x) {
|
|
|
29656
30408
|
function walkDir(dir, baseDir, out) {
|
|
29657
30409
|
let names;
|
|
29658
30410
|
try {
|
|
29659
|
-
names =
|
|
30411
|
+
names = fs7.readdirSync(dir);
|
|
29660
30412
|
} catch {
|
|
29661
30413
|
return;
|
|
29662
30414
|
}
|
|
29663
30415
|
for (const name of names) {
|
|
29664
30416
|
if (name.startsWith(".")) continue;
|
|
29665
30417
|
const full = path14.join(dir, name);
|
|
29666
|
-
let
|
|
30418
|
+
let stat2;
|
|
29667
30419
|
try {
|
|
29668
|
-
|
|
30420
|
+
stat2 = fs7.statSync(full);
|
|
29669
30421
|
} catch {
|
|
29670
30422
|
continue;
|
|
29671
30423
|
}
|
|
29672
30424
|
const relative4 = path14.relative(baseDir, full).replace(/\\/g, "/");
|
|
29673
|
-
if (
|
|
30425
|
+
if (stat2.isDirectory()) {
|
|
29674
30426
|
walkDir(full, baseDir, out);
|
|
29675
|
-
} else if (
|
|
30427
|
+
} else if (stat2.isFile()) {
|
|
29676
30428
|
out.push(relative4);
|
|
29677
30429
|
}
|
|
29678
30430
|
}
|
|
@@ -29696,8 +30448,8 @@ function buildFileIndex(cwd) {
|
|
|
29696
30448
|
const data = { version: INDEX_VERSION, paths, trigramIndex };
|
|
29697
30449
|
const indexPath = getIndexPath(resolved);
|
|
29698
30450
|
try {
|
|
29699
|
-
if (!
|
|
29700
|
-
|
|
30451
|
+
if (!fs7.existsSync(INDEX_DIR)) fs7.mkdirSync(INDEX_DIR, { recursive: true });
|
|
30452
|
+
fs7.writeFileSync(indexPath, JSON.stringify(data), "utf8");
|
|
29701
30453
|
} catch (e) {
|
|
29702
30454
|
console.error("[file-index] Failed to write index:", e);
|
|
29703
30455
|
}
|
|
@@ -29707,7 +30459,7 @@ function loadFileIndex(cwd) {
|
|
|
29707
30459
|
const resolved = path14.resolve(cwd);
|
|
29708
30460
|
const indexPath = getIndexPath(resolved);
|
|
29709
30461
|
try {
|
|
29710
|
-
const raw =
|
|
30462
|
+
const raw = fs7.readFileSync(indexPath, "utf8");
|
|
29711
30463
|
const parsed = JSON.parse(raw);
|
|
29712
30464
|
if (parsed !== null && typeof parsed === "object" && Array.isArray(parsed.paths)) {
|
|
29713
30465
|
const obj = parsed;
|
|
@@ -29811,7 +30563,7 @@ function handleFileBrowserRequest(msg, socket) {
|
|
|
29811
30563
|
const endLine = typeof msg.endLine === "number" ? msg.endLine : void 0;
|
|
29812
30564
|
const lineOffset = typeof msg.lineOffset === "number" ? msg.lineOffset : void 0;
|
|
29813
30565
|
const lineChunkSize = typeof msg.lineChunkSize === "number" ? msg.lineChunkSize : void 0;
|
|
29814
|
-
const result =
|
|
30566
|
+
const result = readFile2(reqPath, startLine, endLine, lineOffset, lineChunkSize);
|
|
29815
30567
|
if ("error" in result) {
|
|
29816
30568
|
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
29817
30569
|
} else {
|
|
@@ -29846,7 +30598,7 @@ function handleFileBrowserSearchMessage(msg, { getWs }) {
|
|
|
29846
30598
|
}
|
|
29847
30599
|
|
|
29848
30600
|
// src/skills/discover-local-agent-skills.ts
|
|
29849
|
-
import
|
|
30601
|
+
import fs8 from "node:fs";
|
|
29850
30602
|
import path15 from "node:path";
|
|
29851
30603
|
var SKILL_DISCOVERY_ROOTS = [".agents/skills", ".claude/skills", ".cursor/skills", "skills"];
|
|
29852
30604
|
function discoverLocalSkills(cwd) {
|
|
@@ -29854,22 +30606,22 @@ function discoverLocalSkills(cwd) {
|
|
|
29854
30606
|
const seenKeys = /* @__PURE__ */ new Set();
|
|
29855
30607
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
29856
30608
|
const base = path15.join(cwd, rel);
|
|
29857
|
-
if (!
|
|
30609
|
+
if (!fs8.existsSync(base) || !fs8.statSync(base).isDirectory()) continue;
|
|
29858
30610
|
let entries = [];
|
|
29859
30611
|
try {
|
|
29860
|
-
entries =
|
|
30612
|
+
entries = fs8.readdirSync(base);
|
|
29861
30613
|
} catch {
|
|
29862
30614
|
continue;
|
|
29863
30615
|
}
|
|
29864
30616
|
for (const name of entries) {
|
|
29865
30617
|
const dir = path15.join(base, name);
|
|
29866
30618
|
try {
|
|
29867
|
-
if (!
|
|
30619
|
+
if (!fs8.statSync(dir).isDirectory()) continue;
|
|
29868
30620
|
} catch {
|
|
29869
30621
|
continue;
|
|
29870
30622
|
}
|
|
29871
30623
|
const skillMd = path15.join(dir, "SKILL.md");
|
|
29872
|
-
if (!
|
|
30624
|
+
if (!fs8.existsSync(skillMd)) continue;
|
|
29873
30625
|
const key = `${rel}/${name}`;
|
|
29874
30626
|
if (seenKeys.has(key)) continue;
|
|
29875
30627
|
seenKeys.add(key);
|
|
@@ -29882,10 +30634,10 @@ function discoverSkillLayoutRoots(cwd) {
|
|
|
29882
30634
|
const roots = [];
|
|
29883
30635
|
for (const rel of SKILL_DISCOVERY_ROOTS) {
|
|
29884
30636
|
const base = path15.join(cwd, rel);
|
|
29885
|
-
if (!
|
|
30637
|
+
if (!fs8.existsSync(base) || !fs8.statSync(base).isDirectory()) continue;
|
|
29886
30638
|
let entries = [];
|
|
29887
30639
|
try {
|
|
29888
|
-
entries =
|
|
30640
|
+
entries = fs8.readdirSync(base);
|
|
29889
30641
|
} catch {
|
|
29890
30642
|
continue;
|
|
29891
30643
|
}
|
|
@@ -29893,11 +30645,11 @@ function discoverSkillLayoutRoots(cwd) {
|
|
|
29893
30645
|
for (const name of entries) {
|
|
29894
30646
|
const dir = path15.join(base, name);
|
|
29895
30647
|
try {
|
|
29896
|
-
if (!
|
|
30648
|
+
if (!fs8.statSync(dir).isDirectory()) continue;
|
|
29897
30649
|
} catch {
|
|
29898
30650
|
continue;
|
|
29899
30651
|
}
|
|
29900
|
-
if (!
|
|
30652
|
+
if (!fs8.existsSync(path15.join(dir, "SKILL.md"))) continue;
|
|
29901
30653
|
const relPath = `${rel}/${name}`.replace(/\\/g, "/");
|
|
29902
30654
|
skills2.push({ name, relPath });
|
|
29903
30655
|
}
|
|
@@ -29917,7 +30669,7 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
29917
30669
|
}
|
|
29918
30670
|
|
|
29919
30671
|
// src/skills/install-remote-skills.ts
|
|
29920
|
-
import
|
|
30672
|
+
import fs9 from "node:fs";
|
|
29921
30673
|
import path16 from "node:path";
|
|
29922
30674
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
29923
30675
|
const installed = [];
|
|
@@ -29933,11 +30685,11 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
29933
30685
|
for (const f of item.files) {
|
|
29934
30686
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
29935
30687
|
const dest = path16.join(skillDir, f.path);
|
|
29936
|
-
|
|
30688
|
+
fs9.mkdirSync(path16.dirname(dest), { recursive: true });
|
|
29937
30689
|
if (f.text !== void 0) {
|
|
29938
|
-
|
|
30690
|
+
fs9.writeFileSync(dest, f.text, "utf8");
|
|
29939
30691
|
} else if (f.base64) {
|
|
29940
|
-
|
|
30692
|
+
fs9.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
29941
30693
|
}
|
|
29942
30694
|
}
|
|
29943
30695
|
installed.push({
|
|
@@ -30031,7 +30783,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
30031
30783
|
};
|
|
30032
30784
|
|
|
30033
30785
|
// src/bridge/routing/handlers/revert-turn-snapshot.ts
|
|
30034
|
-
import * as
|
|
30786
|
+
import * as fs10 from "node:fs";
|
|
30035
30787
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
30036
30788
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
30037
30789
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -30043,7 +30795,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
30043
30795
|
if (!s) return;
|
|
30044
30796
|
const agentBase = sessionWorktreeManager.getAgentCwdForSession(sessionId) ?? getBridgeWorkspaceDirectory();
|
|
30045
30797
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
30046
|
-
if (!
|
|
30798
|
+
if (!fs10.existsSync(file2)) {
|
|
30047
30799
|
sendWsMessage(s, {
|
|
30048
30800
|
type: "revert_turn_snapshot_result",
|
|
30049
30801
|
id,
|
|
@@ -30144,25 +30896,12 @@ function dispatchBridgeMessage(msg, deps) {
|
|
|
30144
30896
|
}
|
|
30145
30897
|
|
|
30146
30898
|
// src/bridge/routing/handle-bridge-message.ts
|
|
30147
|
-
var DEFERRED_INBOUND_TYPES = /* @__PURE__ */ new Set([
|
|
30148
|
-
"server_control",
|
|
30149
|
-
"prompt",
|
|
30150
|
-
"install_skills",
|
|
30151
|
-
"refresh_local_skills",
|
|
30152
|
-
"dev_servers_config"
|
|
30153
|
-
]);
|
|
30154
30899
|
function handleBridgeMessage(data, deps) {
|
|
30155
30900
|
const msg = data;
|
|
30156
|
-
|
|
30157
|
-
|
|
30158
|
-
|
|
30159
|
-
|
|
30160
|
-
setImmediate(() => {
|
|
30161
|
-
dispatchBridgeMessage(msg, deps);
|
|
30162
|
-
});
|
|
30163
|
-
return;
|
|
30164
|
-
}
|
|
30165
|
-
dispatchBridgeMessage(msg, deps);
|
|
30901
|
+
if (!deps.getWs()) return;
|
|
30902
|
+
setImmediate(() => {
|
|
30903
|
+
dispatchBridgeMessage(msg, deps);
|
|
30904
|
+
});
|
|
30166
30905
|
}
|
|
30167
30906
|
|
|
30168
30907
|
// src/worktrees/session-worktree-manager.ts
|
|
@@ -30170,7 +30909,7 @@ import * as path20 from "node:path";
|
|
|
30170
30909
|
import os4 from "node:os";
|
|
30171
30910
|
|
|
30172
30911
|
// src/worktrees/prepare-new-session-worktrees.ts
|
|
30173
|
-
import * as
|
|
30912
|
+
import * as fs12 from "node:fs";
|
|
30174
30913
|
import * as path18 from "node:path";
|
|
30175
30914
|
|
|
30176
30915
|
// src/git/worktree-add.ts
|
|
@@ -30180,7 +30919,7 @@ async function gitWorktreeAddBranch(mainRepoPath, worktreePath, branch) {
|
|
|
30180
30919
|
}
|
|
30181
30920
|
|
|
30182
30921
|
// src/worktrees/worktree-layout-file.ts
|
|
30183
|
-
import * as
|
|
30922
|
+
import * as fs11 from "node:fs";
|
|
30184
30923
|
import * as path17 from "node:path";
|
|
30185
30924
|
import os3 from "node:os";
|
|
30186
30925
|
var LAYOUT_FILENAME = "worktree-launcher-layout.json";
|
|
@@ -30197,8 +30936,8 @@ function normalizeLoadedLayout(raw) {
|
|
|
30197
30936
|
function loadWorktreeLayout() {
|
|
30198
30937
|
try {
|
|
30199
30938
|
const p = defaultWorktreeLayoutPath();
|
|
30200
|
-
if (!
|
|
30201
|
-
const raw = JSON.parse(
|
|
30939
|
+
if (!fs11.existsSync(p)) return { launcherCwds: [] };
|
|
30940
|
+
const raw = JSON.parse(fs11.readFileSync(p, "utf8"));
|
|
30202
30941
|
return normalizeLoadedLayout(raw);
|
|
30203
30942
|
} catch {
|
|
30204
30943
|
return { launcherCwds: [] };
|
|
@@ -30207,8 +30946,8 @@ function loadWorktreeLayout() {
|
|
|
30207
30946
|
function saveWorktreeLayout(layout) {
|
|
30208
30947
|
try {
|
|
30209
30948
|
const dir = path17.dirname(defaultWorktreeLayoutPath());
|
|
30210
|
-
|
|
30211
|
-
|
|
30949
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
30950
|
+
fs11.writeFileSync(defaultWorktreeLayoutPath(), JSON.stringify(layout, null, 2), "utf8");
|
|
30212
30951
|
} catch {
|
|
30213
30952
|
}
|
|
30214
30953
|
}
|
|
@@ -30245,13 +30984,13 @@ async function prepareNewSessionWorktrees(options) {
|
|
|
30245
30984
|
}
|
|
30246
30985
|
const branch = `session-${sessionId}`;
|
|
30247
30986
|
const worktreePaths = [];
|
|
30248
|
-
|
|
30987
|
+
fs12.mkdirSync(agentMirrorRoot, { recursive: true });
|
|
30249
30988
|
for (const repo of repos) {
|
|
30250
30989
|
let rel = path18.relative(launcherResolved, repo.absolutePath);
|
|
30251
30990
|
if (rel.startsWith("..") || path18.isAbsolute(rel)) continue;
|
|
30252
30991
|
const relNorm = rel === "" ? "." : rel;
|
|
30253
30992
|
const wtPath = path18.join(agentMirrorRoot, relNorm, sessionId);
|
|
30254
|
-
|
|
30993
|
+
fs12.mkdirSync(path18.dirname(wtPath), { recursive: true });
|
|
30255
30994
|
try {
|
|
30256
30995
|
await gitWorktreeAddBranch(repo.absolutePath, wtPath, branch);
|
|
30257
30996
|
log2(`[worktrees] Added worktree ${wtPath} (branch ${branch}).`);
|
|
@@ -30288,18 +31027,18 @@ async function renameSessionWorktreeBranches(paths, newBranch, log2) {
|
|
|
30288
31027
|
}
|
|
30289
31028
|
|
|
30290
31029
|
// src/worktrees/remove-session-worktrees.ts
|
|
30291
|
-
import * as
|
|
31030
|
+
import * as fs15 from "node:fs";
|
|
30292
31031
|
|
|
30293
31032
|
// src/git/worktree-remove.ts
|
|
30294
|
-
import * as
|
|
31033
|
+
import * as fs14 from "node:fs";
|
|
30295
31034
|
|
|
30296
31035
|
// src/git/resolve-main-repo-from-git-file.ts
|
|
30297
|
-
import * as
|
|
31036
|
+
import * as fs13 from "node:fs";
|
|
30298
31037
|
import * as path19 from "node:path";
|
|
30299
31038
|
function resolveMainRepoFromWorktreeGitFile(wt) {
|
|
30300
31039
|
const gitDirFile = path19.join(wt, ".git");
|
|
30301
|
-
if (!
|
|
30302
|
-
const first2 =
|
|
31040
|
+
if (!fs13.existsSync(gitDirFile) || !fs13.statSync(gitDirFile).isFile()) return "";
|
|
31041
|
+
const first2 = fs13.readFileSync(gitDirFile, "utf8").trim();
|
|
30303
31042
|
const m = first2.match(/^gitdir:\s*(.+)$/im);
|
|
30304
31043
|
if (!m) return "";
|
|
30305
31044
|
const gitWorktreePath = path19.resolve(wt, m[1].trim());
|
|
@@ -30313,7 +31052,7 @@ async function gitWorktreeRemoveForce(worktreePath) {
|
|
|
30313
31052
|
if (mainRepo) {
|
|
30314
31053
|
await simpleGit(mainRepo).raw(["worktree", "remove", "--force", worktreePath]);
|
|
30315
31054
|
} else {
|
|
30316
|
-
|
|
31055
|
+
fs14.rmSync(worktreePath, { recursive: true, force: true });
|
|
30317
31056
|
}
|
|
30318
31057
|
}
|
|
30319
31058
|
|
|
@@ -30326,7 +31065,7 @@ async function removeSessionWorktrees(paths, log2) {
|
|
|
30326
31065
|
} catch (e) {
|
|
30327
31066
|
log2(`[worktrees] Remove failed for ${wt}: ${e instanceof Error ? e.message : String(e)}`);
|
|
30328
31067
|
try {
|
|
30329
|
-
|
|
31068
|
+
fs15.rmSync(wt, { recursive: true, force: true });
|
|
30330
31069
|
} catch {
|
|
30331
31070
|
}
|
|
30332
31071
|
}
|
|
@@ -30598,7 +31337,7 @@ function forceKillChild(proc, log2, shortId, graceMs) {
|
|
|
30598
31337
|
}
|
|
30599
31338
|
|
|
30600
31339
|
// src/dev-servers/process/wire-dev-server-child-process.ts
|
|
30601
|
-
import
|
|
31340
|
+
import fs16 from "node:fs";
|
|
30602
31341
|
|
|
30603
31342
|
// src/dev-servers/manager/forward-pipe.ts
|
|
30604
31343
|
function forwardChildPipe(childReadable, terminal, onData) {
|
|
@@ -30634,7 +31373,7 @@ function wireDevServerChildProcess(d) {
|
|
|
30634
31373
|
d.setPollInterval(void 0);
|
|
30635
31374
|
return;
|
|
30636
31375
|
}
|
|
30637
|
-
|
|
31376
|
+
fs16.readFile(d.mergedLogPath, (err, buf) => {
|
|
30638
31377
|
if (err || (d.getSpawnGeneration() ?? 0) !== d.scheduledGen) return;
|
|
30639
31378
|
if (buf.length <= d.mergedReadPos.value) return;
|
|
30640
31379
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
@@ -30672,7 +31411,7 @@ ${errTail}` : ""}`);
|
|
|
30672
31411
|
d.sendStatus(code === 0 || code == null ? "stopped" : "error", detail, tails);
|
|
30673
31412
|
};
|
|
30674
31413
|
if (mergedPath) {
|
|
30675
|
-
|
|
31414
|
+
fs16.readFile(mergedPath, (err, buf) => {
|
|
30676
31415
|
if (!err && buf.length > d.mergedReadPos.value) {
|
|
30677
31416
|
const chunk = Buffer.from(buf.subarray(d.mergedReadPos.value));
|
|
30678
31417
|
if (chunk.length > 0) {
|
|
@@ -30774,13 +31513,13 @@ function parseDevServerDefs(servers) {
|
|
|
30774
31513
|
}
|
|
30775
31514
|
|
|
30776
31515
|
// src/dev-servers/manager/shell-spawn/utils.ts
|
|
30777
|
-
import
|
|
31516
|
+
import fs17 from "node:fs";
|
|
30778
31517
|
function isSpawnEbadf(e) {
|
|
30779
31518
|
return typeof e === "object" && e !== null && "code" in e && e.code === "EBADF";
|
|
30780
31519
|
}
|
|
30781
31520
|
function rmDirQuiet(dir) {
|
|
30782
31521
|
try {
|
|
30783
|
-
|
|
31522
|
+
fs17.rmSync(dir, { recursive: true, force: true });
|
|
30784
31523
|
} catch {
|
|
30785
31524
|
}
|
|
30786
31525
|
}
|
|
@@ -30788,7 +31527,7 @@ var cachedDevNullReadFd;
|
|
|
30788
31527
|
function devNullReadFd() {
|
|
30789
31528
|
if (cachedDevNullReadFd === void 0) {
|
|
30790
31529
|
const devPath = process.platform === "win32" ? "nul" : "/dev/null";
|
|
30791
|
-
cachedDevNullReadFd =
|
|
31530
|
+
cachedDevNullReadFd = fs17.openSync(devPath, "r");
|
|
30792
31531
|
}
|
|
30793
31532
|
return cachedDevNullReadFd;
|
|
30794
31533
|
}
|
|
@@ -30862,15 +31601,15 @@ function trySpawnShellTruePiped(command, env, cwd, devNullFd, signal) {
|
|
|
30862
31601
|
|
|
30863
31602
|
// src/dev-servers/manager/shell-spawn/try-spawn-merged-log-file.ts
|
|
30864
31603
|
import { spawn as spawn7 } from "node:child_process";
|
|
30865
|
-
import
|
|
31604
|
+
import fs18 from "node:fs";
|
|
30866
31605
|
import { tmpdir } from "node:os";
|
|
30867
31606
|
import path22 from "node:path";
|
|
30868
31607
|
function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
30869
|
-
const tmpRoot =
|
|
31608
|
+
const tmpRoot = fs18.mkdtempSync(path22.join(tmpdir(), "ba-devsrv-log-"));
|
|
30870
31609
|
const logPath = path22.join(tmpRoot, "combined.log");
|
|
30871
31610
|
let logFd;
|
|
30872
31611
|
try {
|
|
30873
|
-
logFd =
|
|
31612
|
+
logFd = fs18.openSync(logPath, "a");
|
|
30874
31613
|
} catch {
|
|
30875
31614
|
rmDirQuiet(tmpRoot);
|
|
30876
31615
|
return null;
|
|
@@ -30889,7 +31628,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
30889
31628
|
} else {
|
|
30890
31629
|
proc = spawn7("/bin/sh", ["-c", command], { env, cwd, stdio, ...signal ? { signal } : {} });
|
|
30891
31630
|
}
|
|
30892
|
-
|
|
31631
|
+
fs18.closeSync(logFd);
|
|
30893
31632
|
return {
|
|
30894
31633
|
proc,
|
|
30895
31634
|
pipedStdoutStderr: true,
|
|
@@ -30898,7 +31637,7 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
30898
31637
|
};
|
|
30899
31638
|
} catch (e) {
|
|
30900
31639
|
try {
|
|
30901
|
-
|
|
31640
|
+
fs18.closeSync(logFd);
|
|
30902
31641
|
} catch {
|
|
30903
31642
|
}
|
|
30904
31643
|
rmDirQuiet(tmpRoot);
|
|
@@ -30909,22 +31648,22 @@ function trySpawnMergedLogFile(command, env, cwd, signal) {
|
|
|
30909
31648
|
|
|
30910
31649
|
// src/dev-servers/manager/shell-spawn/try-spawn-shell-script-log-redirect.ts
|
|
30911
31650
|
import { spawn as spawn8 } from "node:child_process";
|
|
30912
|
-
import
|
|
31651
|
+
import fs19 from "node:fs";
|
|
30913
31652
|
import { tmpdir as tmpdir2 } from "node:os";
|
|
30914
31653
|
import path23 from "node:path";
|
|
30915
31654
|
function shSingleQuote(s) {
|
|
30916
31655
|
return `'${s.replace(/'/g, `'\\''`)}'`;
|
|
30917
31656
|
}
|
|
30918
31657
|
function trySpawnShellScriptLogRedirectUnix(command, env, cwd, signal) {
|
|
30919
|
-
const tmpRoot =
|
|
31658
|
+
const tmpRoot = fs19.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
30920
31659
|
const logPath = path23.join(tmpRoot, "combined.log");
|
|
30921
31660
|
const innerPath = path23.join(tmpRoot, "_cmd.sh");
|
|
30922
31661
|
const runnerPath = path23.join(tmpRoot, "_run.sh");
|
|
30923
31662
|
try {
|
|
30924
|
-
|
|
31663
|
+
fs19.writeFileSync(innerPath, `#!/bin/sh
|
|
30925
31664
|
${command}
|
|
30926
31665
|
`);
|
|
30927
|
-
|
|
31666
|
+
fs19.writeFileSync(
|
|
30928
31667
|
runnerPath,
|
|
30929
31668
|
`#!/bin/sh
|
|
30930
31669
|
cd ${shSingleQuote(cwd)}
|
|
@@ -30950,13 +31689,13 @@ cd ${shSingleQuote(cwd)}
|
|
|
30950
31689
|
}
|
|
30951
31690
|
}
|
|
30952
31691
|
function trySpawnShellScriptLogRedirectWin(command, env, cwd, signal) {
|
|
30953
|
-
const tmpRoot =
|
|
31692
|
+
const tmpRoot = fs19.mkdtempSync(path23.join(tmpdir2(), "ba-devsrv-sh-"));
|
|
30954
31693
|
const logPath = path23.join(tmpRoot, "combined.log");
|
|
30955
31694
|
const runnerPath = path23.join(tmpRoot, "_run.bat");
|
|
30956
31695
|
const q = (p) => `"${p.replace(/"/g, '""')}"`;
|
|
30957
31696
|
const com = process.env.ComSpec || "cmd.exe";
|
|
30958
31697
|
try {
|
|
30959
|
-
|
|
31698
|
+
fs19.writeFileSync(
|
|
30960
31699
|
runnerPath,
|
|
30961
31700
|
`@ECHO OFF\r
|
|
30962
31701
|
CD /D ${q(cwd)}\r
|
|
@@ -31310,7 +32049,9 @@ var DevServerManager = class {
|
|
|
31310
32049
|
async shutdownAllGraceful() {
|
|
31311
32050
|
const pairs = [...this.processes.entries()];
|
|
31312
32051
|
if (pairs.length === 0) return;
|
|
31313
|
-
this.log(
|
|
32052
|
+
this.log(
|
|
32053
|
+
`[dev-server] Stopping ${pairs.length} local dev server process${pairs.length === 1 ? "" : "es"}\u2026`
|
|
32054
|
+
);
|
|
31314
32055
|
await Promise.all(pairs.map(([serverId, proc]) => this.gracefulTerminateOrUnknown(serverId, proc)));
|
|
31315
32056
|
}
|
|
31316
32057
|
async gracefulTerminateOrUnknown(serverId, proc) {
|
|
@@ -31477,9 +32218,10 @@ var FIREHOSE_CLIENT_PING_MS = 25e3;
|
|
|
31477
32218
|
function connectFirehose(options) {
|
|
31478
32219
|
const { firehoseServerUrl, workspaceId, bridgeName, proxyPorts, log: log2, devServerManager, onOpen, onClose } = options;
|
|
31479
32220
|
const wsUrl = buildFirehoseCliWsUrl(firehoseServerUrl);
|
|
31480
|
-
|
|
32221
|
+
applyCliOutboundNetworkPreferences();
|
|
32222
|
+
const wsOptions = { perMessageDeflate: false, family: 4 };
|
|
31481
32223
|
if (wsUrl.startsWith("wss://")) {
|
|
31482
|
-
wsOptions.agent = new https2.Agent({ rejectUnauthorized: false });
|
|
32224
|
+
wsOptions.agent = new https2.Agent({ rejectUnauthorized: false, family: 4 });
|
|
31483
32225
|
}
|
|
31484
32226
|
const ws = new wrapper_default(wsUrl, wsOptions);
|
|
31485
32227
|
let clientPingTimer = null;
|
|
@@ -31515,16 +32257,14 @@ function connectFirehose(options) {
|
|
|
31515
32257
|
sendWsMessage(ws, { type: "identify", workspaceId, bridgeName, proxyPorts });
|
|
31516
32258
|
});
|
|
31517
32259
|
ws.on("message", (raw) => {
|
|
31518
|
-
|
|
31519
|
-
|
|
31520
|
-
|
|
31521
|
-
|
|
31522
|
-
|
|
31523
|
-
|
|
31524
|
-
|
|
31525
|
-
|
|
31526
|
-
}
|
|
31527
|
-
});
|
|
32260
|
+
if (Buffer.isBuffer(raw) && tryConsumeBinaryProxyBody(raw, deps)) {
|
|
32261
|
+
return;
|
|
32262
|
+
}
|
|
32263
|
+
try {
|
|
32264
|
+
const text = Buffer.isBuffer(raw) ? raw.toString("utf8") : String(raw);
|
|
32265
|
+
dispatchFirehoseJsonMessage(JSON.parse(text), deps);
|
|
32266
|
+
} catch {
|
|
32267
|
+
}
|
|
31528
32268
|
});
|
|
31529
32269
|
ws.on("close", (code, reason) => {
|
|
31530
32270
|
clearClientPing();
|
|
@@ -31570,6 +32310,9 @@ function createOnBridgeIdentified(opts) {
|
|
|
31570
32310
|
function attachFirehose(params) {
|
|
31571
32311
|
state.lastFirehoseParams = params;
|
|
31572
32312
|
clearFirehoseReconnectTimer();
|
|
32313
|
+
if (state.firehoseReconnectAttempt === 0) {
|
|
32314
|
+
logFn("Connecting to preview tunnel (local HTTP proxy and dev logs)\u2026");
|
|
32315
|
+
}
|
|
31573
32316
|
state.firehoseGeneration += 1;
|
|
31574
32317
|
const myGen = state.firehoseGeneration;
|
|
31575
32318
|
if (state.firehoseHandle) {
|
|
@@ -31588,8 +32331,8 @@ function createOnBridgeIdentified(opts) {
|
|
|
31588
32331
|
clearFirehoseReconnectQuietOnOpen({ firehoseQuiet: state.firehoseQuiet }, logFn);
|
|
31589
32332
|
const logOpenAsFirehoseReconnect = state.firehoseReconnectAttempt > 0;
|
|
31590
32333
|
state.firehoseReconnectAttempt = 0;
|
|
31591
|
-
if (logOpenAsFirehoseReconnect) {
|
|
31592
|
-
logFn("
|
|
32334
|
+
if (!logOpenAsFirehoseReconnect) {
|
|
32335
|
+
logFn("Connected to preview tunnel (local HTTP proxy and dev logs).");
|
|
31593
32336
|
}
|
|
31594
32337
|
},
|
|
31595
32338
|
onClose: (code, reason) => {
|
|
@@ -31657,47 +32400,19 @@ function createOnBridgeIdentified(opts) {
|
|
|
31657
32400
|
};
|
|
31658
32401
|
}
|
|
31659
32402
|
|
|
31660
|
-
// src/
|
|
31661
|
-
|
|
31662
|
-
|
|
31663
|
-
|
|
31664
|
-
|
|
31665
|
-
|
|
31666
|
-
|
|
31667
|
-
await execFileAsync4("which", ["agent"], { timeout: 4e3 });
|
|
31668
|
-
return true;
|
|
31669
|
-
} catch {
|
|
31670
|
-
return false;
|
|
31671
|
-
}
|
|
31672
|
-
},
|
|
31673
|
-
"codex-acp": async () => {
|
|
31674
|
-
try {
|
|
31675
|
-
await execFileAsync4("which", ["codex"], { timeout: 4e3 });
|
|
31676
|
-
return true;
|
|
31677
|
-
} catch {
|
|
31678
|
-
return false;
|
|
31679
|
-
}
|
|
31680
|
-
},
|
|
31681
|
-
"claude-code": async () => {
|
|
31682
|
-
try {
|
|
31683
|
-
await execFileAsync4("which", ["claude"], { timeout: 4e3 });
|
|
31684
|
-
return true;
|
|
31685
|
-
} catch {
|
|
31686
|
-
try {
|
|
31687
|
-
await execFileAsync4("npx", ["--yes", "@anthropic-ai/claude-code", "--version"], { timeout: 25e3 });
|
|
31688
|
-
return true;
|
|
31689
|
-
} catch {
|
|
31690
|
-
return false;
|
|
31691
|
-
}
|
|
31692
|
-
}
|
|
31693
|
-
}
|
|
31694
|
-
};
|
|
32403
|
+
// src/acp/detect-local-agent-types.ts
|
|
32404
|
+
var LOCAL_AGENT_ACP_MODULES = [
|
|
32405
|
+
cursor_acp_client_exports,
|
|
32406
|
+
codex_acp_client_exports,
|
|
32407
|
+
kiro_acp_client_exports,
|
|
32408
|
+
claude_code_acp_client_exports
|
|
32409
|
+
];
|
|
31695
32410
|
async function detectLocalAgentTypes() {
|
|
31696
32411
|
try {
|
|
31697
32412
|
const out = [];
|
|
31698
|
-
for (const
|
|
32413
|
+
for (const mod of LOCAL_AGENT_ACP_MODULES) {
|
|
31699
32414
|
try {
|
|
31700
|
-
if (await
|
|
32415
|
+
if (await mod.detectLocalAgentPresence()) out.push(mod.BACKEND_LOCAL_AGENT_TYPE);
|
|
31701
32416
|
} catch {
|
|
31702
32417
|
}
|
|
31703
32418
|
}
|
|
@@ -31787,8 +32502,8 @@ async function createBridgeConnection(options) {
|
|
|
31787
32502
|
clearMainBridgeReconnectQuietOnOpen(state, logFn);
|
|
31788
32503
|
state.reconnectAttempt = 0;
|
|
31789
32504
|
state.logBridgeOpenAsReconnect = false;
|
|
31790
|
-
if (logOpenAsPostRefreshReconnect) {
|
|
31791
|
-
logFn("
|
|
32505
|
+
if (!logOpenAsPostRefreshReconnect) {
|
|
32506
|
+
logFn("Connected to bridge service.");
|
|
31792
32507
|
}
|
|
31793
32508
|
const socket = getWs();
|
|
31794
32509
|
if (socket) {
|
|
@@ -31827,6 +32542,9 @@ async function createBridgeConnection(options) {
|
|
|
31827
32542
|
clearTimeout(state.reconnectTimeout);
|
|
31828
32543
|
state.reconnectTimeout = null;
|
|
31829
32544
|
}
|
|
32545
|
+
if (state.reconnectAttempt === 0) {
|
|
32546
|
+
logFn("Connecting to bridge service\u2026");
|
|
32547
|
+
}
|
|
31830
32548
|
const prev = state.currentWs;
|
|
31831
32549
|
if (prev) {
|
|
31832
32550
|
prev.removeAllListeners();
|
|
@@ -31899,15 +32617,17 @@ async function runBridge(options) {
|
|
|
31899
32617
|
onAuth: (_auth) => {
|
|
31900
32618
|
}
|
|
31901
32619
|
});
|
|
31902
|
-
const onSignal2 = (
|
|
31903
|
-
logImmediate(
|
|
32620
|
+
const onSignal2 = (kind) => {
|
|
32621
|
+
logImmediate(
|
|
32622
|
+
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|
|
32623
|
+
);
|
|
31904
32624
|
setImmediate(() => {
|
|
31905
32625
|
handle2.close();
|
|
31906
32626
|
process.exit(0);
|
|
31907
32627
|
});
|
|
31908
32628
|
};
|
|
31909
|
-
const onSigInt2 = () => onSignal2("
|
|
31910
|
-
const onSigTerm2 = () => onSignal2("
|
|
32629
|
+
const onSigInt2 = () => onSignal2("interrupt");
|
|
32630
|
+
const onSigTerm2 = () => onSignal2("stop");
|
|
31911
32631
|
process.on("SIGINT", onSigInt2);
|
|
31912
32632
|
process.on("SIGTERM", onSigTerm2);
|
|
31913
32633
|
const auth = await handle2.authPromise;
|
|
@@ -31956,22 +32676,24 @@ async function runBridge(options) {
|
|
|
31956
32676
|
});
|
|
31957
32677
|
}
|
|
31958
32678
|
});
|
|
31959
|
-
const onSignal = (
|
|
31960
|
-
logImmediate(
|
|
32679
|
+
const onSignal = (kind) => {
|
|
32680
|
+
logImmediate(
|
|
32681
|
+
kind === "interrupt" ? "Keyboard interrupt (Ctrl+C) \u2014 stopping\u2026" : "Stop requested \u2014 shutting down\u2026"
|
|
32682
|
+
);
|
|
31961
32683
|
setImmediate(() => {
|
|
31962
32684
|
void handle.close().then(() => {
|
|
31963
32685
|
process.exit(0);
|
|
31964
32686
|
});
|
|
31965
32687
|
});
|
|
31966
32688
|
};
|
|
31967
|
-
const onSigInt = () => onSignal("
|
|
31968
|
-
const onSigTerm = () => onSignal("
|
|
32689
|
+
const onSigInt = () => onSignal("interrupt");
|
|
32690
|
+
const onSigTerm = () => onSignal("stop");
|
|
31969
32691
|
process.on("SIGINT", onSigInt);
|
|
31970
32692
|
process.on("SIGTERM", onSigTerm);
|
|
31971
32693
|
}
|
|
31972
32694
|
export {
|
|
31973
32695
|
callSkill,
|
|
31974
|
-
createAcpClient,
|
|
32696
|
+
createSdkStdioAcpClient as createAcpClient,
|
|
31975
32697
|
createBridgeConnection,
|
|
31976
32698
|
createWsBridge,
|
|
31977
32699
|
getSkill,
|