@cotal-ai/cli 0.6.0 → 0.8.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.
Files changed (135) hide show
  1. package/dist/commands/channels.d.ts +4 -2
  2. package/dist/commands/channels.d.ts.map +1 -1
  3. package/dist/commands/channels.js +17 -18
  4. package/dist/commands/channels.js.map +1 -1
  5. package/dist/commands/console.d.ts.map +1 -1
  6. package/dist/commands/console.js +13 -29
  7. package/dist/commands/console.js.map +1 -1
  8. package/dist/commands/down-manifest.d.ts +6 -0
  9. package/dist/commands/down-manifest.d.ts.map +1 -0
  10. package/dist/commands/down-manifest.js +282 -0
  11. package/dist/commands/down-manifest.js.map +1 -0
  12. package/dist/commands/down.d.ts +5 -3
  13. package/dist/commands/down.d.ts.map +1 -1
  14. package/dist/commands/down.js +30 -3
  15. package/dist/commands/down.js.map +1 -1
  16. package/dist/commands/history.d.ts.map +1 -1
  17. package/dist/commands/history.js +6 -13
  18. package/dist/commands/history.js.map +1 -1
  19. package/dist/commands/join.d.ts.map +1 -1
  20. package/dist/commands/join.js +20 -7
  21. package/dist/commands/join.js.map +1 -1
  22. package/dist/commands/meshes.d.ts +5 -0
  23. package/dist/commands/meshes.d.ts.map +1 -0
  24. package/dist/commands/meshes.js +25 -0
  25. package/dist/commands/meshes.js.map +1 -0
  26. package/dist/commands/mint.d.ts.map +1 -1
  27. package/dist/commands/mint.js +2 -1
  28. package/dist/commands/mint.js.map +1 -1
  29. package/dist/commands/setup.d.ts.map +1 -1
  30. package/dist/commands/setup.js +66 -16
  31. package/dist/commands/setup.js.map +1 -1
  32. package/dist/commands/spawn-manifest.d.ts +10 -0
  33. package/dist/commands/spawn-manifest.d.ts.map +1 -0
  34. package/dist/commands/spawn-manifest.js +197 -0
  35. package/dist/commands/spawn-manifest.js.map +1 -0
  36. package/dist/commands/spawn.d.ts +4 -2
  37. package/dist/commands/spawn.d.ts.map +1 -1
  38. package/dist/commands/spawn.js +84 -25
  39. package/dist/commands/spawn.js.map +1 -1
  40. package/dist/commands/topology.d.ts +10 -0
  41. package/dist/commands/topology.d.ts.map +1 -0
  42. package/dist/commands/topology.js +46 -0
  43. package/dist/commands/topology.js.map +1 -0
  44. package/dist/commands/up.d.ts +4 -0
  45. package/dist/commands/up.d.ts.map +1 -1
  46. package/dist/commands/up.js +223 -6
  47. package/dist/commands/up.js.map +1 -1
  48. package/dist/commands/use.d.ts +7 -0
  49. package/dist/commands/use.d.ts.map +1 -0
  50. package/dist/commands/use.js +27 -0
  51. package/dist/commands/use.js.map +1 -0
  52. package/dist/commands/web.d.ts.map +1 -1
  53. package/dist/commands/web.js +60 -28
  54. package/dist/commands/web.js.map +1 -1
  55. package/dist/index.d.ts.map +1 -1
  56. package/dist/index.js +27 -2
  57. package/dist/index.js.map +1 -1
  58. package/dist/lib/connect.d.ts +74 -0
  59. package/dist/lib/connect.d.ts.map +1 -0
  60. package/dist/lib/connect.js +91 -0
  61. package/dist/lib/connect.js.map +1 -0
  62. package/dist/lib/delivery-proc.d.ts.map +1 -1
  63. package/dist/lib/delivery-proc.js +2 -1
  64. package/dist/lib/delivery-proc.js.map +1 -1
  65. package/dist/lib/manager-proc.d.ts +4 -0
  66. package/dist/lib/manager-proc.d.ts.map +1 -1
  67. package/dist/lib/manager-proc.js +17 -0
  68. package/dist/lib/manager-proc.js.map +1 -1
  69. package/dist/lib/manifest/apply.d.ts +29 -0
  70. package/dist/lib/manifest/apply.d.ts.map +1 -0
  71. package/dist/lib/manifest/apply.js +138 -0
  72. package/dist/lib/manifest/apply.js.map +1 -0
  73. package/dist/lib/manifest/errors.d.ts +21 -0
  74. package/dist/lib/manifest/errors.d.ts.map +1 -0
  75. package/dist/lib/manifest/errors.js +19 -0
  76. package/dist/lib/manifest/errors.js.map +1 -0
  77. package/dist/lib/manifest/index.d.ts +13 -0
  78. package/dist/lib/manifest/index.d.ts.map +1 -0
  79. package/dist/lib/manifest/index.js +21 -0
  80. package/dist/lib/manifest/index.js.map +1 -0
  81. package/dist/lib/manifest/ledger.d.ts +81 -0
  82. package/dist/lib/manifest/ledger.d.ts.map +1 -0
  83. package/dist/lib/manifest/ledger.js +213 -0
  84. package/dist/lib/manifest/ledger.js.map +1 -0
  85. package/dist/lib/manifest/live.d.ts +25 -0
  86. package/dist/lib/manifest/live.d.ts.map +1 -0
  87. package/dist/lib/manifest/live.js +61 -0
  88. package/dist/lib/manifest/live.js.map +1 -0
  89. package/dist/lib/manifest/model.d.ts +71 -0
  90. package/dist/lib/manifest/model.d.ts.map +1 -0
  91. package/dist/lib/manifest/model.js +2 -0
  92. package/dist/lib/manifest/model.js.map +1 -0
  93. package/dist/lib/manifest/preflight.d.ts +12 -0
  94. package/dist/lib/manifest/preflight.d.ts.map +1 -0
  95. package/dist/lib/manifest/preflight.js +43 -0
  96. package/dist/lib/manifest/preflight.js.map +1 -0
  97. package/dist/lib/manifest/prepare.d.ts +57 -0
  98. package/dist/lib/manifest/prepare.d.ts.map +1 -0
  99. package/dist/lib/manifest/prepare.js +95 -0
  100. package/dist/lib/manifest/prepare.js.map +1 -0
  101. package/dist/lib/manifest/render.d.ts +41 -0
  102. package/dist/lib/manifest/render.d.ts.map +1 -0
  103. package/dist/lib/manifest/render.js +177 -0
  104. package/dist/lib/manifest/render.js.map +1 -0
  105. package/dist/lib/manifest/resolve.d.ts +5 -0
  106. package/dist/lib/manifest/resolve.d.ts.map +1 -0
  107. package/dist/lib/manifest/resolve.js +185 -0
  108. package/dist/lib/manifest/resolve.js.map +1 -0
  109. package/dist/lib/manifest/schema.d.ts +103 -0
  110. package/dist/lib/manifest/schema.d.ts.map +1 -0
  111. package/dist/lib/manifest/schema.js +77 -0
  112. package/dist/lib/manifest/schema.js.map +1 -0
  113. package/dist/lib/manifest/spawn-plan.d.ts +87 -0
  114. package/dist/lib/manifest/spawn-plan.d.ts.map +1 -0
  115. package/dist/lib/manifest/spawn-plan.js +75 -0
  116. package/dist/lib/manifest/spawn-plan.js.map +1 -0
  117. package/dist/lib/meshes.d.ts +2 -0
  118. package/dist/lib/meshes.d.ts.map +1 -0
  119. package/dist/lib/meshes.js +6 -0
  120. package/dist/lib/meshes.js.map +1 -0
  121. package/dist/lib/onboard.js +6 -6
  122. package/dist/lib/onboard.js.map +1 -1
  123. package/dist/lib/paths.js +1 -1
  124. package/dist/lib/paths.js.map +1 -1
  125. package/dist/lib/status.d.ts.map +1 -1
  126. package/dist/lib/status.js +2 -1
  127. package/dist/lib/status.js.map +1 -1
  128. package/dist/lib/transient.d.ts +7 -6
  129. package/dist/lib/transient.d.ts.map +1 -1
  130. package/dist/lib/transient.js +6 -25
  131. package/dist/lib/transient.js.map +1 -1
  132. package/dist/web/graph.html +207 -0
  133. package/dist/web/graph.js +508 -0
  134. package/dist/web/index.html +6 -0
  135. package/package.json +6 -2
