@tpsdev-ai/flair 0.53.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 (97) hide show
  1. package/README.md +4 -1
  2. package/dist/build-info.json +3 -3
  3. package/dist/cli.js +1791 -15648
  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 +5 -4
  54. package/dist/lib/ops-api-bind.js +115 -0
  55. package/dist/lib/owned-pins.js +219 -0
  56. package/dist/lib/uninstall-purge.js +218 -0
  57. package/dist/rem/restore.js +8 -10
  58. package/dist/resources/AgentReadPosition.js +74 -0
  59. package/dist/resources/Federation.js +8 -2
  60. package/dist/resources/Memory.js +4 -3
  61. package/dist/resources/MemoryBootstrap.js +41 -25
  62. package/dist/resources/MemoryCandidate.js +5 -6
  63. package/dist/resources/OrgEventCatchup.js +126 -47
  64. package/dist/resources/agent-read-position-lib.js +83 -0
  65. package/dist/resources/agent-read-position.js +120 -0
  66. package/dist/resources/embeddings-boot.js +32 -0
  67. package/dist/resources/federation-peer-liveness.js +73 -0
  68. package/dist/resources/health.js +68 -19
  69. package/dist/resources/mcp-tools.js +43 -279
  70. package/dist/resources/memory-visibility.js +3 -3
  71. package/dist/resources/migration-boot.js +59 -18
  72. package/dist/resources/migrations/embedding-stamp.js +20 -1
  73. package/dist/resources/migrations/recheck.js +43 -0
  74. package/dist/resources/migrations/runner.js +6 -1
  75. package/dist/resources/migrations/stamp-outstanding.js +171 -0
  76. package/dist/resources/migrations/visibility-backfill.js +2 -2
  77. package/dist/resources/org-event-catchup-lib.js +47 -0
  78. package/dist/resources/record-owner-guard.js +1 -0
  79. package/dist/stamp-migration-verify.js +163 -0
  80. package/dist/stamp-outstanding.js +144 -0
  81. package/docs/api-reference.md +4 -2
  82. package/docs/deploying-on-fabric.md +11 -10
  83. package/docs/deployment.md +3 -1
  84. package/docs/federation.md +19 -0
  85. package/docs/hosted-on-fabric.md +3 -3
  86. package/docs/quickstart.md +2 -1
  87. package/docs/releasing.md +15 -7
  88. package/docs/spoke-bringup.md +10 -5
  89. package/docs/standalone-local.md +3 -1
  90. package/docs/upgrade.md +25 -6
  91. package/node_modules/@tpsdev-ai/flair-tool-descriptors/LICENSE +19 -0
  92. package/node_modules/@tpsdev-ai/flair-tool-descriptors/README.md +22 -0
  93. package/node_modules/@tpsdev-ai/flair-tool-descriptors/dist/index.d.ts +70 -0
  94. package/node_modules/@tpsdev-ai/flair-tool-descriptors/dist/index.js +665 -0
  95. package/node_modules/@tpsdev-ai/flair-tool-descriptors/package.json +46 -0
  96. package/package.json +9 -4
  97. package/schemas/agent.graphql +15 -0
