@buildautomaton/cli 0.1.35 → 0.1.37
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +409 -112
- package/dist/cli.js.map +4 -4
- package/dist/index.js +403 -106
- package/dist/index.js.map +4 -4
- package/dist/migrations/003_file_index_parent_paths.sql +17 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -22935,6 +22935,16 @@ function isClaudeCodePermissionMode(value) {
|
|
|
22935
22935
|
return MODE_SET.has(value);
|
|
22936
22936
|
}
|
|
22937
22937
|
|
|
22938
|
+
// ../types/src/codex-permission-mode.ts
|
|
22939
|
+
function isCodexPermissionMode(value) {
|
|
22940
|
+
return value.trim() !== "";
|
|
22941
|
+
}
|
|
22942
|
+
function normalizeCodexPermissionModeInput(raw) {
|
|
22943
|
+
if (typeof raw !== "string") return null;
|
|
22944
|
+
const t = raw.trim();
|
|
22945
|
+
return isCodexPermissionMode(t) ? t : null;
|
|
22946
|
+
}
|
|
22947
|
+
|
|
22938
22948
|
// ../types/src/cli-permission-mode.ts
|
|
22939
22949
|
var CLI_PERMISSION_MODE_DEFAULT = "default";
|
|
22940
22950
|
var CLI_PERMISSION_MODE_DANGEROUS = "dangerous";
|
|
@@ -23006,6 +23016,7 @@ function buildCliAutoApprovedPermissionRpcResult(requestParams) {
|
|
|
23006
23016
|
// ../types/src/agent-config.ts
|
|
23007
23017
|
var AGENT_CONFIG_CLAUDE_PERMISSION_MODE_KEY = "claude_permission_mode";
|
|
23008
23018
|
var AGENT_CONFIG_CLI_PERMISSION_MODE_KEY = "cli_permission_mode";
|
|
23019
|
+
var AGENT_CONFIG_CODEX_PERMISSION_MODE_KEY = "codex_permission_mode";
|
|
23009
23020
|
var AGENT_CONFIG_AGENT_MODEL_KEY = "agent_model";
|
|
23010
23021
|
function getClaudePermissionModeFromAgentConfig(config2) {
|
|
23011
23022
|
if (!config2) return null;
|
|
@@ -23018,6 +23029,10 @@ function getCliPermissionModeFromAgentConfig(config2) {
|
|
|
23018
23029
|
if (!config2) return CLI_PERMISSION_MODE_DEFAULT;
|
|
23019
23030
|
return normalizeCliPermissionModeInput(config2[AGENT_CONFIG_CLI_PERMISSION_MODE_KEY]);
|
|
23020
23031
|
}
|
|
23032
|
+
function getCodexPermissionModeFromAgentConfig(config2) {
|
|
23033
|
+
if (!config2) return null;
|
|
23034
|
+
return normalizeCodexPermissionModeInput(config2[AGENT_CONFIG_CODEX_PERMISSION_MODE_KEY]);
|
|
23035
|
+
}
|
|
23021
23036
|
function getAgentModelFromAgentConfig(config2) {
|
|
23022
23037
|
if (!config2) return null;
|
|
23023
23038
|
const cur = config2[AGENT_CONFIG_AGENT_MODEL_KEY];
|
|
@@ -23080,8 +23095,60 @@ async function applyClaudePermissionFromAcpSession(params) {
|
|
|
23080
23095
|
}
|
|
23081
23096
|
}
|
|
23082
23097
|
|
|
23083
|
-
// src/agents/acp/
|
|
23098
|
+
// src/agents/acp/codex-acp-permission-from-session.ts
|
|
23084
23099
|
function flattenSelectOptions2(options) {
|
|
23100
|
+
if (options == null || options.length === 0) return [];
|
|
23101
|
+
const first2 = options[0];
|
|
23102
|
+
if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
|
|
23103
|
+
return options.flatMap(
|
|
23104
|
+
(g) => Array.isArray(g.options) ? g.options : []
|
|
23105
|
+
);
|
|
23106
|
+
}
|
|
23107
|
+
return options;
|
|
23108
|
+
}
|
|
23109
|
+
function pickModeConfigOption2(configOptions) {
|
|
23110
|
+
if (configOptions == null || configOptions.length === 0) return null;
|
|
23111
|
+
const byCategory = configOptions.find((o) => o.category === "mode");
|
|
23112
|
+
if (byCategory) return byCategory;
|
|
23113
|
+
return configOptions.find((o) => o.id === "mode") ?? null;
|
|
23114
|
+
}
|
|
23115
|
+
async function applyCodexPermissionFromAcpSession(params) {
|
|
23116
|
+
const { sessionId, agentConfig, configOptions, modes, setSessionConfigOption, setSessionMode, logDebug: logDebug2 } = params;
|
|
23117
|
+
const desiredMode = getCodexPermissionModeFromAgentConfig(agentConfig);
|
|
23118
|
+
if (desiredMode == null) return;
|
|
23119
|
+
const modeOpt = pickModeConfigOption2(configOptions ?? null);
|
|
23120
|
+
if (modeOpt != null) {
|
|
23121
|
+
const flat = flattenSelectOptions2(modeOpt.options);
|
|
23122
|
+
const allowed = flat.some((o) => o.value === desiredMode);
|
|
23123
|
+
if (allowed && modeOpt.currentValue !== desiredMode) {
|
|
23124
|
+
try {
|
|
23125
|
+
logDebug2(
|
|
23126
|
+
`[Agent] Codex: sending ACP session/set_config_option (mode) configId=${JSON.stringify(modeOpt.id)} value=${JSON.stringify(desiredMode)} was=${JSON.stringify(modeOpt.currentValue)} sessionId=${sessionId.slice(0, 8)}\u2026`
|
|
23127
|
+
);
|
|
23128
|
+
await setSessionConfigOption({ sessionId, configId: modeOpt.id, value: desiredMode });
|
|
23129
|
+
} catch (e) {
|
|
23130
|
+
logDebug2(`[Agent] Codex: session/set_config_option failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
23131
|
+
}
|
|
23132
|
+
}
|
|
23133
|
+
return;
|
|
23134
|
+
}
|
|
23135
|
+
if (modes?.availableModes?.length) {
|
|
23136
|
+
const allowed = modes.availableModes.some((m) => m.id === desiredMode);
|
|
23137
|
+
if (allowed && desiredMode !== modes.currentModeId) {
|
|
23138
|
+
try {
|
|
23139
|
+
logDebug2(
|
|
23140
|
+
`[Agent] Codex: sending ACP session/set_mode modeId=${JSON.stringify(desiredMode)} was=${JSON.stringify(modes.currentModeId ?? null)} sessionId=${sessionId.slice(0, 8)}\u2026`
|
|
23141
|
+
);
|
|
23142
|
+
await setSessionMode({ sessionId, modeId: desiredMode });
|
|
23143
|
+
} catch (e) {
|
|
23144
|
+
logDebug2(`[Agent] Codex: session/set_mode failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
23145
|
+
}
|
|
23146
|
+
}
|
|
23147
|
+
}
|
|
23148
|
+
}
|
|
23149
|
+
|
|
23150
|
+
// src/agents/acp/apply-acp-model-from-agent-session.ts
|
|
23151
|
+
function flattenSelectOptions3(options) {
|
|
23085
23152
|
if (options == null || options.length === 0) return [];
|
|
23086
23153
|
const first2 = options[0];
|
|
23087
23154
|
if (first2 != null && typeof first2 === "object" && "group" in first2 && first2.group != null) {
|
|
@@ -23106,7 +23173,7 @@ async function applyAcpModelFromAcpSession(params) {
|
|
|
23106
23173
|
if (desired == null) return;
|
|
23107
23174
|
const modelOpt = pickModelConfigOption(configOptions ?? null);
|
|
23108
23175
|
if (modelOpt == null) return;
|
|
23109
|
-
const flat =
|
|
23176
|
+
const flat = flattenSelectOptions3(modelOpt.options);
|
|
23110
23177
|
const allowed = flat.some((o) => o.value === desired);
|
|
23111
23178
|
if (!allowed) return;
|
|
23112
23179
|
if (modelOpt.currentValue === desired) return;
|
|
@@ -23186,12 +23253,41 @@ function parseAcpInitAgentCapabilities(initResult) {
|
|
|
23186
23253
|
}
|
|
23187
23254
|
|
|
23188
23255
|
// src/agents/acp/clients/shared/bootstrap-acp-wire-session.ts
|
|
23256
|
+
function configOptionsWithModes(configOptions, modes) {
|
|
23257
|
+
const modeState = modes && typeof modes === "object" ? modes : null;
|
|
23258
|
+
if (!modeState?.availableModes?.length) return configOptions;
|
|
23259
|
+
const hasModeConfig = Array.isArray(configOptions) && configOptions.some((raw) => {
|
|
23260
|
+
if (raw == null || typeof raw !== "object" || Array.isArray(raw)) return false;
|
|
23261
|
+
const o = raw;
|
|
23262
|
+
return o.category === "mode" || o.id === "mode";
|
|
23263
|
+
});
|
|
23264
|
+
if (hasModeConfig) return configOptions;
|
|
23265
|
+
return [
|
|
23266
|
+
...configOptions ?? [],
|
|
23267
|
+
{
|
|
23268
|
+
id: "mode",
|
|
23269
|
+
name: "Mode",
|
|
23270
|
+
type: "select",
|
|
23271
|
+
category: "mode",
|
|
23272
|
+
currentValue: modeState.currentModeId ?? null,
|
|
23273
|
+
options: modeState.availableModes.map((m) => {
|
|
23274
|
+
const r = m;
|
|
23275
|
+
return {
|
|
23276
|
+
value: m.id,
|
|
23277
|
+
name: m.name ?? m.id,
|
|
23278
|
+
...typeof r.description === "string" && r.description.trim() !== "" ? { description: r.description.trim() } : {}
|
|
23279
|
+
};
|
|
23280
|
+
})
|
|
23281
|
+
}
|
|
23282
|
+
];
|
|
23283
|
+
}
|
|
23189
23284
|
async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
|
|
23190
23285
|
const initResult = await transport.initialize(initializeRequest);
|
|
23191
23286
|
const { canResume, canLoad, promptSupportsImage } = parseAcpInitAgentCapabilities(initResult);
|
|
23192
23287
|
ctx.agentPromptImageSupported = promptSupportsImage;
|
|
23193
23288
|
await transport.afterInitialize?.();
|
|
23194
23289
|
const established = await establishAcpSessionWithTransport(transport, ctx, canResume, canLoad);
|
|
23290
|
+
established.configOptions = configOptionsWithModes(established.configOptions, established.modes);
|
|
23195
23291
|
const sessionId = established.sessionId;
|
|
23196
23292
|
ctx.onAcpSessionEstablished?.({
|
|
23197
23293
|
acpSessionId: sessionId,
|
|
@@ -23214,6 +23310,22 @@ async function bootstrapAcpWireSession(transport, ctx, initializeRequest) {
|
|
|
23214
23310
|
logDebug: ctx.logDebug
|
|
23215
23311
|
});
|
|
23216
23312
|
}
|
|
23313
|
+
if (ctx.backendAgentType === "codex-acp") {
|
|
23314
|
+
const cfg = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
|
|
23315
|
+
const configOptionsTyped = established.configOptions;
|
|
23316
|
+
const modesTyped = established.modes;
|
|
23317
|
+
await applyCodexPermissionFromAcpSession({
|
|
23318
|
+
sessionId,
|
|
23319
|
+
agentConfig: cfg,
|
|
23320
|
+
configOptions: configOptionsForPermission(ctx.getActiveConfigOptions, configOptionsTyped),
|
|
23321
|
+
modes: modesTyped,
|
|
23322
|
+
setSessionConfigOption: transport.setSessionConfigOption ? (p) => transport.setSessionConfigOption(p) : async () => {
|
|
23323
|
+
},
|
|
23324
|
+
setSessionMode: transport.setSessionMode ? (p) => transport.setSessionMode(p) : async () => {
|
|
23325
|
+
},
|
|
23326
|
+
logDebug: ctx.logDebug
|
|
23327
|
+
});
|
|
23328
|
+
}
|
|
23217
23329
|
const cfgAll = ctx.agentConfig != null && typeof ctx.agentConfig === "object" && !Array.isArray(ctx.agentConfig) ? ctx.agentConfig : null;
|
|
23218
23330
|
const configOptionsForModel = established.configOptions;
|
|
23219
23331
|
if (transport.setSessionConfigOption) {
|
|
@@ -23964,7 +24076,7 @@ function installBridgeProcessResilience() {
|
|
|
23964
24076
|
}
|
|
23965
24077
|
|
|
23966
24078
|
// src/cli-version.ts
|
|
23967
|
-
var CLI_VERSION = "0.1.
|
|
24079
|
+
var CLI_VERSION = "0.1.37".length > 0 ? "0.1.37" : "0.0.0-dev";
|
|
23968
24080
|
|
|
23969
24081
|
// src/connection/heartbeat/constants.ts
|
|
23970
24082
|
var BRIDGE_APP_HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -25287,6 +25399,7 @@ function recordMigrationAndPruneCheckpointLegacy(db, migration, applied2) {
|
|
|
25287
25399
|
var CHECKPOINT_V1 = "001_cli_sqlite_checkpoint_v1";
|
|
25288
25400
|
var CHECKPOINT_V1_SQL = readCliSqliteMigrationSql("001_cli_sqlite_checkpoint_v1.sql");
|
|
25289
25401
|
var AGENT_CAPABILITIES_SQL = readCliSqliteMigrationSql("002_agent_capabilities.sql");
|
|
25402
|
+
var FILE_INDEX_PARENT_PATHS_SQL = readCliSqliteMigrationSql("003_file_index_parent_paths.sql");
|
|
25290
25403
|
function agentCapabilitiesTableState(db) {
|
|
25291
25404
|
const rows = db.all(
|
|
25292
25405
|
`SELECT name FROM sqlite_master WHERE type='table' AND name IN ('agent_capabilities', 'agent_capability_cache')`
|
|
@@ -25320,6 +25433,18 @@ var CLI_SQLITE_MIGRATIONS = [
|
|
|
25320
25433
|
db.exec(AGENT_CAPABILITIES_SQL);
|
|
25321
25434
|
},
|
|
25322
25435
|
alreadyApplied: (db) => agentCapabilitiesTableState(db) === "current"
|
|
25436
|
+
},
|
|
25437
|
+
{
|
|
25438
|
+
name: "003_file_index_parent_paths",
|
|
25439
|
+
migrate: (db) => {
|
|
25440
|
+
db.exec(FILE_INDEX_PARENT_PATHS_SQL);
|
|
25441
|
+
},
|
|
25442
|
+
alreadyApplied: (db) => {
|
|
25443
|
+
const row = db.get(
|
|
25444
|
+
`SELECT 1 as ok FROM sqlite_master WHERE type='table' AND name='file_index_parent_path' LIMIT 1`
|
|
25445
|
+
);
|
|
25446
|
+
return row != null;
|
|
25447
|
+
}
|
|
25323
25448
|
}
|
|
25324
25449
|
];
|
|
25325
25450
|
function migrateCliSqlite(db) {
|
|
@@ -25358,6 +25483,10 @@ var CliSqliteInterrupted = class extends Error {
|
|
|
25358
25483
|
}
|
|
25359
25484
|
};
|
|
25360
25485
|
function applyCliSqliteConcurrencyPragmas(db) {
|
|
25486
|
+
try {
|
|
25487
|
+
db.run("PRAGMA foreign_keys = ON");
|
|
25488
|
+
} catch {
|
|
25489
|
+
}
|
|
25361
25490
|
try {
|
|
25362
25491
|
db.exec("PRAGMA journal_mode = WAL");
|
|
25363
25492
|
} catch {
|
|
@@ -30923,13 +31052,18 @@ function isCodexAcpCommand(command) {
|
|
|
30923
31052
|
const i = command.indexOf("@zed-industries/codex-acp");
|
|
30924
31053
|
return i >= 0 && (i === 0 || command[i - 1] === "npx" || command[i - 1] === "bunx");
|
|
30925
31054
|
}
|
|
30926
|
-
function buildCodexAcpSpawnCommand(base, _sessionMode) {
|
|
31055
|
+
function buildCodexAcpSpawnCommand(base, _sessionMode, _agentConfig) {
|
|
30927
31056
|
return [...base];
|
|
30928
31057
|
}
|
|
30929
31058
|
async function createCodexAcpClient(options) {
|
|
30930
31059
|
const base = options.command?.length && options.command.some((a) => a.includes("codex-acp")) ? options.command : [...DEFAULT_CODEX_ACP_COMMAND];
|
|
30931
|
-
const command = buildCodexAcpSpawnCommand(base, options.sessionMode);
|
|
30932
|
-
return createSdkStdioAcpClient({
|
|
31060
|
+
const command = buildCodexAcpSpawnCommand(base, options.sessionMode, options.agentConfig);
|
|
31061
|
+
return createSdkStdioAcpClient({
|
|
31062
|
+
...options,
|
|
31063
|
+
command,
|
|
31064
|
+
/** Codex ACP can ignore `session/cancel`; mirror Claude Code's subprocess fallback. */
|
|
31065
|
+
killSubprocessAfterCancelMs: options.killSubprocessAfterCancelMs ?? 2500
|
|
31066
|
+
});
|
|
30933
31067
|
}
|
|
30934
31068
|
|
|
30935
31069
|
// src/agents/acp/clients/cursor/cursor-acp-client.ts
|
|
@@ -31327,7 +31461,7 @@ function resolveAgentCommand(preferredAgentType) {
|
|
|
31327
31461
|
command,
|
|
31328
31462
|
label: preferredAgentType,
|
|
31329
31463
|
createClient: createCodexAcpClient,
|
|
31330
|
-
spawnCommandForSession: (sessionMode,
|
|
31464
|
+
spawnCommandForSession: (sessionMode, agentConfig) => buildCodexAcpSpawnCommand(command, sessionMode, agentConfig)
|
|
31331
31465
|
};
|
|
31332
31466
|
}
|
|
31333
31467
|
if (useKiroAcp(preferredAgentType, command)) {
|
|
@@ -33783,8 +33917,18 @@ import path28 from "node:path";
|
|
|
33783
33917
|
// src/files/index/walk-workspace-tree.ts
|
|
33784
33918
|
import fs24 from "node:fs";
|
|
33785
33919
|
import path27 from "node:path";
|
|
33920
|
+
var DEPENDENCY_INSTALL_DIR_NAMES = /* @__PURE__ */ new Set([
|
|
33921
|
+
"node_modules",
|
|
33922
|
+
"bower_components",
|
|
33923
|
+
"vendor",
|
|
33924
|
+
"Pods",
|
|
33925
|
+
"Carthage",
|
|
33926
|
+
"DerivedData",
|
|
33927
|
+
".yarn",
|
|
33928
|
+
".pnpm-store"
|
|
33929
|
+
]);
|
|
33786
33930
|
function shouldSkipWorkspaceWalkEntry(name) {
|
|
33787
|
-
return
|
|
33931
|
+
return DEPENDENCY_INSTALL_DIR_NAMES.has(name);
|
|
33788
33932
|
}
|
|
33789
33933
|
async function walkWorkspaceTreeAsync(dir, baseDir, onFile, state) {
|
|
33790
33934
|
let names;
|
|
@@ -33855,14 +33999,26 @@ var FILE_INDEX_INTERRUPT_CHECK_EVERY = 256;
|
|
|
33855
33999
|
function assertNotShutdown() {
|
|
33856
34000
|
if (isCliImmediateShutdownRequested()) throw new CliSqliteInterrupted();
|
|
33857
34001
|
}
|
|
34002
|
+
function upsertFileIndexParentPath(db, resolved) {
|
|
34003
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
34004
|
+
db.run(
|
|
34005
|
+
`INSERT INTO file_index_parent_path (path, path_hash, updated_at)
|
|
34006
|
+
VALUES (?, ?, ?)
|
|
34007
|
+
ON CONFLICT(path) DO UPDATE SET path_hash = excluded.path_hash, updated_at = excluded.updated_at`,
|
|
34008
|
+
[resolved, getCwdHashForFileIndex(resolved), now]
|
|
34009
|
+
);
|
|
34010
|
+
const row = db.get("SELECT id FROM file_index_parent_path WHERE path = ?", [resolved]);
|
|
34011
|
+
if (row == null) throw new Error(`Failed to upsert file index parent path: ${resolved}`);
|
|
34012
|
+
return Number(row.id);
|
|
34013
|
+
}
|
|
33858
34014
|
function persistFileIndexPaths(resolved, paths) {
|
|
33859
34015
|
return withCliSqliteSync((db) => {
|
|
33860
|
-
const h = getCwdHashForFileIndex(resolved);
|
|
33861
34016
|
let pathCount = 0;
|
|
33862
34017
|
db.run("BEGIN IMMEDIATE");
|
|
33863
34018
|
try {
|
|
33864
|
-
|
|
33865
|
-
|
|
34019
|
+
const parentId = upsertFileIndexParentPath(db, resolved);
|
|
34020
|
+
db.run("DELETE FROM file_index_child_path WHERE parent_id = ?", [parentId]);
|
|
34021
|
+
const ins = db.prepare("INSERT INTO file_index_child_path (parent_id, path) VALUES (?, ?)");
|
|
33866
34022
|
try {
|
|
33867
34023
|
let batch = 0;
|
|
33868
34024
|
for (const rel of paths) {
|
|
@@ -33870,7 +34026,7 @@ function persistFileIndexPaths(resolved, paths) {
|
|
|
33870
34026
|
batch = 0;
|
|
33871
34027
|
assertNotShutdown();
|
|
33872
34028
|
}
|
|
33873
|
-
ins.run([
|
|
34029
|
+
ins.run([parentId, rel]);
|
|
33874
34030
|
pathCount += 1;
|
|
33875
34031
|
}
|
|
33876
34032
|
} finally {
|
|
@@ -33912,36 +34068,38 @@ async function buildFileIndexAsync(cwd) {
|
|
|
33912
34068
|
// src/files/index/ensure-file-index.ts
|
|
33913
34069
|
import path29 from "node:path";
|
|
33914
34070
|
|
|
33915
|
-
// src/files/index/file-index-dependency-path.ts
|
|
33916
|
-
function sqliteExprBridgeFileIndexDependencyRank() {
|
|
33917
|
-
return `CASE WHEN lower(path) = 'node_modules' OR lower(path) LIKE 'node_modules/%' OR lower(path) LIKE '%/node_modules/%' OR lower(path) = 'bower_components' OR lower(path) LIKE 'bower_components/%' OR lower(path) LIKE '%/bower_components/%' THEN 1 ELSE 0 END`;
|
|
33918
|
-
}
|
|
33919
|
-
|
|
33920
34071
|
// src/files/index/search-file-index.ts
|
|
33921
34072
|
function escapeLikePattern(fragment) {
|
|
33922
34073
|
return fragment.replace(/\\/g, "\\\\").replace(/%/g, "\\%").replace(/_/g, "\\_");
|
|
33923
34074
|
}
|
|
33924
34075
|
function bridgeFileIndexIsPopulatedWithDb(resolvedCwd, db) {
|
|
33925
|
-
const
|
|
33926
|
-
const row = db.get("SELECT 1 as ok FROM file_index_path WHERE cwd_hash = ? LIMIT 1", [h]);
|
|
34076
|
+
const row = db.get("SELECT 1 as ok FROM file_index_parent_path WHERE path = ? LIMIT 1", [resolvedCwd]);
|
|
33927
34077
|
return row != null;
|
|
33928
34078
|
}
|
|
33929
34079
|
function bridgeFileIndexPathCountWithDb(resolvedCwd, db) {
|
|
33930
|
-
const
|
|
33931
|
-
|
|
34080
|
+
const row = db.get(
|
|
34081
|
+
`SELECT COUNT(*) as c
|
|
34082
|
+
FROM file_index_child_path child
|
|
34083
|
+
JOIN file_index_parent_path parent ON parent.id = child.parent_id
|
|
34084
|
+
WHERE parent.path = ?`,
|
|
34085
|
+
[resolvedCwd]
|
|
34086
|
+
);
|
|
33932
34087
|
const c = row?.c ?? 0;
|
|
33933
34088
|
return Number(c);
|
|
33934
34089
|
}
|
|
33935
34090
|
function searchBridgeFilePathsWithDb(resolvedCwd, query, limit, db) {
|
|
33936
34091
|
const q = query.trim().toLowerCase();
|
|
33937
34092
|
if (!q) return [];
|
|
33938
|
-
const h = getCwdHashForFileIndex(resolvedCwd);
|
|
33939
34093
|
const pattern = `%${escapeLikePattern(q)}%`;
|
|
33940
34094
|
const lim = Math.max(0, Math.min(1e4, Math.floor(limit)));
|
|
33941
|
-
const depRank = sqliteExprBridgeFileIndexDependencyRank();
|
|
33942
34095
|
const rows = db.all(
|
|
33943
|
-
`SELECT path
|
|
33944
|
-
|
|
34096
|
+
`SELECT child.path
|
|
34097
|
+
FROM file_index_child_path child
|
|
34098
|
+
JOIN file_index_parent_path parent ON parent.id = child.parent_id
|
|
34099
|
+
WHERE parent.path = ? AND lower(child.path) LIKE ? ESCAPE '\\'
|
|
34100
|
+
ORDER BY child.path
|
|
34101
|
+
LIMIT ?`,
|
|
34102
|
+
[resolvedCwd, pattern, lim]
|
|
33945
34103
|
);
|
|
33946
34104
|
return rows.map((r) => String(r.path));
|
|
33947
34105
|
}
|
|
@@ -33971,9 +34129,7 @@ async function ensureFileIndexAsync(cwd) {
|
|
|
33971
34129
|
var DEBOUNCE_MS = 900;
|
|
33972
34130
|
function shouldIgnoreRelative(rel) {
|
|
33973
34131
|
const n = rel.replace(/\\/g, "/");
|
|
33974
|
-
|
|
33975
|
-
if (n.includes("/.buildautomaton/") || n.startsWith(".buildautomaton/")) return true;
|
|
33976
|
-
return false;
|
|
34132
|
+
return n.split("/").some((segment) => shouldSkipWorkspaceWalkEntry(segment));
|
|
33977
34133
|
}
|
|
33978
34134
|
function attachWatchErrorLog(w) {
|
|
33979
34135
|
w.on("error", (err) => {
|
|
@@ -36016,9 +36172,8 @@ var handleSkillCallMessage = (msg, { getWs, log: log2 }) => {
|
|
|
36016
36172
|
);
|
|
36017
36173
|
};
|
|
36018
36174
|
|
|
36019
|
-
// src/files/list-dir.ts
|
|
36020
|
-
import
|
|
36021
|
-
import path35 from "node:path";
|
|
36175
|
+
// src/files/list-dir/index.ts
|
|
36176
|
+
import fs33 from "node:fs";
|
|
36022
36177
|
|
|
36023
36178
|
// src/files/ensure-under-cwd.ts
|
|
36024
36179
|
import path34 from "node:path";
|
|
@@ -36031,71 +36186,93 @@ function ensureUnderCwd(relativePath, cwd = getBridgeRoot()) {
|
|
|
36031
36186
|
return resolved;
|
|
36032
36187
|
}
|
|
36033
36188
|
|
|
36034
|
-
// src/files/list-dir.ts
|
|
36189
|
+
// src/files/list-dir/types.ts
|
|
36035
36190
|
var LIST_DIR_YIELD_EVERY = 256;
|
|
36036
|
-
|
|
36037
|
-
|
|
36191
|
+
|
|
36192
|
+
// src/files/list-dir/map-dir-entry.ts
|
|
36193
|
+
import path35 from "node:path";
|
|
36194
|
+
import fs32 from "node:fs";
|
|
36195
|
+
async function mapDirEntry(d, relativePath, resolved) {
|
|
36196
|
+
const entryPath = path35.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
36197
|
+
const fullPath = path35.join(resolved, d.name);
|
|
36198
|
+
let isDir = d.isDirectory();
|
|
36199
|
+
if (d.isSymbolicLink()) {
|
|
36200
|
+
try {
|
|
36201
|
+
const targetStat = await fs32.promises.stat(fullPath);
|
|
36202
|
+
isDir = targetStat.isDirectory();
|
|
36203
|
+
} catch {
|
|
36204
|
+
isDir = false;
|
|
36205
|
+
}
|
|
36206
|
+
}
|
|
36207
|
+
return {
|
|
36208
|
+
name: d.name,
|
|
36209
|
+
path: entryPath,
|
|
36210
|
+
isDir,
|
|
36211
|
+
isSymlink: d.isSymbolicLink()
|
|
36212
|
+
};
|
|
36213
|
+
}
|
|
36214
|
+
|
|
36215
|
+
// src/files/list-dir/sort-entries.ts
|
|
36216
|
+
function sortListEntries(entries) {
|
|
36217
|
+
return entries.sort((a, b) => {
|
|
36218
|
+
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
36219
|
+
return a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
|
|
36220
|
+
});
|
|
36221
|
+
}
|
|
36222
|
+
|
|
36223
|
+
// src/files/list-dir/index.ts
|
|
36224
|
+
async function listDirAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
36225
|
+
await yieldToEventLoop();
|
|
36226
|
+
const resolved = ensureUnderCwd(relativePath || ".", sessionParentPath);
|
|
36038
36227
|
if (!resolved) {
|
|
36039
36228
|
return { error: "Path is outside working directory" };
|
|
36040
36229
|
}
|
|
36041
36230
|
try {
|
|
36042
|
-
const names = await
|
|
36043
|
-
const visible = names.filter((d) => !d.name.startsWith("."));
|
|
36231
|
+
const names = await fs33.promises.readdir(resolved, { withFileTypes: true });
|
|
36044
36232
|
const entries = [];
|
|
36045
|
-
for (let i = 0; i <
|
|
36233
|
+
for (let i = 0; i < names.length; i++) {
|
|
36046
36234
|
if (i > 0 && i % LIST_DIR_YIELD_EVERY === 0) {
|
|
36047
36235
|
await yieldToEventLoop();
|
|
36048
36236
|
}
|
|
36049
|
-
|
|
36050
|
-
const entryPath = path35.join(relativePath || ".", d.name).replace(/\\/g, "/");
|
|
36051
|
-
const fullPath = path35.join(resolved, d.name);
|
|
36052
|
-
let isDir = d.isDirectory();
|
|
36053
|
-
if (d.isSymbolicLink()) {
|
|
36054
|
-
try {
|
|
36055
|
-
const targetStat = await fs32.promises.stat(fullPath);
|
|
36056
|
-
isDir = targetStat.isDirectory();
|
|
36057
|
-
} catch {
|
|
36058
|
-
isDir = false;
|
|
36059
|
-
}
|
|
36060
|
-
}
|
|
36061
|
-
entries.push({
|
|
36062
|
-
name: d.name,
|
|
36063
|
-
path: entryPath,
|
|
36064
|
-
isDir,
|
|
36065
|
-
isSymlink: d.isSymbolicLink()
|
|
36066
|
-
});
|
|
36237
|
+
entries.push(await mapDirEntry(names[i], relativePath, resolved));
|
|
36067
36238
|
}
|
|
36068
|
-
entries
|
|
36069
|
-
if (a.isDir !== b.isDir) return a.isDir ? -1 : 1;
|
|
36070
|
-
return a.name.localeCompare(b.name, void 0, { sensitivity: "base" });
|
|
36071
|
-
});
|
|
36072
|
-
return { entries };
|
|
36239
|
+
return { entries: sortListEntries(entries) };
|
|
36073
36240
|
} catch (err) {
|
|
36074
36241
|
const message = err instanceof Error ? err.message : String(err);
|
|
36075
36242
|
return { error: message };
|
|
36076
36243
|
}
|
|
36077
36244
|
}
|
|
36078
36245
|
|
|
36079
|
-
// src/files/read-file.ts
|
|
36080
|
-
|
|
36081
|
-
|
|
36082
|
-
|
|
36083
|
-
|
|
36246
|
+
// src/files/read-file/types.ts
|
|
36247
|
+
var LINE_CHUNK_SIZE = 64 * 1024;
|
|
36248
|
+
var READ_RANGE_YIELD_EVERY_BYTES = 256 * 1024;
|
|
36249
|
+
|
|
36250
|
+
// src/files/read-file/resolve-file-path.ts
|
|
36251
|
+
import fs34 from "node:fs";
|
|
36252
|
+
async function resolveFilePathAsync(relativePath, sessionParentPath = getBridgeRoot()) {
|
|
36253
|
+
const resolved = ensureUnderCwd(relativePath, sessionParentPath);
|
|
36084
36254
|
if (!resolved) return { error: "Path is outside working directory" };
|
|
36085
36255
|
let real;
|
|
36086
36256
|
try {
|
|
36087
|
-
real =
|
|
36257
|
+
real = await fs34.promises.realpath(resolved);
|
|
36088
36258
|
} catch {
|
|
36089
36259
|
real = resolved;
|
|
36090
36260
|
}
|
|
36091
|
-
|
|
36092
|
-
|
|
36093
|
-
|
|
36261
|
+
try {
|
|
36262
|
+
const stat2 = await fs34.promises.stat(real);
|
|
36263
|
+
if (!stat2.isFile()) return { error: "Not a file" };
|
|
36264
|
+
return real;
|
|
36265
|
+
} catch (err) {
|
|
36266
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
36267
|
+
}
|
|
36094
36268
|
}
|
|
36095
|
-
|
|
36096
|
-
|
|
36097
|
-
|
|
36098
|
-
|
|
36269
|
+
|
|
36270
|
+
// src/files/read-file/read-file-range-async.ts
|
|
36271
|
+
import fs35 from "node:fs";
|
|
36272
|
+
import { StringDecoder } from "node:string_decoder";
|
|
36273
|
+
async function readFileRangeAsync(filePath, startLine, endLine, lineOffsetIn, lineChunkSize = LINE_CHUNK_SIZE) {
|
|
36274
|
+
const fileSize = (await fs35.promises.stat(filePath)).size;
|
|
36275
|
+
const fd = await fs35.promises.open(filePath, "r");
|
|
36099
36276
|
const bufSize = 64 * 1024;
|
|
36100
36277
|
const buf = Buffer.alloc(bufSize);
|
|
36101
36278
|
const decoder = new StringDecoder("utf8");
|
|
@@ -36106,9 +36283,18 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
36106
36283
|
let skipLine0Chars = typeof lineOffsetIn === "number" ? lineOffsetIn : 0;
|
|
36107
36284
|
let line0CharsReturned = 0;
|
|
36108
36285
|
let line0Accum = "";
|
|
36286
|
+
let bytesSinceYield = 0;
|
|
36109
36287
|
try {
|
|
36110
|
-
let
|
|
36111
|
-
while (!done
|
|
36288
|
+
let position = 0;
|
|
36289
|
+
while (!done) {
|
|
36290
|
+
const { bytesRead } = await fd.read(buf, 0, bufSize, position);
|
|
36291
|
+
if (bytesRead === 0) break;
|
|
36292
|
+
position += bytesRead;
|
|
36293
|
+
bytesSinceYield += bytesRead;
|
|
36294
|
+
if (bytesSinceYield >= READ_RANGE_YIELD_EVERY_BYTES) {
|
|
36295
|
+
await yieldToEventLoop();
|
|
36296
|
+
bytesSinceYield = 0;
|
|
36297
|
+
}
|
|
36112
36298
|
const text = partial2 + decoder.write(buf.subarray(0, bytesRead));
|
|
36113
36299
|
partial2 = "";
|
|
36114
36300
|
let lineStart = 0;
|
|
@@ -36243,39 +36429,132 @@ function readFileRange(filePath, startLine, endLine, lineOffsetIn, lineChunkSize
|
|
|
36243
36429
|
}
|
|
36244
36430
|
return { content: resultLines.join("\n"), size: fileSize };
|
|
36245
36431
|
} finally {
|
|
36246
|
-
|
|
36432
|
+
await fd.close();
|
|
36247
36433
|
}
|
|
36248
36434
|
}
|
|
36249
|
-
|
|
36435
|
+
|
|
36436
|
+
// src/files/read-file/read-file-buffer-full-async.ts
|
|
36437
|
+
import fs36 from "node:fs";
|
|
36438
|
+
var READ_CHUNK_BYTES = 256 * 1024;
|
|
36439
|
+
async function readFileBufferFullAsync(filePath) {
|
|
36440
|
+
const stat2 = await fs36.promises.stat(filePath);
|
|
36441
|
+
const fd = await fs36.promises.open(filePath, "r");
|
|
36442
|
+
const chunks = [];
|
|
36443
|
+
let position = 0;
|
|
36444
|
+
let bytesSinceYield = 0;
|
|
36250
36445
|
try {
|
|
36251
|
-
|
|
36446
|
+
while (position < stat2.size) {
|
|
36447
|
+
const buf = Buffer.alloc(Math.min(READ_CHUNK_BYTES, stat2.size - position));
|
|
36448
|
+
const { bytesRead } = await fd.read(buf, 0, buf.length, position);
|
|
36449
|
+
if (bytesRead === 0) break;
|
|
36450
|
+
chunks.push(buf.subarray(0, bytesRead));
|
|
36451
|
+
position += bytesRead;
|
|
36452
|
+
bytesSinceYield += bytesRead;
|
|
36453
|
+
if (bytesSinceYield >= READ_RANGE_YIELD_EVERY_BYTES) {
|
|
36454
|
+
await yieldToEventLoop();
|
|
36455
|
+
bytesSinceYield = 0;
|
|
36456
|
+
}
|
|
36457
|
+
}
|
|
36458
|
+
} finally {
|
|
36459
|
+
await fd.close();
|
|
36460
|
+
}
|
|
36461
|
+
return { buffer: Buffer.concat(chunks), size: stat2.size };
|
|
36462
|
+
}
|
|
36463
|
+
|
|
36464
|
+
// src/files/read-file/read-file-full-async.ts
|
|
36465
|
+
async function readFileFullAsync(filePath) {
|
|
36466
|
+
const { buffer, size } = await readFileBufferFullAsync(filePath);
|
|
36467
|
+
const raw = buffer.toString("utf8");
|
|
36468
|
+
const lines = raw.split(/\r?\n/);
|
|
36469
|
+
return { content: raw, totalLines: lines.length, size };
|
|
36470
|
+
}
|
|
36471
|
+
|
|
36472
|
+
// src/files/read-file/guess-mime-type.ts
|
|
36473
|
+
var MIME_BY_EXT = {
|
|
36474
|
+
png: "image/png",
|
|
36475
|
+
jpg: "image/jpeg",
|
|
36476
|
+
jpeg: "image/jpeg",
|
|
36477
|
+
gif: "image/gif",
|
|
36478
|
+
bmp: "image/bmp",
|
|
36479
|
+
ico: "image/x-icon",
|
|
36480
|
+
webp: "image/webp",
|
|
36481
|
+
avif: "image/avif",
|
|
36482
|
+
svg: "image/svg+xml",
|
|
36483
|
+
pdf: "application/pdf",
|
|
36484
|
+
json: "application/json",
|
|
36485
|
+
html: "text/html",
|
|
36486
|
+
htm: "text/html",
|
|
36487
|
+
css: "text/css",
|
|
36488
|
+
js: "text/javascript",
|
|
36489
|
+
mjs: "text/javascript",
|
|
36490
|
+
ts: "text/typescript",
|
|
36491
|
+
txt: "text/plain",
|
|
36492
|
+
md: "text/markdown",
|
|
36493
|
+
xml: "application/xml",
|
|
36494
|
+
zip: "application/zip",
|
|
36495
|
+
gz: "application/gzip",
|
|
36496
|
+
wasm: "application/wasm"
|
|
36497
|
+
};
|
|
36498
|
+
function guessMimeType(filePath) {
|
|
36499
|
+
const ext = filePath.split(".").pop()?.toLowerCase() ?? "";
|
|
36500
|
+
return MIME_BY_EXT[ext] ?? "application/octet-stream";
|
|
36501
|
+
}
|
|
36502
|
+
|
|
36503
|
+
// src/files/read-file/read-file-binary-full-async.ts
|
|
36504
|
+
async function readFileBinaryFullAsync(filePath) {
|
|
36505
|
+
const { buffer, size } = await readFileBufferFullAsync(filePath);
|
|
36506
|
+
return {
|
|
36507
|
+
content: buffer.toString("base64"),
|
|
36508
|
+
size,
|
|
36509
|
+
mimeType: guessMimeType(filePath)
|
|
36510
|
+
};
|
|
36511
|
+
}
|
|
36512
|
+
|
|
36513
|
+
// src/files/read-file/index.ts
|
|
36514
|
+
async function readFileAsync(relativePath, startLine, endLine, lineOffset, lineChunkSize = LINE_CHUNK_SIZE, sessionParentPath = getBridgeRoot(), encoding = "utf8") {
|
|
36515
|
+
await yieldToEventLoop();
|
|
36516
|
+
try {
|
|
36517
|
+
const result = await resolveFilePathAsync(relativePath, sessionParentPath);
|
|
36252
36518
|
if (typeof result === "object") return result;
|
|
36519
|
+
const resolvedPath = result;
|
|
36253
36520
|
const hasRange = typeof startLine === "number" && typeof endLine === "number";
|
|
36521
|
+
if (encoding === "base64") {
|
|
36522
|
+
if (hasRange) return { error: "base64 encoding requires a full file read (no line range)" };
|
|
36523
|
+
const read2 = await readFileBinaryFullAsync(resolvedPath);
|
|
36524
|
+
return { ...read2, resolvedPath };
|
|
36525
|
+
}
|
|
36254
36526
|
if (hasRange) {
|
|
36255
|
-
return
|
|
36527
|
+
return readFileRangeAsync(resolvedPath, startLine, endLine, lineOffset, lineChunkSize);
|
|
36256
36528
|
}
|
|
36257
|
-
const
|
|
36258
|
-
|
|
36259
|
-
const lines = raw.split(/\r?\n/);
|
|
36260
|
-
return { content: raw, totalLines: lines.length, size: stat2.size };
|
|
36529
|
+
const read = await readFileFullAsync(resolvedPath);
|
|
36530
|
+
return { ...read, resolvedPath };
|
|
36261
36531
|
} catch (err) {
|
|
36262
36532
|
return { error: err instanceof Error ? err.message : String(err) };
|
|
36263
36533
|
}
|
|
36264
36534
|
}
|
|
36265
|
-
|
|
36266
|
-
|
|
36267
|
-
|
|
36535
|
+
|
|
36536
|
+
// src/files/resolve-file-browser-session-parent.ts
|
|
36537
|
+
function resolveFileBrowserSessionParent(sessionWorktreeManager, sessionId) {
|
|
36538
|
+
const sid = sessionId?.trim();
|
|
36539
|
+
if (sid) {
|
|
36540
|
+
sessionWorktreeManager.ensureRepoCheckoutPathsForSession(sid);
|
|
36541
|
+
const worktreeRoot = sessionWorktreeManager.getSessionWorktreeRootForSession(sid);
|
|
36542
|
+
if (worktreeRoot) return worktreeRoot;
|
|
36543
|
+
}
|
|
36544
|
+
return getBridgeRoot();
|
|
36268
36545
|
}
|
|
36269
36546
|
|
|
36270
36547
|
// src/files/handle-file-browser-search.ts
|
|
36271
36548
|
import path36 from "node:path";
|
|
36272
36549
|
var SEARCH_LIMIT = 100;
|
|
36273
|
-
function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
36550
|
+
function handleFileBrowserSearch(msg, socket, e2ee, sessionWorktreeManager) {
|
|
36274
36551
|
void (async () => {
|
|
36275
36552
|
await yieldToEventLoop();
|
|
36276
36553
|
const q = typeof msg.q === "string" ? msg.q : "";
|
|
36277
|
-
const
|
|
36278
|
-
|
|
36554
|
+
const sessionParentPath = path36.resolve(
|
|
36555
|
+
sessionWorktreeManager != null ? resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : getBridgeRoot()
|
|
36556
|
+
);
|
|
36557
|
+
if (!await bridgeFileIndexIsPopulated(sessionParentPath)) {
|
|
36279
36558
|
const payload2 = {
|
|
36280
36559
|
type: "file_browser_search_response",
|
|
36281
36560
|
id: msg.id,
|
|
@@ -36285,7 +36564,7 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
|
36285
36564
|
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload2, ["paths"]) : payload2);
|
|
36286
36565
|
return;
|
|
36287
36566
|
}
|
|
36288
|
-
const results = await searchBridgeFilePathsAsync(
|
|
36567
|
+
const results = await searchBridgeFilePathsAsync(sessionParentPath, q, SEARCH_LIMIT);
|
|
36289
36568
|
const payload = {
|
|
36290
36569
|
type: "file_browser_search_response",
|
|
36291
36570
|
id: msg.id,
|
|
@@ -36295,9 +36574,9 @@ function handleFileBrowserSearch(msg, socket, e2ee) {
|
|
|
36295
36574
|
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["paths"]) : payload);
|
|
36296
36575
|
})();
|
|
36297
36576
|
}
|
|
36298
|
-
function triggerFileIndexBuild() {
|
|
36577
|
+
function triggerFileIndexBuild(sessionParentPath = getBridgeRoot()) {
|
|
36299
36578
|
setImmediate(() => {
|
|
36300
|
-
void ensureFileIndexAsync(
|
|
36579
|
+
void ensureFileIndexAsync(sessionParentPath).catch((e) => {
|
|
36301
36580
|
console.error("[file-index] Background build failed:", e);
|
|
36302
36581
|
});
|
|
36303
36582
|
});
|
|
@@ -36307,18 +36586,19 @@ function triggerFileIndexBuild() {
|
|
|
36307
36586
|
function sendFileBrowserMessage(socket, e2ee, payload) {
|
|
36308
36587
|
sendWsMessage(socket, e2ee ? e2ee.encryptFields(payload, ["entries", "content", "totalLines", "size", "lineOffset"]) : payload);
|
|
36309
36588
|
}
|
|
36310
|
-
function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
36589
|
+
function handleFileBrowserRequest(msg, socket, e2ee, sessionWorktreeManager) {
|
|
36311
36590
|
void (async () => {
|
|
36312
36591
|
const reqPath = msg.path.replace(/^\/+/, "") || ".";
|
|
36313
36592
|
const op = msg.op === "read" ? "read" : "list";
|
|
36593
|
+
const sessionParentPath = sessionWorktreeManager != null ? resolveFileBrowserSessionParent(sessionWorktreeManager, msg.sessionId) : void 0;
|
|
36314
36594
|
if (op === "list") {
|
|
36315
|
-
const result = await listDirAsync(reqPath);
|
|
36595
|
+
const result = await listDirAsync(reqPath, sessionParentPath);
|
|
36316
36596
|
if ("error" in result) {
|
|
36317
36597
|
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
36318
36598
|
} else {
|
|
36319
36599
|
sendFileBrowserMessage(socket, e2ee, { type: "file_browser_response", id: msg.id, entries: result.entries });
|
|
36320
36600
|
if (reqPath === "." || reqPath === "") {
|
|
36321
|
-
triggerFileIndexBuild();
|
|
36601
|
+
triggerFileIndexBuild(sessionParentPath);
|
|
36322
36602
|
}
|
|
36323
36603
|
}
|
|
36324
36604
|
} else {
|
|
@@ -36326,7 +36606,16 @@ function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
|
36326
36606
|
const endLine = typeof msg.endLine === "number" ? msg.endLine : void 0;
|
|
36327
36607
|
const lineOffset = typeof msg.lineOffset === "number" ? msg.lineOffset : void 0;
|
|
36328
36608
|
const lineChunkSize = typeof msg.lineChunkSize === "number" ? msg.lineChunkSize : void 0;
|
|
36329
|
-
const
|
|
36609
|
+
const encoding = msg.encoding === "base64" ? "base64" : "utf8";
|
|
36610
|
+
const result = await readFileAsync(
|
|
36611
|
+
reqPath,
|
|
36612
|
+
startLine,
|
|
36613
|
+
endLine,
|
|
36614
|
+
lineOffset,
|
|
36615
|
+
lineChunkSize,
|
|
36616
|
+
sessionParentPath,
|
|
36617
|
+
encoding
|
|
36618
|
+
);
|
|
36330
36619
|
if ("error" in result) {
|
|
36331
36620
|
sendWsMessage(socket, { type: "file_browser_response", id: msg.id, error: result.error });
|
|
36332
36621
|
} else {
|
|
@@ -36338,6 +36627,8 @@ function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
|
36338
36627
|
size: result.size
|
|
36339
36628
|
};
|
|
36340
36629
|
if (result.lineOffset != null) payload.lineOffset = result.lineOffset;
|
|
36630
|
+
if (result.mimeType != null) payload.mimeType = result.mimeType;
|
|
36631
|
+
if (result.resolvedPath != null) payload.resolvedPath = result.resolvedPath;
|
|
36341
36632
|
sendFileBrowserMessage(socket, e2ee, payload);
|
|
36342
36633
|
}
|
|
36343
36634
|
}
|
|
@@ -36345,21 +36636,27 @@ function handleFileBrowserRequest(msg, socket, e2ee) {
|
|
|
36345
36636
|
}
|
|
36346
36637
|
|
|
36347
36638
|
// src/routing/handlers/file-browser-messages.ts
|
|
36348
|
-
function handleFileBrowserRequestMessage(msg, { getWs, e2ee }) {
|
|
36639
|
+
function handleFileBrowserRequestMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
36349
36640
|
if (typeof msg.id !== "string" || typeof msg.path !== "string") return;
|
|
36350
36641
|
const socket = getWs();
|
|
36351
36642
|
if (!socket) return;
|
|
36352
36643
|
handleFileBrowserRequest(
|
|
36353
36644
|
msg,
|
|
36354
36645
|
socket,
|
|
36355
|
-
e2ee
|
|
36646
|
+
e2ee,
|
|
36647
|
+
sessionWorktreeManager
|
|
36356
36648
|
);
|
|
36357
36649
|
}
|
|
36358
|
-
function handleFileBrowserSearchMessage(msg, { getWs, e2ee }) {
|
|
36650
|
+
function handleFileBrowserSearchMessage(msg, { getWs, e2ee, sessionWorktreeManager }) {
|
|
36359
36651
|
if (typeof msg.id !== "string") return;
|
|
36360
36652
|
const socket = getWs();
|
|
36361
36653
|
if (!socket) return;
|
|
36362
|
-
handleFileBrowserSearch(
|
|
36654
|
+
handleFileBrowserSearch(
|
|
36655
|
+
msg,
|
|
36656
|
+
socket,
|
|
36657
|
+
e2ee,
|
|
36658
|
+
sessionWorktreeManager
|
|
36659
|
+
);
|
|
36363
36660
|
}
|
|
36364
36661
|
|
|
36365
36662
|
// src/routing/handlers/skill-layout-request.ts
|
|
@@ -36373,7 +36670,7 @@ function handleSkillLayoutRequest(msg, deps) {
|
|
|
36373
36670
|
}
|
|
36374
36671
|
|
|
36375
36672
|
// src/skills/install-remote-skills.ts
|
|
36376
|
-
import
|
|
36673
|
+
import fs37 from "node:fs";
|
|
36377
36674
|
import path37 from "node:path";
|
|
36378
36675
|
function installRemoteSkills(cwd, targetDir, items) {
|
|
36379
36676
|
const installed2 = [];
|
|
@@ -36389,11 +36686,11 @@ function installRemoteSkills(cwd, targetDir, items) {
|
|
|
36389
36686
|
for (const f of item.files) {
|
|
36390
36687
|
if (typeof f.path !== "string" || !f.text && !f.base64) continue;
|
|
36391
36688
|
const dest = path37.join(skillDir, f.path);
|
|
36392
|
-
|
|
36689
|
+
fs37.mkdirSync(path37.dirname(dest), { recursive: true });
|
|
36393
36690
|
if (f.text !== void 0) {
|
|
36394
|
-
|
|
36691
|
+
fs37.writeFileSync(dest, f.text, "utf8");
|
|
36395
36692
|
} else if (f.base64) {
|
|
36396
|
-
|
|
36693
|
+
fs37.writeFileSync(dest, Buffer.from(f.base64, "base64"));
|
|
36397
36694
|
}
|
|
36398
36695
|
}
|
|
36399
36696
|
installed2.push({
|
|
@@ -36551,7 +36848,7 @@ var handleSessionDiscardedMessage = (msg, deps) => {
|
|
|
36551
36848
|
};
|
|
36552
36849
|
|
|
36553
36850
|
// src/routing/handlers/revert-turn-snapshot.ts
|
|
36554
|
-
import * as
|
|
36851
|
+
import * as fs38 from "node:fs";
|
|
36555
36852
|
var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
36556
36853
|
const id = typeof msg.id === "string" ? msg.id : "";
|
|
36557
36854
|
const sessionId = typeof msg.sessionId === "string" ? msg.sessionId : "";
|
|
@@ -36564,7 +36861,7 @@ var handleRevertTurnSnapshotMessage = (msg, deps) => {
|
|
|
36564
36861
|
const agentBase = sessionWorktreeManager.getSessionWorktreeRootForSession(sessionId) ?? getBridgeRoot();
|
|
36565
36862
|
const file2 = snapshotFilePath(agentBase, turnId);
|
|
36566
36863
|
try {
|
|
36567
|
-
await
|
|
36864
|
+
await fs38.promises.access(file2, fs38.constants.F_OK);
|
|
36568
36865
|
} catch {
|
|
36569
36866
|
sendWsMessage(s, {
|
|
36570
36867
|
type: "revert_turn_snapshot_result",
|