@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/server/bin.cjs
CHANGED
|
@@ -1170,12 +1170,174 @@ var os3 = __toESM(require("os"), 1);
|
|
|
1170
1170
|
var path3 = __toESM(require("path"), 1);
|
|
1171
1171
|
var import_sdk2 = require("@agentclientprotocol/sdk");
|
|
1172
1172
|
var import_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
1173
|
+
|
|
1174
|
+
// ../shared/dist/index.js
|
|
1175
|
+
var consoleLogger = {
|
|
1176
|
+
info: (_message, _data) => {
|
|
1177
|
+
},
|
|
1178
|
+
debug: (_message, _data) => {
|
|
1179
|
+
},
|
|
1180
|
+
error: (_message, _data) => {
|
|
1181
|
+
},
|
|
1182
|
+
warn: (_message, _data) => {
|
|
1183
|
+
}
|
|
1184
|
+
};
|
|
1185
|
+
var Saga = class {
|
|
1186
|
+
completedSteps = [];
|
|
1187
|
+
currentStepName = "unknown";
|
|
1188
|
+
stepTimings = [];
|
|
1189
|
+
log;
|
|
1190
|
+
constructor(logger) {
|
|
1191
|
+
this.log = logger ?? consoleLogger;
|
|
1192
|
+
}
|
|
1193
|
+
/**
|
|
1194
|
+
* Run the saga with the given input.
|
|
1195
|
+
* Returns a discriminated union result - either success with data or failure with error details.
|
|
1196
|
+
*/
|
|
1197
|
+
async run(input) {
|
|
1198
|
+
this.completedSteps = [];
|
|
1199
|
+
this.currentStepName = "unknown";
|
|
1200
|
+
this.stepTimings = [];
|
|
1201
|
+
const sagaStart = performance.now();
|
|
1202
|
+
this.log.info("Starting saga", { sagaName: this.constructor.name });
|
|
1203
|
+
try {
|
|
1204
|
+
const result = await this.execute(input);
|
|
1205
|
+
const totalDuration = performance.now() - sagaStart;
|
|
1206
|
+
this.log.debug("Saga completed successfully", {
|
|
1207
|
+
sagaName: this.constructor.name,
|
|
1208
|
+
stepsCompleted: this.completedSteps.length,
|
|
1209
|
+
totalDurationMs: Math.round(totalDuration),
|
|
1210
|
+
stepTimings: this.stepTimings
|
|
1211
|
+
});
|
|
1212
|
+
return { success: true, data: result };
|
|
1213
|
+
} catch (error) {
|
|
1214
|
+
this.log.error("Saga failed, initiating rollback", {
|
|
1215
|
+
sagaName: this.constructor.name,
|
|
1216
|
+
failedStep: this.currentStepName,
|
|
1217
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1218
|
+
});
|
|
1219
|
+
await this.rollback();
|
|
1220
|
+
return {
|
|
1221
|
+
success: false,
|
|
1222
|
+
error: error instanceof Error ? error.message : String(error),
|
|
1223
|
+
failedStep: this.currentStepName
|
|
1224
|
+
};
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Execute a step with its rollback action.
|
|
1229
|
+
* If the step succeeds, its rollback action is stored for potential rollback.
|
|
1230
|
+
* The step name is automatically tracked for error reporting.
|
|
1231
|
+
*
|
|
1232
|
+
* @param config - Step configuration with name, execute, and rollback functions
|
|
1233
|
+
* @returns The result of the execute function
|
|
1234
|
+
* @throws Re-throws any error from the execute function (triggers rollback)
|
|
1235
|
+
*/
|
|
1236
|
+
async step(config) {
|
|
1237
|
+
this.currentStepName = config.name;
|
|
1238
|
+
this.log.debug(`Executing step: ${config.name}`);
|
|
1239
|
+
const stepStart = performance.now();
|
|
1240
|
+
const result = await config.execute();
|
|
1241
|
+
const durationMs = Math.round(performance.now() - stepStart);
|
|
1242
|
+
this.stepTimings.push({ name: config.name, durationMs });
|
|
1243
|
+
this.log.debug(`Step completed: ${config.name}`, { durationMs });
|
|
1244
|
+
this.completedSteps.push({
|
|
1245
|
+
name: config.name,
|
|
1246
|
+
rollback: () => config.rollback(result)
|
|
1247
|
+
});
|
|
1248
|
+
return result;
|
|
1249
|
+
}
|
|
1250
|
+
/**
|
|
1251
|
+
* Execute a step that doesn't need rollback.
|
|
1252
|
+
* Useful for read-only operations or operations that are idempotent.
|
|
1253
|
+
* The step name is automatically tracked for error reporting.
|
|
1254
|
+
*
|
|
1255
|
+
* @param name - Step name for logging and error tracking
|
|
1256
|
+
* @param execute - The action to execute
|
|
1257
|
+
* @returns The result of the execute function
|
|
1258
|
+
*/
|
|
1259
|
+
async readOnlyStep(name, execute) {
|
|
1260
|
+
this.currentStepName = name;
|
|
1261
|
+
this.log.debug(`Executing read-only step: ${name}`);
|
|
1262
|
+
const stepStart = performance.now();
|
|
1263
|
+
const result = await execute();
|
|
1264
|
+
const durationMs = Math.round(performance.now() - stepStart);
|
|
1265
|
+
this.stepTimings.push({ name, durationMs });
|
|
1266
|
+
this.log.debug(`Read-only step completed: ${name}`, { durationMs });
|
|
1267
|
+
return result;
|
|
1268
|
+
}
|
|
1269
|
+
/**
|
|
1270
|
+
* Roll back all completed steps in reverse order.
|
|
1271
|
+
* Rollback errors are logged but don't stop the rollback of other steps.
|
|
1272
|
+
*/
|
|
1273
|
+
async rollback() {
|
|
1274
|
+
this.log.info("Rolling back saga", {
|
|
1275
|
+
stepsToRollback: this.completedSteps.length
|
|
1276
|
+
});
|
|
1277
|
+
const stepsReversed = [...this.completedSteps].reverse();
|
|
1278
|
+
for (const step of stepsReversed) {
|
|
1279
|
+
try {
|
|
1280
|
+
this.log.debug(`Rolling back step: ${step.name}`);
|
|
1281
|
+
await step.rollback();
|
|
1282
|
+
this.log.debug(`Step rolled back: ${step.name}`);
|
|
1283
|
+
} catch (error) {
|
|
1284
|
+
this.log.error(`Failed to rollback step: ${step.name}`, {
|
|
1285
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1286
|
+
});
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
this.log.info("Rollback completed", {
|
|
1290
|
+
stepsAttempted: this.completedSteps.length
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
/**
|
|
1294
|
+
* Get the number of completed steps (useful for testing)
|
|
1295
|
+
*/
|
|
1296
|
+
getCompletedStepCount() {
|
|
1297
|
+
return this.completedSteps.length;
|
|
1298
|
+
}
|
|
1299
|
+
};
|
|
1300
|
+
var NOOP_COLLECTOR = {
|
|
1301
|
+
time: (_label, fn) => fn(),
|
|
1302
|
+
timeSync: (_label, fn) => fn(),
|
|
1303
|
+
record: () => {
|
|
1304
|
+
},
|
|
1305
|
+
summarize: () => {
|
|
1306
|
+
}
|
|
1307
|
+
};
|
|
1308
|
+
function createTimingCollector(enabled, log) {
|
|
1309
|
+
if (!enabled) return NOOP_COLLECTOR;
|
|
1310
|
+
const steps = {};
|
|
1311
|
+
return {
|
|
1312
|
+
async time(label, fn) {
|
|
1313
|
+
const start = Date.now();
|
|
1314
|
+
const result = await fn();
|
|
1315
|
+
steps[label] = Date.now() - start;
|
|
1316
|
+
return result;
|
|
1317
|
+
},
|
|
1318
|
+
timeSync(label, fn) {
|
|
1319
|
+
const start = Date.now();
|
|
1320
|
+
const result = fn();
|
|
1321
|
+
steps[label] = Date.now() - start;
|
|
1322
|
+
return result;
|
|
1323
|
+
},
|
|
1324
|
+
record(label, ms) {
|
|
1325
|
+
steps[label] = ms;
|
|
1326
|
+
},
|
|
1327
|
+
summarize(label) {
|
|
1328
|
+
const total = Object.values(steps).reduce((a, b) => a + b, 0);
|
|
1329
|
+
log(`[timing] ${label}: ${total}ms`, steps);
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// src/adapters/claude/claude-agent.ts
|
|
1173
1335
|
var import_uuid = require("uuid");
|
|
1174
1336
|
|
|
1175
1337
|
// package.json
|
|
1176
1338
|
var package_default = {
|
|
1177
1339
|
name: "@posthog/agent",
|
|
1178
|
-
version: "2.1.
|
|
1340
|
+
version: "2.1.47",
|
|
1179
1341
|
repository: "https://github.com/PostHog/twig",
|
|
1180
1342
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
1181
1343
|
exports: {
|
|
@@ -1306,11 +1468,16 @@ function unreachable(value, logger) {
|
|
|
1306
1468
|
// src/gateway-models.ts
|
|
1307
1469
|
var DEFAULT_GATEWAY_MODEL = "claude-opus-4-6";
|
|
1308
1470
|
var BLOCKED_MODELS = /* @__PURE__ */ new Set(["gpt-5-mini", "openai/gpt-5-mini"]);
|
|
1471
|
+
var CACHE_TTL = 10 * 60 * 1e3;
|
|
1472
|
+
var gatewayModelsCache = null;
|
|
1309
1473
|
async function fetchGatewayModels(options) {
|
|
1310
1474
|
const gatewayUrl = options?.gatewayUrl ?? process.env.ANTHROPIC_BASE_URL;
|
|
1311
1475
|
if (!gatewayUrl) {
|
|
1312
1476
|
return [];
|
|
1313
1477
|
}
|
|
1478
|
+
if (gatewayModelsCache && gatewayModelsCache.url === gatewayUrl && Date.now() < gatewayModelsCache.expiry) {
|
|
1479
|
+
return gatewayModelsCache.models;
|
|
1480
|
+
}
|
|
1314
1481
|
const modelsUrl = `${gatewayUrl}/v1/models`;
|
|
1315
1482
|
try {
|
|
1316
1483
|
const response = await fetch(modelsUrl);
|
|
@@ -1318,8 +1485,13 @@ async function fetchGatewayModels(options) {
|
|
|
1318
1485
|
return [];
|
|
1319
1486
|
}
|
|
1320
1487
|
const data = await response.json();
|
|
1321
|
-
const models = data.data ?? [];
|
|
1322
|
-
|
|
1488
|
+
const models = (data.data ?? []).filter((m) => !BLOCKED_MODELS.has(m.id));
|
|
1489
|
+
gatewayModelsCache = {
|
|
1490
|
+
models,
|
|
1491
|
+
expiry: Date.now() + CACHE_TTL,
|
|
1492
|
+
url: gatewayUrl
|
|
1493
|
+
};
|
|
1494
|
+
return models;
|
|
1323
1495
|
} catch {
|
|
1324
1496
|
return [];
|
|
1325
1497
|
}
|
|
@@ -3227,12 +3399,8 @@ function clearStatsigCache() {
|
|
|
3227
3399
|
process.env.CLAUDE_CONFIG_DIR || path2.join(os2.homedir(), ".claude"),
|
|
3228
3400
|
"statsig"
|
|
3229
3401
|
);
|
|
3230
|
-
|
|
3231
|
-
|
|
3232
|
-
fs.rmSync(statsigPath, { recursive: true, force: true });
|
|
3233
|
-
}
|
|
3234
|
-
} catch {
|
|
3235
|
-
}
|
|
3402
|
+
fs.rm(statsigPath, { recursive: true, force: true }, () => {
|
|
3403
|
+
});
|
|
3236
3404
|
}
|
|
3237
3405
|
|
|
3238
3406
|
// src/adapters/claude/claude-agent.ts
|
|
@@ -3242,12 +3410,14 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3242
3410
|
backgroundTerminals = {};
|
|
3243
3411
|
clientCapabilities;
|
|
3244
3412
|
logWriter;
|
|
3245
|
-
|
|
3413
|
+
options;
|
|
3246
3414
|
lastSentConfigOptions;
|
|
3247
|
-
|
|
3415
|
+
debug;
|
|
3416
|
+
constructor(client, logWriter, options) {
|
|
3248
3417
|
super(client);
|
|
3249
3418
|
this.logWriter = logWriter;
|
|
3250
|
-
this.
|
|
3419
|
+
this.options = options;
|
|
3420
|
+
this.debug = options?.debug ?? false;
|
|
3251
3421
|
this.toolUseCache = {};
|
|
3252
3422
|
this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
|
|
3253
3423
|
}
|
|
@@ -3290,27 +3460,36 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3290
3460
|
}
|
|
3291
3461
|
async newSession(params) {
|
|
3292
3462
|
this.checkAuthStatus();
|
|
3463
|
+
const tc = createTimingCollector(
|
|
3464
|
+
this.debug,
|
|
3465
|
+
(msg, data) => this.logger.info(msg, data)
|
|
3466
|
+
);
|
|
3293
3467
|
const meta = params._meta;
|
|
3294
3468
|
const sessionId = (0, import_uuid.v7)();
|
|
3295
3469
|
const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
3296
|
-
const mcpServers =
|
|
3297
|
-
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3302
|
-
|
|
3303
|
-
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3470
|
+
const mcpServers = tc.timeSync(
|
|
3471
|
+
"parseMcpServers",
|
|
3472
|
+
() => parseMcpServers(params)
|
|
3473
|
+
);
|
|
3474
|
+
const options = tc.timeSync(
|
|
3475
|
+
"buildSessionOptions",
|
|
3476
|
+
() => buildSessionOptions({
|
|
3477
|
+
cwd: params.cwd,
|
|
3478
|
+
mcpServers,
|
|
3479
|
+
permissionMode,
|
|
3480
|
+
canUseTool: this.createCanUseTool(sessionId),
|
|
3481
|
+
logger: this.logger,
|
|
3482
|
+
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
3483
|
+
userProvidedOptions: meta?.claudeCode?.options,
|
|
3484
|
+
sessionId,
|
|
3485
|
+
isResume: false,
|
|
3486
|
+
onModeChange: this.createOnModeChange(sessionId),
|
|
3487
|
+
onProcessSpawned: this.options?.onProcessSpawned,
|
|
3488
|
+
onProcessExited: this.options?.onProcessExited
|
|
3489
|
+
})
|
|
3490
|
+
);
|
|
3312
3491
|
const input = new Pushable();
|
|
3313
|
-
const q = (0, import_claude_agent_sdk.query)({ prompt: input, options });
|
|
3492
|
+
const q = tc.timeSync("sdkQuery", () => (0, import_claude_agent_sdk.query)({ prompt: input, options }));
|
|
3314
3493
|
const session = this.createSession(
|
|
3315
3494
|
sessionId,
|
|
3316
3495
|
q,
|
|
@@ -3322,28 +3501,40 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3322
3501
|
session.taskRunId = meta?.taskRunId;
|
|
3323
3502
|
this.registerPersistence(sessionId, meta);
|
|
3324
3503
|
if (meta?.taskRunId) {
|
|
3325
|
-
await
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3504
|
+
await tc.time(
|
|
3505
|
+
"extNotification",
|
|
3506
|
+
() => this.client.extNotification("_posthog/sdk_session", {
|
|
3507
|
+
taskRunId: meta.taskRunId,
|
|
3508
|
+
sessionId,
|
|
3509
|
+
adapter: "claude"
|
|
3510
|
+
})
|
|
3511
|
+
);
|
|
3330
3512
|
}
|
|
3331
|
-
const modelOptions = await
|
|
3513
|
+
const modelOptions = await tc.time(
|
|
3514
|
+
"fetchModels",
|
|
3515
|
+
() => this.getModelConfigOptions()
|
|
3516
|
+
);
|
|
3517
|
+
this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
|
|
3332
3518
|
session.modelId = modelOptions.currentModelId;
|
|
3333
3519
|
await this.trySetModel(q, modelOptions.currentModelId);
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3520
|
+
const configOptions = await tc.time(
|
|
3521
|
+
"buildConfigOptions",
|
|
3522
|
+
() => this.buildConfigOptions(modelOptions)
|
|
3337
3523
|
);
|
|
3524
|
+
tc.summarize("newSession");
|
|
3338
3525
|
return {
|
|
3339
3526
|
sessionId,
|
|
3340
|
-
configOptions
|
|
3527
|
+
configOptions
|
|
3341
3528
|
};
|
|
3342
3529
|
}
|
|
3343
3530
|
async loadSession(params) {
|
|
3344
3531
|
return this.resumeSession(params);
|
|
3345
3532
|
}
|
|
3346
3533
|
async resumeSession(params) {
|
|
3534
|
+
const tc = createTimingCollector(
|
|
3535
|
+
this.debug,
|
|
3536
|
+
(msg, data) => this.logger.info(msg, data)
|
|
3537
|
+
);
|
|
3347
3538
|
const meta = params._meta;
|
|
3348
3539
|
const sessionId = meta?.sessionId;
|
|
3349
3540
|
if (!sessionId) {
|
|
@@ -3352,28 +3543,33 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3352
3543
|
if (this.sessionId === sessionId) {
|
|
3353
3544
|
return {};
|
|
3354
3545
|
}
|
|
3355
|
-
const mcpServers =
|
|
3356
|
-
|
|
3546
|
+
const mcpServers = tc.timeSync(
|
|
3547
|
+
"parseMcpServers",
|
|
3548
|
+
() => parseMcpServers(params)
|
|
3549
|
+
);
|
|
3357
3550
|
const permissionMode = meta?.permissionMode && TWIG_EXECUTION_MODES.includes(meta.permissionMode) ? meta.permissionMode : "default";
|
|
3358
|
-
const { query: q, session } = await
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3551
|
+
const { query: q, session } = await tc.time(
|
|
3552
|
+
"initializeQuery",
|
|
3553
|
+
() => this.initializeQuery({
|
|
3554
|
+
cwd: params.cwd,
|
|
3555
|
+
permissionMode,
|
|
3556
|
+
mcpServers,
|
|
3557
|
+
systemPrompt: buildSystemPrompt(meta?.systemPrompt),
|
|
3558
|
+
userProvidedOptions: meta?.claudeCode?.options,
|
|
3559
|
+
sessionId,
|
|
3560
|
+
isResume: true,
|
|
3561
|
+
additionalDirectories: meta?.claudeCode?.options?.additionalDirectories
|
|
3562
|
+
})
|
|
3563
|
+
);
|
|
3368
3564
|
session.taskRunId = meta?.taskRunId;
|
|
3369
3565
|
this.registerPersistence(sessionId, meta);
|
|
3370
|
-
this.
|
|
3371
|
-
|
|
3372
|
-
|
|
3566
|
+
this.deferBackgroundFetches(tc, q, sessionId, mcpServers);
|
|
3567
|
+
const configOptions = await tc.time(
|
|
3568
|
+
"buildConfigOptions",
|
|
3569
|
+
() => this.buildConfigOptions()
|
|
3373
3570
|
);
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
};
|
|
3571
|
+
tc.summarize("resumeSession");
|
|
3572
|
+
return { configOptions };
|
|
3377
3573
|
}
|
|
3378
3574
|
async prompt(params) {
|
|
3379
3575
|
this.session.cancelled = false;
|
|
@@ -3445,8 +3641,8 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3445
3641
|
isResume: config.isResume,
|
|
3446
3642
|
additionalDirectories: config.additionalDirectories,
|
|
3447
3643
|
onModeChange: this.createOnModeChange(config.sessionId),
|
|
3448
|
-
onProcessSpawned: this.
|
|
3449
|
-
onProcessExited: this.
|
|
3644
|
+
onProcessSpawned: this.options?.onProcessSpawned,
|
|
3645
|
+
onProcessExited: this.options?.onProcessExited
|
|
3450
3646
|
});
|
|
3451
3647
|
const q = (0, import_claude_agent_sdk.query)({ prompt: input, options });
|
|
3452
3648
|
const abortController = options.abortController;
|
|
@@ -3556,6 +3752,23 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
3556
3752
|
await q.setModel(fallback);
|
|
3557
3753
|
}
|
|
3558
3754
|
}
|
|
3755
|
+
/**
|
|
3756
|
+
* Fire-and-forget: fetch slash commands and MCP tool metadata in parallel.
|
|
3757
|
+
* Both populate caches used later — neither is needed to return configOptions.
|
|
3758
|
+
*/
|
|
3759
|
+
deferBackgroundFetches(tc, q, sessionId, mcpServers) {
|
|
3760
|
+
Promise.all([
|
|
3761
|
+
tc.time("slashCommands", () => getAvailableSlashCommands(q)),
|
|
3762
|
+
tc.time(
|
|
3763
|
+
"mcpMetadata",
|
|
3764
|
+
() => fetchMcpToolMetadata(mcpServers, this.logger)
|
|
3765
|
+
)
|
|
3766
|
+
]).then(([slashCommands]) => {
|
|
3767
|
+
this.sendAvailableCommandsUpdate(sessionId, slashCommands);
|
|
3768
|
+
}).catch((err) => {
|
|
3769
|
+
this.logger.warn("Failed to fetch deferred session data", { err });
|
|
3770
|
+
});
|
|
3771
|
+
}
|
|
3559
3772
|
registerPersistence(sessionId, meta) {
|
|
3560
3773
|
const persistence = meta?.persistence;
|
|
3561
3774
|
if (persistence && this.logWriter) {
|
|
@@ -3843,7 +4056,10 @@ function createClaudeConnection(config) {
|
|
|
3843
4056
|
const agentStream = (0, import_sdk3.ndJsonStream)(agentWritable, streams.agent.readable);
|
|
3844
4057
|
let agent = null;
|
|
3845
4058
|
const agentConnection = new import_sdk3.AgentSideConnection((client) => {
|
|
3846
|
-
agent = new ClaudeAcpAgent(client, logWriter,
|
|
4059
|
+
agent = new ClaudeAcpAgent(client, logWriter, {
|
|
4060
|
+
...config.processCallbacks,
|
|
4061
|
+
debug: config.debug
|
|
4062
|
+
});
|
|
3847
4063
|
logger.info(`Created ${agent.adapterName} agent`);
|
|
3848
4064
|
return agent;
|
|
3849
4065
|
}, agentStream);
|
|
@@ -9226,133 +9442,6 @@ async function getHeadSha(baseDir, options) {
|
|
|
9226
9442
|
var import_promises2 = require("fs/promises");
|
|
9227
9443
|
var import_node_path3 = require("path");
|
|
9228
9444
|
|
|
9229
|
-
// ../shared/dist/index.js
|
|
9230
|
-
var consoleLogger = {
|
|
9231
|
-
info: (_message, _data) => {
|
|
9232
|
-
},
|
|
9233
|
-
debug: (_message, _data) => {
|
|
9234
|
-
},
|
|
9235
|
-
error: (_message, _data) => {
|
|
9236
|
-
},
|
|
9237
|
-
warn: (_message, _data) => {
|
|
9238
|
-
}
|
|
9239
|
-
};
|
|
9240
|
-
var Saga = class {
|
|
9241
|
-
completedSteps = [];
|
|
9242
|
-
currentStepName = "unknown";
|
|
9243
|
-
stepTimings = [];
|
|
9244
|
-
log;
|
|
9245
|
-
constructor(logger) {
|
|
9246
|
-
this.log = logger ?? consoleLogger;
|
|
9247
|
-
}
|
|
9248
|
-
/**
|
|
9249
|
-
* Run the saga with the given input.
|
|
9250
|
-
* Returns a discriminated union result - either success with data or failure with error details.
|
|
9251
|
-
*/
|
|
9252
|
-
async run(input) {
|
|
9253
|
-
this.completedSteps = [];
|
|
9254
|
-
this.currentStepName = "unknown";
|
|
9255
|
-
this.stepTimings = [];
|
|
9256
|
-
const sagaStart = performance.now();
|
|
9257
|
-
this.log.info("Starting saga", { sagaName: this.constructor.name });
|
|
9258
|
-
try {
|
|
9259
|
-
const result = await this.execute(input);
|
|
9260
|
-
const totalDuration = performance.now() - sagaStart;
|
|
9261
|
-
this.log.debug("Saga completed successfully", {
|
|
9262
|
-
sagaName: this.constructor.name,
|
|
9263
|
-
stepsCompleted: this.completedSteps.length,
|
|
9264
|
-
totalDurationMs: Math.round(totalDuration),
|
|
9265
|
-
stepTimings: this.stepTimings
|
|
9266
|
-
});
|
|
9267
|
-
return { success: true, data: result };
|
|
9268
|
-
} catch (error) {
|
|
9269
|
-
this.log.error("Saga failed, initiating rollback", {
|
|
9270
|
-
sagaName: this.constructor.name,
|
|
9271
|
-
failedStep: this.currentStepName,
|
|
9272
|
-
error: error instanceof Error ? error.message : String(error)
|
|
9273
|
-
});
|
|
9274
|
-
await this.rollback();
|
|
9275
|
-
return {
|
|
9276
|
-
success: false,
|
|
9277
|
-
error: error instanceof Error ? error.message : String(error),
|
|
9278
|
-
failedStep: this.currentStepName
|
|
9279
|
-
};
|
|
9280
|
-
}
|
|
9281
|
-
}
|
|
9282
|
-
/**
|
|
9283
|
-
* Execute a step with its rollback action.
|
|
9284
|
-
* If the step succeeds, its rollback action is stored for potential rollback.
|
|
9285
|
-
* The step name is automatically tracked for error reporting.
|
|
9286
|
-
*
|
|
9287
|
-
* @param config - Step configuration with name, execute, and rollback functions
|
|
9288
|
-
* @returns The result of the execute function
|
|
9289
|
-
* @throws Re-throws any error from the execute function (triggers rollback)
|
|
9290
|
-
*/
|
|
9291
|
-
async step(config) {
|
|
9292
|
-
this.currentStepName = config.name;
|
|
9293
|
-
this.log.debug(`Executing step: ${config.name}`);
|
|
9294
|
-
const stepStart = performance.now();
|
|
9295
|
-
const result = await config.execute();
|
|
9296
|
-
const durationMs = Math.round(performance.now() - stepStart);
|
|
9297
|
-
this.stepTimings.push({ name: config.name, durationMs });
|
|
9298
|
-
this.log.debug(`Step completed: ${config.name}`, { durationMs });
|
|
9299
|
-
this.completedSteps.push({
|
|
9300
|
-
name: config.name,
|
|
9301
|
-
rollback: () => config.rollback(result)
|
|
9302
|
-
});
|
|
9303
|
-
return result;
|
|
9304
|
-
}
|
|
9305
|
-
/**
|
|
9306
|
-
* Execute a step that doesn't need rollback.
|
|
9307
|
-
* Useful for read-only operations or operations that are idempotent.
|
|
9308
|
-
* The step name is automatically tracked for error reporting.
|
|
9309
|
-
*
|
|
9310
|
-
* @param name - Step name for logging and error tracking
|
|
9311
|
-
* @param execute - The action to execute
|
|
9312
|
-
* @returns The result of the execute function
|
|
9313
|
-
*/
|
|
9314
|
-
async readOnlyStep(name, execute) {
|
|
9315
|
-
this.currentStepName = name;
|
|
9316
|
-
this.log.debug(`Executing read-only step: ${name}`);
|
|
9317
|
-
const stepStart = performance.now();
|
|
9318
|
-
const result = await execute();
|
|
9319
|
-
const durationMs = Math.round(performance.now() - stepStart);
|
|
9320
|
-
this.stepTimings.push({ name, durationMs });
|
|
9321
|
-
this.log.debug(`Read-only step completed: ${name}`, { durationMs });
|
|
9322
|
-
return result;
|
|
9323
|
-
}
|
|
9324
|
-
/**
|
|
9325
|
-
* Roll back all completed steps in reverse order.
|
|
9326
|
-
* Rollback errors are logged but don't stop the rollback of other steps.
|
|
9327
|
-
*/
|
|
9328
|
-
async rollback() {
|
|
9329
|
-
this.log.info("Rolling back saga", {
|
|
9330
|
-
stepsToRollback: this.completedSteps.length
|
|
9331
|
-
});
|
|
9332
|
-
const stepsReversed = [...this.completedSteps].reverse();
|
|
9333
|
-
for (const step of stepsReversed) {
|
|
9334
|
-
try {
|
|
9335
|
-
this.log.debug(`Rolling back step: ${step.name}`);
|
|
9336
|
-
await step.rollback();
|
|
9337
|
-
this.log.debug(`Step rolled back: ${step.name}`);
|
|
9338
|
-
} catch (error) {
|
|
9339
|
-
this.log.error(`Failed to rollback step: ${step.name}`, {
|
|
9340
|
-
error: error instanceof Error ? error.message : String(error)
|
|
9341
|
-
});
|
|
9342
|
-
}
|
|
9343
|
-
}
|
|
9344
|
-
this.log.info("Rollback completed", {
|
|
9345
|
-
stepsAttempted: this.completedSteps.length
|
|
9346
|
-
});
|
|
9347
|
-
}
|
|
9348
|
-
/**
|
|
9349
|
-
* Get the number of completed steps (useful for testing)
|
|
9350
|
-
*/
|
|
9351
|
-
getCompletedStepCount() {
|
|
9352
|
-
return this.completedSteps.length;
|
|
9353
|
-
}
|
|
9354
|
-
};
|
|
9355
|
-
|
|
9356
9445
|
// ../git/dist/sagas/tree.js
|
|
9357
9446
|
var import_node_fs2 = require("fs");
|
|
9358
9447
|
var fs5 = __toESM(require("fs/promises"), 1);
|