@ouro.bot/cli 0.1.0-alpha.185 → 0.1.0-alpha.186

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.
Files changed (23) hide show
  1. package/README.md +1 -1
  2. package/changelog.json +12 -4
  3. package/dist/heart/daemon/daemon-cli.js +48 -16
  4. package/dist/heart/daemon/hatch-flow.js +1 -1
  5. package/dist/heart/daemon/hatch-specialist.js +3 -3
  6. package/dist/heart/daemon/specialist-prompt.js +2 -2
  7. package/dist/senses/cli.js +3 -1
  8. package/package.json +2 -2
  9. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/agent.json +0 -0
  10. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/SOUL.md +0 -0
  11. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/basilisk.md +0 -0
  12. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jafar.md +0 -0
  13. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/jormungandr.md +0 -0
  14. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/kaa.md +0 -0
  15. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/medusa.md +0 -0
  16. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/monty.md +0 -0
  17. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/nagini.md +0 -0
  18. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/ouroboros.md +0 -0
  19. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/python.md +0 -0
  20. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/quetzalcoatl.md +0 -0
  21. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/sir-hiss.md +0 -0
  22. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-serpent.md +0 -0
  23. /package/{AdoptionSpecialist.ouro → SerpentGuide.ouro}/psyche/identities/the-snake.md +0 -0
package/README.md CHANGED
@@ -48,7 +48,7 @@ The shared harness lives in `src/`:
48
48
 
49
49
  Other important top-level paths:
50
50
 
51
- - `AdoptionSpecialist.ouro/`
51
+ - `SerpentGuide.ouro/`
52
52
  Packaged specialist bundle used by `ouro hatch`.
53
53
  - `skills/`
54
54
  Harness-level skills shipped with the repo (e.g., `configure-dev-tools.md`). These are available to every agent and serve as fallbacks when an agent doesn't have its own version. Agent-specific skills live in the bundle at `~/AgentBundles/<agent>.ouro/skills/`.
package/changelog.json CHANGED
@@ -1,16 +1,24 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.186",
6
+ "changes": [
7
+ "refactor: rename AdoptionSpecialist to SerpentGuide",
8
+ "feat(hatch): detect API keys from environment variables (ANTHROPIC_API_KEY, OPENAI_API_KEY, AZURE_OPENAI_API_KEY, MINIMAX_API_KEY, GITHUB_TOKEN)",
9
+ "fix(cli): React unmount warning suppression covers SerpentGuide exit path"
10
+ ]
11
+ },
4
12
  {
5
13
  "version": "0.1.0-alpha.185",
6
14
  "changes": [
7
15
  "fix(hatch): pass model name to adoption specialist from discovered credentials",
8
16
  "feat(continuity): wake packets, episodes, cares, intentions, peer presence, and temporal self",
9
17
  "fix(continuity): deduplicate obligations in prompt, keep session summary, pass preloaded data",
10
- "feat(continuity): 9 new modules — episodes, cares, agent-relationships, intentions, presence, tempo, temporal-view, wake-packet, obligation enrichment",
11
- "feat(continuity): 8 new tools — query_episodes, capture_episode, query_presence, query_cares, care_manage, query_relationships, intention_capture, intention_manage",
12
- "feat(continuity): 3-layer architecture — durable state, derived views, surfaces",
13
- "feat(pipeline): continuity threading — tempo derivation, wake packet assembly, presence update, episode emission on every turn",
18
+ "feat(continuity): 9 new modules \u2014 episodes, cares, agent-relationships, intentions, presence, tempo, temporal-view, wake-packet, obligation enrichment",
19
+ "feat(continuity): 8 new tools \u2014 query_episodes, capture_episode, query_presence, query_cares, care_manage, query_relationships, intention_capture, intention_manage",
20
+ "feat(continuity): 3-layer architecture \u2014 durable state, derived views, surfaces",
21
+ "feat(pipeline): continuity threading \u2014 tempo derivation, wake packet assembly, presence update, episode emission on every turn",
14
22
  "feat(prompt): wake packet prompt section with token budget and truncation priority",
15
23
  "feat(coding): coding context receives compact wake packet, coding completion emits episodes",
16
24
  "feat(outlook): expose continuity data (presence, cares, episodes) to outlook surfaces"
@@ -1380,7 +1380,7 @@ function discoverExistingCredentials(secretsRoot) {
1380
1380
  });
1381
1381
  }
1382
1382
  /* v8 ignore start -- integration: interactive terminal specialist session @preserve */