@@ -1,15 +1,15 @@
1
1
  import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
- import { homedir } from "node:os";
3
2
  import { join } from "node:path";
3
+ import { homeCotalDir } from "@cotal-ai/workspace";
4
4
  /** Machine-level "I've onboarded before" marker. Its presence flips `cotal` from the
5
5
  * full first-run flow to the compact ensure+status run. Lives next to the materialized
6
- * plugin marketplace under ~/.cotal. */
7
- const MARKER = join(homedir(), ".cotal", "onboarded.json");
6
+ * plugin marketplace under ~/.cotal (COTAL_HOME-overridable, via {@link homeCotalDir}). */
7
+ const MARKER = () => join(homeCotalDir(), "onboarded.json");
8
8
  export function isOnboarded() {
9
- return existsSync(MARKER);
9
+ return existsSync(MARKER());
10
10
  }
11
11
  export function markOnboarded(version) {
12
- mkdirSync(join(homedir(), ".cotal"), { recursive: true });
13
- writeFileSync(MARKER, JSON.stringify({ version, ts: new Date().toISOString() }, null, 2));
12
+ mkdirSync(homeCotalDir(), { recursive: true, mode: 0o700 });
13
+ writeFileSync(MARKER(), JSON.stringify({ version, ts: new Date().toISOString() }, null, 2));
14
14
  }