@@ -0,0 +1,180 @@
1
+ import { buildTargetUrl as buildDeployUrl, deploy as deployToFabric, validateOptions as validateDeployOptions } from "../deploy.js";
2
+ import { renderFleetSweepTable, sweepFleet } from "../fleet-verify.js";
3
+ let cli;
4
+ /** Bind the cli-locals this module depends on. */
5
+ export function bindCli(fns) {
6
+ cli = fns;
7
+ }
8
+ function fleetSweepCallerExitMessage(...args) {
9
+ return cli.fleetSweepCallerExitMessage(...args);
10
+ }
11
+ function resolveFabricCredentials(...args) {
12
+ return cli.resolveFabricCredentials(...args);
13
+ }
14
+ function shouldRunFleetVerify(...args) {
15
+ return cli.shouldRunFleetVerify(...args);
16
+ }
17
+ export function register(program) {
18
+ // ─── flair deploy ─────────────────────────────────────────────────────────────
19
+ // NOTE on env-var naming for `flair deploy`: the FABRIC_* env vars below intentionally
20
+ // do NOT carry the FLAIR_ prefix that the rest of the CLI uses (FLAIR_ADMIN_PASS,
21
+ // FLAIR_TARGET, FLAIR_PAIRING_TOKEN, etc.). FABRIC_* credentials are shared with
22
+ // the broader TPS tooling stack — multiple tools deploy to the same Harper Fabric
23
+ // org/cluster with the same auth, and demanding a tool-specific prefix would force
24
+ // operators to maintain duplicated env vars. Per Kern review on PR #306: the
25
+ // inconsistency is deliberate, document it here so the next agent doesn't "fix" it.
26
+ program
27
+ .command("deploy")
28
+ .description("Deploy Flair as a component to a remote Harper Fabric cluster")
29
+ .option("--fabric-org <org>", "Fabric org (env: FABRIC_ORG)")
30
+ .option("--fabric-cluster <cluster>", "Fabric cluster within the org (env: FABRIC_CLUSTER)")
31
+ .option("--fabric-user <user>", "Fabric admin username (env: FABRIC_USER preferred; inline leaks to shell history)")
32
+ .option("--fabric-password <pass>", "Fabric admin password (prefer FABRIC_PASSWORD env or --fabric-password-file; inline leaks to shell history)")
33
+ .option("--fabric-password-file <path>", "Read the Fabric admin password from a file (chmod 600)")
34
+ .option("--fabric-token <token>", "OAuth bearer token (env: FABRIC_TOKEN) — reserved for future Fabric bearer support")
35
+ .option("--target <url>", "Override the Fabric URL template (https://<cluster>.<org>.harperfabric.com)")
36
+ .option("--project <name>", "Component name in Fabric", "flair")
37
+ .option("--pkg-version <semver>", "Override version label (default: installed package version)")
38
+ .option("--no-replicated", "Disable cluster-wide replication (default: replicated=true)")
39
+ .option("--no-restart", "Do not restart the component after deploy (default: restart=true)")
40
+ .option("--dry-run", "Resolve package, validate args, skip the deploy call")
41
+ .option("--package-root <dir>", "Override package root (mainly for testing)")
42
+ .option("--deployment-timeout <ms>", "Milliseconds harper waits for cluster-wide peer replication (env: FABRIC_DEPLOYMENT_TIMEOUT; default: 600000 — harper's own 120s default is too short for Fabric)")
43
+ .option("--install-timeout <ms>", "Milliseconds harper waits for package install (env: FABRIC_INSTALL_TIMEOUT; default: 600000)")
44
+ .option("--no-verify", "Skip post-deploy served-API verification (default: verify — on by design, so the CLI can't report success on an empty/broken deploy)")
45
+ .option("--verify-timeout <ms>", "Milliseconds to wait for the served API to settle after harper's post-deploy restart before verifying (default: 300000)")
46
+ .option("--verify-resource <name>", "Resource to verify is serving after deploy (repeatable; default: derived from the deployed package's dist/resources)", (val, prev) => [...prev, val], [])
47
+ .option("--deploy-retries <n>", "Retry the full harper deploy this many times, ONLY when peer replication is positively observed not to converge (default: 0 — retrying re-runs harper's component install and can escalate a transient replication warning into a hard ENOTEMPTY install failure; see flair#878)", "0")
48
+ .option("--ignore-replication-errors", "If peer replication still hasn't converged, treat it as a non-fatal warning and succeed with an origin-only deploy (the peer catches up via federation sync or a later deploy)")
49
+ .option("--no-convergence-check", "Skip the post-replication-error convergence poll and fail on harper's error verbatim (default: poll — Harper replicates asynchronously, so its error is a snapshot, not a verdict; flair#878)")
50
+ .option("--convergence-timeout <ms>", "How long to wait for peer replication to converge before reporting a replication failure (default: 180000)")
51
+ .option("--no-fleet-verify", "Skip the automatic post-deploy fleet convergence sweep (default: sweep runs — see flair#636)")
52
+ .action(async (opts) => {
53
+ const green = (s) => `\x1b[32m${s}\x1b[0m`;
54
+ const red = (s) => `\x1b[31m${s}\x1b[0m`;
55
+ const yellow = (s) => `\x1b[33m${s}\x1b[0m`;
56
+ const dim = (s) => `\x1b[2m${s}\x1b[0m`;
57
+ let fabricUser;
58
+ let fabricPassword;
59
+ let credWarnings = [];
60
+ try {
61
+ ({ fabricUser, fabricPassword, warnings: credWarnings } = resolveFabricCredentials(opts));
62
+ }
63
+ catch (err) {
64
+ console.error(red(`Error: ${err.message}`));
65
+ process.exit(1);
66
+ }
67
+ const deployOpts = {
68
+ fabricOrg: opts.fabricOrg ?? process.env.FABRIC_ORG,
69
+ fabricCluster: opts.fabricCluster ?? process.env.FABRIC_CLUSTER,
70
+ fabricUser,
71
+ fabricPassword,
72
+ fabricToken: opts.fabricToken ?? process.env.FABRIC_TOKEN,
73
+ target: opts.target,
74
+ project: opts.project,
75
+ version: opts.pkgVersion,
76
+ replicated: opts.replicated !== false,
77
+ restart: opts.restart !== false,
78
+ dryRun: opts.dryRun ?? false,
79
+ packageRoot: opts.packageRoot,
80
+ deploymentTimeoutMs: Number(opts.deploymentTimeout ?? process.env.FABRIC_DEPLOYMENT_TIMEOUT ?? 600_000),
81
+ installTimeoutMs: Number(opts.installTimeout ?? process.env.FABRIC_INSTALL_TIMEOUT ?? 600_000),
82
+ verify: opts.verify !== false,
83
+ verifyResources: opts.verifyResource?.length ? opts.verifyResource : undefined,
84
+ verifyTimeoutMs: Number(opts.verifyTimeout ?? 300_000),
85
+ deployRetries: Number(opts.deployRetries ?? 0),
86
+ ignoreReplicationErrors: opts.ignoreReplicationErrors ?? false,
87
+ convergenceCheck: opts.convergenceCheck !== false,
88
+ convergenceTimeoutMs: opts.convergenceTimeout != null ? Number(opts.convergenceTimeout) : undefined,
89
+ onProgress: (msg) => console.log(dim(` ${msg}`)),
90
+ };
91
+ const errors = validateDeployOptions(deployOpts);
92
+ if (errors.length) {
93
+ console.error(red("flair deploy: missing required options"));
94
+ for (const e of errors)
95
+ console.error(` - ${e}`);
96
+ process.exit(1);
97
+ }
98
+ // Never log the credential VALUES — only the flag names, via the
99
+ // resolver's own warning strings (see resolveFabricCredentials above).
100
+ for (const w of credWarnings)
101
+ console.error(dim(w));
102
+ const url = buildDeployUrl(deployOpts);
103
+ console.log(`${green("→")} Deploying ${deployOpts.project} to ${url}`);
104
+ if (deployOpts.dryRun)
105
+ console.log(dim(" (dry-run: skipping API call)"));
106
+ try {
107
+ const result = await deployToFabric(deployOpts);
108
+ if (result.dryRun) {
109
+ console.log(`${green("✓")} dry-run OK: ${result.project} ${result.version} ready to deploy to ${result.url}`);
110
+ console.log(dim(` package root: ${result.packageRoot}`));
111
+ return;
112
+ }
113
+ if (result.convergedAfterReplicationError) {
114
+ // flair#878: harper's exit code said failure; the per-node component
115
+ // comparison said otherwise. Both halves get said out loud.
116
+ console.log(`\n${yellow("⚠")} harper reported a peer-replication failure, but every named peer node's component tree matched the origin when checked afterwards — replication converged on its own.`);
117
+ }
118
+ if (result.replicationWarning) {
119
+ console.log(`\n${yellow("⚠")} Flair ${result.version} deployed to the ORIGIN NODE ONLY — peer replication did not complete (see warning above). The peer will catch up via federation sync or a later deploy.`);
120
+ }
121
+ else {
122
+ console.log(`\n${green("✓")} Flair ${result.version} deployed${deployOpts.verify ? " and verified serving" : ""}`);
123
+ }
124
+ console.log(`\n URL: ${result.url}`);
125
+ console.log(` Project: ${result.project}`);
126
+ // ── Post-deploy fleet sweep (flair#636) ─────────────────────────────
127
+ // Harper's own "Successfully deployed" (and the served-API verify
128
+ // above) only confirm the ORIGIN. This sweeps the origin + every known
129
+ // federation peer for actual version/health convergence — the gap that
130
+ // let the 0.21.0 deploy report success while a peer was still throwing
131
+ // 1006s. Skippable with --no-fleet-verify. Needs Basic-auth creds
132
+ // (fabricUser+fabricPassword) — a --fabric-token-only deploy has no way
133
+ // to authenticate the sweep, so it's skipped with a note instead of a
134
+ // silent no-op.
135
+ if (!shouldRunFleetVerify(opts)) {
136
+ console.log(dim("\n(--no-fleet-verify: skipping post-deploy fleet sweep)"));
137
+ }
138
+ else if (!deployOpts.fabricUser || !deployOpts.fabricPassword) {
139
+ console.log(dim("\n(skipping fleet verify — no --fabric-user/--fabric-password to authenticate the sweep; only --fabric-token was provided)"));
140
+ }
141
+ else {
142
+ console.log(`\n${green("→")} Fleet verify`);
143
+ const sweep = await sweepFleet({
144
+ target: result.url,
145
+ fabricUser: deployOpts.fabricUser,
146
+ fabricPassword: deployOpts.fabricPassword,
147
+ expectVersion: result.version,
148
+ });
149
+ console.log(renderFleetSweepTable(sweep));
150
+ const deploySweepFail = fleetSweepCallerExitMessage(sweep);
151
+ if (deploySweepFail) {
152
+ console.error(red(`\n✗ ${deploySweepFail}`));
153
+ process.exit(sweep.exitCode);
154
+ }
155
+ }
156
+ console.log(`\nNext steps:`);
157
+ console.log(dim(` 1. Set an admin password in Fabric Studio (Cluster Settings → Admin)`));
158
+ console.log(dim(` 2. Seed your first agent:`));
159
+ console.log(` flair agent add --remote ${result.url} --name my-agent`);
160
+ }
161
+ catch (err) {
162
+ console.error(red(`\n✗ deploy failed: ${err.message}`));
163
+ const hint = err.message?.toLowerCase();
164
+ if (hint?.includes("401") || hint?.includes("unauthoriz")) {
165
+ console.error(dim(" hint: check Fabric Studio → Cluster Settings → Admin for the admin password"));
166
+ }
167
+ if (hint?.includes("component is not serving")) {
168
+ console.error(dim(" hint: harper reported success but the served API disagrees — check the Fabric Studio component logs for the real deploy error, then retry"));
169
+ }
170
+ if (hint?.includes("did not settle")) {
171
+ console.error(dim(" hint: Harper may still be restarting — check Fabric Studio, or retry with a longer --verify-timeout"));
172
+ }
173
+ if (hint?.includes("peer replication")) {
174
+ console.error(dim(" hint: pass --ignore-replication-errors to accept an origin-only deploy, or re-run once the peer link recovers"));
175
+ console.error(dim(" hint: --convergence-timeout <ms> waits longer for asynchronous replication before giving up (default 180000)"));
176
+ }
177
+ process.exit(1);
178
+ }
179
+ });
180
+ }