@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.
- package/README.md +4 -1
- package/dist/build-info.json +3 -3
- package/dist/cli.js +1914 -15328
- package/dist/commands/agent.js +453 -0
- package/dist/commands/attention.js +121 -0
- package/dist/commands/backup.js +115 -0
- package/dist/commands/bootstrap.js +91 -0
- package/dist/commands/bridge.js +608 -0
- package/dist/commands/deploy.js +180 -0
- package/dist/commands/doctor.js +1654 -0
- package/dist/commands/export.js +110 -0
- package/dist/commands/federation.js +1575 -0
- package/dist/commands/fleet.js +73 -0
- package/dist/commands/grant.js +109 -0
- package/dist/commands/hook.js +193 -0
- package/dist/commands/idp.js +193 -0
- package/dist/commands/import.js +134 -0
- package/dist/commands/init.js +1203 -0
- package/dist/commands/inspect.js +45 -0
- package/dist/commands/keys.js +187 -0
- package/dist/commands/mcp.js +707 -0
- package/dist/commands/memory.js +501 -0
- package/dist/commands/migrate-harness-memory.js +270 -0
- package/dist/commands/orgevent.js +138 -0
- package/dist/commands/presence.js +76 -0
- package/dist/commands/principal.js +338 -0
- package/dist/commands/quality.js +1164 -0
- package/dist/commands/reembed.js +296 -0
- package/dist/commands/relationship.js +76 -0
- package/dist/commands/rem.js +1048 -0
- package/dist/commands/restore.js +130 -0
- package/dist/commands/search.js +244 -0
- package/dist/commands/service.js +315 -0
- package/dist/commands/session.js +184 -0
- package/dist/commands/soul.js +155 -0
- package/dist/commands/status.js +914 -0
- package/dist/commands/test.js +93 -0
- package/dist/commands/uninstall.js +143 -0
- package/dist/commands/upgrade.js +1592 -0
- package/dist/commands/workspace.js +114 -0
- package/dist/deploy.js +24 -0
- package/dist/fabric-npm-install.js +87 -0
- package/dist/federation-verify.js +498 -0
- package/dist/fleet-verify.js +144 -21
- package/dist/install/clients.js +167 -0
- package/dist/lib/auth-resolve.js +76 -1
- package/dist/lib/daemon-liveness.js +131 -2
- package/dist/lib/doctor-config-path.js +61 -0
- package/dist/lib/doctor-federation-driver.js +189 -0
- package/dist/lib/doctor-run.js +40 -0
- package/dist/lib/entity-vocab-cli.js +3 -3
- package/dist/lib/federation-pair-identity.js +47 -0
- package/dist/lib/launchd-repair.js +199 -0
- package/dist/lib/ops-api-bind.js +115 -0
- package/dist/lib/owned-pins.js +219 -0
- package/dist/lib/stabilize-mqtt-network.js +123 -0
- package/dist/lib/uninstall-purge.js +218 -0
- package/dist/rem/restore.js +8 -10
- package/dist/resources/AgentReadPosition.js +74 -0
- package/dist/resources/Federation.js +8 -2
- package/dist/resources/Memory.js +4 -3
- package/dist/resources/MemoryBootstrap.js +41 -25
- package/dist/resources/MemoryCandidate.js +5 -6
- package/dist/resources/OrgEventCatchup.js +126 -47
- package/dist/resources/agent-read-position-lib.js +83 -0
- package/dist/resources/agent-read-position.js +120 -0
- package/dist/resources/embeddings-boot.js +32 -0
- package/dist/resources/federation-peer-liveness.js +73 -0
- package/dist/resources/health.js +68 -19
- package/dist/resources/mcp-tools.js +43 -279
- package/dist/resources/memory-visibility.js +3 -3
- package/dist/resources/migration-boot.js +59 -18
- package/dist/resources/migrations/embedding-stamp.js +20 -1
- package/dist/resources/migrations/recheck.js +43 -0
- package/dist/resources/migrations/runner.js +6 -1
- package/dist/resources/migrations/stamp-outstanding.js +171 -0
- package/dist/resources/migrations/visibility-backfill.js +2 -2
- package/dist/resources/org-event-catchup-lib.js +47 -0
- package/dist/resources/record-owner-guard.js +1 -0
- package/dist/stamp-migration-verify.js +163 -0
- package/dist/stamp-outstanding.js +144 -0
- package/docs/api-reference.md +4 -2
- package/docs/deploying-on-fabric.md +11 -10
- package/docs/deployment.md +3 -1
- package/docs/federation.md +19 -0
- package/docs/hosted-on-fabric.md +3 -3
- package/docs/quickstart.md +2 -1
- package/docs/releasing.md +15 -7
- package/docs/spoke-bringup.md +10 -5
- package/docs/standalone-local.md +3 -1
- package/docs/upgrade.md +25 -6
- package/node_modules/@tpsdev-ai/flair-tool-descriptors/LICENSE +19 -0
- package/node_modules/@tpsdev-ai/flair-tool-descriptors/README.md +22 -0
- package/node_modules/@tpsdev-ai/flair-tool-descriptors/dist/index.d.ts +70 -0
- package/node_modules/@tpsdev-ai/flair-tool-descriptors/dist/index.js +665 -0
- package/node_modules/@tpsdev-ai/flair-tool-descriptors/package.json +46 -0
- package/package.json +9 -4
- package/schemas/agent.graphql +15 -0
- 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
|
+
}
|