create-open-autonomy 2.3.3 → 2.3.5
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 +1 -1
- package/package.json +2 -2
- package/src/kit.ts +5 -5
- package/template/.open-autonomy/config.yaml +4 -0
- package/template/.open-autonomy/start.ts +22 -12
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@ LICENSE Apache-2.0, seeded; the project's own
|
|
|
31
31
|
package.json, test/ the project's own check (`bun run check`), starting with one test
|
|
32
32
|
hermes/ the agent: SOUL.md, its two skills (develop, pm; a project's own skills live beside them, in hermes/skills/<project>/, and are the project's), profiles/treasurer (the second profile: the one that pays), kanban.seed.json (the board's first tasks, in order),
|
|
33
33
|
cron/jobs.seed.json (the PM, hourly), config.yaml (the model: the project's own choice), the seed hook
|
|
34
|
-
.open-autonomy/ the platform connection: config.yaml (account, publish policy, rail bounds), reporter.ts (the publisher:
|
|
34
|
+
.open-autonomy/ the platform connection: config.yaml (account, publish policy, the model and rail bounds the platform holds the project's funds to), reporter.ts (the publisher:
|
|
35
35
|
sessions, the board, the setup), mint-key.ts (the key, the adopter way), start.ts (the agent's four
|
|
36
36
|
processes, the one way it starts), the vendored SDK, kit.json (which kit, version and parameters made this repository)
|
|
37
37
|
container/ a real setup: one image whose entrypoint is start.ts as root, dropping the gateway to the image's user; the pinned Hermes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-open-autonomy",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.5",
|
|
4
4
|
"description": "The default Open Autonomy starter kit: a complete repository that runs its own Hermes agent against the platform, with the SDK wired in. `bun create open-autonomy <dir>` scaffolds one.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"check": "bunx tsc --noEmit"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@open-autonomy/sdk": "2.
|
|
31
|
+
"@open-autonomy/sdk": "2.3.0"
|
|
32
32
|
},
|
|
33
33
|
"devDependencies": {
|
|
34
34
|
"@types/bun": "^1.3.10",
|
package/src/kit.ts
CHANGED
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
// platform account — into a complete repository. Two kinds of files come out of it:
|
|
3
3
|
// kit-owned the agent's home, the reporter, the container stack, the landing workflows: what the kit
|
|
4
4
|
// keeps current. `check` diffs them against a fresh render; `upgrade` rewrites them.
|
|
5
|
-
// seeded README, the board's seed,
|
|
5
|
+
// seeded README, the board's seed, CONTRIBUTING.md, the constitution, changelog, AGENTS.md, license, the model config, the publish
|
|
6
6
|
// policy: the project's own files, written once as a courtesy and never touched again.
|
|
7
7
|
// `.open-autonomy/kit.json` records which kit, which version and which parameters made the repo: the anchor
|
|
8
8
|
// `check` and `upgrade` read, so neither needs to be told anything twice.
|
|
9
9
|
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
|
|
10
10
|
import { dirname, join, relative, resolve } from 'node:path';
|
|
11
11
|
|
|
12
|
-
export const KIT = { name: 'hermes', version: '2.3.
|
|
12
|
+
export const KIT = { name: 'hermes', version: '2.3.5' } as const;
|
|
13
13
|
export const KIT_FILE = '.open-autonomy/kit.json';
|
|
14
14
|
const TEMPLATE = resolve(import.meta.dir, '..', 'template');
|
|
15
15
|
|
|
@@ -17,9 +17,9 @@ export interface KitParams { project: string; account: string }
|
|
|
17
17
|
export interface KitRecord { kit: string; version: string; params: KitParams; divergences: string[] }
|
|
18
18
|
|
|
19
19
|
// What the kit keeps current. Everything else in the template is seeded once.
|
|
20
|
-
// A project's own, seeded once: its config
|
|
21
|
-
// hermes/skills/open-autonomy/ (the kit's two).
|
|
22
|
-
const OWNED = [/^hermes\/(?!config\.yaml$|kanban\.seed\.json$|cron\/jobs\.seed\.json$|skills\/(?!open-autonomy\/))/, /^\.open-autonomy\/(reporter\.ts|mint-key\.ts|start\.ts|package\.json|sdk\/)/, /^container\//, /^\.github\/workflows\/(ci|land)\.yml$/];
|
|
20
|
+
// A project's own, seeded once: its config (the treasurer's too: the model is the project's choice for both profiles),
|
|
21
|
+
// its board seed, its schedule, and any skill of its own outside hermes/skills/open-autonomy/ (the kit's two).
|
|
22
|
+
const OWNED = [/^hermes\/(?!config\.yaml$|kanban\.seed\.json$|cron\/jobs\.seed\.json$|profiles\/treasurer\/config\.yaml$|skills\/(?!open-autonomy\/))/, /^\.open-autonomy\/(reporter\.ts|mint-key\.ts|start\.ts|package\.json|sdk\/)/, /^container\//, /^\.github\/workflows\/(ci|land)\.yml$/];
|
|
23
23
|
export const isOwned = (rel: string): boolean => OWNED.some((re) => re.test(rel));
|
|
24
24
|
|
|
25
25
|
export function validateParams(p: Partial<KitParams>): KitParams {
|
|
@@ -15,6 +15,10 @@ publish:
|
|
|
15
15
|
# environment), and where it keeps its own cursor (beside this file).
|
|
16
16
|
state_file: reporter-state.json
|
|
17
17
|
|
|
18
|
+
# The models the project's funds may buy on the platform's model rail: a bound the platform reads from this file and
|
|
19
|
+
# holds whatever a key was minted with. Empty: any model the gateway serves (`GET /v1/catalog` lists them).
|
|
20
|
+
models: [zai/glm-5.3-flash]
|
|
21
|
+
|
|
18
22
|
# The rails the agent may spend through beyond model calls, and the owner's bounds on each. Off unless a
|
|
19
23
|
# bound is set. Every rail leaves a record on the public audit trail naming itself.
|
|
20
24
|
rails:
|
|
@@ -6,6 +6,11 @@
|
|
|
6
6
|
//
|
|
7
7
|
// bun .open-autonomy/start.ts [--home <dir>] [--secrets <dir>] [--project <dir>] [--origin <url>] [--as <user>] [--valve <port>]
|
|
8
8
|
//
|
|
9
|
+
// <secrets>/codex.json, when present, is the owner's ChatGPT/Codex subscription login (the Codex CLI's auth.json
|
|
10
|
+
// tokens): the valve serves it on the third port, and the home's .env names it (HERMES_CODEX_BASE_URL) for a custom
|
|
11
|
+
// provider in the project's config that speaks the Codex protocol — the model runs on the subscription, the login
|
|
12
|
+
// never enters the agent.
|
|
13
|
+
//
|
|
9
14
|
// The processes, in order:
|
|
10
15
|
// ssh-agent holds <secrets>/deploy_key, its socket at <home>/ssh-agent.sock; the gateway pushes through it
|
|
11
16
|
// and never holds the key (absent: pushes are your own git's business)
|
|
@@ -81,12 +86,19 @@ if (!existsSync(resolve(project, '.git'))) {
|
|
|
81
86
|
|
|
82
87
|
// 3. The home, from the checkout: everything under hermes/ except its .env, which is the home's own.
|
|
83
88
|
const committed = resolve(project, 'hermes');
|
|
84
|
-
|
|
85
|
-
|
|
89
|
+
if (existsSync(committed)) {
|
|
90
|
+
// The kit's own families are mirrored, not merged: a skill or hook the checkout no longer has leaves the home too.
|
|
91
|
+
for (const family of ['skills/open-autonomy', 'hooks']) rmSync(resolve(home, family), { recursive: true, force: true });
|
|
92
|
+
// force: with a filter, Bun's cpSync leaves an existing file alone unless told to overwrite.
|
|
93
|
+
cpSync(committed, home, { recursive: true, force: true, filter: (src) => basename(src) !== '.env' });
|
|
94
|
+
}
|
|
86
95
|
// The home's .env is the home's own, except the valve's three lines, which are this start's truth on every start.
|
|
87
96
|
const envFile = resolve(home, '.env');
|
|
88
|
-
const kept = existsSync(envFile) ? readFileSync(envFile, 'utf8').split('\n').filter((l) => l.trim() && !/^OPEN_AUTONOMY_(BASE_URL|PAY_URL|KEY)=/.test(l)) : [];
|
|
89
|
-
|
|
97
|
+
const kept = existsSync(envFile) ? readFileSync(envFile, 'utf8').split('\n').filter((l) => l.trim() && !/^(OPEN_AUTONOMY_(BASE_URL|PAY_URL|KEY)|HERMES_CODEX_BASE_URL)=/.test(l)) : [];
|
|
98
|
+
// The Codex subscription's address goes in the .env too: Hermes loads the home's .env into every process it starts,
|
|
99
|
+
// including the scheduler's job runners, which do not inherit the gateway's environment.
|
|
100
|
+
const codexBase = existsSync(resolve(secrets, 'codex.json')) ? [`HERMES_CODEX_BASE_URL=http://127.0.0.1:${valvePort + 2}/backend-api/codex`] : [];
|
|
101
|
+
const lines = [`OPEN_AUTONOMY_BASE_URL=${baseUrl}`, `OPEN_AUTONOMY_PAY_URL=${payUrl}`, 'OPEN_AUTONOMY_KEY=valve', ...codexBase, ...kept];
|
|
90
102
|
// On the first start, what the environment says about the agent's channels comes along: Discord's, and GitHub's for a community desk.
|
|
91
103
|
if (!existsSync(envFile)) for (const k of Object.keys(process.env).sort()) if (/^(DISCORD_|GITHUB_TOKEN$|GITHUB_API_URL$)/.test(k) && process.env[k]) lines.push(`${k}=${process.env[k]}`);
|
|
92
104
|
writeFileSync(envFile, `${lines.join('\n')}\n`);
|
|
@@ -98,19 +110,17 @@ const keys: string[] = [];
|
|
|
98
110
|
if (existsSync(resolve(secrets, 'agent.env'))) keys.push('--key', `${resolve(secrets, 'agent.env')}:${valvePort}`);
|
|
99
111
|
if (existsSync(resolve(secrets, 'treasurer.env'))) keys.push('--key', `${resolve(secrets, 'treasurer.env')}:${valvePort + 1}`);
|
|
100
112
|
if (!keys.length) { console.error(`start: no ${resolve(secrets, 'agent.env')} — mint the developer's key: bun .open-autonomy/mint-key.ts`); process.exit(1); }
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
}
|
|
106
|
-
// The valve and the reporter run from this script's own directory (its node_modules, its vendored SDK): in a
|
|
107
|
-
// container that is the image's copy, and the checkout only has to be the project.
|
|
113
|
+
// The Codex subscription: the valve holds the login and serves it on the third port; Hermes reaches it as a named
|
|
114
|
+
// custom provider speaking the Codex protocol (base_url ${HERMES_CODEX_BASE_URL}, api_key `valve`), which the home's .env names.
|
|
115
|
+
const codexFile = resolve(secrets, 'codex.json');
|
|
116
|
+
const codexPort = valvePort + 2;
|
|
117
|
+
if (existsSync(codexFile)) keys.push('--codex', `${codexFile}:${codexPort}`);
|
|
108
118
|
spawn('valve', ['bun', resolve(import.meta.dir, 'sdk', 'valve.ts'), ...keys], {});
|
|
109
119
|
|
|
110
120
|
// 5. The reporter and the gateway, as the agent.
|
|
111
121
|
const env = agentEnv();
|
|
112
122
|
spawn('reporter', ['bun', resolve(import.meta.dir, 'reporter.ts'), '--config', resolve(project, '.open-autonomy', 'config.yaml')], { asAgent: true, env: { ...env, OPEN_AUTONOMY_BASE_URL: baseUrl } });
|
|
113
123
|
spawn('gateway', ['hermes', 'gateway', 'run'], { asAgent: true, env });
|
|
114
|
-
say(`gateway up in ${project} as ${user?.name ?? userInfo().username}, home ${home}; the valve on :${valvePort}${
|
|
124
|
+
say(`gateway up in ${project} as ${user?.name ?? userInfo().username}, home ${home}; the valve on :${valvePort}${existsSync(resolve(secrets, 'treasurer.env')) ? ` and :${valvePort + 1}` : ''}${existsSync(codexFile) ? `; the Codex subscription on :${codexPort}` : ''}`);
|
|
115
125
|
if (!readFileSync(resolve(project, '.open-autonomy', 'config.yaml'), 'utf8').includes('account:')) say('warning: .open-autonomy/config.yaml names no account');
|
|
116
126
|
await new Promise(() => {});
|