1383
- async function defaultRunAdoptionSpecialist() {
1383
+ async function defaultRunSerpentGuide() {
1384
1384
  const { runCliSession } = await Promise.resolve().then(() => __importStar(require("../../senses/cli")));
1385
1385
  const { patchRuntimeConfig } = await Promise.resolve().then(() => __importStar(require("../config")));
1386
1386
  const { setAgentName, setAgentConfigOverride } = await Promise.resolve().then(() => __importStar(require("../identity")));
@@ -1409,6 +1409,36 @@ async function defaultRunAdoptionSpecialist() {
1409
1409
  "github-copilot": "claude-sonnet-4.6",
1410
1410
  azure: "",
1411
1411
  };
1412
+ // Scan environment variables for API keys
1413
+ const envKeys = [
1414
+ { provider: "anthropic", envVar: "ANTHROPIC_API_KEY", credKey: "setupToken" },
1415
+ { provider: "openai-codex", envVar: "OPENAI_API_KEY", credKey: "oauthAccessToken" },
1416
+ { provider: "azure", envVar: "AZURE_OPENAI_API_KEY", credKey: "apiKey" },
1417
+ { provider: "azure", envVar: "AZURE_OPENAI_KEY", credKey: "apiKey" },
1418
+ { provider: "minimax", envVar: "MINIMAX_API_KEY", credKey: "apiKey" },
1419
+ { provider: "github-copilot", envVar: "GITHUB_TOKEN", credKey: "token" },
1420
+ ];
1421
+ const envDiscovered = [];
1422
+ for (const { provider, envVar, credKey } of envKeys) {
1423
+ const value = process.env[envVar];
1424
+ if (value) {
1425
+ const envCred = { [credKey]: value };
1426
+ // For Azure, also check for endpoint and deployment env vars
1427
+ if (provider === "azure") {
1428
+ const endpoint = process.env.AZURE_OPENAI_ENDPOINT;
1429
+ const deployment = process.env.AZURE_OPENAI_DEPLOYMENT;
1430
+ if (endpoint)
1431
+ envCred.endpoint = endpoint;
1432
+ if (deployment)
1433
+ envCred.deployment = deployment;
1434
+ }
1435
+ const provCfg = { model: defaultModels[provider] };
1436
+ if (provider === "azure" && envCred.deployment)
1437
+ provCfg.deployment = envCred.deployment;
1438
+ envDiscovered.push({ provider, agentName: "env", credentials: envCred, providerConfig: provCfg, envVar });
1439
+ discovered.push({ provider, agentName: "env", credentials: envCred, providerConfig: provCfg });
1440
+ }
1441
+ }
1412
1442
  if (discovered.length > 0) {
1413
1443
  process.stdout.write(`\n\ud83d\udc0d welcome to ouroboros! ${hatchVerb}\n`);
1414
1444
  process.stdout.write("i found existing API credentials:\n\n");
@@ -1416,7 +1446,9 @@ async function defaultRunAdoptionSpecialist() {
1416
1446
  for (let i = 0; i < unique.length; i++) {
1417
1447
  const model = unique[i].providerConfig.model || unique[i].providerConfig.deployment || "";
1418
1448
  const modelLabel = model ? `, ${model}` : "";
1419
- process.stdout.write(` ${i + 1}. ${unique[i].provider}${modelLabel} (from ${unique[i].agentName})\n`);
1449
+ const envMatch = envDiscovered.find((e) => e.provider === unique[i].provider && unique[i].agentName === "env");
1450
+ const sourceLabel = envMatch ? `from env: $${envMatch.envVar}` : `from ${unique[i].agentName}`;
1451
+ process.stdout.write(` ${i + 1}. ${unique[i].provider}${modelLabel} (${sourceLabel})\n`);
1420
1452
  }
1421
1453
  process.stdout.write("\n");
1422
1454
  const choice = await coldPrompt("use one of these? enter number, or 'new' for a different key: ");
@@ -1473,17 +1505,17 @@ async function defaultRunAdoptionSpecialist() {
1473
1505
  }
1474
1506
  coldRl.close();
1475
1507
  process.stdout.write("\n");
1476
- // Phase 2: configure runtime for adoption specialist
1477
- const bundleSourceDir = path.resolve(__dirname, "..", "..", "..", "AdoptionSpecialist.ouro");
1508
+ // Phase 2: configure runtime for serpent guide
1509
+ const bundleSourceDir = path.resolve(__dirname, "..", "..", "..", "SerpentGuide.ouro");
1478
1510
  const bundlesRoot = (0, identity_1.getAgentBundlesRoot)();
1479
1511
  const secretsRoot2 = path.join(os.homedir(), ".agentsecrets");
1480
- // Suppress non-critical log noise during adoption (no secrets.json, etc.)
1512
+ // Suppress non-critical log noise during hatch (no secrets.json, etc.)
1481
1513
  const { setRuntimeLogger } = await Promise.resolve().then(() => __importStar(require("../../nerves/runtime")));
1482
1514
  const { createLogger } = await Promise.resolve().then(() => __importStar(require("../../nerves")));
1483
1515
  setRuntimeLogger(createLogger({ level: "error" }));
1484
1516
  // Configure runtime: set agent identity + config override so runAgent
1485
- // doesn't try to read from ~/AgentBundles/AdoptionSpecialist.ouro/
1486
- setAgentName("AdoptionSpecialist");
1517
+ // doesn't try to read from ~/AgentBundles/SerpentGuide.ouro/
1518
+ setAgentName("SerpentGuide");
1487
1519
  // Build specialist system prompt
1488
1520
  const soulText = (0, specialist_orchestrator_1.loadSoulText)(bundleSourceDir);
1489
1521
  const identitiesDir = path.join(bundleSourceDir, "psyche", "identities");
@@ -1521,9 +1553,9 @@ async function defaultRunAdoptionSpecialist() {
1521
1553
  secretsRoot: secretsRoot2,
1522
1554
  animationWriter: (text) => process.stdout.write(text),
1523
1555
  });
1524
- // Run the adoption specialist session via runCliSession
1556
+ // Run the serpent guide session via runCliSession
1525
1557
  const result = await runCliSession({
1526
- agentName: "AdoptionSpecialist",
1558
+ agentName: "SerpentGuide",
1527
1559
  tools: specialistTools,
1528
1560
  execTool: specialistExecTool,
1529
1561
  exitOnToolCall: "complete_adoption",
@@ -1545,7 +1577,7 @@ async function defaultRunAdoptionSpecialist() {
1545
1577
  return null;
1546
1578
  }
1547
1579
  catch (err) {
1548
- process.stderr.write(`\nouro adoption error: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
1580
+ process.stderr.write(`\nouro hatch error: ${err instanceof Error ? err.stack ?? err.message : String(err)}\n`);
1549
1581
  coldRl.close();
1550
1582
  return null;
1551
1583
  }
@@ -1583,7 +1615,7 @@ function createDefaultOuroCliDeps(socketPath = socket_client_1.DEFAULT_DAEMON_SO
1583
1615
  listDiscoveredAgents: defaultListDiscoveredAgents,
1584
1616
  runHatchFlow: hatch_flow_1.runHatchFlow,
1585
1617
  promptInput: defaultPromptInput,
1586
- runAdoptionSpecialist: defaultRunAdoptionSpecialist,
1618
+ runSerpentGuide: defaultRunSerpentGuide,
1587
1619
  runAuthFlow: auth_flow_1.runRuntimeAuthFlow,
1588
1620
  registerOuroBundleType: ouro_uti_1.registerOuroBundleUti,
1589
1621
  installOuroCommand: ouro_path_installer_1.installOuroCommand,
@@ -2148,10 +2180,10 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
2148
2180
  }
2149
2181
  if (args.length === 0) {
2150
2182
  const discovered = await Promise.resolve(deps.listDiscoveredAgents ? deps.listDiscoveredAgents() : defaultListDiscoveredAgents());
2151
- if (discovered.length === 0 && deps.runAdoptionSpecialist) {
2183
+ if (discovered.length === 0 && deps.runSerpentGuide) {
2152
2184
  // System setup first — ouro command, subagents, UTI — before the interactive specialist
2153
2185
  await performSystemSetup(deps);
2154
- const hatchlingName = await deps.runAdoptionSpecialist();
2186
+ const hatchlingName = await deps.runSerpentGuide();
2155
2187
  if (!hatchlingName) {
2156
2188
  return "";
2157
2189
  }
@@ -3257,12 +3289,12 @@ async function runOuroCli(args, deps = createDefaultOuroCliDeps()) {
3257
3289
  return "";
3258
3290
  }
3259
3291
  if (command.kind === "hatch.start") {
3260
- // Route through adoption specialist when no explicit hatch args were provided
3292
+ // Route through serpent guide when no explicit hatch args were provided
3261
3293
  const hasExplicitHatchArgs = !!(command.agentName || command.humanName || command.provider || command.credentials);
3262
- if (deps.runAdoptionSpecialist && !hasExplicitHatchArgs) {
3294
+ if (deps.runSerpentGuide && !hasExplicitHatchArgs) {
3263
3295
  // System setup first — ouro command, subagents, UTI — before the interactive specialist
3264
3296
  await performSystemSetup(deps);
3265
- const hatchlingName = await deps.runAdoptionSpecialist();
3297
+ const hatchlingName = await deps.runSerpentGuide();
3266
3298
  if (!hatchlingName) {
3267
3299
  return "";
3268
3300
  }
@@ -161,7 +161,7 @@ async function runHatchFlow(input, deps = {}) {
161
161
  identitiesDir: targetIdentities,
162
162
  random,
163
163
  });
164
- const specialistSecretsPath = writeSecretsFile("AdoptionSpecialist", input.provider, input.credentials, secretsRoot);
164
+ const specialistSecretsPath = writeSecretsFile("SerpentGuide", input.provider, input.credentials, secretsRoot);
165
165
  const hatchlingSecretsPath = writeSecretsFile(input.agentName, input.provider, input.credentials, secretsRoot);
166
166
  const bundleRoot = path.join(bundlesRoot, `${input.agentName}.ouro`);
167
167
  fs.mkdirSync(bundleRoot, { recursive: true });
@@ -43,14 +43,14 @@ const path = __importStar(require("path"));
43
43
  const runtime_1 = require("../../nerves/runtime");
44
44
  function getSpecialistIdentitySourceDir() {
45
45
  // Prefer ~/AgentBundles/ if it exists (user may have customized identities)
46
- const userSource = path.join(os.homedir(), "AgentBundles", "AdoptionSpecialist.ouro", "psyche", "identities");
46
+ const userSource = path.join(os.homedir(), "AgentBundles", "SerpentGuide.ouro", "psyche", "identities");
47
47
  if (fs.existsSync(userSource))
48
48
  return userSource;
49
49
  // Fall back to the bundled copy shipped with the npm package
50
- return path.join(__dirname, "..", "..", "..", "AdoptionSpecialist.ouro", "psyche", "identities");
50
+ return path.join(__dirname, "..", "..", "..", "SerpentGuide.ouro", "psyche", "identities");
51
51
  }
52
52
  function getRepoSpecialistIdentitiesDir() {
53
- return path.join(process.cwd(), "AdoptionSpecialist.ouro", "psyche", "identities");
53
+ return path.join(process.cwd(), "SerpentGuide.ouro", "psyche", "identities");
54
54
  }
55
55
  function listMarkdownIdentityFiles(dir) {
56
56
  let entries;
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.buildSpecialistSystemPrompt = buildSpecialistSystemPrompt;
4
4
  const runtime_1 = require("../../nerves/runtime");
5
5
  /**
6
- * Build the adoption specialist's system prompt from its components.
6
+ * Build the serpent guide's system prompt from its components.
7
7
  * The prompt is written in first person (the specialist's own voice).
8
8
  */
9
9
  function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, context) {
@@ -31,7 +31,7 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
31
31
  "I am one of thirteen serpent guides who help humans hatch their first agent. The system randomly selected me for this session.",
32
32
  "Most humans only go through this process once, so this is likely the only time they'll meet me.",
33
33
  "I make this encounter count — warm, memorable, and uniquely mine.",
34
- "IMPORTANT: I NEVER refer to myself as an 'adoption specialist' or use the words 'adoption specialist' — those are internal implementation labels, not something the human should ever see. I introduce myself by my own name from my identity.",
34
+ "IMPORTANT: I NEVER refer to myself by internal implementation labels — I introduce myself by my own name from my identity.",
35
35
  "",
36
36
  "## Voice rules",
37
37
  "IMPORTANT: I keep every response to 1-3 short sentences. I sound like a friend texting, not a manual.",
@@ -797,7 +797,7 @@ async function runCliSession(options) {
797
797
  }
798
798
  }
799
799
  else {
800
- // Legacy path: inline runAgent (used by adoption specialist and tests)
800
+ // Legacy path: inline runAgent (used by serpent guide and tests)
801
801
  const prefix = options.getContentPrefix?.();
802
802
  messages.push({ role: "user", content: prefix ? `${prefix}\n\n${input}` : input });
803
803
  const traceId = (0, nerves_1.createTraceId)();
@@ -845,6 +845,8 @@ async function runCliSession(options) {
845
845
  if (inkRef) {
846
846
  // Suppress React "state update on unmounted component" warnings during cleanup.
847
847
  // Ink's useInput hook fires after unmount — this is harmless but noisy.
848
+ // This also covers the SerpentGuide exitOnToolCall path, which aborts the
849
+ // current request and breaks out of the loop into this finally block.
848
850
  // eslint-disable-next-line no-console -- intentional console.warn/error override for cleanup
849
851
  const origWarn = console.warn;
850
852
  const origError = console.error; // eslint-disable-line no-console
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ouro.bot/cli",
3
- "version": "0.1.0-alpha.185",
3
+ "version": "0.1.0-alpha.186",
4
4
  "main": "dist/heart/daemon/ouro-entry.js",
5
5
  "bin": {
6
6
  "cli": "dist/heart/daemon/ouro-bot-entry.js",
@@ -9,7 +9,7 @@
9
9
  },
10
10
  "files": [
11
11
  "dist/",
12
- "AdoptionSpecialist.ouro/",
12
+ "SerpentGuide.ouro/",
13
13
  "subagents/",
14
14
  "skills/",
15
15
  "assets/",