archymedes-cli 2.6.0 → 3.1.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/bin/archymedes.mjs +64 -0
- package/bin/launcher.d.mts +21 -0
- package/bin/launcher.mjs +54 -0
- package/dist/{archymedes-06fh0z84.mjs → archymedes-95xvcvww.mjs} +1 -4
- package/dist/archymedes-main.mjs +11830 -18495
- package/dist/{archymedes-w4bjfye7.mjs → archymedes-qm9bwbe7.mjs} +2 -2
- package/dist/{factory-hyv8agr0.mjs → factory-8xk6y60m.mjs} +1 -1
- package/dist/{projection-x6x6hm9t.mjs → projection-4jjdaf41.mjs} +1 -1
- package/package.json +9 -7
- package/dist/archymedes-086xsz64.mjs +0 -1119
- package/dist/archymedes-1jcn326m.mjs +0 -240
- package/dist/archymedes-kn6wtq32.mjs +0 -1169
- package/dist/archymedes-s4qcy0q4.mjs +0 -1250
- package/dist/archymedes-t1jtzkmp.mjs +0 -465
- package/dist/archymedes-twanftqk.mjs +0 -144
- package/dist/archymedes-zvcs68bv.mjs +0 -325
- package/dist/editor-screen-pf252j2r.mjs +0 -684
- package/dist/file-screen-1j65f7b4.mjs +0 -322
- package/dist/guide-screen-9vxsk83x.mjs +0 -273
- package/dist/pager-screen-aamt6xv0.mjs +0 -155
- package/dist/workspace-screen-ntdcgfq9.mjs +0 -70
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// The `archymedes` command, as npm installs it.
|
|
3
|
+
//
|
|
4
|
+
// The interface is a Go binary, shipped per platform as an optional dependency
|
|
5
|
+
// (@archymedes/cli-<platform>-<arch>); launcher.mjs decides whether it is usable. The agent behind
|
|
6
|
+
// it is the bundled dist/archymedes.mjs, run with this same Node: the binary is told where it is
|
|
7
|
+
// through ARCHYMEDES_AGENT, as a JSON array so an install path with spaces survives.
|
|
8
|
+
//
|
|
9
|
+
// Where the binary cannot be used, the bundled agent runs alone: every non-interactive mode works as
|
|
10
|
+
// before, and asked for the interface it says why there is none and how to get it.
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import { existsSync } from "node:fs";
|
|
13
|
+
import { createRequire } from "node:module";
|
|
14
|
+
import path from "node:path";
|
|
15
|
+
import { missingInterfaceNotice, resolveInterface } from "./launcher.mjs";
|
|
16
|
+
|
|
17
|
+
const require = createRequire(import.meta.url);
|
|
18
|
+
const agentEntry = path.join(import.meta.dirname, "..", "dist", "archymedes.mjs");
|
|
19
|
+
const { platform, arch } = process;
|
|
20
|
+
|
|
21
|
+
function packageDirectory(name) {
|
|
22
|
+
try {
|
|
23
|
+
return path.dirname(require.resolve(`${name}/package.json`));
|
|
24
|
+
} catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async function runAgentAlone(resolution) {
|
|
30
|
+
// Read by the agent when it is asked for an interface it does not have (src/archymedes.ts).
|
|
31
|
+
process.env.ARCHYMEDES_INTERFACE_MISSING = missingInterfaceNotice(resolution, platform, arch).join("\n");
|
|
32
|
+
await import(agentEntry);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const resolution = resolveInterface({
|
|
36
|
+
platform, arch, override: process.env.ARCHYMEDES_GO_BINARY,
|
|
37
|
+
resolvePackage: packageDirectory, exists: existsSync, join: path.join,
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
if (!("binary" in resolution)) {
|
|
41
|
+
await runAgentAlone(resolution);
|
|
42
|
+
} else {
|
|
43
|
+
const env = { ...process.env, ARCHYMEDES_AGENT: process.env.ARCHYMEDES_AGENT || JSON.stringify([process.execPath, agentEntry]) };
|
|
44
|
+
const child = spawn(resolution.binary, process.argv.slice(2), { stdio: "inherit", env });
|
|
45
|
+
|
|
46
|
+
// The terminal sends Ctrl+C and Ctrl+\ to the whole process group, so the interface already has
|
|
47
|
+
// them and decides what they mean (stop a turn, not quit). This process only waits. A signal
|
|
48
|
+
// aimed at this process alone is passed on.
|
|
49
|
+
for (const signal of ["SIGINT", "SIGQUIT"]) process.on(signal, () => {});
|
|
50
|
+
for (const signal of ["SIGTERM", "SIGHUP"]) process.on(signal, () => child.kill(signal));
|
|
51
|
+
|
|
52
|
+
child.on("error", (error) => {
|
|
53
|
+
// Present but not runnable: a stripped executable bit, a foreign architecture under emulation.
|
|
54
|
+
void runAgentAlone({ reason: "start-failed", detail: error.code ?? error.message });
|
|
55
|
+
});
|
|
56
|
+
child.on("exit", (code, signal) => {
|
|
57
|
+
if (signal) {
|
|
58
|
+
process.removeAllListeners(signal);
|
|
59
|
+
process.kill(process.pid, signal);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
process.exit(code ?? 1);
|
|
63
|
+
});
|
|
64
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const PUBLISHED_PLATFORMS: readonly string[];
|
|
2
|
+
export declare function interfacePackage(platform: string, arch: string): string;
|
|
3
|
+
|
|
4
|
+
export type Resolution =
|
|
5
|
+
| { binary: string }
|
|
6
|
+
| { reason: "unsupported" | "not-installed" | "missing-binary"; packageName: string };
|
|
7
|
+
|
|
8
|
+
export declare function resolveInterface(options: {
|
|
9
|
+
platform: string;
|
|
10
|
+
arch: string;
|
|
11
|
+
override?: string;
|
|
12
|
+
resolvePackage: (name: string) => string | undefined;
|
|
13
|
+
exists: (path: string) => boolean;
|
|
14
|
+
join: (...parts: string[]) => string;
|
|
15
|
+
}): Resolution;
|
|
16
|
+
|
|
17
|
+
export declare function missingInterfaceNotice(
|
|
18
|
+
resolution: Resolution | { reason: "start-failed"; detail: string },
|
|
19
|
+
platform: string,
|
|
20
|
+
arch: string,
|
|
21
|
+
): string[];
|
package/bin/launcher.mjs
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// What `archymedes` runs, decided before anything is drawn: the Go interface for this platform, or
|
|
2
|
+
// — where it cannot be used — the bundled agent alone, which still serves every non-interactive mode. Pure apart from the lookups passed in, so
|
|
3
|
+
// every outcome is testable without installing anything (tooling/build/launcher.test.ts).
|
|
4
|
+
|
|
5
|
+
/** The platforms a Go interface is published for, as `${process.platform}-${process.arch}`. */
|
|
6
|
+
export const PUBLISHED_PLATFORMS = ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64", "win32-arm64", "win32-x64"];
|
|
7
|
+
|
|
8
|
+
export const interfacePackage = (platform, arch) => `@archymedes/cli-${platform}-${arch}`;
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* @param {{ platform: string, arch: string, override?: string,
|
|
12
|
+
* resolvePackage: (name: string) => string | undefined,
|
|
13
|
+
* exists: (path: string) => boolean,
|
|
14
|
+
* join: (...parts: string[]) => string }} options
|
|
15
|
+
* @returns {{ binary: string } | { reason: "unsupported" | "not-installed" | "missing-binary", packageName: string }}
|
|
16
|
+
*/
|
|
17
|
+
export function resolveInterface({ platform, arch, override, resolvePackage, exists, join }) {
|
|
18
|
+
if (override) return { binary: override };
|
|
19
|
+
const packageName = interfacePackage(platform, arch);
|
|
20
|
+
if (!PUBLISHED_PLATFORMS.includes(`${platform}-${arch}`)) return { reason: "unsupported", packageName };
|
|
21
|
+
// resolvePackage returns the package's directory, or undefined when npm did not install it.
|
|
22
|
+
const directory = resolvePackage(packageName);
|
|
23
|
+
if (!directory) return { reason: "not-installed", packageName };
|
|
24
|
+
const binary = join(directory, "bin", platform === "win32" ? "archymedes.exe" : "archymedes");
|
|
25
|
+
return exists(binary) ? { binary } : { reason: "missing-binary", packageName };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Why there is no interactive interface, the one command that fixes it, and what still works.
|
|
30
|
+
*
|
|
31
|
+
* The bundled agent shows it only when someone asks it for the interface (no request): a one-shot
|
|
32
|
+
* run, `--json` or `settings` work the same with or without the binary, so they say nothing.
|
|
33
|
+
*/
|
|
34
|
+
export function missingInterfaceNotice(resolution, platform, arch) {
|
|
35
|
+
const reinstall = "npm install -g archymedes-cli@latest";
|
|
36
|
+
const works = ` Without it, only non-interactive modes work: archymedes "your request", --json, settings, history, doctor, update.`;
|
|
37
|
+
switch (resolution.reason) {
|
|
38
|
+
case "unsupported":
|
|
39
|
+
return [`archymedes: no interactive interface is published for ${platform}-${arch}.`, works];
|
|
40
|
+
case "not-installed":
|
|
41
|
+
return [
|
|
42
|
+
`archymedes: the interactive interface (${resolution.packageName}) was not installed.`,
|
|
43
|
+
` npm skips it when optional dependencies are off, or when the install ran before it reached the registry.`,
|
|
44
|
+
` Fix: ${reinstall}`,
|
|
45
|
+
works,
|
|
46
|
+
];
|
|
47
|
+
case "missing-binary":
|
|
48
|
+
return [`archymedes: ${resolution.packageName} is installed without its binary.`, ` Fix: ${reinstall}`, works];
|
|
49
|
+
case "start-failed":
|
|
50
|
+
return [`archymedes: the interactive interface could not start (${resolution.detail}).`, ` Fix: ${reinstall}`, works];
|
|
51
|
+
default:
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -8995,9 +8995,6 @@ function isWanderObjective(objective) {
|
|
|
8995
8995
|
function isWanderRandomScheduleObjective(objective) {
|
|
8996
8996
|
return /^\[Wander\]\s+cadence=(daily|weekly)\s+topic=random\s*$/i.test(objective.trim());
|
|
8997
8997
|
}
|
|
8998
|
-
function buildWanderScheduleObjective(cadence) {
|
|
8999
|
-
return `${WANDER_MARKER} cadence=${cadence} topic=random`;
|
|
9000
|
-
}
|
|
9001
8998
|
function pickWanderTopic(seed = `${Date.now()}`) {
|
|
9002
8999
|
let hash = 2166136261;
|
|
9003
9000
|
for (let index2 = 0;index2 < seed.length; index2 += 1) {
|
|
@@ -9071,4 +9068,4 @@ function wanderGradeCounts(results) {
|
|
|
9071
9068
|
return WANDER_GRADES.map((grade) => ({ grade, count: results.claims.filter((claim) => claim.grade === grade).length }));
|
|
9072
9069
|
}
|
|
9073
9070
|
|
|
9074
|
-
export { approximateInputTokens, newPartTotals, addPart, tokenEstimateFrom, affordableOutputTokensFor, affordableOutputTokens, priceActualModelUsage, modelPricesFromEnvironment, TASK_KINDS, buildTaskProfile, mergeRoutingReceipts, capabilitiesFor, DEFAULT_OUTPUT_CEILING, PROTOCOL_MAX_OUTPUT_TOKENS, DEFAULT_TOTAL_TIMEOUT_MS, StreamTimeoutError, streamTimeoutsFor, createStreamDeadline, APIConnectionError, makeParseableTextFormat, OpenAI, toWireMessages, withOpenRouterCacheControl, turnFromChatResponse, collectChatStream, OpenAIAgentTurnProvider, WANDER_MARKER, WANDER_LAB_FILES, isWanderObjective, isWanderRandomScheduleObjective,
|
|
9071
|
+
export { approximateInputTokens, newPartTotals, addPart, tokenEstimateFrom, affordableOutputTokensFor, affordableOutputTokens, priceActualModelUsage, modelPricesFromEnvironment, TASK_KINDS, buildTaskProfile, mergeRoutingReceipts, capabilitiesFor, DEFAULT_OUTPUT_CEILING, PROTOCOL_MAX_OUTPUT_TOKENS, DEFAULT_TOTAL_TIMEOUT_MS, StreamTimeoutError, streamTimeoutsFor, createStreamDeadline, APIConnectionError, makeParseableTextFormat, OpenAI, toWireMessages, withOpenRouterCacheControl, turnFromChatResponse, collectChatStream, OpenAIAgentTurnProvider, WANDER_MARKER, WANDER_LAB_FILES, isWanderObjective, isWanderRandomScheduleObjective, pickWanderTopic, buildWanderObjective, wanderPlannerInstructions, WANDER_GRADES, parseWanderResults, wanderGradeCounts };
|