@aiden-ade/sandbox-agent 0.1.48 → 0.1.49
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.cjs +793 -306
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -36,7 +36,7 @@ var require_XMLHttpRequest = __commonJS({
|
|
|
36
36
|
"use strict";
|
|
37
37
|
var fs = require("fs");
|
|
38
38
|
var Url = require("url");
|
|
39
|
-
var
|
|
39
|
+
var spawn6 = require("child_process").spawn;
|
|
40
40
|
module2.exports = XMLHttpRequest3;
|
|
41
41
|
XMLHttpRequest3.XMLHttpRequest = XMLHttpRequest3;
|
|
42
42
|
function XMLHttpRequest3(opts) {
|
|
@@ -332,7 +332,7 @@ var require_XMLHttpRequest = __commonJS({
|
|
|
332
332
|
var syncFile = ".node-xmlhttprequest-sync-" + process.pid;
|
|
333
333
|
fs.writeFileSync(syncFile, "", "utf8");
|
|
334
334
|
var execString = "var http = require('http'), https = require('https'), fs = require('fs');var doRequest = http" + (ssl ? "s" : "") + ".request;var options = " + JSON.stringify(options) + ";var responseText = '';var responseData = Buffer.alloc(0);var req = doRequest(options, function(response) {response.on('data', function(chunk) { var data = Buffer.from(chunk); responseText += data.toString('utf8'); responseData = Buffer.concat([responseData, data]);});response.on('end', function() {fs.writeFileSync('" + contentFile + "', JSON.stringify({err: null, data: {statusCode: response.statusCode, headers: response.headers, text: responseText, data: responseData.toString('base64')}}), 'utf8');fs.unlinkSync('" + syncFile + "');});response.on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});}).on('error', function(error) {fs.writeFileSync('" + contentFile + "', 'NODE-XMLHTTPREQUEST-ERROR:' + JSON.stringify(error), 'utf8');fs.unlinkSync('" + syncFile + "');});" + (data ? "req.write('" + JSON.stringify(data).slice(1, -1).replace(/'/g, "\\'") + "');" : "") + "req.end();";
|
|
335
|
-
var syncProc =
|
|
335
|
+
var syncProc = spawn6(process.argv[0], ["-e", execString]);
|
|
336
336
|
var statusText;
|
|
337
337
|
while (fs.existsSync(syncFile)) {
|
|
338
338
|
}
|
|
@@ -4859,12 +4859,12 @@ function resolveCommand(args, env) {
|
|
|
4859
4859
|
}
|
|
4860
4860
|
|
|
4861
4861
|
// src/daemon.ts
|
|
4862
|
-
var
|
|
4862
|
+
var import_node_child_process6 = require("child_process");
|
|
4863
4863
|
var import_node_crypto3 = require("crypto");
|
|
4864
|
-
var
|
|
4864
|
+
var import_node_fs13 = require("fs");
|
|
4865
4865
|
var import_node_http = __toESM(require("http"), 1);
|
|
4866
|
-
var
|
|
4867
|
-
var
|
|
4866
|
+
var import_node_os8 = require("os");
|
|
4867
|
+
var import_node_path11 = require("path");
|
|
4868
4868
|
|
|
4869
4869
|
// ../agent-core/dist/index.js
|
|
4870
4870
|
var import_fs = require("fs");
|
|
@@ -5020,69 +5020,57 @@ Every \`start_task_session\` message must include all four of these:
|
|
|
5020
5020
|
var GENERAL_PROMPT = `You are Alan, the General Agent \u2014 a flexible general-purpose agent profile. When identifying yourself, say "I'm Alan, the General Agent."`;
|
|
5021
5021
|
var SETUP_PROMPT = `## You are the Setup Agent
|
|
5022
5022
|
|
|
5023
|
-
You are the **Setup Agent** for this environment. When
|
|
5024
|
-
|
|
5025
|
-
to take
|
|
5026
|
-
installed, configured, and **actually running and verified** \u2014 end to end. You
|
|
5027
|
-
are not here to build features; you are here to make the environment work and
|
|
5028
|
-
make that reproducible.
|
|
5023
|
+
You are the **Setup Agent** for this cloud environment. When identifying yourself, say "I'm the Setup Agent (an Alan agent profile) for this environment."
|
|
5024
|
+
|
|
5025
|
+
Your job is to take the repository in this fresh cloud sandbox from an unknown state to a **running, functionally verified, reproducible environment**. You are setting up the project, not building product features. Keep working until the application actually works.
|
|
5029
5026
|
|
|
5030
|
-
##
|
|
5027
|
+
## Environment model
|
|
5031
5028
|
|
|
5032
|
-
You are inside an
|
|
5033
|
-
|
|
5034
|
-
- Install and build
|
|
5035
|
-
-
|
|
5036
|
-
|
|
5037
|
-
- If you must change tracked files (setup scripts, config, docs), commit them on
|
|
5038
|
-
the working branch and open a PR for those changes \u2014 do not leave the tree
|
|
5039
|
-
dirty and do not commit secrets.
|
|
5029
|
+
- You are inside an ephemeral cloud sandbox. Its filesystem can be captured as a reusable snapshot for future sessions.
|
|
5030
|
+
- Do not assume you are on the user's laptop or that tools outside this sandbox exist.
|
|
5031
|
+
- Install and build inside the workspace. Keep all setup repeatable from a fresh clone.
|
|
5032
|
+
- Persist the final ordered commands with \`set_environment_setup_commands\`. Each command is replayed in a fresh shell, so no command may depend on shell state from a previous command.
|
|
5033
|
+
- The snapshot policy is \`block_if_dirty\`: the working tree must be clean before capture.
|
|
5040
5034
|
|
|
5041
|
-
##
|
|
5035
|
+
## Required workflow
|
|
5042
5036
|
|
|
5043
|
-
1.
|
|
5044
|
-
2.
|
|
5045
|
-
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
5050
|
-
\`capture_environment_snapshot\`.
|
|
5037
|
+
1. **Explore** \u2014 read repository instructions, manifests, lockfiles, example env files, and service configuration. Detect the language, package manager, workspace layout, required services, and expected ports.
|
|
5038
|
+
2. **Set up** \u2014 install dependencies, select compatible runtimes, configure non-secret defaults, and build. Diagnose failures yourself before asking the user.
|
|
5039
|
+
3. **Run and verify** \u2014 start the real app or service. Prove it works using process stability, logs, HTTP probes, and \`agent-browser\` interaction when a UI exists. A process merely starting or dependencies merely installing is not success.
|
|
5040
|
+
4. **Persist** \u2014 call \`set_environment_setup_commands\` with only the ordered commands you actually verified from a fresh-shell model.
|
|
5041
|
+
5. **Prepare capture** \u2014 ensure every repository is clean. Verify that \`git status --porcelain --untracked-files=all\` is empty; generated untracked files count as dirty and must be removed or covered by an appropriate existing ignore rule. If setup requires tracked changes, create a focused branch, commit them, push it, and open a PR with \`github_pr_create\` explaining why the setup change is needed. Never commit secrets.
|
|
5042
|
+
6. **Human gate** \u2014 summarize the evidence and ask the user to reply exactly \`Capture snapshot\`. Do not call \`capture_environment_snapshot\` before that explicit confirmation.
|
|
5043
|
+
7. **Capture and re-verify** \u2014 after approval, call \`capture_environment_snapshot\` with \`afterSnapshot: "resume"\`. Poll \`get_cloud_machine\` until the snapshot is ready, then confirm the sandbox remains usable and repeat the key runtime probe before declaring completion.
|
|
5051
5044
|
|
|
5052
|
-
##
|
|
5045
|
+
## Autonomy
|
|
5053
5046
|
|
|
5054
|
-
|
|
5055
|
-
secret value into the chat. When the repo needs env vars/secrets:
|
|
5056
|
-
- Identify exactly which vars are required (from .env.example, config, or boot
|
|
5057
|
-
errors) and tell the user the names and what each is for.
|
|
5058
|
-
- Direct the user to add them in the secure env-vars UI. Adding/editing there is
|
|
5059
|
-
**live-synced into this running sandbox immediately** (no restart needed): the
|
|
5060
|
-
value is injected and the file lands at its configured destinationPath
|
|
5061
|
-
(symlinked from /run/alan/env-files/\u2026).
|
|
5062
|
-
- After the user says they've added a var, **confirm it actually arrived** by
|
|
5063
|
-
reading that destination path (never echo the secret value) and re-running the
|
|
5064
|
-
boot/verification.
|
|
5047
|
+
Prefer acting over asking. Read the repo, inspect logs, try the likely command, and recover from ordinary setup failures yourself. Ask only for information that cannot be derived or safely created: a required secret, paid credential, external account choice, or genuine product-intent fork. Ask one specific question at a time and continue independent work while waiting.
|
|
5065
5048
|
|
|
5066
|
-
|
|
5049
|
+
Do not weaken a required functional check to make it pass. If the real process cannot start, the expected port cannot bind, or a browser-required UI cannot be exercised, diagnose and fix the cause. If the restriction is truly outside the sandbox, report the precise blocker instead of declaring setup complete from a mocked handler or unit-level substitute.
|
|
5067
5050
|
|
|
5068
|
-
|
|
5069
|
-
running, and verified, summarize what you did and ask the user to confirm. Only
|
|
5070
|
-
after explicit confirmation call \`capture_environment_snapshot\`. Keep the sandbox
|
|
5071
|
-
alive while you wait.
|
|
5051
|
+
## Environment variables and secrets
|
|
5072
5052
|
|
|
5073
|
-
|
|
5053
|
+
Never ask the user to paste a secret into chat, and never print secret values. When a required secret is missing:
|
|
5074
5054
|
|
|
5075
|
-
|
|
5076
|
-
|
|
5077
|
-
|
|
5078
|
-
|
|
5055
|
+
1. Name the exact variable and explain what it is used for.
|
|
5056
|
+
2. Direct the user to this cloud environment's Environment Variables / env-files UI.
|
|
5057
|
+
3. Explain that saved values sync into the running sandbox automatically with no restart required. Env files land at their configured \`destinationPath\` through \`/run/alan/env-files/\`.
|
|
5058
|
+
4. After the user saves it, verify only that the key arrived at the configured destination or environment\u2014never echo the value\u2014then continue.
|
|
5079
5059
|
|
|
5080
|
-
|
|
5060
|
+
Derive and configure non-secret values yourself when the repository provides safe defaults.
|
|
5081
5061
|
|
|
5082
|
-
|
|
5083
|
-
|
|
5084
|
-
|
|
5085
|
-
|
|
5062
|
+
## Evidence and completion
|
|
5063
|
+
|
|
5064
|
+
Do not rely on your own claim that setup worked. Before finishing, report:
|
|
5065
|
+
|
|
5066
|
+
- the install/build/run commands that succeeded;
|
|
5067
|
+
- the runtime endpoint and functional checks performed;
|
|
5068
|
+
- whether any user-provided secret was required and whether its presence was verified safely;
|
|
5069
|
+
- the persisted setup commands;
|
|
5070
|
+
- the clean-tree or PR result;
|
|
5071
|
+
- the snapshot ID/state and the post-capture verification result.
|
|
5072
|
+
|
|
5073
|
+
If any required item is missing, you are not done.`;
|
|
5086
5074
|
var REVIEW_PROMPT = `## You are the Review Agent
|
|
5087
5075
|
|
|
5088
5076
|
You are the **Review Agent** (an Alan agent profile) for pull request review sessions. When identifying yourself, say "I'm the Review Agent."
|
|
@@ -9794,6 +9782,150 @@ function createAlanProblem(input) {
|
|
|
9794
9782
|
// ../shared/dist/agent/session-result.js
|
|
9795
9783
|
var SESSION_RESUME_FAILED_MESSAGE = "Session resume failed. The previous session may have expired or is no longer available. Please start a new session.";
|
|
9796
9784
|
|
|
9785
|
+
// ../shared/dist/agent/skill-repo-scope.js
|
|
9786
|
+
var SKILL_ROOT_MARKER_RE = /\/\.(?:claude|agents|codex)\/(?:skills|commands)(?:\/|$)/;
|
|
9787
|
+
function normalizePath(path) {
|
|
9788
|
+
return path.replace(/\\/g, "/").replace(/\/+$/, "");
|
|
9789
|
+
}
|
|
9790
|
+
function deriveSkillRepoRoot(sourcePath) {
|
|
9791
|
+
if (!sourcePath)
|
|
9792
|
+
return void 0;
|
|
9793
|
+
const normalized = normalizePath(sourcePath);
|
|
9794
|
+
const marker = normalized.match(SKILL_ROOT_MARKER_RE);
|
|
9795
|
+
if (!marker || marker.index === void 0)
|
|
9796
|
+
return void 0;
|
|
9797
|
+
const beforeRoot = normalized.slice(0, marker.index).replace(/\/+$/, "");
|
|
9798
|
+
return beforeRoot || void 0;
|
|
9799
|
+
}
|
|
9800
|
+
function deriveSkillRepoLabel(sourcePath) {
|
|
9801
|
+
const repoRoot = deriveSkillRepoRoot(sourcePath);
|
|
9802
|
+
if (!repoRoot)
|
|
9803
|
+
return void 0;
|
|
9804
|
+
const label = repoRoot.split("/").filter(Boolean).pop();
|
|
9805
|
+
if (!label || label === "~")
|
|
9806
|
+
return void 0;
|
|
9807
|
+
return label;
|
|
9808
|
+
}
|
|
9809
|
+
function isTeamSkillSource(source) {
|
|
9810
|
+
return source === "team" || source === "project";
|
|
9811
|
+
}
|
|
9812
|
+
function skillIdentityKey(skill) {
|
|
9813
|
+
const command = skill.command.trim();
|
|
9814
|
+
if (isTeamSkillSource(skill.source)) {
|
|
9815
|
+
const repoRoot = skill.repoRoot && normalizePath(skill.repoRoot) || deriveSkillRepoRoot(skill.sourcePath) || "unknown";
|
|
9816
|
+
return `team:${repoRoot}:${command}`;
|
|
9817
|
+
}
|
|
9818
|
+
return `global:${command}`;
|
|
9819
|
+
}
|
|
9820
|
+
|
|
9821
|
+
// ../shared/dist/agent/skill-discovery.js
|
|
9822
|
+
var SKILL_DIRECTORY_ROOTS = [".claude/skills", ".agents/skills", ".codex/skills"];
|
|
9823
|
+
var SKILL_PATH_RE = /(?:^|[/\\])\.(?:claude|agents|codex)[/\\]+skills[/\\]+([^/\\]+)[/\\]+SKILL\.md$/i;
|
|
9824
|
+
var LEGACY_COMMAND_PATH_RE = /(?:^|[/\\])\.claude[/\\]+commands[/\\]+([^/\\]+)\.md$/i;
|
|
9825
|
+
function normalizeSkillSourcePath(sourcePath) {
|
|
9826
|
+
return sourcePath.replace(/\\/g, "/").replace(/\/{2,}/g, "/");
|
|
9827
|
+
}
|
|
9828
|
+
function unquoteScalar(value2) {
|
|
9829
|
+
const trimmed = value2.trim();
|
|
9830
|
+
if (trimmed.length < 2)
|
|
9831
|
+
return trimmed;
|
|
9832
|
+
const first = trimmed[0];
|
|
9833
|
+
const last = trimmed[trimmed.length - 1];
|
|
9834
|
+
if (first === '"' && last === '"' || first === "'" && last === "'") {
|
|
9835
|
+
return trimmed.slice(1, -1).trim();
|
|
9836
|
+
}
|
|
9837
|
+
return trimmed;
|
|
9838
|
+
}
|
|
9839
|
+
function readScalarField(lines, names) {
|
|
9840
|
+
const nameSet = new Set(names);
|
|
9841
|
+
for (const line of lines) {
|
|
9842
|
+
const colonIdx = line.indexOf(":");
|
|
9843
|
+
if (colonIdx === -1)
|
|
9844
|
+
continue;
|
|
9845
|
+
const key = line.slice(0, colonIdx).trim();
|
|
9846
|
+
if (!nameSet.has(key))
|
|
9847
|
+
continue;
|
|
9848
|
+
const value2 = unquoteScalar(line.slice(colonIdx + 1));
|
|
9849
|
+
if (value2)
|
|
9850
|
+
return value2;
|
|
9851
|
+
}
|
|
9852
|
+
return "";
|
|
9853
|
+
}
|
|
9854
|
+
function parseSkillDescription(markdown) {
|
|
9855
|
+
const normalized = markdown.replace(/\r\n/g, "\n").trim();
|
|
9856
|
+
if (!normalized)
|
|
9857
|
+
return "";
|
|
9858
|
+
const frontmatterMatch = normalized.match(/^---\n([\s\S]*?)\n---(?:\n([\s\S]*))?$/);
|
|
9859
|
+
if (frontmatterMatch) {
|
|
9860
|
+
const description = readScalarField(frontmatterMatch[1].split("\n"), ["description", "desc"]);
|
|
9861
|
+
if (description)
|
|
9862
|
+
return description;
|
|
9863
|
+
const body = frontmatterMatch[2]?.trim() ?? "";
|
|
9864
|
+
const firstBodyLine = body.split("\n").find((line) => line.trim());
|
|
9865
|
+
return firstBodyLine?.trim().slice(0, 200) ?? "";
|
|
9866
|
+
}
|
|
9867
|
+
const firstLine2 = normalized.split("\n").find((line) => line.trim());
|
|
9868
|
+
if (!firstLine2)
|
|
9869
|
+
return "";
|
|
9870
|
+
const inlineDescription = readScalarField([firstLine2], ["description", "desc"]);
|
|
9871
|
+
if (inlineDescription)
|
|
9872
|
+
return inlineDescription;
|
|
9873
|
+
return firstLine2.trim().slice(0, 200);
|
|
9874
|
+
}
|
|
9875
|
+
function extractSkillCommandFromPath(sourcePath) {
|
|
9876
|
+
const normalized = normalizeSkillSourcePath(sourcePath);
|
|
9877
|
+
const skillPathMatch = normalized.match(SKILL_PATH_RE);
|
|
9878
|
+
if (skillPathMatch?.[1])
|
|
9879
|
+
return skillPathMatch[1];
|
|
9880
|
+
const legacyCommandMatch = normalized.match(LEGACY_COMMAND_PATH_RE);
|
|
9881
|
+
if (legacyCommandMatch?.[1])
|
|
9882
|
+
return legacyCommandMatch[1];
|
|
9883
|
+
return null;
|
|
9884
|
+
}
|
|
9885
|
+
function normalizeSkillEntry(entry, defaultSource = "team") {
|
|
9886
|
+
const sourcePath = normalizeSkillSourcePath(entry.sourcePath ?? entry.path ?? "");
|
|
9887
|
+
const command = entry.command ?? entry.cmd ?? extractSkillCommandFromPath(sourcePath);
|
|
9888
|
+
if (!command)
|
|
9889
|
+
return null;
|
|
9890
|
+
const description = entry.description ?? entry.desc ?? parseSkillDescription(entry.content ?? "");
|
|
9891
|
+
const source = entry.source ?? entry.src ?? defaultSource;
|
|
9892
|
+
const repoRoot = entry.repoRoot ?? (isTeamSkillSource(source) ? deriveSkillRepoRoot(sourcePath) : void 0);
|
|
9893
|
+
const repoLabel = entry.repoLabel ?? (isTeamSkillSource(source) ? deriveSkillRepoLabel(sourcePath) : void 0);
|
|
9894
|
+
return {
|
|
9895
|
+
command,
|
|
9896
|
+
description,
|
|
9897
|
+
source,
|
|
9898
|
+
sourcePath,
|
|
9899
|
+
...repoRoot ? { repoRoot } : {},
|
|
9900
|
+
...repoLabel ? { repoLabel } : {}
|
|
9901
|
+
};
|
|
9902
|
+
}
|
|
9903
|
+
function skillPriority(source) {
|
|
9904
|
+
switch (source) {
|
|
9905
|
+
case "team":
|
|
9906
|
+
case "project":
|
|
9907
|
+
return 3;
|
|
9908
|
+
case "global":
|
|
9909
|
+
return 2;
|
|
9910
|
+
case "alan":
|
|
9911
|
+
return 1;
|
|
9912
|
+
}
|
|
9913
|
+
}
|
|
9914
|
+
function dedupeSkillEntries(entries) {
|
|
9915
|
+
const deduped = /* @__PURE__ */ new Map();
|
|
9916
|
+
for (const entry of entries) {
|
|
9917
|
+
const key = skillIdentityKey(entry);
|
|
9918
|
+
const existing = deduped.get(key);
|
|
9919
|
+
if (!existing || skillPriority(entry.source) > skillPriority(existing.source)) {
|
|
9920
|
+
deduped.set(key, entry);
|
|
9921
|
+
}
|
|
9922
|
+
}
|
|
9923
|
+
return Array.from(deduped.values());
|
|
9924
|
+
}
|
|
9925
|
+
function normalizeSkillEntries(entries, defaultSource = "team") {
|
|
9926
|
+
return dedupeSkillEntries(entries.map((entry) => normalizeSkillEntry(entry, defaultSource)).filter((entry) => Boolean(entry)));
|
|
9927
|
+
}
|
|
9928
|
+
|
|
9797
9929
|
// ../shared/dist/agent/system-prompt.js
|
|
9798
9930
|
var ALAN_IDENTITY_PROMPT = `You are Alan, the software factory agent. Alan ships software end to end \u2014 plan, write, review, test, deploy.
|
|
9799
9931
|
|
|
@@ -10155,13 +10287,78 @@ var GROK_CLI_MODELS = [
|
|
|
10155
10287
|
{ id: "grok-composer-2.5-fast", name: "Composer 2.5 Fast" }
|
|
10156
10288
|
];
|
|
10157
10289
|
var COPILOT_CLI_MODELS = [
|
|
10158
|
-
{ id: "
|
|
10290
|
+
{ id: "auto", name: "Auto" },
|
|
10291
|
+
{
|
|
10292
|
+
id: "gpt-5.6-sol",
|
|
10293
|
+
name: "GPT-5.6 Sol",
|
|
10294
|
+
capabilities: { contextWindows: [], effortLevels: GPT_5_6_ULTRA_EFFORT_LEVELS }
|
|
10295
|
+
},
|
|
10296
|
+
{
|
|
10297
|
+
id: "gpt-5.6-terra",
|
|
10298
|
+
name: "GPT-5.6 Terra",
|
|
10299
|
+
capabilities: { contextWindows: [], effortLevels: GPT_5_6_ULTRA_EFFORT_LEVELS }
|
|
10300
|
+
},
|
|
10301
|
+
{
|
|
10302
|
+
id: "gpt-5.6-luna",
|
|
10303
|
+
name: "GPT-5.6 Luna",
|
|
10304
|
+
capabilities: { contextWindows: [], effortLevels: GPT_5_6_EFFORT_LEVELS }
|
|
10305
|
+
},
|
|
10306
|
+
{
|
|
10307
|
+
id: "gpt-5.5",
|
|
10308
|
+
name: "GPT-5.5",
|
|
10309
|
+
capabilities: { contextWindows: [], effortLevels: GPT_5_5_EFFORT_LEVELS }
|
|
10310
|
+
},
|
|
10311
|
+
{
|
|
10312
|
+
id: "gpt-5.4",
|
|
10313
|
+
name: "GPT-5.4",
|
|
10314
|
+
capabilities: { contextWindows: [], effortLevels: GPT_5_4_EFFORT_LEVELS }
|
|
10315
|
+
},
|
|
10316
|
+
{
|
|
10317
|
+
id: "gpt-5.3-codex",
|
|
10318
|
+
name: "GPT-5.3 Codex",
|
|
10319
|
+
capabilities: { contextWindows: [], effortLevels: CODEX_5X_EFFORT_LEVELS }
|
|
10320
|
+
},
|
|
10321
|
+
{
|
|
10322
|
+
id: "gpt-5.4-mini",
|
|
10323
|
+
name: "GPT-5.4 Mini",
|
|
10324
|
+
capabilities: { contextWindows: [], effortLevels: GPT_5_4_EFFORT_LEVELS }
|
|
10325
|
+
},
|
|
10326
|
+
{ id: "gpt-5-mini", name: "GPT-5 Mini" },
|
|
10327
|
+
{
|
|
10328
|
+
id: "claude-sonnet-5",
|
|
10329
|
+
name: "Claude Sonnet 5",
|
|
10330
|
+
capabilities: { contextWindows: ["200k", "1m"], effortLevels: CLAUDE_EFFORT_LEVELS }
|
|
10331
|
+
},
|
|
10159
10332
|
{ id: "claude-sonnet-4.6", name: "Claude Sonnet 4.6" },
|
|
10160
|
-
{ id: "claude-
|
|
10161
|
-
{
|
|
10162
|
-
|
|
10163
|
-
|
|
10164
|
-
|
|
10333
|
+
{ id: "claude-sonnet-4.5", name: "Claude Sonnet 4.5" },
|
|
10334
|
+
{
|
|
10335
|
+
id: "claude-haiku-4.5",
|
|
10336
|
+
name: "Claude Haiku 4.5",
|
|
10337
|
+
capabilities: { contextWindows: ["200k"], effortLevels: [] }
|
|
10338
|
+
},
|
|
10339
|
+
{
|
|
10340
|
+
id: "claude-fable-5",
|
|
10341
|
+
name: "Claude Fable 5",
|
|
10342
|
+
capabilities: { contextWindows: ["1m"], effortLevels: CLAUDE_EFFORT_LEVELS }
|
|
10343
|
+
},
|
|
10344
|
+
{
|
|
10345
|
+
id: "claude-opus-5",
|
|
10346
|
+
name: "Claude Opus 5",
|
|
10347
|
+
capabilities: { contextWindows: ["200k", "1m"], effortLevels: CLAUDE_EFFORT_LEVELS }
|
|
10348
|
+
},
|
|
10349
|
+
{
|
|
10350
|
+
id: "claude-opus-4.8",
|
|
10351
|
+
name: "Claude Opus 4.8",
|
|
10352
|
+
capabilities: { contextWindows: ["200k", "1m"], effortLevels: CLAUDE_EFFORT_LEVELS }
|
|
10353
|
+
},
|
|
10354
|
+
{ id: "claude-opus-4.8-fast", name: "Claude Opus 4.8 Fast" },
|
|
10355
|
+
{ id: "claude-opus-4.7", name: "Claude Opus 4.7" },
|
|
10356
|
+
{ id: "claude-opus-4.6", name: "Claude Opus 4.6" },
|
|
10357
|
+
{ id: "claude-opus-4.5", name: "Claude Opus 4.5" },
|
|
10358
|
+
{ id: "gemini-3.1-pro-preview", name: "Gemini 3.1 Pro Preview" },
|
|
10359
|
+
{ id: "gemini-3.6-flash", name: "Gemini 3.6 Flash" },
|
|
10360
|
+
{ id: "gemini-3.5-flash", name: "Gemini 3.5 Flash" },
|
|
10361
|
+
{ id: "kimi-k2.7-code", name: "Kimi K2.7 Code" }
|
|
10165
10362
|
];
|
|
10166
10363
|
var OPENCODE_PAID_MODEL = {
|
|
10167
10364
|
billing: "paid",
|
|
@@ -12705,7 +12902,11 @@ function buildAntigravityCliArgs(context, prompt, defaultArgs = [], capabilities
|
|
|
12705
12902
|
const args = [];
|
|
12706
12903
|
const selectedModel = context.config.selectedModel?.trim();
|
|
12707
12904
|
const resumeId = context.config.runtimeSessionId?.trim() || context.config.providerSessionId?.trim();
|
|
12708
|
-
if (selectedModel)
|
|
12905
|
+
if (selectedModel) {
|
|
12906
|
+
args.push("--model", selectedModel);
|
|
12907
|
+
const effort = context.config.selectedEffortLevel?.trim().toLowerCase();
|
|
12908
|
+
if (effort && isEffortLevel(effort)) args.push("--effort", effort);
|
|
12909
|
+
}
|
|
12709
12910
|
if (resumeId) args.push("--conversation", resumeId);
|
|
12710
12911
|
if (!shouldUseReadOnlyRuntimePermissions(context.config)) {
|
|
12711
12912
|
args.push("--dangerously-skip-permissions");
|
|
@@ -12716,6 +12917,14 @@ function buildAntigravityCliArgs(context, prompt, defaultArgs = [], capabilities
|
|
|
12716
12917
|
args.push("--print-timeout", "10m");
|
|
12717
12918
|
return [...args, ...defaultArgs, "-p", prompt];
|
|
12718
12919
|
}
|
|
12920
|
+
function buildAntigravityAugmentedPrompt(context, images) {
|
|
12921
|
+
const isResume = Boolean(
|
|
12922
|
+
context.config.runtimeSessionId?.trim() || context.config.providerSessionId?.trim()
|
|
12923
|
+
);
|
|
12924
|
+
const base = buildResumeAwarePrompt(context.config, context.promptText, { isResume });
|
|
12925
|
+
const prompt = context.config.mode === "plan" ? buildPlanModePrefix(base) : base;
|
|
12926
|
+
return appendImagePathReferences(prompt, images);
|
|
12927
|
+
}
|
|
12719
12928
|
function createAntigravityCliBackend(command = "agy", defaultArgs = []) {
|
|
12720
12929
|
return {
|
|
12721
12930
|
kind: "antigravity_cli",
|
|
@@ -12737,7 +12946,7 @@ function createAntigravityCliBackend(command = "agy", defaultArgs = []) {
|
|
|
12737
12946
|
command,
|
|
12738
12947
|
args: [],
|
|
12739
12948
|
buildArgs: (ctx, prompt) => buildAntigravityCliArgs(ctx, prompt, defaultArgs, capabilities),
|
|
12740
|
-
augmentPrompt: (ctx) =>
|
|
12949
|
+
augmentPrompt: (ctx) => buildAntigravityAugmentedPrompt(ctx, imageFiles),
|
|
12741
12950
|
parseStructuredLine: parseAntigravityLine
|
|
12742
12951
|
}).run(context);
|
|
12743
12952
|
} finally {
|
|
@@ -14904,6 +15113,41 @@ var parseCopilotStructuredLine = createStructuredLineParser(
|
|
|
14904
15113
|
"copilot_cli",
|
|
14905
15114
|
handleCopilotStructuredEvent
|
|
14906
15115
|
);
|
|
15116
|
+
function buildCopilotCliArgs(context, prompt, defaultArgs = []) {
|
|
15117
|
+
const args = [
|
|
15118
|
+
"--autopilot",
|
|
15119
|
+
"--yolo",
|
|
15120
|
+
"--max-autopilot-continues",
|
|
15121
|
+
"20",
|
|
15122
|
+
"-s",
|
|
15123
|
+
"--stream",
|
|
15124
|
+
"on",
|
|
15125
|
+
"--output-format",
|
|
15126
|
+
"json",
|
|
15127
|
+
// Without this flag, real captured sessions on this machine show every
|
|
15128
|
+
// assistant.message carrying only an opaque, non-decodable `reasoningOpaque`
|
|
15129
|
+
// blob — never `reasoningText` — so parsers/copilot.ts's onThinking() never
|
|
15130
|
+
// fires and the thinking stream never reaches the UI. `--enable-reasoning-summaries`
|
|
15131
|
+
// is documented in `copilot --help` as exactly this: "Request reasoning
|
|
15132
|
+
// summaries for OpenAI models." Always on — it's additive (models/providers
|
|
15133
|
+
// that don't support summaries are unaffected) and this is the "start in
|
|
15134
|
+
// thinking mode by default" behavior other providers already give equivalent
|
|
15135
|
+
// visibility into.
|
|
15136
|
+
"--enable-reasoning-summaries"
|
|
15137
|
+
];
|
|
15138
|
+
if (shouldUseReadOnlyRuntimePermissions(context.config)) {
|
|
15139
|
+
args.push("--deny-tool", "write");
|
|
15140
|
+
}
|
|
15141
|
+
if (context.config.selectedModel?.trim()) {
|
|
15142
|
+
args.push("--model", context.config.selectedModel.trim());
|
|
15143
|
+
}
|
|
15144
|
+
const effort = context.config.selectedEffortLevel?.trim().toLowerCase();
|
|
15145
|
+
if (effort && isEffortLevel(effort)) {
|
|
15146
|
+
args.push("--effort", effort);
|
|
15147
|
+
}
|
|
15148
|
+
args.push("-p", prompt);
|
|
15149
|
+
return [...args, ...defaultArgs];
|
|
15150
|
+
}
|
|
14907
15151
|
function createCopilotCliBackend(command = "copilot", defaultArgs = []) {
|
|
14908
15152
|
return {
|
|
14909
15153
|
kind: "copilot_cli",
|
|
@@ -14919,25 +15163,7 @@ function createCopilotCliBackend(command = "copilot", defaultArgs = []) {
|
|
|
14919
15163
|
supportTier: "structured",
|
|
14920
15164
|
command,
|
|
14921
15165
|
args: [],
|
|
14922
|
-
buildArgs: (ctx, prompt) =>
|
|
14923
|
-
const args = [
|
|
14924
|
-
"--autopilot",
|
|
14925
|
-
"--yolo",
|
|
14926
|
-
"--max-autopilot-continues",
|
|
14927
|
-
"20",
|
|
14928
|
-
"-s",
|
|
14929
|
-
"--stream",
|
|
14930
|
-
"on",
|
|
14931
|
-
"--output-format",
|
|
14932
|
-
"json",
|
|
14933
|
-
"-p",
|
|
14934
|
-
prompt
|
|
14935
|
-
];
|
|
14936
|
-
if (ctx.config.selectedModel?.trim()) {
|
|
14937
|
-
args.push("--model", ctx.config.selectedModel.trim());
|
|
14938
|
-
}
|
|
14939
|
-
return [...args, ...defaultArgs];
|
|
14940
|
-
},
|
|
15166
|
+
buildArgs: (ctx, prompt) => buildCopilotCliArgs(ctx, prompt, defaultArgs),
|
|
14941
15167
|
augmentPrompt: (ctx) => buildPromptWithImagePathReferences(ctx, imageFiles),
|
|
14942
15168
|
parseStructuredLine: parseCopilotStructuredLine,
|
|
14943
15169
|
// Local background Agent/detached work uses the shared result gate; keep
|
|
@@ -18194,7 +18420,7 @@ function extractPathCandidates(content, options, extensionsPattern = "png|jpe?g|
|
|
|
18194
18420
|
...options.pathHints ?? []
|
|
18195
18421
|
];
|
|
18196
18422
|
}
|
|
18197
|
-
function
|
|
18423
|
+
function normalizePath2(candidate, cwd) {
|
|
18198
18424
|
let path = candidate.trim().replace(/^file:\/\//, "");
|
|
18199
18425
|
try {
|
|
18200
18426
|
path = decodeURI(path);
|
|
@@ -18217,7 +18443,7 @@ function extractBrowserMediaPathHints(content, cwd, toolName, options = {}, kind
|
|
|
18217
18443
|
return extractPathCandidatesFromValues(
|
|
18218
18444
|
collectContentStrings(content, options.toolInput),
|
|
18219
18445
|
extensionsPattern
|
|
18220
|
-
).map((candidate) =>
|
|
18446
|
+
).map((candidate) => normalizePath2(candidate, effectiveCwd)).filter((path) => Boolean(path));
|
|
18221
18447
|
}
|
|
18222
18448
|
function readImageDimensions2(buffer, mimeType) {
|
|
18223
18449
|
if (mimeType === "image/png" && buffer.length >= 24 && buffer.toString("ascii", 1, 4) === "PNG") {
|
|
@@ -18250,7 +18476,7 @@ function extractGeneratedImagesFromToolResult(toolId, content, cwd, toolName, op
|
|
|
18250
18476
|
const seen = /* @__PURE__ */ new Set();
|
|
18251
18477
|
const effectiveCwd = resolveToolCwd(cwd, options.toolInput);
|
|
18252
18478
|
for (const candidate of extractPathCandidates(content, options)) {
|
|
18253
|
-
const path =
|
|
18479
|
+
const path = normalizePath2(candidate, effectiveCwd);
|
|
18254
18480
|
if (!path || seen.has(path) || !(0, import_fs9.existsSync)(path)) continue;
|
|
18255
18481
|
seen.add(path);
|
|
18256
18482
|
const ext = (0, import_path9.extname)(path).toLowerCase();
|
|
@@ -18289,7 +18515,7 @@ function extractSessionMediaFromToolResult(toolId, content, cwd, toolName, optio
|
|
|
18289
18515
|
const maxBytes = kind === "video" ? MAX_SESSION_VIDEO_BYTES : MAX_GENERATED_IMAGE_BYTES;
|
|
18290
18516
|
const mimeByExt = kind === "video" ? VIDEO_MIME_BY_EXT : IMAGE_MIME_BY_EXT;
|
|
18291
18517
|
for (const candidate of extractPathCandidates(content, options, extensionsPattern)) {
|
|
18292
|
-
const path =
|
|
18518
|
+
const path = normalizePath2(candidate, effectiveCwd);
|
|
18293
18519
|
if (!path || seen.has(path) || !(0, import_fs9.existsSync)(path)) continue;
|
|
18294
18520
|
seen.add(path);
|
|
18295
18521
|
const ext = (0, import_path9.extname)(path).toLowerCase();
|
|
@@ -22377,6 +22603,10 @@ Object.assign(lookup, {
|
|
|
22377
22603
|
connect: lookup
|
|
22378
22604
|
});
|
|
22379
22605
|
|
|
22606
|
+
// src/cli-ensure-install.ts
|
|
22607
|
+
var import_node_child_process3 = require("child_process");
|
|
22608
|
+
var import_node_os4 = require("os");
|
|
22609
|
+
|
|
22380
22610
|
// src/cli-executable.ts
|
|
22381
22611
|
var import_node_child_process2 = require("child_process");
|
|
22382
22612
|
var import_node_fs3 = require("fs");
|
|
@@ -22437,6 +22667,8 @@ var CLI_COMMAND_ALIASES = {
|
|
|
22437
22667
|
grok: ["grok-build"]
|
|
22438
22668
|
};
|
|
22439
22669
|
var resolvedCliCache = /* @__PURE__ */ new Map();
|
|
22670
|
+
var NEGATIVE_RESOLUTION_TTL_MS = 15e3;
|
|
22671
|
+
var negativeResolutionExpiry = /* @__PURE__ */ new Map();
|
|
22440
22672
|
var cachedLoginShellEnv = null;
|
|
22441
22673
|
function parseEnvOutput(output) {
|
|
22442
22674
|
const loginEnv = {};
|
|
@@ -22477,9 +22709,23 @@ function getDaemonCliEnvironment() {
|
|
|
22477
22709
|
}
|
|
22478
22710
|
function cacheResolvedCli(command, resolvedPath) {
|
|
22479
22711
|
resolvedCliCache.set(command, resolvedPath);
|
|
22712
|
+
if (resolvedPath === null) {
|
|
22713
|
+
negativeResolutionExpiry.set(command, Date.now() + NEGATIVE_RESOLUTION_TTL_MS);
|
|
22714
|
+
} else {
|
|
22715
|
+
negativeResolutionExpiry.delete(command);
|
|
22716
|
+
}
|
|
22480
22717
|
}
|
|
22481
22718
|
function getCachedResolvedCli(command) {
|
|
22482
|
-
|
|
22719
|
+
const cached = resolvedCliCache.get(command);
|
|
22720
|
+
if (cached === null) {
|
|
22721
|
+
const expiresAt = negativeResolutionExpiry.get(command);
|
|
22722
|
+
if (expiresAt === void 0 || Date.now() >= expiresAt) {
|
|
22723
|
+
resolvedCliCache.delete(command);
|
|
22724
|
+
negativeResolutionExpiry.delete(command);
|
|
22725
|
+
return void 0;
|
|
22726
|
+
}
|
|
22727
|
+
}
|
|
22728
|
+
return cached;
|
|
22483
22729
|
}
|
|
22484
22730
|
function resolveViaWhere(command, env) {
|
|
22485
22731
|
if ((0, import_node_os3.platform)() !== "win32") return null;
|
|
@@ -22602,11 +22848,11 @@ function augmentCliPath2(env) {
|
|
|
22602
22848
|
function resolveCliExecutable(command, env = getDaemonCliEnvironment()) {
|
|
22603
22849
|
const trimmed = command.trim();
|
|
22604
22850
|
if (!trimmed) return null;
|
|
22605
|
-
const cached =
|
|
22851
|
+
const cached = getCachedResolvedCli(trimmed);
|
|
22606
22852
|
if (cached === null) return null;
|
|
22607
22853
|
if (cached && isRunnableFile(cached)) return cached;
|
|
22608
22854
|
if ((trimmed.includes("/") || trimmed.includes("\\")) && isRunnableFile(trimmed)) {
|
|
22609
|
-
|
|
22855
|
+
cacheResolvedCli(trimmed, trimmed);
|
|
22610
22856
|
return trimmed;
|
|
22611
22857
|
}
|
|
22612
22858
|
const enriched = augmentCliPath2(env);
|
|
@@ -22638,16 +22884,16 @@ function resolveCliExecutable(command, env = getDaemonCliEnvironment()) {
|
|
|
22638
22884
|
if (seen.has(candidate)) continue;
|
|
22639
22885
|
seen.add(candidate);
|
|
22640
22886
|
if (isRunnableFile(candidate)) {
|
|
22641
|
-
|
|
22887
|
+
cacheResolvedCli(trimmed, candidate);
|
|
22642
22888
|
return candidate;
|
|
22643
22889
|
}
|
|
22644
22890
|
}
|
|
22645
22891
|
const viaWhere = resolveViaWhere(trimmed, enriched);
|
|
22646
22892
|
if (viaWhere) {
|
|
22647
|
-
|
|
22893
|
+
cacheResolvedCli(trimmed, viaWhere);
|
|
22648
22894
|
return viaWhere;
|
|
22649
22895
|
}
|
|
22650
|
-
|
|
22896
|
+
cacheResolvedCli(trimmed, null);
|
|
22651
22897
|
return null;
|
|
22652
22898
|
}
|
|
22653
22899
|
function normalizeDiscoverableProvider(provider) {
|
|
@@ -22685,26 +22931,128 @@ function resolveBackendRuntimeCommand(backendKind, env = getDaemonCliEnvironment
|
|
|
22685
22931
|
cacheResolvedCli(command, resolved);
|
|
22686
22932
|
return resolved ?? void 0;
|
|
22687
22933
|
}
|
|
22934
|
+
function invalidateResolvedCli(command) {
|
|
22935
|
+
const trimmed = command.trim();
|
|
22936
|
+
if (trimmed) {
|
|
22937
|
+
resolvedCliCache.delete(trimmed);
|
|
22938
|
+
negativeResolutionExpiry.delete(trimmed);
|
|
22939
|
+
}
|
|
22940
|
+
}
|
|
22688
22941
|
function revalidateBackendRuntimeCommand(backendKind, env = getDaemonCliEnvironment()) {
|
|
22689
22942
|
if (!backendKind) return void 0;
|
|
22690
22943
|
const command = BACKEND_CLI_COMMANDS[backendKind];
|
|
22691
22944
|
if (!command) return void 0;
|
|
22692
|
-
|
|
22945
|
+
invalidateResolvedCli(command);
|
|
22693
22946
|
const spec = Object.values(PROVIDER_CLI_COMMANDS).find((entry) => entry.command === command);
|
|
22694
22947
|
const envOverride = spec ? spec.envVars.map((name) => env[name]?.trim()).find(Boolean) : void 0;
|
|
22695
|
-
if (envOverride)
|
|
22948
|
+
if (envOverride) invalidateResolvedCli(envOverride);
|
|
22696
22949
|
return resolveBackendRuntimeCommand(backendKind, env);
|
|
22697
22950
|
}
|
|
22698
22951
|
|
|
22952
|
+
// src/cli-ensure-install.ts
|
|
22953
|
+
var CLI_RUNTIME_VERSIONS_ENV = "ALAN_CLI_RUNTIME_VERSIONS";
|
|
22954
|
+
var INSTALLABLE_PROVIDER_PACKAGES = {
|
|
22955
|
+
claude_cli: { npmPackage: "@anthropic-ai/claude-code", command: "claude", label: "Claude Code" },
|
|
22956
|
+
codex_app_server: { npmPackage: "@openai/codex", command: "codex", label: "Codex" },
|
|
22957
|
+
copilot_cli: { npmPackage: "@github/copilot", command: "copilot", label: "Copilot" },
|
|
22958
|
+
opencode_cli: { npmPackage: "opencode-ai", command: "opencode", label: "opencode" }
|
|
22959
|
+
};
|
|
22960
|
+
var INSTALL_TIMEOUT_MS = 12e4;
|
|
22961
|
+
var installOutcomes = /* @__PURE__ */ new Map();
|
|
22962
|
+
function canInstallProviderCli(backendKind) {
|
|
22963
|
+
return Boolean(backendKind && INSTALLABLE_PROVIDER_PACKAGES[backendKind]);
|
|
22964
|
+
}
|
|
22965
|
+
function pinnedVersion(npmPackage) {
|
|
22966
|
+
const raw = process.env[CLI_RUNTIME_VERSIONS_ENV];
|
|
22967
|
+
if (!raw) return "latest";
|
|
22968
|
+
try {
|
|
22969
|
+
const parsed = JSON.parse(raw);
|
|
22970
|
+
const version = parsed[npmPackage];
|
|
22971
|
+
if (typeof version === "string" && version.trim()) return version.trim();
|
|
22972
|
+
} catch {
|
|
22973
|
+
}
|
|
22974
|
+
return "latest";
|
|
22975
|
+
}
|
|
22976
|
+
function runNpmInstall(installSpec, env, timeoutMs) {
|
|
22977
|
+
return new Promise((resolve6) => {
|
|
22978
|
+
const isWin = (0, import_node_os4.platform)() === "win32";
|
|
22979
|
+
let child;
|
|
22980
|
+
try {
|
|
22981
|
+
child = (0, import_node_child_process3.spawn)("npm", ["install", "-g", installSpec], {
|
|
22982
|
+
env,
|
|
22983
|
+
shell: isWin,
|
|
22984
|
+
windowsHide: isWin ? true : void 0,
|
|
22985
|
+
timeout: timeoutMs,
|
|
22986
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
22987
|
+
});
|
|
22988
|
+
} catch (error) {
|
|
22989
|
+
resolve6({ status: null, stdout: "", stderr: "", error });
|
|
22990
|
+
return;
|
|
22991
|
+
}
|
|
22992
|
+
let stdout = "";
|
|
22993
|
+
let stderr = "";
|
|
22994
|
+
child.stdout?.setEncoding("utf8").on("data", (chunk) => {
|
|
22995
|
+
stdout += chunk;
|
|
22996
|
+
});
|
|
22997
|
+
child.stderr?.setEncoding("utf8").on("data", (chunk) => {
|
|
22998
|
+
stderr += chunk;
|
|
22999
|
+
});
|
|
23000
|
+
child.once("error", (error) => resolve6({ status: null, stdout, stderr, error }));
|
|
23001
|
+
child.once(
|
|
23002
|
+
"close",
|
|
23003
|
+
(status, signal) => resolve6({
|
|
23004
|
+
status,
|
|
23005
|
+
stdout,
|
|
23006
|
+
stderr,
|
|
23007
|
+
// Spawn `timeout` kills by signal without an `error` event; surface it
|
|
23008
|
+
// so a timed-out install is reported as a failure, not status null + ok.
|
|
23009
|
+
...signal ? { error: new Error(`npm install killed by ${signal}`) } : {}
|
|
23010
|
+
})
|
|
23011
|
+
);
|
|
23012
|
+
});
|
|
23013
|
+
}
|
|
23014
|
+
async function attemptInstall(spec, options) {
|
|
23015
|
+
const installSpec = `${spec.npmPackage}@${pinnedVersion(spec.npmPackage)}`;
|
|
23016
|
+
const notify = options?.notify ?? ((message) => console.info(`[cli-ensure-install] ${message}`));
|
|
23017
|
+
notify(`Installing ${spec.label} CLI (${installSpec})\u2026`);
|
|
23018
|
+
const runner = options?.runner ?? runNpmInstall;
|
|
23019
|
+
const result = await runner(installSpec, getDaemonCliEnvironment(), INSTALL_TIMEOUT_MS);
|
|
23020
|
+
if (result.error || result.status !== 0) {
|
|
23021
|
+
console.warn(`[cli-ensure-install] npm install -g ${installSpec} failed`, {
|
|
23022
|
+
status: result.status,
|
|
23023
|
+
error: result.error?.message,
|
|
23024
|
+
output: `${result.stderr || result.stdout}`.trim().slice(-500)
|
|
23025
|
+
});
|
|
23026
|
+
notify(`Failed to install ${spec.label} CLI (${installSpec}).`);
|
|
23027
|
+
return false;
|
|
23028
|
+
}
|
|
23029
|
+
invalidateResolvedCli(spec.command);
|
|
23030
|
+
notify(`Installed ${spec.label} CLI (${installSpec}).`);
|
|
23031
|
+
return true;
|
|
23032
|
+
}
|
|
23033
|
+
function ensureProviderCliInstalled(backendKind, options) {
|
|
23034
|
+
if (!backendKind) return Promise.resolve(false);
|
|
23035
|
+
const spec = INSTALLABLE_PROVIDER_PACKAGES[backendKind];
|
|
23036
|
+
if (!spec) return Promise.resolve(false);
|
|
23037
|
+
const existing = installOutcomes.get(spec.npmPackage);
|
|
23038
|
+
if (existing) return existing;
|
|
23039
|
+
const attempt = attemptInstall(spec, options).catch((error) => {
|
|
23040
|
+
console.warn(`[cli-ensure-install] install attempt for ${spec.npmPackage} threw`, error);
|
|
23041
|
+
return false;
|
|
23042
|
+
});
|
|
23043
|
+
installOutcomes.set(spec.npmPackage, attempt);
|
|
23044
|
+
return attempt;
|
|
23045
|
+
}
|
|
23046
|
+
|
|
22699
23047
|
// src/computer-readiness.ts
|
|
22700
23048
|
var import_node_fs5 = require("fs");
|
|
22701
23049
|
|
|
22702
23050
|
// src/runtime-config.ts
|
|
22703
23051
|
var import_node_fs4 = require("fs");
|
|
22704
|
-
var
|
|
23052
|
+
var import_node_os5 = require("os");
|
|
22705
23053
|
var import_node_path4 = require("path");
|
|
22706
|
-
var DEFAULT_AGENT_DIR = (0, import_node_path4.join)((0,
|
|
22707
|
-
var LEGACY_AGENT_DIR = (0, import_node_path4.join)((0,
|
|
23054
|
+
var DEFAULT_AGENT_DIR = (0, import_node_path4.join)((0, import_node_os5.homedir)(), ".alan", "agent");
|
|
23055
|
+
var LEGACY_AGENT_DIR = (0, import_node_path4.join)((0, import_node_os5.homedir)(), ".aiden", "agent");
|
|
22708
23056
|
var AGENT_CONFIG_KEYS = /* @__PURE__ */ new Map([
|
|
22709
23057
|
["apiUrl", "string"],
|
|
22710
23058
|
["wsUrl", "string"],
|
|
@@ -23012,7 +23360,7 @@ function buildComputerReadiness(input) {
|
|
|
23012
23360
|
}
|
|
23013
23361
|
|
|
23014
23362
|
// src/core-agent.ts
|
|
23015
|
-
var
|
|
23363
|
+
var import_node_os6 = require("os");
|
|
23016
23364
|
var CoreAgent = class _CoreAgent extends BaseMachineAgent {
|
|
23017
23365
|
childProcess = null;
|
|
23018
23366
|
_aborted = false;
|
|
@@ -23064,7 +23412,18 @@ var CoreAgent = class _CoreAgent extends BaseMachineAgent {
|
|
|
23064
23412
|
* and re-resolving once lets the current run recover against the new location.
|
|
23065
23413
|
*/
|
|
23066
23414
|
revalidateRuntimeCommand() {
|
|
23067
|
-
|
|
23415
|
+
const resolved = revalidateBackendRuntimeCommand(this.runtime.backendKind) ?? null;
|
|
23416
|
+
if (!resolved && this.runtime.backendKind) {
|
|
23417
|
+
const backendKind = this.runtime.backendKind;
|
|
23418
|
+
void ensureProviderCliInstalled(backendKind).then((installed) => {
|
|
23419
|
+
if (installed) {
|
|
23420
|
+
console.info("[CoreAgent] Installed missing provider CLI after spawn ENOENT", {
|
|
23421
|
+
backendKind
|
|
23422
|
+
});
|
|
23423
|
+
}
|
|
23424
|
+
});
|
|
23425
|
+
}
|
|
23426
|
+
return resolved;
|
|
23068
23427
|
}
|
|
23069
23428
|
// ── Interactive tool response (WS relay → stdin) ───────────────────────
|
|
23070
23429
|
/**
|
|
@@ -23151,7 +23510,7 @@ var CoreAgent = class _CoreAgent extends BaseMachineAgent {
|
|
|
23151
23510
|
if (this.runtime.backendKind === "grok_cli" && this.providerApiKey) {
|
|
23152
23511
|
augmented.XAI_API_KEY = this.providerApiKey;
|
|
23153
23512
|
}
|
|
23154
|
-
if ((0,
|
|
23513
|
+
if ((0, import_node_os6.platform)() !== "win32") {
|
|
23155
23514
|
const home = augmented.HOME ?? "/home/user";
|
|
23156
23515
|
const extraPaths = [`${home}/.local/node/bin`, `${home}/.local/bin`];
|
|
23157
23516
|
const separator = ":";
|
|
@@ -23706,11 +24065,97 @@ var EncryptedEventOutbox = class _EncryptedEventOutbox {
|
|
|
23706
24065
|
}
|
|
23707
24066
|
};
|
|
23708
24067
|
|
|
23709
|
-
// src/
|
|
23710
|
-
var import_node_crypto2 = require("crypto");
|
|
24068
|
+
// src/local-skill-scan.ts
|
|
23711
24069
|
var import_node_fs7 = require("fs");
|
|
23712
|
-
var import_node_os6 = require("os");
|
|
23713
24070
|
var import_node_path6 = require("path");
|
|
24071
|
+
var SKILL_READ_LIMIT_BYTES = 8192;
|
|
24072
|
+
var SKILL_CACHE_TTL_MS = 3e4;
|
|
24073
|
+
function readSkillHead(path) {
|
|
24074
|
+
const fd = (0, import_node_fs7.openSync)(path, "r");
|
|
24075
|
+
try {
|
|
24076
|
+
const buffer = Buffer.alloc(SKILL_READ_LIMIT_BYTES);
|
|
24077
|
+
const bytesRead = (0, import_node_fs7.readSync)(fd, buffer, 0, SKILL_READ_LIMIT_BYTES, 0);
|
|
24078
|
+
return buffer.subarray(0, bytesRead).toString("utf-8");
|
|
24079
|
+
} finally {
|
|
24080
|
+
(0, import_node_fs7.closeSync)(fd);
|
|
24081
|
+
}
|
|
24082
|
+
}
|
|
24083
|
+
function scanSkillDir(dirPath, source, repoRoot, entries, errors) {
|
|
24084
|
+
if (!(0, import_node_fs7.existsSync)(dirPath)) return;
|
|
24085
|
+
let names;
|
|
24086
|
+
try {
|
|
24087
|
+
names = (0, import_node_fs7.readdirSync)(dirPath);
|
|
24088
|
+
} catch (error) {
|
|
24089
|
+
errors.push(`Failed to scan ${dirPath}: ${error instanceof Error ? error.message : error}`);
|
|
24090
|
+
return;
|
|
24091
|
+
}
|
|
24092
|
+
for (const name of names) {
|
|
24093
|
+
const skillPath = (0, import_node_path6.join)(dirPath, name, "SKILL.md");
|
|
24094
|
+
let isDirectory = false;
|
|
24095
|
+
try {
|
|
24096
|
+
isDirectory = (0, import_node_fs7.statSync)((0, import_node_path6.join)(dirPath, name)).isDirectory();
|
|
24097
|
+
} catch {
|
|
24098
|
+
continue;
|
|
24099
|
+
}
|
|
24100
|
+
if (!isDirectory || !(0, import_node_fs7.existsSync)(skillPath)) continue;
|
|
24101
|
+
try {
|
|
24102
|
+
entries.push({ content: readSkillHead(skillPath), source, sourcePath: skillPath, repoRoot });
|
|
24103
|
+
} catch (error) {
|
|
24104
|
+
errors.push(`Failed to read ${skillPath}: ${error instanceof Error ? error.message : error}`);
|
|
24105
|
+
}
|
|
24106
|
+
}
|
|
24107
|
+
}
|
|
24108
|
+
function discoverChildRepos(parentPath) {
|
|
24109
|
+
let names;
|
|
24110
|
+
try {
|
|
24111
|
+
names = (0, import_node_fs7.readdirSync)(parentPath);
|
|
24112
|
+
} catch {
|
|
24113
|
+
return [];
|
|
24114
|
+
}
|
|
24115
|
+
const children = [];
|
|
24116
|
+
for (const name of names) {
|
|
24117
|
+
if (name.startsWith(".")) continue;
|
|
24118
|
+
const childPath = (0, import_node_path6.join)(parentPath, name);
|
|
24119
|
+
try {
|
|
24120
|
+
if ((0, import_node_fs7.statSync)(childPath).isDirectory()) children.push(childPath);
|
|
24121
|
+
} catch {
|
|
24122
|
+
}
|
|
24123
|
+
}
|
|
24124
|
+
return children;
|
|
24125
|
+
}
|
|
24126
|
+
function scanLocalSkills(homeDir, projectPath) {
|
|
24127
|
+
const rawEntries = [];
|
|
24128
|
+
const errors = [];
|
|
24129
|
+
for (const root of SKILL_DIRECTORY_ROOTS) {
|
|
24130
|
+
scanSkillDir((0, import_node_path6.join)(homeDir, root), "global", void 0, rawEntries, errors);
|
|
24131
|
+
}
|
|
24132
|
+
if (projectPath) {
|
|
24133
|
+
for (const dir of [projectPath, ...discoverChildRepos(projectPath)]) {
|
|
24134
|
+
for (const root of SKILL_DIRECTORY_ROOTS) {
|
|
24135
|
+
scanSkillDir((0, import_node_path6.join)(dir, root), "team", dir, rawEntries, errors);
|
|
24136
|
+
}
|
|
24137
|
+
}
|
|
24138
|
+
}
|
|
24139
|
+
return { skills: normalizeSkillEntries(rawEntries, "team"), errors };
|
|
24140
|
+
}
|
|
24141
|
+
var skillScanCache = /* @__PURE__ */ new Map();
|
|
24142
|
+
function scanLocalSkillsCached(homeDir, projectPath, options) {
|
|
24143
|
+
const key = projectPath ?? "";
|
|
24144
|
+
const now = Date.now();
|
|
24145
|
+
if (!options?.refresh) {
|
|
24146
|
+
const cached = skillScanCache.get(key);
|
|
24147
|
+
if (cached && cached.expiresAt > now) return cached.result;
|
|
24148
|
+
}
|
|
24149
|
+
const result = scanLocalSkills(homeDir, projectPath);
|
|
24150
|
+
skillScanCache.set(key, { expiresAt: now + SKILL_CACHE_TTL_MS, result });
|
|
24151
|
+
return result;
|
|
24152
|
+
}
|
|
24153
|
+
|
|
24154
|
+
// src/mcp-registration.ts
|
|
24155
|
+
var import_node_crypto2 = require("crypto");
|
|
24156
|
+
var import_node_fs8 = require("fs");
|
|
24157
|
+
var import_node_os7 = require("os");
|
|
24158
|
+
var import_node_path7 = require("path");
|
|
23714
24159
|
|
|
23715
24160
|
// ../../node_modules/smol-toml/dist/error.js
|
|
23716
24161
|
function getLineColFromPtr(string, ptr) {
|
|
@@ -24507,18 +24952,18 @@ var inspectAlanMcpThroughProviderCli = async (backendKind, expectedUrl, home) =>
|
|
|
24507
24952
|
return result;
|
|
24508
24953
|
};
|
|
24509
24954
|
async function waitForConfigLock(lockPath) {
|
|
24510
|
-
(0,
|
|
24955
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path7.dirname)(lockPath), { recursive: true });
|
|
24511
24956
|
const startedAt = Date.now();
|
|
24512
24957
|
while (true) {
|
|
24513
24958
|
try {
|
|
24514
|
-
(0,
|
|
24515
|
-
return () => (0,
|
|
24959
|
+
(0, import_node_fs8.mkdirSync)(lockPath);
|
|
24960
|
+
return () => (0, import_node_fs8.rmSync)(lockPath, { recursive: true, force: true });
|
|
24516
24961
|
} catch (error) {
|
|
24517
24962
|
const code = error && typeof error === "object" && "code" in error ? error.code : void 0;
|
|
24518
24963
|
if (code !== "EEXIST") throw error;
|
|
24519
24964
|
try {
|
|
24520
|
-
if (Date.now() - (0,
|
|
24521
|
-
(0,
|
|
24965
|
+
if (Date.now() - (0, import_node_fs8.statSync)(lockPath).mtimeMs > CONFIG_LOCK_STALE_MS) {
|
|
24966
|
+
(0, import_node_fs8.rmSync)(lockPath, { recursive: true, force: true });
|
|
24522
24967
|
continue;
|
|
24523
24968
|
}
|
|
24524
24969
|
} catch {
|
|
@@ -24534,7 +24979,7 @@ async function waitForConfigLock(lockPath) {
|
|
|
24534
24979
|
function saveMalformedBackup(path, content) {
|
|
24535
24980
|
const hash = (0, import_node_crypto2.createHash)("sha256").update(content).digest("hex").slice(0, 12);
|
|
24536
24981
|
const backupPath = `${path}.alan-backup-${hash}`;
|
|
24537
|
-
if (!(0,
|
|
24982
|
+
if (!(0, import_node_fs8.existsSync)(backupPath)) (0, import_node_fs8.copyFileSync)(path, backupPath);
|
|
24538
24983
|
return backupPath;
|
|
24539
24984
|
}
|
|
24540
24985
|
function parseJsonObject2(path, content) {
|
|
@@ -24581,22 +25026,22 @@ function mergeCodexAlanSection(path, existingContent, desiredContent) {
|
|
|
24581
25026
|
function atomicWriteManagedConfig(path, content) {
|
|
24582
25027
|
const pendingPath = `${path}.alan-pending-${process.pid}-${(0, import_node_crypto2.randomBytes)(6).toString("hex")}`;
|
|
24583
25028
|
try {
|
|
24584
|
-
(0,
|
|
24585
|
-
(0,
|
|
25029
|
+
(0, import_node_fs8.writeFileSync)(pendingPath, content, { encoding: "utf8", mode: 384, flag: "wx" });
|
|
25030
|
+
(0, import_node_fs8.renameSync)(pendingPath, path);
|
|
24586
25031
|
} finally {
|
|
24587
|
-
(0,
|
|
25032
|
+
(0, import_node_fs8.rmSync)(pendingPath, { force: true });
|
|
24588
25033
|
}
|
|
24589
25034
|
}
|
|
24590
|
-
async function ensureAlanMcpRegistered(backendKind, registration, home = (0,
|
|
25035
|
+
async function ensureAlanMcpRegistered(backendKind, registration, home = (0, import_node_os7.homedir)(), inspectCli = inspectAlanMcpThroughProviderCli) {
|
|
24591
25036
|
try {
|
|
24592
25037
|
const mcpServers = buildAlanMcpServers(registration);
|
|
24593
25038
|
const files = alanMcpConfigFilesForBackend(backendKind, mcpServers, home);
|
|
24594
25039
|
const paths = [];
|
|
24595
25040
|
for (const file of files) {
|
|
24596
|
-
(0,
|
|
25041
|
+
(0, import_node_fs8.mkdirSync)((0, import_node_path7.dirname)(file.path), { recursive: true });
|
|
24597
25042
|
const releaseLock = await waitForConfigLock(`${file.path}.alan-lock`);
|
|
24598
25043
|
try {
|
|
24599
|
-
const current = (0,
|
|
25044
|
+
const current = (0, import_node_fs8.existsSync)(file.path) ? (0, import_node_fs8.readFileSync)(file.path, "utf8") : null;
|
|
24600
25045
|
const content = file.path.endsWith(".toml") ? mergeCodexAlanSection(file.path, current, file.content) : mergeJsonConfig(file.path, current, file.content);
|
|
24601
25046
|
if (current !== content) atomicWriteManagedConfig(file.path, content);
|
|
24602
25047
|
paths.push(file.path);
|
|
@@ -24647,13 +25092,13 @@ async function ensureAlanMcpRegistered(backendKind, registration, home = (0, imp
|
|
|
24647
25092
|
return { ok: false, paths: [], error: err instanceof Error ? err.message : String(err) };
|
|
24648
25093
|
}
|
|
24649
25094
|
}
|
|
24650
|
-
async function verifyAlanMcpRegistered(backendKind, home = (0,
|
|
25095
|
+
async function verifyAlanMcpRegistered(backendKind, home = (0, import_node_os7.homedir)(), inspectCli = inspectAlanMcpThroughProviderCli) {
|
|
24651
25096
|
const files = alanMcpConfigFilesForBackend(backendKind, {}, home);
|
|
24652
|
-
const missing = files.map((f) => f.path).filter((p) => !(0,
|
|
25097
|
+
const missing = files.map((f) => f.path).filter((p) => !(0, import_node_fs8.existsSync)(p));
|
|
24653
25098
|
const presentEntries = files.map((file) => ({
|
|
24654
25099
|
path: file.path,
|
|
24655
|
-
url: (0,
|
|
24656
|
-
})).filter((entry) => (0,
|
|
25100
|
+
url: (0, import_node_fs8.existsSync)(file.path) ? readUsableAlanMcpUrl(file.path) : null
|
|
25101
|
+
})).filter((entry) => (0, import_node_fs8.existsSync)(entry.path));
|
|
24657
25102
|
let invalid = presentEntries.filter((entry) => !entry.url).map((entry) => entry.path);
|
|
24658
25103
|
const urls = new Set(presentEntries.flatMap((entry) => entry.url ? [entry.url] : []));
|
|
24659
25104
|
if (urls.size > 1) invalid = presentEntries.map((entry) => entry.path);
|
|
@@ -24709,15 +25154,15 @@ function removeAlanFromJsonConfig(path, existingContent) {
|
|
|
24709
25154
|
}
|
|
24710
25155
|
return JSON.stringify(config);
|
|
24711
25156
|
}
|
|
24712
|
-
async function unregisterAlanMcp(backendKind, home = (0,
|
|
25157
|
+
async function unregisterAlanMcp(backendKind, home = (0, import_node_os7.homedir)()) {
|
|
24713
25158
|
const removedPaths = [];
|
|
24714
25159
|
const errors = [];
|
|
24715
25160
|
const files = alanMcpConfigFilesForBackend(backendKind, {}, home);
|
|
24716
25161
|
for (const file of files) {
|
|
24717
|
-
if (!(0,
|
|
25162
|
+
if (!(0, import_node_fs8.existsSync)(file.path)) continue;
|
|
24718
25163
|
const releaseLock = await waitForConfigLock(`${file.path}.alan-lock`);
|
|
24719
25164
|
try {
|
|
24720
|
-
const current = (0,
|
|
25165
|
+
const current = (0, import_node_fs8.readFileSync)(file.path, "utf8");
|
|
24721
25166
|
let next;
|
|
24722
25167
|
if (file.path.endsWith(".toml")) {
|
|
24723
25168
|
const stripped = stripCodexAlanMcpSection(current);
|
|
@@ -24748,7 +25193,7 @@ function isHttpUrl(value2) {
|
|
|
24748
25193
|
}
|
|
24749
25194
|
}
|
|
24750
25195
|
function readUsableAlanMcpUrl(path) {
|
|
24751
|
-
const content = (0,
|
|
25196
|
+
const content = (0, import_node_fs8.readFileSync)(path, "utf8");
|
|
24752
25197
|
if (path.endsWith(".toml")) {
|
|
24753
25198
|
const lines = content.split("\n");
|
|
24754
25199
|
const start = lines.findIndex((line) => line.trim() === "[mcp_servers.alan]");
|
|
@@ -25039,7 +25484,7 @@ ${result.stderr}`.trim();
|
|
|
25039
25484
|
}
|
|
25040
25485
|
|
|
25041
25486
|
// src/provider-model-discovery.ts
|
|
25042
|
-
var
|
|
25487
|
+
var import_node_fs9 = require("fs");
|
|
25043
25488
|
var MODEL_DISCOVERY_TIMEOUT_MS = 8e3;
|
|
25044
25489
|
var ANTIGRAVITY_MODEL_DISCOVERY_TIMEOUT_MS = 12e3;
|
|
25045
25490
|
var OPENCODE_ZEN_MODEL_IDS = OPENCODE_ZEN_MODELS.map((model) => model.id);
|
|
@@ -25253,7 +25698,7 @@ function filterClaudeDatedModelIds(ids) {
|
|
|
25253
25698
|
}
|
|
25254
25699
|
function resolveExecutableForModelScan(executable) {
|
|
25255
25700
|
try {
|
|
25256
|
-
return (0,
|
|
25701
|
+
return (0, import_node_fs9.realpathSync)(executable);
|
|
25257
25702
|
} catch {
|
|
25258
25703
|
return executable;
|
|
25259
25704
|
}
|
|
@@ -25261,7 +25706,7 @@ function resolveExecutableForModelScan(executable) {
|
|
|
25261
25706
|
function extractClaudeModelIdsFromExecutable(executable) {
|
|
25262
25707
|
try {
|
|
25263
25708
|
const resolved = resolveExecutableForModelScan(executable);
|
|
25264
|
-
const text = (0,
|
|
25709
|
+
const text = (0, import_node_fs9.readFileSync)(resolved).toString("latin1");
|
|
25265
25710
|
const matches = text.match(CLAUDE_MODEL_ID_PATTERN) ?? [];
|
|
25266
25711
|
const unique = [
|
|
25267
25712
|
...new Set(matches.map((id) => id.trim()).filter((id) => isValidClaudeModelId(id))),
|
|
@@ -25361,7 +25806,7 @@ async function discoverGenericModels(executable, env) {
|
|
|
25361
25806
|
["models"]
|
|
25362
25807
|
]);
|
|
25363
25808
|
}
|
|
25364
|
-
var CATALOG_ONLY_PROVIDERS = /* @__PURE__ */ new Set(["supatest_cli", "droid_cli"]);
|
|
25809
|
+
var CATALOG_ONLY_PROVIDERS = /* @__PURE__ */ new Set(["supatest_cli", "droid_cli", "copilot_cli"]);
|
|
25365
25810
|
function supportsProviderModelDiscovery(provider) {
|
|
25366
25811
|
return provider in CATALOG_MODEL_IDS_BY_PROVIDER;
|
|
25367
25812
|
}
|
|
@@ -25380,7 +25825,7 @@ async function discoverProviderModels(provider, executable, env) {
|
|
|
25380
25825
|
probed = await discoverCodexModels(executable, env);
|
|
25381
25826
|
} else if (provider === "claude_cli") {
|
|
25382
25827
|
probed = await discoverClaudeModels(executable, env);
|
|
25383
|
-
} else if (provider === "kimi_cli" || provider === "grok_cli"
|
|
25828
|
+
} else if (provider === "kimi_cli" || provider === "grok_cli") {
|
|
25384
25829
|
probed = await discoverGenericModels(executable, env);
|
|
25385
25830
|
}
|
|
25386
25831
|
if (probed.length > 0) return probed;
|
|
@@ -25388,8 +25833,8 @@ async function discoverProviderModels(provider, executable, env) {
|
|
|
25388
25833
|
}
|
|
25389
25834
|
|
|
25390
25835
|
// src/run-journal.ts
|
|
25391
|
-
var
|
|
25392
|
-
var
|
|
25836
|
+
var import_node_fs10 = require("fs");
|
|
25837
|
+
var import_node_path8 = require("path");
|
|
25393
25838
|
var JOURNAL_VERSION = 1;
|
|
25394
25839
|
var INTERRUPTED_ENTRY_TTL_MS = 24 * 60 * 6e4;
|
|
25395
25840
|
function isEntry(value2) {
|
|
@@ -25408,9 +25853,9 @@ function isEntry(value2) {
|
|
|
25408
25853
|
var RuntimeRunJournal = class {
|
|
25409
25854
|
constructor(path, nowMs = Date.now()) {
|
|
25410
25855
|
this.path = path;
|
|
25411
|
-
if (!(0,
|
|
25856
|
+
if (!(0, import_node_fs10.existsSync)(path)) return;
|
|
25412
25857
|
try {
|
|
25413
|
-
const parsed = JSON.parse((0,
|
|
25858
|
+
const parsed = JSON.parse((0, import_node_fs10.readFileSync)(path, "utf8"));
|
|
25414
25859
|
if (parsed.version !== JOURNAL_VERSION || !Array.isArray(parsed.entries)) {
|
|
25415
25860
|
throw new Error("unsupported run journal format");
|
|
25416
25861
|
}
|
|
@@ -25533,18 +25978,18 @@ var RuntimeRunJournal = class {
|
|
|
25533
25978
|
}
|
|
25534
25979
|
persist() {
|
|
25535
25980
|
const pendingPath = `${this.path}.pending`;
|
|
25536
|
-
(0,
|
|
25981
|
+
(0, import_node_fs10.mkdirSync)((0, import_node_path8.dirname)(this.path), { recursive: true });
|
|
25537
25982
|
try {
|
|
25538
|
-
(0,
|
|
25983
|
+
(0, import_node_fs10.writeFileSync)(
|
|
25539
25984
|
pendingPath,
|
|
25540
25985
|
`${JSON.stringify({ version: JOURNAL_VERSION, entries: [...this.entries.values()] })}
|
|
25541
25986
|
`,
|
|
25542
25987
|
{ mode: 384 }
|
|
25543
25988
|
);
|
|
25544
|
-
(0,
|
|
25545
|
-
(0,
|
|
25989
|
+
(0, import_node_fs10.chmodSync)(pendingPath, 384);
|
|
25990
|
+
(0, import_node_fs10.renameSync)(pendingPath, this.path);
|
|
25546
25991
|
} catch (error) {
|
|
25547
|
-
(0,
|
|
25992
|
+
(0, import_node_fs10.rmSync)(pendingPath, { force: true });
|
|
25548
25993
|
throw error;
|
|
25549
25994
|
}
|
|
25550
25995
|
}
|
|
@@ -25571,17 +26016,17 @@ var RunStartGate = class {
|
|
|
25571
26016
|
};
|
|
25572
26017
|
|
|
25573
26018
|
// src/version.ts
|
|
25574
|
-
var AGENT_VERSION = "0.1.
|
|
26019
|
+
var AGENT_VERSION = "0.1.49";
|
|
25575
26020
|
|
|
25576
26021
|
// src/workspace-relocation.ts
|
|
25577
|
-
var
|
|
25578
|
-
var
|
|
25579
|
-
var
|
|
26022
|
+
var import_node_child_process4 = require("child_process");
|
|
26023
|
+
var import_node_fs11 = require("fs");
|
|
26024
|
+
var import_node_path9 = require("path");
|
|
25580
26025
|
var MAX_RELOCATION_CANDIDATES = 200;
|
|
25581
26026
|
var DEFAULT_PROBE = {
|
|
25582
|
-
childDirectories: (parentPath, limit) => (0,
|
|
26027
|
+
childDirectories: (parentPath, limit) => (0, import_node_fs11.readdirSync)(parentPath, { withFileTypes: true }).filter((entry) => entry.isDirectory()).slice(0, limit).map((entry) => (0, import_node_path9.join)(parentPath, entry.name)),
|
|
25583
26028
|
gitRemoteUrl: (candidatePath) => {
|
|
25584
|
-
const result = (0,
|
|
26029
|
+
const result = (0, import_node_child_process4.spawnSync)("git", ["-C", candidatePath, "config", "--get", "remote.origin.url"], {
|
|
25585
26030
|
encoding: "utf8",
|
|
25586
26031
|
env: getDaemonCliEnvironment(),
|
|
25587
26032
|
timeout: 2e3
|
|
@@ -25610,7 +26055,7 @@ function workspaceMatchesExpectedRepositories(input) {
|
|
|
25610
26055
|
input.expectedRepoUrls.map(normalizeRepositoryIdentity).filter((identity2) => Boolean(identity2))
|
|
25611
26056
|
);
|
|
25612
26057
|
if (identities.size === 0) return false;
|
|
25613
|
-
const remote = (input.probe ?? DEFAULT_PROBE).gitRemoteUrl((0,
|
|
26058
|
+
const remote = (input.probe ?? DEFAULT_PROBE).gitRemoteUrl((0, import_node_path9.resolve)(input.workspacePath));
|
|
25614
26059
|
const identity = remote ? normalizeRepositoryIdentity(remote) : null;
|
|
25615
26060
|
return Boolean(identity && identities.has(identity));
|
|
25616
26061
|
}
|
|
@@ -25620,8 +26065,8 @@ function discoverRelocatedWorkspace(input) {
|
|
|
25620
26065
|
);
|
|
25621
26066
|
if (identities.size === 0) return null;
|
|
25622
26067
|
const searchRoots = [
|
|
25623
|
-
(0,
|
|
25624
|
-
...(input.approvedWorkspacePaths ?? []).map((path) => (0,
|
|
26068
|
+
(0, import_node_path9.dirname)((0, import_node_path9.resolve)(input.missingPath)),
|
|
26069
|
+
...(input.approvedWorkspacePaths ?? []).map((path) => (0, import_node_path9.dirname)((0, import_node_path9.resolve)(path)))
|
|
25625
26070
|
].filter((path, index, paths) => paths.indexOf(path) === index);
|
|
25626
26071
|
const candidates = [];
|
|
25627
26072
|
for (const root of searchRoots) {
|
|
@@ -25633,19 +26078,19 @@ function discoverRelocatedWorkspace(input) {
|
|
|
25633
26078
|
}
|
|
25634
26079
|
}
|
|
25635
26080
|
const matches = [];
|
|
25636
|
-
for (const candidate of new Set(candidates.map((path) => (0,
|
|
26081
|
+
for (const candidate of new Set(candidates.map((path) => (0, import_node_path9.resolve)(path)))) {
|
|
25637
26082
|
const remote = (input.probe ?? DEFAULT_PROBE).gitRemoteUrl(candidate);
|
|
25638
26083
|
const identity = remote ? normalizeRepositoryIdentity(remote) : null;
|
|
25639
|
-
if (identity && identities.has(identity)) matches.push((0,
|
|
26084
|
+
if (identity && identities.has(identity)) matches.push((0, import_node_path9.resolve)(candidate));
|
|
25640
26085
|
if (matches.length > 1) return null;
|
|
25641
26086
|
}
|
|
25642
26087
|
return matches[0] ?? null;
|
|
25643
26088
|
}
|
|
25644
26089
|
|
|
25645
26090
|
// src/workspace-run-lease.ts
|
|
25646
|
-
var
|
|
25647
|
-
var
|
|
25648
|
-
var
|
|
26091
|
+
var import_node_child_process5 = require("child_process");
|
|
26092
|
+
var import_node_fs12 = require("fs");
|
|
26093
|
+
var import_node_path10 = require("path");
|
|
25649
26094
|
var WORKSPACE_LEASE_CHECK_INTERVAL_MS = 1e3;
|
|
25650
26095
|
function parsePositiveMs(value2, fallback) {
|
|
25651
26096
|
const parsed = value2 ? Number(value2) : Number.NaN;
|
|
@@ -25656,7 +26101,7 @@ var WORKSPACE_LEASE_GIT_TIMEOUT_MS = parsePositiveMs(
|
|
|
25656
26101
|
2e3
|
|
25657
26102
|
);
|
|
25658
26103
|
function gitValue(cwd, args) {
|
|
25659
|
-
const result = (0,
|
|
26104
|
+
const result = (0, import_node_child_process5.spawnSync)("git", ["-C", cwd, ...args], {
|
|
25660
26105
|
encoding: "utf8",
|
|
25661
26106
|
env: getDaemonCliEnvironment(),
|
|
25662
26107
|
timeout: WORKSPACE_LEASE_GIT_TIMEOUT_MS
|
|
@@ -25665,17 +26110,17 @@ function gitValue(cwd, args) {
|
|
|
25665
26110
|
return result.stdout.trim() || null;
|
|
25666
26111
|
}
|
|
25667
26112
|
function filesystemIdentity(path) {
|
|
25668
|
-
const canonicalPath =
|
|
25669
|
-
const stat = (0,
|
|
26113
|
+
const canonicalPath = import_node_fs12.realpathSync.native(path);
|
|
26114
|
+
const stat = (0, import_node_fs12.statSync)(canonicalPath);
|
|
25670
26115
|
return `${canonicalPath}:${stat.dev}:${stat.ino}`;
|
|
25671
26116
|
}
|
|
25672
26117
|
function resolveGitPath(workspacePath, value2) {
|
|
25673
|
-
return (0,
|
|
26118
|
+
return (0, import_node_path10.isAbsolute)(value2) ? value2 : (0, import_node_path10.resolve)(workspacePath, value2);
|
|
25674
26119
|
}
|
|
25675
26120
|
var DEFAULT_PROBE2 = {
|
|
25676
26121
|
snapshot: (workspacePath) => {
|
|
25677
26122
|
try {
|
|
25678
|
-
const canonicalWorkspacePath =
|
|
26123
|
+
const canonicalWorkspacePath = import_node_fs12.realpathSync.native((0, import_node_path10.resolve)(workspacePath));
|
|
25679
26124
|
const repositoryRoot = gitValue(canonicalWorkspacePath, ["rev-parse", "--show-toplevel"]);
|
|
25680
26125
|
const gitDirectory = gitValue(canonicalWorkspacePath, ["rev-parse", "--git-dir"]);
|
|
25681
26126
|
const commonDirectory = gitValue(canonicalWorkspacePath, ["rev-parse", "--git-common-dir"]);
|
|
@@ -25684,7 +26129,7 @@ var DEFAULT_PROBE2 = {
|
|
|
25684
26129
|
const remote = gitValue(canonicalWorkspacePath, ["config", "--get", "remote.origin.url"]);
|
|
25685
26130
|
const remoteIdentity = remote ? normalizeRepositoryIdentity(remote) : null;
|
|
25686
26131
|
return {
|
|
25687
|
-
workspacePath: (0,
|
|
26132
|
+
workspacePath: (0, import_node_path10.resolve)(workspacePath),
|
|
25688
26133
|
workspaceIdentity: filesystemIdentity(canonicalWorkspacePath),
|
|
25689
26134
|
repositoryIdentity: `${filesystemIdentity(
|
|
25690
26135
|
resolveGitPath(canonicalWorkspacePath, commonDirectory)
|
|
@@ -25698,7 +26143,7 @@ var DEFAULT_PROBE2 = {
|
|
|
25698
26143
|
},
|
|
25699
26144
|
pathExists: (workspacePath) => {
|
|
25700
26145
|
try {
|
|
25701
|
-
return (0,
|
|
26146
|
+
return (0, import_node_fs12.existsSync)((0, import_node_path10.resolve)(workspacePath));
|
|
25702
26147
|
} catch {
|
|
25703
26148
|
return true;
|
|
25704
26149
|
}
|
|
@@ -25729,7 +26174,7 @@ var WorkspaceRunLease = class _WorkspaceRunLease {
|
|
|
25729
26174
|
static capture(targets, probe = DEFAULT_PROBE2) {
|
|
25730
26175
|
const captured = [];
|
|
25731
26176
|
for (const target of targets) {
|
|
25732
|
-
const normalizedTarget = { ...target, workspacePath: (0,
|
|
26177
|
+
const normalizedTarget = { ...target, workspacePath: (0, import_node_path10.resolve)(target.workspacePath) };
|
|
25733
26178
|
const identity = probe.snapshot(normalizedTarget.workspacePath);
|
|
25734
26179
|
if (!identity) return { lease: null, failure: unavailableFailure(normalizedTarget) };
|
|
25735
26180
|
if (normalizedTarget.expectedBranch && identity.branch !== normalizedTarget.expectedBranch) {
|
|
@@ -25882,15 +26327,15 @@ function assertValidGitRef(ref, label) {
|
|
|
25882
26327
|
if (!ref || ref.startsWith("-") || ref.includes("\0")) {
|
|
25883
26328
|
throw new Error(`${label} is not a safe git ref`);
|
|
25884
26329
|
}
|
|
25885
|
-
const result = (0,
|
|
26330
|
+
const result = (0, import_node_child_process6.spawnSync)("git", ["check-ref-format", "--branch", ref], {
|
|
25886
26331
|
env: getDaemonCliEnvironment(),
|
|
25887
26332
|
encoding: "utf8"
|
|
25888
26333
|
});
|
|
25889
26334
|
if (result.status !== 0) throw new Error(`${label} is not a valid git ref`);
|
|
25890
26335
|
}
|
|
25891
26336
|
function isPathContained(childPath, parentPath) {
|
|
25892
|
-
const rel = (0,
|
|
25893
|
-
return rel === "" || !(0,
|
|
26337
|
+
const rel = (0, import_node_path11.relative)((0, import_node_path11.resolve)(parentPath), (0, import_node_path11.resolve)(childPath));
|
|
26338
|
+
return rel === "" || !(0, import_node_path11.isAbsolute)(rel) && rel !== ".." && !rel.startsWith(`..${import_node_path11.sep}`);
|
|
25894
26339
|
}
|
|
25895
26340
|
function assertPathContained(childPath, parentPath, label) {
|
|
25896
26341
|
if (!isPathContained(childPath, parentPath)) {
|
|
@@ -25898,7 +26343,7 @@ function assertPathContained(childPath, parentPath, label) {
|
|
|
25898
26343
|
}
|
|
25899
26344
|
}
|
|
25900
26345
|
function git(cwd, args) {
|
|
25901
|
-
const result = (0,
|
|
26346
|
+
const result = (0, import_node_child_process6.spawnSync)("git", args, {
|
|
25902
26347
|
cwd,
|
|
25903
26348
|
env: getDaemonCliEnvironment(),
|
|
25904
26349
|
encoding: "utf8",
|
|
@@ -25917,14 +26362,14 @@ function gitSafe(cwd, args) {
|
|
|
25917
26362
|
}
|
|
25918
26363
|
}
|
|
25919
26364
|
function worktreeDir(projectPath) {
|
|
25920
|
-
const resolved = (0,
|
|
25921
|
-
return (0,
|
|
26365
|
+
const resolved = (0, import_node_path11.resolve)(projectPath);
|
|
26366
|
+
return (0, import_node_path11.join)((0, import_node_path11.dirname)(resolved), `${(0, import_node_path11.basename)(resolved)}-alan-worktrees`);
|
|
25922
26367
|
}
|
|
25923
26368
|
function pathSegment(value2) {
|
|
25924
26369
|
return value2.toLowerCase().replace(/^alan\//, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 64) || "task";
|
|
25925
26370
|
}
|
|
25926
26371
|
function repoName(repoUrl, localPath) {
|
|
25927
|
-
return repoUrl.replace(/\.git$/, "").split("/").pop() || (0,
|
|
26372
|
+
return repoUrl.replace(/\.git$/, "").split("/").pop() || (0, import_node_path11.basename)(localPath) || "repo";
|
|
25928
26373
|
}
|
|
25929
26374
|
function findWorktreeByBranch(repoPath, branchName) {
|
|
25930
26375
|
const output = gitSafe(repoPath, ["worktree", "list", "--porcelain"]);
|
|
@@ -25940,21 +26385,21 @@ function findWorktreeByBranch(repoPath, branchName) {
|
|
|
25940
26385
|
function ensureGitWorktree(input) {
|
|
25941
26386
|
assertValidGitRef(input.branchName, "branchName");
|
|
25942
26387
|
assertValidGitRef(input.baseBranch, "baseBranch");
|
|
25943
|
-
const repoPath = (0,
|
|
26388
|
+
const repoPath = (0, import_node_path11.resolve)(input.repoPath);
|
|
25944
26389
|
const root = input.allowedRoot ?? worktreeDir(repoPath);
|
|
25945
26390
|
const existingPath = findWorktreeByBranch(input.repoPath, input.branchName);
|
|
25946
26391
|
if (existingPath) {
|
|
25947
|
-
if ((0,
|
|
26392
|
+
if ((0, import_node_path11.resolve)(existingPath) === repoPath) {
|
|
25948
26393
|
throw new Error(`${input.branchName} is checked out in the shared checkout`);
|
|
25949
26394
|
}
|
|
25950
26395
|
return existingPath;
|
|
25951
26396
|
}
|
|
25952
26397
|
assertPathContained(input.worktreePath, root, "worktreePath");
|
|
25953
|
-
(0,
|
|
26398
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(input.worktreePath), { recursive: true });
|
|
25954
26399
|
if (!gitSafe(input.repoPath, ["branch", "--list", input.branchName])) {
|
|
25955
26400
|
git(input.repoPath, ["branch", input.branchName, input.baseBranch]);
|
|
25956
26401
|
}
|
|
25957
|
-
if ((0,
|
|
26402
|
+
if ((0, import_node_fs13.existsSync)(input.worktreePath)) {
|
|
25958
26403
|
if (gitSafe(input.worktreePath, ["branch", "--show-current"]) === input.branchName) {
|
|
25959
26404
|
return input.worktreePath;
|
|
25960
26405
|
}
|
|
@@ -25964,15 +26409,15 @@ function ensureGitWorktree(input) {
|
|
|
25964
26409
|
return input.worktreePath;
|
|
25965
26410
|
}
|
|
25966
26411
|
function resolveProjectWorktreePaths(projectPath, gitRoot, gitWorktreePath) {
|
|
25967
|
-
const resolvedProjectPath = (0,
|
|
25968
|
-
const resolvedGitRoot = (0,
|
|
25969
|
-
const projectRelativePath = (0,
|
|
25970
|
-
if (projectRelativePath === ".." || projectRelativePath.startsWith(`..${
|
|
26412
|
+
const resolvedProjectPath = (0, import_node_path11.resolve)(projectPath);
|
|
26413
|
+
const resolvedGitRoot = (0, import_node_path11.resolve)(gitRoot);
|
|
26414
|
+
const projectRelativePath = (0, import_node_path11.relative)(resolvedGitRoot, resolvedProjectPath);
|
|
26415
|
+
if (projectRelativePath === ".." || projectRelativePath.startsWith(`..${import_node_path11.sep}`) || (0, import_node_path11.isAbsolute)(projectRelativePath)) {
|
|
25971
26416
|
throw new Error("The selected Project folder is outside its Git repository");
|
|
25972
26417
|
}
|
|
25973
26418
|
return {
|
|
25974
26419
|
repoPath: resolvedGitRoot,
|
|
25975
|
-
projectPath: projectRelativePath ? (0,
|
|
26420
|
+
projectPath: projectRelativePath ? (0, import_node_path11.join)((0, import_node_path11.resolve)(gitWorktreePath), projectRelativePath) : (0, import_node_path11.resolve)(gitWorktreePath)
|
|
25976
26421
|
};
|
|
25977
26422
|
}
|
|
25978
26423
|
function ensureWorktree(params) {
|
|
@@ -25984,7 +26429,7 @@ function ensureWorktree(params) {
|
|
|
25984
26429
|
repoLocalPaths: Array.isArray(params.repoLocalPaths) ? params.repoLocalPaths : []
|
|
25985
26430
|
};
|
|
25986
26431
|
if (input.repoLocalPaths?.length) {
|
|
25987
|
-
const taskRoot2 = (0,
|
|
26432
|
+
const taskRoot2 = (0, import_node_path11.join)(
|
|
25988
26433
|
worktreeDir(input.projectPath),
|
|
25989
26434
|
`${pathSegment(input.branchName)}-${input.taskId.slice(0, 8)}`
|
|
25990
26435
|
);
|
|
@@ -25993,7 +26438,7 @@ function ensureWorktree(params) {
|
|
|
25993
26438
|
const baseBranch2 = repo.branch || input.baseBranch || "main";
|
|
25994
26439
|
const worktreePath2 = ensureGitWorktree({
|
|
25995
26440
|
repoPath: repo.localPath,
|
|
25996
|
-
worktreePath: (0,
|
|
26441
|
+
worktreePath: (0, import_node_path11.join)(taskRoot2, pathSegment(repoName(repo.repoUrl, repo.localPath))),
|
|
25997
26442
|
branchName: input.branchName,
|
|
25998
26443
|
baseBranch: baseBranch2,
|
|
25999
26444
|
allowedRoot: worktreeDir(input.projectPath)
|
|
@@ -26008,13 +26453,13 @@ function ensureWorktree(params) {
|
|
|
26008
26453
|
})
|
|
26009
26454
|
};
|
|
26010
26455
|
}
|
|
26011
|
-
const gitRoot = gitSafe((0,
|
|
26456
|
+
const gitRoot = gitSafe((0, import_node_path11.resolve)(input.projectPath), ["rev-parse", "--show-toplevel"]);
|
|
26012
26457
|
if (!gitRoot) {
|
|
26013
26458
|
throw new Error("The selected Project folder is not inside a Git repository");
|
|
26014
26459
|
}
|
|
26015
|
-
const repoPath = (0,
|
|
26460
|
+
const repoPath = (0, import_node_path11.resolve)(gitRoot);
|
|
26016
26461
|
const baseBranch = input.baseBranch || gitSafe(repoPath, ["branch", "--show-current"]) || "HEAD";
|
|
26017
|
-
const taskRoot = (0,
|
|
26462
|
+
const taskRoot = (0, import_node_path11.join)(
|
|
26018
26463
|
worktreeDir(repoPath),
|
|
26019
26464
|
`${pathSegment(input.branchName)}-${input.taskId.slice(0, 8)}`
|
|
26020
26465
|
);
|
|
@@ -26043,7 +26488,7 @@ function ensureWorktree(params) {
|
|
|
26043
26488
|
function ensureSharedCheckoutBranch(input) {
|
|
26044
26489
|
assertValidGitRef(input.branchName, "branchName");
|
|
26045
26490
|
assertValidGitRef(input.baseBranch, "baseBranch");
|
|
26046
|
-
const repoPath = (0,
|
|
26491
|
+
const repoPath = (0, import_node_path11.resolve)(input.repoPath);
|
|
26047
26492
|
if (gitSafe(repoPath, ["rev-parse", "--is-inside-work-tree"]) !== "true") {
|
|
26048
26493
|
return { checkedOut: false, reason: `${repoPath} is not a git work tree` };
|
|
26049
26494
|
}
|
|
@@ -26088,7 +26533,7 @@ function resolveSharedCheckoutTargets(input) {
|
|
|
26088
26533
|
}
|
|
26089
26534
|
function resolveRuntimeCwd(payload) {
|
|
26090
26535
|
const multiRepoWorktree = payload.worktreeInfo?.allWorktrees?.[0]?.worktreePath;
|
|
26091
|
-
if (multiRepoWorktree) return (0,
|
|
26536
|
+
if (multiRepoWorktree) return (0, import_node_path11.dirname)(multiRepoWorktree);
|
|
26092
26537
|
if (isAlanDefaultWorkspace(payload.projectPath)) return resolveAlanDefaultWorkspacePath();
|
|
26093
26538
|
return payload.worktreeInfo?.worktreePath ?? payload.projectPath ?? process.cwd();
|
|
26094
26539
|
}
|
|
@@ -26310,12 +26755,12 @@ function getConfigPath() {
|
|
|
26310
26755
|
return process.env.ALAN_AGENT_CONFIG_PATH ?? boundAgentConfigPath ?? resolveAgentConfigPath({ profile: "production" });
|
|
26311
26756
|
}
|
|
26312
26757
|
function getEndpointDefaultsPath() {
|
|
26313
|
-
return process.env.ALAN_AGENT_ENDPOINTS_PATH ?? (0,
|
|
26758
|
+
return process.env.ALAN_AGENT_ENDPOINTS_PATH ?? (0, import_node_path11.join)((0, import_node_path11.dirname)(getConfigPath()), "endpoints.json");
|
|
26314
26759
|
}
|
|
26315
26760
|
function readConfig() {
|
|
26316
26761
|
const configPath = getConfigPath();
|
|
26317
|
-
if (!(0,
|
|
26318
|
-
const parsed = JSON.parse((0,
|
|
26762
|
+
if (!(0, import_node_fs13.existsSync)(configPath)) return {};
|
|
26763
|
+
const parsed = JSON.parse((0, import_node_fs13.readFileSync)(configPath, "utf8"));
|
|
26319
26764
|
const sanitized = sanitizeAgentConfig(parsed);
|
|
26320
26765
|
if (Object.keys(parsed).some((key) => !Object.hasOwn(sanitized, key))) {
|
|
26321
26766
|
writeConfig(sanitized);
|
|
@@ -26331,27 +26776,27 @@ function readConfigForRegistration() {
|
|
|
26331
26776
|
}
|
|
26332
26777
|
function readEndpointDefaults() {
|
|
26333
26778
|
const endpointsPath = getEndpointDefaultsPath();
|
|
26334
|
-
if (!(0,
|
|
26779
|
+
if (!(0, import_node_fs13.existsSync)(endpointsPath)) return {};
|
|
26335
26780
|
try {
|
|
26336
|
-
return JSON.parse((0,
|
|
26781
|
+
return JSON.parse((0, import_node_fs13.readFileSync)(endpointsPath, "utf8"));
|
|
26337
26782
|
} catch {
|
|
26338
26783
|
return {};
|
|
26339
26784
|
}
|
|
26340
26785
|
}
|
|
26341
26786
|
function writeConfig(config) {
|
|
26342
26787
|
const configPath = getConfigPath();
|
|
26343
|
-
(0,
|
|
26788
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(configPath), { recursive: true, mode: 448 });
|
|
26344
26789
|
const pendingPath = `${configPath}.pending-${process.pid}-${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
26345
26790
|
try {
|
|
26346
|
-
(0,
|
|
26791
|
+
(0, import_node_fs13.writeFileSync)(
|
|
26347
26792
|
pendingPath,
|
|
26348
26793
|
JSON.stringify(sanitizeAgentConfig(config), null, 2),
|
|
26349
26794
|
{ mode: 384 }
|
|
26350
26795
|
);
|
|
26351
|
-
(0,
|
|
26352
|
-
(0,
|
|
26796
|
+
(0, import_node_fs13.chmodSync)(pendingPath, 384);
|
|
26797
|
+
(0, import_node_fs13.renameSync)(pendingPath, configPath);
|
|
26353
26798
|
} finally {
|
|
26354
|
-
(0,
|
|
26799
|
+
(0, import_node_fs13.rmSync)(pendingPath, { force: true });
|
|
26355
26800
|
}
|
|
26356
26801
|
}
|
|
26357
26802
|
function maintenanceLeasePath(configPath) {
|
|
@@ -26359,9 +26804,9 @@ function maintenanceLeasePath(configPath) {
|
|
|
26359
26804
|
}
|
|
26360
26805
|
function readLocalDaemonMaintenanceLease(configPath, nowMs = Date.now()) {
|
|
26361
26806
|
const path = maintenanceLeasePath(configPath);
|
|
26362
|
-
if (!(0,
|
|
26807
|
+
if (!(0, import_node_fs13.existsSync)(path)) return null;
|
|
26363
26808
|
try {
|
|
26364
|
-
const lease = JSON.parse((0,
|
|
26809
|
+
const lease = JSON.parse((0, import_node_fs13.readFileSync)(path, "utf8"));
|
|
26365
26810
|
if (lease.version !== 1 || typeof lease.id !== "string" || lease.reason !== "credential_cleanup" && lease.reason !== "daemon_startup" && lease.reason !== "watchdog" || !(lease.reason === "credential_cleanup" && lease.expiresAtMs === null || typeof lease.expiresAtMs === "number" && Number.isFinite(lease.expiresAtMs))) {
|
|
26366
26811
|
throw new Error("invalid maintenance lease");
|
|
26367
26812
|
}
|
|
@@ -26378,8 +26823,8 @@ function readLocalDaemonMaintenanceLease(configPath, nowMs = Date.now()) {
|
|
|
26378
26823
|
expiresAtMs: nowMs + 5e3
|
|
26379
26824
|
};
|
|
26380
26825
|
try {
|
|
26381
|
-
(0,
|
|
26382
|
-
(0,
|
|
26826
|
+
(0, import_node_fs13.writeFileSync)(path, JSON.stringify(fallback), { mode: 384 });
|
|
26827
|
+
(0, import_node_fs13.chmodSync)(path, 384);
|
|
26383
26828
|
} catch {
|
|
26384
26829
|
}
|
|
26385
26830
|
return fallback;
|
|
@@ -26395,10 +26840,10 @@ function acquireLocalDaemonMaintenanceLease(configPath, reason, ttlMs = 5e3) {
|
|
|
26395
26840
|
expiresAtMs: reason === "credential_cleanup" ? null : Date.now() + Math.max(1e3, Math.min(ttlMs, 6e4))
|
|
26396
26841
|
};
|
|
26397
26842
|
const path = maintenanceLeasePath(configPath);
|
|
26398
|
-
(0,
|
|
26843
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(path), { recursive: true, mode: 448 });
|
|
26399
26844
|
try {
|
|
26400
|
-
(0,
|
|
26401
|
-
(0,
|
|
26845
|
+
(0, import_node_fs13.writeFileSync)(path, JSON.stringify(lease), { mode: 384, flag: "wx" });
|
|
26846
|
+
(0, import_node_fs13.chmodSync)(path, 384);
|
|
26402
26847
|
return { acquired: true, lease };
|
|
26403
26848
|
} catch (error) {
|
|
26404
26849
|
const raced = readLocalDaemonMaintenanceLease(configPath);
|
|
@@ -26414,9 +26859,9 @@ function daemonOwnerLeasePath(configPath) {
|
|
|
26414
26859
|
}
|
|
26415
26860
|
function readLocalDaemonOwnerLease(configPath) {
|
|
26416
26861
|
const path = daemonOwnerLeasePath(configPath);
|
|
26417
|
-
if (!(0,
|
|
26862
|
+
if (!(0, import_node_fs13.existsSync)(path)) return null;
|
|
26418
26863
|
try {
|
|
26419
|
-
const lease = JSON.parse((0,
|
|
26864
|
+
const lease = JSON.parse((0, import_node_fs13.readFileSync)(path, "utf8"));
|
|
26420
26865
|
if (lease.version !== 1 || typeof lease.id !== "string" || typeof lease.daemonSessionId !== "string" || !Number.isSafeInteger(lease.pid) || lease.pid <= 0 || typeof lease.startedAtMs !== "number" || !Number.isFinite(lease.startedAtMs) || typeof lease.runtimeId !== "string" || typeof lease.localServiceId !== "string" || !Number.isSafeInteger(lease.localApiPort) || lease.localApiPort < 0 || lease.localApiPort > 65535 || typeof lease.localApiToken !== "string" || lease.localApiToken.length === 0) {
|
|
26421
26866
|
throw new Error("invalid daemon owner lease");
|
|
26422
26867
|
}
|
|
@@ -26468,10 +26913,10 @@ async function acquireLocalDaemonOwnerLease(input) {
|
|
|
26468
26913
|
localApiToken: input.localApiToken
|
|
26469
26914
|
};
|
|
26470
26915
|
const path = daemonOwnerLeasePath(input.configPath);
|
|
26471
|
-
(0,
|
|
26916
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(path), { recursive: true, mode: 448 });
|
|
26472
26917
|
try {
|
|
26473
|
-
(0,
|
|
26474
|
-
(0,
|
|
26918
|
+
(0, import_node_fs13.writeFileSync)(path, JSON.stringify(lease), { mode: 384, flag: "wx" });
|
|
26919
|
+
(0, import_node_fs13.chmodSync)(path, 384);
|
|
26475
26920
|
return { acquired: true, lease };
|
|
26476
26921
|
} catch (error) {
|
|
26477
26922
|
const raced = readLocalDaemonOwnerLease(input.configPath);
|
|
@@ -26486,12 +26931,12 @@ function updateLocalDaemonOwnerEndpoint(configPath, lease, localApiPort) {
|
|
|
26486
26931
|
const path = daemonOwnerLeasePath(configPath);
|
|
26487
26932
|
const pendingPath = `${path}.pending-${lease.id}`;
|
|
26488
26933
|
try {
|
|
26489
|
-
(0,
|
|
26490
|
-
(0,
|
|
26491
|
-
(0,
|
|
26934
|
+
(0, import_node_fs13.writeFileSync)(pendingPath, JSON.stringify(updated), { mode: 384 });
|
|
26935
|
+
(0, import_node_fs13.chmodSync)(pendingPath, 384);
|
|
26936
|
+
(0, import_node_fs13.renameSync)(pendingPath, path);
|
|
26492
26937
|
return updated;
|
|
26493
26938
|
} finally {
|
|
26494
|
-
(0,
|
|
26939
|
+
(0, import_node_fs13.rmSync)(pendingPath, { force: true });
|
|
26495
26940
|
}
|
|
26496
26941
|
}
|
|
26497
26942
|
function releaseLocalDaemonOwnerLease(configPath, leaseId) {
|
|
@@ -26500,13 +26945,13 @@ function releaseLocalDaemonOwnerLease(configPath, leaseId) {
|
|
|
26500
26945
|
function releaseOwnedJsonFile(path, ownerId, ownerField = "id") {
|
|
26501
26946
|
const releasePath = `${path}.release-${process.pid}-${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
26502
26947
|
try {
|
|
26503
|
-
(0,
|
|
26948
|
+
(0, import_node_fs13.renameSync)(path, releasePath);
|
|
26504
26949
|
} catch (error) {
|
|
26505
26950
|
if (error.code === "ENOENT") return;
|
|
26506
26951
|
throw error;
|
|
26507
26952
|
}
|
|
26508
26953
|
try {
|
|
26509
|
-
const content = (0,
|
|
26954
|
+
const content = (0, import_node_fs13.readFileSync)(releasePath, "utf8");
|
|
26510
26955
|
let capturedOwnerId = null;
|
|
26511
26956
|
try {
|
|
26512
26957
|
const captured = JSON.parse(content);
|
|
@@ -26515,13 +26960,13 @@ function releaseOwnedJsonFile(path, ownerId, ownerField = "id") {
|
|
|
26515
26960
|
}
|
|
26516
26961
|
if (capturedOwnerId === ownerId) return;
|
|
26517
26962
|
try {
|
|
26518
|
-
(0,
|
|
26519
|
-
(0,
|
|
26963
|
+
(0, import_node_fs13.writeFileSync)(path, content, { mode: 384, flag: "wx" });
|
|
26964
|
+
(0, import_node_fs13.chmodSync)(path, 384);
|
|
26520
26965
|
} catch (error) {
|
|
26521
26966
|
if (error.code !== "EEXIST") throw error;
|
|
26522
26967
|
}
|
|
26523
26968
|
} finally {
|
|
26524
|
-
(0,
|
|
26969
|
+
(0, import_node_fs13.rmSync)(releasePath, { force: true });
|
|
26525
26970
|
}
|
|
26526
26971
|
}
|
|
26527
26972
|
function inspectLocalDaemonRunJournal(configPath) {
|
|
@@ -26531,8 +26976,8 @@ function inspectLocalDaemonRunJournal(configPath) {
|
|
|
26531
26976
|
try {
|
|
26532
26977
|
let activeRunCount = 0;
|
|
26533
26978
|
for (const artifact of [path, pendingPath]) {
|
|
26534
|
-
if (!(0,
|
|
26535
|
-
const parsed = JSON.parse((0,
|
|
26979
|
+
if (!(0, import_node_fs13.existsSync)(artifact)) continue;
|
|
26980
|
+
const parsed = JSON.parse((0, import_node_fs13.readFileSync)(artifact, "utf8"));
|
|
26536
26981
|
if (parsed.version !== 1 || !Array.isArray(parsed.entries))
|
|
26537
26982
|
throw new Error("invalid journal");
|
|
26538
26983
|
if (artifact === path) {
|
|
@@ -26551,7 +26996,7 @@ function inspectLocalDaemonRunJournal(configPath) {
|
|
|
26551
26996
|
}).length;
|
|
26552
26997
|
continue;
|
|
26553
26998
|
}
|
|
26554
|
-
const legacyStartedAtMs = (0,
|
|
26999
|
+
const legacyStartedAtMs = (0, import_node_fs13.statSync)(pendingPath).mtimeMs;
|
|
26555
27000
|
activeRunCount += parsed.entries.filter((entry) => {
|
|
26556
27001
|
if (!entry || typeof entry !== "object") throw new Error("invalid pending run entry");
|
|
26557
27002
|
const startedAtMs = entry.startedAtMs;
|
|
@@ -26578,9 +27023,9 @@ function setupTokenHash(setupToken) {
|
|
|
26578
27023
|
function getOrCreateSetupAttemptId(setupToken) {
|
|
26579
27024
|
const intentPath = pendingSetupIntentPath();
|
|
26580
27025
|
const tokenHash = setupTokenHash(setupToken);
|
|
26581
|
-
if ((0,
|
|
27026
|
+
if ((0, import_node_fs13.existsSync)(intentPath)) {
|
|
26582
27027
|
try {
|
|
26583
|
-
const stored = JSON.parse((0,
|
|
27028
|
+
const stored = JSON.parse((0, import_node_fs13.readFileSync)(intentPath, "utf8"));
|
|
26584
27029
|
if (stored.setupTokenHash === tokenHash && typeof stored.registrationAttemptId === "string" && stored.registrationAttemptId.length > 0) {
|
|
26585
27030
|
return stored.registrationAttemptId;
|
|
26586
27031
|
}
|
|
@@ -26588,23 +27033,23 @@ function getOrCreateSetupAttemptId(setupToken) {
|
|
|
26588
27033
|
}
|
|
26589
27034
|
}
|
|
26590
27035
|
const registrationAttemptId = (0, import_node_crypto3.randomUUID)();
|
|
26591
|
-
(0,
|
|
27036
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(intentPath), { recursive: true, mode: 448 });
|
|
26592
27037
|
const writePath = `${intentPath}.pending-${process.pid}-${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
26593
27038
|
try {
|
|
26594
|
-
(0,
|
|
27039
|
+
(0, import_node_fs13.writeFileSync)(
|
|
26595
27040
|
writePath,
|
|
26596
27041
|
JSON.stringify({ setupTokenHash: tokenHash, registrationAttemptId }, null, 2),
|
|
26597
27042
|
{ mode: 384 }
|
|
26598
27043
|
);
|
|
26599
|
-
(0,
|
|
26600
|
-
(0,
|
|
27044
|
+
(0, import_node_fs13.chmodSync)(writePath, 384);
|
|
27045
|
+
(0, import_node_fs13.renameSync)(writePath, intentPath);
|
|
26601
27046
|
} finally {
|
|
26602
|
-
(0,
|
|
27047
|
+
(0, import_node_fs13.rmSync)(writePath, { force: true });
|
|
26603
27048
|
}
|
|
26604
27049
|
return registrationAttemptId;
|
|
26605
27050
|
}
|
|
26606
27051
|
function clearPendingSetupIntent() {
|
|
26607
|
-
(0,
|
|
27052
|
+
(0, import_node_fs13.rmSync)(pendingSetupIntentPath(), { force: true });
|
|
26608
27053
|
}
|
|
26609
27054
|
function pendingDeviceAuthorizationPath() {
|
|
26610
27055
|
return `${getConfigPath()}.device-auth-pending`;
|
|
@@ -26625,8 +27070,8 @@ function parseDeviceAuthorizationOperationContent(content) {
|
|
|
26625
27070
|
}
|
|
26626
27071
|
function restoreCapturedFileUnlessReplaced(path, content) {
|
|
26627
27072
|
try {
|
|
26628
|
-
(0,
|
|
26629
|
-
(0,
|
|
27073
|
+
(0, import_node_fs13.writeFileSync)(path, content, { mode: 384, flag: "wx" });
|
|
27074
|
+
(0, import_node_fs13.chmodSync)(path, 384);
|
|
26630
27075
|
} catch (error) {
|
|
26631
27076
|
if (error.code !== "EEXIST") throw error;
|
|
26632
27077
|
}
|
|
@@ -26634,26 +27079,26 @@ function restoreCapturedFileUnlessReplaced(path, content) {
|
|
|
26634
27079
|
function quarantineCorruptDeviceAuthorizationOperation(path) {
|
|
26635
27080
|
const quarantinePath = `${path}.corrupt-${process.pid}-${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
26636
27081
|
try {
|
|
26637
|
-
(0,
|
|
27082
|
+
(0, import_node_fs13.renameSync)(path, quarantinePath);
|
|
26638
27083
|
} catch (error) {
|
|
26639
27084
|
if (error.code === "ENOENT") return null;
|
|
26640
27085
|
throw error;
|
|
26641
27086
|
}
|
|
26642
27087
|
try {
|
|
26643
|
-
const capturedContent = (0,
|
|
27088
|
+
const capturedContent = (0, import_node_fs13.readFileSync)(quarantinePath, "utf8");
|
|
26644
27089
|
if (parseDeviceAuthorizationOperationContent(capturedContent)) {
|
|
26645
27090
|
restoreCapturedFileUnlessReplaced(path, capturedContent);
|
|
26646
27091
|
}
|
|
26647
27092
|
} finally {
|
|
26648
|
-
(0,
|
|
27093
|
+
(0, import_node_fs13.rmSync)(quarantinePath, { force: true });
|
|
26649
27094
|
}
|
|
26650
|
-
if (!(0,
|
|
26651
|
-
return parseDeviceAuthorizationOperationContent((0,
|
|
27095
|
+
if (!(0, import_node_fs13.existsSync)(path)) return null;
|
|
27096
|
+
return parseDeviceAuthorizationOperationContent((0, import_node_fs13.readFileSync)(path, "utf8"));
|
|
26652
27097
|
}
|
|
26653
27098
|
function readDeviceAuthorizationOperation() {
|
|
26654
27099
|
const path = deviceAuthorizationOperationPath();
|
|
26655
|
-
if (!(0,
|
|
26656
|
-
const parsed = parseDeviceAuthorizationOperationContent((0,
|
|
27100
|
+
if (!(0, import_node_fs13.existsSync)(path)) return null;
|
|
27101
|
+
const parsed = parseDeviceAuthorizationOperationContent((0, import_node_fs13.readFileSync)(path, "utf8"));
|
|
26657
27102
|
const lease = parsed ?? quarantineCorruptDeviceAuthorizationOperation(path);
|
|
26658
27103
|
if (!lease) return null;
|
|
26659
27104
|
if (lease.expiresAtMs <= Date.now()) {
|
|
@@ -26671,10 +27116,10 @@ function acquireDeviceAuthorizationOperation() {
|
|
|
26671
27116
|
expiresAtMs: Date.now() + 6e4
|
|
26672
27117
|
};
|
|
26673
27118
|
const path = deviceAuthorizationOperationPath();
|
|
26674
|
-
(0,
|
|
27119
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(path), { recursive: true, mode: 448 });
|
|
26675
27120
|
try {
|
|
26676
|
-
(0,
|
|
26677
|
-
(0,
|
|
27121
|
+
(0, import_node_fs13.writeFileSync)(path, JSON.stringify(lease), { mode: 384, flag: "wx" });
|
|
27122
|
+
(0, import_node_fs13.chmodSync)(path, 384);
|
|
26678
27123
|
return lease;
|
|
26679
27124
|
} catch (error) {
|
|
26680
27125
|
if (error.code === "EEXIST") return null;
|
|
@@ -26689,15 +27134,15 @@ function extendDeviceAuthorizationOperation(operationId, expiresAtMs) {
|
|
|
26689
27134
|
const path = deviceAuthorizationOperationPath();
|
|
26690
27135
|
const pendingPath = `${path}.pending-${process.pid}-${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
26691
27136
|
try {
|
|
26692
|
-
(0,
|
|
27137
|
+
(0, import_node_fs13.writeFileSync)(
|
|
26693
27138
|
pendingPath,
|
|
26694
27139
|
JSON.stringify({ ...current, expiresAtMs: Math.max(expiresAtMs, Date.now() + 6e4) }),
|
|
26695
27140
|
{ mode: 384 }
|
|
26696
27141
|
);
|
|
26697
|
-
(0,
|
|
26698
|
-
(0,
|
|
27142
|
+
(0, import_node_fs13.chmodSync)(pendingPath, 384);
|
|
27143
|
+
(0, import_node_fs13.renameSync)(pendingPath, path);
|
|
26699
27144
|
} finally {
|
|
26700
|
-
(0,
|
|
27145
|
+
(0, import_node_fs13.rmSync)(pendingPath, { force: true });
|
|
26701
27146
|
}
|
|
26702
27147
|
}
|
|
26703
27148
|
function assertDeviceAuthorizationOperationOwner(operationId) {
|
|
@@ -26708,12 +27153,12 @@ function assertDeviceAuthorizationOperationOwner(operationId) {
|
|
|
26708
27153
|
function clearPendingDeviceAuthorization(operationId) {
|
|
26709
27154
|
const path = pendingDeviceAuthorizationPath();
|
|
26710
27155
|
if (!operationId) {
|
|
26711
|
-
(0,
|
|
27156
|
+
(0, import_node_fs13.rmSync)(path, { force: true });
|
|
26712
27157
|
return;
|
|
26713
27158
|
}
|
|
26714
|
-
if (!(0,
|
|
27159
|
+
if (!(0, import_node_fs13.existsSync)(path)) return;
|
|
26715
27160
|
try {
|
|
26716
|
-
const pending = JSON.parse((0,
|
|
27161
|
+
const pending = JSON.parse((0, import_node_fs13.readFileSync)(path, "utf8"));
|
|
26717
27162
|
if (pending.operationId !== operationId) return;
|
|
26718
27163
|
} catch {
|
|
26719
27164
|
return;
|
|
@@ -26722,9 +27167,9 @@ function clearPendingDeviceAuthorization(operationId) {
|
|
|
26722
27167
|
}
|
|
26723
27168
|
function readPendingDeviceAuthorization(apiUrl) {
|
|
26724
27169
|
const path = pendingDeviceAuthorizationPath();
|
|
26725
|
-
if (!(0,
|
|
27170
|
+
if (!(0, import_node_fs13.existsSync)(path)) return null;
|
|
26726
27171
|
try {
|
|
26727
|
-
const pending = JSON.parse((0,
|
|
27172
|
+
const pending = JSON.parse((0, import_node_fs13.readFileSync)(path, "utf8"));
|
|
26728
27173
|
const expiresAtMs = Date.parse(pending.expiresAt ?? "");
|
|
26729
27174
|
if (pending.apiUrl !== apiUrl || typeof pending.deviceCode !== "string" || typeof pending.userCode !== "string" || typeof pending.verificationUri !== "string" || typeof pending.installationId !== "string" || pending.operationId !== void 0 && typeof pending.operationId !== "string" || !Number.isFinite(pending.intervalSeconds) || !Number.isFinite(expiresAtMs) || expiresAtMs <= Date.now()) {
|
|
26730
27175
|
return null;
|
|
@@ -26736,20 +27181,20 @@ function readPendingDeviceAuthorization(apiUrl) {
|
|
|
26736
27181
|
}
|
|
26737
27182
|
function writePendingDeviceAuthorization(pending) {
|
|
26738
27183
|
const path = pendingDeviceAuthorizationPath();
|
|
26739
|
-
(0,
|
|
27184
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(path), { recursive: true, mode: 448 });
|
|
26740
27185
|
const writePath = `${path}.pending-${process.pid}-${(0, import_node_crypto3.randomBytes)(6).toString("hex")}`;
|
|
26741
27186
|
try {
|
|
26742
|
-
(0,
|
|
26743
|
-
(0,
|
|
26744
|
-
(0,
|
|
27187
|
+
(0, import_node_fs13.writeFileSync)(writePath, JSON.stringify(pending, null, 2), { mode: 384 });
|
|
27188
|
+
(0, import_node_fs13.chmodSync)(writePath, 384);
|
|
27189
|
+
(0, import_node_fs13.renameSync)(writePath, path);
|
|
26745
27190
|
} finally {
|
|
26746
|
-
(0,
|
|
27191
|
+
(0, import_node_fs13.rmSync)(writePath, { force: true });
|
|
26747
27192
|
}
|
|
26748
27193
|
}
|
|
26749
27194
|
function removeAlanOwnedLocalArtifacts() {
|
|
26750
27195
|
const configPath = getConfigPath();
|
|
26751
|
-
const directory = (0,
|
|
26752
|
-
const configName = (0,
|
|
27196
|
+
const directory = (0, import_node_path11.dirname)(configPath);
|
|
27197
|
+
const configName = (0, import_node_path11.basename)(configPath).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
26753
27198
|
const alanAtomicSidecarPattern = new RegExp(
|
|
26754
27199
|
`^${configName}(?:|\\.setup-pending|\\.device-auth-pending|\\.device-auth-operation\\.json|\\.maintenance-lease\\.json|\\.event-outbox\\.enc)\\.(?:pending|release|corrupt)-\\d+-[a-f0-9]{12}$`
|
|
26755
27200
|
);
|
|
@@ -26766,13 +27211,13 @@ function removeAlanOwnedLocalArtifacts() {
|
|
|
26766
27211
|
`${configPath}.pending-runs.json.pending`,
|
|
26767
27212
|
maintenanceLeasePath(configPath)
|
|
26768
27213
|
]);
|
|
26769
|
-
if ((0,
|
|
26770
|
-
for (const entry of (0,
|
|
26771
|
-
if (alanAtomicSidecarPattern.test(entry)) artifacts.add((0,
|
|
27214
|
+
if ((0, import_node_fs13.existsSync)(directory)) {
|
|
27215
|
+
for (const entry of (0, import_node_fs13.readdirSync)(directory)) {
|
|
27216
|
+
if (alanAtomicSidecarPattern.test(entry)) artifacts.add((0, import_node_path11.join)(directory, entry));
|
|
26772
27217
|
}
|
|
26773
27218
|
}
|
|
26774
|
-
for (const artifact of artifacts) (0,
|
|
26775
|
-
(0,
|
|
27219
|
+
for (const artifact of artifacts) (0, import_node_fs13.rmSync)(artifact, { force: true });
|
|
27220
|
+
(0, import_node_fs13.rmSync)(configPath, { force: true });
|
|
26776
27221
|
}
|
|
26777
27222
|
function argValue(args, name) {
|
|
26778
27223
|
const index = args.indexOf(name);
|
|
@@ -26994,13 +27439,13 @@ var DurablePendingRunStarts = class extends Map {
|
|
|
26994
27439
|
}
|
|
26995
27440
|
persist() {
|
|
26996
27441
|
if (this.size === 0) {
|
|
26997
|
-
(0,
|
|
27442
|
+
(0, import_node_fs13.rmSync)(this.path, { force: true });
|
|
26998
27443
|
return;
|
|
26999
27444
|
}
|
|
27000
27445
|
const pendingPath = `${this.path}.pending`;
|
|
27001
|
-
(0,
|
|
27446
|
+
(0, import_node_fs13.mkdirSync)((0, import_node_path11.dirname)(this.path), { recursive: true, mode: 448 });
|
|
27002
27447
|
try {
|
|
27003
|
-
(0,
|
|
27448
|
+
(0, import_node_fs13.writeFileSync)(
|
|
27004
27449
|
pendingPath,
|
|
27005
27450
|
JSON.stringify({
|
|
27006
27451
|
version: 1,
|
|
@@ -27013,10 +27458,10 @@ var DurablePendingRunStarts = class extends Map {
|
|
|
27013
27458
|
}),
|
|
27014
27459
|
{ mode: 384 }
|
|
27015
27460
|
);
|
|
27016
|
-
(0,
|
|
27017
|
-
(0,
|
|
27461
|
+
(0, import_node_fs13.chmodSync)(pendingPath, 384);
|
|
27462
|
+
(0, import_node_fs13.renameSync)(pendingPath, this.path);
|
|
27018
27463
|
} finally {
|
|
27019
|
-
(0,
|
|
27464
|
+
(0, import_node_fs13.rmSync)(pendingPath, { force: true });
|
|
27020
27465
|
}
|
|
27021
27466
|
}
|
|
27022
27467
|
};
|
|
@@ -27251,21 +27696,21 @@ function reconcileActiveRuns(input) {
|
|
|
27251
27696
|
}
|
|
27252
27697
|
}
|
|
27253
27698
|
function collectRuntimeMetadata() {
|
|
27254
|
-
const cpuList = (0,
|
|
27699
|
+
const cpuList = (0, import_node_os8.cpus)();
|
|
27255
27700
|
const metadata = {
|
|
27256
|
-
platform: (0,
|
|
27257
|
-
arch: (0,
|
|
27258
|
-
osVersion: (0,
|
|
27701
|
+
platform: (0, import_node_os8.platform)(),
|
|
27702
|
+
arch: (0, import_node_os8.arch)(),
|
|
27703
|
+
osVersion: (0, import_node_os8.release)(),
|
|
27259
27704
|
agentVersion: AGENT_VERSION,
|
|
27260
|
-
memoryBytes: (0,
|
|
27261
|
-
memoryFreeBytes: (0,
|
|
27705
|
+
memoryBytes: (0, import_node_os8.totalmem)(),
|
|
27706
|
+
memoryFreeBytes: (0, import_node_os8.freemem)()
|
|
27262
27707
|
};
|
|
27263
27708
|
if (cpuList.length > 0) {
|
|
27264
27709
|
metadata.cpuModel = cpuList[0]?.model;
|
|
27265
27710
|
metadata.cpuCores = cpuList.length;
|
|
27266
27711
|
}
|
|
27267
27712
|
try {
|
|
27268
|
-
const disk = (0,
|
|
27713
|
+
const disk = (0, import_node_fs13.statfsSync)((0, import_node_os8.homedir)());
|
|
27269
27714
|
metadata.diskFreeBytes = disk.bavail * disk.bsize;
|
|
27270
27715
|
metadata.diskTotalBytes = disk.blocks * disk.bsize;
|
|
27271
27716
|
} catch {
|
|
@@ -27521,7 +27966,7 @@ async function setupDaemon(args) {
|
|
|
27521
27966
|
const teamId = argValue(args, "--team") ?? process.env.ALAN_TEAM_ID;
|
|
27522
27967
|
const setupToken = argValue(args, "--setup-token") ?? process.env.ALAN_RUNTIME_SETUP_TOKEN;
|
|
27523
27968
|
const token = argValue(args, "--token") ?? process.env.ALAN_SETUP_TOKEN;
|
|
27524
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
27969
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os8.hostname)();
|
|
27525
27970
|
const scope = argValue(args, "--scope") ?? process.env.ALAN_RUNTIME_SCOPE ?? (setupToken ? "team" : "user");
|
|
27526
27971
|
const installationId = argValue(args, "--installation-id") ?? previousConfig.installationId ?? (0, import_node_crypto3.randomUUID)();
|
|
27527
27972
|
if (scope !== "team" && scope !== "user") {
|
|
@@ -27544,7 +27989,7 @@ async function setupDaemon(args) {
|
|
|
27544
27989
|
...teamId ? { teamId } : {},
|
|
27545
27990
|
...setupToken ? { setupToken, registrationAttemptId } : {},
|
|
27546
27991
|
displayName,
|
|
27547
|
-
hostname: (0,
|
|
27992
|
+
hostname: (0, import_node_os8.hostname)(),
|
|
27548
27993
|
runtimeKind: "machine",
|
|
27549
27994
|
managementKind: "user_managed",
|
|
27550
27995
|
hostKind: "daemon",
|
|
@@ -27628,7 +28073,7 @@ async function loginWithDeviceCode(args) {
|
|
|
27628
28073
|
}
|
|
27629
28074
|
const previousConfig = readConfigForRegistration();
|
|
27630
28075
|
const { apiUrl, wsUrl, endpointProfile } = resolveEndpoints(args);
|
|
27631
|
-
const displayName = argValue(args, "--name") ?? (0,
|
|
28076
|
+
const displayName = argValue(args, "--name") ?? (0, import_node_os8.hostname)();
|
|
27632
28077
|
const maxPolls = Number.parseInt(argValue(args, "--max-polls") ?? "300", 10);
|
|
27633
28078
|
const resumed = readPendingDeviceAuthorization(apiUrl);
|
|
27634
28079
|
const installationId = resumed?.installationId ?? previousConfig.installationId ?? (0, import_node_crypto3.randomUUID)();
|
|
@@ -27640,7 +28085,7 @@ async function loginWithDeviceCode(args) {
|
|
|
27640
28085
|
headers: { "content-type": "application/json" },
|
|
27641
28086
|
body: JSON.stringify({
|
|
27642
28087
|
displayName,
|
|
27643
|
-
hostname: (0,
|
|
28088
|
+
hostname: (0, import_node_os8.hostname)(),
|
|
27644
28089
|
capabilities: discoverCapabilities(),
|
|
27645
28090
|
metadata: {
|
|
27646
28091
|
...await collectRuntimeMetadataWithProviderLimits(),
|
|
@@ -27874,7 +28319,7 @@ async function startDaemon(args) {
|
|
|
27874
28319
|
const workspaceRelocations = /* @__PURE__ */ new Map();
|
|
27875
28320
|
for (const relocation of stored.workspaceRelocations ?? []) {
|
|
27876
28321
|
if (relocation?.conversationId && relocation.runId && relocation.previousPath && relocation.canonicalPath) {
|
|
27877
|
-
workspaceRelocations.set((0,
|
|
28322
|
+
workspaceRelocations.set((0, import_node_path11.resolve)(relocation.previousPath), relocation);
|
|
27878
28323
|
}
|
|
27879
28324
|
}
|
|
27880
28325
|
if (stored.localApiPort !== localApiPort || stored.localApiToken !== localApiToken || stored.localServiceId !== localServiceId || stored.localServiceSecret !== localServiceSecret || stored.eventSpoolKey !== eventSpoolKey || stored.daemonEpoch !== daemonEpoch || stored.installationId !== installationId) {
|
|
@@ -28270,7 +28715,26 @@ async function startDaemon(args) {
|
|
|
28270
28715
|
return;
|
|
28271
28716
|
}
|
|
28272
28717
|
const backendKind = normalizeBackendKind2(payload.backendKind);
|
|
28273
|
-
|
|
28718
|
+
let runtimeCommand = resolveBackendRuntimeCommand(backendKind ?? payload.backendKind);
|
|
28719
|
+
if (!runtimeCommand && backendKind) {
|
|
28720
|
+
runtimeCommand = revalidateBackendRuntimeCommand(backendKind);
|
|
28721
|
+
}
|
|
28722
|
+
if (!runtimeCommand && backendKind && canInstallProviderCli(backendKind)) {
|
|
28723
|
+
pendingRunStarts.set(payload.runId, payload.conversationId);
|
|
28724
|
+
try {
|
|
28725
|
+
const installed = await ensureProviderCliInstalled(backendKind, {
|
|
28726
|
+
notify: (message) => {
|
|
28727
|
+
pushLog(message);
|
|
28728
|
+
console.info(`[alan-agent] ${message}`);
|
|
28729
|
+
}
|
|
28730
|
+
});
|
|
28731
|
+
if (installed) {
|
|
28732
|
+
runtimeCommand = revalidateBackendRuntimeCommand(backendKind);
|
|
28733
|
+
}
|
|
28734
|
+
} finally {
|
|
28735
|
+
pendingRunStarts.delete(payload.runId);
|
|
28736
|
+
}
|
|
28737
|
+
}
|
|
28274
28738
|
if (!runtimeCommand && backendKind) {
|
|
28275
28739
|
socket.emit("agent.rejected", {
|
|
28276
28740
|
runId: payload.runId,
|
|
@@ -28284,31 +28748,31 @@ async function startDaemon(args) {
|
|
|
28284
28748
|
const workspaceRequired = Boolean(explicitWorkspacePath);
|
|
28285
28749
|
if (isAlanDefaultWorkspace(payload.projectPath)) {
|
|
28286
28750
|
try {
|
|
28287
|
-
(0,
|
|
28751
|
+
(0, import_node_fs13.mkdirSync)(cwd, { recursive: true });
|
|
28288
28752
|
} catch {
|
|
28289
28753
|
}
|
|
28290
28754
|
}
|
|
28291
28755
|
let workspaceReadiness = inspectWorkspaceReadiness(workspaceRequired ? cwd : void 0);
|
|
28292
28756
|
const expectedRepoUrls = [
|
|
28293
28757
|
...(payload.repoLocalPaths ?? []).filter(
|
|
28294
|
-
(repo) => explicitWorkspacePath ? (0,
|
|
28758
|
+
(repo) => explicitWorkspacePath ? (0, import_node_path11.resolve)(repo.localPath) === (0, import_node_path11.resolve)(explicitWorkspacePath) : false
|
|
28295
28759
|
).map((repo) => repo.repoUrl),
|
|
28296
28760
|
...payload.localRepoUrls ?? []
|
|
28297
28761
|
];
|
|
28298
28762
|
if (workspaceReadiness.code === "workspace_missing" && explicitWorkspacePath && !payload.worktreeInfo) {
|
|
28299
|
-
const previousPath = (0,
|
|
28763
|
+
const previousPath = (0, import_node_path11.resolve)(explicitWorkspacePath);
|
|
28300
28764
|
const remembered = workspaceRelocations.get(previousPath);
|
|
28301
28765
|
const rememberedPath = remembered?.canonicalPath;
|
|
28302
28766
|
const relocated = rememberedPath && workspaceMatchesExpectedRepositories({
|
|
28303
28767
|
workspacePath: rememberedPath,
|
|
28304
28768
|
expectedRepoUrls
|
|
28305
|
-
}) ? (0,
|
|
28769
|
+
}) ? (0, import_node_path11.resolve)(rememberedPath) : discoverRelocatedWorkspace({
|
|
28306
28770
|
missingPath: explicitWorkspacePath,
|
|
28307
28771
|
approvedWorkspacePaths: payload.approvedWorkspacePaths,
|
|
28308
28772
|
expectedRepoUrls
|
|
28309
28773
|
});
|
|
28310
28774
|
if (relocated) {
|
|
28311
|
-
if (!remembered || (0,
|
|
28775
|
+
if (!remembered || (0, import_node_path11.resolve)(remembered.canonicalPath) !== relocated) {
|
|
28312
28776
|
workspaceRelocations.set(previousPath, {
|
|
28313
28777
|
conversationId: payload.conversationId,
|
|
28314
28778
|
runId: payload.runId,
|
|
@@ -28769,6 +29233,29 @@ async function startDaemon(args) {
|
|
|
28769
29233
|
})();
|
|
28770
29234
|
}
|
|
28771
29235
|
);
|
|
29236
|
+
socket.on(
|
|
29237
|
+
"runtime.skills.scan",
|
|
29238
|
+
(payload) => {
|
|
29239
|
+
if (!payload?.requestId) return;
|
|
29240
|
+
const requestId = payload.requestId;
|
|
29241
|
+
try {
|
|
29242
|
+
const projectPath = isAlanDefaultWorkspace(payload.projectPath) ? resolveAlanDefaultWorkspacePath() : payload.projectPath;
|
|
29243
|
+
const result = scanLocalSkillsCached((0, import_node_os8.homedir)(), projectPath, {
|
|
29244
|
+
refresh: payload.refresh === true
|
|
29245
|
+
});
|
|
29246
|
+
socket.emit("runtime.skills.result", {
|
|
29247
|
+
requestId,
|
|
29248
|
+
skills: result.skills,
|
|
29249
|
+
errors: result.errors
|
|
29250
|
+
});
|
|
29251
|
+
} catch (error) {
|
|
29252
|
+
socket.emit("runtime.skills.result", {
|
|
29253
|
+
requestId,
|
|
29254
|
+
error: error instanceof Error ? error.message : String(error)
|
|
29255
|
+
});
|
|
29256
|
+
}
|
|
29257
|
+
}
|
|
29258
|
+
);
|
|
28772
29259
|
const adoptionChallenges = /* @__PURE__ */ new Map();
|
|
28773
29260
|
const localServer = import_node_http.default.createServer((req, res) => {
|
|
28774
29261
|
if (req.method === "GET" && req.url === "/owner") {
|
|
@@ -29762,7 +30249,7 @@ var agentProbeAckSchema = external_exports.object({
|
|
|
29762
30249
|
|
|
29763
30250
|
// src/sandbox-outbox.ts
|
|
29764
30251
|
var import_node_crypto5 = require("crypto");
|
|
29765
|
-
var
|
|
30252
|
+
var import_node_fs14 = require("fs");
|
|
29766
30253
|
var SANDBOX_EVENT_OUTBOX_ENV = "ALAN_EVENT_OUTBOX_ENABLED";
|
|
29767
30254
|
function isSandboxEventOutboxEnabled(env = process.env) {
|
|
29768
30255
|
return env[SANDBOX_EVENT_OUTBOX_ENV] === "true";
|
|
@@ -29785,7 +30272,7 @@ function createSandboxEventOutbox(input) {
|
|
|
29785
30272
|
input.pushLog?.(
|
|
29786
30273
|
`sandbox_outbox_spool_reset ${error instanceof Error ? error.message : String(error)}`
|
|
29787
30274
|
);
|
|
29788
|
-
(0,
|
|
30275
|
+
(0, import_node_fs14.rmSync)(path, { force: true });
|
|
29789
30276
|
return new EncryptedEventOutbox(path, key, input.pushLog, input.options);
|
|
29790
30277
|
}
|
|
29791
30278
|
}
|
|
@@ -30482,10 +30969,10 @@ async function runSandbox(config) {
|
|
|
30482
30969
|
}
|
|
30483
30970
|
|
|
30484
30971
|
// src/service-manager.ts
|
|
30485
|
-
var
|
|
30486
|
-
var
|
|
30487
|
-
var
|
|
30488
|
-
var
|
|
30972
|
+
var import_node_child_process7 = require("child_process");
|
|
30973
|
+
var import_node_fs15 = require("fs");
|
|
30974
|
+
var import_node_os9 = require("os");
|
|
30975
|
+
var import_node_path12 = require("path");
|
|
30489
30976
|
var SERVICE_LABEL = "ai.tryalan.agent";
|
|
30490
30977
|
var SYSTEMD_UNIT = "alan-agent.service";
|
|
30491
30978
|
var WINDOWS_TASK = "Alan Agent";
|
|
@@ -30505,8 +30992,8 @@ function buildDaemonServicePlan(input) {
|
|
|
30505
30992
|
if (userId === void 0) throw new Error("Cannot determine the current macOS user ID");
|
|
30506
30993
|
const domain = `gui/${userId}`;
|
|
30507
30994
|
const serviceTarget = `${domain}/${SERVICE_LABEL}`;
|
|
30508
|
-
const manifestPath = (0,
|
|
30509
|
-
const logDir = (0,
|
|
30995
|
+
const manifestPath = (0, import_node_path12.join)(input.homeDir, "Library", "LaunchAgents", `${SERVICE_LABEL}.plist`);
|
|
30996
|
+
const logDir = (0, import_node_path12.join)(input.homeDir, ".alan", "agent", "logs");
|
|
30510
30997
|
const programArguments = daemonArgs.map((arg) => ` <string>${xml(arg)}</string>`).join("\n");
|
|
30511
30998
|
const manifest = `<?xml version="1.0" encoding="UTF-8"?>
|
|
30512
30999
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -30528,9 +31015,9 @@ ${programArguments}
|
|
|
30528
31015
|
<key>ThrottleInterval</key>
|
|
30529
31016
|
<integer>5</integer>
|
|
30530
31017
|
<key>StandardOutPath</key>
|
|
30531
|
-
<string>${xml((0,
|
|
31018
|
+
<string>${xml((0, import_node_path12.join)(logDir, "daemon.log"))}</string>
|
|
30532
31019
|
<key>StandardErrorPath</key>
|
|
30533
|
-
<string>${xml((0,
|
|
31020
|
+
<string>${xml((0, import_node_path12.join)(logDir, "daemon-error.log"))}</string>
|
|
30534
31021
|
</dict>
|
|
30535
31022
|
</plist>
|
|
30536
31023
|
`;
|
|
@@ -30569,7 +31056,7 @@ ${programArguments}
|
|
|
30569
31056
|
};
|
|
30570
31057
|
}
|
|
30571
31058
|
if (input.platform === "linux") {
|
|
30572
|
-
const manifestPath = (0,
|
|
31059
|
+
const manifestPath = (0, import_node_path12.join)(input.homeDir, ".config", "systemd", "user", SYSTEMD_UNIT);
|
|
30573
31060
|
const manifest = `[Unit]
|
|
30574
31061
|
Description=Alan local agent daemon
|
|
30575
31062
|
After=network-online.target
|
|
@@ -30666,7 +31153,7 @@ WantedBy=default.target
|
|
|
30666
31153
|
};
|
|
30667
31154
|
}
|
|
30668
31155
|
function currentServicePlan(args) {
|
|
30669
|
-
const currentPlatform = (0,
|
|
31156
|
+
const currentPlatform = (0, import_node_os9.platform)();
|
|
30670
31157
|
if (currentPlatform !== "darwin" && currentPlatform !== "linux" && currentPlatform !== "win32") {
|
|
30671
31158
|
throw new Error(`Daemon service installation is not supported on ${currentPlatform}`);
|
|
30672
31159
|
}
|
|
@@ -30675,25 +31162,25 @@ function currentServicePlan(args) {
|
|
|
30675
31162
|
if (!cliEntry) throw new Error("Cannot determine the alan-agent executable path");
|
|
30676
31163
|
return buildDaemonServicePlan({
|
|
30677
31164
|
platform: currentPlatform,
|
|
30678
|
-
homeDir: (0,
|
|
31165
|
+
homeDir: (0, import_node_os9.homedir)(),
|
|
30679
31166
|
nodeExecutable: process.execPath,
|
|
30680
|
-
cliEntry: (0,
|
|
31167
|
+
cliEntry: (0, import_node_path12.resolve)(cliEntry),
|
|
30681
31168
|
profile
|
|
30682
31169
|
});
|
|
30683
31170
|
}
|
|
30684
31171
|
function writeManifest(path, contents) {
|
|
30685
|
-
(0,
|
|
31172
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path12.dirname)(path), { recursive: true, mode: 448 });
|
|
30686
31173
|
const pendingPath = `${path}.pending-${process.pid}`;
|
|
30687
31174
|
try {
|
|
30688
|
-
(0,
|
|
30689
|
-
(0,
|
|
30690
|
-
(0,
|
|
31175
|
+
(0, import_node_fs15.writeFileSync)(pendingPath, contents, { mode: 384 });
|
|
31176
|
+
(0, import_node_fs15.chmodSync)(pendingPath, 384);
|
|
31177
|
+
(0, import_node_fs15.renameSync)(pendingPath, path);
|
|
30691
31178
|
} finally {
|
|
30692
|
-
(0,
|
|
31179
|
+
(0, import_node_fs15.rmSync)(pendingPath, { force: true });
|
|
30693
31180
|
}
|
|
30694
31181
|
}
|
|
30695
31182
|
function runServiceCommand(command) {
|
|
30696
|
-
const result = (0,
|
|
31183
|
+
const result = (0, import_node_child_process7.spawnSync)(command.command, command.args, { encoding: "utf8" });
|
|
30697
31184
|
const status = result.status ?? 1;
|
|
30698
31185
|
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
|
|
30699
31186
|
if (status !== 0 && !command.tolerateFailure) {
|
|
@@ -30711,8 +31198,8 @@ function installDaemonService(args = []) {
|
|
|
30711
31198
|
}
|
|
30712
31199
|
const plan = currentServicePlan(args);
|
|
30713
31200
|
if (plan.manifestPath && plan.manifest) {
|
|
30714
|
-
if ((0,
|
|
30715
|
-
(0,
|
|
31201
|
+
if ((0, import_node_os9.platform)() === "darwin") {
|
|
31202
|
+
(0, import_node_fs15.mkdirSync)((0, import_node_path12.join)((0, import_node_os9.homedir)(), ".alan", "agent", "logs"), { recursive: true, mode: 448 });
|
|
30716
31203
|
}
|
|
30717
31204
|
writeManifest(plan.manifestPath, plan.manifest);
|
|
30718
31205
|
}
|
|
@@ -30722,7 +31209,7 @@ function installDaemonService(args = []) {
|
|
|
30722
31209
|
function uninstallDaemonService(args = []) {
|
|
30723
31210
|
const plan = currentServicePlan(args);
|
|
30724
31211
|
for (const command of plan.uninstallCommands) runServiceCommand(command);
|
|
30725
|
-
if (plan.manifestPath) (0,
|
|
31212
|
+
if (plan.manifestPath) (0, import_node_fs15.rmSync)(plan.manifestPath, { force: true });
|
|
30726
31213
|
console.info("[alan-agent] Per-user daemon service removed");
|
|
30727
31214
|
}
|
|
30728
31215
|
function printDaemonServiceStatus(args = []) {
|