runwork 0.26.0 → 0.27.0
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/index.js +1136 -477
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -8205,7 +8205,7 @@ function createKeyboardListener() {
|
|
|
8205
8205
|
}
|
|
8206
8206
|
|
|
8207
8207
|
// src/generated/version.ts
|
|
8208
|
-
var VERSION = "0.
|
|
8208
|
+
var VERSION = "0.27.0";
|
|
8209
8209
|
|
|
8210
8210
|
// src/commands/dev.ts
|
|
8211
8211
|
var exports_dev = {};
|
|
@@ -9184,6 +9184,14 @@ function expandWindowsPathTemplate(path2, resolved) {
|
|
|
9184
9184
|
}
|
|
9185
9185
|
return { path: path2, needsHomeJoin: !/^([A-Za-z]:[\\/]|\\\\|\/)/.test(path2) };
|
|
9186
9186
|
}
|
|
9187
|
+
function parseConfigDeclaredPath(text2, key) {
|
|
9188
|
+
const escapedKey = key.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
9189
|
+
const match = new RegExp(`^\\s*${escapedKey}\\s*=\\s*"((?:[^"\\\\]|\\\\.)*)"`, "m").exec(text2);
|
|
9190
|
+
if (!match)
|
|
9191
|
+
return null;
|
|
9192
|
+
const path2 = match[1].replace(/\\(.)/g, "$1");
|
|
9193
|
+
return path2 || null;
|
|
9194
|
+
}
|
|
9187
9195
|
var PATH_REFRESH_FAILED_MARKER = "__runwork_path_refresh_failed__", WINDOWS_PATH_REFRESH, COMMAND_NOT_FOUND_EXIT_CODES, WINDOWS_PATH_PLACEHOLDERS;
|
|
9188
9196
|
var init_detection_probes = __esm(() => {
|
|
9189
9197
|
WINDOWS_PATH_REFRESH = "try { $env:Path = [Environment]::GetEnvironmentVariable('Path','Machine') + ';' + " + "[Environment]::GetEnvironmentVariable('Path','User') + ';' + $env:Path } " + `catch { Write-Output '${PATH_REFRESH_FAILED_MARKER}' }; `;
|
|
@@ -9605,6 +9613,9 @@ function getAgent(slug) {
|
|
|
9605
9613
|
function getAgents() {
|
|
9606
9614
|
return AGENT_REGISTRY;
|
|
9607
9615
|
}
|
|
9616
|
+
function getDetectableAgents() {
|
|
9617
|
+
return AGENT_REGISTRY.filter((a) => a.detection);
|
|
9618
|
+
}
|
|
9608
9619
|
function isConnectOnlyAgent(agent) {
|
|
9609
9620
|
if (!agent)
|
|
9610
9621
|
return false;
|
|
@@ -9633,11 +9644,15 @@ function resolveAgentCli(agent) {
|
|
|
9633
9644
|
return;
|
|
9634
9645
|
return detectionBinaryTarget(agent.detection);
|
|
9635
9646
|
}
|
|
9636
|
-
var CLAUDE_CODE_NATIVE_INSTALL_PATHS, CHATGPT_SECURITY_SETTINGS_URL = "https://chatgpt.com/plugins#settings/Security", CHATGPT_CREATE_CONNECTOR_URL = "https://chatgpt.com/plugins#settings/Connectors?create-connector=true&redirectAfter=%2Fplugins", AGENT_REGISTRY, slugIndex, nameIndex, CUSTOM_ADAPTER_SLUGS, getRegistryAgent, getRegistryAgents;
|
|
9647
|
+
var CLAUDE_CODE_NATIVE_INSTALL_PATHS, CODEX_CONFIG_FILE = ".codex/config.toml", CODEX_BUNDLED_CLI_PATHS, CHATGPT_SECURITY_SETTINGS_URL = "https://chatgpt.com/plugins#settings/Security", CHATGPT_CREATE_CONNECTOR_URL = "https://chatgpt.com/plugins#settings/Connectors?create-connector=true&redirectAfter=%2Fplugins", AGENT_REGISTRY, slugIndex, nameIndex, CUSTOM_ADAPTER_SLUGS, getRegistryAgent, getRegistryAgents;
|
|
9637
9648
|
var init_registry_data = __esm(() => {
|
|
9638
9649
|
CLAUDE_CODE_NATIVE_INSTALL_PATHS = [
|
|
9639
9650
|
{ macos: ".local/bin/claude", linux: ".local/bin/claude", windows: ".local/bin/claude.exe" }
|
|
9640
9651
|
];
|
|
9652
|
+
CODEX_BUNDLED_CLI_PATHS = [
|
|
9653
|
+
{ macos: "/Applications/ChatGPT.app/Contents/Resources/codex" },
|
|
9654
|
+
{ macos: "/Applications/Codex.app/Contents/Resources/codex" }
|
|
9655
|
+
];
|
|
9641
9656
|
AGENT_REGISTRY = [
|
|
9642
9657
|
{
|
|
9643
9658
|
slug: "claude-code",
|
|
@@ -9869,8 +9884,18 @@ var init_registry_data = __esm(() => {
|
|
|
9869
9884
|
name: "Codex CLI",
|
|
9870
9885
|
description: "AI in your terminal by OpenAI, great for coding, debugging, and automating dev tasks",
|
|
9871
9886
|
category: "cli",
|
|
9872
|
-
detection: {
|
|
9873
|
-
|
|
9887
|
+
detection: {
|
|
9888
|
+
method: "any",
|
|
9889
|
+
target: [
|
|
9890
|
+
{ method: "binary", target: "codex" },
|
|
9891
|
+
{
|
|
9892
|
+
method: "config-value",
|
|
9893
|
+
target: { file: CODEX_CONFIG_FILE, key: "CODEX_CLI_PATH" }
|
|
9894
|
+
},
|
|
9895
|
+
...CODEX_BUNDLED_CLI_PATHS.map((target) => ({ method: "path", target }))
|
|
9896
|
+
]
|
|
9897
|
+
},
|
|
9898
|
+
launch: { cli: "codex", cliAcceptsPrompt: true, cliWellKnownPaths: CODEX_BUNDLED_CLI_PATHS },
|
|
9874
9899
|
logo: "codex",
|
|
9875
9900
|
downloadUrl: "https://learn.chatgpt.com/docs/codex/cli",
|
|
9876
9901
|
install: {
|
|
@@ -9907,6 +9932,7 @@ var init_registry_data = __esm(() => {
|
|
|
9907
9932
|
launch: { url: "https://chatgpt.com/?prompt={prompt}" },
|
|
9908
9933
|
logo: "openai",
|
|
9909
9934
|
downloadUrl: "https://chatgpt.com",
|
|
9935
|
+
suggestsCli: "codex",
|
|
9910
9936
|
firstClass: true,
|
|
9911
9937
|
resumeCapability: {
|
|
9912
9938
|
mode: "url-prompt",
|
|
@@ -9963,6 +9989,7 @@ var init_registry_data = __esm(() => {
|
|
|
9963
9989
|
]
|
|
9964
9990
|
},
|
|
9965
9991
|
launch: { app: { macos: "ChatGPT Classic", windows: "ChatGPT Classic" }, bundleId: { macos: "com.openai.chat" }, appxPackage: "OpenAI.ChatGPT", url: "https://chatgpt.com/?prompt={prompt}" },
|
|
9992
|
+
suggestsCli: "codex",
|
|
9966
9993
|
logo: "openai",
|
|
9967
9994
|
downloadUrl: "https://chatgpt.com/download",
|
|
9968
9995
|
downloadUrls: {
|
|
@@ -10208,12 +10235,145 @@ var init_registry_data = __esm(() => {
|
|
|
10208
10235
|
getRegistryAgents = getAgents;
|
|
10209
10236
|
});
|
|
10210
10237
|
|
|
10238
|
+
// src/agents/detection.ts
|
|
10239
|
+
import { execFile } from "child_process";
|
|
10240
|
+
import { existsSync as existsSync26, readFileSync as readFileSync23 } from "fs";
|
|
10241
|
+
import { homedir as homedir6, platform as platform2 } from "os";
|
|
10242
|
+
import { join as join22 } from "path";
|
|
10243
|
+
import { promisify } from "util";
|
|
10244
|
+
function isWindows() {
|
|
10245
|
+
return platform2() === "win32";
|
|
10246
|
+
}
|
|
10247
|
+
function toList(value) {
|
|
10248
|
+
return Array.isArray(value) ? value : [value];
|
|
10249
|
+
}
|
|
10250
|
+
async function runPowerShell(script) {
|
|
10251
|
+
const execFileAsync = promisify(execFile);
|
|
10252
|
+
try {
|
|
10253
|
+
await execFileAsync("powershell", ["-NoProfile", "-Command", script]);
|
|
10254
|
+
return true;
|
|
10255
|
+
} catch {
|
|
10256
|
+
return false;
|
|
10257
|
+
}
|
|
10258
|
+
}
|
|
10259
|
+
function resolveDetectionPath(target) {
|
|
10260
|
+
const resolved = resolvePlatformString(target);
|
|
10261
|
+
if (!resolved)
|
|
10262
|
+
return null;
|
|
10263
|
+
const expanded = expandWindowsPathTemplate(resolved, {
|
|
10264
|
+
"%APPDATA%": process.env.APPDATA,
|
|
10265
|
+
"%LOCALAPPDATA%": process.env.LOCALAPPDATA,
|
|
10266
|
+
"%ProgramFiles%": process.env.ProgramFiles
|
|
10267
|
+
});
|
|
10268
|
+
return expanded.needsHomeJoin ? join22(homedir6(), expanded.path) : expanded.path;
|
|
10269
|
+
}
|
|
10270
|
+
function checkPath(target) {
|
|
10271
|
+
const absolute = resolveDetectionPath(target);
|
|
10272
|
+
if (!absolute)
|
|
10273
|
+
return null;
|
|
10274
|
+
return existsSync26(absolute) ? absolute : null;
|
|
10275
|
+
}
|
|
10276
|
+
function checkConfigDeclaredPath(target) {
|
|
10277
|
+
const configPath = resolveDetectionPath(target.file);
|
|
10278
|
+
if (!configPath)
|
|
10279
|
+
return null;
|
|
10280
|
+
let text2;
|
|
10281
|
+
try {
|
|
10282
|
+
if (!existsSync26(configPath))
|
|
10283
|
+
return null;
|
|
10284
|
+
text2 = readFileSync23(configPath, "utf-8");
|
|
10285
|
+
} catch {
|
|
10286
|
+
return null;
|
|
10287
|
+
}
|
|
10288
|
+
const declared = parseConfigDeclaredPath(text2, target.key);
|
|
10289
|
+
return declared && existsSync26(declared) ? declared : null;
|
|
10290
|
+
}
|
|
10291
|
+
async function checkMacosBundleId(target) {
|
|
10292
|
+
if (platform2() !== "darwin")
|
|
10293
|
+
return false;
|
|
10294
|
+
const execFileAsync = promisify(execFile);
|
|
10295
|
+
for (const id of toList(target)) {
|
|
10296
|
+
if (!isValidBundleId(id))
|
|
10297
|
+
continue;
|
|
10298
|
+
try {
|
|
10299
|
+
await execFileAsync("sh", ["-c", macosBundleIdProbeScript(id)]);
|
|
10300
|
+
return true;
|
|
10301
|
+
} catch {}
|
|
10302
|
+
}
|
|
10303
|
+
return false;
|
|
10304
|
+
}
|
|
10305
|
+
async function checkWindowsAppxPackage(target) {
|
|
10306
|
+
if (!isWindows())
|
|
10307
|
+
return false;
|
|
10308
|
+
const probes = toList(target).map((pkg) => runPowerShell(appxPackageProbeScript(pkg)));
|
|
10309
|
+
const results = await Promise.all(probes);
|
|
10310
|
+
return results.some(Boolean);
|
|
10311
|
+
}
|
|
10312
|
+
async function checkWindowsStartApp(target) {
|
|
10313
|
+
if (!isWindows())
|
|
10314
|
+
return false;
|
|
10315
|
+
const probes = toList(target).map((pattern) => runPowerShell(startAppProbeScript(pattern)));
|
|
10316
|
+
const results = await Promise.all(probes);
|
|
10317
|
+
return results.some(Boolean);
|
|
10318
|
+
}
|
|
10319
|
+
async function runAgentDetectionDetailed(detection) {
|
|
10320
|
+
switch (detection.method) {
|
|
10321
|
+
case "binary": {
|
|
10322
|
+
const target = resolvePlatformString(detection.target);
|
|
10323
|
+
const resolved = target ? whichBinary(target) : null;
|
|
10324
|
+
return resolved ? { detected: true, via: "binary", resolvedPath: resolved } : NOT_DETECTED;
|
|
10325
|
+
}
|
|
10326
|
+
case "path": {
|
|
10327
|
+
const resolved = checkPath(detection.target);
|
|
10328
|
+
return resolved ? { detected: true, via: "path", resolvedPath: resolved } : NOT_DETECTED;
|
|
10329
|
+
}
|
|
10330
|
+
case "config-value": {
|
|
10331
|
+
const resolved = checkConfigDeclaredPath(detection.target);
|
|
10332
|
+
return resolved ? { detected: true, via: "config-value", resolvedPath: resolved } : NOT_DETECTED;
|
|
10333
|
+
}
|
|
10334
|
+
case "windows-appx":
|
|
10335
|
+
return await checkWindowsAppxPackage(detection.target) ? { detected: true, via: "windows-appx" } : NOT_DETECTED;
|
|
10336
|
+
case "windows-start-app":
|
|
10337
|
+
return await checkWindowsStartApp(detection.target) ? { detected: true, via: "windows-start-app" } : NOT_DETECTED;
|
|
10338
|
+
case "macos-bundle-id":
|
|
10339
|
+
return await checkMacosBundleId(detection.target) ? { detected: true, via: "macos-bundle-id" } : NOT_DETECTED;
|
|
10340
|
+
case "any": {
|
|
10341
|
+
const probes = await Promise.all(detection.target.map((p) => runAgentDetectionDetailed(p)));
|
|
10342
|
+
return probes.find((p) => p.detected) ?? NOT_DETECTED;
|
|
10343
|
+
}
|
|
10344
|
+
case "always":
|
|
10345
|
+
return { detected: true, via: "always" };
|
|
10346
|
+
default:
|
|
10347
|
+
return NOT_DETECTED;
|
|
10348
|
+
}
|
|
10349
|
+
}
|
|
10350
|
+
async function runAgentDetection(detection) {
|
|
10351
|
+
return (await runAgentDetectionDetailed(detection)).detected;
|
|
10352
|
+
}
|
|
10353
|
+
|
|
10354
|
+
class RegistryDetectedAdapter {
|
|
10355
|
+
async detect() {
|
|
10356
|
+
const def = getRegistryAgent(this.slug);
|
|
10357
|
+
if (!def)
|
|
10358
|
+
return false;
|
|
10359
|
+
return runAgentDetection(def.detection);
|
|
10360
|
+
}
|
|
10361
|
+
}
|
|
10362
|
+
var NOT_DETECTED;
|
|
10363
|
+
var init_detection = __esm(() => {
|
|
10364
|
+
init_which();
|
|
10365
|
+
init_registry_data();
|
|
10366
|
+
init_registry();
|
|
10367
|
+
init_detection_probes();
|
|
10368
|
+
NOT_DETECTED = { detected: false };
|
|
10369
|
+
});
|
|
10370
|
+
|
|
10211
10371
|
// src/agents/registry.ts
|
|
10212
|
-
import { platform as
|
|
10213
|
-
import { isAbsolute as
|
|
10214
|
-
import { existsSync as
|
|
10372
|
+
import { platform as platform3, homedir as homedir7 } from "os";
|
|
10373
|
+
import { isAbsolute as isAbsolute3, join as join23 } from "path";
|
|
10374
|
+
import { existsSync as existsSync27 } from "fs";
|
|
10215
10375
|
function getNodePlatform() {
|
|
10216
|
-
const p =
|
|
10376
|
+
const p = platform3();
|
|
10217
10377
|
if (p === "darwin")
|
|
10218
10378
|
return "macos";
|
|
10219
10379
|
if (p === "win32")
|
|
@@ -10230,7 +10390,7 @@ function resolveToAbsolute(ps, scope) {
|
|
|
10230
10390
|
const resolved = resolvePlatformString(ps);
|
|
10231
10391
|
if (!resolved)
|
|
10232
10392
|
return;
|
|
10233
|
-
return scope === "global" ?
|
|
10393
|
+
return scope === "global" ? join23(homedir7(), resolved) : join23(process.cwd(), resolved);
|
|
10234
10394
|
}
|
|
10235
10395
|
function resolveAgentCliCommand(slug) {
|
|
10236
10396
|
const agent = getAgent(slug);
|
|
@@ -10239,19 +10399,40 @@ function resolveAgentCliCommand(slug) {
|
|
|
10239
10399
|
return null;
|
|
10240
10400
|
if (whichBinary(cli))
|
|
10241
10401
|
return cli;
|
|
10402
|
+
const declared = vendorDeclaredCliPath(slug);
|
|
10403
|
+
if (declared)
|
|
10404
|
+
return declared;
|
|
10242
10405
|
for (const candidate of agent?.launch?.cliWellKnownPaths ?? []) {
|
|
10243
10406
|
const resolved = resolvePlatformString(candidate);
|
|
10244
10407
|
if (!resolved)
|
|
10245
10408
|
continue;
|
|
10246
|
-
const absolute =
|
|
10247
|
-
if (
|
|
10409
|
+
const absolute = isAbsolute3(resolved) ? resolved : join23(homedir7(), resolved);
|
|
10410
|
+
if (existsSync27(absolute))
|
|
10248
10411
|
return absolute;
|
|
10249
10412
|
}
|
|
10250
10413
|
return null;
|
|
10251
10414
|
}
|
|
10415
|
+
function configValueMatchers(detection) {
|
|
10416
|
+
if (!detection)
|
|
10417
|
+
return [];
|
|
10418
|
+
if (detection.method === "config-value")
|
|
10419
|
+
return [detection.target];
|
|
10420
|
+
if (detection.method === "any")
|
|
10421
|
+
return detection.target.flatMap(configValueMatchers);
|
|
10422
|
+
return [];
|
|
10423
|
+
}
|
|
10424
|
+
function vendorDeclaredCliPath(slug) {
|
|
10425
|
+
for (const matcher of configValueMatchers(getAgent(slug)?.detection)) {
|
|
10426
|
+
const resolved = checkConfigDeclaredPath(matcher);
|
|
10427
|
+
if (resolved)
|
|
10428
|
+
return resolved;
|
|
10429
|
+
}
|
|
10430
|
+
return null;
|
|
10431
|
+
}
|
|
10252
10432
|
var init_registry = __esm(() => {
|
|
10253
10433
|
init_which();
|
|
10254
10434
|
init_registry_data();
|
|
10435
|
+
init_detection();
|
|
10255
10436
|
init_registry_data();
|
|
10256
10437
|
});
|
|
10257
10438
|
|
|
@@ -11092,6 +11273,8 @@ function scanClaudeJsonlHead(head) {
|
|
|
11092
11273
|
result.firstTimestamp = o.timestamp;
|
|
11093
11274
|
if (!result.cwd && typeof o.cwd === "string")
|
|
11094
11275
|
result.cwd = o.cwd;
|
|
11276
|
+
if (!result.surface && typeof o.entrypoint === "string")
|
|
11277
|
+
result.surface = o.entrypoint;
|
|
11095
11278
|
if (!result.title && o.type === "ai-title" && typeof o.aiTitle === "string") {
|
|
11096
11279
|
result.title = titleFromText(o.aiTitle);
|
|
11097
11280
|
}
|
|
@@ -11117,7 +11300,7 @@ function scanClaudeJsonlHead(head) {
|
|
|
11117
11300
|
}
|
|
11118
11301
|
}
|
|
11119
11302
|
}
|
|
11120
|
-
if (result.title && result.firstTimestamp && result.cwd)
|
|
11303
|
+
if (result.title && result.firstTimestamp && result.cwd && result.surface)
|
|
11121
11304
|
break;
|
|
11122
11305
|
}
|
|
11123
11306
|
if (!result.title && firstUserText)
|
|
@@ -11146,6 +11329,8 @@ function scanCodexRolloutHead(head) {
|
|
|
11146
11329
|
result.cwd = p.cwd;
|
|
11147
11330
|
if (typeof p.id === "string" && !result.sessionId)
|
|
11148
11331
|
result.sessionId = p.id;
|
|
11332
|
+
if (typeof p.originator === "string" && !result.surface)
|
|
11333
|
+
result.surface = p.originator;
|
|
11149
11334
|
}
|
|
11150
11335
|
if (!result.title && o.type === "response_item" && p.type === "message" && p.role === "user" && Array.isArray(p.content)) {
|
|
11151
11336
|
for (const item of p.content) {
|
|
@@ -11245,23 +11430,23 @@ function skillNameFromPath(path2) {
|
|
|
11245
11430
|
}
|
|
11246
11431
|
|
|
11247
11432
|
// src/utils/trash.ts
|
|
11248
|
-
import { cpSync, existsSync as
|
|
11249
|
-
import { basename as basename2, dirname as dirname6, join as
|
|
11250
|
-
import { homedir as
|
|
11433
|
+
import { cpSync, existsSync as existsSync28, mkdirSync as mkdirSync13, readdirSync as readdirSync5, renameSync as renameSync3, rmSync as rmSync4, statSync as statSync3 } from "fs";
|
|
11434
|
+
import { basename as basename2, dirname as dirname6, join as join24 } from "path";
|
|
11435
|
+
import { homedir as homedir8 } from "os";
|
|
11251
11436
|
function trashRoot() {
|
|
11252
|
-
return
|
|
11437
|
+
return join24(homedir8(), ".runwork", "trash");
|
|
11253
11438
|
}
|
|
11254
11439
|
function batchDir(now) {
|
|
11255
11440
|
const stamp = now.toISOString().replace(/[:.]/g, "-");
|
|
11256
|
-
return
|
|
11441
|
+
return join24(trashRoot(), `${stamp}-${process.pid}`);
|
|
11257
11442
|
}
|
|
11258
11443
|
function pruneTrash(now = new Date) {
|
|
11259
11444
|
const root = trashRoot();
|
|
11260
|
-
if (!
|
|
11445
|
+
if (!existsSync28(root))
|
|
11261
11446
|
return;
|
|
11262
11447
|
const cutoff = now.getTime() - TRASH_RETENTION_DAYS * 24 * 60 * 60 * 1000;
|
|
11263
11448
|
for (const entry of readdirSync5(root)) {
|
|
11264
|
-
const dir =
|
|
11449
|
+
const dir = join24(root, entry);
|
|
11265
11450
|
try {
|
|
11266
11451
|
if (statSync3(dir).mtimeMs < cutoff)
|
|
11267
11452
|
rmSync4(dir, { recursive: true, force: true });
|
|
@@ -11269,7 +11454,7 @@ function pruneTrash(now = new Date) {
|
|
|
11269
11454
|
}
|
|
11270
11455
|
}
|
|
11271
11456
|
function moveToTrash(sourcePath, reason, now = new Date) {
|
|
11272
|
-
if (!
|
|
11457
|
+
if (!existsSync28(sourcePath))
|
|
11273
11458
|
return null;
|
|
11274
11459
|
if (!activeBatch || !activeBatch.startsWith(trashRoot())) {
|
|
11275
11460
|
activeBatch = batchDir(now);
|
|
@@ -11277,8 +11462,8 @@ function moveToTrash(sourcePath, reason, now = new Date) {
|
|
|
11277
11462
|
}
|
|
11278
11463
|
const parent = basename2(dirname6(sourcePath));
|
|
11279
11464
|
const grandparent = basename2(dirname6(dirname6(sourcePath)));
|
|
11280
|
-
const destDir =
|
|
11281
|
-
const dest =
|
|
11465
|
+
const destDir = join24(activeBatch, `${grandparent}__${parent}`.replace(/[^a-zA-Z0-9._-]/g, "-"));
|
|
11466
|
+
const dest = join24(destDir, basename2(sourcePath));
|
|
11282
11467
|
try {
|
|
11283
11468
|
mkdirSync13(destDir, { recursive: true });
|
|
11284
11469
|
try {
|
|
@@ -11290,7 +11475,7 @@ function moveToTrash(sourcePath, reason, now = new Date) {
|
|
|
11290
11475
|
} catch {
|
|
11291
11476
|
return null;
|
|
11292
11477
|
}
|
|
11293
|
-
const manifestPath =
|
|
11478
|
+
const manifestPath = join24(activeBatch, "manifest.json");
|
|
11294
11479
|
const manifest = readJsonOrNull(manifestPath) ?? { entries: [] };
|
|
11295
11480
|
manifest.entries.push({ from: sourcePath, to: dest, reason, at: now.toISOString() });
|
|
11296
11481
|
try {
|
|
@@ -11333,27 +11518,27 @@ function configHash(value) {
|
|
|
11333
11518
|
var init_hash = () => {};
|
|
11334
11519
|
|
|
11335
11520
|
// src/agents/utils/json-config.ts
|
|
11336
|
-
import { readFileSync as
|
|
11521
|
+
import { readFileSync as readFileSync24, writeFileSync as writeFileSync14, mkdirSync as mkdirSync14, existsSync as existsSync29 } from "fs";
|
|
11337
11522
|
import { dirname as dirname7 } from "path";
|
|
11338
11523
|
function isRunworkManagedKey(key) {
|
|
11339
11524
|
return key === RUNWORK_WORKSPACE_MCP_NAME || key.startsWith(RUNWORK_MCP_PREFIX) || key.startsWith(RUNWORK_MCP_PREFIX_LEGACY);
|
|
11340
11525
|
}
|
|
11341
11526
|
function readJsonConfig(filePath) {
|
|
11342
|
-
if (!
|
|
11527
|
+
if (!existsSync29(filePath))
|
|
11343
11528
|
return {};
|
|
11344
11529
|
try {
|
|
11345
|
-
return JSON.parse(
|
|
11530
|
+
return JSON.parse(readFileSync24(filePath, "utf-8"));
|
|
11346
11531
|
} catch (err) {
|
|
11347
11532
|
console.warn(` [config] ${filePath} is not valid JSON: ${err instanceof Error ? err.message : err}`);
|
|
11348
11533
|
return {};
|
|
11349
11534
|
}
|
|
11350
11535
|
}
|
|
11351
11536
|
function existingContentIsUnparseable(filePath) {
|
|
11352
|
-
if (!
|
|
11537
|
+
if (!existsSync29(filePath))
|
|
11353
11538
|
return { bad: false };
|
|
11354
11539
|
let raw;
|
|
11355
11540
|
try {
|
|
11356
|
-
raw =
|
|
11541
|
+
raw = readFileSync24(filePath, "utf-8");
|
|
11357
11542
|
} catch {
|
|
11358
11543
|
return { bad: false };
|
|
11359
11544
|
}
|
|
@@ -11375,7 +11560,7 @@ function writeJsonConfig(filePath, config) {
|
|
|
11375
11560
|
`);
|
|
11376
11561
|
}
|
|
11377
11562
|
function removeRunworkMcpServers(filePath, topKey) {
|
|
11378
|
-
if (!
|
|
11563
|
+
if (!existsSync29(filePath))
|
|
11379
11564
|
return false;
|
|
11380
11565
|
const config = readJsonConfig(filePath);
|
|
11381
11566
|
const existing = config[topKey] || {};
|
|
@@ -11430,25 +11615,25 @@ var init_json_config = __esm(() => {
|
|
|
11430
11615
|
});
|
|
11431
11616
|
|
|
11432
11617
|
// src/agents/utils/skill-removal.ts
|
|
11433
|
-
import { existsSync as
|
|
11434
|
-
import { join as
|
|
11618
|
+
import { existsSync as existsSync30, readdirSync as readdirSync6 } from "fs";
|
|
11619
|
+
import { join as join25 } from "path";
|
|
11435
11620
|
function removeMatchingSkillDirs(dir, allowed, reason = "skill removed") {
|
|
11436
|
-
if (!allowed.size || !
|
|
11621
|
+
if (!allowed.size || !existsSync30(dir))
|
|
11437
11622
|
return;
|
|
11438
11623
|
for (const entry of readdirSync6(dir)) {
|
|
11439
11624
|
if (!allowed.has(entry))
|
|
11440
11625
|
continue;
|
|
11441
|
-
moveToTrash(
|
|
11626
|
+
moveToTrash(join25(dir, entry), reason);
|
|
11442
11627
|
}
|
|
11443
11628
|
}
|
|
11444
11629
|
function removeMatchingSkillFiles(dir, allowed, suffix, reason = "skill removed") {
|
|
11445
|
-
if (!allowed.size || !
|
|
11630
|
+
if (!allowed.size || !existsSync30(dir))
|
|
11446
11631
|
return;
|
|
11447
11632
|
const names = new Set([...allowed].map((slug) => `${slug}${suffix}`));
|
|
11448
11633
|
for (const entry of readdirSync6(dir)) {
|
|
11449
11634
|
if (!names.has(entry))
|
|
11450
11635
|
continue;
|
|
11451
|
-
moveToTrash(
|
|
11636
|
+
moveToTrash(join25(dir, entry), reason);
|
|
11452
11637
|
}
|
|
11453
11638
|
}
|
|
11454
11639
|
var init_skill_removal = __esm(() => {
|
|
@@ -11456,7 +11641,7 @@ var init_skill_removal = __esm(() => {
|
|
|
11456
11641
|
});
|
|
11457
11642
|
|
|
11458
11643
|
// src/agents/utils/instruction-hint.ts
|
|
11459
|
-
import { existsSync as
|
|
11644
|
+
import { existsSync as existsSync31, readFileSync as readFileSync25, writeFileSync as writeFileSync15, mkdirSync as mkdirSync15 } from "fs";
|
|
11460
11645
|
import { dirname as dirname8 } from "path";
|
|
11461
11646
|
function writeHintToFile(filePath, hint) {
|
|
11462
11647
|
mkdirSync15(dirname8(filePath), { recursive: true });
|
|
@@ -11466,8 +11651,8 @@ ${hint}
|
|
|
11466
11651
|
${END_MARKER}`;
|
|
11467
11652
|
}
|
|
11468
11653
|
let content = "";
|
|
11469
|
-
if (
|
|
11470
|
-
content =
|
|
11654
|
+
if (existsSync31(filePath)) {
|
|
11655
|
+
content = readFileSync25(filePath, "utf-8");
|
|
11471
11656
|
}
|
|
11472
11657
|
const startIdx = content.indexOf(START_MARKER);
|
|
11473
11658
|
const endIdx = content.indexOf(END_MARKER);
|
|
@@ -11489,9 +11674,9 @@ ${END_MARKER}`;
|
|
|
11489
11674
|
writeFileSync15(filePath, content);
|
|
11490
11675
|
}
|
|
11491
11676
|
function removeHintFromFile(filePath) {
|
|
11492
|
-
if (!
|
|
11677
|
+
if (!existsSync31(filePath))
|
|
11493
11678
|
return false;
|
|
11494
|
-
let content =
|
|
11679
|
+
let content = readFileSync25(filePath, "utf-8");
|
|
11495
11680
|
const startIdx = content.indexOf(START_MARKER);
|
|
11496
11681
|
const endIdx = content.indexOf(END_MARKER);
|
|
11497
11682
|
if (startIdx < 0 || endIdx < 0)
|
|
@@ -11509,9 +11694,9 @@ function removeHintFromFile(filePath) {
|
|
|
11509
11694
|
return true;
|
|
11510
11695
|
}
|
|
11511
11696
|
function removeTeamInstructionsFromFile(filePath) {
|
|
11512
|
-
if (!
|
|
11697
|
+
if (!existsSync31(filePath))
|
|
11513
11698
|
return false;
|
|
11514
|
-
let content =
|
|
11699
|
+
let content = readFileSync25(filePath, "utf-8");
|
|
11515
11700
|
const startIdx = content.indexOf(TEAM_START_MARKER);
|
|
11516
11701
|
const endIdx = content.indexOf(TEAM_END_MARKER);
|
|
11517
11702
|
if (startIdx < 0 || endIdx < 0)
|
|
@@ -11531,8 +11716,8 @@ function removeTeamInstructionsFromFile(filePath) {
|
|
|
11531
11716
|
function writeTeamInstructionsToFile(filePath, instructions) {
|
|
11532
11717
|
mkdirSync15(dirname8(filePath), { recursive: true });
|
|
11533
11718
|
let content = "";
|
|
11534
|
-
if (
|
|
11535
|
-
content =
|
|
11719
|
+
if (existsSync31(filePath)) {
|
|
11720
|
+
content = readFileSync25(filePath, "utf-8");
|
|
11536
11721
|
}
|
|
11537
11722
|
const block = `${TEAM_START_MARKER}
|
|
11538
11723
|
${instructions}
|
|
@@ -11981,120 +12166,6 @@ function vlog(...args) {
|
|
|
11981
12166
|
}
|
|
11982
12167
|
var verbose = false;
|
|
11983
12168
|
|
|
11984
|
-
// src/agents/detection.ts
|
|
11985
|
-
import { execFile } from "child_process";
|
|
11986
|
-
import { existsSync as existsSync31 } from "fs";
|
|
11987
|
-
import { homedir as homedir8, platform as platform3 } from "os";
|
|
11988
|
-
import { join as join25 } from "path";
|
|
11989
|
-
import { promisify } from "util";
|
|
11990
|
-
function isWindows() {
|
|
11991
|
-
return platform3() === "win32";
|
|
11992
|
-
}
|
|
11993
|
-
function toList(value) {
|
|
11994
|
-
return Array.isArray(value) ? value : [value];
|
|
11995
|
-
}
|
|
11996
|
-
async function runPowerShell(script) {
|
|
11997
|
-
const execFileAsync = promisify(execFile);
|
|
11998
|
-
try {
|
|
11999
|
-
await execFileAsync("powershell", ["-NoProfile", "-Command", script]);
|
|
12000
|
-
return true;
|
|
12001
|
-
} catch {
|
|
12002
|
-
return false;
|
|
12003
|
-
}
|
|
12004
|
-
}
|
|
12005
|
-
function resolveDetectionPath(target) {
|
|
12006
|
-
const resolved = resolvePlatformString(target);
|
|
12007
|
-
if (!resolved)
|
|
12008
|
-
return null;
|
|
12009
|
-
const expanded = expandWindowsPathTemplate(resolved, {
|
|
12010
|
-
"%APPDATA%": process.env.APPDATA,
|
|
12011
|
-
"%LOCALAPPDATA%": process.env.LOCALAPPDATA,
|
|
12012
|
-
"%ProgramFiles%": process.env.ProgramFiles
|
|
12013
|
-
});
|
|
12014
|
-
return expanded.needsHomeJoin ? join25(homedir8(), expanded.path) : expanded.path;
|
|
12015
|
-
}
|
|
12016
|
-
function checkPath(target) {
|
|
12017
|
-
const absolute = resolveDetectionPath(target);
|
|
12018
|
-
if (!absolute)
|
|
12019
|
-
return null;
|
|
12020
|
-
return existsSync31(absolute) ? absolute : null;
|
|
12021
|
-
}
|
|
12022
|
-
async function checkMacosBundleId(target) {
|
|
12023
|
-
if (platform3() !== "darwin")
|
|
12024
|
-
return false;
|
|
12025
|
-
const execFileAsync = promisify(execFile);
|
|
12026
|
-
for (const id of toList(target)) {
|
|
12027
|
-
if (!isValidBundleId(id))
|
|
12028
|
-
continue;
|
|
12029
|
-
try {
|
|
12030
|
-
await execFileAsync("sh", ["-c", macosBundleIdProbeScript(id)]);
|
|
12031
|
-
return true;
|
|
12032
|
-
} catch {}
|
|
12033
|
-
}
|
|
12034
|
-
return false;
|
|
12035
|
-
}
|
|
12036
|
-
async function checkWindowsAppxPackage(target) {
|
|
12037
|
-
if (!isWindows())
|
|
12038
|
-
return false;
|
|
12039
|
-
const probes = toList(target).map((pkg) => runPowerShell(appxPackageProbeScript(pkg)));
|
|
12040
|
-
const results = await Promise.all(probes);
|
|
12041
|
-
return results.some(Boolean);
|
|
12042
|
-
}
|
|
12043
|
-
async function checkWindowsStartApp(target) {
|
|
12044
|
-
if (!isWindows())
|
|
12045
|
-
return false;
|
|
12046
|
-
const probes = toList(target).map((pattern) => runPowerShell(startAppProbeScript(pattern)));
|
|
12047
|
-
const results = await Promise.all(probes);
|
|
12048
|
-
return results.some(Boolean);
|
|
12049
|
-
}
|
|
12050
|
-
async function runAgentDetectionDetailed(detection) {
|
|
12051
|
-
switch (detection.method) {
|
|
12052
|
-
case "binary": {
|
|
12053
|
-
const target = resolvePlatformString(detection.target);
|
|
12054
|
-
const resolved = target ? whichBinary(target) : null;
|
|
12055
|
-
return resolved ? { detected: true, via: "binary", resolvedPath: resolved } : NOT_DETECTED;
|
|
12056
|
-
}
|
|
12057
|
-
case "path": {
|
|
12058
|
-
const resolved = checkPath(detection.target);
|
|
12059
|
-
return resolved ? { detected: true, via: "path", resolvedPath: resolved } : NOT_DETECTED;
|
|
12060
|
-
}
|
|
12061
|
-
case "windows-appx":
|
|
12062
|
-
return await checkWindowsAppxPackage(detection.target) ? { detected: true, via: "windows-appx" } : NOT_DETECTED;
|
|
12063
|
-
case "windows-start-app":
|
|
12064
|
-
return await checkWindowsStartApp(detection.target) ? { detected: true, via: "windows-start-app" } : NOT_DETECTED;
|
|
12065
|
-
case "macos-bundle-id":
|
|
12066
|
-
return await checkMacosBundleId(detection.target) ? { detected: true, via: "macos-bundle-id" } : NOT_DETECTED;
|
|
12067
|
-
case "any": {
|
|
12068
|
-
const probes = await Promise.all(detection.target.map((p) => runAgentDetectionDetailed(p)));
|
|
12069
|
-
return probes.find((p) => p.detected) ?? NOT_DETECTED;
|
|
12070
|
-
}
|
|
12071
|
-
case "always":
|
|
12072
|
-
return { detected: true, via: "always" };
|
|
12073
|
-
default:
|
|
12074
|
-
return NOT_DETECTED;
|
|
12075
|
-
}
|
|
12076
|
-
}
|
|
12077
|
-
async function runAgentDetection(detection) {
|
|
12078
|
-
return (await runAgentDetectionDetailed(detection)).detected;
|
|
12079
|
-
}
|
|
12080
|
-
|
|
12081
|
-
class RegistryDetectedAdapter {
|
|
12082
|
-
async detect() {
|
|
12083
|
-
const def = getRegistryAgent(this.slug);
|
|
12084
|
-
if (!def)
|
|
12085
|
-
return false;
|
|
12086
|
-
return runAgentDetection(def.detection);
|
|
12087
|
-
}
|
|
12088
|
-
}
|
|
12089
|
-
var NOT_DETECTED;
|
|
12090
|
-
var init_detection = __esm(() => {
|
|
12091
|
-
init_which();
|
|
12092
|
-
init_registry_data();
|
|
12093
|
-
init_registry();
|
|
12094
|
-
init_detection_probes();
|
|
12095
|
-
NOT_DETECTED = { detected: false };
|
|
12096
|
-
});
|
|
12097
|
-
|
|
12098
12169
|
// src/agents/transcript-sources.ts
|
|
12099
12170
|
import { accessSync, constants, statSync as statSync4 } from "fs";
|
|
12100
12171
|
function classifyFsErrorCode(code) {
|
|
@@ -12158,7 +12229,7 @@ function summarizeTranscriptSources(sources) {
|
|
|
12158
12229
|
var init_transcript_sources = () => {};
|
|
12159
12230
|
|
|
12160
12231
|
// src/agents/claude-code.ts
|
|
12161
|
-
import { chmodSync, existsSync as existsSync32, mkdirSync as mkdirSync16, readFileSync as
|
|
12232
|
+
import { chmodSync, existsSync as existsSync32, mkdirSync as mkdirSync16, readFileSync as readFileSync26, readdirSync as readdirSync7, rmSync as rmSync5, statSync as statSync5, writeFileSync as writeFileSync16 } from "fs";
|
|
12162
12233
|
import { join as join26 } from "path";
|
|
12163
12234
|
import { homedir as homedir9 } from "os";
|
|
12164
12235
|
function getPluginJson() {
|
|
@@ -12349,7 +12420,7 @@ ${instructions}`;
|
|
|
12349
12420
|
let settings = {};
|
|
12350
12421
|
if (hadFile) {
|
|
12351
12422
|
try {
|
|
12352
|
-
settings = JSON.parse(
|
|
12423
|
+
settings = JSON.parse(readFileSync26(settingsPath, "utf-8"));
|
|
12353
12424
|
} catch {}
|
|
12354
12425
|
}
|
|
12355
12426
|
if (settings.permissions && typeof settings.permissions === "object") {
|
|
@@ -12410,7 +12481,7 @@ ${instructions}`;
|
|
|
12410
12481
|
const settingsPath = join26(homedir9(), ".claude", "settings.json");
|
|
12411
12482
|
if (existsSync32(settingsPath)) {
|
|
12412
12483
|
try {
|
|
12413
|
-
const settings = JSON.parse(
|
|
12484
|
+
const settings = JSON.parse(readFileSync26(settingsPath, "utf-8"));
|
|
12414
12485
|
if (settings.permissions) {
|
|
12415
12486
|
for (const key of ["allow", "deny"]) {
|
|
12416
12487
|
const arr = settings.permissions[key];
|
|
@@ -12508,7 +12579,7 @@ ${instructions}`;
|
|
|
12508
12579
|
continue;
|
|
12509
12580
|
let content;
|
|
12510
12581
|
try {
|
|
12511
|
-
content =
|
|
12582
|
+
content = readFileSync26(filePath, "utf-8");
|
|
12512
12583
|
} catch {
|
|
12513
12584
|
continue;
|
|
12514
12585
|
}
|
|
@@ -12633,7 +12704,7 @@ ${instructions}`;
|
|
|
12633
12704
|
continue;
|
|
12634
12705
|
let content;
|
|
12635
12706
|
try {
|
|
12636
|
-
content =
|
|
12707
|
+
content = readFileSync26(filePath, "utf-8");
|
|
12637
12708
|
} catch {
|
|
12638
12709
|
continue;
|
|
12639
12710
|
}
|
|
@@ -12689,7 +12760,7 @@ ${instructions}`;
|
|
|
12689
12760
|
const sessionId = file.slice(0, -".jsonl".length);
|
|
12690
12761
|
let endedAt = null;
|
|
12691
12762
|
try {
|
|
12692
|
-
const stamp = JSON.parse(
|
|
12763
|
+
const stamp = JSON.parse(readFileSync26(join26(homedir9(), ".runwork", "sessions", `${sessionId}.ended.json`), "utf-8"));
|
|
12693
12764
|
if (stamp && typeof stamp.endedAt === "string")
|
|
12694
12765
|
endedAt = stamp.endedAt;
|
|
12695
12766
|
} catch {}
|
|
@@ -12701,7 +12772,8 @@ ${instructions}`;
|
|
|
12701
12772
|
startedAt: scanned.firstTimestamp,
|
|
12702
12773
|
lastActivityAt: resolveLastActivity(filePath, stat.mtimeMs),
|
|
12703
12774
|
endedAt,
|
|
12704
|
-
transcriptPath: filePath
|
|
12775
|
+
transcriptPath: filePath,
|
|
12776
|
+
surface: scanned.surface ?? null
|
|
12705
12777
|
});
|
|
12706
12778
|
}
|
|
12707
12779
|
}
|
|
@@ -12755,7 +12827,7 @@ ${instructions}`;
|
|
|
12755
12827
|
continue;
|
|
12756
12828
|
let content;
|
|
12757
12829
|
try {
|
|
12758
|
-
content =
|
|
12830
|
+
content = readFileSync26(filePath, "utf-8");
|
|
12759
12831
|
} catch {
|
|
12760
12832
|
continue;
|
|
12761
12833
|
}
|
|
@@ -13003,7 +13075,7 @@ var init_claude_desktop_plugin_tree = __esm(() => {
|
|
|
13003
13075
|
});
|
|
13004
13076
|
|
|
13005
13077
|
// src/agents/claude-desktop.ts
|
|
13006
|
-
import { existsSync as existsSync34, mkdtempSync as mkdtempSync3, readdirSync as readdirSync8, readFileSync as
|
|
13078
|
+
import { existsSync as existsSync34, mkdtempSync as mkdtempSync3, readdirSync as readdirSync8, readFileSync as readFileSync27, rmSync as rmSync7, statSync as statSync6, writeFileSync as writeFileSync18, mkdirSync as mkdirSync18 } from "fs";
|
|
13007
13079
|
import { dirname as dirname9, join as join28 } from "path";
|
|
13008
13080
|
import { homedir as homedir10, platform as platform4, tmpdir as tmpdir3 } from "os";
|
|
13009
13081
|
function isRunworkRpmPluginName(name) {
|
|
@@ -13122,7 +13194,7 @@ function findRpmPluginByName(pluginName) {
|
|
|
13122
13194
|
if (!existsSync34(manifestPath))
|
|
13123
13195
|
return null;
|
|
13124
13196
|
try {
|
|
13125
|
-
const manifest = JSON.parse(
|
|
13197
|
+
const manifest = JSON.parse(readFileSync27(manifestPath, "utf-8"));
|
|
13126
13198
|
const entry = manifest.plugins?.find((p) => p.name === pluginName);
|
|
13127
13199
|
if (!entry?.id)
|
|
13128
13200
|
return null;
|
|
@@ -13303,7 +13375,7 @@ var init_claude_desktop = __esm(() => {
|
|
|
13303
13375
|
let desktopConfig = {};
|
|
13304
13376
|
if (existsSync34(configPath)) {
|
|
13305
13377
|
try {
|
|
13306
|
-
desktopConfig = JSON.parse(
|
|
13378
|
+
desktopConfig = JSON.parse(readFileSync27(configPath, "utf-8"));
|
|
13307
13379
|
} catch {}
|
|
13308
13380
|
}
|
|
13309
13381
|
if (!desktopConfig.preferences)
|
|
@@ -13342,7 +13414,7 @@ var init_claude_desktop = __esm(() => {
|
|
|
13342
13414
|
if (!existsSync34(manifestPath))
|
|
13343
13415
|
continue;
|
|
13344
13416
|
try {
|
|
13345
|
-
const manifest = JSON.parse(
|
|
13417
|
+
const manifest = JSON.parse(readFileSync27(manifestPath, "utf-8"));
|
|
13346
13418
|
if (!Array.isArray(manifest.plugins))
|
|
13347
13419
|
continue;
|
|
13348
13420
|
const ours = manifest.plugins.filter((p) => isRunworkRpmPluginName(p.name));
|
|
@@ -13444,7 +13516,7 @@ var init_claude_desktop = __esm(() => {
|
|
|
13444
13516
|
continue;
|
|
13445
13517
|
let content;
|
|
13446
13518
|
try {
|
|
13447
|
-
content =
|
|
13519
|
+
content = readFileSync27(filePath, "utf-8");
|
|
13448
13520
|
} catch {
|
|
13449
13521
|
continue;
|
|
13450
13522
|
}
|
|
@@ -13484,7 +13556,7 @@ var init_claude_desktop = __esm(() => {
|
|
|
13484
13556
|
const metaPath = join28(orgPath, entry);
|
|
13485
13557
|
let meta;
|
|
13486
13558
|
try {
|
|
13487
|
-
meta = JSON.parse(
|
|
13559
|
+
meta = JSON.parse(readFileSync27(metaPath, "utf-8"));
|
|
13488
13560
|
} catch {
|
|
13489
13561
|
continue;
|
|
13490
13562
|
}
|
|
@@ -13520,7 +13592,8 @@ var init_claude_desktop = __esm(() => {
|
|
|
13520
13592
|
title: typeof meta.title === "string" && meta.title ? meta.title : null,
|
|
13521
13593
|
startedAt: typeof meta.createdAt === "number" ? new Date(meta.createdAt).toISOString() : null,
|
|
13522
13594
|
lastActivityAt: new Date(lastActivityMs).toISOString(),
|
|
13523
|
-
transcriptPath
|
|
13595
|
+
transcriptPath,
|
|
13596
|
+
surface: "local-agent"
|
|
13524
13597
|
});
|
|
13525
13598
|
}
|
|
13526
13599
|
}
|
|
@@ -13586,7 +13659,7 @@ var init_claude_desktop = __esm(() => {
|
|
|
13586
13659
|
const scheduledTasksPath = join28(claudeAppDir, "scheduled-tasks.json");
|
|
13587
13660
|
if (existsSync34(scheduledTasksPath)) {
|
|
13588
13661
|
try {
|
|
13589
|
-
const raw =
|
|
13662
|
+
const raw = readFileSync27(scheduledTasksPath, "utf-8");
|
|
13590
13663
|
const parsed = JSON.parse(raw);
|
|
13591
13664
|
const tasks = Array.isArray(parsed) ? parsed : Object.values(parsed);
|
|
13592
13665
|
for (const task of tasks) {
|
|
@@ -13630,7 +13703,7 @@ var init_claude_desktop = __esm(() => {
|
|
|
13630
13703
|
}
|
|
13631
13704
|
const versionPath = join28(claudeAppDir, "claude-code", "sdk-version");
|
|
13632
13705
|
if (existsSync34(versionPath)) {
|
|
13633
|
-
return
|
|
13706
|
+
return readFileSync27(versionPath, "utf-8").trim();
|
|
13634
13707
|
}
|
|
13635
13708
|
return null;
|
|
13636
13709
|
} catch {
|
|
@@ -13663,7 +13736,7 @@ var init_claude_desktop = __esm(() => {
|
|
|
13663
13736
|
if (!file.endsWith(".json"))
|
|
13664
13737
|
continue;
|
|
13665
13738
|
try {
|
|
13666
|
-
const session = JSON.parse(
|
|
13739
|
+
const session = JSON.parse(readFileSync27(join28(userPath, file), "utf-8"));
|
|
13667
13740
|
onSession(session);
|
|
13668
13741
|
} catch {
|
|
13669
13742
|
continue;
|
|
@@ -14207,7 +14280,7 @@ ${hint}`;
|
|
|
14207
14280
|
});
|
|
14208
14281
|
|
|
14209
14282
|
// src/agents/codex.ts
|
|
14210
|
-
import { existsSync as existsSync37, mkdirSync as mkdirSync21, readdirSync as readdirSync11, readFileSync as
|
|
14283
|
+
import { existsSync as existsSync37, mkdirSync as mkdirSync21, readdirSync as readdirSync11, readFileSync as readFileSync28, statSync as statSync7, writeFileSync as writeFileSync21 } from "fs";
|
|
14211
14284
|
import { basename as basename3, join as join31 } from "path";
|
|
14212
14285
|
import { homedir as homedir13 } from "os";
|
|
14213
14286
|
import { parse, stringify } from "smol-toml";
|
|
@@ -14240,7 +14313,7 @@ var init_codex = __esm(async () => {
|
|
|
14240
14313
|
const configPath = join31(homedir13(), ".codex", "config.toml");
|
|
14241
14314
|
let parsed = {};
|
|
14242
14315
|
if (existsSync37(configPath)) {
|
|
14243
|
-
parsed = parse(
|
|
14316
|
+
parsed = parse(readFileSync28(configPath, "utf-8"));
|
|
14244
14317
|
}
|
|
14245
14318
|
if (!parsed.mcp_servers || typeof parsed.mcp_servers !== "object") {
|
|
14246
14319
|
parsed.mcp_servers = {};
|
|
@@ -14295,7 +14368,7 @@ var init_codex = __esm(async () => {
|
|
|
14295
14368
|
const configPath = scope === "project" ? join31(process.cwd(), ".codex", "config.toml") : join31(homedir13(), ".codex", "config.toml");
|
|
14296
14369
|
let parsed = {};
|
|
14297
14370
|
if (existsSync37(configPath)) {
|
|
14298
|
-
parsed = parse(
|
|
14371
|
+
parsed = parse(readFileSync28(configPath, "utf-8"));
|
|
14299
14372
|
}
|
|
14300
14373
|
if (config.modelPreference) {
|
|
14301
14374
|
parsed.model = config.modelPreference;
|
|
@@ -14354,7 +14427,7 @@ var init_codex = __esm(async () => {
|
|
|
14354
14427
|
const configPath = join31(homedir13(), ".codex", "config.toml");
|
|
14355
14428
|
if (existsSync37(configPath)) {
|
|
14356
14429
|
try {
|
|
14357
|
-
const parsed = parse(
|
|
14430
|
+
const parsed = parse(readFileSync28(configPath, "utf-8"));
|
|
14358
14431
|
if (parsed.mcp_servers && typeof parsed.mcp_servers === "object") {
|
|
14359
14432
|
const mcpServers = parsed.mcp_servers;
|
|
14360
14433
|
for (const key of Object.keys(mcpServers)) {
|
|
@@ -14403,7 +14476,7 @@ var init_codex = __esm(async () => {
|
|
|
14403
14476
|
if (messageCount === 0) {
|
|
14404
14477
|
const historyPath = join31(codexDir, "history.jsonl");
|
|
14405
14478
|
if (existsSync37(historyPath)) {
|
|
14406
|
-
const content =
|
|
14479
|
+
const content = readFileSync28(historyPath, "utf-8").trim();
|
|
14407
14480
|
if (content) {
|
|
14408
14481
|
for (const line of content.split(/[\r\n]+/)) {
|
|
14409
14482
|
try {
|
|
@@ -14483,7 +14556,7 @@ var init_codex = __esm(async () => {
|
|
|
14483
14556
|
continue;
|
|
14484
14557
|
let content;
|
|
14485
14558
|
try {
|
|
14486
|
-
content =
|
|
14559
|
+
content = readFileSync28(file, "utf-8");
|
|
14487
14560
|
} catch {
|
|
14488
14561
|
continue;
|
|
14489
14562
|
}
|
|
@@ -14575,7 +14648,7 @@ var init_codex = __esm(async () => {
|
|
|
14575
14648
|
continue;
|
|
14576
14649
|
let content;
|
|
14577
14650
|
try {
|
|
14578
|
-
content =
|
|
14651
|
+
content = readFileSync28(file, "utf-8");
|
|
14579
14652
|
} catch {
|
|
14580
14653
|
continue;
|
|
14581
14654
|
}
|
|
@@ -14634,7 +14707,8 @@ var init_codex = __esm(async () => {
|
|
|
14634
14707
|
title: scanned.title,
|
|
14635
14708
|
startedAt: scanned.firstTimestamp,
|
|
14636
14709
|
lastActivityAt: resolveLastActivity(file, stat.mtimeMs),
|
|
14637
|
-
transcriptPath: file
|
|
14710
|
+
transcriptPath: file,
|
|
14711
|
+
surface: scanned.surface ?? null
|
|
14638
14712
|
});
|
|
14639
14713
|
}
|
|
14640
14714
|
return sessions;
|
|
@@ -14646,7 +14720,7 @@ var init_codex = __esm(async () => {
|
|
|
14646
14720
|
try {
|
|
14647
14721
|
const versionPath = join31(homedir13(), ".codex", "version.json");
|
|
14648
14722
|
if (existsSync37(versionPath)) {
|
|
14649
|
-
const data = JSON.parse(
|
|
14723
|
+
const data = JSON.parse(readFileSync28(versionPath, "utf-8"));
|
|
14650
14724
|
return data.latest_version ?? null;
|
|
14651
14725
|
}
|
|
14652
14726
|
} catch {}
|
|
@@ -14707,7 +14781,7 @@ var init_codex = __esm(async () => {
|
|
|
14707
14781
|
parseRolloutForSkills(filePath, sinceMs, skillCounts) {
|
|
14708
14782
|
let content;
|
|
14709
14783
|
try {
|
|
14710
|
-
content =
|
|
14784
|
+
content = readFileSync28(filePath, "utf-8");
|
|
14711
14785
|
} catch {
|
|
14712
14786
|
return;
|
|
14713
14787
|
}
|
|
@@ -14760,7 +14834,7 @@ var init_codex = __esm(async () => {
|
|
|
14760
14834
|
let state = {};
|
|
14761
14835
|
if (existsSync37(statePath)) {
|
|
14762
14836
|
try {
|
|
14763
|
-
state = JSON.parse(
|
|
14837
|
+
state = JSON.parse(readFileSync28(statePath, "utf-8"));
|
|
14764
14838
|
} catch {
|
|
14765
14839
|
return "app_running";
|
|
14766
14840
|
}
|
|
@@ -14795,23 +14869,11 @@ var init_codex = __esm(async () => {
|
|
|
14795
14869
|
CodexDesktopAdapter = class CodexDesktopAdapter extends CodexAdapter {
|
|
14796
14870
|
name = "Codex";
|
|
14797
14871
|
slug = "codex-app";
|
|
14798
|
-
async readUsageStats() {
|
|
14799
|
-
return null;
|
|
14800
|
-
}
|
|
14801
|
-
async listSessions() {
|
|
14802
|
-
return null;
|
|
14803
|
-
}
|
|
14804
|
-
async readSessionDigests() {
|
|
14805
|
-
return null;
|
|
14806
|
-
}
|
|
14807
|
-
transcriptSources() {
|
|
14808
|
-
return [];
|
|
14809
|
-
}
|
|
14810
14872
|
};
|
|
14811
14873
|
});
|
|
14812
14874
|
|
|
14813
14875
|
// src/agents/cline.ts
|
|
14814
|
-
import { existsSync as existsSync38, mkdirSync as mkdirSync22, readFileSync as
|
|
14876
|
+
import { existsSync as existsSync38, mkdirSync as mkdirSync22, readFileSync as readFileSync29, readdirSync as readdirSync12, rmSync as rmSync10, unlinkSync as unlinkSync6, writeFileSync as writeFileSync22 } from "fs";
|
|
14815
14877
|
import { join as join32 } from "path";
|
|
14816
14878
|
import { homedir as homedir14 } from "os";
|
|
14817
14879
|
var ClineAdapter;
|
|
@@ -14872,7 +14934,7 @@ var init_cline = __esm(() => {
|
|
|
14872
14934
|
let state = {};
|
|
14873
14935
|
if (existsSync38(globalStatePath)) {
|
|
14874
14936
|
try {
|
|
14875
|
-
state = JSON.parse(
|
|
14937
|
+
state = JSON.parse(readFileSync29(globalStatePath, "utf-8"));
|
|
14876
14938
|
} catch {}
|
|
14877
14939
|
}
|
|
14878
14940
|
if (config.modelPreference) {
|
|
@@ -14929,7 +14991,7 @@ var init_cline = __esm(() => {
|
|
|
14929
14991
|
});
|
|
14930
14992
|
|
|
14931
14993
|
// src/agents/gemini.ts
|
|
14932
|
-
import { existsSync as existsSync39, mkdirSync as mkdirSync23, readdirSync as readdirSync13, readFileSync as
|
|
14994
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync23, readdirSync as readdirSync13, readFileSync as readFileSync30, statSync as statSync8, writeFileSync as writeFileSync23 } from "fs";
|
|
14933
14995
|
import { basename as basename4, join as join33 } from "path";
|
|
14934
14996
|
import { homedir as homedir15 } from "os";
|
|
14935
14997
|
var GeminiAdapter;
|
|
@@ -14989,7 +15051,7 @@ var init_gemini = __esm(() => {
|
|
|
14989
15051
|
let settings = {};
|
|
14990
15052
|
if (existsSync39(settingsPath)) {
|
|
14991
15053
|
try {
|
|
14992
|
-
settings = JSON.parse(
|
|
15054
|
+
settings = JSON.parse(readFileSync30(settingsPath, "utf-8"));
|
|
14993
15055
|
} catch {}
|
|
14994
15056
|
}
|
|
14995
15057
|
if (config.modelPreference) {
|
|
@@ -15050,7 +15112,7 @@ var init_gemini = __esm(() => {
|
|
|
15050
15112
|
continue;
|
|
15051
15113
|
let session;
|
|
15052
15114
|
try {
|
|
15053
|
-
session = JSON.parse(
|
|
15115
|
+
session = JSON.parse(readFileSync30(filePath, "utf-8"));
|
|
15054
15116
|
} catch {
|
|
15055
15117
|
continue;
|
|
15056
15118
|
}
|
|
@@ -15141,7 +15203,7 @@ var init_gemini = __esm(() => {
|
|
|
15141
15203
|
for (const { filePath, project, mtimeMs } of this.chatFiles(sinceMs)) {
|
|
15142
15204
|
let session;
|
|
15143
15205
|
try {
|
|
15144
|
-
session = JSON.parse(
|
|
15206
|
+
session = JSON.parse(readFileSync30(filePath, "utf-8"));
|
|
15145
15207
|
} catch {
|
|
15146
15208
|
continue;
|
|
15147
15209
|
}
|
|
@@ -15182,7 +15244,7 @@ var init_gemini = __esm(() => {
|
|
|
15182
15244
|
for (const { filePath, project } of this.chatFiles(sinceMs)) {
|
|
15183
15245
|
let content;
|
|
15184
15246
|
try {
|
|
15185
|
-
content =
|
|
15247
|
+
content = readFileSync30(filePath, "utf-8");
|
|
15186
15248
|
} catch {
|
|
15187
15249
|
continue;
|
|
15188
15250
|
}
|
|
@@ -15425,6 +15487,23 @@ function describeScanOutcome(outcome) {
|
|
|
15425
15487
|
function scanOutcomeNeedsAttention(outcome) {
|
|
15426
15488
|
return outcome.status === "permission-denied" || outcome.status === "error";
|
|
15427
15489
|
}
|
|
15490
|
+
function describeStoreOutcome(outcome) {
|
|
15491
|
+
if (outcome.status === "orphaned") {
|
|
15492
|
+
return `not read: nothing on this machine was detected as ${outcome.members.join(" or ")}`;
|
|
15493
|
+
}
|
|
15494
|
+
if (outcome.status === "ok")
|
|
15495
|
+
return null;
|
|
15496
|
+
return describeScanOutcome({
|
|
15497
|
+
agentSlug: outcome.storeId,
|
|
15498
|
+
status: outcome.status,
|
|
15499
|
+
sessions: outcome.sessions,
|
|
15500
|
+
path: outcome.path,
|
|
15501
|
+
...outcome.detail ? { detail: outcome.detail } : {}
|
|
15502
|
+
});
|
|
15503
|
+
}
|
|
15504
|
+
function storeOutcomeNeedsAttention(outcome) {
|
|
15505
|
+
return outcome.status === "orphaned" || outcome.status === "permission-denied" || outcome.status === "error";
|
|
15506
|
+
}
|
|
15428
15507
|
|
|
15429
15508
|
// src/utils/insight-id.ts
|
|
15430
15509
|
import { createHash as createHash3 } from "node:crypto";
|
|
@@ -15437,7 +15516,7 @@ function insightLocalKey(teaches, slug) {
|
|
|
15437
15516
|
var init_insight_id = () => {};
|
|
15438
15517
|
|
|
15439
15518
|
// src/reflect/insight-store.ts
|
|
15440
|
-
import { existsSync as existsSync41, readFileSync as
|
|
15519
|
+
import { existsSync as existsSync41, readFileSync as readFileSync31 } from "fs";
|
|
15441
15520
|
import { join as join35 } from "path";
|
|
15442
15521
|
import { homedir as homedir17 } from "os";
|
|
15443
15522
|
function storePath2() {
|
|
@@ -15448,7 +15527,7 @@ function readAll() {
|
|
|
15448
15527
|
if (!existsSync41(path2))
|
|
15449
15528
|
return {};
|
|
15450
15529
|
try {
|
|
15451
|
-
const parsed = JSON.parse(
|
|
15530
|
+
const parsed = JSON.parse(readFileSync31(path2, "utf-8"));
|
|
15452
15531
|
return parsed && typeof parsed === "object" ? parsed : {};
|
|
15453
15532
|
} catch {
|
|
15454
15533
|
return {};
|
|
@@ -15493,7 +15572,7 @@ var init_insight_store = __esm(() => {
|
|
|
15493
15572
|
var DEFAULT_DAILY_TIER2_BUDGET = 3;
|
|
15494
15573
|
|
|
15495
15574
|
// src/reflect/cadence.ts
|
|
15496
|
-
import { existsSync as existsSync42, readFileSync as
|
|
15575
|
+
import { existsSync as existsSync42, readFileSync as readFileSync32 } from "fs";
|
|
15497
15576
|
import { join as join36 } from "path";
|
|
15498
15577
|
import { homedir as homedir18 } from "os";
|
|
15499
15578
|
function remainingDailyAnalyses(state, now = new Date, budget = DEFAULT_DAILY_TIER2_BUDGET) {
|
|
@@ -15515,7 +15594,7 @@ function loadCadenceState() {
|
|
|
15515
15594
|
const p = statePath();
|
|
15516
15595
|
if (!existsSync42(p))
|
|
15517
15596
|
return { ...DEFAULT_STATE };
|
|
15518
|
-
const parsed = JSON.parse(
|
|
15597
|
+
const parsed = JSON.parse(readFileSync32(p, "utf-8"));
|
|
15519
15598
|
const state = { ...DEFAULT_STATE, ...parsed && typeof parsed === "object" ? parsed : {} };
|
|
15520
15599
|
if (state.enabled === false && state.disabledByUser !== true) {
|
|
15521
15600
|
state.enabled = true;
|
|
@@ -15576,7 +15655,7 @@ __export(exports_run_log, {
|
|
|
15576
15655
|
RUN_LOG_CAP: () => RUN_LOG_CAP,
|
|
15577
15656
|
ANALYST_ERROR_MAX_CHARS: () => ANALYST_ERROR_MAX_CHARS
|
|
15578
15657
|
});
|
|
15579
|
-
import { existsSync as existsSync43, mkdirSync as mkdirSync25, readFileSync as
|
|
15658
|
+
import { existsSync as existsSync43, mkdirSync as mkdirSync25, readFileSync as readFileSync33, readdirSync as readdirSync15, statSync as statSync9, unlinkSync as unlinkSync7, writeFileSync as writeFileSync25 } from "fs";
|
|
15580
15659
|
import { dirname as dirname10, join as join37 } from "path";
|
|
15581
15660
|
import { homedir as homedir19 } from "os";
|
|
15582
15661
|
function runLogPath() {
|
|
@@ -15587,7 +15666,7 @@ function loadRunLog() {
|
|
|
15587
15666
|
const p = runLogPath();
|
|
15588
15667
|
if (!existsSync43(p))
|
|
15589
15668
|
return [];
|
|
15590
|
-
const parsed = JSON.parse(
|
|
15669
|
+
const parsed = JSON.parse(readFileSync33(p, "utf-8"));
|
|
15591
15670
|
return Array.isArray(parsed) ? parsed : [];
|
|
15592
15671
|
} catch {
|
|
15593
15672
|
return [];
|
|
@@ -15755,7 +15834,7 @@ var init_run_log = __esm(() => {
|
|
|
15755
15834
|
});
|
|
15756
15835
|
|
|
15757
15836
|
// src/reflect/conversation-queue.ts
|
|
15758
|
-
import { existsSync as existsSync44, readFileSync as
|
|
15837
|
+
import { existsSync as existsSync44, readFileSync as readFileSync34 } from "fs";
|
|
15759
15838
|
import { join as join38 } from "path";
|
|
15760
15839
|
import { homedir as homedir20 } from "os";
|
|
15761
15840
|
function conversationKey(c) {
|
|
@@ -15769,7 +15848,7 @@ function loadQueueState() {
|
|
|
15769
15848
|
const p = queuePath();
|
|
15770
15849
|
if (!existsSync44(p))
|
|
15771
15850
|
return { entries: {} };
|
|
15772
|
-
const parsed = JSON.parse(
|
|
15851
|
+
const parsed = JSON.parse(readFileSync34(p, "utf-8"));
|
|
15773
15852
|
if (parsed && typeof parsed === "object" && parsed.entries && typeof parsed.entries === "object") {
|
|
15774
15853
|
return { entries: parsed.entries };
|
|
15775
15854
|
}
|
|
@@ -15977,7 +16056,7 @@ function parseHandoffResult(kind, text2) {
|
|
|
15977
16056
|
}
|
|
15978
16057
|
|
|
15979
16058
|
// src/reflect/model-repair.ts
|
|
15980
|
-
import { existsSync as existsSync45, readFileSync as
|
|
16059
|
+
import { existsSync as existsSync45, readFileSync as readFileSync35, writeFileSync as writeFileSync26 } from "fs";
|
|
15981
16060
|
import { homedir as homedir21 } from "os";
|
|
15982
16061
|
import { join as join39 } from "path";
|
|
15983
16062
|
function codexConfigPath() {
|
|
@@ -16014,7 +16093,7 @@ function repairCodexModelPin() {
|
|
|
16014
16093
|
const path2 = codexConfigPath();
|
|
16015
16094
|
if (!existsSync45(path2))
|
|
16016
16095
|
return null;
|
|
16017
|
-
const current =
|
|
16096
|
+
const current = readFileSync35(path2, "utf-8");
|
|
16018
16097
|
const stripped = stripModelPin(current);
|
|
16019
16098
|
if (!stripped)
|
|
16020
16099
|
return null;
|
|
@@ -16837,7 +16916,214 @@ ${all.length} insight(s) from your recent work:
|
|
|
16837
16916
|
});
|
|
16838
16917
|
});
|
|
16839
16918
|
|
|
16919
|
+
// src/agents/transcript-stores.ts
|
|
16920
|
+
function joiner(input) {
|
|
16921
|
+
const sep4 = input.sep ?? (input.platform === "win32" ? "\\" : "/");
|
|
16922
|
+
return (...parts) => parts.join(sep4);
|
|
16923
|
+
}
|
|
16924
|
+
function home(input) {
|
|
16925
|
+
return input.homeDir.replace(/[/\\]+$/, "");
|
|
16926
|
+
}
|
|
16927
|
+
function appDataRoot(input) {
|
|
16928
|
+
const join41 = joiner(input);
|
|
16929
|
+
if (input.platform === "darwin")
|
|
16930
|
+
return join41(home(input), "Library", "Application Support");
|
|
16931
|
+
if (input.platform === "win32") {
|
|
16932
|
+
return input.appData ?? join41(home(input), "AppData", "Roaming");
|
|
16933
|
+
}
|
|
16934
|
+
return join41(home(input), ".config");
|
|
16935
|
+
}
|
|
16936
|
+
function localAppDataRoot(input) {
|
|
16937
|
+
const join41 = joiner(input);
|
|
16938
|
+
return input.localAppData ?? join41(home(input), "AppData", "Local");
|
|
16939
|
+
}
|
|
16940
|
+
function codexOriginator(head) {
|
|
16941
|
+
for (const line of head.split(`
|
|
16942
|
+
`)) {
|
|
16943
|
+
if (!line.trim())
|
|
16944
|
+
continue;
|
|
16945
|
+
let o;
|
|
16946
|
+
try {
|
|
16947
|
+
o = JSON.parse(line);
|
|
16948
|
+
} catch {
|
|
16949
|
+
continue;
|
|
16950
|
+
}
|
|
16951
|
+
if (o.type !== "session_meta")
|
|
16952
|
+
continue;
|
|
16953
|
+
const payload = o.payload;
|
|
16954
|
+
return typeof payload?.originator === "string" ? payload.originator : null;
|
|
16955
|
+
}
|
|
16956
|
+
return null;
|
|
16957
|
+
}
|
|
16958
|
+
function claudeEntrypoint(head) {
|
|
16959
|
+
for (const line of head.split(`
|
|
16960
|
+
`)) {
|
|
16961
|
+
if (!line.trim())
|
|
16962
|
+
continue;
|
|
16963
|
+
let o;
|
|
16964
|
+
try {
|
|
16965
|
+
o = JSON.parse(line);
|
|
16966
|
+
} catch {
|
|
16967
|
+
continue;
|
|
16968
|
+
}
|
|
16969
|
+
if (typeof o.entrypoint === "string")
|
|
16970
|
+
return o.entrypoint;
|
|
16971
|
+
}
|
|
16972
|
+
return null;
|
|
16973
|
+
}
|
|
16974
|
+
function attributeCodexOriginator(marker) {
|
|
16975
|
+
switch (marker) {
|
|
16976
|
+
case "Codex Desktop":
|
|
16977
|
+
case "codex_work_desktop":
|
|
16978
|
+
return "codex-app";
|
|
16979
|
+
case "codex-tui":
|
|
16980
|
+
case "codex_exec":
|
|
16981
|
+
case "Claude Code":
|
|
16982
|
+
return "codex";
|
|
16983
|
+
default:
|
|
16984
|
+
return null;
|
|
16985
|
+
}
|
|
16986
|
+
}
|
|
16987
|
+
function attributeClaudeEntrypoint(marker) {
|
|
16988
|
+
switch (marker) {
|
|
16989
|
+
case "cli":
|
|
16990
|
+
case "sdk-cli":
|
|
16991
|
+
return "claude-code";
|
|
16992
|
+
case "claude-desktop":
|
|
16993
|
+
case "local-agent":
|
|
16994
|
+
return "claude-desktop";
|
|
16995
|
+
default:
|
|
16996
|
+
return null;
|
|
16997
|
+
}
|
|
16998
|
+
}
|
|
16999
|
+
function resolveTranscriptStores(input) {
|
|
17000
|
+
const resolved = [];
|
|
17001
|
+
for (const def of TRANSCRIPT_STORES) {
|
|
17002
|
+
const path2 = def.path(input);
|
|
17003
|
+
if (path2 === null)
|
|
17004
|
+
continue;
|
|
17005
|
+
resolved.push({ def, path: path2, altPaths: def.altPaths?.(input) ?? [] });
|
|
17006
|
+
}
|
|
17007
|
+
return resolved;
|
|
17008
|
+
}
|
|
17009
|
+
function familyMembers(family, table = TRANSCRIPT_STORES) {
|
|
17010
|
+
const slugs = new Set;
|
|
17011
|
+
for (const store of table) {
|
|
17012
|
+
if (store.family !== family)
|
|
17013
|
+
continue;
|
|
17014
|
+
for (const member of store.members)
|
|
17015
|
+
slugs.add(member);
|
|
17016
|
+
}
|
|
17017
|
+
return [...slugs];
|
|
17018
|
+
}
|
|
17019
|
+
function isStoreUnlocked(def, detectedSlugs, table = TRANSCRIPT_STORES) {
|
|
17020
|
+
const detected = detectedSlugs instanceof Set ? detectedSlugs : new Set(detectedSlugs);
|
|
17021
|
+
return familyMembers(def.family, table).some((m) => detected.has(m));
|
|
17022
|
+
}
|
|
17023
|
+
function telemetryOwner(def, detectedSlugs) {
|
|
17024
|
+
const detected = detectedSlugs instanceof Set ? detectedSlugs : new Set(detectedSlugs);
|
|
17025
|
+
if (detected.has(def.readerSlug))
|
|
17026
|
+
return def.readerSlug;
|
|
17027
|
+
return def.members.find((m) => detected.has(m)) ?? null;
|
|
17028
|
+
}
|
|
17029
|
+
function suppressedStoreReaders(detectedSlugs, sharesImplementation, table = TRANSCRIPT_STORES) {
|
|
17030
|
+
const detected = detectedSlugs instanceof Set ? detectedSlugs : new Set(detectedSlugs);
|
|
17031
|
+
const suppressed = new Set;
|
|
17032
|
+
for (const store of table) {
|
|
17033
|
+
const owner = telemetryOwner(store, detected);
|
|
17034
|
+
if (owner === null)
|
|
17035
|
+
continue;
|
|
17036
|
+
for (const member of store.members) {
|
|
17037
|
+
if (member === owner || !detected.has(member))
|
|
17038
|
+
continue;
|
|
17039
|
+
if (sharesImplementation(member, owner))
|
|
17040
|
+
suppressed.add(member);
|
|
17041
|
+
}
|
|
17042
|
+
}
|
|
17043
|
+
return suppressed;
|
|
17044
|
+
}
|
|
17045
|
+
function attributeTranscript(def, head) {
|
|
17046
|
+
if (head === null || !def.marker) {
|
|
17047
|
+
return { agentSlug: def.defaultMember, marker: null, recognised: false };
|
|
17048
|
+
}
|
|
17049
|
+
const marker = def.marker(head);
|
|
17050
|
+
if (marker === null)
|
|
17051
|
+
return { agentSlug: def.defaultMember, marker: null, recognised: false };
|
|
17052
|
+
const slug = def.attribute?.(marker) ?? null;
|
|
17053
|
+
return slug === null ? { agentSlug: def.defaultMember, marker, recognised: false } : { agentSlug: slug, marker, recognised: true };
|
|
17054
|
+
}
|
|
17055
|
+
var CODEX_HEAD, CLAUDE_HEAD, TRANSCRIPT_STORES;
|
|
17056
|
+
var init_transcript_stores = __esm(() => {
|
|
17057
|
+
CODEX_HEAD = 256 * 1024;
|
|
17058
|
+
CLAUDE_HEAD = 64 * 1024;
|
|
17059
|
+
TRANSCRIPT_STORES = [
|
|
17060
|
+
{
|
|
17061
|
+
id: "codex/sessions",
|
|
17062
|
+
readerSlug: "codex",
|
|
17063
|
+
family: "codex",
|
|
17064
|
+
members: ["codex", "codex-app"],
|
|
17065
|
+
defaultMember: "codex",
|
|
17066
|
+
kind: "dir",
|
|
17067
|
+
path: (i) => joiner(i)(home(i), ".codex", "sessions"),
|
|
17068
|
+
matches: (n) => n.startsWith("rollout-") && n.endsWith(".jsonl"),
|
|
17069
|
+
headBytes: CODEX_HEAD,
|
|
17070
|
+
marker: codexOriginator,
|
|
17071
|
+
attribute: attributeCodexOriginator
|
|
17072
|
+
},
|
|
17073
|
+
{
|
|
17074
|
+
id: "claude/projects",
|
|
17075
|
+
readerSlug: "claude-code",
|
|
17076
|
+
family: "claude",
|
|
17077
|
+
members: ["claude-code", "claude-desktop"],
|
|
17078
|
+
defaultMember: "claude-code",
|
|
17079
|
+
kind: "dir",
|
|
17080
|
+
path: (i) => joiner(i)(home(i), ".claude", "projects"),
|
|
17081
|
+
matches: (n) => n.endsWith(".jsonl"),
|
|
17082
|
+
subordinate: (rel) => rel.split(/[\\/]/).length > 2,
|
|
17083
|
+
headBytes: CLAUDE_HEAD,
|
|
17084
|
+
marker: claudeEntrypoint,
|
|
17085
|
+
attribute: attributeClaudeEntrypoint
|
|
17086
|
+
},
|
|
17087
|
+
{
|
|
17088
|
+
id: "claude/cowork",
|
|
17089
|
+
readerSlug: "claude-desktop",
|
|
17090
|
+
family: "claude",
|
|
17091
|
+
members: ["claude-desktop"],
|
|
17092
|
+
defaultMember: "claude-desktop",
|
|
17093
|
+
kind: "dir",
|
|
17094
|
+
path: (i) => joiner(i)(appDataRoot(i), "Claude", "local-agent-mode-sessions"),
|
|
17095
|
+
altPaths: (i) => i.platform === "win32" ? [joiner(i)(localAppDataRoot(i), "Packages", "Claude_pzs8sxrjxfjjc", "LocalCache", "Roaming", "Claude", "local-agent-mode-sessions")] : [],
|
|
17096
|
+
matches: (n) => n.endsWith(".jsonl"),
|
|
17097
|
+
headBytes: CLAUDE_HEAD,
|
|
17098
|
+
marker: claudeEntrypoint,
|
|
17099
|
+
attribute: attributeClaudeEntrypoint,
|
|
17100
|
+
note: "macOS TCC can refuse this while it still exists"
|
|
17101
|
+
},
|
|
17102
|
+
{
|
|
17103
|
+
id: "gemini/tmp",
|
|
17104
|
+
readerSlug: "gemini",
|
|
17105
|
+
family: "gemini",
|
|
17106
|
+
members: ["gemini"],
|
|
17107
|
+
defaultMember: "gemini",
|
|
17108
|
+
kind: "dir",
|
|
17109
|
+
path: (i) => joiner(i)(home(i), ".gemini", "tmp"),
|
|
17110
|
+
matches: (n) => n.endsWith(".json")
|
|
17111
|
+
},
|
|
17112
|
+
{
|
|
17113
|
+
id: "cursor/state",
|
|
17114
|
+
readerSlug: "cursor",
|
|
17115
|
+
family: "cursor",
|
|
17116
|
+
members: ["cursor"],
|
|
17117
|
+
defaultMember: "cursor",
|
|
17118
|
+
kind: "file",
|
|
17119
|
+
path: (i) => joiner(i)(appDataRoot(i), "Cursor", "User", "globalStorage", "state.vscdb"),
|
|
17120
|
+
tool: "sqlite"
|
|
17121
|
+
}
|
|
17122
|
+
];
|
|
17123
|
+
});
|
|
17124
|
+
|
|
16840
17125
|
// src/reflect/conversation-registry.ts
|
|
17126
|
+
import { homedir as homedir22, platform as platform7 } from "os";
|
|
16841
17127
|
function computeStatus(lastActivityAt, nowMs, idleMinutes = DEFAULT_IDLE_MINUTES) {
|
|
16842
17128
|
const lastMs = new Date(lastActivityAt).getTime();
|
|
16843
17129
|
if (Number.isNaN(lastMs))
|
|
@@ -16868,44 +17154,114 @@ function mergeSessionListings(listings, opts) {
|
|
|
16868
17154
|
status: isFreshEndStamp(s.endedAt, s.lastActivityAt) ? "finished" : computeStatus(s.lastActivityAt, opts.nowMs, opts.idleMinutes)
|
|
16869
17155
|
}));
|
|
16870
17156
|
}
|
|
17157
|
+
function machineStores(opts) {
|
|
17158
|
+
return opts.stores ?? resolveTranscriptStores({
|
|
17159
|
+
platform: platform7(),
|
|
17160
|
+
homeDir: homedir22(),
|
|
17161
|
+
appData: process.env.APPDATA ?? null,
|
|
17162
|
+
localAppData: process.env.LOCALAPPDATA ?? null
|
|
17163
|
+
});
|
|
17164
|
+
}
|
|
17165
|
+
function attributeListing(store, sessions) {
|
|
17166
|
+
if (!store.def.attribute)
|
|
17167
|
+
return sessions;
|
|
17168
|
+
return sessions.map((s) => {
|
|
17169
|
+
const surface = s.surface ?? null;
|
|
17170
|
+
const slug = surface === null ? null : store.def.attribute?.(surface) ?? null;
|
|
17171
|
+
return {
|
|
17172
|
+
...s,
|
|
17173
|
+
agentSlug: slug ?? store.def.defaultMember,
|
|
17174
|
+
surface
|
|
17175
|
+
};
|
|
17176
|
+
});
|
|
17177
|
+
}
|
|
16871
17178
|
async function listLocalConversations(opts = {}) {
|
|
16872
|
-
const
|
|
17179
|
+
const detected = opts.detected ?? (await detectAgents()).map((a) => a.slug);
|
|
17180
|
+
const detectedSet = new Set(detected);
|
|
16873
17181
|
const sinceISO = opts.sinceISO ?? null;
|
|
17182
|
+
const maxPerStore = opts.maxPerStore ?? DEFAULT_MAX_PER_STORE;
|
|
16874
17183
|
const listings = [];
|
|
16875
|
-
const
|
|
16876
|
-
|
|
16877
|
-
|
|
16878
|
-
|
|
17184
|
+
const perStore = [];
|
|
17185
|
+
const stores = machineStores(opts);
|
|
17186
|
+
const table = stores.map((s) => s.def);
|
|
17187
|
+
for (const store of stores) {
|
|
17188
|
+
const base = {
|
|
17189
|
+
storeId: store.def.id,
|
|
17190
|
+
family: store.def.family,
|
|
17191
|
+
members: [...familyMembers(store.def.family, table)],
|
|
17192
|
+
path: store.path
|
|
17193
|
+
};
|
|
17194
|
+
if (!isStoreUnlocked(store.def, detectedSet, table)) {
|
|
17195
|
+
perStore.push({ ...base, status: "orphaned", sessions: null });
|
|
17196
|
+
continue;
|
|
17197
|
+
}
|
|
17198
|
+
const reader = (opts.readerFor ?? getAdapterBySlug)(store.def.readerSlug);
|
|
17199
|
+
if (!reader?.listSessions) {
|
|
17200
|
+
perStore.push({ ...base, status: "no-reader", sessions: null });
|
|
16879
17201
|
continue;
|
|
16880
17202
|
}
|
|
16881
17203
|
try {
|
|
16882
|
-
const sessions = await
|
|
17204
|
+
const sessions = await reader.listSessions(sinceISO);
|
|
16883
17205
|
if (sessions === null) {
|
|
16884
|
-
|
|
17206
|
+
const outcome = diagnoseTranscriptRead(reader);
|
|
17207
|
+
perStore.push({ ...base, status: outcome.status, sessions: null, ...outcome.detail ? { detail: outcome.detail } : {} });
|
|
16885
17208
|
continue;
|
|
16886
17209
|
}
|
|
16887
|
-
|
|
16888
|
-
|
|
17210
|
+
const attributed = attributeListing(store, sessions).sort((a, b) => b.lastActivityAt.localeCompare(a.lastActivityAt)).slice(0, maxPerStore);
|
|
17211
|
+
listings.push(attributed);
|
|
17212
|
+
perStore.push({
|
|
17213
|
+
...base,
|
|
17214
|
+
status: "ok",
|
|
17215
|
+
sessions: attributed.length,
|
|
17216
|
+
...sessions.length > attributed.length ? { truncated: sessions.length } : {}
|
|
17217
|
+
});
|
|
16889
17218
|
} catch (err) {
|
|
16890
|
-
|
|
17219
|
+
const outcome = diagnoseTranscriptRead(reader, err);
|
|
17220
|
+
perStore.push({ ...base, status: outcome.status, sessions: null, ...outcome.detail ? { detail: outcome.detail } : {} });
|
|
16891
17221
|
}
|
|
16892
17222
|
}
|
|
16893
17223
|
const conversations = mergeSessionListings(listings, {
|
|
16894
17224
|
nowMs: opts.nowMs ?? Date.now(),
|
|
16895
17225
|
idleMinutes: opts.idleMinutes
|
|
16896
17226
|
});
|
|
16897
|
-
return { conversations, perAgent };
|
|
17227
|
+
return { conversations, perAgent: derivePerAgent(perStore, conversations), perStore };
|
|
17228
|
+
}
|
|
17229
|
+
function derivePerAgent(perStore, conversations) {
|
|
17230
|
+
const counts = new Map;
|
|
17231
|
+
for (const c of conversations)
|
|
17232
|
+
counts.set(c.agentSlug, (counts.get(c.agentSlug) ?? 0) + 1);
|
|
17233
|
+
const rows = new Map;
|
|
17234
|
+
for (const store of perStore) {
|
|
17235
|
+
for (const slug of store.members) {
|
|
17236
|
+
const existing = rows.get(slug);
|
|
17237
|
+
if (store.status === "ok") {
|
|
17238
|
+
rows.set(slug, { agentSlug: slug, status: "ok", sessions: counts.get(slug) ?? 0 });
|
|
17239
|
+
continue;
|
|
17240
|
+
}
|
|
17241
|
+
if (!existing || existing.status !== "ok") {
|
|
17242
|
+
rows.set(slug, {
|
|
17243
|
+
agentSlug: slug,
|
|
17244
|
+
status: store.status === "orphaned" ? "missing-dir" : store.status,
|
|
17245
|
+
sessions: null,
|
|
17246
|
+
...store.path ? { path: store.path } : {},
|
|
17247
|
+
...store.detail ? { detail: store.detail } : {}
|
|
17248
|
+
});
|
|
17249
|
+
}
|
|
17250
|
+
}
|
|
17251
|
+
}
|
|
17252
|
+
return [...rows.values()];
|
|
16898
17253
|
}
|
|
16899
|
-
var DEFAULT_IDLE_MINUTES = 10;
|
|
17254
|
+
var DEFAULT_IDLE_MINUTES = 10, DEFAULT_MAX_PER_STORE = 500;
|
|
16900
17255
|
var init_conversation_registry = __esm(async () => {
|
|
16901
17256
|
init_transcript_sources();
|
|
17257
|
+
init_transcript_stores();
|
|
16902
17258
|
await init_detect();
|
|
16903
17259
|
});
|
|
16904
17260
|
|
|
16905
17261
|
// src/reflect/session-summary.ts
|
|
16906
17262
|
import { createHash as createHash4 } from "crypto";
|
|
16907
17263
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
16908
|
-
import { readFileSync as
|
|
17264
|
+
import { readFileSync as readFileSync36 } from "fs";
|
|
16909
17265
|
import { isAbsolute as isAbsolute4 } from "path";
|
|
16910
17266
|
function validateAssetMarkers(markers, knownSkills) {
|
|
16911
17267
|
if (!markers || markers.length === 0)
|
|
@@ -17007,7 +17363,7 @@ function digestForEntry(entry) {
|
|
|
17007
17363
|
return null;
|
|
17008
17364
|
let content;
|
|
17009
17365
|
try {
|
|
17010
|
-
content =
|
|
17366
|
+
content = readFileSync36(entry.transcriptPath, "utf-8");
|
|
17011
17367
|
} catch {
|
|
17012
17368
|
return null;
|
|
17013
17369
|
}
|
|
@@ -17135,18 +17491,18 @@ var init_session_summary = __esm(() => {
|
|
|
17135
17491
|
});
|
|
17136
17492
|
|
|
17137
17493
|
// src/reflect/telemetry-outbox.ts
|
|
17138
|
-
import { existsSync as
|
|
17139
|
-
import { join as
|
|
17140
|
-
import { homedir as
|
|
17494
|
+
import { existsSync as existsSync47, readFileSync as readFileSync37 } from "fs";
|
|
17495
|
+
import { join as join42 } from "path";
|
|
17496
|
+
import { homedir as homedir23 } from "os";
|
|
17141
17497
|
function outboxPath() {
|
|
17142
|
-
return
|
|
17498
|
+
return join42(homedir23(), ".runwork", "telemetry-outbox.json");
|
|
17143
17499
|
}
|
|
17144
17500
|
function loadTelemetryOutbox() {
|
|
17145
17501
|
try {
|
|
17146
17502
|
const p = outboxPath();
|
|
17147
|
-
if (!
|
|
17503
|
+
if (!existsSync47(p))
|
|
17148
17504
|
return [];
|
|
17149
|
-
const parsed = JSON.parse(
|
|
17505
|
+
const parsed = JSON.parse(readFileSync37(p, "utf-8"));
|
|
17150
17506
|
if (!Array.isArray(parsed))
|
|
17151
17507
|
return [];
|
|
17152
17508
|
return parsed.filter((e) => !!e && typeof e === "object" && typeof e.dedupeKey === "string" && !!e.event && typeof e.event === "object");
|
|
@@ -17207,8 +17563,8 @@ var init_active_time = __esm(() => {
|
|
|
17207
17563
|
|
|
17208
17564
|
// src/reflect/pattern-store.ts
|
|
17209
17565
|
import { createHash as createHash5 } from "crypto";
|
|
17210
|
-
import { join as
|
|
17211
|
-
import { homedir as
|
|
17566
|
+
import { join as join43 } from "path";
|
|
17567
|
+
import { homedir as homedir24 } from "os";
|
|
17212
17568
|
function addBuckets(a, b) {
|
|
17213
17569
|
if (!a)
|
|
17214
17570
|
return b ? { ...b } : null;
|
|
@@ -17369,7 +17725,7 @@ function buildPatternEvent(payload, nowISO) {
|
|
|
17369
17725
|
};
|
|
17370
17726
|
}
|
|
17371
17727
|
function storePath3() {
|
|
17372
|
-
return
|
|
17728
|
+
return join43(homedir24(), ".runwork", "pattern-store.json");
|
|
17373
17729
|
}
|
|
17374
17730
|
function loadPatternStore() {
|
|
17375
17731
|
const parsed = readJsonOrNull(storePath3());
|
|
@@ -17579,7 +17935,7 @@ var init_triage = __esm(async () => {
|
|
|
17579
17935
|
});
|
|
17580
17936
|
|
|
17581
17937
|
// src/reflect/conversation-analysis.ts
|
|
17582
|
-
import { existsSync as
|
|
17938
|
+
import { existsSync as existsSync48 } from "fs";
|
|
17583
17939
|
import { basename as basename5 } from "path";
|
|
17584
17940
|
function brokenAnalystBinaries() {
|
|
17585
17941
|
return TIER2_ANALYSTS.filter((a) => {
|
|
@@ -17607,7 +17963,7 @@ function isPromptStillValid(key) {
|
|
|
17607
17963
|
if (!standing?.promptPath || standing.promptConversationKey !== key)
|
|
17608
17964
|
return false;
|
|
17609
17965
|
try {
|
|
17610
|
-
return
|
|
17966
|
+
return existsSync48(standing.promptPath);
|
|
17611
17967
|
} catch {
|
|
17612
17968
|
return false;
|
|
17613
17969
|
}
|
|
@@ -20661,6 +21017,159 @@ var skillsCommand = new Command13("skills").description("Manage workspace skills
|
|
|
20661
21017
|
// src/index.ts
|
|
20662
21018
|
await init_reflect();
|
|
20663
21019
|
|
|
21020
|
+
// src/commands/conversations.ts
|
|
21021
|
+
init_transcript_stores();
|
|
21022
|
+
await init_detect();
|
|
21023
|
+
import { Command as Command15 } from "commander";
|
|
21024
|
+
import { join as join44 } from "path";
|
|
21025
|
+
import { homedir as homedir25, platform as platform8 } from "os";
|
|
21026
|
+
|
|
21027
|
+
// src/agents/store-census.ts
|
|
21028
|
+
init_transcript_stores();
|
|
21029
|
+
import { readdirSync as readdirSync16, statSync as statSync10, existsSync as existsSync46, openSync as openSync5, readSync as readSync3, closeSync as closeSync5 } from "fs";
|
|
21030
|
+
import { join as join41 } from "path";
|
|
21031
|
+
function sanitizeMarker(raw) {
|
|
21032
|
+
const cleaned = raw.replace(/[^\x20-\x7E]/g, "").trim();
|
|
21033
|
+
return cleaned.length > 64 ? `${cleaned.slice(0, 63)}…` : cleaned;
|
|
21034
|
+
}
|
|
21035
|
+
function readHead(path2, n) {
|
|
21036
|
+
let fd;
|
|
21037
|
+
try {
|
|
21038
|
+
fd = openSync5(path2, "r");
|
|
21039
|
+
const buf = Buffer.alloc(n);
|
|
21040
|
+
const read = readSync3(fd, buf, 0, n, 0);
|
|
21041
|
+
return buf.subarray(0, read).toString("utf-8");
|
|
21042
|
+
} catch {
|
|
21043
|
+
return null;
|
|
21044
|
+
} finally {
|
|
21045
|
+
if (fd !== undefined) {
|
|
21046
|
+
try {
|
|
21047
|
+
closeSync5(fd);
|
|
21048
|
+
} catch {}
|
|
21049
|
+
}
|
|
21050
|
+
}
|
|
21051
|
+
}
|
|
21052
|
+
function isPermissionError(err) {
|
|
21053
|
+
const code = err?.code;
|
|
21054
|
+
return code === "EACCES" || code === "EPERM";
|
|
21055
|
+
}
|
|
21056
|
+
function isMissingError(err) {
|
|
21057
|
+
const code = err?.code;
|
|
21058
|
+
return code === "ENOENT" || code === "ENOTDIR";
|
|
21059
|
+
}
|
|
21060
|
+
function collect(dir, def, out, budget) {
|
|
21061
|
+
if (budget.left <= 0)
|
|
21062
|
+
return;
|
|
21063
|
+
const entries = readdirSync16(dir, { withFileTypes: true });
|
|
21064
|
+
for (const e of entries) {
|
|
21065
|
+
if (budget.left <= 0)
|
|
21066
|
+
return;
|
|
21067
|
+
const full = join41(dir, e.name);
|
|
21068
|
+
if (e.isDirectory()) {
|
|
21069
|
+
try {
|
|
21070
|
+
collect(full, def, out, budget);
|
|
21071
|
+
} catch (err) {
|
|
21072
|
+
if (isPermissionError(err))
|
|
21073
|
+
throw err;
|
|
21074
|
+
}
|
|
21075
|
+
} else if (!def.matches || def.matches(e.name)) {
|
|
21076
|
+
out.push(full);
|
|
21077
|
+
budget.left--;
|
|
21078
|
+
}
|
|
21079
|
+
}
|
|
21080
|
+
}
|
|
21081
|
+
var DEFAULT_MAX_FILES = 2000;
|
|
21082
|
+
function censusStore(store, unlocked, opts = {}) {
|
|
21083
|
+
const { def, path: path2, altPaths } = store;
|
|
21084
|
+
const base = {
|
|
21085
|
+
storeId: def.id,
|
|
21086
|
+
family: def.family,
|
|
21087
|
+
members: def.members,
|
|
21088
|
+
path: path2,
|
|
21089
|
+
unlocked,
|
|
21090
|
+
status: "ok"
|
|
21091
|
+
};
|
|
21092
|
+
const altHits = altPaths.filter((p) => {
|
|
21093
|
+
try {
|
|
21094
|
+
return existsSync46(p);
|
|
21095
|
+
} catch {
|
|
21096
|
+
return false;
|
|
21097
|
+
}
|
|
21098
|
+
});
|
|
21099
|
+
if (altHits.length > 0)
|
|
21100
|
+
base.altHits = altHits;
|
|
21101
|
+
if (!existsSync46(path2))
|
|
21102
|
+
return { ...base, status: "missing" };
|
|
21103
|
+
if (def.kind === "file") {
|
|
21104
|
+
try {
|
|
21105
|
+
const s = statSync10(path2);
|
|
21106
|
+
return { ...base, files: 1, bytes: s.size, newestAt: new Date(s.mtimeMs).toISOString() };
|
|
21107
|
+
} catch (err) {
|
|
21108
|
+
return { ...base, status: isPermissionError(err) ? "permission-denied" : "error", detail: String(err) };
|
|
21109
|
+
}
|
|
21110
|
+
}
|
|
21111
|
+
const all = [];
|
|
21112
|
+
const budget = { left: opts.maxFiles ?? DEFAULT_MAX_FILES };
|
|
21113
|
+
try {
|
|
21114
|
+
collect(path2, def, all, budget);
|
|
21115
|
+
} catch (err) {
|
|
21116
|
+
if (isPermissionError(err))
|
|
21117
|
+
return { ...base, status: "permission-denied", detail: "EACCES" };
|
|
21118
|
+
if (isMissingError(err))
|
|
21119
|
+
return { ...base, status: "missing" };
|
|
21120
|
+
return { ...base, status: "error", detail: err instanceof Error ? err.message : String(err) };
|
|
21121
|
+
}
|
|
21122
|
+
const files = [];
|
|
21123
|
+
let nested = 0;
|
|
21124
|
+
for (const f of all) {
|
|
21125
|
+
const rel = f.slice(path2.length).replace(/^[\\/]+/, "");
|
|
21126
|
+
if (def.subordinate?.(rel))
|
|
21127
|
+
nested++;
|
|
21128
|
+
else
|
|
21129
|
+
files.push(f);
|
|
21130
|
+
}
|
|
21131
|
+
let bytes = 0;
|
|
21132
|
+
let newest = 0;
|
|
21133
|
+
for (const f of all) {
|
|
21134
|
+
try {
|
|
21135
|
+
const s = statSync10(f);
|
|
21136
|
+
bytes += s.size;
|
|
21137
|
+
if (s.mtimeMs > newest)
|
|
21138
|
+
newest = s.mtimeMs;
|
|
21139
|
+
} catch {}
|
|
21140
|
+
}
|
|
21141
|
+
const result = {
|
|
21142
|
+
...base,
|
|
21143
|
+
files: files.length,
|
|
21144
|
+
...nested > 0 ? { nested } : {},
|
|
21145
|
+
bytes,
|
|
21146
|
+
newestAt: newest > 0 ? new Date(newest).toISOString() : null
|
|
21147
|
+
};
|
|
21148
|
+
if (opts.skipMarkers || !def.marker)
|
|
21149
|
+
return result;
|
|
21150
|
+
const counts = new Map;
|
|
21151
|
+
for (const f of files) {
|
|
21152
|
+
const head = readHead(f, def.headBytes ?? 64 * 1024);
|
|
21153
|
+
const { agentSlug, marker, recognised } = attributeTranscript(def, head);
|
|
21154
|
+
const clean = marker === null ? null : sanitizeMarker(marker);
|
|
21155
|
+
const key = clean ?? "\x00none";
|
|
21156
|
+
const existing = counts.get(key);
|
|
21157
|
+
if (existing)
|
|
21158
|
+
existing.count++;
|
|
21159
|
+
else
|
|
21160
|
+
counts.set(key, { marker: clean, count: 1, agentSlug, recognised });
|
|
21161
|
+
}
|
|
21162
|
+
result.markers = [...counts.values()].sort((a, b) => b.count - a.count);
|
|
21163
|
+
return result;
|
|
21164
|
+
}
|
|
21165
|
+
function censusStores(stores, detectedSlugs, opts = {}) {
|
|
21166
|
+
const detected = new Set(detectedSlugs);
|
|
21167
|
+
return stores.map((store) => censusStore(store, isStoreUnlocked(store.def, detected), opts));
|
|
21168
|
+
}
|
|
21169
|
+
function orphanedStoresWithContent(censuses) {
|
|
21170
|
+
return censuses.filter((c) => !c.unlocked && c.status === "ok" && (c.files ?? 0) > 0);
|
|
21171
|
+
}
|
|
21172
|
+
|
|
20664
21173
|
// src/commands/conversations.ts
|
|
20665
21174
|
init_conversation_queue();
|
|
20666
21175
|
init_session_summary();
|
|
@@ -20676,10 +21185,7 @@ await __promiseAll([
|
|
|
20676
21185
|
init_conversation_registry(),
|
|
20677
21186
|
init_conversation_analysis()
|
|
20678
21187
|
]);
|
|
20679
|
-
|
|
20680
|
-
import { join as join43 } from "path";
|
|
20681
|
-
import { homedir as homedir24 } from "os";
|
|
20682
|
-
var DEFAULT_LOOKBACK_DAYS = 30;
|
|
21188
|
+
var DEFAULT_LOOKBACK_DAYS = 0;
|
|
20683
21189
|
function sinceFromDays(days) {
|
|
20684
21190
|
if (days <= 0)
|
|
20685
21191
|
return null;
|
|
@@ -20743,18 +21249,25 @@ function fit(text2, width) {
|
|
|
20743
21249
|
return text2.length > width ? text2.slice(0, width - 1) + "…" : text2;
|
|
20744
21250
|
}
|
|
20745
21251
|
var conversationsCommand = new Command15("conversations").description("Local AI conversations across your agents (registry, end detection)");
|
|
20746
|
-
conversationsCommand.command("list").description("List local conversations across all detected agents (metadata only)").option("--days <n>", "
|
|
21252
|
+
conversationsCommand.command("list").description("List local conversations across all detected agents (metadata only)").option("--days <n>", "Narrow to this many days (0 = no window, the default)", String(DEFAULT_LOOKBACK_DAYS)).option("--idle-minutes <n>", "Idle threshold that marks a conversation finished", String(DEFAULT_IDLE_MINUTES)).action(async (opts, command) => {
|
|
20747
21253
|
const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
|
|
20748
21254
|
const days = parseDays(opts.days);
|
|
20749
21255
|
const idleMinutes = Math.max(1, Number(opts.idleMinutes) || DEFAULT_IDLE_MINUTES);
|
|
20750
21256
|
const result = await listLocalConversations({ sinceISO: sinceFromDays(days), idleMinutes });
|
|
20751
21257
|
if (json) {
|
|
20752
|
-
jsonOut({ conversations: result.conversations, perAgent: result.perAgent });
|
|
21258
|
+
jsonOut({ conversations: result.conversations, perAgent: result.perAgent, perStore: result.perStore });
|
|
20753
21259
|
return;
|
|
20754
21260
|
}
|
|
20755
21261
|
console.log(bold(days > 0 ? `
|
|
20756
21262
|
Local conversations, last ${days} day(s)` : `
|
|
20757
21263
|
Local conversations (all)`));
|
|
21264
|
+
for (const s of result.perStore) {
|
|
21265
|
+
const reason = describeStoreOutcome(s);
|
|
21266
|
+
if (reason === null)
|
|
21267
|
+
continue;
|
|
21268
|
+
const line = ` ${s.storeId}: ${reason}`;
|
|
21269
|
+
console.log(storeOutcomeNeedsAttention(s) ? yellow(line) : dim(line));
|
|
21270
|
+
}
|
|
20758
21271
|
for (const a of result.perAgent) {
|
|
20759
21272
|
if (a.status === "no-reader")
|
|
20760
21273
|
continue;
|
|
@@ -20780,17 +21293,26 @@ Local conversations (all)`));
|
|
|
20780
21293
|
if (result.conversations.length === 0)
|
|
20781
21294
|
console.log(dim(" none"));
|
|
20782
21295
|
});
|
|
20783
|
-
conversationsCommand.command("status").description("Why each agent did or did not contribute conversations (no conversation data)").option("--days <n>", "
|
|
21296
|
+
conversationsCommand.command("status").description("Why each agent did or did not contribute conversations (no conversation data)").option("--days <n>", "Narrow to this many days (0 = no window, the default)", String(DEFAULT_LOOKBACK_DAYS)).action(async (opts, command) => {
|
|
20784
21297
|
const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
|
|
20785
21298
|
const days = parseDays(opts.days);
|
|
20786
|
-
const { perAgent } = await listLocalConversations({ sinceISO: sinceFromDays(days) });
|
|
21299
|
+
const { perAgent, perStore } = await listLocalConversations({ sinceISO: sinceFromDays(days) });
|
|
20787
21300
|
if (json) {
|
|
20788
|
-
jsonOut({ perAgent });
|
|
21301
|
+
jsonOut({ perAgent, perStore });
|
|
20789
21302
|
return;
|
|
20790
21303
|
}
|
|
20791
21304
|
console.log(bold(days > 0 ? `
|
|
20792
21305
|
Conversation sources, last ${days} day(s)` : `
|
|
20793
21306
|
Conversation sources`));
|
|
21307
|
+
for (const s of perStore) {
|
|
21308
|
+
const reason = describeStoreOutcome(s);
|
|
21309
|
+
if (reason === null) {
|
|
21310
|
+
console.log(` ${cyan(s.storeId)}: ${s.sessions} conversation(s)`);
|
|
21311
|
+
} else {
|
|
21312
|
+
console.log(` ${cyan(s.storeId)}: ${storeOutcomeNeedsAttention(s) ? yellow(reason) : dim(reason)}`);
|
|
21313
|
+
}
|
|
21314
|
+
}
|
|
21315
|
+
console.log("");
|
|
20794
21316
|
for (const a of perAgent) {
|
|
20795
21317
|
const reason = describeScanOutcome(a);
|
|
20796
21318
|
if (reason === null) {
|
|
@@ -20800,7 +21322,7 @@ Conversation sources`));
|
|
|
20800
21322
|
}
|
|
20801
21323
|
}
|
|
20802
21324
|
});
|
|
20803
|
-
conversationsCommand.command("scan").description("Detect finished conversations (idle threshold) and queue them for reflection").option("--days <n>", "
|
|
21325
|
+
conversationsCommand.command("scan").description("Detect finished conversations (idle threshold) and queue them for reflection").option("--days <n>", "Narrow to this many days (0 = no window, the default)", String(DEFAULT_LOOKBACK_DAYS)).option("--idle-minutes <n>", "Idle threshold that marks a conversation finished", String(DEFAULT_IDLE_MINUTES)).action(async (opts, command) => {
|
|
20804
21326
|
const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
|
|
20805
21327
|
const days = parseDays(opts.days);
|
|
20806
21328
|
const idleMinutes = Math.max(1, Number(opts.idleMinutes) || DEFAULT_IDLE_MINUTES);
|
|
@@ -20864,9 +21386,10 @@ conversationsCommand.command("scan").description("Detect finished conversations
|
|
|
20864
21386
|
generatedAt: new Date().toISOString(),
|
|
20865
21387
|
idleMinutes,
|
|
20866
21388
|
conversations: [...listed, ...rescued].sort((a, b) => b.lastActivityAt.localeCompare(a.lastActivityAt)),
|
|
20867
|
-
perAgent: result.perAgent
|
|
21389
|
+
perAgent: result.perAgent,
|
|
21390
|
+
perStore: result.perStore
|
|
20868
21391
|
};
|
|
20869
|
-
writeJsonAtomic(
|
|
21392
|
+
writeJsonAtomic(join44(homedir25(), ".runwork", "conversations.json"), snapshot);
|
|
20870
21393
|
if (json) {
|
|
20871
21394
|
jsonOut({ queued: scan.queued, reopened: scan.reopened, pruned: scan.pruned, pending, finished: finished.length, perAgent: result.perAgent });
|
|
20872
21395
|
return;
|
|
@@ -20889,15 +21412,71 @@ conversationsCommand.command("analyze").description("Analyze queued finished con
|
|
|
20889
21412
|
}
|
|
20890
21413
|
console.log(outcome.reason ? dim(describeAnalysisOutcome(outcome)) : green(describeAnalysisOutcome(outcome)));
|
|
20891
21414
|
});
|
|
21415
|
+
conversationsCommand.command("stores").description("Every local transcript store: what is in it, who wrote it, and whether anything reads it").option("--max-files <n>", "Cap transcripts inspected per store", String(DEFAULT_MAX_FILES)).option("--no-markers", "Skip provenance reads; counts, sizes and mtimes only").action(async (opts, command) => {
|
|
21416
|
+
const json = command.optsWithGlobals().json === true || !process.stdout.isTTY;
|
|
21417
|
+
const maxFiles = Math.max(1, Number(opts.maxFiles) || DEFAULT_MAX_FILES);
|
|
21418
|
+
const detected = (await detectAgents()).map((a) => a.slug);
|
|
21419
|
+
const stores = resolveTranscriptStores({
|
|
21420
|
+
platform: platform8(),
|
|
21421
|
+
homeDir: homedir25(),
|
|
21422
|
+
appData: process.env.APPDATA ?? null,
|
|
21423
|
+
localAppData: process.env.LOCALAPPDATA ?? null
|
|
21424
|
+
});
|
|
21425
|
+
const censuses = censusStores(stores, detected, {
|
|
21426
|
+
maxFiles,
|
|
21427
|
+
skipMarkers: opts.markers === false
|
|
21428
|
+
});
|
|
21429
|
+
if (json) {
|
|
21430
|
+
jsonOut({ detected, stores: censuses });
|
|
21431
|
+
return;
|
|
21432
|
+
}
|
|
21433
|
+
console.log(bold(`
|
|
21434
|
+
Transcript stores`));
|
|
21435
|
+
console.log(dim(` detected agents: ${detected.length > 0 ? detected.join(", ") : "none"}
|
|
21436
|
+
`));
|
|
21437
|
+
for (const c of censuses) {
|
|
21438
|
+
const owner = c.unlocked ? green("read") : yellow("ORPHANED");
|
|
21439
|
+
console.log(`${bold(c.storeId)} ${owner} ${dim(`family ${c.family}: ${c.members.join(", ")}`)}`);
|
|
21440
|
+
console.log(dim(` ${c.path}`));
|
|
21441
|
+
if (c.status !== "ok") {
|
|
21442
|
+
console.log(` ${yellow(c.status)}${c.detail ? dim(` (${c.detail})`) : ""}`);
|
|
21443
|
+
} else {
|
|
21444
|
+
const mb = ((c.bytes ?? 0) / 1e6).toFixed(1);
|
|
21445
|
+
const newest = c.newestAt ? c.newestAt.slice(0, 16).replace("T", " ") : "-";
|
|
21446
|
+
const nested = c.nested ? `, plus ${c.nested} subagent transcript(s)` : "";
|
|
21447
|
+
console.log(dim(` ${c.files} conversation(s)${nested}, ${mb} MB, newest ${newest}`));
|
|
21448
|
+
for (const m of c.markers ?? []) {
|
|
21449
|
+
if (m.marker === null) {
|
|
21450
|
+
console.log(` ${String(m.count).padStart(5)} ${dim(`(no marker, pre-dates the field) -> ${m.agentSlug}`)}`);
|
|
21451
|
+
continue;
|
|
21452
|
+
}
|
|
21453
|
+
const flag = m.recognised ? dim(`-> ${m.agentSlug}`) : yellow(`-> ${m.agentSlug} (UNRECOGNISED surface)`);
|
|
21454
|
+
console.log(` ${String(m.count).padStart(5)} ${cyan(m.marker)} ${flag}`);
|
|
21455
|
+
}
|
|
21456
|
+
}
|
|
21457
|
+
for (const alt of c.altHits ?? []) {
|
|
21458
|
+
console.log(` ${yellow("also present:")} ${dim(alt)}`);
|
|
21459
|
+
}
|
|
21460
|
+
console.log("");
|
|
21461
|
+
}
|
|
21462
|
+
const orphans = orphanedStoresWithContent(censuses);
|
|
21463
|
+
if (orphans.length > 0) {
|
|
21464
|
+
console.log(yellow(`${orphans.length} store(s) hold transcripts that no detected agent reads:`));
|
|
21465
|
+
for (const o of orphans) {
|
|
21466
|
+
console.log(` ${o.path} ${dim(`(${o.files} transcripts; needs one of: ${o.members.join(", ")})`)}`);
|
|
21467
|
+
}
|
|
21468
|
+
console.log("");
|
|
21469
|
+
}
|
|
21470
|
+
});
|
|
20892
21471
|
|
|
20893
21472
|
// src/commands/instructions.ts
|
|
20894
21473
|
init_store();
|
|
20895
21474
|
init_client();
|
|
20896
21475
|
init_resolve();
|
|
20897
21476
|
import { Command as Command16 } from "commander";
|
|
20898
|
-
import { readFileSync as
|
|
20899
|
-
import { join as
|
|
20900
|
-
import { homedir as
|
|
21477
|
+
import { readFileSync as readFileSync38, existsSync as existsSync49 } from "fs";
|
|
21478
|
+
import { join as join45 } from "path";
|
|
21479
|
+
import { homedir as homedir26 } from "os";
|
|
20901
21480
|
|
|
20902
21481
|
// ../../shared/agent-instructions/runwork-instructions.ts
|
|
20903
21482
|
function formatList(items, max = 8) {
|
|
@@ -21377,13 +21956,13 @@ async function buildInstructionContext(client, workspace) {
|
|
|
21377
21956
|
// src/commands/instructions.ts
|
|
21378
21957
|
function readSetupExtras(workspaceId) {
|
|
21379
21958
|
for (const path2 of [
|
|
21380
|
-
|
|
21381
|
-
|
|
21959
|
+
join45(process.cwd(), ".runwork", "setup.json"),
|
|
21960
|
+
join45(homedir26(), ".runwork", "setup.json")
|
|
21382
21961
|
]) {
|
|
21383
|
-
if (!
|
|
21962
|
+
if (!existsSync49(path2))
|
|
21384
21963
|
continue;
|
|
21385
21964
|
try {
|
|
21386
|
-
const state = JSON.parse(
|
|
21965
|
+
const state = JSON.parse(readFileSync38(path2, "utf-8"));
|
|
21387
21966
|
if (state.workspaceId === workspaceId) {
|
|
21388
21967
|
return { workspaceSlug: state.workspaceSlug, persona: state.persona };
|
|
21389
21968
|
}
|
|
@@ -21427,16 +22006,16 @@ import { Command as Command17 } from "commander";
|
|
|
21427
22006
|
import * as path3 from "node:path";
|
|
21428
22007
|
|
|
21429
22008
|
// src/utils/data-input.ts
|
|
21430
|
-
import { readFileSync as
|
|
22009
|
+
import { readFileSync as readFileSync39, existsSync as existsSync50 } from "fs";
|
|
21431
22010
|
async function parseDataInput(dataFlag) {
|
|
21432
22011
|
if (dataFlag) {
|
|
21433
22012
|
if (dataFlag.startsWith("@")) {
|
|
21434
22013
|
const filePath = dataFlag.slice(1);
|
|
21435
|
-
if (!
|
|
22014
|
+
if (!existsSync50(filePath)) {
|
|
21436
22015
|
console.error(`File not found: ${filePath}`);
|
|
21437
22016
|
process.exit(1);
|
|
21438
22017
|
}
|
|
21439
|
-
const content =
|
|
22018
|
+
const content = readFileSync39(filePath, "utf-8");
|
|
21440
22019
|
return parseJson(content, filePath);
|
|
21441
22020
|
}
|
|
21442
22021
|
return parseJson(dataFlag, "--data");
|
|
@@ -22490,7 +23069,7 @@ init_resolve();
|
|
|
22490
23069
|
init_prompt();
|
|
22491
23070
|
init_http();
|
|
22492
23071
|
import { Command as Command21 } from "commander";
|
|
22493
|
-
import { writeFileSync as writeFileSync29, readFileSync as
|
|
23072
|
+
import { writeFileSync as writeFileSync29, readFileSync as readFileSync40 } from "fs";
|
|
22494
23073
|
import { basename as basename6 } from "path";
|
|
22495
23074
|
function formatSize(bytes) {
|
|
22496
23075
|
if (bytes === undefined)
|
|
@@ -22600,7 +23179,7 @@ var uploadCommand = new Command21("upload").description("Upload a local file to
|
|
|
22600
23179
|
const { workspaceId } = await resolveWorkspace2(client, opts);
|
|
22601
23180
|
const objectKey = key || basename6(localPath);
|
|
22602
23181
|
try {
|
|
22603
|
-
const fileBuffer =
|
|
23182
|
+
const fileBuffer = readFileSync40(localPath);
|
|
22604
23183
|
const { url } = await client.getPresignedUrl(workspaceId, bucket, { action: "write", key: objectKey });
|
|
22605
23184
|
const response = await httpFetch(url, { method: "PUT", body: fileBuffer });
|
|
22606
23185
|
if (!response.ok) {
|
|
@@ -23117,8 +23696,8 @@ init_resolve();
|
|
|
23117
23696
|
init_prompt();
|
|
23118
23697
|
await init_detect();
|
|
23119
23698
|
import { Command as Command27 } from "commander";
|
|
23120
|
-
import { join as
|
|
23121
|
-
import { homedir as
|
|
23699
|
+
import { join as join50 } from "path";
|
|
23700
|
+
import { homedir as homedir29 } from "os";
|
|
23122
23701
|
|
|
23123
23702
|
// src/commands/sync.ts
|
|
23124
23703
|
init_store();
|
|
@@ -23129,9 +23708,9 @@ await __promiseAll([
|
|
|
23129
23708
|
init_codex()
|
|
23130
23709
|
]);
|
|
23131
23710
|
import { Command as Command26 } from "commander";
|
|
23132
|
-
import { readFileSync as
|
|
23133
|
-
import { join as
|
|
23134
|
-
import { homedir as
|
|
23711
|
+
import { readFileSync as readFileSync42, existsSync as existsSync53 } from "fs";
|
|
23712
|
+
import { join as join49 } from "path";
|
|
23713
|
+
import { homedir as homedir28 } from "os";
|
|
23135
23714
|
|
|
23136
23715
|
// src/commands/mcp-entries.ts
|
|
23137
23716
|
init_types();
|
|
@@ -23195,6 +23774,7 @@ var RUNWORK_AGENT_DEFAULTS = {
|
|
|
23195
23774
|
};
|
|
23196
23775
|
var AGENT_DEFAULTS_SCHEMA_VERSION = 1;
|
|
23197
23776
|
// src/commands/sync-telemetry.ts
|
|
23777
|
+
init_transcript_stores();
|
|
23198
23778
|
var TELEMETRY_BACKFILL_MS = 30 * 24 * 60 * 60 * 1000;
|
|
23199
23779
|
function resolveTelemetrySince(state, nowMs = Date.now()) {
|
|
23200
23780
|
if (state.lastTelemetryAt)
|
|
@@ -23205,11 +23785,20 @@ async function collectTelemetryEvents(params) {
|
|
|
23205
23785
|
const now = params.now ?? new Date().toISOString();
|
|
23206
23786
|
const events = [];
|
|
23207
23787
|
const adapterResults = [];
|
|
23788
|
+
const bySlug = new Map(params.adapters.map((a) => [a.slug, a]));
|
|
23789
|
+
const suppressed = suppressedStoreReaders(params.adapters.map((a) => a.slug), (a, b) => {
|
|
23790
|
+
const left = bySlug.get(a);
|
|
23791
|
+
const right = bySlug.get(b);
|
|
23792
|
+
if (!left || !right)
|
|
23793
|
+
return false;
|
|
23794
|
+
return left.readUsageStats !== undefined && left.readUsageStats === right.readUsageStats || left.readSkillUsage !== undefined && left.readSkillUsage === right.readSkillUsage;
|
|
23795
|
+
});
|
|
23208
23796
|
for (const adapter2 of params.adapters) {
|
|
23209
23797
|
let stats = "unsupported";
|
|
23210
23798
|
let skills = "unsupported";
|
|
23211
23799
|
let error;
|
|
23212
|
-
|
|
23800
|
+
const readsStore = !suppressed.has(adapter2.slug);
|
|
23801
|
+
if (adapter2.readUsageStats && readsStore) {
|
|
23213
23802
|
try {
|
|
23214
23803
|
stats = await adapter2.readUsageStats(params.since);
|
|
23215
23804
|
if (stats && stats.hasNewActivity) {
|
|
@@ -23237,7 +23826,7 @@ async function collectTelemetryEvents(params) {
|
|
|
23237
23826
|
stats = null;
|
|
23238
23827
|
}
|
|
23239
23828
|
}
|
|
23240
|
-
if (adapter2.readSkillUsage) {
|
|
23829
|
+
if (adapter2.readSkillUsage && readsStore) {
|
|
23241
23830
|
try {
|
|
23242
23831
|
skills = await adapter2.readSkillUsage(params.since);
|
|
23243
23832
|
if (skills && skills.length > 0) {
|
|
@@ -24013,10 +24602,10 @@ function sameStringSet(a, b) {
|
|
|
24013
24602
|
}
|
|
24014
24603
|
|
|
24015
24604
|
// src/utils/sync-lock.ts
|
|
24016
|
-
import { existsSync as
|
|
24017
|
-
import { join as
|
|
24018
|
-
import { homedir as
|
|
24019
|
-
var LOCK_PATH =
|
|
24605
|
+
import { existsSync as existsSync52, mkdirSync as mkdirSync28, readFileSync as readFileSync41, unlinkSync as unlinkSync8, writeFileSync as writeFileSync30 } from "fs";
|
|
24606
|
+
import { join as join48 } from "path";
|
|
24607
|
+
import { homedir as homedir27 } from "os";
|
|
24608
|
+
var LOCK_PATH = join48(homedir27(), ".runwork", "sync.lock");
|
|
24020
24609
|
var STALE_LOCK_MS = 5 * 60 * 1000;
|
|
24021
24610
|
var DEFAULT_WAIT_MS = 30000;
|
|
24022
24611
|
var exitHandlerRegistered = false;
|
|
@@ -24036,15 +24625,15 @@ function isProcessAlive(pid) {
|
|
|
24036
24625
|
}
|
|
24037
24626
|
function readLock() {
|
|
24038
24627
|
try {
|
|
24039
|
-
return JSON.parse(
|
|
24628
|
+
return JSON.parse(readFileSync41(LOCK_PATH, "utf-8"));
|
|
24040
24629
|
} catch {
|
|
24041
24630
|
return null;
|
|
24042
24631
|
}
|
|
24043
24632
|
}
|
|
24044
24633
|
function writeLockExclusive() {
|
|
24045
24634
|
try {
|
|
24046
|
-
if (!
|
|
24047
|
-
mkdirSync28(
|
|
24635
|
+
if (!existsSync52(join48(homedir27(), ".runwork"))) {
|
|
24636
|
+
mkdirSync28(join48(homedir27(), ".runwork"), { recursive: true });
|
|
24048
24637
|
}
|
|
24049
24638
|
writeFileSync30(LOCK_PATH, JSON.stringify({ pid: process.pid, startedAt: Date.now() }), {
|
|
24050
24639
|
flag: "wx"
|
|
@@ -24113,10 +24702,10 @@ Tip: ${hint.title}`);
|
|
|
24113
24702
|
} catch {}
|
|
24114
24703
|
}
|
|
24115
24704
|
function loadSetupState(filePath) {
|
|
24116
|
-
if (!
|
|
24705
|
+
if (!existsSync53(filePath))
|
|
24117
24706
|
return null;
|
|
24118
24707
|
try {
|
|
24119
|
-
return JSON.parse(
|
|
24708
|
+
return JSON.parse(readFileSync42(filePath, "utf-8"));
|
|
24120
24709
|
} catch {
|
|
24121
24710
|
return null;
|
|
24122
24711
|
}
|
|
@@ -24137,15 +24726,15 @@ function readLocalSkills(state) {
|
|
|
24137
24726
|
if (!baseDir)
|
|
24138
24727
|
continue;
|
|
24139
24728
|
for (const skillName of state.skills) {
|
|
24140
|
-
const skillMdPath =
|
|
24141
|
-
if (
|
|
24142
|
-
results.push({ name: skillName, content:
|
|
24729
|
+
const skillMdPath = join49(baseDir, skillName, "SKILL.md");
|
|
24730
|
+
if (existsSync53(skillMdPath)) {
|
|
24731
|
+
results.push({ name: skillName, content: readFileSync42(skillMdPath, "utf-8") });
|
|
24143
24732
|
continue;
|
|
24144
24733
|
}
|
|
24145
24734
|
const filename = skillName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
24146
|
-
const flatPath =
|
|
24147
|
-
if (
|
|
24148
|
-
results.push({ name: skillName, content:
|
|
24735
|
+
const flatPath = join49(baseDir, `${filename}.md`);
|
|
24736
|
+
if (existsSync53(flatPath)) {
|
|
24737
|
+
results.push({ name: skillName, content: readFileSync42(flatPath, "utf-8") });
|
|
24149
24738
|
}
|
|
24150
24739
|
}
|
|
24151
24740
|
if (results.length > 0)
|
|
@@ -24399,9 +24988,9 @@ This account is not a member of "${state.workspaceName || state.workspaceId}".`)
|
|
|
24399
24988
|
persona: state.persona
|
|
24400
24989
|
});
|
|
24401
24990
|
let projectAppSkillFilter = null;
|
|
24402
|
-
if (
|
|
24991
|
+
if (existsSync53(".runwork.json")) {
|
|
24403
24992
|
try {
|
|
24404
|
-
const config = JSON.parse(
|
|
24993
|
+
const config = JSON.parse(readFileSync42(".runwork.json", "utf-8"));
|
|
24405
24994
|
if (config.appName) {
|
|
24406
24995
|
projectAppSkillFilter = config.appName.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
24407
24996
|
}
|
|
@@ -24670,7 +25259,7 @@ This account is not a member of "${state.workspaceName || state.workspaceId}".`)
|
|
|
24670
25259
|
}
|
|
24671
25260
|
for (const adapter2 of adapters) {
|
|
24672
25261
|
if (adapter2 instanceof CodexAdapter) {
|
|
24673
|
-
const runworkDir =
|
|
25262
|
+
const runworkDir = join49(homedir28(), ".runwork");
|
|
24674
25263
|
const result = adapter2.registerDesktopWorkspace(runworkDir, "Runwork");
|
|
24675
25264
|
if (result === "written") {
|
|
24676
25265
|
vlog(` [${adapter2.name}] Registered workspace in Codex desktop app`);
|
|
@@ -24830,8 +25419,8 @@ var syncCommand = new Command26("sync").description("Sync skills bidirectionally
|
|
|
24830
25419
|
verbose: !!opts.verbose,
|
|
24831
25420
|
redetect: !!opts.redetect
|
|
24832
25421
|
};
|
|
24833
|
-
const projectStatePath =
|
|
24834
|
-
const userStatePath =
|
|
25422
|
+
const projectStatePath = join49(process.cwd(), ".runwork", "setup.json");
|
|
25423
|
+
const userStatePath = join49(homedir28(), ".runwork", "setup.json");
|
|
24835
25424
|
const projectState = loadSetupState(projectStatePath);
|
|
24836
25425
|
const userState = loadSetupState(userStatePath);
|
|
24837
25426
|
if (!projectState && !userState) {
|
|
@@ -24900,7 +25489,7 @@ function toSkillFilename(name) {
|
|
|
24900
25489
|
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
|
|
24901
25490
|
}
|
|
24902
25491
|
function loadSetupStateForScope(scope) {
|
|
24903
|
-
const path4 = scope === "project" ?
|
|
25492
|
+
const path4 = scope === "project" ? join50(process.cwd(), ".runwork", "setup.json") : join50(homedir29(), ".runwork", "setup.json");
|
|
24904
25493
|
return readJsonOrNull(path4);
|
|
24905
25494
|
}
|
|
24906
25495
|
async function parkAndTeardownWorkspace(previous, scopes) {
|
|
@@ -25069,8 +25658,8 @@ Re-run without --dry-run to sync workspace data.`);
|
|
|
25069
25658
|
}
|
|
25070
25659
|
persistDefaultWorkspace(workspaceId, workspaceName);
|
|
25071
25660
|
for (const s of scopes) {
|
|
25072
|
-
const dir = s === "project" ? ".runwork" :
|
|
25073
|
-
writeJsonAtomic(
|
|
25661
|
+
const dir = s === "project" ? ".runwork" : join50(homedir29(), ".runwork");
|
|
25662
|
+
writeJsonAtomic(join50(dir, "setup.json"), state);
|
|
25074
25663
|
}
|
|
25075
25664
|
if (restored)
|
|
25076
25665
|
clearParkedState(workspaceId);
|
|
@@ -25078,7 +25667,7 @@ Re-run without --dry-run to sync workspace data.`);
|
|
|
25078
25667
|
Syncing workspace data...
|
|
25079
25668
|
`);
|
|
25080
25669
|
for (const s of scopes) {
|
|
25081
|
-
const statePath2 = s === "project" ?
|
|
25670
|
+
const statePath2 = s === "project" ? join50(process.cwd(), ".runwork", "setup.json") : join50(homedir29(), ".runwork", "setup.json");
|
|
25082
25671
|
await syncFromState(state, statePath2, credentials, {
|
|
25083
25672
|
dryRun: false,
|
|
25084
25673
|
pullOnly: true,
|
|
@@ -25098,16 +25687,16 @@ init_client();
|
|
|
25098
25687
|
import { Command as Command28 } from "commander";
|
|
25099
25688
|
|
|
25100
25689
|
// src/utils/setup-state.ts
|
|
25101
|
-
import { existsSync as
|
|
25102
|
-
import { join as
|
|
25103
|
-
import { homedir as
|
|
25690
|
+
import { existsSync as existsSync54, readFileSync as readFileSync43 } from "fs";
|
|
25691
|
+
import { join as join51 } from "path";
|
|
25692
|
+
import { homedir as homedir30 } from "os";
|
|
25104
25693
|
function loadSetupState2() {
|
|
25105
|
-
const projectPath =
|
|
25106
|
-
const userPath =
|
|
25694
|
+
const projectPath = join51(process.cwd(), ".runwork", "setup.json");
|
|
25695
|
+
const userPath = join51(homedir30(), ".runwork", "setup.json");
|
|
25107
25696
|
for (const p of [projectPath, userPath]) {
|
|
25108
|
-
if (
|
|
25697
|
+
if (existsSync54(p)) {
|
|
25109
25698
|
try {
|
|
25110
|
-
return JSON.parse(
|
|
25699
|
+
return JSON.parse(readFileSync43(p, "utf-8"));
|
|
25111
25700
|
} catch {
|
|
25112
25701
|
continue;
|
|
25113
25702
|
}
|
|
@@ -25166,14 +25755,14 @@ init_client();
|
|
|
25166
25755
|
init_types();
|
|
25167
25756
|
await init_detect();
|
|
25168
25757
|
import { Command as Command29 } from "commander";
|
|
25169
|
-
import { existsSync as
|
|
25170
|
-
import { resolve as resolve3, join as
|
|
25171
|
-
import { homedir as
|
|
25758
|
+
import { existsSync as existsSync55, readFileSync as readFileSync44 } from "fs";
|
|
25759
|
+
import { resolve as resolve3, join as join52 } from "path";
|
|
25760
|
+
import { homedir as homedir31 } from "os";
|
|
25172
25761
|
function loadSetupState3(filePath) {
|
|
25173
|
-
if (!
|
|
25762
|
+
if (!existsSync55(filePath))
|
|
25174
25763
|
return null;
|
|
25175
25764
|
try {
|
|
25176
|
-
return JSON.parse(
|
|
25765
|
+
return JSON.parse(readFileSync44(filePath, "utf-8"));
|
|
25177
25766
|
} catch {
|
|
25178
25767
|
return null;
|
|
25179
25768
|
}
|
|
@@ -25189,8 +25778,8 @@ var buildPluginCommand = new Command29("build-plugin").description("Build an ins
|
|
|
25189
25778
|
process.exit(1);
|
|
25190
25779
|
}
|
|
25191
25780
|
const credentials = requireAuth();
|
|
25192
|
-
const projectStatePath =
|
|
25193
|
-
const userStatePath =
|
|
25781
|
+
const projectStatePath = join52(process.cwd(), ".runwork", "setup.json");
|
|
25782
|
+
const userStatePath = join52(homedir31(), ".runwork", "setup.json");
|
|
25194
25783
|
const state = loadSetupState3(projectStatePath) ?? loadSetupState3(userStatePath);
|
|
25195
25784
|
if (!state) {
|
|
25196
25785
|
console.error("No setup state found. Run `runwork setup` first.");
|
|
@@ -25283,14 +25872,14 @@ init_prompt();
|
|
|
25283
25872
|
init_subprocess();
|
|
25284
25873
|
await init_detect();
|
|
25285
25874
|
import { Command as Command30 } from "commander";
|
|
25286
|
-
import { existsSync as
|
|
25287
|
-
import { join as
|
|
25288
|
-
import { homedir as
|
|
25875
|
+
import { existsSync as existsSync56, readFileSync as readFileSync45, writeFileSync as writeFileSync32, readdirSync as readdirSync17, rmSync as rmSync12, unlinkSync as unlinkSync9, lstatSync, readlinkSync } from "fs";
|
|
25876
|
+
import { join as join53, resolve as resolve4, relative as relative5, isAbsolute as isAbsolute5 } from "path";
|
|
25877
|
+
import { homedir as homedir32 } from "os";
|
|
25289
25878
|
function loadSetupState4(filePath) {
|
|
25290
|
-
if (!
|
|
25879
|
+
if (!existsSync56(filePath))
|
|
25291
25880
|
return null;
|
|
25292
25881
|
try {
|
|
25293
|
-
return JSON.parse(
|
|
25882
|
+
return JSON.parse(readFileSync45(filePath, "utf-8"));
|
|
25294
25883
|
} catch {
|
|
25295
25884
|
return null;
|
|
25296
25885
|
}
|
|
@@ -25298,22 +25887,22 @@ function loadSetupState4(filePath) {
|
|
|
25298
25887
|
var PRESERVED_ENTRIES = ["bin", "apps", "trash"];
|
|
25299
25888
|
function removeRunworkState(stateDir, opts) {
|
|
25300
25889
|
const result = { removed: [], preserved: [], errors: [] };
|
|
25301
|
-
if (!
|
|
25890
|
+
if (!existsSync56(stateDir))
|
|
25302
25891
|
return result;
|
|
25303
25892
|
const preserve = new Set(PRESERVED_ENTRIES);
|
|
25304
25893
|
if (opts.keepAuth)
|
|
25305
25894
|
preserve.add(".credentials");
|
|
25306
25895
|
let entries;
|
|
25307
25896
|
try {
|
|
25308
|
-
entries =
|
|
25897
|
+
entries = readdirSync17(stateDir);
|
|
25309
25898
|
} catch (err) {
|
|
25310
25899
|
result.errors.push(`${stateDir}: ${err instanceof Error ? err.message : err}`);
|
|
25311
25900
|
return result;
|
|
25312
25901
|
}
|
|
25313
25902
|
for (const entry of entries) {
|
|
25314
|
-
const target =
|
|
25903
|
+
const target = join53(stateDir, entry);
|
|
25315
25904
|
if (preserve.has(entry)) {
|
|
25316
|
-
if (
|
|
25905
|
+
if (existsSync56(target))
|
|
25317
25906
|
result.preserved.push(target);
|
|
25318
25907
|
continue;
|
|
25319
25908
|
}
|
|
@@ -25329,11 +25918,11 @@ function removeRunworkState(stateDir, opts) {
|
|
|
25329
25918
|
var SHELL_PROFILES = [".zshrc", ".zprofile", ".bashrc", ".bash_profile", ".profile"];
|
|
25330
25919
|
var BIN_DIR_PATTERN = /\.runwork[\\/]bin/;
|
|
25331
25920
|
function stripRunworkPathLines(file) {
|
|
25332
|
-
if (!
|
|
25921
|
+
if (!existsSync56(file))
|
|
25333
25922
|
return false;
|
|
25334
25923
|
let content;
|
|
25335
25924
|
try {
|
|
25336
|
-
content =
|
|
25925
|
+
content = readFileSync45(file, "utf-8");
|
|
25337
25926
|
} catch {
|
|
25338
25927
|
return false;
|
|
25339
25928
|
}
|
|
@@ -25362,7 +25951,7 @@ function stripRunworkPathLines(file) {
|
|
|
25362
25951
|
}
|
|
25363
25952
|
}
|
|
25364
25953
|
function cleanShellProfilePathEntries() {
|
|
25365
|
-
return SHELL_PROFILES.map((name) =>
|
|
25954
|
+
return SHELL_PROFILES.map((name) => join53(homedir32(), name)).filter(stripRunworkPathLines);
|
|
25366
25955
|
}
|
|
25367
25956
|
function cleanPowerShellProfilePathEntries() {
|
|
25368
25957
|
if (process.platform !== "win32")
|
|
@@ -25402,7 +25991,7 @@ function removeRunworkSymlink(linkPath) {
|
|
|
25402
25991
|
} catch {
|
|
25403
25992
|
return false;
|
|
25404
25993
|
}
|
|
25405
|
-
const ours = resolve4(
|
|
25994
|
+
const ours = resolve4(join53(homedir32(), ".runwork", "bin"));
|
|
25406
25995
|
const rel = relative5(ours, resolve4(target));
|
|
25407
25996
|
const insideOurs = rel === "" || !rel.startsWith("..") && !isAbsolute5(rel);
|
|
25408
25997
|
if (!insideOurs)
|
|
@@ -25415,8 +26004,8 @@ function removeRunworkSymlink(linkPath) {
|
|
|
25415
26004
|
}
|
|
25416
26005
|
}
|
|
25417
26006
|
var uninstallCommand = new Command30("uninstall").description("Remove all Runwork configuration from local agents (MCP servers, skills, instructions)").option("-y, --yes", "Skip confirmation prompt").option("--keep-auth", "Keep authentication credentials (only remove agent configs)").action(async (opts) => {
|
|
25418
|
-
const projectStatePath =
|
|
25419
|
-
const userStatePath =
|
|
26007
|
+
const projectStatePath = join53(process.cwd(), ".runwork", "setup.json");
|
|
26008
|
+
const userStatePath = join53(homedir32(), ".runwork", "setup.json");
|
|
25420
26009
|
const projectState = loadSetupState4(projectStatePath);
|
|
25421
26010
|
const userState = loadSetupState4(userStatePath);
|
|
25422
26011
|
if (!projectState && !userState) {
|
|
@@ -25503,8 +26092,8 @@ This will remove all Runwork configuration from your local agents:
|
|
|
25503
26092
|
}
|
|
25504
26093
|
}
|
|
25505
26094
|
}
|
|
25506
|
-
const stateDir = label === "project" ?
|
|
25507
|
-
if (
|
|
26095
|
+
const stateDir = label === "project" ? join53(process.cwd(), ".runwork") : join53(homedir32(), ".runwork");
|
|
26096
|
+
if (existsSync56(stateDir)) {
|
|
25508
26097
|
const outcome = removeRunworkState(stateDir, {
|
|
25509
26098
|
keepAuth: Boolean(opts.keepAuth) && label === "user"
|
|
25510
26099
|
});
|
|
@@ -25534,7 +26123,7 @@ This will remove all Runwork configuration from your local agents:
|
|
|
25534
26123
|
console.log(` - ${file}`);
|
|
25535
26124
|
}
|
|
25536
26125
|
const removedLinks = [
|
|
25537
|
-
|
|
26126
|
+
join53(homedir32(), ".local", "bin", "runwork"),
|
|
25538
26127
|
"/usr/local/bin/runwork"
|
|
25539
26128
|
].filter(removeRunworkSymlink);
|
|
25540
26129
|
if (removedLinks.length > 0) {
|
|
@@ -25546,7 +26135,7 @@ This will remove all Runwork configuration from your local agents:
|
|
|
25546
26135
|
if (process.platform === "win32") {
|
|
25547
26136
|
console.log("");
|
|
25548
26137
|
console.log(" Still on your PATH (remove by hand if you want it gone):");
|
|
25549
|
-
console.log(` ${
|
|
26138
|
+
console.log(` ${join53(homedir32(), ".runwork", "bin")} in your user PATH`);
|
|
25550
26139
|
}
|
|
25551
26140
|
console.log("");
|
|
25552
26141
|
if (errors > 0) {
|
|
@@ -25672,7 +26261,7 @@ var membersCommand = new Command32("members").description("List workspace member
|
|
|
25672
26261
|
init_store();
|
|
25673
26262
|
init_client();
|
|
25674
26263
|
import { Command as Command33 } from "commander";
|
|
25675
|
-
import { readFileSync as
|
|
26264
|
+
import { readFileSync as readFileSync46 } from "fs";
|
|
25676
26265
|
function normalizeApiPath(rawPath, baseUrl) {
|
|
25677
26266
|
if (/^https?:\/\//i.test(rawPath)) {
|
|
25678
26267
|
const target = new URL(rawPath);
|
|
@@ -25705,7 +26294,7 @@ to be read or pasted manually. Prefer a dedicated command when one exists
|
|
|
25705
26294
|
let curlStr = opts.curl;
|
|
25706
26295
|
if (opts.curlFile) {
|
|
25707
26296
|
try {
|
|
25708
|
-
curlStr =
|
|
26297
|
+
curlStr = readFileSync46(opts.curlFile, "utf-8");
|
|
25709
26298
|
} catch (err) {
|
|
25710
26299
|
console.error(`Could not read --curl-file: ${err instanceof Error ? err.message : err}`);
|
|
25711
26300
|
process.exit(1);
|
|
@@ -25725,7 +26314,7 @@ to be read or pasted manually. Prefer a dedicated command when one exists
|
|
|
25725
26314
|
let raw = opts.body;
|
|
25726
26315
|
if (raw.startsWith("@")) {
|
|
25727
26316
|
try {
|
|
25728
|
-
raw =
|
|
26317
|
+
raw = readFileSync46(raw.slice(1), "utf-8");
|
|
25729
26318
|
} catch (err) {
|
|
25730
26319
|
console.error(`Could not read body file: ${err instanceof Error ? err.message : err}`);
|
|
25731
26320
|
process.exit(1);
|
|
@@ -25779,9 +26368,9 @@ init_preflight();
|
|
|
25779
26368
|
init_credentials();
|
|
25780
26369
|
await init_detect();
|
|
25781
26370
|
import { parse as parse2 } from "smol-toml";
|
|
25782
|
-
import { existsSync as
|
|
25783
|
-
import { join as
|
|
25784
|
-
import { homedir as
|
|
26371
|
+
import { existsSync as existsSync57, readFileSync as readFileSync47 } from "fs";
|
|
26372
|
+
import { join as join54, sep as sep4 } from "path";
|
|
26373
|
+
import { homedir as homedir33, platform as osPlatform2, arch as osArch } from "os";
|
|
25785
26374
|
var BASE_URL2 = process.env.RUNWORK_DOWNLOAD_BASE_URL || "https://runwork.ai";
|
|
25786
26375
|
var LATEST_JSON_URL2 = `${BASE_URL2}/cli/latest.json`;
|
|
25787
26376
|
function detectPlatform() {
|
|
@@ -25809,10 +26398,10 @@ function buildContext() {
|
|
|
25809
26398
|
const credentials = getCredentials();
|
|
25810
26399
|
const client = credentials ? new ApiClient(credentials) : null;
|
|
25811
26400
|
let config = null;
|
|
25812
|
-
const configPath =
|
|
25813
|
-
if (
|
|
26401
|
+
const configPath = join54(process.cwd(), ".runwork.json");
|
|
26402
|
+
if (existsSync57(configPath)) {
|
|
25814
26403
|
try {
|
|
25815
|
-
config = JSON.parse(
|
|
26404
|
+
config = JSON.parse(readFileSync47(configPath, "utf-8"));
|
|
25816
26405
|
} catch {}
|
|
25817
26406
|
}
|
|
25818
26407
|
return { credentials, client, config, cwd: process.cwd() };
|
|
@@ -25866,8 +26455,8 @@ async function checkCliVersion() {
|
|
|
25866
26455
|
};
|
|
25867
26456
|
}
|
|
25868
26457
|
async function checkCliArtifactReachable() {
|
|
25869
|
-
const
|
|
25870
|
-
if (!
|
|
26458
|
+
const platform9 = detectPlatform();
|
|
26459
|
+
if (!platform9.key) {
|
|
25871
26460
|
return {
|
|
25872
26461
|
name: "cli-artifact",
|
|
25873
26462
|
status: "skip",
|
|
@@ -25883,12 +26472,12 @@ async function checkCliArtifactReachable() {
|
|
|
25883
26472
|
fix: "check network / outbound access to runwork.ai"
|
|
25884
26473
|
};
|
|
25885
26474
|
}
|
|
25886
|
-
const entry = manifest.artifacts?.[
|
|
26475
|
+
const entry = manifest.artifacts?.[platform9.key];
|
|
25887
26476
|
if (!entry?.path) {
|
|
25888
26477
|
return {
|
|
25889
26478
|
name: "cli-artifact",
|
|
25890
26479
|
status: "fail",
|
|
25891
|
-
message: `manifest has no artifact for ${
|
|
26480
|
+
message: `manifest has no artifact for ${platform9.key}`
|
|
25892
26481
|
};
|
|
25893
26482
|
}
|
|
25894
26483
|
const artifactUrl = `${BASE_URL2}${entry.path}`;
|
|
@@ -25901,7 +26490,7 @@ async function checkCliArtifactReachable() {
|
|
|
25901
26490
|
message: `${artifactUrl} returned HTTP ${response.status}`
|
|
25902
26491
|
};
|
|
25903
26492
|
}
|
|
25904
|
-
return { name: "cli-artifact", status: "pass", message: `${
|
|
26493
|
+
return { name: "cli-artifact", status: "pass", message: `${platform9.key} reachable` };
|
|
25905
26494
|
} catch (err) {
|
|
25906
26495
|
const msg = err instanceof Error ? err.message : String(err);
|
|
25907
26496
|
return {
|
|
@@ -25913,9 +26502,9 @@ async function checkCliArtifactReachable() {
|
|
|
25913
26502
|
}
|
|
25914
26503
|
async function checkCliInstallLocation() {
|
|
25915
26504
|
const isWindows2 = osPlatform2() === "win32";
|
|
25916
|
-
const
|
|
25917
|
-
const canonicalDir =
|
|
25918
|
-
const canonicalBinary = isWindows2 ?
|
|
26505
|
+
const home2 = homedir33();
|
|
26506
|
+
const canonicalDir = join54(home2, ".runwork", "bin");
|
|
26507
|
+
const canonicalBinary = isWindows2 ? join54(canonicalDir, "runwork.exe") : join54(canonicalDir, "runwork");
|
|
25919
26508
|
const candidates = [process.execPath, process.argv[1] || ""].filter(Boolean);
|
|
25920
26509
|
const runsFromCanonical = candidates.some((p) => normalizePath(p) === normalizePath(canonicalBinary));
|
|
25921
26510
|
if (runsFromCanonical) {
|
|
@@ -25925,7 +26514,7 @@ async function checkCliInstallLocation() {
|
|
|
25925
26514
|
message: `canonical (${canonicalBinary})`
|
|
25926
26515
|
};
|
|
25927
26516
|
}
|
|
25928
|
-
if (
|
|
26517
|
+
if (existsSync57(canonicalBinary)) {
|
|
25929
26518
|
return {
|
|
25930
26519
|
name: "cli-install-location",
|
|
25931
26520
|
status: "warn",
|
|
@@ -26058,8 +26647,8 @@ async function checkGitCredentialHelper(ctx) {
|
|
|
26058
26647
|
};
|
|
26059
26648
|
}
|
|
26060
26649
|
async function checkProjectConfig(ctx) {
|
|
26061
|
-
const configPath =
|
|
26062
|
-
if (!
|
|
26650
|
+
const configPath = join54(ctx.cwd, ".runwork.json");
|
|
26651
|
+
if (!existsSync57(configPath)) {
|
|
26063
26652
|
if (!ctx.credentials) {
|
|
26064
26653
|
return { name: "project-config", status: "skip", message: "no project (not logged in)" };
|
|
26065
26654
|
}
|
|
@@ -26121,7 +26710,7 @@ async function checkGitRemote(ctx) {
|
|
|
26121
26710
|
if (!ctx.config) {
|
|
26122
26711
|
return { name: "git-remote", status: "skip", message: "skipped (no project)" };
|
|
26123
26712
|
}
|
|
26124
|
-
if (!
|
|
26713
|
+
if (!existsSync57(join54(ctx.cwd, ".git"))) {
|
|
26125
26714
|
return {
|
|
26126
26715
|
name: "git-remote",
|
|
26127
26716
|
status: "fail",
|
|
@@ -26175,12 +26764,12 @@ async function checkDeployFreshness(ctx) {
|
|
|
26175
26764
|
return { name: "deploy-freshness", status: "skip", message: "local HEAD unknown" };
|
|
26176
26765
|
}
|
|
26177
26766
|
function loadSetupState5() {
|
|
26178
|
-
const projectPath =
|
|
26179
|
-
const userPath =
|
|
26767
|
+
const projectPath = join54(process.cwd(), ".runwork", "setup.json");
|
|
26768
|
+
const userPath = join54(homedir33(), ".runwork", "setup.json");
|
|
26180
26769
|
for (const p of [projectPath, userPath]) {
|
|
26181
|
-
if (
|
|
26770
|
+
if (existsSync57(p)) {
|
|
26182
26771
|
try {
|
|
26183
|
-
return JSON.parse(
|
|
26772
|
+
return JSON.parse(readFileSync47(p, "utf-8"));
|
|
26184
26773
|
} catch {
|
|
26185
26774
|
continue;
|
|
26186
26775
|
}
|
|
@@ -26195,13 +26784,13 @@ async function checkCodexNetwork() {
|
|
|
26195
26784
|
if (!state || !state.configuredAgents.includes("codex")) {
|
|
26196
26785
|
return { name, status: "skip", message: "Codex not configured for Runwork" };
|
|
26197
26786
|
}
|
|
26198
|
-
const configPath =
|
|
26199
|
-
if (!
|
|
26787
|
+
const configPath = join54(homedir33(), ".codex", "config.toml");
|
|
26788
|
+
if (!existsSync57(configPath)) {
|
|
26200
26789
|
return { name, status: "skip", message: "no Codex config found" };
|
|
26201
26790
|
}
|
|
26202
26791
|
let parsed;
|
|
26203
26792
|
try {
|
|
26204
|
-
parsed = parse2(
|
|
26793
|
+
parsed = parse2(readFileSync47(configPath, "utf-8"));
|
|
26205
26794
|
} catch {
|
|
26206
26795
|
return { name, status: "warn", message: "could not parse ~/.codex/config.toml" };
|
|
26207
26796
|
}
|
|
@@ -26254,19 +26843,19 @@ async function checkCodexDesktopProject() {
|
|
|
26254
26843
|
if (!usesCodex) {
|
|
26255
26844
|
return { name, status: "skip", message: "Codex not configured for Runwork" };
|
|
26256
26845
|
}
|
|
26257
|
-
const statePath2 =
|
|
26258
|
-
if (!
|
|
26846
|
+
const statePath2 = join54(homedir33(), ".codex", ".codex-global-state.json");
|
|
26847
|
+
if (!existsSync57(statePath2)) {
|
|
26259
26848
|
return { name, status: "skip", message: "Codex desktop app not detected" };
|
|
26260
26849
|
}
|
|
26261
26850
|
let savedRoots = [];
|
|
26262
26851
|
try {
|
|
26263
|
-
const parsed = JSON.parse(
|
|
26852
|
+
const parsed = JSON.parse(readFileSync47(statePath2, "utf-8"));
|
|
26264
26853
|
const roots = parsed["electron-saved-workspace-roots"];
|
|
26265
26854
|
savedRoots = Array.isArray(roots) ? roots.filter((r) => typeof r === "string") : [];
|
|
26266
26855
|
} catch {
|
|
26267
26856
|
return { name, status: "warn", message: "could not read Codex desktop state" };
|
|
26268
26857
|
}
|
|
26269
|
-
const runworkDir =
|
|
26858
|
+
const runworkDir = join54(homedir33(), ".runwork");
|
|
26270
26859
|
if (savedRoots.includes(runworkDir)) {
|
|
26271
26860
|
return { name, status: "pass", message: "Runwork project added to Codex desktop sidebar" };
|
|
26272
26861
|
}
|
|
@@ -26320,9 +26909,9 @@ async function checkAgentSetup() {
|
|
|
26320
26909
|
if (!adapter2 || !adapter2.supportsMcpScope("user"))
|
|
26321
26910
|
continue;
|
|
26322
26911
|
const mcpConfigPath = getMcpConfigPath2(slug, "user");
|
|
26323
|
-
if (mcpConfigPath &&
|
|
26912
|
+
if (mcpConfigPath && existsSync57(mcpConfigPath)) {
|
|
26324
26913
|
try {
|
|
26325
|
-
const content =
|
|
26914
|
+
const content = readFileSync47(mcpConfigPath, "utf-8");
|
|
26326
26915
|
const missingMcp = state.mcpServers.filter((name) => !content.includes(name));
|
|
26327
26916
|
if (missingMcp.length > 0) {
|
|
26328
26917
|
details.push(`${missingMcp.length} MCP server(s) missing from ${slug} config`);
|
|
@@ -26353,8 +26942,8 @@ async function checkAgentSetup() {
|
|
|
26353
26942
|
const missingSkills = state.skills.filter((name) => {
|
|
26354
26943
|
if (isCoveredByMcp(name))
|
|
26355
26944
|
return false;
|
|
26356
|
-
const skillPath =
|
|
26357
|
-
return !
|
|
26945
|
+
const skillPath = join54(skillsDir, name, "SKILL.md");
|
|
26946
|
+
return !existsSync57(skillPath);
|
|
26358
26947
|
});
|
|
26359
26948
|
if (missingSkills.length > 0) {
|
|
26360
26949
|
details.push(`${missingSkills.length} skill(s) missing from ${slug}`);
|
|
@@ -26384,28 +26973,28 @@ async function checkAgentSetup() {
|
|
|
26384
26973
|
};
|
|
26385
26974
|
}
|
|
26386
26975
|
function getMcpConfigPath2(slug, scope) {
|
|
26387
|
-
const
|
|
26976
|
+
const home2 = homedir33();
|
|
26388
26977
|
switch (slug) {
|
|
26389
26978
|
case "claude-code":
|
|
26390
|
-
return scope === "project" ?
|
|
26979
|
+
return scope === "project" ? join54(process.cwd(), ".mcp.json") : join54(home2, ".claude", "settings.json");
|
|
26391
26980
|
case "cursor":
|
|
26392
|
-
return scope === "project" ?
|
|
26981
|
+
return scope === "project" ? join54(process.cwd(), ".cursor", "mcp.json") : join54(home2, ".cursor", "mcp.json");
|
|
26393
26982
|
case "windsurf":
|
|
26394
|
-
return scope === "project" ?
|
|
26983
|
+
return scope === "project" ? join54(process.cwd(), ".windsurf", "mcp.json") : join54(home2, ".windsurf", "mcp.json");
|
|
26395
26984
|
case "codex":
|
|
26396
26985
|
case "codex-app":
|
|
26397
|
-
return scope === "user" ?
|
|
26986
|
+
return scope === "user" ? join54(home2, ".codex", "config.toml") : null;
|
|
26398
26987
|
case "gemini":
|
|
26399
|
-
return scope === "user" ?
|
|
26988
|
+
return scope === "user" ? join54(home2, ".gemini", "settings.json") : null;
|
|
26400
26989
|
default:
|
|
26401
26990
|
return null;
|
|
26402
26991
|
}
|
|
26403
26992
|
}
|
|
26404
26993
|
async function checkWorkspacePointers() {
|
|
26405
|
-
const userStatePath =
|
|
26406
|
-
const state =
|
|
26994
|
+
const userStatePath = join54(homedir33(), ".runwork", "setup.json");
|
|
26995
|
+
const state = existsSync57(userStatePath) ? (() => {
|
|
26407
26996
|
try {
|
|
26408
|
-
return JSON.parse(
|
|
26997
|
+
return JSON.parse(readFileSync47(userStatePath, "utf-8"));
|
|
26409
26998
|
} catch {
|
|
26410
26999
|
return null;
|
|
26411
27000
|
}
|
|
@@ -26435,15 +27024,15 @@ async function checkWorkspacePointers() {
|
|
|
26435
27024
|
};
|
|
26436
27025
|
}
|
|
26437
27026
|
function getSkillsDir(slug, scope) {
|
|
26438
|
-
const
|
|
27027
|
+
const home2 = homedir33();
|
|
26439
27028
|
switch (slug) {
|
|
26440
27029
|
case "claude-code":
|
|
26441
|
-
return scope === "project" ?
|
|
27030
|
+
return scope === "project" ? join54(process.cwd(), ".claude", "skills") : join54(home2, ".claude", "skills");
|
|
26442
27031
|
case "codex":
|
|
26443
27032
|
case "codex-app":
|
|
26444
|
-
return scope === "project" ?
|
|
27033
|
+
return scope === "project" ? join54(process.cwd(), ".agents", "skills") : join54(home2, ".agents", "skills");
|
|
26445
27034
|
case "gemini":
|
|
26446
|
-
return scope === "project" ?
|
|
27035
|
+
return scope === "project" ? join54(process.cwd(), ".gemini", "skills") : join54(home2, ".gemini", "skills");
|
|
26447
27036
|
default:
|
|
26448
27037
|
return null;
|
|
26449
27038
|
}
|
|
@@ -26496,8 +27085,8 @@ async function runAllChecks(options) {
|
|
|
26496
27085
|
// src/health/fix.ts
|
|
26497
27086
|
init_credentials();
|
|
26498
27087
|
init_remote();
|
|
26499
|
-
import { existsSync as
|
|
26500
|
-
import { join as
|
|
27088
|
+
import { existsSync as existsSync58 } from "fs";
|
|
27089
|
+
import { join as join55 } from "path";
|
|
26501
27090
|
async function applyDoctorFixes(ctx, failingNames) {
|
|
26502
27091
|
const failing = new Set(failingNames);
|
|
26503
27092
|
const outcomes = [];
|
|
@@ -26524,7 +27113,7 @@ async function applyDoctorFixes(ctx, failingNames) {
|
|
|
26524
27113
|
applied: false,
|
|
26525
27114
|
message: "no project config -- run inside an app directory"
|
|
26526
27115
|
});
|
|
26527
|
-
} else if (!
|
|
27116
|
+
} else if (!existsSync58(join55(ctx.cwd, ".git"))) {
|
|
26528
27117
|
outcomes.push({
|
|
26529
27118
|
name: "git-remote",
|
|
26530
27119
|
applied: false,
|
|
@@ -26543,10 +27132,10 @@ async function applyDoctorFixes(ctx, failingNames) {
|
|
|
26543
27132
|
}
|
|
26544
27133
|
|
|
26545
27134
|
// src/agents/runtime-detection.ts
|
|
26546
|
-
import { existsSync as
|
|
26547
|
-
import { homedir as
|
|
26548
|
-
import { join as
|
|
26549
|
-
var RUNWORK_SESSIONS_DIR =
|
|
27135
|
+
import { existsSync as existsSync59, readFileSync as readFileSync48, statSync as statSync12, readdirSync as readdirSync18 } from "fs";
|
|
27136
|
+
import { homedir as homedir34 } from "os";
|
|
27137
|
+
import { join as join56 } from "path";
|
|
27138
|
+
var RUNWORK_SESSIONS_DIR = join56(homedir34(), ".runwork", "sessions");
|
|
26550
27139
|
function detectCurrentAgent() {
|
|
26551
27140
|
const claudeCodeSessionId = process.env.CLAUDE_CODE_SESSION_ID;
|
|
26552
27141
|
if (claudeCodeSessionId) {
|
|
@@ -26609,11 +27198,11 @@ function detectCurrentAgent() {
|
|
|
26609
27198
|
return null;
|
|
26610
27199
|
}
|
|
26611
27200
|
function readHookSessionInfo(sessionId) {
|
|
26612
|
-
const path4 =
|
|
26613
|
-
if (!
|
|
27201
|
+
const path4 = join56(RUNWORK_SESSIONS_DIR, `${sessionId}.json`);
|
|
27202
|
+
if (!existsSync59(path4))
|
|
26614
27203
|
return null;
|
|
26615
27204
|
try {
|
|
26616
|
-
const raw =
|
|
27205
|
+
const raw = readFileSync48(path4, "utf8");
|
|
26617
27206
|
const parsed = JSON.parse(raw);
|
|
26618
27207
|
return parsed;
|
|
26619
27208
|
} catch {
|
|
@@ -26621,40 +27210,40 @@ function readHookSessionInfo(sessionId) {
|
|
|
26621
27210
|
}
|
|
26622
27211
|
}
|
|
26623
27212
|
function findClaudeCodeSessionFile(sessionId) {
|
|
26624
|
-
const root =
|
|
26625
|
-
if (!
|
|
27213
|
+
const root = join56(homedir34(), ".claude", "projects");
|
|
27214
|
+
if (!existsSync59(root))
|
|
26626
27215
|
return null;
|
|
26627
27216
|
let projectDirs;
|
|
26628
27217
|
try {
|
|
26629
|
-
projectDirs =
|
|
27218
|
+
projectDirs = readdirSync18(root);
|
|
26630
27219
|
} catch {
|
|
26631
27220
|
return null;
|
|
26632
27221
|
}
|
|
26633
27222
|
for (const dir of projectDirs) {
|
|
26634
|
-
const candidate =
|
|
26635
|
-
if (
|
|
27223
|
+
const candidate = join56(root, dir, `${sessionId}.jsonl`);
|
|
27224
|
+
if (existsSync59(candidate))
|
|
26636
27225
|
return candidate;
|
|
26637
27226
|
}
|
|
26638
27227
|
return null;
|
|
26639
27228
|
}
|
|
26640
27229
|
function findCodexRolloutFile(threadId) {
|
|
26641
|
-
const root =
|
|
26642
|
-
if (!
|
|
27230
|
+
const root = join56(homedir34(), ".codex", "sessions");
|
|
27231
|
+
if (!existsSync59(root))
|
|
26643
27232
|
return null;
|
|
26644
27233
|
const stack = [root];
|
|
26645
27234
|
while (stack.length > 0) {
|
|
26646
27235
|
const dir = stack.pop();
|
|
26647
27236
|
let entries;
|
|
26648
27237
|
try {
|
|
26649
|
-
entries =
|
|
27238
|
+
entries = readdirSync18(dir);
|
|
26650
27239
|
} catch {
|
|
26651
27240
|
continue;
|
|
26652
27241
|
}
|
|
26653
27242
|
for (const entry of entries) {
|
|
26654
|
-
const full =
|
|
27243
|
+
const full = join56(dir, entry);
|
|
26655
27244
|
let s;
|
|
26656
27245
|
try {
|
|
26657
|
-
s =
|
|
27246
|
+
s = statSync12(full);
|
|
26658
27247
|
} catch {
|
|
26659
27248
|
continue;
|
|
26660
27249
|
}
|
|
@@ -26668,30 +27257,30 @@ function findCodexRolloutFile(threadId) {
|
|
|
26668
27257
|
return null;
|
|
26669
27258
|
}
|
|
26670
27259
|
function findNewestClaudeCodeSession() {
|
|
26671
|
-
const root =
|
|
26672
|
-
if (!
|
|
27260
|
+
const root = join56(homedir34(), ".claude", "projects");
|
|
27261
|
+
if (!existsSync59(root))
|
|
26673
27262
|
return null;
|
|
26674
27263
|
let projectDirs;
|
|
26675
27264
|
try {
|
|
26676
|
-
projectDirs =
|
|
27265
|
+
projectDirs = readdirSync18(root);
|
|
26677
27266
|
} catch {
|
|
26678
27267
|
return null;
|
|
26679
27268
|
}
|
|
26680
27269
|
let best = null;
|
|
26681
27270
|
for (const dir of projectDirs) {
|
|
26682
|
-
const projectPath =
|
|
27271
|
+
const projectPath = join56(root, dir);
|
|
26683
27272
|
let files;
|
|
26684
27273
|
try {
|
|
26685
|
-
files =
|
|
27274
|
+
files = readdirSync18(projectPath);
|
|
26686
27275
|
} catch {
|
|
26687
27276
|
continue;
|
|
26688
27277
|
}
|
|
26689
27278
|
for (const file of files) {
|
|
26690
27279
|
if (!file.endsWith(".jsonl"))
|
|
26691
27280
|
continue;
|
|
26692
|
-
const full =
|
|
27281
|
+
const full = join56(projectPath, file);
|
|
26693
27282
|
try {
|
|
26694
|
-
const s =
|
|
27283
|
+
const s = statSync12(full);
|
|
26695
27284
|
if (!best || s.mtimeMs > best.mtime) {
|
|
26696
27285
|
best = {
|
|
26697
27286
|
sessionId: file.replace(/\.jsonl$/, ""),
|
|
@@ -26707,8 +27296,8 @@ function findNewestClaudeCodeSession() {
|
|
|
26707
27296
|
return best ? { sessionId: best.sessionId, path: best.path } : null;
|
|
26708
27297
|
}
|
|
26709
27298
|
function findNewestCodexRollout() {
|
|
26710
|
-
const root =
|
|
26711
|
-
if (!
|
|
27299
|
+
const root = join56(homedir34(), ".codex", "sessions");
|
|
27300
|
+
if (!existsSync59(root))
|
|
26712
27301
|
return null;
|
|
26713
27302
|
const stack = [root];
|
|
26714
27303
|
let best = null;
|
|
@@ -26716,15 +27305,15 @@ function findNewestCodexRollout() {
|
|
|
26716
27305
|
const dir = stack.pop();
|
|
26717
27306
|
let entries;
|
|
26718
27307
|
try {
|
|
26719
|
-
entries =
|
|
27308
|
+
entries = readdirSync18(dir);
|
|
26720
27309
|
} catch {
|
|
26721
27310
|
continue;
|
|
26722
27311
|
}
|
|
26723
27312
|
for (const entry of entries) {
|
|
26724
|
-
const full =
|
|
27313
|
+
const full = join56(dir, entry);
|
|
26725
27314
|
let s;
|
|
26726
27315
|
try {
|
|
26727
|
-
s =
|
|
27316
|
+
s = statSync12(full);
|
|
26728
27317
|
} catch {
|
|
26729
27318
|
continue;
|
|
26730
27319
|
}
|
|
@@ -26951,11 +27540,13 @@ var doctorCommand = new Command34("doctor").description("Check system health: au
|
|
|
26951
27540
|
// src/commands/debug.ts
|
|
26952
27541
|
init_colors();
|
|
26953
27542
|
import { Command as Command35 } from "commander";
|
|
26954
|
-
import { readFileSync as
|
|
26955
|
-
import { homedir as
|
|
26956
|
-
import { join as
|
|
27543
|
+
import { readFileSync as readFileSync49 } from "fs";
|
|
27544
|
+
import { homedir as homedir36, platform as platform9, release, arch, type as osType } from "os";
|
|
27545
|
+
import { join as join59 } from "path";
|
|
26957
27546
|
|
|
26958
27547
|
// src/debug/capture-plan.ts
|
|
27548
|
+
init_transcript_stores();
|
|
27549
|
+
init_registry_data();
|
|
26959
27550
|
var CONFIG_MAX_BYTES = 64 * 1024;
|
|
26960
27551
|
var LOG_TAIL_BYTES = 64 * 1024;
|
|
26961
27552
|
var CENSUS_MAX_ENTRIES = 200;
|
|
@@ -26981,9 +27572,9 @@ var ENV_NAMES = [
|
|
|
26981
27572
|
];
|
|
26982
27573
|
function buildCapturePlan(input) {
|
|
26983
27574
|
const sep5 = input.sep ?? (input.platform === "win32" ? "\\" : "/");
|
|
26984
|
-
const
|
|
26985
|
-
const
|
|
26986
|
-
const rw = (...parts) =>
|
|
27575
|
+
const join57 = (...parts) => parts.join(sep5);
|
|
27576
|
+
const home2 = input.homeDir.replace(/[/\\]+$/, "");
|
|
27577
|
+
const rw = (...parts) => join57(home2, ".runwork", ...parts);
|
|
26987
27578
|
const steps = [];
|
|
26988
27579
|
steps.push({ id: "env", kind: "env", names: ENV_NAMES, note: "process environment (proxy credentials stripped)" });
|
|
26989
27580
|
for (const [id, file] of [
|
|
@@ -27013,62 +27604,129 @@ function buildCapturePlan(input) {
|
|
|
27013
27604
|
["codex.agents-md", ".codex", "AGENTS.md"],
|
|
27014
27605
|
["gemini.settings", ".gemini", "settings.json"]
|
|
27015
27606
|
]) {
|
|
27016
|
-
steps.push({ id, kind: "file", path:
|
|
27017
|
-
}
|
|
27607
|
+
steps.push({ id, kind: "file", path: join57(home2, ...parts), maxBytes: CONFIG_MAX_BYTES });
|
|
27608
|
+
}
|
|
27609
|
+
steps.push({
|
|
27610
|
+
id: "claude.desktop-config",
|
|
27611
|
+
kind: "file",
|
|
27612
|
+
path: join57(appDataRootFor(input, join57), "Claude", "claude_desktop_config.json"),
|
|
27613
|
+
maxBytes: CONFIG_MAX_BYTES,
|
|
27614
|
+
note: "the MCP config we write for Claude Desktop, next to its session store"
|
|
27615
|
+
});
|
|
27616
|
+
steps.push({
|
|
27617
|
+
id: "codex.version",
|
|
27618
|
+
kind: "file",
|
|
27619
|
+
path: join57(home2, ".codex", "version.json"),
|
|
27620
|
+
maxBytes: 4096,
|
|
27621
|
+
note: "Codex build, for placing an unrecognised originator value"
|
|
27622
|
+
});
|
|
27018
27623
|
for (const [id, ...parts] of [
|
|
27019
27624
|
["claude.skills", ".claude", "skills"],
|
|
27020
27625
|
["claude.plugins", ".claude", "plugins"],
|
|
27021
27626
|
["agents.skills", ".agents", "skills"],
|
|
27022
27627
|
["codex.skills", ".codex", "skills"]
|
|
27023
27628
|
]) {
|
|
27024
|
-
steps.push({ id, kind: "census", path:
|
|
27629
|
+
steps.push({ id, kind: "census", path: join57(home2, ...parts), depth: 1, maxEntries: CENSUS_MAX_ENTRIES });
|
|
27630
|
+
}
|
|
27631
|
+
for (const store of resolveTranscriptStores({
|
|
27632
|
+
platform: input.platform,
|
|
27633
|
+
homeDir: home2,
|
|
27634
|
+
sep: sep5,
|
|
27635
|
+
appData: input.appData,
|
|
27636
|
+
localAppData: input.localAppData
|
|
27637
|
+
})) {
|
|
27638
|
+
const id = `stores.${store.def.id.replace(/\//g, ".")}`;
|
|
27639
|
+
steps.push(store.def.kind === "file" ? { id, kind: "stat", path: store.path, ...store.def.note ? { note: store.def.note } : {} } : { id, kind: "census", path: store.path, depth: 2, maxEntries: CENSUS_MAX_ENTRIES, ...store.def.note ? { note: store.def.note } : {} });
|
|
27640
|
+
for (const parent of parentsWorthProbing(store.path, sep5)) {
|
|
27641
|
+
steps.push({ id: `${id}.parent`, kind: "census", path: parent, depth: 1, maxEntries: 50, note: "is the vendor directory there at all" });
|
|
27642
|
+
}
|
|
27643
|
+
store.altPaths.forEach((alt, i) => {
|
|
27644
|
+
steps.push({ id: `${id}.alt${i}`, kind: "stat", path: alt, note: "alternate location; a hit means the canonical path is wrong here" });
|
|
27645
|
+
});
|
|
27646
|
+
}
|
|
27647
|
+
if (input.platform === "win32") {
|
|
27648
|
+
steps.push({
|
|
27649
|
+
id: "windows.appx-packages",
|
|
27650
|
+
kind: "census",
|
|
27651
|
+
path: join57(input.localAppData ?? join57(home2, "AppData", "Local"), "Packages"),
|
|
27652
|
+
depth: 1,
|
|
27653
|
+
maxEntries: CENSUS_MAX_ENTRIES,
|
|
27654
|
+
note: "AppX package identities: an MSIX agent can virtualize its writes in here"
|
|
27655
|
+
});
|
|
27025
27656
|
}
|
|
27026
|
-
steps.push({ id: "transcripts.claude-code", kind: "census", path: join56(home, ".claude", "projects"), depth: 1, maxEntries: CENSUS_MAX_ENTRIES }, { id: "transcripts.codex", kind: "census", path: join56(home, ".codex", "sessions"), depth: 2, maxEntries: CENSUS_MAX_ENTRIES }, { id: "transcripts.gemini", kind: "census", path: join56(home, ".gemini", "tmp"), depth: 1, maxEntries: CENSUS_MAX_ENTRIES }, { id: "transcripts.cowork", kind: "census", path: coworkBaseDir(input, join56), depth: 1, maxEntries: CENSUS_MAX_ENTRIES, note: "macOS TCC can refuse this while it still exists" });
|
|
27027
27657
|
for (const profile of shellProfiles(input.platform)) {
|
|
27028
27658
|
steps.push({
|
|
27029
27659
|
id: `shell${profile}`,
|
|
27030
27660
|
kind: "stat",
|
|
27031
|
-
path:
|
|
27661
|
+
path: join57(home2, profile),
|
|
27032
27662
|
note: "presence only: profile bodies can contain the user's own secrets"
|
|
27033
27663
|
});
|
|
27034
27664
|
}
|
|
27035
27665
|
steps.push(...binaryResolutionSteps(input));
|
|
27666
|
+
steps.push(...agentBinaryProbes(input));
|
|
27036
27667
|
if (input.cliPath) {
|
|
27037
|
-
steps.push({ id: "cli.version", kind: "exec", command: input.cliPath, args: ["--version"] }, { id: "cli.doctor", kind: "exec", command: input.cliPath, args: ["--json", "doctor", "-v"] }, { id: "cli.conversations", kind: "exec", command: input.cliPath, args: ["--json", "conversations", "status", "--days", "0"], note: "per-agent scan outcome, no conversation data" });
|
|
27668
|
+
steps.push({ id: "cli.version", kind: "exec", command: input.cliPath, args: ["--version"] }, { id: "cli.doctor", kind: "exec", command: input.cliPath, args: ["--json", "doctor", "-v"] }, { id: "cli.conversations", kind: "exec", command: input.cliPath, args: ["--json", "conversations", "status", "--days", "0"], note: "per-agent scan outcome, no conversation data" }, { id: "cli.stores", kind: "exec", command: input.cliPath, args: ["--json", "conversations", "stores"], note: "per-store contents and provenance, no conversation text" });
|
|
27038
27669
|
}
|
|
27039
27670
|
return steps;
|
|
27040
27671
|
}
|
|
27041
|
-
function
|
|
27042
|
-
const
|
|
27043
|
-
if (
|
|
27044
|
-
return
|
|
27045
|
-
|
|
27046
|
-
|
|
27047
|
-
|
|
27048
|
-
return
|
|
27672
|
+
function parentsWorthProbing(storePath4, sep5) {
|
|
27673
|
+
const idx = storePath4.lastIndexOf(sep5);
|
|
27674
|
+
if (idx <= 0)
|
|
27675
|
+
return [];
|
|
27676
|
+
const parent = storePath4.slice(0, idx);
|
|
27677
|
+
const parentIdx = parent.lastIndexOf(sep5);
|
|
27678
|
+
if (parentIdx <= 0)
|
|
27679
|
+
return [];
|
|
27680
|
+
return [parent];
|
|
27681
|
+
}
|
|
27682
|
+
function agentBinaryProbes(input) {
|
|
27683
|
+
const finder = input.platform === "win32" ? "where.exe" : "which";
|
|
27684
|
+
const args = (binary) => input.platform === "win32" ? [binary] : ["-a", binary];
|
|
27685
|
+
const seen = new Set;
|
|
27686
|
+
const steps = [];
|
|
27687
|
+
for (const agent of getDetectableAgents()) {
|
|
27688
|
+
const binary = agent.launch?.cli;
|
|
27689
|
+
if (!binary || seen.has(binary))
|
|
27690
|
+
continue;
|
|
27691
|
+
seen.add(binary);
|
|
27692
|
+
steps.push({
|
|
27693
|
+
id: `agent-binary.${agent.slug}`,
|
|
27694
|
+
kind: "exec",
|
|
27695
|
+
command: finder,
|
|
27696
|
+
args: args(binary),
|
|
27697
|
+
note: `is ${agent.name}'s CLI on PATH, and where`
|
|
27698
|
+
});
|
|
27049
27699
|
}
|
|
27050
|
-
return
|
|
27700
|
+
return steps;
|
|
27701
|
+
}
|
|
27702
|
+
function appDataRootFor(input, join57) {
|
|
27703
|
+
const home2 = input.homeDir.replace(/[/\\]+$/, "");
|
|
27704
|
+
if (input.platform === "darwin")
|
|
27705
|
+
return join57(home2, "Library", "Application Support");
|
|
27706
|
+
if (input.platform === "win32")
|
|
27707
|
+
return input.appData ?? join57(home2, "AppData", "Roaming");
|
|
27708
|
+
return join57(home2, ".config");
|
|
27051
27709
|
}
|
|
27052
|
-
function shellProfiles(
|
|
27053
|
-
if (
|
|
27710
|
+
function shellProfiles(platform9) {
|
|
27711
|
+
if (platform9 === "win32")
|
|
27054
27712
|
return [];
|
|
27055
27713
|
return [".zshrc", ".zprofile", ".bashrc", ".bash_profile", ".profile"];
|
|
27056
27714
|
}
|
|
27057
27715
|
function binaryResolutionSteps(input) {
|
|
27058
27716
|
const sep5 = input.sep ?? (input.platform === "win32" ? "\\" : "/");
|
|
27059
|
-
const
|
|
27060
|
-
const
|
|
27717
|
+
const join57 = (...parts) => parts.join(sep5);
|
|
27718
|
+
const home2 = input.homeDir.replace(/[/\\]+$/, "");
|
|
27061
27719
|
if (input.platform === "win32") {
|
|
27062
27720
|
return [
|
|
27063
27721
|
{ id: "binaries.where", kind: "exec", command: "where.exe", args: ["runwork"], note: "every match, not just the first" },
|
|
27064
|
-
{ id: "binaries.runwork-bin", kind: "stat", path:
|
|
27722
|
+
{ id: "binaries.runwork-bin", kind: "stat", path: join57(home2, ".runwork", "bin", "runwork.exe") },
|
|
27065
27723
|
{ id: "binaries.user-path", kind: "exec", command: "reg.exe", args: ["query", "HKCU\\Environment", "/v", "Path"], note: "the PATH a NEW shell will inherit, not this one" }
|
|
27066
27724
|
];
|
|
27067
27725
|
}
|
|
27068
27726
|
return [
|
|
27069
27727
|
{ id: "binaries.which", kind: "exec", command: "which", args: ["-a", "runwork"], note: "every match, not just the first" },
|
|
27070
|
-
{ id: "binaries.runwork-bin", kind: "stat", path:
|
|
27071
|
-
{ id: "binaries.local-bin", kind: "stat", path:
|
|
27728
|
+
{ id: "binaries.runwork-bin", kind: "stat", path: join57(home2, ".runwork", "bin", "runwork") },
|
|
27729
|
+
{ id: "binaries.local-bin", kind: "stat", path: join57(home2, ".local", "bin", "runwork") },
|
|
27072
27730
|
...input.platform === "darwin" ? [{ id: "binaries.usr-local-bin", kind: "stat", path: "/usr/local/bin/runwork" }] : []
|
|
27073
27731
|
];
|
|
27074
27732
|
}
|
|
@@ -27284,10 +27942,10 @@ async function runCapture(port, producer, steps, opts = {}) {
|
|
|
27284
27942
|
// src/utils/machine-id.ts
|
|
27285
27943
|
init_atomic_json();
|
|
27286
27944
|
import { randomUUID } from "crypto";
|
|
27287
|
-
import { homedir as
|
|
27288
|
-
import { join as
|
|
27945
|
+
import { homedir as homedir35 } from "os";
|
|
27946
|
+
import { join as join57 } from "path";
|
|
27289
27947
|
function machineIdPath() {
|
|
27290
|
-
return
|
|
27948
|
+
return join57(homedir35(), ".runwork", "machine.json");
|
|
27291
27949
|
}
|
|
27292
27950
|
function isValidId(value) {
|
|
27293
27951
|
return typeof value === "string" && /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(value);
|
|
@@ -27315,8 +27973,8 @@ init_resolve();
|
|
|
27315
27973
|
// src/debug/node-port.ts
|
|
27316
27974
|
init_subprocess();
|
|
27317
27975
|
init_which();
|
|
27318
|
-
import { closeSync as
|
|
27319
|
-
import { dirname as dirname12, join as
|
|
27976
|
+
import { closeSync as closeSync6, fsyncSync, mkdirSync as mkdirSync29, openSync as openSync6, readSync as readSync4, readdirSync as readdirSync19, statSync as statSync13, writeSync } from "fs";
|
|
27977
|
+
import { dirname as dirname12, join as join58 } from "path";
|
|
27320
27978
|
var EXEC_OUTPUT_MAX = 256 * 1024;
|
|
27321
27979
|
var EXEC_TIMEOUT_MS = 20000;
|
|
27322
27980
|
function truncate5(text2, maxBytes) {
|
|
@@ -27324,7 +27982,7 @@ function truncate5(text2, maxBytes) {
|
|
|
27324
27982
|
}
|
|
27325
27983
|
function entryKind(path4) {
|
|
27326
27984
|
try {
|
|
27327
|
-
const s =
|
|
27985
|
+
const s = statSync13(path4);
|
|
27328
27986
|
return s.isDirectory() ? "dir" : s.isFile() ? "file" : "other";
|
|
27329
27987
|
} catch {
|
|
27330
27988
|
return "other";
|
|
@@ -27332,9 +27990,9 @@ function entryKind(path4) {
|
|
|
27332
27990
|
}
|
|
27333
27991
|
function createNodeCapturePort(outputPath) {
|
|
27334
27992
|
mkdirSync29(dirname12(outputPath), { recursive: true });
|
|
27335
|
-
const fd =
|
|
27993
|
+
const fd = openSync6(outputPath, "w");
|
|
27336
27994
|
return {
|
|
27337
|
-
close: () =>
|
|
27995
|
+
close: () => closeSync6(fd),
|
|
27338
27996
|
async append(record) {
|
|
27339
27997
|
writeSync(fd, JSON.stringify(record) + `
|
|
27340
27998
|
`);
|
|
@@ -27350,7 +28008,7 @@ function createNodeCapturePort(outputPath) {
|
|
|
27350
28008
|
const { dir, prefix, level } = queue.shift();
|
|
27351
28009
|
let names;
|
|
27352
28010
|
try {
|
|
27353
|
-
names =
|
|
28011
|
+
names = readdirSync19(dir);
|
|
27354
28012
|
} catch (err) {
|
|
27355
28013
|
if (first)
|
|
27356
28014
|
throw err;
|
|
@@ -27361,12 +28019,12 @@ function createNodeCapturePort(outputPath) {
|
|
|
27361
28019
|
for (const name of names) {
|
|
27362
28020
|
if (out.length >= maxEntries)
|
|
27363
28021
|
break;
|
|
27364
|
-
const full =
|
|
28022
|
+
const full = join58(dir, name);
|
|
27365
28023
|
const kind = entryKind(full);
|
|
27366
28024
|
let bytes;
|
|
27367
28025
|
let modifiedAt;
|
|
27368
28026
|
try {
|
|
27369
|
-
const s =
|
|
28027
|
+
const s = statSync13(full);
|
|
27370
28028
|
bytes = s.size;
|
|
27371
28029
|
modifiedAt = new Date(s.mtimeMs).toISOString();
|
|
27372
28030
|
} catch {}
|
|
@@ -27379,7 +28037,7 @@ function createNodeCapturePort(outputPath) {
|
|
|
27379
28037
|
return out;
|
|
27380
28038
|
},
|
|
27381
28039
|
async stat(path4) {
|
|
27382
|
-
const s =
|
|
28040
|
+
const s = statSync13(path4);
|
|
27383
28041
|
return {
|
|
27384
28042
|
bytes: s.size,
|
|
27385
28043
|
modifiedAt: new Date(s.mtimeMs).toISOString(),
|
|
@@ -27387,16 +28045,16 @@ function createNodeCapturePort(outputPath) {
|
|
|
27387
28045
|
};
|
|
27388
28046
|
},
|
|
27389
28047
|
async readText(path4, maxBytes, tail) {
|
|
27390
|
-
const s =
|
|
28048
|
+
const s = statSync13(path4);
|
|
27391
28049
|
const size = s.size;
|
|
27392
28050
|
const length = Math.min(size, maxBytes);
|
|
27393
28051
|
const start = tail && size > maxBytes ? size - maxBytes : 0;
|
|
27394
28052
|
const buffer = Buffer.alloc(length);
|
|
27395
|
-
const handle =
|
|
28053
|
+
const handle = openSync6(path4, "r");
|
|
27396
28054
|
try {
|
|
27397
|
-
|
|
28055
|
+
readSync4(handle, buffer, 0, length, start);
|
|
27398
28056
|
} finally {
|
|
27399
|
-
|
|
28057
|
+
closeSync6(handle);
|
|
27400
28058
|
}
|
|
27401
28059
|
return { text: buffer.toString("utf-8"), truncated: size > length };
|
|
27402
28060
|
},
|
|
@@ -27429,7 +28087,7 @@ init_which();
|
|
|
27429
28087
|
await init_detect();
|
|
27430
28088
|
function defaultOutputPath(now) {
|
|
27431
28089
|
const stamp = now.toISOString().replace(/[:.]/g, "-").replace("T", "_").slice(0, 19);
|
|
27432
|
-
return
|
|
28090
|
+
return join59(homedir36(), ".runwork", "debug", `runwork-debug-${stamp}.jsonl`);
|
|
27433
28091
|
}
|
|
27434
28092
|
async function cliClaims() {
|
|
27435
28093
|
const records = [];
|
|
@@ -27442,7 +28100,7 @@ async function cliClaims() {
|
|
|
27442
28100
|
execPath: process.execPath,
|
|
27443
28101
|
argv0: process.argv[1] ?? null,
|
|
27444
28102
|
nodeVersion: process.version,
|
|
27445
|
-
platform:
|
|
28103
|
+
platform: platform9(),
|
|
27446
28104
|
osType: osType(),
|
|
27447
28105
|
release: release(),
|
|
27448
28106
|
arch: arch(),
|
|
@@ -27482,9 +28140,10 @@ debugCommand.command("capture").description("Collect a diagnostic bundle to a fi
|
|
|
27482
28140
|
const outputPath = typeof opts.out === "string" && opts.out ? opts.out : defaultOutputPath(new Date);
|
|
27483
28141
|
const cliPath = whichBinary("runwork");
|
|
27484
28142
|
const plan = buildCapturePlan({
|
|
27485
|
-
platform:
|
|
27486
|
-
homeDir:
|
|
28143
|
+
platform: platform9(),
|
|
28144
|
+
homeDir: homedir36(),
|
|
27487
28145
|
appData: process.env.APPDATA ?? null,
|
|
28146
|
+
localAppData: process.env.LOCALAPPDATA ?? null,
|
|
27488
28147
|
cliPath
|
|
27489
28148
|
});
|
|
27490
28149
|
if (!json) {
|
|
@@ -27528,7 +28187,7 @@ Done. ${counted} checks recorded.`));
|
|
|
27528
28187
|
});
|
|
27529
28188
|
async function sendBundle(path4, note) {
|
|
27530
28189
|
try {
|
|
27531
|
-
const content =
|
|
28190
|
+
const content = readFileSync49(path4, "utf-8");
|
|
27532
28191
|
const summary = summarizeBundle(content);
|
|
27533
28192
|
const machineId = getMachineId();
|
|
27534
28193
|
if (!machineId)
|
|
@@ -27547,7 +28206,7 @@ async function sendBundle(path4, note) {
|
|
|
27547
28206
|
...note ? { note } : {},
|
|
27548
28207
|
context: {
|
|
27549
28208
|
cliVersion: VERSION,
|
|
27550
|
-
platform:
|
|
28209
|
+
platform: platform9(),
|
|
27551
28210
|
release: release(),
|
|
27552
28211
|
stepsPlanned: summary.stepsPlanned,
|
|
27553
28212
|
stepsRun: summary.stepsRun,
|
|
@@ -27567,8 +28226,8 @@ init_store();
|
|
|
27567
28226
|
init_client();
|
|
27568
28227
|
init_resolve();
|
|
27569
28228
|
import { Command as Command36 } from "commander";
|
|
27570
|
-
import { readFileSync as
|
|
27571
|
-
import { join as
|
|
28229
|
+
import { readFileSync as readFileSync50, writeFileSync as writeFileSync33, existsSync as existsSync60, mkdtempSync as mkdtempSync4 } from "fs";
|
|
28230
|
+
import { join as join60 } from "path";
|
|
27572
28231
|
import { tmpdir as tmpdir4 } from "os";
|
|
27573
28232
|
import { createHash as createHash6 } from "crypto";
|
|
27574
28233
|
|
|
@@ -27690,13 +28349,13 @@ function resolveLocalSessionShare(opts, conversation) {
|
|
|
27690
28349
|
process.exit(1);
|
|
27691
28350
|
}
|
|
27692
28351
|
const title = opts.title ?? conversation.title ?? conversation.project;
|
|
27693
|
-
const markdown = renderTranscriptMarkdown(
|
|
28352
|
+
const markdown = renderTranscriptMarkdown(readFileSync50(conversation.transcriptPath, "utf8"), family, title);
|
|
27694
28353
|
if (!markdown) {
|
|
27695
28354
|
console.error("Error: this conversation has no shareable content.");
|
|
27696
28355
|
process.exit(1);
|
|
27697
28356
|
}
|
|
27698
|
-
const tempDir = mkdtempSync4(
|
|
27699
|
-
const transcriptFile =
|
|
28357
|
+
const tempDir = mkdtempSync4(join60(tmpdir4(), "runwork-share-"));
|
|
28358
|
+
const transcriptFile = join60(tempDir, "transcript.md");
|
|
27700
28359
|
writeFileSync33(transcriptFile, markdown);
|
|
27701
28360
|
opts.transcriptFile = transcriptFile;
|
|
27702
28361
|
opts.nativeFile = opts.nativeFile ?? conversation.transcriptPath;
|
|
@@ -27734,7 +28393,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
|
|
|
27734
28393
|
console.error("Error: --transcript-file is required. Pass the path to the LLM-emitted markdown transcript.");
|
|
27735
28394
|
process.exit(1);
|
|
27736
28395
|
}
|
|
27737
|
-
if (!
|
|
28396
|
+
if (!existsSync60(opts.transcriptFile)) {
|
|
27738
28397
|
console.error(`Error: transcript file does not exist: ${opts.transcriptFile}`);
|
|
27739
28398
|
process.exit(1);
|
|
27740
28399
|
}
|
|
@@ -27755,7 +28414,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
|
|
|
27755
28414
|
const credentials = requireAuth();
|
|
27756
28415
|
const client = new ApiClient(credentials);
|
|
27757
28416
|
const { workspaceId } = await resolveWorkspace2(client, { workspace: opts.workspace });
|
|
27758
|
-
const transcriptContent =
|
|
28417
|
+
const transcriptContent = readFileSync50(opts.transcriptFile, "utf8");
|
|
27759
28418
|
const bundles = [
|
|
27760
28419
|
{
|
|
27761
28420
|
format: "transcript",
|
|
@@ -27768,19 +28427,19 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
|
|
|
27768
28427
|
const sourceAgent = opts.sourceAgent ?? detected?.slug ?? "generic";
|
|
27769
28428
|
let nativeFilePath = null;
|
|
27770
28429
|
if (opts.nativeFile) {
|
|
27771
|
-
if (!
|
|
28430
|
+
if (!existsSync60(opts.nativeFile)) {
|
|
27772
28431
|
console.error(`Error: --native-file path does not exist: ${opts.nativeFile}`);
|
|
27773
28432
|
process.exit(1);
|
|
27774
28433
|
}
|
|
27775
28434
|
nativeFilePath = opts.nativeFile;
|
|
27776
|
-
} else if (detected?.sessionFilePath &&
|
|
28435
|
+
} else if (detected?.sessionFilePath && existsSync60(detected.sessionFilePath)) {
|
|
27777
28436
|
nativeFilePath = detected.sessionFilePath;
|
|
27778
28437
|
}
|
|
27779
28438
|
if (nativeFilePath) {
|
|
27780
28439
|
const nativeFormat = nativeBundleFormatForAgent(sourceAgent);
|
|
27781
28440
|
if (nativeFormat) {
|
|
27782
28441
|
try {
|
|
27783
|
-
const content =
|
|
28442
|
+
const content = readFileSync50(nativeFilePath, "utf8");
|
|
27784
28443
|
bundles.push({
|
|
27785
28444
|
format: nativeFormat,
|
|
27786
28445
|
content,
|
|
@@ -27796,7 +28455,7 @@ async function runShareConvo(opts, command, isPersonalAlias = false) {
|
|
|
27796
28455
|
let metadata = {};
|
|
27797
28456
|
if (opts.metadataFile) {
|
|
27798
28457
|
try {
|
|
27799
|
-
metadata = JSON.parse(
|
|
28458
|
+
metadata = JSON.parse(readFileSync50(opts.metadataFile, "utf8"));
|
|
27800
28459
|
} catch (err) {
|
|
27801
28460
|
console.error(`Error: --metadata-file is not valid JSON: ${err instanceof Error ? err.message : err}`);
|
|
27802
28461
|
process.exit(1);
|
|
@@ -27906,8 +28565,8 @@ init_resolve();
|
|
|
27906
28565
|
init_registry_data();
|
|
27907
28566
|
import { Command as Command39 } from "commander";
|
|
27908
28567
|
import { writeFileSync as writeFileSync34, mkdirSync as mkdirSync30, realpathSync } from "fs";
|
|
27909
|
-
import { homedir as
|
|
27910
|
-
import { join as
|
|
28568
|
+
import { homedir as homedir37 } from "os";
|
|
28569
|
+
import { join as join61 } from "path";
|
|
27911
28570
|
import { spawn as spawn5 } from "child_process";
|
|
27912
28571
|
init_registry();
|
|
27913
28572
|
init_which();
|
|
@@ -27946,9 +28605,9 @@ function extractCodexUuid(rolloutContent) {
|
|
|
27946
28605
|
}
|
|
27947
28606
|
function placeClaudeJsonl(uuid, content, recipientCwd) {
|
|
27948
28607
|
const encoded = encodeClaudeCodeCwd(recipientCwd);
|
|
27949
|
-
const projectDir =
|
|
28608
|
+
const projectDir = join61(homedir37(), ".claude", "projects", encoded);
|
|
27950
28609
|
mkdirSync30(projectDir, { recursive: true });
|
|
27951
|
-
const placedAt =
|
|
28610
|
+
const placedAt = join61(projectDir, `${uuid}.jsonl`);
|
|
27952
28611
|
writeFileSync34(placedAt, content);
|
|
27953
28612
|
return { placedAt, runFromCwd: recipientCwd };
|
|
27954
28613
|
}
|
|
@@ -27957,10 +28616,10 @@ function placeCodexRollout(uuid, content) {
|
|
|
27957
28616
|
const yyyy = String(now.getUTCFullYear());
|
|
27958
28617
|
const mm = String(now.getUTCMonth() + 1).padStart(2, "0");
|
|
27959
28618
|
const dd = String(now.getUTCDate()).padStart(2, "0");
|
|
27960
|
-
const dir =
|
|
28619
|
+
const dir = join61(homedir37(), ".codex", "sessions", yyyy, mm, dd);
|
|
27961
28620
|
mkdirSync30(dir, { recursive: true });
|
|
27962
28621
|
const ts = now.toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
|
|
27963
|
-
const placedAt =
|
|
28622
|
+
const placedAt = join61(dir, `rollout-${ts}-${uuid}.jsonl`);
|
|
27964
28623
|
writeFileSync34(placedAt, content);
|
|
27965
28624
|
return { placedAt };
|
|
27966
28625
|
}
|