create-open-autonomy 2.4.4 → 2.4.6

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.4",
3
+ "version": "2.4.6",
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.4' } as const;
12
+ export const KIT = { name: 'hermes', version: '2.4.6' } as const;
13
13
  export const KIT_FILE = '.open-autonomy/kit.json';
14
14
  const TEMPLATE = resolve(import.meta.dir, '..', 'template');
15
15
 
@@ -16,7 +16,9 @@ import { resolve } from 'node:path';
16
16
 
17
17
  const api = (process.env.GITHUB_API_URL ?? 'https://api.github.com').replace(/\/$/, '');
18
18
  const token = process.env.GITHUB_TOKEN ?? '';
19
- if (!token) { console.error('community: no GITHUB_TOKEN — the desk has no GitHub door (a github-app.json beside the keys gives it one through the valve)'); process.exit(3); }
19
+ // No GITHUB_TOKEN: the desk has no GitHub door (a github-app.json beside the keys gives it one through the valve). That
20
+ // is a fact, not a failure: a look finds nothing on GitHub and says so, and the channel alone is the desk's.
21
+ const doorless = !token;
20
22
  const project = resolve(import.meta.dir, '..');
21
23
  const account = /^account:\s*(\S+)/m.exec(readFileSync(resolve(project, '.open-autonomy', 'config.yaml'), 'utf8'))?.[1] ?? '';
22
24
  if (!account) throw new Error('community: .open-autonomy/config.yaml names no account');
@@ -44,7 +46,13 @@ const after = (at: string | null | undefined, since: string): boolean => !at ||
44
46
  const firstLine = (s: string): string => (s ?? '').split('\n')[0]!.slice(0, 120);
45
47
 
46
48
  const [command, ...rest] = process.argv.slice(2);
47
- if (command === 'poll') {
49
+ if (command === 'poll' && doorless) {
50
+ console.log(`NOTE no GitHub door (no GITHUB_TOKEN): issues and discussions are not read; the channel alone is the desk's`);
51
+ console.log(`COMMUNITY_POLL_DONE since ${cursor()}`);
52
+ } else if ((command === 'comment' || command === 'discuss') && doorless) {
53
+ console.error('community: no GitHub door (no GITHUB_TOKEN) — nothing can be posted on GitHub');
54
+ process.exit(3);
55
+ } else if (command === 'poll') {
48
56
  const since = cursor();
49
57
  const issues = await github<Array<{ number: number; title: string; body: string | null; created_at: string; pull_request?: unknown; user?: { login?: string } }>>('GET', `/repos/${account}/issues?state=open&per_page=50&since=${encodeURIComponent(since)}`);
50
58
  for (const i of issues) if (!i.pull_request && after(i.created_at, since)) console.log(`NEW issue #${i.number} ${JSON.stringify(i.title)} by ${i.user?.login ?? 'someone'}: ${firstLine(i.body ?? '')}`);
@@ -29,7 +29,8 @@
29
29
  // reporter keyless, publishing the home's sessions and board through the valve
30
30
  // gateway `hermes gateway run` in the checkout, HERMES_HOME=<home>
31
31
  // When any of them ends, all of them end and this exits 1: the supervisor outside (you, launchd, Docker) restarts.
32
- import { cpSync, existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
32
+ import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
33
+ import { tmpdir } from 'node:os';
33
34
  import { homedir, userInfo } from 'node:os';
34
35
  import { basename, resolve } from 'node:path';
35
36
 
@@ -85,6 +86,7 @@ if (existsSync(deployKey)) {
85
86
  } else say(`no ${deployKey}: pushes use your own git and keys`);
86
87
 
87
88
  // 2. The checkout.
89
+ let committedFrom: string | undefined;
88
90
  if (!existsSync(resolve(project, '.git'))) {
89
91
  if (!origin) { console.error(`start: ${project} is not a checkout and no --origin to clone`); process.exit(1); }
90
92
  mkdirSync(project, { recursive: true }); own(project);
@@ -98,13 +100,19 @@ if (!existsSync(resolve(project, '.git'))) {
98
100
  // said and not fatal.
99
101
  const git = (...args: string[]) => Bun.spawnSync({ cmd: drop(['git', ...args]), cwd: project, env: agentEnv(), stdout: 'pipe', stderr: 'pipe' });
100
102
  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()})`);
103
+ if (git('fetch', '-q', 'origin').exitCode !== 0) say(`cannot fetch origin in ${project}; the checkout is left where it is`);
104
+ else if (dirty) {
105
+ // The working tree is a killed attempt's; what the agent IS still comes from main: its hermes/ is taken from
106
+ // origin/main directly, and the tree is left for the next attempt to carry over.
107
+ say(`checkout ${project} has uncommitted changes; left where it is, the home synced from origin/main`);
108
+ const dir = mkdtempSync(resolve(tmpdir(), 'open-autonomy-hermes-'));
109
+ const archive = Bun.spawnSync({ cmd: drop(['sh', '-c', `git archive --format=tar origin/main hermes | tar -x -C "${dir}"`]), cwd: project, env: agentEnv(), stdout: 'pipe', stderr: 'pipe' });
110
+ if (archive.exitCode === 0 && existsSync(resolve(dir, 'hermes'))) committedFrom = resolve(dir, 'hermes');
111
+ } else if (git('checkout', '-q', '--detach', 'origin/main').exitCode === 0) say(`checkout ${project} at origin/main (${git('rev-parse', '--short', 'HEAD').stdout.toString().trim()})`);
104
112
  }
105
113
 
106
- // 3. The home, from the checkout: everything under hermes/ except its .env, which is the home's own.
107
- const committed = resolve(project, 'hermes');
114
+ // 3. The home, from the repository: everything under hermes/ except its .env, which is the home's own.
115
+ const committed = committedFrom ?? resolve(project, 'hermes');
108
116
  if (existsSync(committed)) {
109
117
  // The kit's own families are mirrored, not merged: a skill or hook the checkout no longer has leaves the home too.
110
118
  for (const family of ['skills/open-autonomy', 'hooks']) rmSync(resolve(home, family), { recursive: true, force: true });