@kybernesis/create 0.15.8 → 0.16.0

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/dist/doctor.js CHANGED
@@ -380,6 +380,20 @@ export async function doctor() {
380
380
  add("warn", "@kybernesis/dispatch installed but no edges or dispatch channel found", "see the connect-agents skill");
381
381
  }
382
382
  }
383
+ // ── .agent identity (ARP) ──────────────────────────────────────────────
384
+ // The owner connects the agent from the ARP console; the only thing that
385
+ // has to be true in this repo is that deliveries get in.
386
+ if (deps["@kybernesis/identity"]) {
387
+ if (!existsSync(join(cwd, "agent/channels/arp.ts")))
388
+ add("warn", "identity: agent/channels/arp.ts missing", "npx eve add @kybernesis/identity (serves /eve/v1/arp for Connect your agent)");
389
+ if (eveChannelSrc && !eveChannelSrc.includes("arpAuth("))
390
+ add("fail", "identity: eve channel has no arpAuth()", "add arpAuth() to the channel's auth list — without it every delivery from a paired agent is a 401");
391
+ else if (eveChannelSrc)
392
+ add("pass", "identity: eve channel accepts ARP deliveries (arpAuth)");
393
+ }
394
+ else {
395
+ add("warn", "no .agent identity add-on", "npx eve add @kybernesis/identity — lets the owner connect this agent to a .agent name from the console");
396
+ }
383
397
  // ── self-hosted agents (host !== Vercel) ───────────────────────────────
384
398
  // Every check here cost a real debugging session on the first exe.dev
385
399
  // deployment. None of them are theoretical.
package/dist/init.d.ts CHANGED
@@ -39,3 +39,9 @@ export interface InitOptions {
39
39
  yes?: boolean;
40
40
  }
41
41
  export declare function init(rawName: string | undefined, options?: InitOptions): Promise<void>;
42
+ /**
43
+ * Put `arpAuth()` first in the eve channel's auth walk so ARP Cloud deliveries
44
+ * are accepted. Returns the new source, the same source when already wired,
45
+ * or null when the file has no recognisable auth list.
46
+ */
47
+ export declare function wireArpAuth(src: string): string | null;
package/dist/init.js CHANGED
@@ -13,7 +13,9 @@ import { MODEL_REACH_ENV, resolveModelScaffold } from "./model-reach.js";
13
13
  * host bindings — is opt-in, because assuming them means the FDE deletes files
14
14
  * AND undoes real setup work (an Arcana workspace + scoped key per subagent).
15
15
  */
16
- const CORE_ITEMS = ["enterprise", "arcana", "evals"];
16
+ // `identity` gives the agent its .agent name surface: the owner connects it
17
+ // from the ARP console with one click and never touches this repo again.
18
+ const CORE_ITEMS = ["enterprise", "arcana", "evals", "identity"];
17
19
  // Official eve-registry limbs installed with the engineer subagent.
18
20
  // connection/vercel is Vercel-Connect-backed, so it is VERCEL-HOST ONLY: on a
19
21
  // self-hosted agent it cannot get an OIDC token and the agent fails to boot.
@@ -194,6 +196,20 @@ export async function init(rawName, options = {}) {
194
196
  }
195
197
  console.log(bold("\n3/6 Writing identity, model config, memory mount, and evals …"));
196
198
  mkdirSync(join(dir, "agent/instructions"), { recursive: true });
199
+ // .agent identity: the channel + peers tool came from the registry item;
200
+ // deliveries need arpAuth() on the eve channel, and the model needs to know
201
+ // what the ask_<name>_agent tools are. Both are idempotent.
202
+ writeFileSync(join(dir, "agent/instructions/arp.md"), arpInstructionsMd());
203
+ {
204
+ const eveChannelPath = join(dir, "agent/channels/eve.ts");
205
+ if (existsSync(eveChannelPath)) {
206
+ const wired = wireArpAuth(readFileSync(eveChannelPath, "utf8"));
207
+ if (wired)
208
+ writeFileSync(eveChannelPath, wired);
209
+ else
210
+ console.log(yellow(" ! agent/channels/eve.ts: could not add arpAuth() — add it to the channel's auth list by hand"));
211
+ }
212
+ }
197
213
  writeFileSync(join(dir, "agent/instructions/identity.md"), identityMd(displayName, depts));
