cruo-agent 0.1.6 → 0.1.7
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/VERSION +1 -1
- package/dist/cli.js +98 -3
- package/package.json +1 -1
package/dist/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.1.
|
|
1
|
+
0.1.7
|
package/dist/cli.js
CHANGED
|
@@ -45905,6 +45905,14 @@ function stripTokenFlag(argv2) {
|
|
|
45905
45905
|
if (at < 0) return [...argv2];
|
|
45906
45906
|
return [...argv2.slice(0, at), ...argv2.slice(at + 2)];
|
|
45907
45907
|
}
|
|
45908
|
+
function isKnownCommandWord(first) {
|
|
45909
|
+
if (first === void 0) return true;
|
|
45910
|
+
if (first.startsWith("-")) return true;
|
|
45911
|
+
return CRUO_COMMANDS.includes(first);
|
|
45912
|
+
}
|
|
45913
|
+
function nearestCommands(first) {
|
|
45914
|
+
return CRUO_COMMANDS.filter((k) => k[0] === first[0]).slice(0, 3);
|
|
45915
|
+
}
|
|
45908
45916
|
function numericIn(argv2, name, spec = {}) {
|
|
45909
45917
|
const i = argv2.indexOf(`--${name}`);
|
|
45910
45918
|
if (i < 0) return spec.fallback;
|
|
@@ -45939,10 +45947,24 @@ function requiredNumericIn(argv2, name, fallback, spec = {}) {
|
|
|
45939
45947
|
function secondsIn(argv2, name, fallbackSeconds) {
|
|
45940
45948
|
return requiredNumericIn(argv2, name, fallbackSeconds, { unit: "seconds" }) * 1e3;
|
|
45941
45949
|
}
|
|
45942
|
-
var OptionError, flagIn, optIn;
|
|
45950
|
+
var CRUO_COMMANDS, OptionError, flagIn, optIn;
|
|
45943
45951
|
var init_options = __esm({
|
|
45944
45952
|
"src/options.ts"() {
|
|
45945
45953
|
"use strict";
|
|
45954
|
+
CRUO_COMMANDS = [
|
|
45955
|
+
"login",
|
|
45956
|
+
"logout",
|
|
45957
|
+
"agents",
|
|
45958
|
+
"whoami",
|
|
45959
|
+
"usage",
|
|
45960
|
+
"help",
|
|
45961
|
+
"start",
|
|
45962
|
+
"ps",
|
|
45963
|
+
"stop",
|
|
45964
|
+
"pause",
|
|
45965
|
+
"resume",
|
|
45966
|
+
"logs"
|
|
45967
|
+
];
|
|
45946
45968
|
OptionError = class extends Error {
|
|
45947
45969
|
constructor(message) {
|
|
45948
45970
|
super(message);
|
|
@@ -46978,11 +47000,22 @@ async function invokeHarness(ctx, identity, hit, worktree) {
|
|
|
46978
47000
|
const cwd = worktree?.path ?? options.cwd;
|
|
46979
47001
|
const { path: mcpConfig, cleanup } = await writeMcpConfig();
|
|
46980
47002
|
const streaming = options.usage === true;
|
|
47003
|
+
const builtinTools = [
|
|
47004
|
+
...new Set(
|
|
47005
|
+
options.allow.split(",").map((t) => t.trim()).filter((t) => t !== "" && !t.startsWith("mcp__")).map((t) => t.replace(/\(.*$/, ""))
|
|
47006
|
+
)
|
|
47007
|
+
].join(",");
|
|
46981
47008
|
const args = [
|
|
46982
47009
|
"-p",
|
|
46983
47010
|
userPrompt(hit),
|
|
46984
47011
|
"--mcp-config",
|
|
46985
47012
|
mcpConfig,
|
|
47013
|
+
// Both, always. See the note above: without `--restricted` the harness
|
|
47014
|
+
// inherits the operator's settings, and without `--tools` it keeps every
|
|
47015
|
+
// built-in that `--restricted` does not itself remove.
|
|
47016
|
+
"--restricted",
|
|
47017
|
+
"--tools",
|
|
47018
|
+
builtinTools,
|
|
46986
47019
|
// Only the server we just described. Without this the harness would also
|
|
46987
47020
|
// load the developer's own .mcp.json — including, on this machine, a Cruo
|
|
46988
47021
|
// token belonging to a human.
|
|
@@ -47416,6 +47449,22 @@ async function main() {
|
|
|
47416
47449
|
installControls();
|
|
47417
47450
|
const runName = identityName();
|
|
47418
47451
|
if (!options.once && !options.dryRun) {
|
|
47452
|
+
const existing = await liveness(runName, true);
|
|
47453
|
+
if (existing.state === "running") {
|
|
47454
|
+
console.error(
|
|
47455
|
+
`
|
|
47456
|
+
${runName} is already running here (pid ${existing.record.pid}, up ${since(existing.record.startedAt)}).
|
|
47457
|
+
|
|
47458
|
+
Two supervisors for one agent share a token, a queue and a heartbeat,
|
|
47459
|
+
and the second would take over the first one's record \u2014 leaving the
|
|
47460
|
+
first with no way to be stopped except by pid.
|
|
47461
|
+
|
|
47462
|
+
stop it cruo stop ${runName}
|
|
47463
|
+
look at it cruo ps
|
|
47464
|
+
`
|
|
47465
|
+
);
|
|
47466
|
+
process.exit(2);
|
|
47467
|
+
}
|
|
47419
47468
|
await writeRecord({
|
|
47420
47469
|
agent: runName,
|
|
47421
47470
|
pid: process.pid,
|
|
@@ -47962,7 +48011,19 @@ ${name} is not running. Start it with \`cruo start --as ${name}\`.
|
|
|
47962
48011
|
async function startDetached(argv2, asName) {
|
|
47963
48012
|
const { spawn: spawn2 } = await import("node:child_process");
|
|
47964
48013
|
const { open, mkdir: mkdir4 } = await import("node:fs/promises");
|
|
47965
|
-
const
|
|
48014
|
+
const positional = argv2[1] && !argv2[1].startsWith("--") ? argv2[1] : null;
|
|
48015
|
+
if (positional && asName && safeName(positional) !== safeName(asName)) {
|
|
48016
|
+
console.error(
|
|
48017
|
+
`
|
|
48018
|
+
Two different agents named: \`${positional}\` and \`--as ${asName}\`.
|
|
48019
|
+
|
|
48020
|
+
Say one: cruo start ${positional} \u2026
|
|
48021
|
+
or cruo start --as ${asName} \u2026
|
|
48022
|
+
`
|
|
48023
|
+
);
|
|
48024
|
+
process.exit(2);
|
|
48025
|
+
}
|
|
48026
|
+
const name = await targetName(positional, asName);
|
|
47966
48027
|
const already = await liveness(name, true);
|
|
47967
48028
|
if (already.state === "running") {
|
|
47968
48029
|
console.error(
|
|
@@ -47973,10 +48034,30 @@ Stop it first, or use --as <name> to run a different agent.
|
|
|
47973
48034
|
);
|
|
47974
48035
|
process.exit(1);
|
|
47975
48036
|
}
|
|
48037
|
+
const config3 = await readConfig2();
|
|
48038
|
+
const storedKey = Object.keys(config3.agents).find((k) => safeName(k) === name) ?? null;
|
|
48039
|
+
const hasToken = Boolean(process.env.CRUO_TOKEN?.trim()) || argv2.includes("--token") || storedKey !== null;
|
|
48040
|
+
if (!hasToken) {
|
|
48041
|
+
const stored = Object.keys(config3.agents);
|
|
48042
|
+
console.error(
|
|
48043
|
+
`
|
|
48044
|
+
Nothing stored for \`${name}\`, so there is no token to run it with.
|
|
48045
|
+
|
|
48046
|
+
` + (stored.length > 0 ? `Stored: ${stored.join(", ")}
|
|
48047
|
+
Either \`cruo start ${stored[0]}\`, or add this one:
|
|
48048
|
+
` : `Nothing is stored at all. Add one:
|
|
48049
|
+
`) + ` cruo login <token>
|
|
48050
|
+
`
|
|
48051
|
+
);
|
|
48052
|
+
process.exit(2);
|
|
48053
|
+
}
|
|
47976
48054
|
await mkdir4(logDir(), { recursive: true });
|
|
47977
48055
|
const logPath = join4(logDir(), `${name}.log`);
|
|
47978
48056
|
const handle = await open(logPath, "a");
|
|
47979
|
-
const
|
|
48057
|
+
const rest = argv2.slice(positional ? 2 : 1).filter((a) => a !== "--all");
|
|
48058
|
+
const chosen = storedKey ?? positional ?? asName;
|
|
48059
|
+
const withoutAs = rest.filter((a, i, all) => a !== "--as" && all[i - 1] !== "--as");
|
|
48060
|
+
const forwarded = chosen ? ["--as", chosen, ...withoutAs] : withoutAs;
|
|
47980
48061
|
const child = spawn2(process.execPath, [process.argv[1], ...forwarded], {
|
|
47981
48062
|
detached: true,
|
|
47982
48063
|
stdio: ["ignore", handle.fd, handle.fd],
|
|
@@ -48120,6 +48201,20 @@ Usage: cruo login <token> [--as <name>]
|
|
|
48120
48201
|
console.log(USAGE);
|
|
48121
48202
|
return;
|
|
48122
48203
|
}
|
|
48204
|
+
if (!isKnownCommandWord(first)) {
|
|
48205
|
+
const near = nearestCommands(first);
|
|
48206
|
+
console.error(
|
|
48207
|
+
`
|
|
48208
|
+
\`${first}\` is not a cruo command.
|
|
48209
|
+
|
|
48210
|
+
` + (near.length > 0 ? `Did you mean: ${near.map((k) => `cruo ${k}`).join(" ")}
|
|
48211
|
+
|
|
48212
|
+
` : "") + `To run the agent, give no command: cruo [options]
|
|
48213
|
+
Everything it takes: cruo --help
|
|
48214
|
+
`
|
|
48215
|
+
);
|
|
48216
|
+
process.exit(2);
|
|
48217
|
+
}
|
|
48123
48218
|
if (first === "start") return startDetached(argv2, flagValue("--as"));
|
|
48124
48219
|
const flagIndex = argv2.indexOf("--token");
|
|
48125
48220
|
const fromFlag = flagIndex >= 0 ? argv2[flagIndex + 1] : void 0;
|
package/package.json
CHANGED