@tpsdev-ai/flair 0.52.0 → 0.54.1

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 (99) hide show
  1. package/README.md +4 -1
  2. package/dist/build-info.json +3 -3
  3. package/dist/cli.js +1914 -15328
  4. package/dist/commands/agent.js +453 -0
  5. package/dist/commands/attention.js +121 -0
  6. package/dist/commands/backup.js +115 -0
  7. package/dist/commands/bootstrap.js +91 -0
  8. package/dist/commands/bridge.js +608 -0
  9. package/dist/commands/deploy.js +180 -0
  10. package/dist/commands/doctor.js +1654 -0
  11. package/dist/commands/export.js +110 -0
  12. package/dist/commands/federation.js +1575 -0
  13. package/dist/commands/fleet.js +73 -0
  14. package/dist/commands/grant.js +109 -0
  15. package/dist/commands/hook.js +193 -0
  16. package/dist/commands/idp.js +193 -0
  17. package/dist/commands/import.js +134 -0
  18. package/dist/commands/init.js +1203 -0
  19. package/dist/commands/inspect.js +45 -0
  20. package/dist/commands/keys.js +187 -0
  21. package/dist/commands/mcp.js +707 -0
  22. package/dist/commands/memory.js +501 -0
  23. package/dist/commands/migrate-harness-memory.js +270 -0
  24. package/dist/commands/orgevent.js +138 -0
  25. package/dist/commands/presence.js +76 -0
  26. package/dist/commands/principal.js +338 -0
  27. package/dist/commands/quality.js +1164 -0
  28. package/dist/commands/reembed.js +296 -0
  29. package/dist/commands/relationship.js +76 -0
  30. package/dist/commands/rem.js +1048 -0
  31. package/dist/commands/restore.js +130 -0
  32. package/dist/commands/search.js +244 -0
  33. package/dist/commands/service.js +315 -0
  34. package/dist/commands/session.js +184 -0
  35. package/dist/commands/soul.js +155 -0
  36. package/dist/commands/status.js +914 -0
  37. package/dist/commands/test.js +93 -0
  38. package/dist/commands/uninstall.js +143 -0
  39. package/dist/commands/upgrade.js +1592 -0
  40. package/dist/commands/workspace.js +114 -0
  41. package/dist/deploy.js +24 -0
  42. package/dist/fabric-npm-install.js +87 -0
  43. package/dist/federation-verify.js +498 -0
  44. package/dist/fleet-verify.js +144 -21
  45. package/dist/install/clients.js +167 -0
  46. package/dist/lib/auth-resolve.js +76 -1
  47. package/dist/lib/daemon-liveness.js +131 -2
  48. package/dist/lib/doctor-config-path.js +61 -0
  49. package/dist/lib/doctor-federation-driver.js +189 -0
  50. package/dist/lib/doctor-run.js +40 -0
  51. package/dist/lib/entity-vocab-cli.js +3 -3
  52. package/dist/lib/federation-pair-identity.js +47 -0
  53. package/dist/lib/launchd-repair.js +199 -0
  54. package/dist/lib/ops-api-bind.js +115 -0
  55. package/dist/lib/owned-pins.js +219 -0
  56. package/dist/lib/stabilize-mqtt-network.js +123 -0
  57. package/dist/lib/uninstall-purge.js +218 -0
  58. package/dist/rem/restore.js +8 -10
  59. package/dist/resources/AgentReadPosition.js +74 -0
  60. package/dist/resources/Federation.js +8 -2
  61. package/dist/resources/Memory.js +4 -3
  62. package/dist/resources/MemoryBootstrap.js +41 -25
  63. package/dist/resources/MemoryCandidate.js +5 -6
  64. package/dist/resources/OrgEventCatchup.js +126 -47
  65. package/dist/resources/agent-read-position-lib.js +83 -0
  66. package/dist/resources/agent-read-position.js +120 -0
  67. package/dist/resources/embeddings-boot.js +32 -0
  68. package/dist/resources/federation-peer-liveness.js +73 -0
  69. package/dist/resources/health.js +68 -19
  70. package/dist/resources/mcp-tools.js +43 -279
  71. package/dist/resources/memory-visibility.js +3 -3
  72. package/dist/resources/migration-boot.js +59 -18
  73. package/dist/resources/migrations/embedding-stamp.js +20 -1
  74. package/dist/resources/migrations/recheck.js +43 -0
  75. package/dist/resources/migrations/runner.js +6 -1
  76. package/dist/resources/migrations/stamp-outstanding.js +171 -0
  77. package/dist/resources/migrations/visibility-backfill.js +2 -2
  78. package/dist/resources/org-event-catchup-lib.js +47 -0
  79. package/dist/resources/record-owner-guard.js +1 -0
  80. package/dist/stamp-migration-verify.js +163 -0
  81. package/dist/stamp-outstanding.js +144 -0
  82. package/docs/api-reference.md +4 -2
  83. package/docs/deploying-on-fabric.md +11 -10
  84. package/docs/deployment.md +3 -1
  85. package/docs/federation.md +19 -0
  86. package/docs/hosted-on-fabric.md +3 -3
  87. package/docs/quickstart.md +2 -1
  88. package/docs/releasing.md +15 -7
  89. package/docs/spoke-bringup.md +10 -5
  90. package/docs/standalone-local.md +3 -1
  91. package/docs/upgrade.md +25 -6
  92. package/node_modules/@tpsdev-ai/flair-tool-descriptors/LICENSE +19 -0
  93. package/node_modules/@tpsdev-ai/flair-tool-descriptors/README.md +22 -0
  94. package/node_modules/@tpsdev-ai/flair-tool-descriptors/dist/index.d.ts +70 -0
  95. package/node_modules/@tpsdev-ai/flair-tool-descriptors/dist/index.js +665 -0
  96. package/node_modules/@tpsdev-ai/flair-tool-descriptors/package.json +46 -0
  97. package/package.json +9 -4
  98. package/schemas/agent.graphql +15 -0
  99. package/templates/launchd/start-flair-with-admin-pass.sh +73 -0
