neurastream 0.1.5 → 0.1.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": "neurastream",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "Harness-agnostic agent orchestration: queue, guards, blockers, scoring, ledger.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -34,7 +34,9 @@ export function helpText(): string {
34
34
  "",
35
35
  "Usage:",
36
36
  " neurastream --help",
37
- " neurastream init create config, index, notes, blockers, queue template, state dirs",
37
+ " neurastream init [--agent-dir <dir>]",
38
+ " create config, index, notes, blockers, queue template, state dirs",
39
+ " (--agent-dir: keep an existing index/notes/blockers dir)",
38
40
  " neurastream adapter install omp",
39
41
  " link the omp extension under this HOME",
40
42
  " neurastream doctor report hand-edited live files and a stale install",
@@ -55,7 +57,7 @@ export async function run(cmd: string, args: string[]): Promise<number> {
55
57
  console.log(helpText());
56
58
  return 0;
57
59
  }
58
- if (cmd === "init") return runInit();
60
+ if (cmd === "init") return runInit(args);
59
61
  if (cmd === "adapter") return runAdapterInstall(args);
60
62
  if (cmd === "config") {
61
63
  try {
package/src/cli/init.ts CHANGED
@@ -53,19 +53,24 @@ export function installedBins(home: string, invoked: string): string[] {
53
53
  return [...new Set(out)];
54
54
  }
55
55
 
56
- function configText(home: string, invoked: string): string {
56
+ // The path keys that sit under the agent dir (same derivation as the queue library's agentDir()).
57
+ const AGENT_DIR_KEYS = /^( (?:agent_dir|queue_index|blockers|notes|ranking_board|subagents|cancelled|unlock): )"~\/\.config\/neurastream/gm;
58
+
59
+ function configText(home: string, invoked: string, agentDir?: string): string {
57
60
  let text = readFileSync(TEMPLATE_PATH, "utf8");
58
61
  if (!text.endsWith("\n")) text += "\n";
59
62
  if (existsSync(join(home, "Work", "pm-counts"))) {
60
63
  if (!text.includes('default_repo: ""')) throw new Error("templates/config.yml has no default_repo placeholder");
61
64
  text = text.replace('default_repo: ""', 'default_repo: "~/Work/pm-counts"');
62
65
  }
63
- const protectedPaths = [
64
- ...installedBins(home, invoked),
65
- "~/.config/neurastream/notes/",
66
- "~/.config/neurastream/blockers/",
67
- "~/.config/neurastream/queue/",
68
- ];
66
+ // An existing machine keeps its index, notes, blockers and unlock where they are today.
67
+ const agent = agentDir ? tilde(home, resolve(home, agentDir.replace(/^~(?=\/|$)/, home))) : "~/.config/neurastream";
68
+ if (agentDir) {
69
+ const hits = text.match(AGENT_DIR_KEYS)?.length ?? 0;
70
+ if (hits !== 8) throw new Error(`templates/config.yml: expected 8 agent-dir path keys, found ${hits}`);
71
+ text = text.replace(AGENT_DIR_KEYS, (_m, key: string) => `${key}${yamlQuote(agent).slice(0, -1)}`);
72
+ }
73
+ const protectedPaths = [...installedBins(home, invoked), `${agent}/notes/`, `${agent}/blockers/`, `${agent}/queue/`];
69
74
  const list = [" protected:", ...protectedPaths.map(p => ` - ${yamlQuote(p)}`)].join("\n");
70
75
  if (!text.includes(" protected: []")) throw new Error("templates/config.yml has no protected placeholder");
71
76
  return text.replace(" protected: []", list);
@@ -101,12 +106,12 @@ Empty until \`agent-score board\` writes this file. Do not hand-edit after that.
101
106
  `;
102
107
 
103
108
  /** Create the layout. Existing files are left byte-for-byte alone. */
104
- export function initHome(home: string, opts: { invoked?: string; env?: NodeJS.ProcessEnv } = {}): InitResult {
109
+ export function initHome(home: string, opts: { invoked?: string; env?: NodeJS.ProcessEnv; agentDir?: string } = {}): InitResult {
105
110
  const created: string[] = [];
106
111
  const unchanged: string[] = [];
107
112
  const invoked = opts.invoked ?? "";
108
113
  const cfgPath = configFile(home);
109
- putFile(cfgPath, configText(home, invoked), 0o644, created, unchanged);
114
+ putFile(cfgPath, configText(home, invoked, opts.agentDir), 0o644, created, unchanged);
110
115
 
111
116
  const cfg: Config = loadConfig({ home, env: opts.env ?? {} });
112
117
  putDir(cfg.paths.config_dir);
@@ -127,15 +132,13 @@ export function initHome(home: string, opts: { invoked?: string; env?: NodeJS.Pr
127
132
  putFile(cfg.paths.subagents, note("subagents.md"), 0o644, created, unchanged);
128
133
  putFile(join(cfg.paths.notes, "lessons.md"), note("lessons.md"), 0o644, created, unchanged);
129
134
  putFile(cfg.paths.ranking_board, RANKING_STUB, 0o644, created, unchanged);
130
- const queueText = readFileSync(join(PACKAGE_ROOT, "templates/queue/TEMPLATE.md"), "utf8");
131
- if (!queueText.includes("{{HOME}}")) throw new Error("templates/queue/TEMPLATE.md has no {{HOME}} placeholder");
132
- putFile(
133
- join(cfg.paths.agent_dir, "queue", "TEMPLATE.md"),
134
- queueText.replaceAll("{{HOME}}", home),
135
- 0o644,
136
- created,
137
- unchanged,
138
- );
135
+ // An adopted agent dir (--agent-dir) keeps queue/ for the harness adapter, which links its own
136
+ // queue/lib.ts and queue/TEMPLATE.md there; two writers for one slot would collide.
137
+ if (!opts.agentDir) {
138
+ const queueText = readFileSync(join(PACKAGE_ROOT, "templates/queue/TEMPLATE.md"), "utf8");
139
+ if (!queueText.includes("{{HOME}}")) throw new Error("templates/queue/TEMPLATE.md has no {{HOME}} placeholder");
140
+ putFile(join(cfg.paths.agent_dir, "queue", "TEMPLATE.md"), queueText.replaceAll("{{HOME}}", home), 0o644, created, unchanged);
141
+ }
139
142
  for (const b of BLOCKERS) {
140
143
  putFile(join(cfg.paths.blockers, b.name), blockerWrapper(b.fn), 0o755, created, unchanged);
141
144
  }
@@ -152,9 +155,12 @@ export function printInit(result: InitResult): void {
152
155
  if (result.unchanged.length) console.log(`neurastream init: left ${result.unchanged.length} existing file(s) alone`);
153
156
  }
154
157
 
155
- export function runInit(): number {
158
+ export function runInit(args: string[] = []): number {
156
159
  try {
157
- printInit(initHome(homedir(), { invoked: process.argv[1] ?? "", env: process.env }));
160
+ const i = args.indexOf("--agent-dir");
161
+ const agentDir = i >= 0 ? args[i + 1] : undefined;
162
+ if (i >= 0 && !agentDir) throw new Error("usage: neurastream init [--agent-dir <dir>]");
163
+ printInit(initHome(homedir(), { invoked: process.argv[1] ?? "", env: process.env, agentDir }));
158
164
  return 0;
159
165
  } catch (err) {
160
166
  console.error(err instanceof Error ? err.message : String(err));