15
15
  //# sourceMappingURL=onboard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"onboard.js","sourceRoot":"","sources":["../../src/lib/onboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;yCAEyC;AACzC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,gBAAgB,CAAC,CAAC;AAE3D,MAAM,UAAU,WAAW;IACzB,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC;AAC5B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC1D,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC"}
1
+ {"version":3,"file":"onboard.js","sourceRoot":"","sources":["../../src/lib/onboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC/D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;4FAE4F;AAC5F,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,EAAE,gBAAgB,CAAC,CAAC;AAE5D,MAAM,UAAU,WAAW;IACzB,OAAO,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,SAAS,CAAC,YAAY,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAC5D,aAAa,CAAC,MAAM,EAAE,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC9F,CAAC"}
package/dist/lib/paths.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { join } from "node:path";
2
- import { findCotalRoot } from "@cotal-ai/core";
2
+ import { findCotalRoot } from "@cotal-ai/workspace";
3
3
  /** The project's `.cotal/` root, found by walking up from cwd (like git finds `.git`), so every
4
4
  * command resolves the same `.cotal/` whether you're at the project root or a subdirectory. */
5
5
  export function cotalRoot() {
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C;gGACgG;AAChG,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,EAAE,CAAC;AACzB,CAAC;AAED;yDACyD;AACzD,MAAM,UAAU,SAAS,CAAC,GAAG,QAAkB;IAC7C,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/lib/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD;gGACgG;AAChG,MAAM,UAAU,SAAS;IACvB,OAAO,aAAa,EAAE,CAAC;AACzB,CAAC;AAED;yDACyD;AACzD,MAAM,UAAU,SAAS,CAAC,GAAG,QAAkB;IAC7C,OAAO,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC,CAAC;AAClD,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/lib/status.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;sEAEsE;AACtE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;8FAC8F;AAC9F,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CASjE;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACrC,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;CAChD;AAED,kEAAkE;AAClE,wBAAsB,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC,CAe5D;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAG3C;AAQD,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGjD"}
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/lib/status.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;sEAEsE;AACtE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAEhD;AAED;8FAC8F;AAC9F,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CASjE;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAAC;IACrC,YAAY,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE;QAAE,MAAM,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAA;KAAE,CAAC;CAChD;AAED,kEAAkE;AAClE,wBAAsB,aAAa,IAAI,OAAO,CAAC,aAAa,CAAC,CAe5D;AAED,wBAAgB,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAG3C;AAQD,qEAAqE;AACrE,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAGjD"}
@@ -1,7 +1,8 @@
1
1
  import { spawnSync } from "node:child_process";
2
2
  import { existsSync } from "node:fs";
3
3
  import { join } from "node:path";
4
- import { DEFAULT_SERVER, DEFAULT_SPACE, authDir, findCotalRoot, isReachable, loadSpaceAuth } from "@cotal-ai/core";
4
+ import { DEFAULT_SERVER, DEFAULT_SPACE, isReachable } from "@cotal-ai/core";
5
+ import { authDir, findCotalRoot, loadSpaceAuth } from "@cotal-ai/workspace";
5
6
  import { resolveNatsServer } from "./nats-bin.js";
6
7
  /** The space this folder operates on: its `.cotal/auth` space if set up, else the default.
7
8
  * A folder has exactly one space (its auth) — commands resolve it through here so they always
@@ -1 +1 @@
1
- {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/lib/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACnH,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AASlD;;sEAEsE;AACtE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,aAAa,CAAC;AAC5E,CAAC;AAED;8FAC8F;AAC9F,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC;IAC9B,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO;QACL,SAAS,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC;QACpC,MAAM;QACN,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,aAAa;QACnC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;KACpB,CAAC;AACJ,CAAC;AAQD,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,IAAI,GAA0B,SAAS,CAAC;IAC5C,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,IAAI;QACJ,YAAY,EAAE,qBAAqB,EAAE;QACrC,MAAM,EAAE;YACN,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC;YACxB,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;SAC7B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,qBAAqB;IAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACxE,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;AACzF,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAC3G,CAAC"}
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/lib/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AASlD;;sEAEsE;AACtE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,OAAO,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,aAAa,CAAC;AAC5E,CAAC;AAED;8FAC8F;AAC9F,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC;IAC9B,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACxD,OAAO;QACL,SAAS,EAAE,MAAM,WAAW,CAAC,MAAM,CAAC;QACpC,MAAM;QACN,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,aAAa;QACnC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC;KACpB,CAAC;AACJ,CAAC;AAQD,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,IAAI,GAA0B,SAAS,CAAC;IAC5C,IAAI,CAAC;QACH,IAAI,GAAG,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC,MAAM,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,SAAS,CAAC;IACnB,CAAC;IACD,OAAO;QACL,IAAI;QACJ,YAAY,EAAE,qBAAqB,EAAE;QACrC,MAAM,EAAE;YACN,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC;YACxB,QAAQ,EAAE,MAAM,CAAC,UAAU,CAAC;SAC7B;KACF,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,MAAM,CAAC,GAAW;IAChC,MAAM,CAAC,GAAG,SAAS,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7D,OAAO,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,qBAAqB;IAC5B,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,CAAC,GAAG,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IACxE,OAAO,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,GAAG,CAAC,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;AACzF,CAAC;AAED,qEAAqE;AACrE,MAAM,UAAU,YAAY,CAAC,GAAW;IACtC,MAAM,IAAI,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAChC,OAAO,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC;AAC3G,CAAC"}
@@ -1,18 +1,19 @@
1
1
  import { CotalEndpoint } from "@cotal-ai/core";
2
2
  /**
3
3
  * A one-shot, write-capable connection for the headless commands that touch the live mesh
4
- * (`dm`/`msg`/`ask`, and `personas list --running`). Resolve space/server/creds the same way
5
- * everywhere, open a transient endpoint that never joins the roster, do the one thing, stop.
6
- * Fail-loud throughout an unreachable server or a space mismatch exits, never degrades.
4
+ * (`dm`/`msg`/`ask`, and `personas list --running`). Resolution + creds + reachability all go through
5
+ * the shared `connectOrExit` (so these work from any directory, and an explicit `--creds` is a raw
6
+ * off-registry connection). Opens a transient endpoint that never joins the roster, does the one
7
+ * thing, stops.
7
8
  */
8
9
  export interface ConnectValues {
9
10
  space?: string;
10
11
  server?: string;
11
12
  creds?: string;
12
13
  }
13
- /** Resolve where to connect and with what credentials: an explicit `--creds` wins; else self-mint
14
- * from `.cotal/auth` so an AUTH-mode mesh admits us; else connect bare on an open mesh. Exits with
15
- * a clear message on a `--space` that contradicts the local auth, or an unreachable server. */
14
+ /** Resolve where to connect + with what credentials (`--creds` → raw off-registry; else the running
15
+ * mesh's minted manager creds). Fail-loud an unresolved registry or an unreachable/auth-mismatched
16
+ * broker exits with one sentence, never degrades. */
16
17
  export declare function resolveConnect(values: ConnectValues): Promise<{
17
18
  server: string;
18
19
  space: string;
@@ -1 +1 @@
1
- {"version":3,"file":"transient.d.ts","sourceRoot":"","sources":["../../src/lib/transient.ts"],"names":[],"mappings":"AACA,OAAO,EACL,aAAa,EAQd,MAAM,gBAAgB,CAAC;AAIxB;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;gGAEgG;AAChG,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAuB5D;AAED;iGACiG;AACjG,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAe/C"}
1
+ {"version":3,"file":"transient.d.ts","sourceRoot":"","sources":["../../src/lib/transient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAI/C;;;;;;GAMG;AAEH,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;sDAEsD;AACtD,wBAAsB,cAAc,CAClC,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAG5D;AAED;iGACiG;AACjG,wBAAsB,aAAa,CACjC,MAAM,EAAE,aAAa,EACrB,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,EAAE,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAe/C"}
@@ -1,30 +1,11 @@
1
- import { readFileSync } from "node:fs";
2
- import { CotalEndpoint, isReachable, DEFAULT_SERVER, DEFAULT_SPACE, authDir, loadSpaceAuth, mintCreds, newIdentity, } from "@cotal-ai/core";
1
+ import { CotalEndpoint } from "@cotal-ai/core";
3
2
  import { c } from "../ui.js";
4
- import { cotalRoot } from "./paths.js";
5
- /** Resolve where to connect and with what credentials: an explicit `--creds` wins; else self-mint
6
- * from `.cotal/auth` so an AUTH-mode mesh admits us; else connect bare on an open mesh. Exits with
7
- * a clear message on a `--space` that contradicts the local auth, or an unreachable server. */
3
+ import { connectOrExit } from "./connect.js";
4
+ /** Resolve where to connect + with what credentials (`--creds` → raw off-registry; else the running
5
+ * mesh's minted manager creds). Fail-loud an unresolved registry or an unreachable/auth-mismatched
6
+ * broker exits with one sentence, never degrades. */
8
7
  export async function resolveConnect(values) {
9
- const server = values.server ?? DEFAULT_SERVER;
10
- let creds = values.creds ? readFileSync(values.creds, "utf8") : undefined;
11
- let space = values.space;
12
- if (!creds) {
13
- const auth = loadSpaceAuth(authDir(cotalRoot()));
14
- if (auth) {
15
- if (space && space !== auth.space) {
16
- console.error(c.red(`Auth here is for space "${auth.space}", not "${space}". Use --space ${auth.space} (or pass --creds).`));
17
- process.exit(1);
18
- }
19
- space = auth.space;
20
- creds = await mintCreds(auth, newIdentity(), "manager");
21
- }
22
- }
23
- space = space ?? DEFAULT_SPACE;
24
- if (!(await isReachable(server, { creds }))) {
25
- console.error(c.red(`Can't reach NATS at ${server}. Run: cotal up`));
26
- process.exit(1);
27
- }
8
+ const { server, space, creds } = await connectOrExit(values, "manager");
28
9
  return { server, space, creds };
29
10
  }
30
11
  /** Open a transient endpoint: it watches presence (so name→id resolution and the live roster work)
@@ -1 +1 @@
1
- {"version":3,"file":"transient.js","sourceRoot":"","sources":["../../src/lib/transient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EACL,aAAa,EACb,WAAW,EACX,cAAc,EACd,aAAa,EACb,OAAO,EACP,aAAa,EACb,SAAS,EACT,WAAW,GACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,CAAC,EAAE,MAAM,UAAU,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAevC;;gGAEgG;AAChG,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAqB;IAErB,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,IAAI,cAAc,CAAC;IAC/C,IAAI,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC1E,IAAI,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IACzB,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,GAAG,aAAa,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC;QACjD,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,KAAK,IAAI,KAAK,KAAK,IAAI,CAAC,KAAK,EAAE,CAAC;gBAClC,OAAO,CAAC,KAAK,CACX,CAAC,CAAC,GAAG,CAAC,2BAA2B,IAAI,CAAC,KAAK,WAAW,KAAK,kBAAkB,IAAI,CAAC,KAAK,qBAAqB,CAAC,CAC9G,CAAC;gBACF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;YACnB,KAAK,GAAG,MAAM,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,EAAE,SAAS,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,KAAK,GAAG,KAAK,IAAI,aAAa,CAAC;IAC/B,IAAI,CAAC,CAAC,MAAM,WAAW,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC;QAC5C,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,uBAAuB,MAAM,iBAAiB,CAAC,CAAC,CAAC;QACrE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC;AAED;iGACiG;AACjG,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAqB,EACrB,IAAY;IAEZ,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,EAAE,GAAG,IAAI,aAAa,CAAC;QAC3B,KAAK;QACL,OAAO,EAAE,MAAM;QACf,KAAK;QACL,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE,IAAI;QACnB,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE;KACjC,CAAC,CAAC;IACH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;IACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"transient.js","sourceRoot":"","sources":["../../src/lib/transient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,EAAE,CAAC,EAAE,MAAM,UAAU,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAgB7C;;sDAEsD;AACtD,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAqB;IAErB,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACxE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAClC,CAAC;AAED;iGACiG;AACjG,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAqB,EACrB,IAAY;IAEZ,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,EAAE,GAAG,IAAI,aAAa,CAAC;QAC3B,KAAK;QACL,OAAO,EAAE,MAAM;QACf,KAAK;QACL,QAAQ,EAAE,EAAE;QACZ,OAAO,EAAE,KAAK;QACd,gBAAgB,EAAE,KAAK;QACvB,aAAa,EAAE,IAAI;QACnB,IAAI,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE;KACjC,CAAC,CAAC;IACH,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACrE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC;IACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,207 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
6
+ <title>Cotal · graph</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com" />
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
+ <link
10
+ href="https://fonts.googleapis.com/css2?family=Work+Sans:wght@400;500;600;700&display=swap"
11
+ rel="stylesheet"
12
+ />
13
+ <style>
14
+ :root {
15
+ --bg: #131a26; --panel: #1b2330cc; --line: #38414f; --fg: #eef2f7;
16
+ --dim: #8b949e; --faint: #6e7681;
17
+ --chat: #58a6ff; --unicast: #d29922; --anycast: #3fb950;
18
+ --working: #3fb950; --waiting: #e3b341; --idle: #6e7681; --red: #f85149;
19
+ --font: "Work Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
20
+ }
21
+ * { box-sizing: border-box; }
22
+ html, body { height: 100%; margin: 0; }
23
+ body {
24
+ font-family: var(--font); font-size: 13px; background: var(--bg); color: var(--fg);
25
+ overflow: hidden; -webkit-font-smoothing: antialiased;
26
+ }
27
+ #graph { position: fixed; inset: 0; display: block; cursor: grab; }
28
+ #graph.hover { cursor: pointer; }
29
+
30
+ /* floating glass surfaces */
31
+ .glass {
32
+ background: var(--panel); border: 1px solid var(--line); border-radius: 12px;
33
+ backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
34
+ }
35
+
36
+ /* ── header (top, floating) ── */
37
+ header {
38
+ position: fixed; top: 14px; left: 14px; right: 14px; z-index: 10;
39
+ display: flex; align-items: center; gap: 16px; padding: 9px 14px;
40
+ }
41
+ .brand { display: flex; align-items: center; gap: 9px; }
42
+ .brand .mark { width: 9px; height: 9px; border-radius: 50%; background: var(--chat);
43
+ box-shadow: 0 0 10px var(--chat); }
44
+ .brand .title { font-size: 16px; font-weight: 700; }
45
+ .brand .space { font-size: 13px; color: var(--dim); }
46
+ .navlink {
47
+ font-size: 12px; font-weight: 600; color: var(--dim); text-decoration: none;
48
+ padding: 5px 11px; border-radius: 8px; border: 1px solid var(--line);
49
+ }
50
+ .navlink:hover { color: var(--fg); border-color: var(--chat); }
51
+ .pill { display: inline-flex; align-items: center; gap: 6px; padding: 4px 9px;
52
+ border-radius: 20px; background: #1f2d24; }
53
+ .pill .d { width: 7px; height: 7px; border-radius: 50%; background: var(--working); }
54
+ .pill .t { font-size: 11px; font-weight: 600; color: var(--working); }
55
+ .pill.down { background: #2a1717; } .pill.down .d { background: var(--red); }
56
+ .pill.down .t { color: var(--red); }
57
+ /* membership-freshness pill states */
58
+ .pill.stale { background: #2a2417; } .pill.stale .d { background: var(--waiting); }
59
+ .pill.stale .t { color: var(--waiting); }
60
+ .pill.off { background: #1f242c; } .pill.off .d { background: var(--faint); }
61
+ .pill.off .t { color: var(--dim); }
62
+
63
+ .ctrls { margin-left: auto; display: flex; align-items: center; gap: 7px; }
64
+ .grp { display: flex; align-items: center; gap: 4px; padding-right: 7px;
65
+ margin-right: 0; border-right: 1px solid var(--line); }
66
+ .grp:last-child { border-right: 0; padding-right: 0; }
67
+ .chip {
68
+ font-size: 11px; padding: 4px 9px; border-radius: 13px; cursor: pointer;
69
+ color: var(--faint); user-select: none; border: 1px solid transparent; white-space: nowrap;
70
+ }
71
+ .chip:hover { color: var(--fg); }
72
+ .chip.on { background: #ffffff10; border-color: var(--line); color: var(--fg); }
73
+ .chip.mode.chat.on { color: var(--chat); } .chip.mode.unicast.on { color: var(--unicast); }
74
+ .chip.mode.anycast.on { color: var(--anycast); }
75
+ .chip.pause.on { color: var(--waiting); border-color: var(--waiting); }
76
+ .chip.offline.on { color: var(--idle); border-color: var(--line); }
77
+
78
+ /* ── legend (bottom-left, collapsible) ── */
79
+ #legend { position: fixed; left: 14px; bottom: 14px; z-index: 10; padding: 0;
80
+ max-width: 200px; overflow: hidden; }
81
+ #legend .ltoggle {
82
+ display: flex; align-items: center; justify-content: space-between;
83
+ width: 100%; padding: 7px 12px; cursor: pointer; appearance: none;
84
+ font-size: 10px; font-weight: 600; letter-spacing: .6px; color: var(--faint);
85
+ text-transform: uppercase; background: transparent; border: 0;
86
+ text-align: left; font-family: inherit;
87
+ }
88
+ #legend .ltoggle:hover { color: var(--dim); }
89
+ #legend .ltoggle .chev { font-size: 9px; opacity: .5; transition: transform .2s ease; }
90
+ #legend.collapsed .ltoggle .chev { transform: rotate(-90deg); }
91
+ #legend .lbody { display: flex; flex-direction: column; gap: 5px; padding: 2px 12px 10px; }
92
+ #legend.collapsed .lbody { display: none; }
93
+ #legend .ls { font-size: 9px; font-weight: 600; letter-spacing: .5px; color: var(--faint);
94
+ text-transform: uppercase; opacity: .65; margin-top: 3px; }
95
+ #legend .ls:first-child { margin-top: 0; }
96
+ #legend .row { display: flex; align-items: center; gap: 9px; font-size: 11px; color: var(--dim); }
97
+ #legend .sw { width: 14px; height: 2px; border-radius: 1px; flex: none; }
98
+ #legend .sw-dot { width: 8px; height: 8px; border-radius: 50%; }
99
+ #legend .ring { width: 8px; height: 8px; border-radius: 50%; flex: none;
100
+ background: transparent; box-shadow: 0 0 0 1.5px currentColor inset; }
101
+
102
+ /* ── detail panel (right, floating) ── */
103
+ #detail {
104
+ position: fixed; top: 64px; right: 14px; bottom: 14px; width: 308px; z-index: 10;
105
+ padding: 16px 16px 18px; overflow-y: auto; display: none; flex-direction: column; gap: 14px;
106
+ scrollbar-width: thin; scrollbar-color: var(--line) transparent;
107
+ }
108
+ #detail::-webkit-scrollbar { width: 6px; }
109
+ #detail::-webkit-scrollbar-thumb { background: var(--line); border-radius: 3px; }
110
+ #detail.open { display: flex; }
111
+ #detail .x { position: absolute; top: 10px; right: 10px; cursor: pointer; color: var(--faint);
112
+ font-size: 13px; width: 22px; height: 22px; display: flex; align-items: center;
113
+ justify-content: center; border-radius: 5px; line-height: 1; }
114
+ #detail .x:hover { color: var(--fg); background: #ffffff12; }
115
+ .d-kind { font-size: 10px; font-weight: 600; letter-spacing: .6px; color: var(--faint);
116
+ text-transform: uppercase; }
117
+ .d-who { font-size: 16px; font-weight: 700; line-height: 1.25; padding-right: 26px; }
118
+ .d-who .role { font-size: 11px; font-weight: 500; color: var(--faint); margin-left: 6px; }
119
+ .d-status { display: inline-flex; align-items: center; gap: 6px; font-size: 11.5px;
120
+ font-weight: 500; padding: 3px 10px; border-radius: 20px; background: #ffffff08;
121
+ color: var(--dim); width: fit-content; }
122
+ .d-status .dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor;
123
+ box-shadow: 0 0 6px currentColor; }
124
+ .d-status.working { background: #16231a; color: var(--working); }
125
+ .d-status.waiting { background: #2a2117; color: var(--waiting); }
126
+ .d-status.idle { color: var(--dim); }
127
+ .d-status.offline { color: var(--faint); }
128
+ .d-section { display: flex; flex-direction: column; gap: 5px; }
129
+ .d-label { font-size: 9.5px; font-weight: 600; letter-spacing: .5px; color: var(--faint);
130
+ text-transform: uppercase; }
131
+ .d-block { font-size: 12px; line-height: 1.55; padding: 9px 11px; border-radius: 7px;
132
+ background: #ffffff08; border: 1px solid var(--line); white-space: pre-wrap; word-break: break-word; }
133
+ .d-block.muted { color: var(--dim); font-style: italic; }
134
+ .d-rows { display: flex; flex-direction: column; gap: 5px; }
135
+ .d-row { display: flex; gap: 10px; font-size: 11.5px; line-height: 1.4; }
136
+ .d-row .k { color: var(--faint); min-width: 64px; flex: none; }
137
+ .d-row .v { color: var(--fg); word-break: break-word; }
138
+ .d-msgs { display: flex; flex-direction: column; gap: 5px; }
139
+ .d-msg { font-size: 11px; line-height: 1.45; padding: 7px 10px 8px; border-radius: 6px;
140
+ background: #ffffff06; border-left: 2px solid var(--line); }
141
+ .d-msg .mhead { display: flex; align-items: baseline; gap: 6px; margin-bottom: 3px; }
142
+ .d-msg .m { font-size: 9px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; }
143
+ .d-msg .who { color: var(--fg); font-weight: 600; }
144
+ .d-msg .tgt { color: var(--dim); }
145
+ .d-msg .body { color: var(--dim); word-break: break-word; }
146
+ .d-msg.empty { text-align: center; color: var(--faint); font-style: italic; border-left-color: transparent; }
147
+ /* member / subscription tag rows in the detail panel */
148
+ .d-tags { display: flex; flex-wrap: wrap; gap: 5px; }
149
+ .mtag { display: inline-flex; align-items: center; gap: 6px; font-size: 11px; color: var(--fg);
150
+ padding: 3px 8px; border-radius: 13px; background: #ffffff08; border: 1px solid var(--line); }
151
+ .mtag .dot { width: 7px; height: 7px; border-radius: 50%; flex: none; box-shadow: 0 0 5px currentColor; }
152
+ .mtag .act { font-size: 9px; font-weight: 700; letter-spacing: .3px; text-transform: uppercase; color: var(--chat); }
153
+ .mtag .off { font-size: 9px; font-weight: 600; letter-spacing: .3px; text-transform: uppercase; color: var(--faint); }
154
+ .ctag { font-size: 11px; color: var(--chat); padding: 3px 8px; border-radius: 13px;
155
+ background: #58a6ff14; border: 1px solid #58a6ff33; }
156
+ .ctag.off { color: var(--dim); background: #ffffff06; border-color: var(--line); }
157
+ .hint { position: fixed; bottom: 16px; left: 50%; transform: translateX(-50%); z-index: 9;
158
+ font-size: 11.5px; color: var(--faint); pointer-events: none; transition: opacity .4s; }
159
+ </style>
160
+ </head>
161
+ <body>
162
+ <canvas id="graph"></canvas>
163
+
164
+ <header class="glass">
165
+ <span class="brand">
166
+ <span class="mark"></span>
167
+ <span class="title">Cotal</span>
168
+ <span class="space" id="space"></span>
169
+ </span>
170
+ <a class="navlink" href="/">← Monitor</a>
171
+ <span class="pill down" id="conn"><span class="d"></span><span class="t">connecting</span></span>
172
+ <span class="pill off" id="feed" hidden><span class="d"></span><span class="t">membership</span></span>
173
+ <div class="ctrls">
174
+ <div class="grp" id="modes">
175
+ <span class="chip mode chat on" data-mode="chat">channel</span>
176
+ <span class="chip mode unicast on" data-mode="unicast">direct</span>
177
+ <span class="chip mode anycast on" data-mode="anycast">anycast</span>
178
+ </div>
179
+ <span class="chip offline on" id="hideOffline">hide offline</span>
180
+ <span class="chip offline on" id="hideEmpty">hide empty</span>
181
+ <span class="chip pause" id="pause">⏸ pause</span>
182
+ </div>
183
+ </header>
184
+
185
+ <div id="legend" class="glass">
186
+ <button class="ltoggle" id="legendToggle" type="button"><span>legend</span><span class="chev">▾</span></button>
187
+ <div class="lbody">
188
+ <span class="ls">traffic</span>
189
+ <span class="row"><span class="sw" style="background:var(--chat)"></span> channel post → hub</span>
190
+ <span class="row"><span class="sw" style="background:var(--unicast)"></span> direct message</span>
191
+ <span class="row"><span class="sw sw-dot" style="background:var(--anycast)"></span> anycast (to a role)</span>
192
+ <span class="ls">membership</span>
193
+ <span class="row"><span class="sw" style="background:#8493a8"></span> subscribed (live)</span>
194
+ <span class="row"><span class="sw" style="background:#5a6472;opacity:.7"></span> member · offline</span>
195
+ <span class="ls">agents</span>
196
+ <span class="row"><span class="ring" style="color:var(--working)"></span> working</span>
197
+ <span class="row"><span class="ring" style="color:var(--waiting)"></span> waiting · needs input</span>
198
+ <span class="row"><span class="ring" style="color:var(--idle)"></span> idle / offline</span>
199
+ </div>
200
+ </div>
201
+
202
+ <aside id="detail" class="glass"></aside>
203
+ <div class="hint" id="hint">click a node for detail · scroll to zoom · drag to pan</div>
204
+
205
+ <script src="/graph.js"></script>
206
+ </body>
207
+ </html>