@kybernesis/create 0.26.3 → 0.26.4

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/buzz.js CHANGED
@@ -2,6 +2,7 @@ import { existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync
2
2
  import { tmpdir, userInfo } from "node:os";
3
3
  import { basename, join, resolve } from "node:path";
4
4
  import { upsertEnv } from "./envfile.js";
5
+ import { buzzBridgeUnitsFor } from "./systemd.js";
5
6
  import { bold, capture, dim, green, linePackage, red, run, yellow } from "./util.js";
6
7
  /**
7
8
  * `kyb add buzz` — get an agent ready for its owner's Buzz community.
@@ -32,7 +33,7 @@ export function buzzKeyPath(appDir) {
32
33
  return join(appDir, ".buzz", "agent-key.json");
33
34
  }
34
35
  export function buzzBridgeUnitName(agent) {
35
- return `${agent}-buzz-bridge`;
36
+ return `${agent.toLowerCase()}-buzz-bridge`;
36
37
  }
37
38
  /** The bridge's systemd unit. Pure, so the test pins what every host gets. */
38
39
  export function buzzBridgeUnit(input) {
@@ -119,6 +120,15 @@ export function addBuzz(cwd = resolve(process.cwd())) {
119
120
  console.log(yellow(" ! no docker here, so the Buzz CLI was not built; the agent can talk in Buzz but not act in it."));
120
121
  }
121
122
  }
123
+ // A bridge already serving this folder is this agent's bridge, whatever it is called.
124
+ // Installing another beside it would answer every message twice.
125
+ const existingUnits = buzzBridgeUnitsFor(cwd);
126
+ if (existingUnits.length > 0) {
127
+ console.log(dim(` bridge: ${existingUnits.join(", ")} already serves this agent`));
128
+ console.log(bold("\n Next:"));
129
+ console.log(` · The owner connects it from the Channels page: their community's address, then an admin adds ${npub} as a member.`);
130
+ return;
131
+ }
122
132
  const unitName = buzzBridgeUnitName(agent);
123
133
  const dir = mkdtempSync(join(tmpdir(), "kyb-buzz-"));
124
134
  try {
package/dist/doctor.js CHANGED
@@ -3,7 +3,7 @@ import { TEMPLATE_CONTAINER_PROBE, parseTemplateContainers, templateContainerDoc
3
3
  import { join } from "node:path";
4
4
  import { pathToFileURL } from "node:url";
5
5
  import { EVE_VERSION, REGISTRY_URL, bold, capture, dim, green, parseEnv, red, yellow } from "./util.js";
6
- import { diagnoseManageRestart, findMatchingAgentServiceUnit } from "./systemd.js";
6
+ import { buzzBridgeUnitsFor, diagnoseManageRestart, findMatchingAgentServiceUnit } from "./systemd.js";
7
7
  import { inspectEveAgent } from "./agent-limits.js";
8
8
  import { classifyModelReach } from "./model-reach.js";
9
9
  import { countAbandonedRuns } from "./run-store.js";
@@ -195,6 +195,11 @@ export async function doctor() {
195
195
  * two changes signed off as deployed were live nowhere. Nothing looked
196
196
  * broken — the old code simply kept doing what it did.
197
197
  */
198
+ // One bridge per agent: two answer every Buzz message twice.
199
+ const bridges = buzzBridgeUnitsFor(cwd);
200
+ if (bridges.length > 1) {
201
+ add("fail", `${bridges.length} Buzz bridges run for this agent (${bridges.join(", ")})`, `Each answers every message, so people get every answer twice. Keep the one deploy.sh restarts and remove the rest: sudo systemctl disable --now <unit> && sudo rm /etc/systemd/system/<unit>.service && sudo systemctl daemon-reload`);
202
+ }
198
203
  const packageChange = newestPackageChange(cwd);
199
204
  const started = new Map();
200
205
  for (const unit of listAgentUnits()) {
package/dist/systemd.d.ts CHANGED
@@ -21,6 +21,14 @@ export interface InstalledAgentService {
21
21
  values: UnitValues;
22
22
  mode: number;
23
23
  }
24
+ /**
25
+ * The Buzz bridge units that run in this agent's folder, whatever they are called.
26
+ *
27
+ * A bridge belongs to an agent by the folder it runs in, not by its name: a
28
+ * second unit with another name ("Kyber-buzz-bridge" beside "kyber-buzz-bridge")
29
+ * is a second bridge on the same key, and every message is answered twice.
30
+ */
31
+ export declare function buzzBridgeUnitsFor(cwd: string, systemdDir?: string): string[];
24
32
  export declare function findMatchingAgentServiceUnit(cwd: string, systemdDir?: string): InstalledAgentService | null;
25
33
  /**
26
34
  * Refresh an existing package-generated unit. Deliberately never creates a
package/dist/systemd.js CHANGED
@@ -83,6 +83,28 @@ function dropIns(dir) {
83
83
  return [];
84
84
  }
85
85
  }
86
+ /**
87
+ * The Buzz bridge units that run in this agent's folder, whatever they are called.
88
+ *
89
+ * A bridge belongs to an agent by the folder it runs in, not by its name: a
90
+ * second unit with another name ("Kyber-buzz-bridge" beside "kyber-buzz-bridge")
91
+ * is a second bridge on the same key, and every message is answered twice.
92
+ */
93
+ export function buzzBridgeUnitsFor(cwd, systemdDir = "/etc/systemd/system") {
94
+ try {
95
+ return readdirSync(systemdDir)
96
+ .filter((entry) => /buzz-bridge.*\.service$/.test(entry))
97
+ .filter((file) => {
98
+ const dir = readFileSync(join(systemdDir, file), "utf8").match(/^WorkingDirectory=(.+)$/m)?.[1]?.trim();
99
+ return dir !== undefined && resolve(dir) === resolve(cwd);
100
+ })
101
+ .map((file) => file.replace(/\.service$/, ""))
102
+ .sort();
103
+ }
104
+ catch {
105
+ return [];
106
+ }
107
+ }
86
108
  export function findMatchingAgentServiceUnit(cwd, systemdDir = "/etc/systemd/system") {
87
109
  try {
88
110
  for (const file of readdirSync(systemdDir).filter((entry) => entry.endsWith("-agent.service"))) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kybernesis/create",
3
- "version": "0.26.3",
3
+ "version": "0.26.4",
4
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",