create-open-autonomy 2.4.1 → 2.4.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-open-autonomy",
3
- "version": "2.4.1",
3
+ "version": "2.4.3",
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": {
package/src/kit.ts CHANGED
@@ -9,7 +9,7 @@
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.4.1' } as const;
12
+ export const KIT = { name: 'hermes', version: '2.4.3' } as const;
13
13
  export const KIT_FILE = '.open-autonomy/kit.json';
14
14
  const TEMPLATE = resolve(import.meta.dir, '..', 'template');
15
15
 
@@ -19,7 +19,8 @@
19
19
  // The processes, in order:
20
20
  // ssh-agent holds <secrets>/deploy_key, its socket at <home>/ssh-agent.sock; the gateway pushes through it
21
21
  // and never holds the key (absent: pushes are your own git's business)
22
- // the clone <project> cloned from --origin when it is not a checkout yet (a container's first boot)
22
+ // the clone <project> cloned from --origin when it is not a checkout yet (a container's first boot); a clean
23
+ // checkout is brought to origin/main on every start, so the agent is what the repository says today
23
24
  // the home hermes/ in the checkout copied into <home> before every start — the repository is the source of
24
25
  // truth for what the agent IS; the home keeps what it has since done (its .env is kept)
25
26
  // valve <secrets>/agent.env on :8787 (the developer's key), <secrets>/treasurer.env on :8788 (the
@@ -35,7 +36,10 @@ import { basename, resolve } from 'node:path';
35
36
  const argv = process.argv.slice(2);
36
37
  const arg = (name: string): string | undefined => { const i = argv.indexOf(name); return i >= 0 ? argv[i + 1] : undefined; };
37
38
  const project = resolve(arg('--project') ?? resolve(import.meta.dir, '..'));
38
- const home = resolve(arg('--home') ?? process.env.AGENT_HOME ?? resolve(homedir(), '.local', 'state', 'open-autonomy', basename(project), 'home'));
39
+ // The home's default is named by the project's account (owner/repo from .open-autonomy/config.yaml), never by the
40
+ // checkout's directory name: two projects checked out as `project` must not share one home.
41
+ const account = /^account:\s*(\S+)/m.exec(existsSync(resolve(project, '.open-autonomy', 'config.yaml')) ? readFileSync(resolve(project, '.open-autonomy', 'config.yaml'), 'utf8') : '')?.[1];
42
+ const home = resolve(arg('--home') ?? process.env.AGENT_HOME ?? resolve(homedir(), '.local', 'state', 'open-autonomy', ...(account ?? basename(project)).split('/'), 'home'));
39
43
  const secrets = resolve(arg('--secrets') ?? process.env.AGENT_SECRETS ?? resolve(homedir(), '.config', 'open-autonomy'));
40
44
  const origin = arg('--origin') ?? process.env.ORIGIN;
41
45
  const as = arg('--as');
@@ -87,6 +91,16 @@ if (!existsSync(resolve(project, '.git'))) {
87
91
  const clone = Bun.spawnSync({ cmd: drop(['git', 'clone', '-q', origin, project]), env: agentEnv(), stdout: 'inherit', stderr: 'inherit' });
88
92
  if (clone.exitCode !== 0) { console.error(`start: cannot clone ${origin}`); process.exit(1); }
89
93
  say(`cloned ${origin} → ${project}`);
94
+ } else {
95
+ // What the agent IS is what main says: a clean checkout moves to origin/main before the home is synced from it
96
+ // (the skills, the schedule, the documents the reporter publishes). A dirty one — a killed attempt's work — is
97
+ // left as it is; the next attempt starts from a fresh main itself. A fetch that fails (no network, a world) is
98
+ // said and not fatal.
99
+ const git = (...args: string[]) => Bun.spawnSync({ cmd: drop(['git', ...args]), cwd: project, env: agentEnv(), stdout: 'pipe', stderr: 'pipe' });
100
+ const dirty = git('status', '--porcelain').stdout.toString().trim();
101
+ if (dirty) say(`checkout ${project} has uncommitted changes; left where it is`);
102
+ else if (git('fetch', '-q', 'origin').exitCode !== 0) say(`cannot fetch origin in ${project}; left where it is`);
103
+ else if (git('checkout', '-q', '--detach', 'origin/main').exitCode === 0) say(`checkout ${project} at origin/main (${git('rev-parse', '--short', 'HEAD').stdout.toString().trim()})`);
90
104
  }
91
105
 
92
106
  // 3. The home, from the checkout: everything under hermes/ except its .env, which is the home's own.
@@ -129,8 +143,14 @@ const githubFile = resolve(secrets, 'github-app.json');
129
143
  if (githubApp) keys.push('--github-app', `${githubFile}:${valvePort + 3}`);
130
144
  spawn('valve', ['bun', resolve(import.meta.dir, 'sdk', 'valve.ts'), ...keys], {});
131
145
 
132
- // 5. The reporter and the gateway, as the agent.
146
+ // 5. The reporter and the gateway, as the agent. The reporter's own dependencies (supercode, beside it in
147
+ // .open-autonomy/package.json) are installed on the first start of a bare checkout.
133
148
  const env = agentEnv();
149
+ if (!existsSync(resolve(import.meta.dir, 'node_modules'))) {
150
+ const install = Bun.spawnSync({ cmd: drop(['bun', 'install']), cwd: import.meta.dir, env, stdout: 'inherit', stderr: 'inherit' });
151
+ if (install.exitCode !== 0) { console.error(`start: cannot install the reporter's dependencies in ${import.meta.dir}`); process.exit(1); }
152
+ say(`reporter dependencies installed in ${import.meta.dir}`);
153
+ }
134
154
  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 } });
135
155
  spawn('gateway', ['hermes', 'gateway', 'run'], { asAgent: true, env });
136
156
  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}` : ''}${githubApp ? `; the GitHub App on :${valvePort + 3}` : ''}`);