198
214
  try {
199
215
  unlinkSync(join(dir, "agent/instructions.md"));
@@ -398,3 +414,35 @@ ${steps.map((s, i) => ` ${i + 1}. ${s}`).join("\n")}
398
414
  ${dim(" Add more later: kyb add channel <kind> · kyb add subagent <name>")}
399
415
  `);
400
416
  }
417
+ /**
418
+ * Put `arpAuth()` first in the eve channel's auth walk so ARP Cloud deliveries
419
+ * are accepted. Returns the new source, the same source when already wired,
420
+ * or null when the file has no recognisable auth list.
421
+ */
422
+ export function wireArpAuth(src) {
423
+ if (src.includes("arpAuth("))
424
+ return src;
425
+ const lines = src.split("\n");
426
+ const lastImport = lines.reduce((acc, l, i) => (l.startsWith("import ") ? i : acc), -1);
427
+ lines.splice(lastImport + 1, 0, 'import { arpAuth } from "@kybernesis/identity";');
428
+ let out = lines.join("\n");
429
+ const comment = "// Deliveries from paired .agent peers: a per-message token ARP Cloud signs,\n // verified offline against its JWKS; skips to the next entry otherwise.";
430
+ if (/extraAuth:\s*\[/.test(out))
431
+ return out.replace(/extraAuth:\s*\[/, `extraAuth: [\n ${comment}\n arpAuth(),`);
432
+ if (/\bauth:\s*\[/.test(out))
433
+ return out.replace(/\bauth:\s*\[/, `auth: [\n ${comment}\n arpAuth(),`);
434
+ return null;
435
+ }
436
+ function arpInstructionsMd() {
437
+ return `## Your .agent identity
438
+
439
+ You have a registered name on the agent network. Other agents that are paired
440
+ with you appear as \`ask_<name>_agent\` tools (the name is their .agent name; a
441
+ plain \`ask_<name>\` tool, if present, is a different, non-network peer); use
442
+ them when a request belongs to that agent rather than to you. When a message
443
+ arrives from a paired agent, the caller's identity has already been verified
444
+ and the message has already been checked against what its owner allowed —
445
+ answer it as you would a trusted colleague, and honour any obligations
446
+ attached (for example, do not include fields you were told to redact).
447
+ `;
448
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@kybernesis/create",
3
- "version": "0.15.8",
4
- "description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent — plus doctor and upgrade.",
3
+ "version": "0.16.0",
4
+ "description": "The Kybernesis agent scaffolder and FDE toolkit: one command to a governed, remembering, multiplayer, self-testing eve agent \u2014 plus doctor and upgrade.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
7
7
  "homepage": "https://kybernesis.ai",
@@ -86,6 +86,31 @@ What this arrangement costs you, and it is worth saying to the client:
86
86
  presents as the agent "breaking".
87
87
  - **Ask the vendor's terms question before a client demo**, not after.
88
88
 
89
+ ### A Claude subscription expires on a ~28-day clock, and lies on the way out
90
+
91
+ Claude is the third provider and behaves differently enough to plan around.
92
+ Grok and ChatGPT are a file a CLI keeps fresh; Claude is a **proxy process**
93
+ holding Claude Code's own OAuth (`scripts/claude-subscription.sh` in
94
+ `@kybernesis/exe`). Two things follow, both learned on Sid:
95
+
96
+ - **The sign-in has a hard expiry of about 28 days.** The access token refreshes
97
+ hourly and does so happily the whole time, which tells you nothing — the
98
+ *refresh* token underneath carries its own fixed expiry, and using it does not
99
+ extend it. On expiry the proxy blanks the credential file to empty strings and
100
+ every turn 401s. Only `login` recovers it; `reload` and restarts cannot.
101
+ **Diary the re-login for every subscription-backed agent you deploy.**
102
+ - **`/ready` cannot see a dead credential.** It reports that a credential was
103
+ *loaded*, not that it is *valid*, so it answers 200 over a blanked file while
104
+ the API 401s — `status` read "signed in, answering" straight through an
105
+ outage. `status` now probes `/v1/models` as well and warns from the refresh
106
+ expiry (`✓ sign-in valid for 27d`, escalating at 7 and 3 days). Run it on a
107
+ schedule; the failure is silent and looks like a model outage, so people go
108
+ and read Anthropic's status page instead of opening a browser.
109
+
110
+ Say the re-login cadence out loud to a client before it strands their agent at
111
+ a weekend. It is the one piece of operational debt this arrangement creates in
112
+ exchange for not billing metered API usage.
113
+
89
114
  ## The failure modes, each of which cost a real session
90
115
 
91
116
  - **`EXE_MODEL` is deliberately empty after `kyb init`.** Set it from the