@posthog/agent 2.1.35 → 2.1.47
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/{agent-DcBmoTR4.d.ts → agent-BJ7Uacyp.d.ts} +2 -0
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +161 -60
- package/dist/agent.js.map +1 -1
- package/dist/gateway-models.js +21 -2
- package/dist/gateway-models.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +292 -193
- package/dist/index.js.map +1 -1
- package/dist/server/agent-server.js +282 -193
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +276 -187
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +1 -1
- package/src/adapters/acp-connection.ts +6 -1
- package/src/adapters/claude/claude-agent.ts +107 -50
- package/src/adapters/claude/session/options.ts +3 -7
- package/src/agent.ts +1 -0
- package/src/gateway-models.ts +42 -2
package/dist/index.js
CHANGED
|
@@ -1169,12 +1169,174 @@ import {
|
|
|
1169
1169
|
import {
|
|
1170
1170
|
query
|
|
1171
1171
|
} from "@anthropic-ai/claude-agent-sdk";
|
|
1172
|
+
|
|
1173
|
+
// ../shared/dist/index.js
|
|
1174
|
+
var consoleLogger = {
|
|
1175
|
+
info: (_message, _data) => {
|
|
1176
|
+
},
|
|
1177
|
+
debug: (_message, _data) => {
|
|
1178
|
+
},
|
|
1179
|
+
error: (_message, _data) => {
|
|
1180
|
+
},
|
|
1181
|
+
warn: (_message, _data) => {
|
|
1182
|
+
}
|
|
1183
|
+
};
|
|
1184
|
+
var Saga = class {
|
|
1185
|
+
completedSteps = [];
|
|
1186
|
+
currentStepName = "unknown";
|
|
1187
|
+
stepTimings = [];
|
|
1188
|
+
log;
|
|
1189
|
+
constructor(logger) {
|
|
1190
|
+
this.log = logger ?? consoleLogger;
|
|
1191
|
+
}
|
|
1192
|
+
/**
|
|
1193
|
+
* Run the saga with the given input.
|
|
1194
|
+
* Returns a discriminated union result - either success with data or failure with error details.
|
|
1195
|
+
*/
|
|
1196
|
+
async run(input) {
|
|
1197
|
+
this.completedSteps = [];
|
|
1198
|
+
this.currentStepName = "unknown";
|
|
1199
|
+
this.stepTimings = [];
|
|
1200
|
+
const sagaStart = performance.now();
|
|
1201
|
+
this.log.info("Starting saga", { sagaName: this.constructor.name });
|
|
1202
|
+
try {
|
|
1203
|
+
const result = await this.execute(input);
|
|
1204
|
+
const totalDuration = performance.now() - sagaStart;
|
|
1205
|
+
this.log.debug("Saga completed successfully", {
|
|
1206
|
+
sagaName: this.constructor.name,
|
|
1207
|
+
stepsCompleted: this.completedSteps.length,
|
|
1208
|
+
totalDurationMs: Math.round(totalDuration),
|
|
1209
|
+
stepTimings: this.stepTimings
|
|
1210
|
+
});
|
|
1211
|
+
return { success: true, data: result };
|
|
1212
|
+
} catch (error) {
|
|
1213
|
+
this.log.error("Saga failed, initiating rollback", {
|
|
1214
|
+
sagaName: this.constructor.name,
|
|
1215
|
+
failedStep: this.currentStepName,
|
|
1216
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1217
|
+
});
|
|
1218
|
+
await this.rollback();
|
|
1219
|
+
return {
|
|
1220
|
+
success: false,
|
|
1221
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1222
|
+
failedStep: this.currentStepName
|
|
1223
|
+
};
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
/**
|
|
1227
|
+
* Execute a step with its rollback action.
|
|
1228
|
+
* If the step succeeds, its rollback action is stored for potential rollback.
|
|
1229
|
+
* The step name is automatically tracked for error reporting.
|
|
1230
|
+
*
|
|
1231
|
+
* @param config - Step configuration with name, execute, and rollback functions
|
|
1232
|
+
* @returns The result of the execute function
|
|
1233
|
+
* @throws Re-throws any error from the execute function (triggers rollback)
|
|
1234
|
+
*/
|
|
1235
|
+
async step(config) {
|
|
1236
|
+
this.currentStepName = config.name;
|
|
1237
|
+
this.log.debug(`Executing step: ${config.name}`);
|
|
1238
|
+
const stepStart = performance.now();
|
|
1239
|
+
const result = await config.execute();
|
|
1240
|
+
const durationMs = Math.round(performance.now() - stepStart);
|
|
1241
|
+
this.stepTimings.push({ name: config.name, durationMs });
|
|
1242
|
+
this.log.debug(`Step completed: ${config.name}`, { durationMs });
|
|
1243
|
+
this.completedSteps.push({
|
|
1244
|
+
name: config.name,
|
|
1245
|
+
rollback: () => config.rollback(result)
|
|
1246
|
+
});
|
|
1247
|
+
return result;
|
|
1248
|
+
}
|
|
1249
|
+
/**
|
|
1250
|
+
* Execute a step that doesn't need rollback.
|
|
1251
|
+
* Useful for read-only operations or operations that are idempotent.
|
|
1252
|
+
* The step name is automatically tracked for error reporting.
|
|
1253
|
+
*
|
|
1254
|
+
* @param name - Step name for logging and error tracking
|
|
1255
|
+
* @param execute - The action to execute
|
|
1256
|
+
* @returns The result of the execute function
|
|
1257
|
+
*/
|
|
1258
|
+
async readOnlyStep(name, execute) {
|
|
1259
|
+
this.currentStepName = name;
|
|
1260
|
+
this.log.debug(`Executing read-only step: ${name}`);
|
|
1261
|
+
const stepStart = performance.now();
|
|
1262
|
+
const result = await execute();
|
|
1263
|
+
const durationMs = Math.round(performance.now() - stepStart);
|
|
1264
|
+
this.stepTimings.push({ name, durationMs });
|
|
1265
|
+
this.log.debug(`Read-only step completed: ${name}`, { durationMs });
|
|
1266
|
+
return result;
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Roll back all completed steps in reverse order.
|
|
1270
|
+
* Rollback errors are logged but don't stop the rollback of other steps.
|
|
1271
|
+
*/
|
|
1272
|
+
async rollback() {
|
|
1273
|
+
this.log.info("Rolling back saga", {
|
|
1274
|
+
stepsToRollback: this.completedSteps.length
|
|
1275
|
+
});
|
|
1276
|
+
const stepsReversed = [...this.completedSteps].reverse();
|
|
1277
|
+
for (const step of stepsReversed) {
|
|
1278
|
+
try {
|
|
1279
|
+
this.log.debug(`Rolling back step: ${step.name}`);
|
|
1280
|
+
await step.rollback();
|
|
1281
|
+
this.log.debug(`Step rolled back: ${step.name}`);
|
|
1282
|
+
} catch (error) {
|
|
1283
|
+
this.log.error(`Failed to rollback step: ${step.name}`, {
|
|
1284
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
this.log.info("Rollback completed", {
|
|
1289
|
+
stepsAttempted: this.completedSteps.length
|
|
1290
|
+
});
|
|
1291
|
+
}
|
|
1292
|
+
/**
|
|
1293
|
+
* Get the number of completed steps (useful for testing)
|
|
1294
|
+
*/
|
|
1295
|
+
getCompletedStepCount() {
|
|
1296
|
+
return this.completedSteps.length;
|
|
1297
|
+
}
|
|
1298
|
+
};
|
|
1299
|
+
var NOOP_COLLECTOR = {
|
|
1300
|
+
time: (_label, fn) => fn(),
|
|
1301
|
+
timeSync: (_label, fn) => fn(),
|
|
1302
|
+
record: () => {
|
|
1303
|
+
},
|
|
1304
|
+
summarize: () => {
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1307
|
+
function createTimingCollector(enabled, log) {
|
|
1308
|
+
if (!enabled) return NOOP_COLLECTOR;
|
|
1309
|
+
const steps = {};
|
|
1310
|
+
return {
|
|
1311
|
+
async time(label, fn) {
|
|
1312
|
+
const start = Date.now();
|
|
1313
|
+
const result = await fn();
|
|
1314
|
+
steps[label] = Date.now() - start;
|
|
1315
|
+
return result;
|
|
1316
|
+
},
|
|
1317
|
+
timeSync(label, fn) {
|
|
1318
|
+
const start = Date.now();
|
|
1319
|
+
const result = fn();
|
|
1320
|
+
steps[label] = Date.now() - start;
|
|
1321
|
+
return result;
|
|
1322
|
+
},
|
|
1323
|
+
record(label, ms) {
|
|
1324
|
+
steps[label] = ms;
|
|
1325
|
+
},
|
|
1326
|
+
summarize(label) {
|
|
1327
|
+
const total = Object.values(steps).reduce((a, b) => a + b, 0);
|
|
1328
|
+
log(`[timing] ${label}: ${total}ms`, steps);
|
|
1329
|
+
}
|
|
1330
|
+
};
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
// src/adapters/claude/claude-agent.ts
|
|
1172
1334
|
import { v7 as uuidv7 } from "uuid";
|
|
1173
1335
|
|
|
1174
1336
|
// package.json
|
|
1175
1337
|
var package_default = {
|
|
1176
1338
|
name: "@posthog/agent",
|
|
1177
|
-
version: "2.1.
|
|
1339
|
+
version: "2.1.47",
|
|
1178
1340
|
repository: "https://github.com/PostHog/twig",
|
|
1179
1341
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
1180
1342
|
exports: {
|
|
@@ -1305,11 +1467,16 @@ function unreachable(value, logger) {
|
|
|
1305
1467
|
// src/gateway-models.ts
|
|
1306
1468
|
var DEFAULT_GATEWAY_MODEL = "claude-opus-4-6";
|
|
1307
1469
|
var BLOCKED_MODELS = /* @__PURE__ */ new Set(["gpt-5-mini", "openai/gpt-5-mini"]);
|
|
1470
|
+
var CACHE_TTL = 10 * 60 * 1e3;
|
|
1471
|
+
var gatewayModelsCache = null;
|
|
1308
1472
|
async function fetchGatewayModels(options) {
|
|
1309
1473
|
const gatewayUrl = options?.gatewayUrl ?? process.env.ANTHROPIC_BASE_URL;
|
|
1310
1474
|
if (!gatewayUrl) {
|
|
1311
1475
|
return [];
|
|
1312
1476
|
}
|
|
1477
|
+
if (gatewayModelsCache && gatewayModelsCache.url === gatewayUrl && Date.now() < gatewayModelsCache.expiry) {
|
|
1478
|
+
return gatewayModelsCache.models;
|
|
1479
|
+
}
|
|
1313
1480
|
const modelsUrl = `${gatewayUrl}/v1/models`;
|
|
1314
1481
|
try {
|
|
1315
1482
|
const response = await fetch(modelsUrl);
|
|
@@ -1317,8 +1484,13 @@ async function fetchGatewayModels(options) {
|
|
|
1317
1484
|
return [];
|
|
1318
1485
|
}
|
|
1319
1486
|
const data = await response.json();
|
|
1320
|
-
const models = data.data ?? [];
|
|
1321
|
-
|
|
1487
|
+
const models = (data.data ?? []).filter((m) => !BLOCKED_MODELS.has(m.id));
|
|
1488
|
+
gatewayModelsCache = {
|
|
1489
|
+
models,
|
|
1490
|
+
expiry: Date.now() + CACHE_TTL,
|
|
1491
|
+
url: gatewayUrl
|
|
1492
|
+
};
|
|
1493
|
+
return models;
|
|
1322
1494
|
} catch {
|
|
1323
1495
|
return [];
|
|
1324
1496
|
}
|
|
@@ -1329,11 +1501,15 @@ function isAnthropicModel(model) {
|
|
|
1329
1501
|
}
|
|
1330
1502
|
return model.id.startsWith("claude-") || model.id.startsWith("anthropic/");
|
|
1331
1503
|
}
|
|
1504
|
+
var arrayModelsCache = null;
|
|
1332
1505
|
async function fetchArrayModels(options) {
|
|
1333
1506
|
const gatewayUrl = options?.gatewayUrl ?? process.env.ANTHROPIC_BASE_URL;
|
|
1334
1507
|
if (!gatewayUrl) {
|
|
1335
1508
|
return [];
|
|
1336
1509
|
}
|
|
1510
|
+
if (arrayModelsCache && arrayModelsCache.url === gatewayUrl && Date.now() < arrayModelsCache.expiry) {
|
|
1511
|
+
return arrayModelsCache.models;
|
|
1512
|
+
}
|
|
1337
1513
|
try {
|
|
1338
1514
|
const base = new URL(gatewayUrl);
|
|
1339
1515
|
base.pathname = "/array/v1/models";
|
|
@@ -1351,6 +1527,11 @@ async function fetchArrayModels(options) {
|
|
|
1351
1527
|
if (!id) continue;
|
|
1352
1528
|
results.push({ id, owned_by: model?.owned_by });
|
|
1353
1529
|
}
|
|
1530
|
+
arrayModelsCache = {
|
|
1531
|
+
models: results,
|
|
1532
|
+
expiry: Date.now() + CACHE_TTL,
|
|
1533
|
+
url: gatewayUrl
|
|
1534
|
+
};
|
|
1354
1535
|
return results;
|
|
1355
1536
|
} catch {
|
|
1356
1537
|
return [];
|
|
@@ -3261,12 +3442,8 @@ function clearStatsigCache() {
|
|
|
3261
3442
|
process.env.CLAUDE_CONFIG_DIR || path2.join(os2.homedir(), ".claude"),
|
|
3262
3443
|
"statsig"
|
|
3263
3444
|
);
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
fs.rmSync(statsigPath, { recursive: true, force: true });
|
|
3267
|
-
}
|
|
3268
|
-
} catch {
|
|
3269
|
-
}
|
|
3445
|
+
fs.rm(statsigPath, { recursive: true, force: true }, () => {
|
|
3446
|
+
});
|
|
3270
3447
|
}
|
|
3271
3448
|
|
|
3272
3449
|
// src/adapters/claude/claude-agent.ts
|
|
@@ -3276,12 +3453,14 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3276
3453
|
backgroundTerminals = {};
|
|
3277
3454
|
clientCapabilities;
|
|
3278
3455
|
logWriter;
|
|
3279
|
-
|
|
3456
|
+
options;
|
|
3280
3457
|
lastSentConfigOptions;
|
|
3281
|
-
|
|
3458
|
+
debug;
|
|
3459
|
+
constructor(client, logWriter, options) {
|
|
3282
3460
|
super(client);
|
|
3283
3461
|
this.logWriter = logWriter;
|
|
3284
|
-
this.
|
|
3462
|
+
this.options = options;
|
|
3463
|
+
this.debug = options?.debug ?? false;
|
|
3285
3464
|
this.toolUseCache = {};
|
|
3286
3465
|
this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
|
|
3287
3466
|
}
|
|
@@ -3324,27 +3503,36 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3324
3503
|
}
|
|
3325
3504
|
async newSession(params) {
|
|
3326
3505
|
this.checkAuthStatus();
|
|
3506
|
+
const tc = createTimingCollector(
|
|
3507
|
+
this.debug,
|
|
3508
|
+
(msg, data) => this.logger.info(msg, data)
|
|
3509
|
+
);
|
|
3327
3510
|
const meta = params._meta;
|
|
3328
3511
|
const sessionId = uuidv7();
|
|
3329
3512
|
const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
3330
|
-
const mcpServers =
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3513
|
+
const mcpServers = tc.timeSync(
|
|
3514
|
+
"parseMcpServers",
|
|
3515
|
+
() => parseMcpServers(params)
|
|
3516
|
+
);
|
|
3517
|
+
const options = tc.timeSync(
|
|
3518
|
+
"buildSessionOptions",
|
|
3519
|
+
() => buildSessionOptions({
|
|
3520
|
+
cwd: params.cwd,
|
|
3521
|
+
mcpServers,
|
|
3522
|
+
permissionMode,
|
|
3523
|
+
canUseTool: this.createCanUseTool(sessionId),
|
|
3524
|
+
logger: this.logger,
|
|
3525
|
+
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
3526
|
+
userProvidedOptions: meta?.claudeCode?.options,
|
|
3527
|
+
sessionId,
|
|
3528
|
+
isResume: false,
|
|
3529
|
+
onModeChange: this.createOnModeChange(sessionId),
|
|
3530
|
+
onProcessSpawned: this.options?.onProcessSpawned,
|
|
3531
|
+
onProcessExited: this.options?.onProcessExited
|
|
3532
|
+
})
|
|
3533
|
+
);
|
|
3346
3534
|
const input = new Pushable();
|
|
3347
|
-
const q = query({ prompt: input, options });
|
|
3535
|
+
const q = tc.timeSync("sdkQuery", () => query({ prompt: input, options }));
|
|
3348
3536
|
const session = this.createSession(
|
|
3349
3537
|
sessionId,
|
|
3350
3538
|
q,
|
|
@@ -3356,28 +3544,40 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3356
3544
|
session.taskRunId = meta?.taskRunId;
|
|
3357
3545
|
this.registerPersistence(sessionId, meta);
|
|
3358
3546
|
if (meta?.taskRunId) {
|
|
3359
|
-
await
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3547
|
+
await tc.time(
|
|
3548
|
+
"extNotification",
|
|
3549
|
+
() => this.client.extNotification("_posthog/sdk_session", {
|
|
3550
|
+
taskRunId: meta.taskRunId,
|
|
3551
|
+
sessionId,
|
|
3552
|
+
adapter: "claude"
|
|
3553
|
+
})
|
|
3554
|
+
);
|
|
3364
3555
|
}
|
|
3365
|
-
const modelOptions = await
|
|
3556
|
+
const modelOptions = await tc.time(
|
|
3557
|
+
"fetchModels",
|
|
3558
|
+
() => this.getModelConfigOptions()
|
|
3559
|
+
);
|
|
3560
|
+
this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
|
|
3366
3561
|
session.modelId = modelOptions.currentModelId;
|
|
3367
3562
|
await this.trySetModel(q, modelOptions.currentModelId);
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3563
|
+
const configOptions = await tc.time(
|
|
3564
|
+
"buildConfigOptions",
|
|
3565
|
+
() => this.buildConfigOptions(modelOptions)
|
|
3371
3566
|
);
|
|
3567
|
+
tc.summarize("newSession");
|
|
3372
3568
|
return {
|
|
3373
3569
|
sessionId,
|
|
3374
|
-
configOptions
|
|
3570
|
+
configOptions
|
|
3375
3571
|
};
|
|
3376
3572
|
}
|
|
3377
3573
|
async loadSession(params) {
|
|
3378
3574
|
return this.resumeSession(params);
|
|
3379
3575
|
}
|
|
3380
3576
|
async resumeSession(params) {
|
|
3577
|
+
const tc = createTimingCollector(
|
|
3578
|
+
this.debug,
|
|
3579
|
+
(msg, data) => this.logger.info(msg, data)
|
|
3580
|
+
);
|
|
3381
3581
|
const meta = params._meta;
|
|
3382
3582
|
const sessionId = meta?.sessionId;
|
|
3383
3583
|
if (!sessionId) {
|
|
@@ -3386,28 +3586,33 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3386
3586
|
if (this.sessionId === sessionId) {
|
|
3387
3587
|
return {};
|
|
3388
3588
|
}
|
|
3389
|
-
const mcpServers =
|
|
3390
|
-
|
|
3589
|
+
const mcpServers = tc.timeSync(
|
|
3590
|
+
"parseMcpServers",
|
|
3591
|
+
() => parseMcpServers(params)
|
|
3592
|
+
);
|
|
3391
3593
|
const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
3392
|
-
const { query: q, session } = await
|
|
3393
|
-
|
|
3394
|
-
|
|
3395
|
-
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3594
|
+
const { query: q, session } = await tc.time(
|
|
3595
|
+
"initializeQuery",
|
|
3596
|
+
() => this.initializeQuery({
|
|
3597
|
+
cwd: params.cwd,
|
|
3598
|
+
permissionMode,
|
|
3599
|
+
mcpServers,
|
|
3600
|
+
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
3601
|
+
userProvidedOptions: meta?.claudeCode?.options,
|
|
3602
|
+
sessionId,
|
|
3603
|
+
isResume: true,
|
|
3604
|
+
additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
|
|
3605
|
+
})
|
|
3606
|
+
);
|
|
3402
3607
|
session.taskRunId = meta?.taskRunId;
|
|
3403
3608
|
this.registerPersistence(sessionId, meta);
|
|
3404
|
-
this.
|
|
3405
|
-
|
|
3406
|
-
|
|
3609
|
+
this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
|
|
3610
|
+
const configOptions = await tc.time(
|
|
3611
|
+
"buildConfigOptions",
|
|
3612
|
+
() => this.buildConfigOptions()
|
|
3407
3613
|
);
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
};
|
|
3614
|
+
tc.summarize("resumeSession");
|
|
3615
|
+
return { configOptions };
|
|
3411
3616
|
}
|
|
3412
3617
|
async prompt(params) {
|
|
3413
3618
|
this.session.cancelled = false;
|
|
@@ -3479,8 +3684,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3479
3684
|
isResume: config.isResume,
|
|
3480
3685
|
additionalDirectories: config.additionalDirectories,
|
|
3481
3686
|
onModeChange: this.createOnModeChange(config.sessionId),
|
|
3482
|
-
onProcessSpawned: this.
|
|
3483
|
-
onProcessExited: this.
|
|
3687
|
+
onProcessSpawned: this.options?.onProcessSpawned,
|
|
3688
|
+
onProcessExited: this.options?.onProcessExited
|
|
3484
3689
|
});
|
|
3485
3690
|
const q = query({ prompt: input, options });
|
|
3486
3691
|
const abortController = options.abortController;
|
|
@@ -3590,6 +3795,23 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3590
3795
|
await q.setModel(fallback);
|
|
3591
3796
|
}
|
|
3592
3797
|
}
|
|
3798
|
+
/**
|
|
3799
|
+
* Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
|
|
3800
|
+
* Both populate caches used later — neither is needed to return configOptions.
|
|
3801
|
+
*/
|
|
3802
|
+
deferBackgroundFetches(tc, q, sessionId, mcpServers) {
|
|
3803
|
+
Promise.all([
|
|
3804
|
+
tc.time("slashCommands", () => getAvailableSlashCommands(q)),
|
|
3805
|
+
tc.time(
|
|
3806
|
+
"mcpMetadata",
|
|
3807
|
+
() => fetchMcpToolMetadata(mcpServers, this.logger)
|
|
3808
|
+
)
|
|
3809
|
+
]).then(([slashCommands]) => {
|
|
3810
|
+
this.sendAvailableCommandsUpdate(sessionId, slashCommands);
|
|
3811
|
+
}).catch((err) => {
|
|
3812
|
+
this.logger.warn("Failed to fetch deferred session data", { err });
|
|
3813
|
+
});
|
|
3814
|
+
}
|
|
3593
3815
|
registerPersistence(sessionId, meta) {
|
|
3594
3816
|
const persistence = meta?.persistence;
|
|
3595
3817
|
if (persistence && this.logWriter) {
|
|
@@ -3877,7 +4099,10 @@ function createClaudeConnection(config) {
|
|
|
3877
4099
|
const agentStream = ndJsonStream(agentWritable, streams.agent.readable);
|
|
3878
4100
|
let agent = null;
|
|
3879
4101
|
const agentConnection = new AgentSideConnection((client) => {
|
|
3880
|
-
agent = new ClaudeAcpAgent(client, logWriter,
|
|
4102
|
+
agent = new ClaudeAcpAgent(client, logWriter, {
|
|
4103
|
+
...config.processCallbacks,
|
|
4104
|
+
debug: config.debug
|
|
4105
|
+
});
|
|
3881
4106
|
logger.info(`Created ${agent.adapterName} agent`);
|
|
3882
4107
|
return agent;
|
|
3883
4108
|
}, agentStream);
|
|
@@ -4577,6 +4802,7 @@ var Agent = class {
|
|
|
4577
4802
|
taskId,
|
|
4578
4803
|
deviceType: "local",
|
|
4579
4804
|
logger: this.logger,
|
|
4805
|
+
debug: this.debug,
|
|
4580
4806
|
processCallbacks: options.processCallbacks,
|
|
4581
4807
|
allowedModelIds,
|
|
4582
4808
|
codexOptions: options.adapter === "codex" && gatewayConfig ? {
|
|
@@ -4677,133 +4903,6 @@ var OtelLogWriter = class {
|
|
|
4677
4903
|
}
|
|
4678
4904
|
};
|
|
4679
4905
|
|
|
4680
|
-
// ../shared/dist/index.js
|
|
4681
|
-
var consoleLogger = {
|
|
4682
|
-
info: (_message, _data) => {
|
|
4683
|
-
},
|
|
4684
|
-
debug: (_message, _data) => {
|
|
4685
|
-
},
|
|
4686
|
-
error: (_message, _data) => {
|
|
4687
|
-
},
|
|
4688
|
-
warn: (_message, _data) => {
|
|
4689
|
-
}
|
|
4690
|
-
};
|
|
4691
|
-
var Saga = class {
|
|
4692
|
-
completedSteps = [];
|
|
4693
|
-
currentStepName = "unknown";
|
|
4694
|
-
stepTimings = [];
|
|
4695
|
-
log;
|
|
4696
|
-
constructor(logger) {
|
|
4697
|
-
this.log = logger ?? consoleLogger;
|
|
4698
|
-
}
|
|
4699
|
-
/**
|
|
4700
|
-
* Run the saga with the given input.
|
|
4701
|
-
* Returns a discriminated union result - either success with data or failure with error details.
|
|
4702
|
-
*/
|
|
4703
|
-
async run(input) {
|
|
4704
|
-
this.completedSteps = [];
|
|
4705
|
-
this.currentStepName = "unknown";
|
|
4706
|
-
this.stepTimings = [];
|
|
4707
|
-
const sagaStart = performance.now();
|
|
4708
|
-
this.log.info("Starting saga", { sagaName: this.constructor.name });
|
|
4709
|
-
try {
|
|
4710
|
-
const result = await this.execute(input);
|
|
4711
|
-
const totalDuration = performance.now() - sagaStart;
|
|
4712
|
-
this.log.debug("Saga completed successfully", {
|
|
4713
|
-
sagaName: this.constructor.name,
|
|
4714
|
-
stepsCompleted: this.completedSteps.length,
|
|
4715
|
-
totalDurationMs: Math.round(totalDuration),
|
|
4716
|
-
stepTimings: this.stepTimings
|
|
4717
|
-
});
|
|
4718
|
-
return { success: true, data: result };
|
|
4719
|
-
} catch (error) {
|
|
4720
|
-
this.log.error("Saga failed, initiating rollback", {
|
|
4721
|
-
sagaName: this.constructor.name,
|
|
4722
|
-
failedStep: this.currentStepName,
|
|
4723
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4724
|
-
});
|
|
4725
|
-
await this.rollback();
|
|
4726
|
-
return {
|
|
4727
|
-
success: false,
|
|
4728
|
-
error: error instanceof Error ? error.message : String(error),
|
|
4729
|
-
failedStep: this.currentStepName
|
|
4730
|
-
};
|
|
4731
|
-
}
|
|
4732
|
-
}
|
|
4733
|
-
/**
|
|
4734
|
-
* Execute a step with its rollback action.
|
|
4735
|
-
* If the step succeeds, its rollback action is stored for potential rollback.
|
|
4736
|
-
* The step name is automatically tracked for error reporting.
|
|
4737
|
-
*
|
|
4738
|
-
* @param config - Step configuration with name, execute, and rollback functions
|
|
4739
|
-
* @returns The result of the execute function
|
|
4740
|
-
* @throws Re-throws any error from the execute function (triggers rollback)
|
|
4741
|
-
*/
|
|
4742
|
-
async step(config) {
|
|
4743
|
-
this.currentStepName = config.name;
|
|
4744
|
-
this.log.debug(`Executing step: ${config.name}`);
|
|
4745
|
-
const stepStart = performance.now();
|
|
4746
|
-
const result = await config.execute();
|
|
4747
|
-
const durationMs = Math.round(performance.now() - stepStart);
|
|
4748
|
-
this.stepTimings.push({ name: config.name, durationMs });
|
|
4749
|
-
this.log.debug(`Step completed: ${config.name}`, { durationMs });
|
|
4750
|
-
this.completedSteps.push({
|
|
4751
|
-
name: config.name,
|
|
4752
|
-
rollback: () => config.rollback(result)
|
|
4753
|
-
});
|
|
4754
|
-
return result;
|
|
4755
|
-
}
|
|
4756
|
-
/**
|
|
4757
|
-
* Execute a step that doesn't need rollback.
|
|
4758
|
-
* Useful for read-only operations or operations that are idempotent.
|
|
4759
|
-
* The step name is automatically tracked for error reporting.
|
|
4760
|
-
*
|
|
4761
|
-
* @param name - Step name for logging and error tracking
|
|
4762
|
-
* @param execute - The action to execute
|
|
4763
|
-
* @returns The result of the execute function
|
|
4764
|
-
*/
|
|
4765
|
-
async readOnlyStep(name, execute) {
|
|
4766
|
-
this.currentStepName = name;
|
|
4767
|
-
this.log.debug(`Executing read-only step: ${name}`);
|
|
4768
|
-
const stepStart = performance.now();
|
|
4769
|
-
const result = await execute();
|
|
4770
|
-
const durationMs = Math.round(performance.now() - stepStart);
|
|
4771
|
-
this.stepTimings.push({ name, durationMs });
|
|
4772
|
-
this.log.debug(`Read-only step completed: ${name}`, { durationMs });
|
|
4773
|
-
return result;
|
|
4774
|
-
}
|
|
4775
|
-
/**
|
|
4776
|
-
* Roll back all completed steps in reverse order.
|
|
4777
|
-
* Rollback errors are logged but don't stop the rollback of other steps.
|
|
4778
|
-
*/
|
|
4779
|
-
async rollback() {
|
|
4780
|
-
this.log.info("Rolling back saga", {
|
|
4781
|
-
stepsToRollback: this.completedSteps.length
|
|
4782
|
-
});
|
|
4783
|
-
const stepsReversed = [...this.completedSteps].reverse();
|
|
4784
|
-
for (const step of stepsReversed) {
|
|
4785
|
-
try {
|
|
4786
|
-
this.log.debug(`Rolling back step: ${step.name}`);
|
|
4787
|
-
await step.rollback();
|
|
4788
|
-
this.log.debug(`Step rolled back: ${step.name}`);
|
|
4789
|
-
} catch (error) {
|
|
4790
|
-
this.log.error(`Failed to rollback step: ${step.name}`, {
|
|
4791
|
-
error: error instanceof Error ? error.message : String(error)
|
|
4792
|
-
});
|
|
4793
|
-
}
|
|
4794
|
-
}
|
|
4795
|
-
this.log.info("Rollback completed", {
|
|
4796
|
-
stepsAttempted: this.completedSteps.length
|
|
4797
|
-
});
|
|
4798
|
-
}
|
|
4799
|
-
/**
|
|
4800
|
-
* Get the number of completed steps (useful for testing)
|
|
4801
|
-
*/
|
|
4802
|
-
getCompletedStepCount() {
|
|
4803
|
-
return this.completedSteps.length;
|
|
4804
|
-
}
|
|
4805
|
-
};
|
|
4806
|
-
|
|
4807
4906
|
// ../git/dist/queries.js
|
|
4808
4907
|
import * as fs4 from "fs/promises";
|
|
4809
4908
|
import * as path5 from "path";
|
|
@@ -9570,7 +9669,7 @@ async function isCommitOnRemote(baseDir, commit, options) {
|
|
|
9570
9669
|
}
|
|
9571
9670
|
|
|
9572
9671
|
// src/sagas/apply-snapshot-saga.ts
|
|
9573
|
-
import { mkdir as mkdir3, rm as
|
|
9672
|
+
import { mkdir as mkdir3, rm as rm3, writeFile as writeFile3 } from "fs/promises";
|
|
9574
9673
|
import { join as join5 } from "path";
|
|
9575
9674
|
|
|
9576
9675
|
// ../git/dist/sagas/tree.js
|
|
@@ -9884,7 +9983,7 @@ var ApplySnapshotSaga = class extends Saga {
|
|
|
9884
9983
|
},
|
|
9885
9984
|
rollback: async () => {
|
|
9886
9985
|
if (this.archivePath) {
|
|
9887
|
-
await
|
|
9986
|
+
await rm3(this.archivePath, { force: true }).catch(() => {
|
|
9888
9987
|
});
|
|
9889
9988
|
}
|
|
9890
9989
|
}
|
|
@@ -9900,7 +9999,7 @@ var ApplySnapshotSaga = class extends Saga {
|
|
|
9900
9999
|
if (!applyResult.success) {
|
|
9901
10000
|
throw new Error(`Failed to apply tree: ${applyResult.error}`);
|
|
9902
10001
|
}
|
|
9903
|
-
await
|
|
10002
|
+
await rm3(this.archivePath, { force: true }).catch(() => {
|
|
9904
10003
|
});
|
|
9905
10004
|
this.log.info("Tree snapshot applied", {
|
|
9906
10005
|
treeHash: snapshot.treeHash,
|
|
@@ -9913,7 +10012,7 @@ var ApplySnapshotSaga = class extends Saga {
|
|
|
9913
10012
|
|
|
9914
10013
|
// src/sagas/capture-tree-saga.ts
|
|
9915
10014
|
import { existsSync as existsSync5 } from "fs";
|
|
9916
|
-
import { readFile as readFile3, rm as
|
|
10015
|
+
import { readFile as readFile3, rm as rm4 } from "fs/promises";
|
|
9917
10016
|
import { join as join6 } from "path";
|
|
9918
10017
|
var CaptureTreeSaga2 = class extends Saga {
|
|
9919
10018
|
async execute(input) {
|
|
@@ -9962,7 +10061,7 @@ var CaptureTreeSaga2 = class extends Saga {
|
|
|
9962
10061
|
runId
|
|
9963
10062
|
);
|
|
9964
10063
|
} finally {
|
|
9965
|
-
await
|
|
10064
|
+
await rm4(createdArchivePath, { force: true }).catch(() => {
|
|
9966
10065
|
});
|
|
9967
10066
|
}
|
|
9968
10067
|
}
|
|
@@ -10006,7 +10105,7 @@ var CaptureTreeSaga2 = class extends Saga {
|
|
|
10006
10105
|
return void 0;
|
|
10007
10106
|
},
|
|
10008
10107
|
rollback: async () => {
|
|
10009
|
-
await
|
|
10108
|
+
await rm4(archivePath, { force: true }).catch(() => {
|
|
10010
10109
|
});
|
|
10011
10110
|
}
|
|
10012
10111
|
});
|