@@ -0,0 +1,110 @@
1
+ import { defaultKeysDir, resolveAdminUser } from "../lib/auth-resolve.js";
2
+ import * as render from "../render.js";
3
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
4
+ import { homedir } from "node:os";
5
+ import { join, resolve } from "node:path";
6
+ let cli;
7
+ /** Bind the cli-locals this module depends on. */
8
+ export function bindCli(fns) {
9
+ cli = fns;
10
+ }
11
+ function privKeyPath(...args) {
12
+ return cli.privKeyPath(...args);
13
+ }
14
+ function resolveHttpPort(...args) {
15
+ return cli.resolveHttpPort(...args);
16
+ }
17
+ export function register(program) {
18
+ // ─── flair export ────────────────────────────────────────────────────────────
19
+ program
20
+ .command("export <agent-id>")
21
+ .description("Export a single agent's identity (soul + memories) to a portable file")
22
+ .option("--output <path>", "Output file path")
23
+ .option("--include-key", "Include private key in export (UNENCRYPTED — keep the output file secure)")
24
+ .option("--port <port>", "Harper HTTP port")
25
+ .option("--url <url>", "Flair base URL (overrides --port)")
26
+ .option("--admin-pass <pass>", "Admin password (or set FLAIR_ADMIN_PASS env)")
27
+ .option("--admin-user <name>", "Admin username for Basic auth (env: FLAIR_ADMIN_USER; default: admin)")
28
+ .option("--keys-dir <dir>", "Keys directory", defaultKeysDir())
29
+ .action(async (agentId, opts) => {
30
+ const baseUrl = opts.url ?? `http://127.0.0.1:${resolveHttpPort(opts)}`;
31
+ const adminPass = opts.adminPass ?? process.env.FLAIR_ADMIN_PASS ?? "";
32
+ if (!adminPass) {
33
+ console.error("Error: --admin-pass or FLAIR_ADMIN_PASS required");
34
+ process.exit(1);
35
+ }
36
+ const auth = `Basic ${Buffer.from(`${resolveAdminUser(opts.adminUser)}:${adminPass}`).toString("base64")}`;
37
+ async function adminGet(path) {
38
+ const res = await fetch(`${baseUrl}${path}`, { headers: { Authorization: auth }, signal: AbortSignal.timeout(10_000) });
39
+ if (!res.ok)
40
+ throw new Error(`GET ${path} failed (${res.status})`);
41
+ return res.json();
42
+ }
43
+ console.log(`Exporting agent '${agentId}'...`);
44
+ // Fetch agent record
45
+ let agent;
46
+ try {
47
+ agent = await adminGet(`/Agent/${agentId}`);
48
+ }
49
+ catch {
50
+ console.error(`Agent '${agentId}' not found`);
51
+ process.exit(1);
52
+ }
53
+ // Fetch memories
54
+ const allMemories = await adminGet("/Memory/").catch(() => []);
55
+ const memories = Array.isArray(allMemories)
56
+ ? allMemories.filter((m) => m.agentId === agentId)
57
+ : [];
58
+ // Fetch souls
59
+ const allSouls = await adminGet("/Soul/").catch(() => []);
60
+ const souls = Array.isArray(allSouls)
61
+ ? allSouls.filter((s) => s.agentId === agentId)
62
+ : [];
63
+ // Fetch grants
64
+ const allGrants = await adminGet("/MemoryGrant/").catch(() => []);
65
+ const grants = Array.isArray(allGrants)
66
+ ? allGrants.filter((g) => g.ownerId === agentId || g.granteeId === agentId)
67
+ : [];
68
+ // Optionally include private key
69
+ let privateKey;
70
+ if (opts.includeKey) {
71
+ const keyPath = privKeyPath(agentId, opts.keysDir);
72
+ if (existsSync(keyPath)) {
73
+ privateKey = readFileSync(keyPath, "utf-8").trim();
74
+ console.log(" Including private key (base64-encoded in export)");
75
+ }
76
+ else {
77
+ console.warn(` Warning: key file not found at ${keyPath} — skipping key export`);
78
+ }
79
+ }
80
+ const exportData = {
81
+ version: 1,
82
+ type: "agent-export",
83
+ exportedAt: new Date().toISOString(),
84
+ source: baseUrl,
85
+ agent,
86
+ memories,
87
+ souls,
88
+ grants,
89
+ ...(privateKey ? { privateKey } : {}),
90
+ };
91
+ const rawOutputPath = opts.output ?? join(homedir(), ".flair", "exports", `${agentId}-${Date.now()}.json`);
92
+ // Canonicalize to prevent path traversal (e.g. ../../etc/passwd)
93
+ const outputPath = resolve(rawOutputPath);
94
+ mkdirSync(join(outputPath, ".."), { recursive: true });
95
+ const fileMode = privateKey ? 0o600 : 0o644;
96
+ writeFileSync(outputPath, JSON.stringify(exportData, null, 2), { mode: fileMode });
97
+ if (privateKey)
98
+ chmodSync(outputPath, 0o600); // enforce even if umask is permissive
99
+ console.log(`\n${render.icons.ok} ${render.wrap(render.c.green, `Agent '${agentId}' exported`)}`);
100
+ console.log(render.kv("Memories", render.wrap(render.c.bold, String(memories.length))));
101
+ console.log(render.kv("Souls", render.wrap(render.c.bold, String(souls.length))));
102
+ console.log(render.kv("Grants", render.wrap(render.c.bold, String(grants.length))));
103
+ const keyText = privateKey
104
+ ? `${render.wrap(render.c.magenta, "included")} ${render.wrap(render.c.red, "(UNENCRYPTED — protect this file)")}`
105
+ : render.wrap(render.c.dim, "not included");
106
+ console.log(render.kv("Key", keyText));
107
+ console.log(render.kv("Mode", `${fileMode.toString(8)} ${render.wrap(render.c.dim, `(${privateKey ? "owner-only" : "standard"})`)}`));
108
+ console.log(render.kv("Output", render.wrap(render.c.dim, outputPath)));
109
+ });
110
+ }