headlesscode 1.2.1 → 1.2.2
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 +245 -459
- package/package.json +2 -1
- package/shared/openshell/headlesscode-openrouter.yaml +21 -0
- package/shared/openshell/headlesscode-policy.yaml +21 -0
- package/src/cli.ts +30 -0
- package/src/cloud/openshell-preflight.ts +16 -0
- package/src/cloud/openshell-provider.ts +582 -0
- package/src/cloud/openshell-session.ts +119 -0
- package/src/cloud/openshell-subsession.ts +63 -0
- package/src/cloud/openshell-worker.ts +124 -0
- package/src/engine/events.ts +3 -0
- package/src/engine/loop.ts +143 -0
- package/src/engine/types.ts +42 -0
- package/src/monitoring/controller.ts +73 -0
- package/src/monitoring/features.ts +103 -0
- package/src/monitoring/index.ts +4 -0
- package/src/monitoring/predictor.ts +246 -0
- package/src/monitoring/types.ts +192 -0
- package/src/orchestrator/cli.ts +24 -0
- package/src/orchestrator/reviewer.ts +11 -0
- package/src/project-store.ts +11 -0
- package/src/qa/qa.ts +12 -0
- package/src/watcher/cli.ts +18 -0
- package/src/watcher/watch.ts +3 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "headlesscode",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.2",
|
|
4
4
|
"description": "Standalone headless coding-agent harness: runs the Zoo Code agent loop (prompts, tools, modes) without a VS Code UI, driven by CLI, HTTP, and parallel worktree orchestration.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"dev": "tsx src/index.ts",
|
|
42
42
|
"start": "tsx src/cli.ts",
|
|
43
43
|
"cli": "tsx src/cli.ts",
|
|
44
|
+
"monitor:pilot": "tsx scripts/monitor-pilot/run.ts",
|
|
44
45
|
"test": "node scripts/run-tests.mjs",
|
|
45
46
|
"prepublishOnly": "npm ci && npm test"
|
|
46
47
|
},
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
id: headlesscode-openrouter
|
|
2
|
+
display_name: HeadlessCode OpenRouter
|
|
3
|
+
description: OpenRouter inference access for HeadlessCode workers running in Node.js
|
|
4
|
+
category: inference
|
|
5
|
+
inference_capable: true
|
|
6
|
+
credentials:
|
|
7
|
+
- name: api_key
|
|
8
|
+
description: OpenRouter API key
|
|
9
|
+
env_vars: [HEADLESSCODE_OPENROUTER_API_KEY]
|
|
10
|
+
required: true
|
|
11
|
+
auth_style: bearer
|
|
12
|
+
header_name: authorization
|
|
13
|
+
discovery:
|
|
14
|
+
credentials: [api_key]
|
|
15
|
+
endpoints:
|
|
16
|
+
- host: openrouter.ai
|
|
17
|
+
port: 443
|
|
18
|
+
protocol: rest
|
|
19
|
+
access: read-write
|
|
20
|
+
enforcement: enforce
|
|
21
|
+
binaries: [/usr/local/bin/node]
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
version: 1
|
|
2
|
+
filesystem_policy:
|
|
3
|
+
include_workdir: true
|
|
4
|
+
read_only:
|
|
5
|
+
- /usr
|
|
6
|
+
- /lib
|
|
7
|
+
- /lib64
|
|
8
|
+
- /etc
|
|
9
|
+
- /proc
|
|
10
|
+
- /dev/urandom
|
|
11
|
+
- /var/log
|
|
12
|
+
read_write:
|
|
13
|
+
- /sandbox
|
|
14
|
+
- /tmp
|
|
15
|
+
- /dev/null
|
|
16
|
+
landlock:
|
|
17
|
+
compatibility: hard_requirement
|
|
18
|
+
process:
|
|
19
|
+
run_as_user: sandbox
|
|
20
|
+
run_as_group: sandbox
|
|
21
|
+
network_policies: {}
|
package/src/cli.ts
CHANGED
|
@@ -44,6 +44,7 @@ import { costHistoryCliMain } from "./orchestrator/cost-history-cli.js"
|
|
|
44
44
|
import { resolvePermissions, type PermissionsConfig } from "./permissions/config.js"
|
|
45
45
|
import { resolveModelForMode, resolveReasoningEffortForMode } from "./config/mode-models.js"
|
|
46
46
|
import { improveMain } from "./rsi/controller.js"
|
|
47
|
+
import { openShellSessionMain } from "./cloud/openshell-session.js"
|
|
47
48
|
|
|
48
49
|
const VERSION = "0.1.0"
|
|
49
50
|
|
|
@@ -187,6 +188,9 @@ Usage:
|
|
|
187
188
|
headlesscode --dry-run [options] # build system prompt + validate config, no LLM call
|
|
188
189
|
|
|
189
190
|
Subcommands:
|
|
191
|
+
headlesscode openshell-session --repo <path> --task <text> --policy <path>
|
|
192
|
+
Run one task in an OpenShell sandbox and keep its Git worktree
|
|
193
|
+
for review. See \`openshell-session --help\` for options.
|
|
190
194
|
headlesscode improve --repo <path> [--model <id>] [--population <n>] [--dry-run]
|
|
191
195
|
Run a bounded recursive self-improvement generation. Candidates
|
|
192
196
|
use isolated git worktrees; evaluator/scoring paths are protected.
|
|
@@ -721,6 +725,32 @@ export function parseArgs(argv: string[]): { options: CliOptions; error?: string
|
|
|
721
725
|
}
|
|
722
726
|
|
|
723
727
|
export async function main(argv: string[] = process.argv.slice(2)): Promise<number> {
|
|
728
|
+
if (argv[0] === "openshell-review-session" || argv[0] === "openshell-qa-session") {
|
|
729
|
+
let payload: Record<string, unknown>
|
|
730
|
+
try {
|
|
731
|
+
payload = JSON.parse(Buffer.from(argv[1] ?? "", "base64url").toString("utf8")) as Record<string, unknown>
|
|
732
|
+
} catch {
|
|
733
|
+
process.stderr.write("headlesscode: invalid OpenShell session payload\n")
|
|
734
|
+
return 2
|
|
735
|
+
}
|
|
736
|
+
if (argv[0] === "openshell-review-session") {
|
|
737
|
+
const { runReview } = await import("./orchestrator/reviewer.js")
|
|
738
|
+
const result = await runReview(payload as unknown as Parameters<typeof runReview>[0])
|
|
739
|
+
process.stdout.write(`HEADLESSCODE_RESULT_JSON:${JSON.stringify(result)}\n`)
|
|
740
|
+
return 0
|
|
741
|
+
}
|
|
742
|
+
const { runQa } = await import("./qa/qa.js")
|
|
743
|
+
const result = await runQa(payload as unknown as Parameters<typeof runQa>[0])
|
|
744
|
+
process.stdout.write(`HEADLESSCODE_RESULT_JSON:${JSON.stringify(result)}\n`)
|
|
745
|
+
return 0
|
|
746
|
+
}
|
|
747
|
+
if (argv[0] === "openshell-worker") {
|
|
748
|
+
const { openShellWorkerMain } = await import("./cloud/openshell-worker.js")
|
|
749
|
+
return openShellWorkerMain(argv.slice(1))
|
|
750
|
+
}
|
|
751
|
+
if (argv[0] === "openshell-session") {
|
|
752
|
+
return openShellSessionMain(argv.slice(1))
|
|
753
|
+
}
|
|
724
754
|
// Bounded recursive self-improvement: the supervisor owns the evaluator,
|
|
725
755
|
// archive, and selection logic while each candidate runs in its own
|
|
726
756
|
// worktree. See docs/recursive-self-improvement.md.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process"
|
|
2
|
+
import * as fs from "node:fs"
|
|
3
|
+
|
|
4
|
+
export function openshellPreflight(): string | undefined {
|
|
5
|
+
const policy = process.env.HEADLESSCODE_OPENSHELL_POLICY
|
|
6
|
+
if (!policy || !fs.existsSync(policy)) return "set HEADLESSCODE_OPENSHELL_POLICY to an existing base policy YAML"
|
|
7
|
+
if (!process.env.HEADLESSCODE_OPENROUTER_API_KEY) return "set HEADLESSCODE_OPENROUTER_API_KEY so OpenShell can provide the imported credential profile"
|
|
8
|
+
const version = spawnSync("openshell", ["--version"], { encoding: "utf8", timeout: 5000 })
|
|
9
|
+
if (version.error || version.status !== 0) return "OpenShell CLI is unavailable"
|
|
10
|
+
const gateway = spawnSync("openshell", ["gateway", "info"], { encoding: "utf8", timeout: 10000 })
|
|
11
|
+
const output = `${gateway.stdout ?? ""}${gateway.stderr ?? ""}`
|
|
12
|
+
if (gateway.error || gateway.status !== 0 || !/Status:\s+healthy/i.test(output)) {
|
|
13
|
+
return `OpenShell gateway is not healthy${output.trim() ? ": " + output.trim() : ""}`
|
|
14
|
+
}
|
|
15
|
+
return undefined
|
|
16
|
+
}
|