@astrale-os/cli 0.6.3-alpha.0 → 0.8.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -2
- package/dist/astrale.js +339 -242
- package/package.json +2 -3
- package/src/commands/__tests__/admin-instance.test.ts +49 -2
- package/src/commands/__tests__/domain-install-owned.test.ts +122 -0
- package/src/commands/__tests__/help-contract.test.ts +15 -0
- package/src/commands/domain/install.ts +15 -4
- package/src/commands/instance/active.ts +4 -7
- package/src/commands/instance/list.ts +4 -8
- package/src/commands/instance/status.ts +14 -9
- package/src/commands/instance/use.ts +13 -11
- package/src/commands/studio.ts +13 -0
- package/src/commands/view.ts +40 -13
- package/src/kernel/__tests__/client-owned-lookup.test.ts +51 -0
- package/src/kernel/client.ts +47 -20
- package/src/kernel/expand.ts +3 -22
- package/src/lib/__tests__/instance-candidates.test.ts +94 -19
- package/src/lib/__tests__/instance-target.test.ts +9 -1
- package/src/lib/__tests__/view-assets.test.ts +114 -0
- package/src/lib/__tests__/view-port-allocation.test.ts +82 -0
- package/src/lib/admin-instance.ts +27 -2
- package/src/lib/instance-candidates.ts +3 -3
- package/src/lib/instance-target.ts +1 -0
- package/src/lib/instance.ts +0 -11
- package/src/lib/login-flow.ts +4 -41
- package/src/lib/view/assets.ts +64 -0
- package/src/lib/view/port-allocation.ts +19 -0
- package/src/lib/view/server.ts +4 -37
- package/src/setup/__tests__/instance-step.test.ts +239 -0
- package/src/setup/steps/instance.ts +141 -61
- package/studio/client/dist/assets/index-BaqEuIQJ.js +109 -0
- package/studio/client/dist/assets/index-jRdExahh.css +1 -0
- package/studio/client/dist/index.html +2 -2
- package/studio/server/agent/ask.test.ts +74 -0
- package/studio/server/agent/ask.ts +20 -22
- package/studio/server/agent/bridge/client.test.ts +49 -0
- package/studio/server/agent/bridge/client.ts +37 -0
- package/studio/server/agent/bridge/grant.test.ts +62 -0
- package/studio/server/agent/bridge/grant.ts +84 -0
- package/studio/server/agent/bridge/routes.test.ts +151 -0
- package/studio/server/agent/bridge/routes.ts +148 -0
- package/studio/server/agent/{bridge-mcp.ts → bridge/stdio.ts} +27 -21
- package/studio/server/agent/conversation.test.ts +84 -0
- package/studio/server/agent/conversation.ts +110 -0
- package/studio/server/agent/{types.ts → harness/adapter.ts} +63 -12
- package/studio/server/agent/harness/claude/adapter.test.ts +338 -0
- package/studio/server/agent/harness/claude/adapter.ts +71 -0
- package/studio/server/agent/harness/claude/ask.ts +114 -0
- package/studio/server/agent/harness/claude/capabilities.ts +27 -0
- package/studio/server/agent/harness/claude/command.ts +63 -0
- package/studio/server/agent/harness/claude/events.ts +215 -0
- package/studio/server/agent/harness/claude/loadout.ts +132 -0
- package/studio/server/agent/harness/claude/mcp.test.ts +36 -0
- package/studio/server/agent/harness/claude/mcp.ts +41 -0
- package/studio/server/agent/harness/claude/skills.ts +43 -0
- package/studio/server/agent/harness/codex/adapter.test.ts +269 -0
- package/studio/server/agent/harness/codex/adapter.ts +116 -0
- package/studio/server/agent/harness/codex/ask.test.ts +176 -0
- package/studio/server/agent/harness/codex/ask.ts +181 -0
- package/studio/server/agent/harness/codex/command.test.ts +69 -0
- package/studio/server/agent/harness/codex/command.ts +43 -0
- package/studio/server/agent/harness/codex/events.test.ts +94 -0
- package/studio/server/agent/harness/codex/events.ts +132 -0
- package/studio/server/agent/harness/codex/exec.ts +113 -0
- package/studio/server/agent/harness/codex/loadout.ts +63 -0
- package/studio/server/agent/harness/codex/mcp.test.ts +32 -0
- package/studio/server/agent/harness/codex/mcp.ts +27 -0
- package/studio/server/agent/harness/codex/models.test.ts +167 -0
- package/studio/server/agent/harness/codex/models.ts +211 -0
- package/studio/server/agent/harness/codex/skills.ts +33 -0
- package/studio/server/agent/harness/gateway/config.test.ts +98 -0
- package/studio/server/{state/harness-gateway.ts → agent/harness/gateway/config.ts} +30 -8
- package/studio/server/agent/harness/gateway/token.test.ts +133 -0
- package/studio/server/agent/harness/gateway/token.ts +166 -0
- package/studio/server/agent/harness/mock/adapter.ts +190 -0
- package/studio/server/agent/harness/mock/domain-edit.ts +41 -0
- package/studio/server/agent/harness/process.test.ts +46 -0
- package/studio/server/agent/harness/process.ts +104 -0
- package/studio/server/agent/harness/registry.ts +37 -0
- package/studio/server/agent/harness/selection.test.ts +75 -0
- package/studio/server/agent/harness/selection.ts +77 -0
- package/studio/server/agent/harness/skills.test.ts +95 -0
- package/studio/server/agent/harness/skills.ts +100 -0
- package/studio/server/agent/layout.test.ts +95 -0
- package/studio/server/agent/notify.ts +12 -0
- package/studio/server/agent/{schema-map.ts → prompts/anchors.ts} +2 -2
- package/studio/server/agent/prompts/ask.ts +34 -0
- package/studio/server/agent/{prompt.ts → prompts/system.ts} +3 -107
- package/studio/server/agent/prompts/turn.ts +57 -0
- package/studio/server/agent/routes.test.ts +176 -0
- package/studio/server/agent/routes.ts +214 -0
- package/studio/server/agent/run/completion.ts +193 -0
- package/studio/server/agent/run/coordinator.test.ts +337 -0
- package/studio/server/agent/run/coordinator.ts +104 -0
- package/studio/server/agent/run/live-state.ts +73 -0
- package/studio/server/agent/run/preparation.ts +162 -0
- package/studio/server/agent/run/transcript.test.ts +47 -0
- package/studio/server/agent/run/transcript.ts +30 -0
- package/studio/server/agent/run/usage.test.ts +46 -0
- package/studio/server/{state → agent/run}/usage.ts +4 -4
- package/studio/server/agent/stream.ts +37 -0
- package/studio/server/agent/{session-id.ts → telemetry.ts} +1 -1
- package/studio/server/api-agent-loadout.test.ts +69 -0
- package/studio/server/api.ts +3 -155
- package/studio/server/index.ts +6 -5
- package/studio/server/state/comments.test.ts +29 -0
- package/studio/server/state/comments.ts +3 -3
- package/studio/server/state/settings.test.ts +78 -0
- package/studio/server/state/settings.ts +28 -1
- package/studio/shared/agent-effort.test.ts +12 -0
- package/studio/shared/agent-effort.ts +15 -0
- package/studio/shared/agent-models.test.ts +9 -0
- package/studio/shared/agent-models.ts +14 -0
- package/studio/shared/settings-values.test.ts +18 -0
- package/studio/shared/settings-values.ts +20 -0
- package/studio/shared/types.ts +58 -7
- package/src/connect-core.test.ts +0 -42
- package/src/connect-core.ts +0 -53
- package/studio/client/dist/assets/index-CyN5G8IA.js +0 -109
- package/studio/client/dist/assets/index-DKKMHBBC.css +0 -1
- package/studio/server/agent/bridge.ts +0 -188
- package/studio/server/agent/claude.ts +0 -678
- package/studio/server/agent/mock.ts +0 -186
- package/studio/server/agent/registry.ts +0 -29
- package/studio/server/agent/runner.ts +0 -487
- package/studio/server/state/harness-token.ts +0 -0
package/dist/astrale.js
CHANGED
|
@@ -2576,7 +2576,7 @@ var package_default;
|
|
|
2576
2576
|
var init_package = __esm(() => {
|
|
2577
2577
|
package_default = {
|
|
2578
2578
|
name: "@astrale-os/cli",
|
|
2579
|
-
version: "0.
|
|
2579
|
+
version: "0.8.0-alpha.0",
|
|
2580
2580
|
description: "Astrale CLI — connect to existing Astrale kernels",
|
|
2581
2581
|
keywords: [
|
|
2582
2582
|
"astrale",
|
|
@@ -2606,8 +2606,7 @@ var init_package = __esm(() => {
|
|
|
2606
2606
|
type: "module",
|
|
2607
2607
|
exports: {
|
|
2608
2608
|
"./keys": "./src/lib/keys.ts",
|
|
2609
|
-
"./paths": "./src/lib/paths.ts"
|
|
2610
|
-
"./connect-core": "./src/connect-core.ts"
|
|
2609
|
+
"./paths": "./src/lib/paths.ts"
|
|
2611
2610
|
},
|
|
2612
2611
|
publishConfig: {
|
|
2613
2612
|
access: "public",
|
|
@@ -59080,24 +59079,14 @@ async function obtainToken(idp, opts, scope2) {
|
|
|
59080
59079
|
scope: scope2,
|
|
59081
59080
|
audience: opts.audience
|
|
59082
59081
|
});
|
|
59083
|
-
if (
|
|
59084
|
-
|
|
59085
|
-
|
|
59086
|
-
|
|
59087
|
-
|
|
59088
|
-
|
|
59089
|
-
|
|
59090
|
-
});
|
|
59091
|
-
} else {
|
|
59092
|
-
if (device.verification_uri_complete)
|
|
59093
|
-
log.info(`Open: ${device.verification_uri_complete}`);
|
|
59094
|
-
else if (device.verification_uri)
|
|
59095
|
-
log.info(`Open: ${device.verification_uri}`);
|
|
59096
|
-
if (device.user_code)
|
|
59097
|
-
log.info(`Code: ${device.user_code}`);
|
|
59098
|
-
if (device.message)
|
|
59099
|
-
log.dim(` ${device.message}`);
|
|
59100
|
-
}
|
|
59082
|
+
if (device.verification_uri_complete)
|
|
59083
|
+
log.info(`Open: ${device.verification_uri_complete}`);
|
|
59084
|
+
else if (device.verification_uri)
|
|
59085
|
+
log.info(`Open: ${device.verification_uri}`);
|
|
59086
|
+
if (device.user_code)
|
|
59087
|
+
log.info(`Code: ${device.user_code}`);
|
|
59088
|
+
if (device.message)
|
|
59089
|
+
log.dim(` ${device.message}`);
|
|
59101
59090
|
return pollDeviceToken({
|
|
59102
59091
|
idp,
|
|
59103
59092
|
deviceCode: device.device_code,
|
|
@@ -65902,6 +65891,12 @@ var init_session = __esm(() => {
|
|
|
65902
65891
|
function adminInstanceMethod(method) {
|
|
65903
65892
|
return `${ADMIN_INSTANCE}:${method}`;
|
|
65904
65893
|
}
|
|
65894
|
+
async function callOwnedInstances(client) {
|
|
65895
|
+
return await client.call(adminInstanceMethod("listMine"), {});
|
|
65896
|
+
}
|
|
65897
|
+
function findOwnedInstance(instances, identifier) {
|
|
65898
|
+
return instances.find((instance) => instance.id === identifier || instance.slug === identifier);
|
|
65899
|
+
}
|
|
65905
65900
|
function formatInstanceLocation(info2) {
|
|
65906
65901
|
return [info2.state && info2.state !== "ready" ? info2.state : undefined, info2.region, info2.hostId].filter(Boolean).join(" · ");
|
|
65907
65902
|
}
|
|
@@ -66019,6 +66014,8 @@ function adminTargetToInstance(target) {
|
|
|
66019
66014
|
};
|
|
66020
66015
|
}
|
|
66021
66016
|
function isManagedInstanceNotFound(error52) {
|
|
66017
|
+
if (error52 instanceof AstraleError && error52.code === "INSTANCE_NOT_FOUND")
|
|
66018
|
+
return true;
|
|
66022
66019
|
if (!(error52 instanceof Error))
|
|
66023
66020
|
return false;
|
|
66024
66021
|
if (error52.name === "NotFoundError")
|
|
@@ -66384,13 +66381,13 @@ var init_ca_fetch = () => {};
|
|
|
66384
66381
|
// src/kernel/client.ts
|
|
66385
66382
|
async function resolveKernelTarget(opts, config2) {
|
|
66386
66383
|
if (opts.url && !opts.instance) {
|
|
66387
|
-
const resolved2 = await resolveInstanceTarget({ source: "url", url: opts.url }, { config: config2
|
|
66384
|
+
const resolved2 = await resolveInstanceTarget({ source: "url", url: opts.url }, { config: config2 });
|
|
66388
66385
|
return resolvedToKernelTarget(resolved2);
|
|
66389
66386
|
}
|
|
66390
66387
|
const resolved = await resolveInstanceTarget(opts.instance ? { source: "name", name: opts.instance } : { source: "active" }, {
|
|
66391
66388
|
config: config2,
|
|
66392
|
-
admin:
|
|
66393
|
-
managed: (slug) =>
|
|
66389
|
+
admin: {},
|
|
66390
|
+
managed: (slug) => lookupImplicitOwnedInstance(slug, opts)
|
|
66394
66391
|
});
|
|
66395
66392
|
return resolvedToKernelTarget(resolved, opts.url);
|
|
66396
66393
|
}
|
|
@@ -66399,16 +66396,22 @@ async function withKernelClient(opts, fn2) {
|
|
|
66399
66396
|
const target = await resolveKernelTarget(opts, config2);
|
|
66400
66397
|
return withResolvedKernelClient(opts, config2, target, fn2);
|
|
66401
66398
|
}
|
|
66402
|
-
async function
|
|
66403
|
-
return await withAdminKernelClient(
|
|
66399
|
+
async function listOwnedInstances(opts) {
|
|
66400
|
+
return await withAdminKernelClient(opts, async (ctx) => callOwnedInstances(ctx.client));
|
|
66404
66401
|
}
|
|
66405
|
-
function
|
|
66406
|
-
|
|
66407
|
-
|
|
66408
|
-
|
|
66409
|
-
|
|
66410
|
-
|
|
66411
|
-
|
|
66402
|
+
async function lookupOwnedInstance(slug, opts) {
|
|
66403
|
+
const instance = findOwnedInstance(await listOwnedInstances(opts), slug);
|
|
66404
|
+
if (instance)
|
|
66405
|
+
return instance;
|
|
66406
|
+
throw new AstraleError("INSTANCE_NOT_FOUND", `No owned instance matches "${slug}".`);
|
|
66407
|
+
}
|
|
66408
|
+
async function lookupImplicitOwnedInstance(slug, targetOpts, deps = {
|
|
66409
|
+
lookupOwned: lookupOwnedInstance
|
|
66410
|
+
}) {
|
|
66411
|
+
return await deps.lookupOwned(slug, {
|
|
66412
|
+
timeout: targetOpts.timeout,
|
|
66413
|
+
debug: targetOpts.debug
|
|
66414
|
+
});
|
|
66412
66415
|
}
|
|
66413
66416
|
function resolvedToKernelTarget(target, urlOverride) {
|
|
66414
66417
|
return {
|
|
@@ -66564,30 +66567,97 @@ var init_provision_instance = __esm(() => {
|
|
|
66564
66567
|
});
|
|
66565
66568
|
|
|
66566
66569
|
// src/setup/steps/instance.ts
|
|
66567
|
-
async function fetchManaged(ctx) {
|
|
66568
|
-
try {
|
|
66569
|
-
return await withSpinner("Checking for existing instances", !ctx.machine, () => withAdminKernelClient(ctx.opts, async (client) => await client.client.call(adminInstanceMethod("list"), {})));
|
|
66570
|
-
} catch {
|
|
66571
|
-
return [];
|
|
66572
|
-
}
|
|
66573
|
-
}
|
|
66574
66570
|
function hero(slug, kernelUrl) {
|
|
66575
66571
|
console.log("");
|
|
66576
66572
|
console.log(renderInstanceHero(slug, guiOrigin(kernelUrl)));
|
|
66577
66573
|
console.log("");
|
|
66578
66574
|
}
|
|
66579
|
-
async function
|
|
66580
|
-
|
|
66581
|
-
|
|
66575
|
+
async function adoptOwnedInstance(info2, deps = {
|
|
66576
|
+
upsert: upsertManagedBookmark,
|
|
66577
|
+
activate: setActive
|
|
66578
|
+
}) {
|
|
66579
|
+
const { repointedFrom } = await deps.upsert(info2.slug, info2.slug, info2.url, info2.organizationId);
|
|
66580
|
+
await deps.activate(info2.slug);
|
|
66582
66581
|
if (repointedFrom) {
|
|
66583
66582
|
log.warn(`Bookmark "${info2.slug}" repointed: ${repointedFrom} → ${normalizeInstanceKernelUrl(info2.url)}`);
|
|
66584
66583
|
}
|
|
66585
66584
|
log.success(`Active instance: ${info2.slug}`);
|
|
66586
66585
|
hero(info2.slug, info2.url);
|
|
66587
66586
|
}
|
|
66587
|
+
function defaultDependencies(ctx) {
|
|
66588
|
+
return {
|
|
66589
|
+
fetchOwned: (setupCtx) => withSpinner("Checking for existing instances", !setupCtx.machine, () => listOwnedInstances(setupCtx.opts)),
|
|
66590
|
+
adopt: adoptOwnedInstance,
|
|
66591
|
+
selectReady: (instances) => selectFrom("No active instance. Pick one:", instances.map((info2) => ({
|
|
66592
|
+
label: `${info2.slug} ${source_default.dim(guiOrigin(info2.url))}`,
|
|
66593
|
+
value: info2
|
|
66594
|
+
}))),
|
|
66595
|
+
confirmCreate: () => confirmDefaultYes("No instances yet. Provision your first one now?"),
|
|
66596
|
+
promptSlug: () => ctx.slug ? Promise.resolve(ctx.slug) : promptText("Pick a slug for your instance", { validate: slugError }),
|
|
66597
|
+
provision: (slug) => provisionInstance(slug, ctx.opts)
|
|
66598
|
+
};
|
|
66599
|
+
}
|
|
66600
|
+
async function ensureOwnedInstance(ctx, deps = defaultDependencies(ctx)) {
|
|
66601
|
+
let owned;
|
|
66602
|
+
try {
|
|
66603
|
+
owned = await deps.fetchOwned(ctx);
|
|
66604
|
+
} catch (cause) {
|
|
66605
|
+
const detail = cause instanceof Error ? cause.message : String(cause);
|
|
66606
|
+
throw new AstraleError("INSTANCE_DISCOVERY_FAILED", `Could not check your Astrale instances: ${detail}`, "No instance was created. Check `astrale admin status`, then rerun `astrale setup`.");
|
|
66607
|
+
}
|
|
66608
|
+
const ready = owned.filter((info2) => info2.state === "ready");
|
|
66609
|
+
if (ready.length === 1) {
|
|
66610
|
+
await deps.adopt(ready[0]);
|
|
66611
|
+
return "fixed";
|
|
66612
|
+
}
|
|
66613
|
+
if (ready.length > 1) {
|
|
66614
|
+
const choice = await deps.selectReady(ready);
|
|
66615
|
+
if (choice === null) {
|
|
66616
|
+
log.dim(" Skipped — no active instance set.");
|
|
66617
|
+
return "skipped";
|
|
66618
|
+
}
|
|
66619
|
+
await deps.adopt(choice);
|
|
66620
|
+
return "fixed";
|
|
66621
|
+
}
|
|
66622
|
+
if (owned.length > 0) {
|
|
66623
|
+
reportNotReady(owned);
|
|
66624
|
+
return "skipped";
|
|
66625
|
+
}
|
|
66626
|
+
if (!await deps.confirmCreate()) {
|
|
66627
|
+
log.dim(" Skipped — create one later: astrale instance create <slug>");
|
|
66628
|
+
return "skipped";
|
|
66629
|
+
}
|
|
66630
|
+
const slug = await deps.promptSlug();
|
|
66631
|
+
if (!slug) {
|
|
66632
|
+
log.dim(" Skipped — no slug given.");
|
|
66633
|
+
return "skipped";
|
|
66634
|
+
}
|
|
66635
|
+
const { created, selectionError } = await deps.provision(slug);
|
|
66636
|
+
if (selectionError) {
|
|
66637
|
+
const detail = selectionError instanceof Error ? selectionError.message : String(selectionError);
|
|
66638
|
+
throw new AstraleError("INSTANCE_SELECTION_FAILED", `Instance "${slug}" was provisioned, but the CLI could not select it: ${detail}`, `Fix local CLI storage, then run \`astrale instance use ${slug}\`.`);
|
|
66639
|
+
}
|
|
66640
|
+
hero(slug, created.url);
|
|
66641
|
+
return "fixed";
|
|
66642
|
+
}
|
|
66643
|
+
function reportNotReady(instances) {
|
|
66644
|
+
log.warn(`${instances.length === 1 ? "Your instance is" : "Your instances are"} not ready; setup will not create another.`);
|
|
66645
|
+
for (const info2 of instances) {
|
|
66646
|
+
const phase = info2.phase && info2.phase !== info2.state ? ` (${info2.phase})` : "";
|
|
66647
|
+
log.dim(` ${info2.slug}: ${info2.state}${phase} · astrale instance status ${info2.slug}`);
|
|
66648
|
+
if (info2.error)
|
|
66649
|
+
log.dim(` ${info2.error}`);
|
|
66650
|
+
}
|
|
66651
|
+
if (instances.some((info2) => info2.state === "failed")) {
|
|
66652
|
+
log.dim(" Inspect the failure, then deliberately delete/recreate it with `astrale instance` commands.");
|
|
66653
|
+
} else {
|
|
66654
|
+
log.dim(" Wait for provisioning to finish, then rerun `astrale setup`.");
|
|
66655
|
+
}
|
|
66656
|
+
}
|
|
66588
66657
|
var instanceStep;
|
|
66589
66658
|
var init_instance2 = __esm(() => {
|
|
66590
66659
|
init_source();
|
|
66660
|
+
init_errors3();
|
|
66591
66661
|
init_client2();
|
|
66592
66662
|
init_instance();
|
|
66593
66663
|
init_local_status();
|
|
@@ -66617,38 +66687,7 @@ var init_instance2 = __esm(() => {
|
|
|
66617
66687
|
log.success(`Active instance: ${instance.active} (${guiOrigin(instance.url)})`);
|
|
66618
66688
|
return "unchanged";
|
|
66619
66689
|
}
|
|
66620
|
-
|
|
66621
|
-
if (managed.length > 0) {
|
|
66622
|
-
const choice = await selectFrom("No active instance. Pick one or create a new instance:", [
|
|
66623
|
-
...managed.map((info2) => ({
|
|
66624
|
-
label: `${info2.slug} ${source_default.dim(guiOrigin(info2.url))}`,
|
|
66625
|
-
value: info2
|
|
66626
|
-
})),
|
|
66627
|
-
{ label: source_default.cyan("➕ Create a new instance"), value: "create" }
|
|
66628
|
-
]);
|
|
66629
|
-
if (choice === null) {
|
|
66630
|
-
log.dim(" Skipped — no active instance set.");
|
|
66631
|
-
return "skipped";
|
|
66632
|
-
}
|
|
66633
|
-
if (choice !== "create") {
|
|
66634
|
-
await adopt(choice);
|
|
66635
|
-
return "fixed";
|
|
66636
|
-
}
|
|
66637
|
-
} else {
|
|
66638
|
-
const yes = await confirmDefaultYes("No instances yet. Provision your first one now?");
|
|
66639
|
-
if (!yes) {
|
|
66640
|
-
log.dim(" Skipped — create one later: astrale instance create <slug>");
|
|
66641
|
-
return "skipped";
|
|
66642
|
-
}
|
|
66643
|
-
}
|
|
66644
|
-
const slug = ctx.slug ?? await promptText("Pick a slug for your instance", { validate: slugError });
|
|
66645
|
-
if (!slug) {
|
|
66646
|
-
log.dim(" Skipped — no slug given.");
|
|
66647
|
-
return "skipped";
|
|
66648
|
-
}
|
|
66649
|
-
const { created } = await provisionInstance(slug, ctx.opts);
|
|
66650
|
-
hero(slug, created.url);
|
|
66651
|
-
return "fixed";
|
|
66690
|
+
return ensureOwnedInstance(ctx);
|
|
66652
66691
|
}
|
|
66653
66692
|
};
|
|
66654
66693
|
});
|
|
@@ -67027,7 +67066,7 @@ async function resolveUseTarget2(name, opts) {
|
|
|
67027
67066
|
return await resolveInstance(chosen.key);
|
|
67028
67067
|
}
|
|
67029
67068
|
assertManagedReady(chosen.info);
|
|
67030
|
-
const { repointedFrom } = await upsertManagedBookmark(chosen.key, chosen.info.slug, chosen.url);
|
|
67069
|
+
const { repointedFrom } = await upsertManagedBookmark(chosen.key, chosen.info.slug, chosen.url, chosen.info.organizationId);
|
|
67031
67070
|
if (repointedFrom) {
|
|
67032
67071
|
log.warn(`Bookmark "${chosen.key}" repointed: ${repointedFrom} → ${chosen.url}`);
|
|
67033
67072
|
}
|
|
@@ -67040,16 +67079,16 @@ async function fetchManagedInstances(name, opts) {
|
|
|
67040
67079
|
return [];
|
|
67041
67080
|
}
|
|
67042
67081
|
try {
|
|
67043
|
-
return await
|
|
67082
|
+
return await listOwnedInstances(opts);
|
|
67044
67083
|
} catch {
|
|
67045
67084
|
return [];
|
|
67046
67085
|
}
|
|
67047
67086
|
}
|
|
67048
67087
|
function assertManagedReady(info2) {
|
|
67049
|
-
if (
|
|
67088
|
+
if (info2.state === "ready")
|
|
67050
67089
|
return;
|
|
67051
67090
|
const detail = info2.phase && info2.phase !== info2.state ? ` (${info2.phase})` : "";
|
|
67052
|
-
throw new AstraleError("INSTANCE_NOT_READY", `Instance "${info2.slug}" is ${info2.state}${detail}; it cannot be selected yet.`, info2.error ??
|
|
67091
|
+
throw new AstraleError("INSTANCE_NOT_READY", `Instance "${info2.slug}" is ${info2.state}${detail}; it cannot be selected yet.`, info2.error ?? `Run: astrale instance status ${info2.slug}`);
|
|
67053
67092
|
}
|
|
67054
67093
|
async function pickCandidate(name, candidates) {
|
|
67055
67094
|
return selectFrom(`Multiple instances match "${name}":`, candidates.map((candidate) => ({
|
|
@@ -68002,8 +68041,8 @@ async function buildSelfContext(opts) {
|
|
|
68002
68041
|
} else {
|
|
68003
68042
|
const resolved = await resolveInstanceTarget(opts.instance ? { source: "name", name: opts.instance } : { source: "active" }, {
|
|
68004
68043
|
config: config2,
|
|
68005
|
-
admin:
|
|
68006
|
-
managed: (instanceSlug) =>
|
|
68044
|
+
admin: {},
|
|
68045
|
+
managed: (instanceSlug) => lookupImplicitOwnedInstance(instanceSlug, opts)
|
|
68007
68046
|
});
|
|
68008
68047
|
slug = resolved.name;
|
|
68009
68048
|
defaultIdentity = resolved.defaultIdentity;
|
|
@@ -68034,17 +68073,6 @@ async function buildSelfContext(opts) {
|
|
|
68034
68073
|
}
|
|
68035
68074
|
return { identity: identity4, instanceSlug: slug, credsJwt: opts.creds, instanceSigned, idpSubject };
|
|
68036
68075
|
}
|
|
68037
|
-
function adminLookupOpts2(opts) {
|
|
68038
|
-
return {
|
|
68039
|
-
as: opts.as,
|
|
68040
|
-
creds: opts.creds,
|
|
68041
|
-
timeout: opts.timeout,
|
|
68042
|
-
debug: opts.debug
|
|
68043
|
-
};
|
|
68044
|
-
}
|
|
68045
|
-
async function lookupManagedInstance2(slug, opts) {
|
|
68046
|
-
return await withAdminKernelClient(adminLookupOpts2(opts), async (ctx) => await ctx.client.call(adminInstanceMethod("info"), { id: slug }));
|
|
68047
|
-
}
|
|
68048
68076
|
async function withSelfHint(fn2, meta3) {
|
|
68049
68077
|
if (!meta3)
|
|
68050
68078
|
return fn2();
|
|
@@ -69727,67 +69755,6 @@ async function findFreePort(start, span2 = 20, host = LOOPBACK) {
|
|
|
69727
69755
|
var LOOPBACK = "127.0.0.1";
|
|
69728
69756
|
var init_port = () => {};
|
|
69729
69757
|
|
|
69730
|
-
// src/lib/view/resolve.ts
|
|
69731
|
-
function parseViewSpec(spec) {
|
|
69732
|
-
if (VIEW_PATH_RE.test(spec))
|
|
69733
|
-
return { kind: "view", path: spec };
|
|
69734
|
-
if (spec.startsWith("/") || spec.startsWith("@"))
|
|
69735
|
-
return { kind: "target", path: spec };
|
|
69736
|
-
throw new AstraleError("INVALID_ARGUMENT", `"${spec}" is neither a ViewPath (/:origin:view.slug) nor a node path (/… or @id)`);
|
|
69737
|
-
}
|
|
69738
|
-
async function resolveViewCandidates(ctx, nodePath) {
|
|
69739
|
-
const result = await ctx.client.call(VIEW_RESOLVE_PATH, { node: nodePath });
|
|
69740
|
-
if (!Array.isArray(result)) {
|
|
69741
|
-
throw new AstraleError("UNEXPECTED_RESULT", `View:resolve returned a non-array for ${nodePath}`);
|
|
69742
|
-
}
|
|
69743
|
-
return result;
|
|
69744
|
-
}
|
|
69745
|
-
function candidateSlug(candidate) {
|
|
69746
|
-
const fromPath = candidate.path?.split("/").pop() ?? "";
|
|
69747
|
-
return candidate.name ?? fromPath;
|
|
69748
|
-
}
|
|
69749
|
-
function pickCandidate2(candidates, nodePath, slug) {
|
|
69750
|
-
if (slug) {
|
|
69751
|
-
const match = candidates.find((c) => candidateSlug(c) === slug || c.path.endsWith(`/${slug}`));
|
|
69752
|
-
if (!match) {
|
|
69753
|
-
throw new AstraleError("VIEW_NOT_FOUND", `No view "${slug}" on ${nodePath} — available: ${candidates.map(candidateSlug).join(", ") || "(none)"}`);
|
|
69754
|
-
}
|
|
69755
|
-
return match;
|
|
69756
|
-
}
|
|
69757
|
-
if (candidates.length === 0) {
|
|
69758
|
-
throw new AstraleError("VIEW_NOT_FOUND", `No views resolve on ${nodePath}`);
|
|
69759
|
-
}
|
|
69760
|
-
if (candidates.length === 1)
|
|
69761
|
-
return candidates[0];
|
|
69762
|
-
return "ambiguous";
|
|
69763
|
-
}
|
|
69764
|
-
function applyViewUrlOverride(resolvedUrl, override) {
|
|
69765
|
-
const parsed = parseUrl(override);
|
|
69766
|
-
if (parsed.pathname !== "/")
|
|
69767
|
-
return parsed.toString();
|
|
69768
|
-
const original = parseUrl(resolvedUrl);
|
|
69769
|
-
return new URL(original.pathname + original.search + original.hash, parsed.origin).toString();
|
|
69770
|
-
}
|
|
69771
|
-
function rewriteLocalViewUrl(url2) {
|
|
69772
|
-
const parsed = parseUrl(url2);
|
|
69773
|
-
if (parsed.hostname !== "host.docker.internal")
|
|
69774
|
-
return url2;
|
|
69775
|
-
parsed.hostname = "127.0.0.1";
|
|
69776
|
-
return parsed.toString();
|
|
69777
|
-
}
|
|
69778
|
-
function parseUrl(raw) {
|
|
69779
|
-
try {
|
|
69780
|
-
return new URL(raw);
|
|
69781
|
-
} catch {
|
|
69782
|
-
throw new AstraleError("INVALID_URL", `Not a valid URL: ${raw}`);
|
|
69783
|
-
}
|
|
69784
|
-
}
|
|
69785
|
-
var VIEW_RESOLVE_PATH = "/:kernel.astrale.ai:class.View:resolve", VIEW_PATH_RE;
|
|
69786
|
-
var init_resolve7 = __esm(() => {
|
|
69787
|
-
init_errors3();
|
|
69788
|
-
VIEW_PATH_RE = /^\/:[^\s/:@]+:view\.[a-z][a-z0-9-]*$/;
|
|
69789
|
-
});
|
|
69790
|
-
|
|
69791
69758
|
// src/lib/view/session.ts
|
|
69792
69759
|
import { mkdir as mkdir9, readdir as readdir2, readFile as readFile10, rm as rm2, writeFile as writeFile8 } from "node:fs/promises";
|
|
69793
69760
|
import { join as join10 } from "node:path";
|
|
@@ -69858,11 +69825,132 @@ var init_session2 = __esm(() => {
|
|
|
69858
69825
|
VIEW_DIR = join10(paths.home, "view");
|
|
69859
69826
|
});
|
|
69860
69827
|
|
|
69861
|
-
// src/lib/view/
|
|
69828
|
+
// src/lib/view/port-allocation.ts
|
|
69829
|
+
import { join as join11 } from "node:path";
|
|
69830
|
+
function withViewPortAllocationLock(fn2, lockPath = VIEW_PORT_LOCK) {
|
|
69831
|
+
return withFileLock(lockPath, fn2);
|
|
69832
|
+
}
|
|
69833
|
+
var VIEW_PORT_LOCK;
|
|
69834
|
+
var init_port_allocation = __esm(() => {
|
|
69835
|
+
init_fs_atomic();
|
|
69836
|
+
init_session2();
|
|
69837
|
+
VIEW_PORT_LOCK = join11(VIEW_DIR, "ports.lock");
|
|
69838
|
+
});
|
|
69839
|
+
|
|
69840
|
+
// src/lib/view/resolve.ts
|
|
69841
|
+
function parseViewSpec(spec) {
|
|
69842
|
+
if (VIEW_PATH_RE.test(spec))
|
|
69843
|
+
return { kind: "view", path: spec };
|
|
69844
|
+
if (spec.startsWith("/") || spec.startsWith("@"))
|
|
69845
|
+
return { kind: "target", path: spec };
|
|
69846
|
+
throw new AstraleError("INVALID_ARGUMENT", `"${spec}" is neither a ViewPath (/:origin:view.slug) nor a node path (/… or @id)`);
|
|
69847
|
+
}
|
|
69848
|
+
async function resolveViewCandidates(ctx, nodePath) {
|
|
69849
|
+
const result = await ctx.client.call(VIEW_RESOLVE_PATH, { node: nodePath });
|
|
69850
|
+
if (!Array.isArray(result)) {
|
|
69851
|
+
throw new AstraleError("UNEXPECTED_RESULT", `View:resolve returned a non-array for ${nodePath}`);
|
|
69852
|
+
}
|
|
69853
|
+
return result;
|
|
69854
|
+
}
|
|
69855
|
+
function candidateSlug(candidate) {
|
|
69856
|
+
const fromPath = candidate.path?.split("/").pop() ?? "";
|
|
69857
|
+
return candidate.name ?? fromPath;
|
|
69858
|
+
}
|
|
69859
|
+
function pickCandidate2(candidates, nodePath, slug) {
|
|
69860
|
+
if (slug) {
|
|
69861
|
+
const match = candidates.find((c) => candidateSlug(c) === slug || c.path.endsWith(`/${slug}`));
|
|
69862
|
+
if (!match) {
|
|
69863
|
+
throw new AstraleError("VIEW_NOT_FOUND", `No view "${slug}" on ${nodePath} — available: ${candidates.map(candidateSlug).join(", ") || "(none)"}`);
|
|
69864
|
+
}
|
|
69865
|
+
return match;
|
|
69866
|
+
}
|
|
69867
|
+
if (candidates.length === 0) {
|
|
69868
|
+
throw new AstraleError("VIEW_NOT_FOUND", `No views resolve on ${nodePath}`);
|
|
69869
|
+
}
|
|
69870
|
+
if (candidates.length === 1)
|
|
69871
|
+
return candidates[0];
|
|
69872
|
+
return "ambiguous";
|
|
69873
|
+
}
|
|
69874
|
+
function applyViewUrlOverride(resolvedUrl, override) {
|
|
69875
|
+
const parsed = parseUrl(override);
|
|
69876
|
+
if (parsed.pathname !== "/")
|
|
69877
|
+
return parsed.toString();
|
|
69878
|
+
const original = parseUrl(resolvedUrl);
|
|
69879
|
+
return new URL(original.pathname + original.search + original.hash, parsed.origin).toString();
|
|
69880
|
+
}
|
|
69881
|
+
function rewriteLocalViewUrl(url2) {
|
|
69882
|
+
const parsed = parseUrl(url2);
|
|
69883
|
+
if (parsed.hostname !== "host.docker.internal")
|
|
69884
|
+
return url2;
|
|
69885
|
+
parsed.hostname = "127.0.0.1";
|
|
69886
|
+
return parsed.toString();
|
|
69887
|
+
}
|
|
69888
|
+
function parseUrl(raw) {
|
|
69889
|
+
try {
|
|
69890
|
+
return new URL(raw);
|
|
69891
|
+
} catch {
|
|
69892
|
+
throw new AstraleError("INVALID_URL", `Not a valid URL: ${raw}`);
|
|
69893
|
+
}
|
|
69894
|
+
}
|
|
69895
|
+
var VIEW_RESOLVE_PATH = "/:kernel.astrale.ai:class.View:resolve", VIEW_PATH_RE;
|
|
69896
|
+
var init_resolve7 = __esm(() => {
|
|
69897
|
+
init_errors3();
|
|
69898
|
+
VIEW_PATH_RE = /^\/:[^\s/:@]+:view\.[a-z][a-z0-9-]*$/;
|
|
69899
|
+
});
|
|
69900
|
+
|
|
69901
|
+
// src/lib/view/assets.ts
|
|
69862
69902
|
import { existsSync as existsSync5 } from "node:fs";
|
|
69903
|
+
import { copyFile as copyFile2 } from "node:fs/promises";
|
|
69904
|
+
import { dirname as dirname8, join as join12 } from "node:path";
|
|
69905
|
+
import { fileURLToPath } from "node:url";
|
|
69906
|
+
function viewerDistDir(moduleUrl = import.meta.url, entry = process.argv[1] ?? ".") {
|
|
69907
|
+
const override = process.env.ASTRALE_VIEWER_DIR;
|
|
69908
|
+
if (override)
|
|
69909
|
+
return override;
|
|
69910
|
+
const moduleDirectory = dirname8(fileURLToPath(moduleUrl));
|
|
69911
|
+
const published = join12(moduleDirectory, "..", "viewer", "dist");
|
|
69912
|
+
const source = join12(moduleDirectory, "..", "..", "..", "viewer", "dist");
|
|
69913
|
+
const legacy = join12(dirname8(entry), "..", "viewer", "dist");
|
|
69914
|
+
const complete = [published, source, legacy].find(hasViewerBundle);
|
|
69915
|
+
if (complete)
|
|
69916
|
+
return complete;
|
|
69917
|
+
if (hasViewerSource(join12(source, "..")))
|
|
69918
|
+
return source;
|
|
69919
|
+
return published;
|
|
69920
|
+
}
|
|
69921
|
+
async function ensureViewerAssets(moduleUrl = import.meta.url, entry = process.argv[1] ?? ".") {
|
|
69922
|
+
const dist = viewerDistDir(moduleUrl, entry);
|
|
69923
|
+
if (hasViewerBundle(dist))
|
|
69924
|
+
return dist;
|
|
69925
|
+
const srcDir = join12(dist, "..");
|
|
69926
|
+
const bun = globalThis.Bun;
|
|
69927
|
+
if (bun && hasViewerSource(srcDir)) {
|
|
69928
|
+
const result = await bun.build({
|
|
69929
|
+
entrypoints: [join12(srcDir, "main.ts")],
|
|
69930
|
+
outdir: dist,
|
|
69931
|
+
target: "browser",
|
|
69932
|
+
minify: false
|
|
69933
|
+
});
|
|
69934
|
+
if (!result.success)
|
|
69935
|
+
throw new Error(`viewer build failed: ${result.logs.join(`
|
|
69936
|
+
`)}`);
|
|
69937
|
+
await copyFile2(join12(srcDir, "index.html"), join12(dist, "index.html"));
|
|
69938
|
+
return dist;
|
|
69939
|
+
}
|
|
69940
|
+
throw new Error(`viewer bundle missing at ${dist} — reinstall the CLI (or run \`bun scripts/build.ts\` in a dev checkout)`);
|
|
69941
|
+
}
|
|
69942
|
+
function hasViewerBundle(directory) {
|
|
69943
|
+
return existsSync5(join12(directory, "main.js")) && existsSync5(join12(directory, "index.html"));
|
|
69944
|
+
}
|
|
69945
|
+
function hasViewerSource(directory) {
|
|
69946
|
+
return existsSync5(join12(directory, "main.ts")) && existsSync5(join12(directory, "index.html"));
|
|
69947
|
+
}
|
|
69948
|
+
var init_assets = () => {};
|
|
69949
|
+
|
|
69950
|
+
// src/lib/view/server.ts
|
|
69863
69951
|
import { readFile as readFile11 } from "node:fs/promises";
|
|
69864
69952
|
import { createServer } from "node:http";
|
|
69865
|
-
import {
|
|
69953
|
+
import { join as join13 } from "node:path";
|
|
69866
69954
|
import { Readable } from "node:stream";
|
|
69867
69955
|
function startViewServer(config2) {
|
|
69868
69956
|
const { session, proxy } = config2;
|
|
@@ -69920,11 +70008,11 @@ function startViewServer(config2) {
|
|
|
69920
70008
|
return;
|
|
69921
70009
|
}
|
|
69922
70010
|
if (sub === "/" || sub === "/index.html") {
|
|
69923
|
-
await serveAsset(res,
|
|
70011
|
+
await serveAsset(res, join13(hostDir, "index.html"), "text/html; charset=utf-8");
|
|
69924
70012
|
return;
|
|
69925
70013
|
}
|
|
69926
70014
|
if (sub === "/main.js") {
|
|
69927
|
-
await serveAsset(res,
|
|
70015
|
+
await serveAsset(res, join13(hostDir, "main.js"), "text/javascript; charset=utf-8");
|
|
69928
70016
|
return;
|
|
69929
70017
|
}
|
|
69930
70018
|
if (sub === "/config.json" && req.method === "GET") {
|
|
@@ -70009,34 +70097,6 @@ function startViewServer(config2) {
|
|
|
70009
70097
|
server.listen(session.port, "127.0.0.1");
|
|
70010
70098
|
return server;
|
|
70011
70099
|
}
|
|
70012
|
-
function viewerDistDir() {
|
|
70013
|
-
const override = process.env.ASTRALE_VIEWER_DIR;
|
|
70014
|
-
if (override)
|
|
70015
|
-
return override;
|
|
70016
|
-
return join11(dirname8(process.argv[1] ?? "."), "..", "viewer", "dist");
|
|
70017
|
-
}
|
|
70018
|
-
async function ensureViewerAssets() {
|
|
70019
|
-
const dist = viewerDistDir();
|
|
70020
|
-
if (existsSync5(join11(dist, "main.js")) && existsSync5(join11(dist, "index.html")))
|
|
70021
|
-
return dist;
|
|
70022
|
-
const srcDir = join11(dist, "..");
|
|
70023
|
-
const bun = globalThis.Bun;
|
|
70024
|
-
if (bun && existsSync5(join11(srcDir, "main.ts"))) {
|
|
70025
|
-
const result = await bun.build({
|
|
70026
|
-
entrypoints: [join11(srcDir, "main.ts")],
|
|
70027
|
-
outdir: dist,
|
|
70028
|
-
target: "browser",
|
|
70029
|
-
minify: false
|
|
70030
|
-
});
|
|
70031
|
-
if (!result.success)
|
|
70032
|
-
throw new Error(`viewer build failed: ${result.logs.join(`
|
|
70033
|
-
`)}`);
|
|
70034
|
-
const { copyFile: copyFile2 } = await import("node:fs/promises");
|
|
70035
|
-
await copyFile2(join11(srcDir, "index.html"), join11(dist, "index.html"));
|
|
70036
|
-
return dist;
|
|
70037
|
-
}
|
|
70038
|
-
throw new Error(`viewer bundle missing at ${dist} — reinstall the CLI (or run \`bun scripts/build.ts\` in a dev checkout)`);
|
|
70039
|
-
}
|
|
70040
70100
|
function jwtExpiry(token) {
|
|
70041
70101
|
try {
|
|
70042
70102
|
const payload = JSON.parse(Buffer.from(token.split(".")[1], "base64url").toString("utf8"));
|
|
@@ -70093,7 +70153,9 @@ var TOKEN_REFRESH_MARGIN_MS, FALLBACK_TOKEN_TTL_MS = 3600000, IDLE_SWEEP_MS = 60
|
|
|
70093
70153
|
var init_server = __esm(() => {
|
|
70094
70154
|
init_kernel2();
|
|
70095
70155
|
init_ca_fetch();
|
|
70156
|
+
init_assets();
|
|
70096
70157
|
init_session2();
|
|
70158
|
+
init_assets();
|
|
70097
70159
|
TOKEN_REFRESH_MARGIN_MS = 5 * 60000;
|
|
70098
70160
|
});
|
|
70099
70161
|
|
|
@@ -70174,7 +70236,7 @@ __export(exports_view, {
|
|
|
70174
70236
|
import { randomBytes } from "node:crypto";
|
|
70175
70237
|
import { closeSync, existsSync as existsSync6, openSync, statSync } from "node:fs";
|
|
70176
70238
|
import { mkdir as mkdir10, readdir as readdir3, readFile as readFile12, writeFile as writeFile9 } from "node:fs/promises";
|
|
70177
|
-
import { dirname as dirname9, join as
|
|
70239
|
+
import { dirname as dirname9, join as join14 } from "node:path";
|
|
70178
70240
|
async function resolveSession(spec, opts) {
|
|
70179
70241
|
const parsed = spec ? parseViewSpec(spec) : undefined;
|
|
70180
70242
|
if (parsed?.kind === "target" && opts.target) {
|
|
@@ -70250,7 +70312,7 @@ async function resolveServeRuntime() {
|
|
|
70250
70312
|
if (node2 && entry?.endsWith(".js") && existsSync6(entry))
|
|
70251
70313
|
return { file: node2, args: [entry] };
|
|
70252
70314
|
if (node2 && entry?.endsWith(".ts")) {
|
|
70253
|
-
const dist =
|
|
70315
|
+
const dist = join14(dirname9(entry), "..", "dist", "astrale.js");
|
|
70254
70316
|
await ensureDevDist(entry, dist);
|
|
70255
70317
|
if (existsSync6(dist))
|
|
70256
70318
|
return { file: node2, args: [dist] };
|
|
@@ -70268,7 +70330,7 @@ async function ensureDevDist(entry, dist) {
|
|
|
70268
70330
|
const bun = globalThis.Bun;
|
|
70269
70331
|
if (!bun)
|
|
70270
70332
|
return;
|
|
70271
|
-
const srcDir =
|
|
70333
|
+
const srcDir = join14(dirname9(entry), "..", "src");
|
|
70272
70334
|
if (existsSync6(dist) && !await newerThan(srcDir, statSync(dist).mtimeMs))
|
|
70273
70335
|
return;
|
|
70274
70336
|
console.error("(dev) building dist/astrale.js for the session server…");
|
|
@@ -70284,7 +70346,7 @@ async function newerThan(dir, mtimeMs) {
|
|
|
70284
70346
|
for (const item of entries) {
|
|
70285
70347
|
if (!item.isFile())
|
|
70286
70348
|
continue;
|
|
70287
|
-
if (statSync(
|
|
70349
|
+
if (statSync(join14(item.parentPath, item.name)).mtimeMs > mtimeMs)
|
|
70288
70350
|
return true;
|
|
70289
70351
|
}
|
|
70290
70352
|
return false;
|
|
@@ -70293,11 +70355,18 @@ async function startSession(view, target, opts) {
|
|
|
70293
70355
|
await ensureViewerAssets();
|
|
70294
70356
|
const config2 = await readConfig();
|
|
70295
70357
|
const kernelTarget = await resolveKernelTarget(opts, config2);
|
|
70358
|
+
const [instances, identities, runtime] = await Promise.all([
|
|
70359
|
+
readInstances(),
|
|
70360
|
+
readIdentities(),
|
|
70361
|
+
resolveServeRuntime()
|
|
70362
|
+
]);
|
|
70363
|
+
return withViewPortAllocationLock(() => startSessionLocked(view, target, opts, kernelTarget, instances.active, identities.default, runtime));
|
|
70364
|
+
}
|
|
70365
|
+
async function startSessionLocked(view, target, opts, kernelTarget, activeInstance, defaultIdentity, runtime) {
|
|
70296
70366
|
const port = await findFreePort(VIEW_PORT_BASE, VIEW_PORT_SPAN);
|
|
70297
70367
|
if (port === null) {
|
|
70298
|
-
|
|
70368
|
+
throw new Error(`No free port in ${VIEW_PORT_BASE}-${VIEW_PORT_BASE + VIEW_PORT_SPAN - 1} — close sessions with \`astrale view --close --all\``);
|
|
70299
70369
|
}
|
|
70300
|
-
const [instances, identities] = await Promise.all([readInstances(), readIdentities()]);
|
|
70301
70370
|
const id = `v-${randomBytes(3).toString("hex")}`;
|
|
70302
70371
|
const nonce = randomBytes(12).toString("hex");
|
|
70303
70372
|
const record2 = {
|
|
@@ -70308,8 +70377,8 @@ async function startSession(view, target, opts) {
|
|
|
70308
70377
|
pageUrl: `http://127.0.0.1:${port}/s/${nonce}/`,
|
|
70309
70378
|
view,
|
|
70310
70379
|
target,
|
|
70311
|
-
instance: opts.instance ?? (opts.url ? opts.url :
|
|
70312
|
-
identity: opts.creds ? "(pre-signed creds)" : opts.as ??
|
|
70380
|
+
instance: opts.instance ?? (opts.url ? opts.url : activeInstance),
|
|
70381
|
+
identity: opts.creds ? "(pre-signed creds)" : opts.as ?? defaultIdentity,
|
|
70313
70382
|
createdAt: new Date().toISOString()
|
|
70314
70383
|
};
|
|
70315
70384
|
const serveConfig = {
|
|
@@ -70331,7 +70400,6 @@ async function startSession(view, target, opts) {
|
|
|
70331
70400
|
await mkdir10(VIEW_DIR, { recursive: true });
|
|
70332
70401
|
await writeFile9(configPath(id), JSON.stringify(serveConfig, null, 2));
|
|
70333
70402
|
const logFd = openSync(logPath(id), "a");
|
|
70334
|
-
const runtime = await resolveServeRuntime();
|
|
70335
70403
|
const child = spawnHandle(runtime.file, [...runtime.args, "__view-serve", "--config", configPath(id)], {
|
|
70336
70404
|
detached: true,
|
|
70337
70405
|
stdio: ["ignore", logFd, logFd]
|
|
@@ -70339,7 +70407,7 @@ async function startSession(view, target, opts) {
|
|
|
70339
70407
|
child.unref();
|
|
70340
70408
|
closeSync(logFd);
|
|
70341
70409
|
if (!child.pid)
|
|
70342
|
-
|
|
70410
|
+
throw new Error("Failed to spawn the view session server");
|
|
70343
70411
|
const live = { ...record2, pid: child.pid };
|
|
70344
70412
|
await saveRecord(live);
|
|
70345
70413
|
const deadline = Date.now() + READY_TIMEOUT_MS;
|
|
@@ -70355,9 +70423,9 @@ async function startSession(view, target, opts) {
|
|
|
70355
70423
|
}
|
|
70356
70424
|
const tail = await readFile12(logPath(id), "utf8").catch(() => "");
|
|
70357
70425
|
await closeSession(live);
|
|
70358
|
-
|
|
70426
|
+
throw new Error(`View session server did not come up.${tail ? `
|
|
70359
70427
|
--- server log ---
|
|
70360
|
-
${tail.slice(-2000)}` : ""}`)
|
|
70428
|
+
${tail.slice(-2000)}` : ""}`);
|
|
70361
70429
|
}
|
|
70362
70430
|
async function waitForPageState(record2) {
|
|
70363
70431
|
const deadline = Date.now() + STATE_TIMEOUT_MS;
|
|
@@ -70502,6 +70570,7 @@ var init_view4 = __esm(() => {
|
|
|
70502
70570
|
init_output();
|
|
70503
70571
|
init_port();
|
|
70504
70572
|
init_proc();
|
|
70573
|
+
init_port_allocation();
|
|
70505
70574
|
init_resolve7();
|
|
70506
70575
|
init_server();
|
|
70507
70576
|
init_session2();
|
|
@@ -70886,28 +70955,28 @@ __export(exports_studio, {
|
|
|
70886
70955
|
default: () => studio_default
|
|
70887
70956
|
});
|
|
70888
70957
|
import { existsSync as existsSync8, realpathSync } from "node:fs";
|
|
70889
|
-
import { dirname as dirname10, join as
|
|
70958
|
+
import { dirname as dirname10, join as join15, resolve } from "node:path";
|
|
70890
70959
|
function resolveStudioDir() {
|
|
70891
70960
|
const candidates = [];
|
|
70892
70961
|
if (process.env.ASTRALE_STUDIO_DIR)
|
|
70893
70962
|
candidates.push(process.env.ASTRALE_STUDIO_DIR);
|
|
70894
70963
|
try {
|
|
70895
70964
|
const entryDir = dirname10(realpathSync(process.argv[1] ?? ""));
|
|
70896
|
-
candidates.push(
|
|
70965
|
+
candidates.push(join15(entryDir, "..", "studio"), join15(entryDir, "studio"));
|
|
70897
70966
|
} catch {}
|
|
70898
70967
|
for (const c of candidates) {
|
|
70899
|
-
if (existsSync8(
|
|
70968
|
+
if (existsSync8(join15(c, "server", "index.ts")))
|
|
70900
70969
|
return resolve(c);
|
|
70901
70970
|
}
|
|
70902
70971
|
throw new Error(`Domain Studio assets not found (looked in: ${candidates.join(", ") || "<none>"}). ` + `Reinstall the astrale CLI, or set ASTRALE_STUDIO_DIR to a studio checkout.`);
|
|
70903
70972
|
}
|
|
70904
70973
|
function isDevSource(studioDir) {
|
|
70905
|
-
return existsSync8(
|
|
70974
|
+
return existsSync8(join15(studioDir, "vite.config.ts")) && existsSync8(join15(studioDir, "client", "src"));
|
|
70906
70975
|
}
|
|
70907
70976
|
function resolveViteBin(studioDir) {
|
|
70908
70977
|
for (const c of [
|
|
70909
|
-
|
|
70910
|
-
|
|
70978
|
+
join15(studioDir, "node_modules", ".bin", "vite"),
|
|
70979
|
+
join15(studioDir, "..", "..", "node_modules", ".bin", "vite")
|
|
70911
70980
|
]) {
|
|
70912
70981
|
if (existsSync8(c))
|
|
70913
70982
|
return c;
|
|
@@ -70982,6 +71051,11 @@ var init_studio = __esm(() => {
|
|
|
70982
71051
|
},
|
|
70983
71052
|
{ flags: "--prod", description: "Serve the prebuilt client (the default)" },
|
|
70984
71053
|
{ flags: "--schema-dir <dir>", description: "Schema entry dir to scan for (default: schema)" },
|
|
71054
|
+
{
|
|
71055
|
+
flags: "--harness <name>",
|
|
71056
|
+
description: "Lock the agent harness for this Studio process",
|
|
71057
|
+
choices: ["claude", "codex"]
|
|
71058
|
+
},
|
|
70985
71059
|
...RAW_OUTPUT_OPTIONS
|
|
70986
71060
|
],
|
|
70987
71061
|
afterHelpText: `
|
|
@@ -71005,6 +71079,10 @@ Behavior:
|
|
|
71005
71079
|
By default the command just PRINTS the URL — it does not pop a browser (that's
|
|
71006
71080
|
invasive when you already have a tab open). Pass --open to launch one.
|
|
71007
71081
|
|
|
71082
|
+
Agent harness: choose Claude Code or Codex per domain in Studio Settings. Pass
|
|
71083
|
+
--harness claude|codex to lock this process to one harness. Each harness uses
|
|
71084
|
+
its existing local authentication and keeps an independent resumable session.
|
|
71085
|
+
|
|
71008
71086
|
The command stays attached and supervises its child processes; Ctrl-C tears
|
|
71009
71087
|
them all down (a second Ctrl-C force-kills). With --json it prints a
|
|
71010
71088
|
{ url, port, mode, workspace } descriptor.
|
|
@@ -71013,6 +71091,7 @@ Examples:
|
|
|
71013
71091
|
$ astrale studio # start the studio + print its URL (no browser)
|
|
71014
71092
|
$ astrale studio --open # …and open it in a browser
|
|
71015
71093
|
$ astrale studio ./my-domain
|
|
71094
|
+
$ astrale studio --harness codex
|
|
71016
71095
|
$ astrale studio --port 4400
|
|
71017
71096
|
$ astrale studio --dev # live-edit the studio itself (from source)
|
|
71018
71097
|
`,
|
|
@@ -71115,12 +71194,13 @@ Examples:
|
|
|
71115
71194
|
DOMAIN_STUDIO_DEV: "1",
|
|
71116
71195
|
VITE_URL: `http://127.0.0.1:${vitePort}`,
|
|
71117
71196
|
PORT: String(studioPort),
|
|
71118
|
-
DOMAIN_STUDIO_HOST: "127.0.0.1"
|
|
71197
|
+
DOMAIN_STUDIO_HOST: "127.0.0.1",
|
|
71198
|
+
...opts.harness ? { DOMAIN_STUDIO_HARNESS: opts.harness } : {}
|
|
71119
71199
|
}
|
|
71120
71200
|
}), "server");
|
|
71121
71201
|
} else {
|
|
71122
|
-
const dist =
|
|
71123
|
-
if (!existsSync8(
|
|
71202
|
+
const dist = join15(studioDir, "client", "dist");
|
|
71203
|
+
if (!existsSync8(join15(dist, "index.html"))) {
|
|
71124
71204
|
throw new Error(`studio client not built at ${dist} — run: pnpm --filter @astrale-os/studio build`);
|
|
71125
71205
|
}
|
|
71126
71206
|
serverChild = supervise(spawnHandle("bun", ["server/index.ts", workspace, "--port", String(studioPort), "--no-open"], {
|
|
@@ -71130,7 +71210,8 @@ Examples:
|
|
|
71130
71210
|
...process.env,
|
|
71131
71211
|
DOMAIN_STUDIO_DIST: dist,
|
|
71132
71212
|
PORT: String(studioPort),
|
|
71133
|
-
DOMAIN_STUDIO_HOST: "127.0.0.1"
|
|
71213
|
+
DOMAIN_STUDIO_HOST: "127.0.0.1",
|
|
71214
|
+
...opts.harness ? { DOMAIN_STUDIO_HARNESS: opts.harness } : {}
|
|
71134
71215
|
}
|
|
71135
71216
|
}), "server");
|
|
71136
71217
|
}
|
|
@@ -71242,7 +71323,7 @@ var init_list = __esm(() => {
|
|
|
71242
71323
|
}));
|
|
71243
71324
|
let managed = [];
|
|
71244
71325
|
if (!opts.bookmarked) {
|
|
71245
|
-
managed = await withSpinner("Fetching instances", !isMachine(opts), () =>
|
|
71326
|
+
managed = await withSpinner("Fetching instances", !isMachine(opts), () => listOwnedInstances(opts));
|
|
71246
71327
|
}
|
|
71247
71328
|
if (isMachine(opts)) {
|
|
71248
71329
|
output({
|
|
@@ -71499,6 +71580,7 @@ __export(exports_status2, {
|
|
|
71499
71580
|
var status_default2;
|
|
71500
71581
|
var init_status2 = __esm(() => {
|
|
71501
71582
|
init_source();
|
|
71583
|
+
init_errors3();
|
|
71502
71584
|
init_client2();
|
|
71503
71585
|
init_admin_target();
|
|
71504
71586
|
init_log();
|
|
@@ -71510,20 +71592,26 @@ var init_status2 = __esm(() => {
|
|
|
71510
71592
|
options: [...ADMIN_TARGET_OPTIONS],
|
|
71511
71593
|
action: async (id, opts) => {
|
|
71512
71594
|
try {
|
|
71513
|
-
const result = await withSpinner(`Fetching instance ${id}`, !isMachine(opts), () =>
|
|
71595
|
+
const result = await withSpinner(`Fetching instance ${id}`, !isMachine(opts), () => listOwnedInstances(opts).then((instances) => {
|
|
71596
|
+
const match = findOwnedInstance(instances, id);
|
|
71597
|
+
if (match)
|
|
71598
|
+
return match;
|
|
71599
|
+
throw new AstraleError("INSTANCE_NOT_FOUND", `No owned instance matches "${id}".`, "Run `astrale instance list` to see your instances.");
|
|
71600
|
+
}));
|
|
71514
71601
|
if (isMachine(opts)) {
|
|
71515
71602
|
output(result, opts);
|
|
71516
71603
|
return;
|
|
71517
71604
|
}
|
|
71518
71605
|
console.log(`${source_default.bold(result.slug)} ${source_default.dim(result.url)}`);
|
|
71519
|
-
|
|
71520
|
-
log.dim(` state: ${result.state}${result.phase ? ` (${result.phase})` : ""}`);
|
|
71606
|
+
log.dim(` state: ${result.state}${result.phase ? ` (${result.phase})` : ""}`);
|
|
71521
71607
|
if (result.error)
|
|
71522
71608
|
log.dim(` error: ${result.error}`);
|
|
71523
71609
|
if (result.region)
|
|
71524
71610
|
log.dim(` region: ${result.region}`);
|
|
71525
71611
|
if (result.hostId)
|
|
71526
71612
|
log.dim(` host: ${result.hostId}`);
|
|
71613
|
+
if (result.organizationId)
|
|
71614
|
+
log.dim(` organization: ${result.organizationId}`);
|
|
71527
71615
|
if (result.createdAt)
|
|
71528
71616
|
log.dim(` created: ${result.createdAt}`);
|
|
71529
71617
|
} catch (e) {
|
|
@@ -71548,7 +71636,9 @@ async function resolveActiveForDisplay() {
|
|
|
71548
71636
|
};
|
|
71549
71637
|
}
|
|
71550
71638
|
try {
|
|
71551
|
-
const managed = await
|
|
71639
|
+
const managed = findOwnedInstance(await listOwnedInstances({}), active.name);
|
|
71640
|
+
if (!managed)
|
|
71641
|
+
return { name: active.name };
|
|
71552
71642
|
return {
|
|
71553
71643
|
name: managed.slug,
|
|
71554
71644
|
url: normalizeInstanceKernelUrl(managed.url),
|
|
@@ -71834,7 +71924,7 @@ async function installViaAdmin(target, opts) {
|
|
|
71834
71924
|
const adminOpts = { ...opts, instance: undefined };
|
|
71835
71925
|
try {
|
|
71836
71926
|
await withAdminKernelClient(adminOpts, async (ctx) => {
|
|
71837
|
-
const instances = await ctx.client
|
|
71927
|
+
const instances = await callOwnedInstances(ctx.client);
|
|
71838
71928
|
const ref2 = await resolveDomainRef(ctx, target, interactive);
|
|
71839
71929
|
const slug = await resolveTargetSlug(opts, target, interactive, instances);
|
|
71840
71930
|
const match = instances.find((i) => i.slug === slug);
|
|
@@ -71842,6 +71932,7 @@ async function installViaAdmin(target, opts) {
|
|
|
71842
71932
|
const known = instances.map((i) => i.slug).join(", ") || "(none)";
|
|
71843
71933
|
throw new AstraleError("INSTANCE_NOT_MANAGED", `Instance "${slug}" is not admin-managed (managed: ${known}).`, `Install the url directly onto it instead: astrale domain install <url> --direct -i ${slug}`);
|
|
71844
71934
|
}
|
|
71935
|
+
assertInstallTargetReady(match);
|
|
71845
71936
|
const label = ref2.origin ?? ref2.url ?? "domain";
|
|
71846
71937
|
const result = await withSpinner(`Installing ${label} on ${match.slug}`, !isMachine(opts), () => ctx.client.call(adminDomainMethod("install"), {
|
|
71847
71938
|
instanceId: match.slug,
|
|
@@ -71858,9 +71949,15 @@ async function installViaAdmin(target, opts) {
|
|
|
71858
71949
|
log.dim(` url: ${result.url}`);
|
|
71859
71950
|
});
|
|
71860
71951
|
} catch (e) {
|
|
71861
|
-
fatal(e);
|
|
71952
|
+
fatal(e, opts);
|
|
71862
71953
|
}
|
|
71863
71954
|
}
|
|
71955
|
+
function assertInstallTargetReady(instance) {
|
|
71956
|
+
if (instance.state === "ready")
|
|
71957
|
+
return;
|
|
71958
|
+
const detail = instance.phase && instance.phase !== instance.state ? ` (${instance.phase})` : "";
|
|
71959
|
+
throw new AstraleError("INSTANCE_NOT_READY", `Instance "${instance.slug}" is ${instance.state}${detail}; domains cannot be installed yet.`, instance.error ?? `Run: astrale instance status ${instance.slug}`);
|
|
71960
|
+
}
|
|
71864
71961
|
function domainRefFromTarget(target) {
|
|
71865
71962
|
return isHttpUrl(target) ? { url: target } : { origin: target };
|
|
71866
71963
|
}
|
|
@@ -72959,21 +73056,21 @@ var init_status4 = __esm(() => {
|
|
|
72959
73056
|
|
|
72960
73057
|
// src/telemetry/store.ts
|
|
72961
73058
|
import { existsSync as existsSync9, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync2 } from "node:fs";
|
|
72962
|
-
import { join as
|
|
73059
|
+
import { join as join16 } from "node:path";
|
|
72963
73060
|
function sessionsRoot() {
|
|
72964
|
-
return
|
|
73061
|
+
return join16(createPaths().home, "sessions");
|
|
72965
73062
|
}
|
|
72966
73063
|
function sessionDir(id) {
|
|
72967
|
-
return
|
|
73064
|
+
return join16(sessionsRoot(), id);
|
|
72968
73065
|
}
|
|
72969
73066
|
function eventsPath(id) {
|
|
72970
|
-
return
|
|
73067
|
+
return join16(sessionDir(id), "events.jsonl");
|
|
72971
73068
|
}
|
|
72972
73069
|
function metaPath(id) {
|
|
72973
|
-
return
|
|
73070
|
+
return join16(sessionDir(id), "meta.json");
|
|
72974
73071
|
}
|
|
72975
73072
|
function markerPath(id) {
|
|
72976
|
-
return
|
|
73073
|
+
return join16(sessionDir(id), ".analyzed");
|
|
72977
73074
|
}
|
|
72978
73075
|
function readJsonSafe(path4) {
|
|
72979
73076
|
try {
|
|
@@ -73051,12 +73148,12 @@ var init_list4 = __esm(() => {
|
|
|
73051
73148
|
// src/telemetry/adapters/claude-code.ts
|
|
73052
73149
|
import { existsSync as existsSync10, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
|
|
73053
73150
|
import { homedir as homedir3 } from "node:os";
|
|
73054
|
-
import { join as
|
|
73151
|
+
import { join as join17 } from "node:path";
|
|
73055
73152
|
function mungeCwd(cwd) {
|
|
73056
73153
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
73057
73154
|
}
|
|
73058
|
-
function claudeCodeAdapter(base2 =
|
|
73059
|
-
const projectsDir =
|
|
73155
|
+
function claudeCodeAdapter(base2 = join17(homedir3(), ".claude")) {
|
|
73156
|
+
const projectsDir = join17(base2, "projects");
|
|
73060
73157
|
function detect2() {
|
|
73061
73158
|
try {
|
|
73062
73159
|
return existsSync10(projectsDir);
|
|
@@ -73080,7 +73177,7 @@ function claudeCodeAdapter(base2 = join15(homedir3(), ".claude")) {
|
|
|
73080
73177
|
for (const dir of dirs) {
|
|
73081
73178
|
if (dir !== munged && !dir.startsWith(prefix))
|
|
73082
73179
|
continue;
|
|
73083
|
-
const projectPath =
|
|
73180
|
+
const projectPath = join17(projectsDir, dir);
|
|
73084
73181
|
let files;
|
|
73085
73182
|
try {
|
|
73086
73183
|
files = readdirSync3(projectPath);
|
|
@@ -73090,7 +73187,7 @@ function claudeCodeAdapter(base2 = join15(homedir3(), ".claude")) {
|
|
|
73090
73187
|
for (const file2 of files) {
|
|
73091
73188
|
if (!file2.endsWith(".jsonl"))
|
|
73092
73189
|
continue;
|
|
73093
|
-
const transcriptPath =
|
|
73190
|
+
const transcriptPath = join17(projectPath, file2);
|
|
73094
73191
|
try {
|
|
73095
73192
|
const st = statSync3(transcriptPath);
|
|
73096
73193
|
const mtimeMs = st.mtime.getTime();
|
|
@@ -73126,7 +73223,7 @@ var init_claude_code = __esm(() => {
|
|
|
73126
73223
|
import { existsSync as existsSync11, openSync as openSync2, readdirSync as readdirSync4, readSync, statSync as statSync4 } from "node:fs";
|
|
73127
73224
|
import { closeSync as closeSync2 } from "node:fs";
|
|
73128
73225
|
import { homedir as homedir4 } from "node:os";
|
|
73129
|
-
import { join as
|
|
73226
|
+
import { join as join18 } from "node:path";
|
|
73130
73227
|
function readFirstLine(path4) {
|
|
73131
73228
|
let fd = null;
|
|
73132
73229
|
try {
|
|
@@ -73166,8 +73263,8 @@ function numericDirs(path4) {
|
|
|
73166
73263
|
return [];
|
|
73167
73264
|
}
|
|
73168
73265
|
}
|
|
73169
|
-
function codexAdapter(base2 =
|
|
73170
|
-
const sessionsDir =
|
|
73266
|
+
function codexAdapter(base2 = join18(homedir4(), ".codex")) {
|
|
73267
|
+
const sessionsDir = join18(base2, "sessions");
|
|
73171
73268
|
function detect2() {
|
|
73172
73269
|
try {
|
|
73173
73270
|
return existsSync11(sessionsDir);
|
|
@@ -73182,12 +73279,12 @@ function codexAdapter(base2 = join16(homedir4(), ".codex")) {
|
|
|
73182
73279
|
const endMs = window2.end.getTime();
|
|
73183
73280
|
const lowerMs = startMs - DAY_MS;
|
|
73184
73281
|
for (const yyyy of numericDirs(sessionsDir)) {
|
|
73185
|
-
for (const mm of numericDirs(
|
|
73186
|
-
for (const dd of numericDirs(
|
|
73282
|
+
for (const mm of numericDirs(join18(sessionsDir, yyyy))) {
|
|
73283
|
+
for (const dd of numericDirs(join18(sessionsDir, yyyy, mm))) {
|
|
73187
73284
|
const dayStart = Date.UTC(Number(yyyy), Number(mm) - 1, Number(dd));
|
|
73188
73285
|
if (dayStart > endMs + DAY_MS || dayStart + DAY_MS <= lowerMs)
|
|
73189
73286
|
continue;
|
|
73190
|
-
scanDay(
|
|
73287
|
+
scanDay(join18(sessionsDir, yyyy, mm, dd), root, startMs, endMs, sessions);
|
|
73191
73288
|
}
|
|
73192
73289
|
}
|
|
73193
73290
|
}
|
|
@@ -73209,7 +73306,7 @@ function scanDay(dayPath, root, startMs, endMs, out) {
|
|
|
73209
73306
|
for (const file2 of files) {
|
|
73210
73307
|
if (!file2.startsWith("rollout-") || !file2.endsWith(".jsonl"))
|
|
73211
73308
|
continue;
|
|
73212
|
-
const transcriptPath =
|
|
73309
|
+
const transcriptPath = join18(dayPath, file2);
|
|
73213
73310
|
try {
|
|
73214
73311
|
const st = statSync4(transcriptPath);
|
|
73215
73312
|
const mtimeMs = st.mtime.getTime();
|
|
@@ -73356,7 +73453,7 @@ var init_gate = () => {};
|
|
|
73356
73453
|
// src/telemetry/analyze.ts
|
|
73357
73454
|
import { spawn as spawn3 } from "node:child_process";
|
|
73358
73455
|
import { appendFileSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
73359
|
-
import { join as
|
|
73456
|
+
import { join as join19 } from "node:path";
|
|
73360
73457
|
function writeMarker(id, marker) {
|
|
73361
73458
|
writeFileSync2(markerPath(id), JSON.stringify(marker, null, 2) + `
|
|
73362
73459
|
`);
|
|
@@ -73452,7 +73549,7 @@ async function analyzeSession(id, opts = {}) {
|
|
|
73452
73549
|
const guides = new Map(adapters.map((a) => [a.name, a.readingGuide]));
|
|
73453
73550
|
const prompt = buildPrompt({ id, root, signals: signals2, guides, file: opts.file ?? false });
|
|
73454
73551
|
const dir = sessionDir(id);
|
|
73455
|
-
writeFileSync2(
|
|
73552
|
+
writeFileSync2(join19(dir, "analyzer-prompt.md"), prompt);
|
|
73456
73553
|
const outcome = await runClaude(prompt, dir, opts);
|
|
73457
73554
|
const marker = {
|
|
73458
73555
|
analyzedAt: new Date().toISOString(),
|
|
@@ -73460,7 +73557,7 @@ async function analyzeSession(id, opts = {}) {
|
|
|
73460
73557
|
note: outcome.note
|
|
73461
73558
|
};
|
|
73462
73559
|
writeMarker(id, marker);
|
|
73463
|
-
return { ...marker, reportPath:
|
|
73560
|
+
return { ...marker, reportPath: join19(dir, "report.md") };
|
|
73464
73561
|
}
|
|
73465
73562
|
function runClaude(prompt, cwd, opts) {
|
|
73466
73563
|
return new Promise((resolve2) => {
|
|
@@ -73490,7 +73587,7 @@ function runClaude(prompt, cwd, opts) {
|
|
|
73490
73587
|
child.on("close", (code) => {
|
|
73491
73588
|
clearTimeout(timer);
|
|
73492
73589
|
try {
|
|
73493
|
-
appendFileSync(
|
|
73590
|
+
appendFileSync(join19(cwd, "analyzer.log"), out + (err ? `
|
|
73494
73591
|
--- stderr ---
|
|
73495
73592
|
${err}` : ""));
|
|
73496
73593
|
} catch {}
|
|
@@ -73540,9 +73637,9 @@ var init_settings = __esm(() => {
|
|
|
73540
73637
|
|
|
73541
73638
|
// src/telemetry/trigger.ts
|
|
73542
73639
|
import { existsSync as existsSync12, mkdirSync as mkdirSync2, readFileSync as readFileSync6, rmSync as rmSync2, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
73543
|
-
import { join as
|
|
73640
|
+
import { join as join20 } from "node:path";
|
|
73544
73641
|
function lockPath() {
|
|
73545
|
-
return
|
|
73642
|
+
return join20(sessionsRoot(), ".analyzer.lock");
|
|
73546
73643
|
}
|
|
73547
73644
|
function releaseLock() {
|
|
73548
73645
|
try {
|
|
@@ -74301,12 +74398,12 @@ function redactArgv(argv) {
|
|
|
74301
74398
|
init_store2();
|
|
74302
74399
|
import { createHash as createHash2 } from "node:crypto";
|
|
74303
74400
|
import { existsSync as existsSync13, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
74304
|
-
import { dirname as dirname12, join as
|
|
74401
|
+
import { dirname as dirname12, join as join21 } from "node:path";
|
|
74305
74402
|
var MAX_ID_LEN = 64;
|
|
74306
74403
|
function findGitRoot(start) {
|
|
74307
74404
|
let dir = start;
|
|
74308
74405
|
for (;; ) {
|
|
74309
|
-
if (existsSync13(
|
|
74406
|
+
if (existsSync13(join21(dir, ".git")))
|
|
74310
74407
|
return dir;
|
|
74311
74408
|
const parent = dirname12(dir);
|
|
74312
74409
|
if (parent === dir)
|
|
@@ -74407,7 +74504,7 @@ init_settings();
|
|
|
74407
74504
|
init_store2();
|
|
74408
74505
|
import { spawn as spawn4 } from "node:child_process";
|
|
74409
74506
|
import { existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync as rmSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
74410
|
-
import { join as
|
|
74507
|
+
import { join as join22 } from "node:path";
|
|
74411
74508
|
var LOCK_STALE_MS2 = 30 * 60 * 1000;
|
|
74412
74509
|
var GC_AGE_MS2 = 30 * 24 * 60 * 60 * 1000;
|
|
74413
74510
|
var GC_MAX_PER_RUN = 20;
|
|
@@ -74426,7 +74523,7 @@ function gcOldSessions(sessions) {
|
|
|
74426
74523
|
} catch {}
|
|
74427
74524
|
}
|
|
74428
74525
|
function lockPath2() {
|
|
74429
|
-
return
|
|
74526
|
+
return join22(sessionsRoot(), ".analyzer.lock");
|
|
74430
74527
|
}
|
|
74431
74528
|
function claimLock() {
|
|
74432
74529
|
const path4 = lockPath2();
|