@posthog/agent 2.3.508 → 2.3.513
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.js +234 -110
- package/dist/agent.js.map +1 -1
- package/dist/handoff-checkpoint.js +212 -18
- package/dist/handoff-checkpoint.js.map +1 -1
- package/dist/posthog-api.js +1 -1
- package/dist/posthog-api.js.map +1 -1
- package/dist/server/agent-server.js +463 -145
- package/dist/server/agent-server.js.map +1 -1
- package/dist/server/bin.cjs +445 -127
- package/dist/server/bin.cjs.map +1 -1
- package/package.json +2 -2
- package/src/adapters/claude/claude-agent.ts +10 -0
- package/src/adapters/claude/conversion/sdk-to-acp.ts +67 -6
- package/src/adapters/claude/session/mcp-config.test.ts +112 -0
- package/src/adapters/claude/session/mcp-config.ts +45 -0
- package/src/adapters/claude/session/options.ts +4 -0
- package/src/adapters/claude/types.ts +10 -0
- package/src/utils/partial-json.test.ts +72 -0
- package/src/utils/partial-json.ts +68 -0
package/dist/server/bin.cjs
CHANGED
|
@@ -509,7 +509,7 @@ var require_has_flag = __commonJS({
|
|
|
509
509
|
var require_supports_color = __commonJS({
|
|
510
510
|
"../../node_modules/supports-color/index.js"(exports2, module2) {
|
|
511
511
|
"use strict";
|
|
512
|
-
var
|
|
512
|
+
var os8 = require("os");
|
|
513
513
|
var tty = require("tty");
|
|
514
514
|
var hasFlag = require_has_flag();
|
|
515
515
|
var { env } = process;
|
|
@@ -557,7 +557,7 @@ var require_supports_color = __commonJS({
|
|
|
557
557
|
return min;
|
|
558
558
|
}
|
|
559
559
|
if (process.platform === "win32") {
|
|
560
|
-
const osRelease =
|
|
560
|
+
const osRelease = os8.release().split(".");
|
|
561
561
|
if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
|
|
562
562
|
return Number(osRelease[2]) >= 14931 ? 3 : 2;
|
|
563
563
|
}
|
|
@@ -805,10 +805,10 @@ var require_src2 = __commonJS({
|
|
|
805
805
|
var fs_1 = require("fs");
|
|
806
806
|
var debug_1 = __importDefault(require_src());
|
|
807
807
|
var log = debug_1.default("@kwsites/file-exists");
|
|
808
|
-
function check(
|
|
809
|
-
log(`checking %s`,
|
|
808
|
+
function check(path17, isFile2, isDirectory) {
|
|
809
|
+
log(`checking %s`, path17);
|
|
810
810
|
try {
|
|
811
|
-
const stat4 = fs_1.statSync(
|
|
811
|
+
const stat4 = fs_1.statSync(path17);
|
|
812
812
|
if (stat4.isFile() && isFile2) {
|
|
813
813
|
log(`[OK] path represents a file`);
|
|
814
814
|
return true;
|
|
@@ -828,8 +828,8 @@ var require_src2 = __commonJS({
|
|
|
828
828
|
throw e;
|
|
829
829
|
}
|
|
830
830
|
}
|
|
831
|
-
function exists2(
|
|
832
|
-
return check(
|
|
831
|
+
function exists2(path17, type = exports2.READABLE) {
|
|
832
|
+
return check(path17, (type & exports2.FILE) > 0, (type & exports2.FOLDER) > 0);
|
|
833
833
|
}
|
|
834
834
|
exports2.exists = exists2;
|
|
835
835
|
exports2.FILE = 1;
|
|
@@ -925,11 +925,11 @@ var require_tree_sitter = __commonJS({
|
|
|
925
925
|
throw toThrow;
|
|
926
926
|
};
|
|
927
927
|
var scriptDirectory = "";
|
|
928
|
-
function locateFile(
|
|
928
|
+
function locateFile(path17) {
|
|
929
929
|
if (Module["locateFile"]) {
|
|
930
|
-
return Module["locateFile"](
|
|
930
|
+
return Module["locateFile"](path17, scriptDirectory);
|
|
931
931
|
}
|
|
932
|
-
return scriptDirectory +
|
|
932
|
+
return scriptDirectory + path17;
|
|
933
933
|
}
|
|
934
934
|
var readAsync, readBinary;
|
|
935
935
|
if (ENVIRONMENT_IS_NODE) {
|
|
@@ -3450,8 +3450,8 @@ var require_tree_sitter = __commonJS({
|
|
|
3450
3450
|
} else {
|
|
3451
3451
|
const url = input;
|
|
3452
3452
|
if (typeof process !== "undefined" && process.versions && process.versions.node) {
|
|
3453
|
-
const
|
|
3454
|
-
bytes = Promise.resolve(
|
|
3453
|
+
const fs14 = require("fs");
|
|
3454
|
+
bytes = Promise.resolve(fs14.readFileSync(url));
|
|
3455
3455
|
} else {
|
|
3456
3456
|
bytes = fetch(url).then((response) => response.arrayBuffer().then((buffer) => {
|
|
3457
3457
|
if (response.ok) {
|
|
@@ -3991,8 +3991,8 @@ function pathspec(...paths) {
|
|
|
3991
3991
|
cache.set(key, paths);
|
|
3992
3992
|
return key;
|
|
3993
3993
|
}
|
|
3994
|
-
function isPathSpec(
|
|
3995
|
-
return
|
|
3994
|
+
function isPathSpec(path17) {
|
|
3995
|
+
return path17 instanceof String && cache.has(path17);
|
|
3996
3996
|
}
|
|
3997
3997
|
function toPaths(pathSpec) {
|
|
3998
3998
|
return cache.get(pathSpec) || [];
|
|
@@ -4081,8 +4081,8 @@ function toLinesWithContent(input = "", trimmed2 = true, separator = "\n") {
|
|
|
4081
4081
|
function forEachLineWithContent(input, callback) {
|
|
4082
4082
|
return toLinesWithContent(input, true).map((line) => callback(line));
|
|
4083
4083
|
}
|
|
4084
|
-
function folderExists(
|
|
4085
|
-
return (0, import_file_exists.exists)(
|
|
4084
|
+
function folderExists(path17) {
|
|
4085
|
+
return (0, import_file_exists.exists)(path17, import_file_exists.FOLDER);
|
|
4086
4086
|
}
|
|
4087
4087
|
function append(target, item) {
|
|
4088
4088
|
if (Array.isArray(target)) {
|
|
@@ -4486,8 +4486,8 @@ function checkIsRepoRootTask() {
|
|
|
4486
4486
|
commands,
|
|
4487
4487
|
format: "utf-8",
|
|
4488
4488
|
onError,
|
|
4489
|
-
parser(
|
|
4490
|
-
return /^\.(git)?$/.test(
|
|
4489
|
+
parser(path17) {
|
|
4490
|
+
return /^\.(git)?$/.test(path17.trim());
|
|
4491
4491
|
}
|
|
4492
4492
|
};
|
|
4493
4493
|
}
|
|
@@ -4921,11 +4921,11 @@ function parseGrep(grep) {
|
|
|
4921
4921
|
const paths = /* @__PURE__ */ new Set();
|
|
4922
4922
|
const results = {};
|
|
4923
4923
|
forEachLineWithContent(grep, (input) => {
|
|
4924
|
-
const [
|
|
4925
|
-
paths.add(
|
|
4926
|
-
(results[
|
|
4924
|
+
const [path17, line, preview] = input.split(NULL);
|
|
4925
|
+
paths.add(path17);
|
|
4926
|
+
(results[path17] = results[path17] || []).push({
|
|
4927
4927
|
line: asNumber(line),
|
|
4928
|
-
path:
|
|
4928
|
+
path: path17,
|
|
4929
4929
|
preview
|
|
4930
4930
|
});
|
|
4931
4931
|
});
|
|
@@ -5690,14 +5690,14 @@ var init_hash_object = __esm({
|
|
|
5690
5690
|
init_task();
|
|
5691
5691
|
}
|
|
5692
5692
|
});
|
|
5693
|
-
function parseInit(bare,
|
|
5693
|
+
function parseInit(bare, path17, text2) {
|
|
5694
5694
|
const response = String(text2).trim();
|
|
5695
5695
|
let result;
|
|
5696
5696
|
if (result = initResponseRegex.exec(response)) {
|
|
5697
|
-
return new InitSummary(bare,
|
|
5697
|
+
return new InitSummary(bare, path17, false, result[1]);
|
|
5698
5698
|
}
|
|
5699
5699
|
if (result = reInitResponseRegex.exec(response)) {
|
|
5700
|
-
return new InitSummary(bare,
|
|
5700
|
+
return new InitSummary(bare, path17, true, result[1]);
|
|
5701
5701
|
}
|
|
5702
5702
|
let gitDir = "";
|
|
5703
5703
|
const tokens = response.split(" ");
|
|
@@ -5708,7 +5708,7 @@ function parseInit(bare, path16, text2) {
|
|
|
5708
5708
|
break;
|
|
5709
5709
|
}
|
|
5710
5710
|
}
|
|
5711
|
-
return new InitSummary(bare,
|
|
5711
|
+
return new InitSummary(bare, path17, /^re/i.test(response), gitDir);
|
|
5712
5712
|
}
|
|
5713
5713
|
var InitSummary;
|
|
5714
5714
|
var initResponseRegex;
|
|
@@ -5717,9 +5717,9 @@ var init_InitSummary = __esm({
|
|
|
5717
5717
|
"src/lib/responses/InitSummary.ts"() {
|
|
5718
5718
|
"use strict";
|
|
5719
5719
|
InitSummary = class {
|
|
5720
|
-
constructor(bare,
|
|
5720
|
+
constructor(bare, path17, existing, gitDir) {
|
|
5721
5721
|
this.bare = bare;
|
|
5722
|
-
this.path =
|
|
5722
|
+
this.path = path17;
|
|
5723
5723
|
this.existing = existing;
|
|
5724
5724
|
this.gitDir = gitDir;
|
|
5725
5725
|
}
|
|
@@ -5731,7 +5731,7 @@ var init_InitSummary = __esm({
|
|
|
5731
5731
|
function hasBareCommand(command) {
|
|
5732
5732
|
return command.includes(bareCommand);
|
|
5733
5733
|
}
|
|
5734
|
-
function initTask(bare = false,
|
|
5734
|
+
function initTask(bare = false, path17, customArgs) {
|
|
5735
5735
|
const commands = ["init", ...customArgs];
|
|
5736
5736
|
if (bare && !hasBareCommand(commands)) {
|
|
5737
5737
|
commands.splice(1, 0, bareCommand);
|
|
@@ -5740,7 +5740,7 @@ function initTask(bare = false, path16, customArgs) {
|
|
|
5740
5740
|
commands,
|
|
5741
5741
|
format: "utf-8",
|
|
5742
5742
|
parser(text2) {
|
|
5743
|
-
return parseInit(commands.includes("--bare"),
|
|
5743
|
+
return parseInit(commands.includes("--bare"), path17, text2);
|
|
5744
5744
|
}
|
|
5745
5745
|
};
|
|
5746
5746
|
}
|
|
@@ -6556,12 +6556,12 @@ var init_FileStatusSummary = __esm({
|
|
|
6556
6556
|
"use strict";
|
|
6557
6557
|
fromPathRegex = /^(.+)\0(.+)$/;
|
|
6558
6558
|
FileStatusSummary = class {
|
|
6559
|
-
constructor(
|
|
6560
|
-
this.path =
|
|
6559
|
+
constructor(path17, index, working_dir) {
|
|
6560
|
+
this.path = path17;
|
|
6561
6561
|
this.index = index;
|
|
6562
6562
|
this.working_dir = working_dir;
|
|
6563
6563
|
if (index === "R" || working_dir === "R") {
|
|
6564
|
-
const detail = fromPathRegex.exec(
|
|
6564
|
+
const detail = fromPathRegex.exec(path17) || [null, path17, path17];
|
|
6565
6565
|
this.from = detail[2] || "";
|
|
6566
6566
|
this.path = detail[1] || "";
|
|
6567
6567
|
}
|
|
@@ -6592,14 +6592,14 @@ function splitLine(result, lineStr) {
|
|
|
6592
6592
|
default:
|
|
6593
6593
|
return;
|
|
6594
6594
|
}
|
|
6595
|
-
function data(index, workingDir,
|
|
6595
|
+
function data(index, workingDir, path17) {
|
|
6596
6596
|
const raw = `${index}${workingDir}`;
|
|
6597
6597
|
const handler = parsers6.get(raw);
|
|
6598
6598
|
if (handler) {
|
|
6599
|
-
handler(result,
|
|
6599
|
+
handler(result, path17);
|
|
6600
6600
|
}
|
|
6601
6601
|
if (raw !== "##" && raw !== "!!") {
|
|
6602
|
-
result.files.push(new FileStatusSummary(
|
|
6602
|
+
result.files.push(new FileStatusSummary(path17, index, workingDir));
|
|
6603
6603
|
}
|
|
6604
6604
|
}
|
|
6605
6605
|
}
|
|
@@ -6912,9 +6912,9 @@ var init_simple_git_api = __esm({
|
|
|
6912
6912
|
next
|
|
6913
6913
|
);
|
|
6914
6914
|
}
|
|
6915
|
-
hashObject(
|
|
6915
|
+
hashObject(path17, write) {
|
|
6916
6916
|
return this._runTask(
|
|
6917
|
-
hashObjectTask(
|
|
6917
|
+
hashObjectTask(path17, write === true),
|
|
6918
6918
|
trailingFunctionArgument(arguments)
|
|
6919
6919
|
);
|
|
6920
6920
|
}
|
|
@@ -7267,8 +7267,8 @@ var init_branch = __esm({
|
|
|
7267
7267
|
}
|
|
7268
7268
|
});
|
|
7269
7269
|
function toPath(input) {
|
|
7270
|
-
const
|
|
7271
|
-
return
|
|
7270
|
+
const path17 = input.trim().replace(/^["']|["']$/g, "");
|
|
7271
|
+
return path17 && (0, import_node_path.normalize)(path17);
|
|
7272
7272
|
}
|
|
7273
7273
|
var parseCheckIgnore;
|
|
7274
7274
|
var init_CheckIgnore = __esm({
|
|
@@ -7582,8 +7582,8 @@ __export(sub_module_exports, {
|
|
|
7582
7582
|
subModuleTask: () => subModuleTask,
|
|
7583
7583
|
updateSubModuleTask: () => updateSubModuleTask
|
|
7584
7584
|
});
|
|
7585
|
-
function addSubModuleTask(repo,
|
|
7586
|
-
return subModuleTask(["add", repo,
|
|
7585
|
+
function addSubModuleTask(repo, path17) {
|
|
7586
|
+
return subModuleTask(["add", repo, path17]);
|
|
7587
7587
|
}
|
|
7588
7588
|
function initSubModuleTask(customArgs) {
|
|
7589
7589
|
return subModuleTask(["init", ...customArgs]);
|
|
@@ -7913,8 +7913,8 @@ var require_git = __commonJS2({
|
|
|
7913
7913
|
}
|
|
7914
7914
|
return this._runTask(straightThroughStringTask2(command, this._trimmed), next);
|
|
7915
7915
|
};
|
|
7916
|
-
Git2.prototype.submoduleAdd = function(repo,
|
|
7917
|
-
return this._runTask(addSubModuleTask2(repo,
|
|
7916
|
+
Git2.prototype.submoduleAdd = function(repo, path17, then) {
|
|
7917
|
+
return this._runTask(addSubModuleTask2(repo, path17), trailingFunctionArgument2(arguments));
|
|
7918
7918
|
};
|
|
7919
7919
|
Git2.prototype.submoduleUpdate = function(args2, then) {
|
|
7920
7920
|
return this._runTask(
|
|
@@ -8755,7 +8755,7 @@ var import_zod3 = require("zod");
|
|
|
8755
8755
|
// package.json
|
|
8756
8756
|
var package_default = {
|
|
8757
8757
|
name: "@posthog/agent",
|
|
8758
|
-
version: "2.3.
|
|
8758
|
+
version: "2.3.513",
|
|
8759
8759
|
repository: "https://github.com/PostHog/code",
|
|
8760
8760
|
description: "TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog",
|
|
8761
8761
|
exports: {
|
|
@@ -9191,9 +9191,9 @@ function nodeWritableToWebWritable(nodeStream) {
|
|
|
9191
9191
|
|
|
9192
9192
|
// src/adapters/claude/claude-agent.ts
|
|
9193
9193
|
var import_node_crypto = require("crypto");
|
|
9194
|
-
var
|
|
9195
|
-
var
|
|
9196
|
-
var
|
|
9194
|
+
var fs9 = __toESM(require("fs"), 1);
|
|
9195
|
+
var os5 = __toESM(require("os"), 1);
|
|
9196
|
+
var path11 = __toESM(require("path"), 1);
|
|
9197
9197
|
var import_sdk2 = require("@agentclientprotocol/sdk");
|
|
9198
9198
|
var import_claude_agent_sdk = require("@anthropic-ai/claude-agent-sdk");
|
|
9199
9199
|
var import_uuid = require("uuid");
|
|
@@ -13600,8 +13600,8 @@ var ToolContentBuilder = class {
|
|
|
13600
13600
|
this.items.push({ type: "content", content: image(data, mimeType, uri) });
|
|
13601
13601
|
return this;
|
|
13602
13602
|
}
|
|
13603
|
-
diff(
|
|
13604
|
-
this.items.push({ type: "diff", path:
|
|
13603
|
+
diff(path17, oldText, newText) {
|
|
13604
|
+
this.items.push({ type: "diff", path: path17, oldText, newText });
|
|
13605
13605
|
return this;
|
|
13606
13606
|
}
|
|
13607
13607
|
build() {
|
|
@@ -13612,6 +13612,54 @@ function toolContent() {
|
|
|
13612
13612
|
return new ToolContentBuilder();
|
|
13613
13613
|
}
|
|
13614
13614
|
|
|
13615
|
+
// src/utils/partial-json.ts
|
|
13616
|
+
function tryParsePartialJson(s) {
|
|
13617
|
+
const trimmed2 = s.trim();
|
|
13618
|
+
if (!trimmed2) return null;
|
|
13619
|
+
try {
|
|
13620
|
+
return JSON.parse(trimmed2);
|
|
13621
|
+
} catch {
|
|
13622
|
+
}
|
|
13623
|
+
const closers = [];
|
|
13624
|
+
let inString = false;
|
|
13625
|
+
let escaped = false;
|
|
13626
|
+
for (let i2 = 0; i2 < trimmed2.length; i2++) {
|
|
13627
|
+
const ch = trimmed2[i2];
|
|
13628
|
+
if (inString) {
|
|
13629
|
+
if (escaped) {
|
|
13630
|
+
escaped = false;
|
|
13631
|
+
} else if (ch === "\\") {
|
|
13632
|
+
escaped = true;
|
|
13633
|
+
} else if (ch === '"') {
|
|
13634
|
+
inString = false;
|
|
13635
|
+
}
|
|
13636
|
+
continue;
|
|
13637
|
+
}
|
|
13638
|
+
if (ch === '"') inString = true;
|
|
13639
|
+
else if (ch === "{") closers.push("}");
|
|
13640
|
+
else if (ch === "[") closers.push("]");
|
|
13641
|
+
else if (ch === "}" || ch === "]") closers.pop();
|
|
13642
|
+
}
|
|
13643
|
+
const closeBrackets = (str) => {
|
|
13644
|
+
let out2 = str;
|
|
13645
|
+
for (let i2 = closers.length - 1; i2 >= 0; i2--) out2 += closers[i2];
|
|
13646
|
+
return out2;
|
|
13647
|
+
};
|
|
13648
|
+
const candidates = [];
|
|
13649
|
+
const closedString = inString ? `${trimmed2}"` : trimmed2;
|
|
13650
|
+
candidates.push(closeBrackets(closedString));
|
|
13651
|
+
let stripped = closedString.replace(/[,:]\s*$/, "");
|
|
13652
|
+
stripped = stripped.replace(/,?\s*"[^"]*"\s*:?\s*$/, "");
|
|
13653
|
+
candidates.push(closeBrackets(stripped));
|
|
13654
|
+
for (const candidate of candidates) {
|
|
13655
|
+
try {
|
|
13656
|
+
return JSON.parse(candidate);
|
|
13657
|
+
} catch {
|
|
13658
|
+
}
|
|
13659
|
+
}
|
|
13660
|
+
return null;
|
|
13661
|
+
}
|
|
13662
|
+
|
|
13615
13663
|
// src/adapters/claude/permissions/posthog-exec-gate.ts
|
|
13616
13664
|
var POSTHOG_EXEC_TOOL_RE = /^mcp__posthog(?:_[^_]+)*__exec$/;
|
|
13617
13665
|
var POSTHOG_CALL_COMMAND_RE = /^\s*call\s+(?:--json\s+)?([a-zA-Z0-9_-]+)/;
|
|
@@ -14778,12 +14826,19 @@ function toAcpNotifications(content, role, sessionId, toolUseCache, fileContentC
|
|
|
14778
14826
|
}
|
|
14779
14827
|
return output;
|
|
14780
14828
|
}
|
|
14781
|
-
function streamEventToAcpNotifications(message, sessionId, toolUseCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache) {
|
|
14829
|
+
function streamEventToAcpNotifications(message, sessionId, toolUseCache, toolUseStreamCache, fileContentCache, client, logger, parentToolCallId, registerHooks, supportsTerminalOutput, cwd, enrichedReadCache) {
|
|
14782
14830
|
const event = message.event;
|
|
14783
14831
|
switch (event.type) {
|
|
14784
|
-
case "content_block_start":
|
|
14832
|
+
case "content_block_start": {
|
|
14833
|
+
const block = event.content_block;
|
|
14834
|
+
if (block.type === "tool_use" || block.type === "mcp_tool_use") {
|
|
14835
|
+
toolUseStreamCache.set(event.index, {
|
|
14836
|
+
toolUseId: block.id,
|
|
14837
|
+
partialJson: ""
|
|
14838
|
+
});
|
|
14839
|
+
}
|
|
14785
14840
|
return toAcpNotifications(
|
|
14786
|
-
[
|
|
14841
|
+
[block],
|
|
14787
14842
|
"assistant",
|
|
14788
14843
|
sessionId,
|
|
14789
14844
|
toolUseCache,
|
|
@@ -14797,7 +14852,16 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, fileCon
|
|
|
14797
14852
|
void 0,
|
|
14798
14853
|
enrichedReadCache
|
|
14799
14854
|
);
|
|
14800
|
-
|
|
14855
|
+
}
|
|
14856
|
+
case "content_block_delta": {
|
|
14857
|
+
if (event.delta.type === "input_json_delta") {
|
|
14858
|
+
return inputJsonDeltaToAcpNotifications(
|
|
14859
|
+
event.index,
|
|
14860
|
+
event.delta.partial_json,
|
|
14861
|
+
sessionId,
|
|
14862
|
+
toolUseStreamCache
|
|
14863
|
+
);
|
|
14864
|
+
}
|
|
14801
14865
|
return toAcpNotifications(
|
|
14802
14866
|
[event.delta],
|
|
14803
14867
|
"assistant",
|
|
@@ -14813,16 +14877,36 @@ function streamEventToAcpNotifications(message, sessionId, toolUseCache, fileCon
|
|
|
14813
14877
|
void 0,
|
|
14814
14878
|
enrichedReadCache
|
|
14815
14879
|
);
|
|
14880
|
+
}
|
|
14881
|
+
case "content_block_stop":
|
|
14882
|
+
toolUseStreamCache.delete(event.index);
|
|
14883
|
+
return [];
|
|
14816
14884
|
case "message_start":
|
|
14817
14885
|
case "message_delta":
|
|
14818
14886
|
case "message_stop":
|
|
14819
|
-
case "content_block_stop":
|
|
14820
14887
|
return [];
|
|
14821
14888
|
default:
|
|
14822
14889
|
unreachable(event, logger);
|
|
14823
14890
|
return [];
|
|
14824
14891
|
}
|
|
14825
14892
|
}
|
|
14893
|
+
function inputJsonDeltaToAcpNotifications(index, partialJson, sessionId, toolUseStreamCache) {
|
|
14894
|
+
const entry = toolUseStreamCache.get(index);
|
|
14895
|
+
if (!entry) return [];
|
|
14896
|
+
entry.partialJson += partialJson;
|
|
14897
|
+
const parsed = tryParsePartialJson(entry.partialJson);
|
|
14898
|
+
if (!parsed || typeof parsed !== "object") return [];
|
|
14899
|
+
return [
|
|
14900
|
+
{
|
|
14901
|
+
sessionId,
|
|
14902
|
+
update: {
|
|
14903
|
+
sessionUpdate: "tool_call_update",
|
|
14904
|
+
toolCallId: entry.toolUseId,
|
|
14905
|
+
rawInput: parsed
|
|
14906
|
+
}
|
|
14907
|
+
}
|
|
14908
|
+
];
|
|
14909
|
+
}
|
|
14826
14910
|
async function handleSystemMessage(message, context) {
|
|
14827
14911
|
const { session, sessionId, client, logger } = context;
|
|
14828
14912
|
switch (message.subtype) {
|
|
@@ -14966,12 +15050,20 @@ function extractUsageFromResult(message) {
|
|
|
14966
15050
|
};
|
|
14967
15051
|
}
|
|
14968
15052
|
async function handleStreamEvent(message, context) {
|
|
14969
|
-
const {
|
|
15053
|
+
const {
|
|
15054
|
+
sessionId,
|
|
15055
|
+
client,
|
|
15056
|
+
toolUseCache,
|
|
15057
|
+
toolUseStreamCache,
|
|
15058
|
+
fileContentCache,
|
|
15059
|
+
logger
|
|
15060
|
+
} = context;
|
|
14970
15061
|
const parentToolCallId = message.parent_tool_use_id ?? void 0;
|
|
14971
15062
|
for (const notification of streamEventToAcpNotifications(
|
|
14972
15063
|
message,
|
|
14973
15064
|
sessionId,
|
|
14974
15065
|
toolUseCache,
|
|
15066
|
+
toolUseStreamCache,
|
|
14975
15067
|
fileContentCache,
|
|
14976
15068
|
client,
|
|
14977
15069
|
logger,
|
|
@@ -15884,6 +15976,31 @@ function getAvailableSlashCommands(commands) {
|
|
|
15884
15976
|
}
|
|
15885
15977
|
|
|
15886
15978
|
// src/adapters/claude/session/mcp-config.ts
|
|
15979
|
+
var fs6 = __toESM(require("fs"), 1);
|
|
15980
|
+
var os2 = __toESM(require("os"), 1);
|
|
15981
|
+
var path8 = __toESM(require("path"), 1);
|
|
15982
|
+
function loadUserClaudeJsonMcpServers(cwd, logger, homeDir = os2.homedir()) {
|
|
15983
|
+
const claudeJsonPath = path8.join(homeDir, ".claude.json");
|
|
15984
|
+
let raw;
|
|
15985
|
+
try {
|
|
15986
|
+
raw = fs6.readFileSync(claudeJsonPath, "utf8");
|
|
15987
|
+
} catch {
|
|
15988
|
+
return {};
|
|
15989
|
+
}
|
|
15990
|
+
let cfg;
|
|
15991
|
+
try {
|
|
15992
|
+
cfg = JSON.parse(raw);
|
|
15993
|
+
} catch (err2) {
|
|
15994
|
+
logger?.warn("Failed to parse ~/.claude.json", {
|
|
15995
|
+
error: err2 instanceof Error ? err2.message : String(err2)
|
|
15996
|
+
});
|
|
15997
|
+
return {};
|
|
15998
|
+
}
|
|
15999
|
+
const topLevel = cfg.mcpServers && typeof cfg.mcpServers === "object" ? cfg.mcpServers : {};
|
|
16000
|
+
const project = cfg.projects?.[cwd];
|
|
16001
|
+
const projectScoped = project?.mcpServers && typeof project.mcpServers === "object" ? project.mcpServers : {};
|
|
16002
|
+
return { ...topLevel, ...projectScoped };
|
|
16003
|
+
}
|
|
15887
16004
|
function parseMcpServers(params) {
|
|
15888
16005
|
const mcpServers = {};
|
|
15889
16006
|
if (!Array.isArray(params.mcpServers)) {
|
|
@@ -15910,9 +16027,9 @@ function parseMcpServers(params) {
|
|
|
15910
16027
|
|
|
15911
16028
|
// src/adapters/claude/session/options.ts
|
|
15912
16029
|
var import_node_child_process2 = require("child_process");
|
|
15913
|
-
var
|
|
15914
|
-
var
|
|
15915
|
-
var
|
|
16030
|
+
var fs7 = __toESM(require("fs"), 1);
|
|
16031
|
+
var os3 = __toESM(require("os"), 1);
|
|
16032
|
+
var path9 = __toESM(require("path"), 1);
|
|
15916
16033
|
|
|
15917
16034
|
// src/adapters/claude/session/instructions.ts
|
|
15918
16035
|
var BRANCH_NAMING = `
|
|
@@ -15963,8 +16080,9 @@ function buildSystemPrompt(customPrompt) {
|
|
|
15963
16080
|
}
|
|
15964
16081
|
return defaultPrompt;
|
|
15965
16082
|
}
|
|
15966
|
-
function buildMcpServers(userServers, acpServers) {
|
|
16083
|
+
function buildMcpServers(userServers, acpServers, projectScopedServers) {
|
|
15967
16084
|
return {
|
|
16085
|
+
...projectScopedServers,
|
|
15968
16086
|
...userServers || {},
|
|
15969
16087
|
...acpServers
|
|
15970
16088
|
};
|
|
@@ -16113,12 +16231,12 @@ function buildSpawnWrapper(sessionId, onProcessSpawned, onProcessExited, logger)
|
|
|
16113
16231
|
};
|
|
16114
16232
|
}
|
|
16115
16233
|
function ensureLocalSettings(cwd) {
|
|
16116
|
-
const claudeDir =
|
|
16117
|
-
const localSettingsPath =
|
|
16234
|
+
const claudeDir = path9.join(cwd, ".claude");
|
|
16235
|
+
const localSettingsPath = path9.join(claudeDir, "settings.local.json");
|
|
16118
16236
|
try {
|
|
16119
|
-
if (!
|
|
16120
|
-
|
|
16121
|
-
|
|
16237
|
+
if (!fs7.existsSync(localSettingsPath)) {
|
|
16238
|
+
fs7.mkdirSync(claudeDir, { recursive: true });
|
|
16239
|
+
fs7.writeFileSync(localSettingsPath, "{}\n", { flag: "wx" });
|
|
16122
16240
|
}
|
|
16123
16241
|
} catch {
|
|
16124
16242
|
}
|
|
@@ -16148,7 +16266,8 @@ function buildSessionOptions(params) {
|
|
|
16148
16266
|
},
|
|
16149
16267
|
mcpServers: buildMcpServers(
|
|
16150
16268
|
params.userProvidedOptions?.mcpServers,
|
|
16151
|
-
params.mcpServers
|
|
16269
|
+
params.mcpServers,
|
|
16270
|
+
loadUserClaudeJsonMcpServers(params.cwd, params.logger)
|
|
16152
16271
|
),
|
|
16153
16272
|
env: buildEnvironment(),
|
|
16154
16273
|
hooks: buildHooks(
|
|
@@ -16193,18 +16312,18 @@ function buildSessionOptions(params) {
|
|
|
16193
16312
|
return options;
|
|
16194
16313
|
}
|
|
16195
16314
|
function clearStatsigCache() {
|
|
16196
|
-
const statsigPath =
|
|
16197
|
-
process.env.CLAUDE_CONFIG_DIR ||
|
|
16315
|
+
const statsigPath = path9.join(
|
|
16316
|
+
process.env.CLAUDE_CONFIG_DIR || path9.join(os3.homedir(), ".claude"),
|
|
16198
16317
|
"statsig"
|
|
16199
16318
|
);
|
|
16200
|
-
|
|
16319
|
+
fs7.rm(statsigPath, { recursive: true, force: true }, () => {
|
|
16201
16320
|
});
|
|
16202
16321
|
}
|
|
16203
16322
|
|
|
16204
16323
|
// src/adapters/claude/session/settings.ts
|
|
16205
|
-
var
|
|
16206
|
-
var
|
|
16207
|
-
var
|
|
16324
|
+
var fs8 = __toESM(require("fs"), 1);
|
|
16325
|
+
var os4 = __toESM(require("os"), 1);
|
|
16326
|
+
var path10 = __toESM(require("path"), 1);
|
|
16208
16327
|
var import_minimatch = require("minimatch");
|
|
16209
16328
|
|
|
16210
16329
|
// src/utils/async-mutex.ts
|
|
@@ -16285,13 +16404,13 @@ function parseRule(rule) {
|
|
|
16285
16404
|
function normalizePath(filePath, cwd) {
|
|
16286
16405
|
let resolved = filePath;
|
|
16287
16406
|
if (resolved.startsWith("~/")) {
|
|
16288
|
-
resolved =
|
|
16407
|
+
resolved = path10.join(os4.homedir(), resolved.slice(2));
|
|
16289
16408
|
} else if (resolved.startsWith("./")) {
|
|
16290
|
-
resolved =
|
|
16291
|
-
} else if (!
|
|
16292
|
-
resolved =
|
|
16409
|
+
resolved = path10.join(cwd, resolved.slice(2));
|
|
16410
|
+
} else if (!path10.isAbsolute(resolved)) {
|
|
16411
|
+
resolved = path10.join(cwd, resolved);
|
|
16293
16412
|
}
|
|
16294
|
-
return
|
|
16413
|
+
return path10.normalize(resolved).replace(/\\/g, "/");
|
|
16295
16414
|
}
|
|
16296
16415
|
function matchesGlob(pattern, filePath, cwd) {
|
|
16297
16416
|
const normalizedPattern = normalizePath(pattern, cwd);
|
|
@@ -16338,11 +16457,11 @@ function formatRule(rule) {
|
|
|
16338
16457
|
}
|
|
16339
16458
|
async function writeFileAtomic(filePath, data) {
|
|
16340
16459
|
const tmpPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
|
|
16341
|
-
await
|
|
16460
|
+
await fs8.promises.writeFile(tmpPath, data);
|
|
16342
16461
|
try {
|
|
16343
|
-
await
|
|
16462
|
+
await fs8.promises.rename(tmpPath, filePath);
|
|
16344
16463
|
} catch (error) {
|
|
16345
|
-
await
|
|
16464
|
+
await fs8.promises.rm(tmpPath, { force: true });
|
|
16346
16465
|
throw error;
|
|
16347
16466
|
}
|
|
16348
16467
|
}
|
|
@@ -16351,7 +16470,7 @@ async function loadSettingsFile(filePath) {
|
|
|
16351
16470
|
return {};
|
|
16352
16471
|
}
|
|
16353
16472
|
try {
|
|
16354
|
-
const content = await
|
|
16473
|
+
const content = await fs8.promises.readFile(filePath, "utf-8");
|
|
16355
16474
|
return JSON.parse(content);
|
|
16356
16475
|
} catch (error) {
|
|
16357
16476
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -16366,7 +16485,7 @@ async function loadSettingsFile(filePath) {
|
|
|
16366
16485
|
}
|
|
16367
16486
|
async function readSettingsFileForUpdate(filePath) {
|
|
16368
16487
|
try {
|
|
16369
|
-
const content = await
|
|
16488
|
+
const content = await fs8.promises.readFile(filePath, "utf-8");
|
|
16370
16489
|
return JSON.parse(content);
|
|
16371
16490
|
} catch (error) {
|
|
16372
16491
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
@@ -16412,11 +16531,11 @@ var SettingsManager = class {
|
|
|
16412
16531
|
return this.initPromise;
|
|
16413
16532
|
}
|
|
16414
16533
|
getUserSettingsPath() {
|
|
16415
|
-
const configDir = process.env.CLAUDE_CONFIG_DIR ||
|
|
16416
|
-
return
|
|
16534
|
+
const configDir = process.env.CLAUDE_CONFIG_DIR || path10.join(os4.homedir(), ".claude");
|
|
16535
|
+
return path10.join(configDir, "settings.json");
|
|
16417
16536
|
}
|
|
16418
16537
|
getProjectSettingsPath() {
|
|
16419
|
-
return
|
|
16538
|
+
return path10.join(this.cwd, ".claude", "settings.json");
|
|
16420
16539
|
}
|
|
16421
16540
|
/**
|
|
16422
16541
|
* Local settings are anchored to the primary worktree so every worktree of
|
|
@@ -16424,7 +16543,7 @@ var SettingsManager = class {
|
|
|
16424
16543
|
* avoids re-prompting for the same permission in every worktree.
|
|
16425
16544
|
*/
|
|
16426
16545
|
getLocalSettingsPath() {
|
|
16427
|
-
return
|
|
16546
|
+
return path10.join(this.repoRoot, ".claude", "settings.local.json");
|
|
16428
16547
|
}
|
|
16429
16548
|
async loadAllSettings() {
|
|
16430
16549
|
this.repoRoot = await resolveMainRepoPath(this.cwd);
|
|
@@ -16551,7 +16670,7 @@ var SettingsManager = class {
|
|
|
16551
16670
|
}
|
|
16552
16671
|
permissions.allow = Array.from(current2);
|
|
16553
16672
|
const next = { ...existing, permissions };
|
|
16554
|
-
await
|
|
16673
|
+
await fs8.promises.mkdir(path10.dirname(filePath), { recursive: true });
|
|
16555
16674
|
await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
|
|
16556
16675
|
`);
|
|
16557
16676
|
this.localSettings = next;
|
|
@@ -16584,7 +16703,7 @@ var SettingsManager = class {
|
|
|
16584
16703
|
...existing,
|
|
16585
16704
|
posthogApprovedExecTools: Array.from(current2)
|
|
16586
16705
|
};
|
|
16587
|
-
await
|
|
16706
|
+
await fs8.promises.mkdir(path10.dirname(filePath), { recursive: true });
|
|
16588
16707
|
await writeFileAtomic(filePath, `${JSON.stringify(next, null, 2)}
|
|
16589
16708
|
`);
|
|
16590
16709
|
this.localSettings = next;
|
|
@@ -16627,6 +16746,7 @@ function shouldEmitRawMessage(config, message) {
|
|
|
16627
16746
|
var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
16628
16747
|
adapterName = "claude";
|
|
16629
16748
|
toolUseCache;
|
|
16749
|
+
toolUseStreamCache;
|
|
16630
16750
|
backgroundTerminals = {};
|
|
16631
16751
|
clientCapabilities;
|
|
16632
16752
|
options;
|
|
@@ -16636,6 +16756,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
16636
16756
|
super(client);
|
|
16637
16757
|
this.options = options;
|
|
16638
16758
|
this.toolUseCache = {};
|
|
16759
|
+
this.toolUseStreamCache = /* @__PURE__ */ new Map();
|
|
16639
16760
|
this.logger = new Logger({ debug: true, prefix: "[ClaudeAcpAgent]" });
|
|
16640
16761
|
this.enrichment = createEnrichment(options?.posthogApiConfig, this.logger);
|
|
16641
16762
|
}
|
|
@@ -16688,7 +16809,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
16688
16809
|
};
|
|
16689
16810
|
}
|
|
16690
16811
|
async newSession(params) {
|
|
16691
|
-
if (
|
|
16812
|
+
if (fs9.existsSync(path11.resolve(os5.homedir(), ".claude.json.backup")) && !fs9.existsSync(path11.resolve(os5.homedir(), ".claude.json"))) {
|
|
16692
16813
|
throw import_sdk2.RequestError.authRequired();
|
|
16693
16814
|
}
|
|
16694
16815
|
const response = await this.createSession(params, {
|
|
@@ -16830,6 +16951,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
16830
16951
|
sessionId: params.sessionId,
|
|
16831
16952
|
client: this.client,
|
|
16832
16953
|
toolUseCache: this.toolUseCache,
|
|
16954
|
+
toolUseStreamCache: this.toolUseStreamCache,
|
|
16833
16955
|
fileContentCache: this.fileContentCache,
|
|
16834
16956
|
enrichedReadCache: this.enrichedReadCache,
|
|
16835
16957
|
logger: this.logger,
|
|
@@ -17082,6 +17204,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
17082
17204
|
}
|
|
17083
17205
|
throw error;
|
|
17084
17206
|
} finally {
|
|
17207
|
+
this.toolUseStreamCache.clear();
|
|
17085
17208
|
if (!handedOff) {
|
|
17086
17209
|
this.session.promptRunning = false;
|
|
17087
17210
|
for (const [key, pending] of this.session.pendingMessages) {
|
|
@@ -17656,6 +17779,7 @@ var ClaudeAcpAgent = class extends BaseAcpAgent {
|
|
|
17656
17779
|
sessionId,
|
|
17657
17780
|
client: this.client,
|
|
17658
17781
|
toolUseCache: this.toolUseCache,
|
|
17782
|
+
toolUseStreamCache: this.toolUseStreamCache,
|
|
17659
17783
|
fileContentCache: this.fileContentCache,
|
|
17660
17784
|
enrichedReadCache: this.enrichedReadCache,
|
|
17661
17785
|
logger: this.logger,
|
|
@@ -17890,9 +18014,9 @@ function resetUsage(state) {
|
|
|
17890
18014
|
}
|
|
17891
18015
|
|
|
17892
18016
|
// src/adapters/codex/settings.ts
|
|
17893
|
-
var
|
|
17894
|
-
var
|
|
17895
|
-
var
|
|
18017
|
+
var fs10 = __toESM(require("fs"), 1);
|
|
18018
|
+
var os6 = __toESM(require("os"), 1);
|
|
18019
|
+
var path12 = __toESM(require("path"), 1);
|
|
17896
18020
|
var CodexSettingsManager = class {
|
|
17897
18021
|
cwd;
|
|
17898
18022
|
settings = { mcpServerNames: [] };
|
|
@@ -17903,12 +18027,12 @@ var CodexSettingsManager = class {
|
|
|
17903
18027
|
async initialize() {
|
|
17904
18028
|
}
|
|
17905
18029
|
getConfigPath() {
|
|
17906
|
-
return
|
|
18030
|
+
return path12.join(os6.homedir(), ".codex", "config.toml");
|
|
17907
18031
|
}
|
|
17908
18032
|
loadSettings() {
|
|
17909
18033
|
const configPath = this.getConfigPath();
|
|
17910
18034
|
try {
|
|
17911
|
-
const content =
|
|
18035
|
+
const content = fs10.readFileSync(configPath, "utf-8");
|
|
17912
18036
|
this.settings = parseCodexToml(content, this.cwd);
|
|
17913
18037
|
} catch {
|
|
17914
18038
|
this.settings = { mcpServerNames: [] };
|
|
@@ -18689,8 +18813,8 @@ var import_node_path5 = __toESM(require("path"), 1);
|
|
|
18689
18813
|
|
|
18690
18814
|
// ../git/dist/sagas/checkpoint.js
|
|
18691
18815
|
var import_node_crypto2 = require("crypto");
|
|
18692
|
-
var
|
|
18693
|
-
var
|
|
18816
|
+
var fs11 = __toESM(require("fs/promises"), 1);
|
|
18817
|
+
var path13 = __toESM(require("path"), 1);
|
|
18694
18818
|
|
|
18695
18819
|
// ../shared/dist/index.js
|
|
18696
18820
|
var CLOUD_PROMPT_PREFIX = "__twig_cloud_prompt_v1__:";
|
|
@@ -18963,12 +19087,12 @@ async function getGitBusyState(git) {
|
|
|
18963
19087
|
const toplevel = (await git.raw(["rev-parse", "--show-toplevel"])).trim();
|
|
18964
19088
|
const resolveGitPath = async (gitPath) => {
|
|
18965
19089
|
const relative = (await git.raw(["rev-parse", "--git-path", gitPath])).trim();
|
|
18966
|
-
return
|
|
19090
|
+
return path13.isAbsolute(relative) ? relative : path13.resolve(toplevel, relative);
|
|
18967
19091
|
};
|
|
18968
19092
|
const pathExists = async (gitPath) => {
|
|
18969
19093
|
const resolved = await resolveGitPath(gitPath);
|
|
18970
19094
|
try {
|
|
18971
|
-
await
|
|
19095
|
+
await fs11.access(resolved);
|
|
18972
19096
|
return true;
|
|
18973
19097
|
} catch {
|
|
18974
19098
|
return false;
|
|
@@ -18977,7 +19101,7 @@ async function getGitBusyState(git) {
|
|
|
18977
19101
|
const dirExists = async (gitPath) => {
|
|
18978
19102
|
const resolved = await resolveGitPath(gitPath);
|
|
18979
19103
|
try {
|
|
18980
|
-
const stat4 = await
|
|
19104
|
+
const stat4 = await fs11.stat(resolved);
|
|
18981
19105
|
return stat4.isDirectory();
|
|
18982
19106
|
} catch {
|
|
18983
19107
|
return false;
|
|
@@ -18997,6 +19121,7 @@ async function getGitBusyState(git) {
|
|
|
18997
19121
|
}
|
|
18998
19122
|
return { busy: false };
|
|
18999
19123
|
}
|
|
19124
|
+
var MAX_WORKTREE_FILE_BYTES = 1024 * 1024;
|
|
19000
19125
|
async function createWorktreeTree(git, baseDir, head) {
|
|
19001
19126
|
const { tempGit, tempIndexPath } = await createTempIndexGit(git, baseDir, "checkpoint-worktree");
|
|
19002
19127
|
try {
|
|
@@ -19006,13 +19131,85 @@ async function createWorktreeTree(git, baseDir, head) {
|
|
|
19006
19131
|
await tempGit.raw(["read-tree", "--empty"]);
|
|
19007
19132
|
}
|
|
19008
19133
|
await tempGit.raw(["add", "-A", "--", "."]);
|
|
19134
|
+
await reconcileLargeBlobs(tempGit, head, MAX_WORKTREE_FILE_BYTES);
|
|
19009
19135
|
const treeHash = await tempGit.raw(["write-tree"]);
|
|
19010
19136
|
return treeHash.trim();
|
|
19011
19137
|
} finally {
|
|
19012
|
-
await
|
|
19138
|
+
await fs11.rm(tempIndexPath, { force: true }).catch(() => {
|
|
19013
19139
|
});
|
|
19014
19140
|
}
|
|
19015
19141
|
}
|
|
19142
|
+
async function reconcileLargeBlobs(tempGit, head, maxBytes) {
|
|
19143
|
+
const intermediateTree = (await tempGit.raw(["write-tree"])).trim();
|
|
19144
|
+
const largePaths = await listLargeBlobPaths(tempGit, intermediateTree, maxBytes);
|
|
19145
|
+
if (largePaths.length === 0)
|
|
19146
|
+
return;
|
|
19147
|
+
const headEntries = head ? await readHeadBlobEntries(tempGit, head, largePaths) : /* @__PURE__ */ new Map();
|
|
19148
|
+
for (const filePath of largePaths) {
|
|
19149
|
+
const headEntry = headEntries.get(filePath);
|
|
19150
|
+
if (headEntry) {
|
|
19151
|
+
await tempGit.raw([
|
|
19152
|
+
"update-index",
|
|
19153
|
+
"--cacheinfo",
|
|
19154
|
+
`${headEntry.mode},${headEntry.hash},${filePath}`
|
|
19155
|
+
]);
|
|
19156
|
+
} else {
|
|
19157
|
+
await tempGit.raw(["update-index", "--force-remove", filePath]).catch(() => {
|
|
19158
|
+
});
|
|
19159
|
+
}
|
|
19160
|
+
}
|
|
19161
|
+
}
|
|
19162
|
+
async function listLargeBlobPaths(tempGit, tree, maxBytes) {
|
|
19163
|
+
const output = await tempGit.raw(["ls-tree", "-r", "-l", tree]);
|
|
19164
|
+
const result = [];
|
|
19165
|
+
for (const line of output.split("\n")) {
|
|
19166
|
+
if (!line)
|
|
19167
|
+
continue;
|
|
19168
|
+
const tabIndex = line.indexOf(" ");
|
|
19169
|
+
if (tabIndex < 0)
|
|
19170
|
+
continue;
|
|
19171
|
+
const meta = line.slice(0, tabIndex);
|
|
19172
|
+
const filePath = line.slice(tabIndex + 1);
|
|
19173
|
+
const parts2 = meta.split(/\s+/);
|
|
19174
|
+
if (parts2.length < 4)
|
|
19175
|
+
continue;
|
|
19176
|
+
const [, type, , sizeStr] = parts2;
|
|
19177
|
+
if (type !== "blob")
|
|
19178
|
+
continue;
|
|
19179
|
+
if (sizeStr === "-")
|
|
19180
|
+
continue;
|
|
19181
|
+
const size = Number.parseInt(sizeStr, 10);
|
|
19182
|
+
if (Number.isFinite(size) && size > maxBytes) {
|
|
19183
|
+
result.push(filePath);
|
|
19184
|
+
}
|
|
19185
|
+
}
|
|
19186
|
+
return result;
|
|
19187
|
+
}
|
|
19188
|
+
async function readHeadBlobEntries(tempGit, head, paths) {
|
|
19189
|
+
const result = /* @__PURE__ */ new Map();
|
|
19190
|
+
const CHUNK_SIZE = 100;
|
|
19191
|
+
for (let i2 = 0; i2 < paths.length; i2 += CHUNK_SIZE) {
|
|
19192
|
+
const chunk = paths.slice(i2, i2 + CHUNK_SIZE);
|
|
19193
|
+
const output = await tempGit.raw(["ls-tree", "-r", head, "--", ...chunk]).catch(() => "");
|
|
19194
|
+
for (const line of output.split("\n")) {
|
|
19195
|
+
if (!line)
|
|
19196
|
+
continue;
|
|
19197
|
+
const tabIndex = line.indexOf(" ");
|
|
19198
|
+
if (tabIndex < 0)
|
|
19199
|
+
continue;
|
|
19200
|
+
const meta = line.slice(0, tabIndex);
|
|
19201
|
+
const filePath = line.slice(tabIndex + 1);
|
|
19202
|
+
const parts2 = meta.split(/\s+/);
|
|
19203
|
+
if (parts2.length < 3)
|
|
19204
|
+
continue;
|
|
19205
|
+
const [mode, type, hash] = parts2;
|
|
19206
|
+
if (type !== "blob")
|
|
19207
|
+
continue;
|
|
19208
|
+
result.set(filePath, { mode, hash });
|
|
19209
|
+
}
|
|
19210
|
+
}
|
|
19211
|
+
return result;
|
|
19212
|
+
}
|
|
19016
19213
|
async function createMetaTree(git, baseDir, indexTree, worktreeTree) {
|
|
19017
19214
|
const { tempGit, tempIndexPath } = await createTempIndexGit(git, baseDir, "checkpoint-meta");
|
|
19018
19215
|
try {
|
|
@@ -19036,7 +19233,7 @@ async function createMetaTree(git, baseDir, indexTree, worktreeTree) {
|
|
|
19036
19233
|
const metaTree = await tempGit.raw(["write-tree"]);
|
|
19037
19234
|
return metaTree.trim();
|
|
19038
19235
|
} finally {
|
|
19039
|
-
await
|
|
19236
|
+
await fs11.rm(tempIndexPath, { force: true }).catch(() => {
|
|
19040
19237
|
});
|
|
19041
19238
|
}
|
|
19042
19239
|
}
|
|
@@ -19053,12 +19250,12 @@ function formatCheckpointMessage(meta) {
|
|
|
19053
19250
|
async function getGitCommonDir(git, baseDir) {
|
|
19054
19251
|
const raw = await git.raw(["rev-parse", "--git-common-dir"]);
|
|
19055
19252
|
const dir = raw.trim() || ".git";
|
|
19056
|
-
return
|
|
19253
|
+
return path13.isAbsolute(dir) ? dir : path13.resolve(baseDir, dir);
|
|
19057
19254
|
}
|
|
19058
19255
|
async function createTempIndexGit(git, baseDir, label) {
|
|
19059
|
-
const tmpDir =
|
|
19060
|
-
await
|
|
19061
|
-
const tempIndexPath =
|
|
19256
|
+
const tmpDir = path13.join(await getGitCommonDir(git, baseDir), "posthog-code-tmp");
|
|
19257
|
+
await fs11.mkdir(tmpDir, { recursive: true });
|
|
19258
|
+
const tempIndexPath = path13.join(tmpDir, `${label}-${Date.now()}-${(0, import_node_crypto2.randomUUID)()}`);
|
|
19062
19259
|
const tempGit = createGitClient(baseDir).env({
|
|
19063
19260
|
...process.env,
|
|
19064
19261
|
GIT_INDEX_FILE: tempIndexPath
|
|
@@ -19085,6 +19282,7 @@ async function deleteCheckpoint(git, checkpointId) {
|
|
|
19085
19282
|
// ../git/dist/handoff.js
|
|
19086
19283
|
var HANDOFF_HEAD_REF_PREFIX = "refs/posthog-code-handoff/head/";
|
|
19087
19284
|
var CHECKPOINT_REF_PREFIX2 = "refs/posthog-code-checkpoint/";
|
|
19285
|
+
var MAX_HANDOFF_FILE_BYTES = 1024 * 1024;
|
|
19088
19286
|
var GitHandoffTracker = class {
|
|
19089
19287
|
repositoryPath;
|
|
19090
19288
|
logger;
|
|
@@ -19092,7 +19290,7 @@ var GitHandoffTracker = class {
|
|
|
19092
19290
|
this.repositoryPath = config.repositoryPath;
|
|
19093
19291
|
this.logger = config.logger;
|
|
19094
19292
|
}
|
|
19095
|
-
async captureForHandoff(
|
|
19293
|
+
async captureForHandoff(localGitState) {
|
|
19096
19294
|
const captureSaga = new CaptureCheckpointSaga(this.logger);
|
|
19097
19295
|
const result = await captureSaga.run({ baseDir: this.repositoryPath });
|
|
19098
19296
|
if (!result.success) {
|
|
@@ -19102,17 +19300,20 @@ var GitHandoffTracker = class {
|
|
|
19102
19300
|
const git = createGitClient(this.repositoryPath);
|
|
19103
19301
|
const tempDir = await this.createTempDir(checkpoint.checkpointId);
|
|
19104
19302
|
const checkpointRef = `${CHECKPOINT_REF_PREFIX2}${checkpoint.checkpointId}`;
|
|
19105
|
-
const packRefs = [
|
|
19106
|
-
checkpoint.head,
|
|
19107
|
-
checkpoint.indexTree,
|
|
19108
|
-
checkpoint.worktreeTree
|
|
19109
|
-
].filter((ref) => !!ref);
|
|
19110
|
-
const headRef = checkpoint.head ? `${HANDOFF_HEAD_REF_PREFIX}${checkpoint.checkpointId}` : void 0;
|
|
19111
|
-
const packPrefix = import_node_path5.default.join(tempDir, checkpoint.checkpointId);
|
|
19112
19303
|
try {
|
|
19304
|
+
const reconciledIndex = await this.reconcileHandoffIndex(git, checkpoint.head, checkpoint.indexTree, tempDir, checkpoint.checkpointId);
|
|
19305
|
+
const packBaseline = localGitState?.upstreamHead ?? null;
|
|
19306
|
+
const packRefs = [
|
|
19307
|
+
checkpoint.head,
|
|
19308
|
+
reconciledIndex.indexTree,
|
|
19309
|
+
checkpoint.worktreeTree,
|
|
19310
|
+
packBaseline ? `^${packBaseline}` : null
|
|
19311
|
+
].filter((ref) => !!ref);
|
|
19312
|
+
const headRef = checkpoint.head ? `${HANDOFF_HEAD_REF_PREFIX}${checkpoint.checkpointId}` : void 0;
|
|
19313
|
+
const packPrefix = import_node_path5.default.join(tempDir, checkpoint.checkpointId);
|
|
19113
19314
|
const [headPack, indexFile, tracking] = await Promise.all([
|
|
19114
19315
|
this.captureObjectPack(packPrefix, packRefs),
|
|
19115
|
-
this.
|
|
19316
|
+
this.statFileArtifact(reconciledIndex.indexFilePath),
|
|
19116
19317
|
getTrackingMetadata(git, checkpoint.branch)
|
|
19117
19318
|
]);
|
|
19118
19319
|
return {
|
|
@@ -19123,7 +19324,7 @@ var GitHandoffTracker = class {
|
|
|
19123
19324
|
headRef,
|
|
19124
19325
|
head: checkpoint.head,
|
|
19125
19326
|
branch: checkpoint.branch,
|
|
19126
|
-
indexTree:
|
|
19327
|
+
indexTree: reconciledIndex.indexTree,
|
|
19127
19328
|
worktreeTree: checkpoint.worktreeTree,
|
|
19128
19329
|
timestamp: checkpoint.timestamp,
|
|
19129
19330
|
upstreamRemote: tracking.upstreamRemote,
|
|
@@ -19143,6 +19344,7 @@ var GitHandoffTracker = class {
|
|
|
19143
19344
|
const { checkpoint, headPackPath, indexPath, localGitState, onDivergedBranch } = input;
|
|
19144
19345
|
const git = createGitClient(this.repositoryPath);
|
|
19145
19346
|
if (headPackPath) {
|
|
19347
|
+
await this.ensureBaselineForApply(git, checkpoint, localGitState);
|
|
19146
19348
|
await this.unpackPackFile(headPackPath);
|
|
19147
19349
|
}
|
|
19148
19350
|
if (checkpoint.branch && checkpoint.head) {
|
|
@@ -19181,14 +19383,89 @@ var GitHandoffTracker = class {
|
|
|
19181
19383
|
});
|
|
19182
19384
|
return { path: packPath, rawBytes };
|
|
19183
19385
|
}
|
|
19184
|
-
async
|
|
19185
|
-
const
|
|
19186
|
-
const
|
|
19187
|
-
await (0, import_promises2.copyFile)(
|
|
19188
|
-
|
|
19189
|
-
|
|
19190
|
-
|
|
19191
|
-
}
|
|
19386
|
+
async reconcileHandoffIndex(git, head, indexTree, tempDir, checkpointId) {
|
|
19387
|
+
const realIndexPath = await this.getGitPath(git, "index");
|
|
19388
|
+
const tempIndexPath = import_node_path5.default.join(tempDir, `${checkpointId}.index`);
|
|
19389
|
+
await (0, import_promises2.copyFile)(realIndexPath, tempIndexPath);
|
|
19390
|
+
const largePaths = await this.listLargeBlobsInTree(indexTree, MAX_HANDOFF_FILE_BYTES);
|
|
19391
|
+
if (largePaths.length === 0) {
|
|
19392
|
+
return { indexTree, indexFilePath: tempIndexPath };
|
|
19393
|
+
}
|
|
19394
|
+
const headBlobs = head ? await this.readHeadBlobsForPaths(head, largePaths) : /* @__PURE__ */ new Map();
|
|
19395
|
+
const env = { ...process.env, GIT_INDEX_FILE: tempIndexPath };
|
|
19396
|
+
for (const filePath of largePaths) {
|
|
19397
|
+
const headBlob = headBlobs.get(filePath);
|
|
19398
|
+
if (headBlob) {
|
|
19399
|
+
await this.runGitWithEnv(env, [
|
|
19400
|
+
"update-index",
|
|
19401
|
+
"--cacheinfo",
|
|
19402
|
+
`${headBlob.mode},${headBlob.hash},${filePath}`
|
|
19403
|
+
]);
|
|
19404
|
+
} else {
|
|
19405
|
+
await this.runGitWithEnv(env, [
|
|
19406
|
+
"update-index",
|
|
19407
|
+
"--force-remove",
|
|
19408
|
+
filePath
|
|
19409
|
+
]).catch(() => {
|
|
19410
|
+
});
|
|
19411
|
+
}
|
|
19412
|
+
}
|
|
19413
|
+
const reconciledTree = (await this.runGitWithEnv(env, ["write-tree"])).trim();
|
|
19414
|
+
return { indexTree: reconciledTree, indexFilePath: tempIndexPath };
|
|
19415
|
+
}
|
|
19416
|
+
async listLargeBlobsInTree(tree, maxBytes) {
|
|
19417
|
+
const { stdout } = await this.runGitProcess(["ls-tree", "-r", "-l", tree], "");
|
|
19418
|
+
const result = [];
|
|
19419
|
+
for (const line of stdout.split("\n")) {
|
|
19420
|
+
if (!line)
|
|
19421
|
+
continue;
|
|
19422
|
+
const tabIndex = line.indexOf(" ");
|
|
19423
|
+
if (tabIndex < 0)
|
|
19424
|
+
continue;
|
|
19425
|
+
const meta = line.slice(0, tabIndex);
|
|
19426
|
+
const filePath = line.slice(tabIndex + 1);
|
|
19427
|
+
const parts2 = meta.split(/\s+/);
|
|
19428
|
+
if (parts2.length < 4)
|
|
19429
|
+
continue;
|
|
19430
|
+
const [, type, , sizeStr] = parts2;
|
|
19431
|
+
if (type !== "blob")
|
|
19432
|
+
continue;
|
|
19433
|
+
if (sizeStr === "-")
|
|
19434
|
+
continue;
|
|
19435
|
+
const size = Number.parseInt(sizeStr, 10);
|
|
19436
|
+
if (Number.isFinite(size) && size > maxBytes) {
|
|
19437
|
+
result.push(filePath);
|
|
19438
|
+
}
|
|
19439
|
+
}
|
|
19440
|
+
return result;
|
|
19441
|
+
}
|
|
19442
|
+
async readHeadBlobsForPaths(head, paths) {
|
|
19443
|
+
const result = /* @__PURE__ */ new Map();
|
|
19444
|
+
const CHUNK_SIZE = 100;
|
|
19445
|
+
for (let i2 = 0; i2 < paths.length; i2 += CHUNK_SIZE) {
|
|
19446
|
+
const chunk = paths.slice(i2, i2 + CHUNK_SIZE);
|
|
19447
|
+
const { stdout } = await this.runGitProcess(["ls-tree", "-r", head, "--", ...chunk], "").catch(() => ({ stdout: "", stderr: "" }));
|
|
19448
|
+
for (const line of stdout.split("\n")) {
|
|
19449
|
+
if (!line)
|
|
19450
|
+
continue;
|
|
19451
|
+
const tabIndex = line.indexOf(" ");
|
|
19452
|
+
if (tabIndex < 0)
|
|
19453
|
+
continue;
|
|
19454
|
+
const meta = line.slice(0, tabIndex);
|
|
19455
|
+
const filePath = line.slice(tabIndex + 1);
|
|
19456
|
+
const parts2 = meta.split(/\s+/);
|
|
19457
|
+
if (parts2.length < 3)
|
|
19458
|
+
continue;
|
|
19459
|
+
const [mode, type, hash] = parts2;
|
|
19460
|
+
if (type !== "blob")
|
|
19461
|
+
continue;
|
|
19462
|
+
result.set(filePath, { mode, hash });
|
|
19463
|
+
}
|
|
19464
|
+
}
|
|
19465
|
+
return result;
|
|
19466
|
+
}
|
|
19467
|
+
async statFileArtifact(filePath) {
|
|
19468
|
+
return { path: filePath, rawBytes: await this.getFileSize(filePath) };
|
|
19192
19469
|
}
|
|
19193
19470
|
async restoreIndexFile(git, indexPath) {
|
|
19194
19471
|
const gitIndexPath = await this.getGitPath(git, "index");
|
|
@@ -19216,6 +19493,20 @@ var GitHandoffTracker = class {
|
|
|
19216
19493
|
shouldRestoreTracking(branchStatus2, localGitState, tracking) {
|
|
19217
19494
|
return branchStatus2.kind === "missing" || !hasTrackingConfig(localGitState) && (tracking.upstreamRemote !== null || tracking.upstreamMergeRef !== null);
|
|
19218
19495
|
}
|
|
19496
|
+
async ensureBaselineForApply(git, checkpoint, localGitState) {
|
|
19497
|
+
const tracking = this.getPreferredTracking(localGitState, checkpoint);
|
|
19498
|
+
if (!tracking.upstreamRemote || !tracking.upstreamMergeRef)
|
|
19499
|
+
return;
|
|
19500
|
+
await this.ensureRemoteForTracking(git, tracking).catch(() => {
|
|
19501
|
+
});
|
|
19502
|
+
await git.raw(["fetch", tracking.upstreamRemote, tracking.upstreamMergeRef]).catch((err2) => {
|
|
19503
|
+
this.logger?.error("Handoff baseline fetch failed; if the pack excludes commits the receiver does not already have, the subsequent unpack/read-tree will fail with an object-missing error", {
|
|
19504
|
+
err: String(err2),
|
|
19505
|
+
remote: tracking.upstreamRemote,
|
|
19506
|
+
ref: tracking.upstreamMergeRef
|
|
19507
|
+
});
|
|
19508
|
+
});
|
|
19509
|
+
}
|
|
19219
19510
|
async ensureRemoteForTracking(git, tracking) {
|
|
19220
19511
|
if (!tracking.upstreamRemote || !tracking.remoteUrl)
|
|
19221
19512
|
return;
|
|
@@ -19352,6 +19643,31 @@ var GitHandoffTracker = class {
|
|
|
19352
19643
|
});
|
|
19353
19644
|
});
|
|
19354
19645
|
}
|
|
19646
|
+
async runGitWithEnv(env, args2) {
|
|
19647
|
+
return new Promise((resolve7, reject) => {
|
|
19648
|
+
const child = (0, import_node_child_process4.spawn)("git", args2, {
|
|
19649
|
+
cwd: this.repositoryPath,
|
|
19650
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
19651
|
+
env
|
|
19652
|
+
});
|
|
19653
|
+
let stdout = "";
|
|
19654
|
+
let stderr = "";
|
|
19655
|
+
child.stdout.on("data", (chunk) => {
|
|
19656
|
+
stdout += chunk.toString();
|
|
19657
|
+
});
|
|
19658
|
+
child.stderr.on("data", (chunk) => {
|
|
19659
|
+
stderr += chunk.toString();
|
|
19660
|
+
});
|
|
19661
|
+
child.on("error", reject);
|
|
19662
|
+
child.on("close", (code) => {
|
|
19663
|
+
if (code === 0) {
|
|
19664
|
+
resolve7(stdout);
|
|
19665
|
+
return;
|
|
19666
|
+
}
|
|
19667
|
+
reject(new Error(stderr || `git ${args2.join(" ")} failed with code ${code}`));
|
|
19668
|
+
});
|
|
19669
|
+
});
|
|
19670
|
+
}
|
|
19355
19671
|
runGitProcess(args2, input) {
|
|
19356
19672
|
return new Promise((resolve7, reject) => {
|
|
19357
19673
|
const child = (0, import_node_child_process4.spawn)("git", args2, {
|
|
@@ -19374,6 +19690,8 @@ var GitHandoffTracker = class {
|
|
|
19374
19690
|
}
|
|
19375
19691
|
reject(new Error(stderr || `git ${args2.join(" ")} failed with code ${code}`));
|
|
19376
19692
|
});
|
|
19693
|
+
child.stdin.on("error", () => {
|
|
19694
|
+
});
|
|
19377
19695
|
child.stdin.end(input);
|
|
19378
19696
|
});
|
|
19379
19697
|
}
|
|
@@ -19864,9 +20182,9 @@ var PostHogAPIClient = class {
|
|
|
19864
20182
|
|
|
19865
20183
|
// src/adapters/claude/session/jsonl-hydration.ts
|
|
19866
20184
|
var import_node_crypto3 = require("crypto");
|
|
19867
|
-
var
|
|
19868
|
-
var
|
|
19869
|
-
var
|
|
20185
|
+
var fs12 = __toESM(require("fs/promises"), 1);
|
|
20186
|
+
var os7 = __toESM(require("os"), 1);
|
|
20187
|
+
var path15 = __toESM(require("path"), 1);
|
|
19870
20188
|
var CHARS_PER_TOKEN = 4;
|
|
19871
20189
|
var DEFAULT_MAX_TOKENS = 15e4;
|
|
19872
20190
|
function estimateTurnTokens(turn) {
|
|
@@ -20532,7 +20850,7 @@ async function getAgentshVersion() {
|
|
|
20532
20850
|
}
|
|
20533
20851
|
async function resolveAgentshRuntimeInfo({
|
|
20534
20852
|
sessionIdPath = AGENTSH_SESSION_ID_FILE,
|
|
20535
|
-
readSessionId = async (
|
|
20853
|
+
readSessionId = async (path17) => (0, import_promises5.readFile)(path17, "utf8"),
|
|
20536
20854
|
getVersion = getAgentshVersion
|
|
20537
20855
|
} = {}) {
|
|
20538
20856
|
let sessionId;
|