@4ort/cli 0.4.0 → 0.6.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.
- package/README.md +286 -0
- package/dist/commands/kg/agent-context.d.ts +3 -0
- package/dist/commands/kg/agent-context.js +54 -0
- package/dist/commands/kg/agent-context.js.map +1 -0
- package/dist/commands/kg/article-context.d.ts +3 -0
- package/dist/commands/kg/article-context.js +51 -0
- package/dist/commands/kg/article-context.js.map +1 -0
- package/dist/commands/kg/ask.d.ts +5 -0
- package/dist/commands/kg/ask.js +121 -0
- package/dist/commands/kg/ask.js.map +1 -0
- package/dist/commands/kg/auth.d.ts +9 -0
- package/dist/commands/kg/auth.js +95 -0
- package/dist/commands/kg/auth.js.map +1 -0
- package/dist/commands/kg/entity.d.ts +4 -0
- package/dist/commands/kg/entity.js +33 -0
- package/dist/commands/kg/entity.js.map +1 -0
- package/dist/commands/kg/match.d.ts +5 -0
- package/dist/commands/kg/match.js +44 -0
- package/dist/commands/kg/match.js.map +1 -0
- package/dist/commands/kg/popularity.d.ts +3 -0
- package/dist/commands/kg/popularity.js +42 -0
- package/dist/commands/kg/popularity.js.map +1 -0
- package/dist/commands/kg/search.d.ts +4 -0
- package/dist/commands/kg/search.js +34 -0
- package/dist/commands/kg/search.js.map +1 -0
- package/dist/commands/kg/trending.d.ts +6 -0
- package/dist/commands/kg/trending.js +35 -0
- package/dist/commands/kg/trending.js.map +1 -0
- package/dist/commands/mcp.d.ts +5 -0
- package/dist/commands/mcp.js +24 -0
- package/dist/commands/mcp.js.map +1 -0
- package/dist/commands/mov.d.ts +17 -0
- package/dist/commands/mov.js +124 -0
- package/dist/commands/mov.js.map +1 -0
- package/dist/commands/run.d.ts +10 -0
- package/dist/commands/run.js +74 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/search.d.ts +7 -0
- package/dist/commands/search.js +105 -0
- package/dist/commands/search.js.map +1 -0
- package/dist/commands/vault.d.ts +7 -0
- package/dist/commands/vault.js +62 -0
- package/dist/commands/vault.js.map +1 -0
- package/dist/commands/web.d.ts +6 -0
- package/dist/commands/web.js +44 -0
- package/dist/commands/web.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.js +97 -1
- package/dist/config.js.map +1 -1
- package/dist/config.mov.test.d.ts +1 -0
- package/dist/config.mov.test.js +23 -0
- package/dist/config.mov.test.js.map +1 -0
- package/dist/index.js +195 -37
- package/dist/index.js.map +1 -1
- package/dist/kg-client.d.ts +42 -0
- package/dist/kg-client.js +125 -0
- package/dist/kg-client.js.map +1 -0
- package/dist/kg-output.d.ts +33 -0
- package/dist/kg-output.js +132 -0
- package/dist/kg-output.js.map +1 -0
- package/dist/mcp-server.d.ts +5 -0
- package/dist/mcp-server.js +363 -0
- package/dist/mcp-server.js.map +1 -0
- package/dist/peertube-client.d.ts +47 -0
- package/dist/peertube-client.js +144 -0
- package/dist/peertube-client.js.map +1 -0
- package/dist/peertube-client.test.d.ts +1 -0
- package/dist/peertube-client.test.js +92 -0
- package/dist/peertube-client.test.js.map +1 -0
- package/dist/web-client.d.ts +20 -0
- package/dist/web-client.js +335 -0
- package/dist/web-client.js.map +1 -0
- package/package.json +21 -4
- package/src/api-client.ts +0 -51
- package/src/commands/delete.ts +0 -15
- package/src/commands/list.ts +0 -25
- package/src/commands/mail.ts +0 -79
- package/src/commands/provision.ts +0 -106
- package/src/commands/push.ts +0 -63
- package/src/commands/recover.ts +0 -37
- package/src/commands/register.ts +0 -40
- package/src/commands/whoami.ts +0 -20
- package/src/config.ts +0 -40
- package/src/index.ts +0 -114
- package/tsconfig.json +0 -8
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../src/commands/search.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Link this machine to the 4ort.ai secrets vault using a token minted from the
|
|
2
|
+
* Secrets panel. The token is stored at ~/.4ort/config.json (mode 0600). */
|
|
3
|
+
export declare function vaultLogin(token: string | undefined, opts: {
|
|
4
|
+
server?: string;
|
|
5
|
+
}): Promise<void>;
|
|
6
|
+
export declare function vaultStatus(): void;
|
|
7
|
+
export declare function vaultLogout(): void;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { createInterface } from "node:readline";
|
|
2
|
+
import { loadConfig, saveConfig, saveVaultConfig } from "../config.js";
|
|
3
|
+
const DEFAULT_VAULT_SERVER = "https://4ort.ai";
|
|
4
|
+
function readLine(prompt) {
|
|
5
|
+
const rl = createInterface({ input: process.stdin, output: process.stderr });
|
|
6
|
+
return new Promise((resolve) => {
|
|
7
|
+
rl.question(prompt, (answer) => {
|
|
8
|
+
rl.close();
|
|
9
|
+
resolve(answer.trim());
|
|
10
|
+
});
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
/** Link this machine to the 4ort.ai secrets vault using a token minted from the
|
|
14
|
+
* Secrets panel. The token is stored at ~/.4ort/config.json (mode 0600). */
|
|
15
|
+
export async function vaultLogin(token, opts) {
|
|
16
|
+
const server = (opts.server || DEFAULT_VAULT_SERVER).replace(/\/$/, "");
|
|
17
|
+
let tok = token;
|
|
18
|
+
if (!tok) {
|
|
19
|
+
tok = await readLine("Paste your vault token (4vt_…): ");
|
|
20
|
+
}
|
|
21
|
+
if (!tok || !tok.startsWith("4vt_")) {
|
|
22
|
+
console.error("Expected a token starting with 4vt_. Generate one in the 4ort.ai Secrets panel.");
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
// Verify the token against the vault (empty resolve = a cheap auth check).
|
|
26
|
+
try {
|
|
27
|
+
const res = await fetch(`${server}/api/secrets/resolve`, {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: { "Content-Type": "application/json", Authorization: `Bearer ${tok}` },
|
|
30
|
+
body: JSON.stringify({ refs: [] }),
|
|
31
|
+
});
|
|
32
|
+
if (!res.ok) {
|
|
33
|
+
console.error(`Vault login failed (HTTP ${res.status}). Check the token and --server.`);
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
catch (e) {
|
|
38
|
+
console.error(`Could not reach the vault at ${server}: ${e.message}`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
saveVaultConfig({ token: tok, server });
|
|
42
|
+
console.error(`✓ Vault linked (${server}).`);
|
|
43
|
+
console.error("Use 4ort:// references in your env, then run: 4ort run -- <command>");
|
|
44
|
+
}
|
|
45
|
+
export function vaultStatus() {
|
|
46
|
+
const c = loadConfig();
|
|
47
|
+
if (c?.vault?.token) {
|
|
48
|
+
console.log(`Vault: linked to ${c.vault.server} (token ${c.vault.token.slice(0, 12)}…)`);
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
console.log("Vault: not linked. Run: 4ort vault login");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function vaultLogout() {
|
|
55
|
+
const c = loadConfig();
|
|
56
|
+
if (c?.vault) {
|
|
57
|
+
delete c.vault;
|
|
58
|
+
saveConfig(c);
|
|
59
|
+
}
|
|
60
|
+
console.log("Vault unlinked.");
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../../src/commands/vault.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 4ort web get <url>
|
|
3
|
+
*
|
|
4
|
+
* Fetch a URL and return its readable text — "Reader Mode" style. Tiered:
|
|
5
|
+
* our own entity pages → structured record; everything else → live fetch +
|
|
6
|
+
* Mozilla Readability. No browser, no JS. On block / paywall / binary / parse
|
|
7
|
+
* failure: ok:false + the URL, so a calling agent can fall back.
|
|
8
|
+
*/
|
|
9
|
+
import { webRead } from "../web-client.js";
|
|
10
|
+
import { printJson } from "../kg-output.js";
|
|
11
|
+
export async function webGet(url, options) {
|
|
12
|
+
const maxChars = options.maxChars ? parseInt(options.maxChars, 10) : undefined;
|
|
13
|
+
const res = await webRead(url, { maxChars });
|
|
14
|
+
if (options.json) {
|
|
15
|
+
printJson(res);
|
|
16
|
+
process.exit(res.ok ? 0 : 1);
|
|
17
|
+
}
|
|
18
|
+
if (!res.ok) {
|
|
19
|
+
console.error(`✗ ${res.reason || "failed"}`);
|
|
20
|
+
console.error(` ${res.final_url || res.url}`);
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
if (res.source === "4ort.xyz" && res.entity) {
|
|
24
|
+
const e = res.entity;
|
|
25
|
+
console.log(`# ${e?.name || res.title || res.url}`);
|
|
26
|
+
console.log(`(4ort.xyz knowledge-graph entity — structured)\n`);
|
|
27
|
+
if (e?.description)
|
|
28
|
+
console.log(`${e.description}\n`);
|
|
29
|
+
printJson(e);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (res.title)
|
|
33
|
+
console.log(`# ${res.title}`);
|
|
34
|
+
if (res.byline)
|
|
35
|
+
console.log(`_by ${res.byline}_`);
|
|
36
|
+
const meta = [
|
|
37
|
+
res.word_count != null ? `${res.word_count} words` : null,
|
|
38
|
+
res.truncated ? "truncated" : null,
|
|
39
|
+
res.reason || null,
|
|
40
|
+
].filter(Boolean).join(" · ");
|
|
41
|
+
console.log(`<${res.final_url || res.url}>${meta ? ` — ${meta}` : ""}\n`);
|
|
42
|
+
console.log(res.text || "(no text extracted)");
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"web.js","sourceRoot":"","sources":["../../src/commands/web.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAO5C,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,GAAW,EAAE,OAAsB;IAC9D,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC/E,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;IAE7C,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,SAAS,CAAC,GAAG,CAAC,CAAC;QACf,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,MAAM,IAAI,QAAQ,EAAE,CAAC,CAAC;QAC7C,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,GAAG,CAAC,MAAM,KAAK,UAAU,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC;QAC5C,MAAM,CAAC,GAAG,GAAG,CAAC,MAAa,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,IAAI,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;QAChE,IAAI,CAAC,EAAE,WAAW;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC;QACtD,SAAS,CAAC,CAAC,CAAC,CAAC;QACb,OAAO;IACT,CAAC;IAED,IAAI,GAAG,CAAC,KAAK;QAAE,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;IAC7C,IAAI,GAAG,CAAC,MAAM;QAAE,OAAO,CAAC,GAAG,CAAC,OAAO,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG;QACX,GAAG,CAAC,UAAU,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,UAAU,QAAQ,CAAC,CAAC,CAAC,IAAI;QACzD,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI;QAClC,GAAG,CAAC,MAAM,IAAI,IAAI;KACnB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;IAC3E,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,qBAAqB,CAAC,CAAC;AACjD,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -1,10 +1,48 @@
|
|
|
1
|
+
export interface KgConfig {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
recoveryCode?: string;
|
|
4
|
+
server: string;
|
|
5
|
+
name?: string;
|
|
6
|
+
tier?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface VaultConfig {
|
|
9
|
+
token: string;
|
|
10
|
+
server: string;
|
|
11
|
+
}
|
|
12
|
+
export interface MovConfig {
|
|
13
|
+
server: string;
|
|
14
|
+
accessToken: string;
|
|
15
|
+
refreshToken: string;
|
|
16
|
+
clientId: string;
|
|
17
|
+
clientSecret: string;
|
|
18
|
+
username?: string;
|
|
19
|
+
}
|
|
1
20
|
export interface Config {
|
|
2
21
|
apiKey: string;
|
|
3
22
|
recoveryCode?: string;
|
|
4
23
|
server: string;
|
|
5
24
|
agentName: string;
|
|
25
|
+
kg?: KgConfig;
|
|
26
|
+
vault?: VaultConfig;
|
|
27
|
+
mov?: MovConfig;
|
|
6
28
|
}
|
|
7
29
|
export declare function loadConfig(): Config | null;
|
|
8
30
|
export declare function saveConfig(config: Config): void;
|
|
31
|
+
/** Save just the KG block, preserving any existing 4ort.net config. */
|
|
32
|
+
export declare function saveKgConfig(kg: KgConfig): void;
|
|
9
33
|
export declare function requireConfig(): Config;
|
|
34
|
+
export declare function requireKgConfig(): KgConfig;
|
|
35
|
+
/**
|
|
36
|
+
* Like requireKgConfig, but never exits — for public KG endpoints (e.g.
|
|
37
|
+
* /api/v1/route). Returns the KG key if present, else the 4ort.net key, else an
|
|
38
|
+
* empty key against the canonical server. Callers should treat auth as optional.
|
|
39
|
+
*/
|
|
40
|
+
export declare function optionalKgConfig(): KgConfig;
|
|
10
41
|
export declare function getConfigPath(): string;
|
|
42
|
+
/** Save just the vault block, preserving the rest of the config. */
|
|
43
|
+
export declare function saveVaultConfig(vault: VaultConfig): void;
|
|
44
|
+
export declare function requireVaultConfig(): VaultConfig;
|
|
45
|
+
/** Save just the mov block (4ort.mov / PeerTube), preserving the rest. */
|
|
46
|
+
export declare function saveMovConfig(mov: MovConfig): void;
|
|
47
|
+
/** Return the mov block or exit with a friendly hint if not logged in. */
|
|
48
|
+
export declare function optionalMovConfig(): MovConfig;
|
package/dist/config.js
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persisted CLI config at ~/.4ort/config.json (mode 0600).
|
|
3
|
+
*
|
|
4
|
+
* Layout:
|
|
5
|
+
* {
|
|
6
|
+
* "apiKey": "...", // 4ort.net agent key (4n_-prefixed going forward)
|
|
7
|
+
* "recoveryCode": "...",
|
|
8
|
+
* "server": "https://4ort.net",
|
|
9
|
+
* "agentName": "ryan",
|
|
10
|
+
* "kg": { // 4ort.xyz knowledge graph (optional)
|
|
11
|
+
* "apiKey": "4kg_...",
|
|
12
|
+
* "recoveryCode": "...",
|
|
13
|
+
* "server": "https://4ort.xyz",
|
|
14
|
+
* "name": "my-agent",
|
|
15
|
+
* "tier": "free"
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
*
|
|
19
|
+
* Both blocks are independent — a user can sign in to 4ort.net only,
|
|
20
|
+
* 4ort.xyz only, or both. The CLI picks the right block per command.
|
|
21
|
+
*/
|
|
1
22
|
import fs from "node:fs";
|
|
2
23
|
import path from "node:path";
|
|
3
24
|
import os from "node:os";
|
|
@@ -16,15 +37,90 @@ export function saveConfig(config) {
|
|
|
16
37
|
fs.mkdirSync(CONFIG_DIR, { recursive: true });
|
|
17
38
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2) + "\n", { mode: 0o600 });
|
|
18
39
|
}
|
|
40
|
+
/** Save just the KG block, preserving any existing 4ort.net config. */
|
|
41
|
+
export function saveKgConfig(kg) {
|
|
42
|
+
const existing = loadConfig();
|
|
43
|
+
const next = existing
|
|
44
|
+
? { ...existing, kg }
|
|
45
|
+
: { apiKey: "", server: "https://4ort.net", agentName: "", kg };
|
|
46
|
+
saveConfig(next);
|
|
47
|
+
}
|
|
19
48
|
export function requireConfig() {
|
|
20
49
|
const config = loadConfig();
|
|
21
|
-
if (!config) {
|
|
50
|
+
if (!config || !config.apiKey) {
|
|
22
51
|
console.error("Not logged in. Run: 4ort register <name>");
|
|
23
52
|
process.exit(1);
|
|
53
|
+
throw new Error("unreachable");
|
|
24
54
|
}
|
|
25
55
|
return config;
|
|
26
56
|
}
|
|
57
|
+
export function requireKgConfig() {
|
|
58
|
+
const config = loadConfig();
|
|
59
|
+
if (config?.kg?.apiKey)
|
|
60
|
+
return config.kg;
|
|
61
|
+
// Fall back to 4ort.net membership if present — federated keys validate
|
|
62
|
+
// against 4ort.net automatically.
|
|
63
|
+
if (config?.apiKey) {
|
|
64
|
+
return {
|
|
65
|
+
apiKey: config.apiKey,
|
|
66
|
+
server: "https://4ort.xyz",
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
console.error("Not signed in to 4ort.xyz. Run one of:");
|
|
70
|
+
console.error(" 4ort kg register # one-shot, no email needed");
|
|
71
|
+
console.error(" 4ort kg auth login # paste an existing key");
|
|
72
|
+
process.exit(1);
|
|
73
|
+
throw new Error("unreachable");
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Like requireKgConfig, but never exits — for public KG endpoints (e.g.
|
|
77
|
+
* /api/v1/route). Returns the KG key if present, else the 4ort.net key, else an
|
|
78
|
+
* empty key against the canonical server. Callers should treat auth as optional.
|
|
79
|
+
*/
|
|
80
|
+
export function optionalKgConfig() {
|
|
81
|
+
const config = loadConfig();
|
|
82
|
+
if (config?.kg?.apiKey)
|
|
83
|
+
return config.kg;
|
|
84
|
+
if (config?.apiKey)
|
|
85
|
+
return { apiKey: config.apiKey, server: "https://4ort.xyz" };
|
|
86
|
+
return { apiKey: "", server: "https://4ort.xyz" };
|
|
87
|
+
}
|
|
27
88
|
export function getConfigPath() {
|
|
28
89
|
return CONFIG_FILE;
|
|
29
90
|
}
|
|
91
|
+
/** Save just the vault block, preserving the rest of the config. */
|
|
92
|
+
export function saveVaultConfig(vault) {
|
|
93
|
+
const existing = loadConfig();
|
|
94
|
+
const next = existing
|
|
95
|
+
? { ...existing, vault }
|
|
96
|
+
: { apiKey: "", server: "https://4ort.net", agentName: "", vault };
|
|
97
|
+
saveConfig(next);
|
|
98
|
+
}
|
|
99
|
+
export function requireVaultConfig() {
|
|
100
|
+
const config = loadConfig();
|
|
101
|
+
if (config?.vault?.token) {
|
|
102
|
+
return config.vault;
|
|
103
|
+
}
|
|
104
|
+
console.error("Not signed in to the 4ort.ai vault. Run:");
|
|
105
|
+
console.error(" 4ort vault login # paste a token from the Secrets panel");
|
|
106
|
+
process.exit(1);
|
|
107
|
+
throw new Error("unreachable");
|
|
108
|
+
}
|
|
109
|
+
/** Save just the mov block (4ort.mov / PeerTube), preserving the rest. */
|
|
110
|
+
export function saveMovConfig(mov) {
|
|
111
|
+
const existing = loadConfig();
|
|
112
|
+
const next = existing
|
|
113
|
+
? { ...existing, mov }
|
|
114
|
+
: { apiKey: "", server: "https://4ort.net", agentName: "", mov };
|
|
115
|
+
saveConfig(next);
|
|
116
|
+
}
|
|
117
|
+
/** Return the mov block or exit with a friendly hint if not logged in. */
|
|
118
|
+
export function optionalMovConfig() {
|
|
119
|
+
const config = loadConfig();
|
|
120
|
+
if (config?.mov?.accessToken)
|
|
121
|
+
return config.mov;
|
|
122
|
+
console.error("Not signed in to 4ort.mov. Run: 4ort mov login");
|
|
123
|
+
process.exit(1);
|
|
124
|
+
throw new Error("unreachable");
|
|
125
|
+
}
|
|
30
126
|
//# sourceMappingURL=config.js.map
|
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,CAAC,CAAC;AACpD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
test("saveMovConfig round-trips and preserves other blocks", async () => {
|
|
7
|
+
const tmp = fs.mkdtempSync(path.join(os.tmpdir(), "fort-"));
|
|
8
|
+
process.env.HOME = tmp; // CONFIG_DIR derives from os.homedir()
|
|
9
|
+
const cfg = await import(`./config.js?case=${Date.now()}`);
|
|
10
|
+
cfg.saveConfig({ apiKey: "x", server: "https://4ort.net", agentName: "ryan" });
|
|
11
|
+
cfg.saveMovConfig({
|
|
12
|
+
server: "https://4ort.mov",
|
|
13
|
+
accessToken: "tok",
|
|
14
|
+
refreshToken: "ref",
|
|
15
|
+
clientId: "c",
|
|
16
|
+
clientSecret: "s",
|
|
17
|
+
});
|
|
18
|
+
const loaded = cfg.loadConfig();
|
|
19
|
+
assert.equal(loaded.apiKey, "x"); // pre-existing block preserved
|
|
20
|
+
assert.equal(loaded.mov.accessToken, "tok");
|
|
21
|
+
assert.equal(loaded.mov.server, "https://4ort.mov");
|
|
22
|
+
});
|
|
23
|
+
//# sourceMappingURL=config.mov.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.mov.test.js","sourceRoot":"","sources":["../src/config.mov.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,IAAI,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;IACtE,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,OAAO,CAAC,CAAC,CAAC;IAC5D,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,uCAAuC;IAC/D,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,oBAAoB,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAC3D,GAAG,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,kBAAkB,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC,CAAC;IAC/E,GAAG,CAAC,aAAa,CAAC;QAChB,MAAM,EAAE,kBAAkB;QAC1B,WAAW,EAAE,KAAK;QAClB,YAAY,EAAE,KAAK;QACnB,QAAQ,EAAE,GAAG;QACb,YAAY,EAAE,GAAG;KAClB,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,GAAG,CAAC,UAAU,EAAE,CAAC;IAChC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,+BAA+B;IACjE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,13 +6,31 @@ import { list } from "./commands/list.js";
|
|
|
6
6
|
import { deleteSite } from "./commands/delete.js";
|
|
7
7
|
import { whoami } from "./commands/whoami.js";
|
|
8
8
|
import { checkMail, readMail, sendMail, deleteMail } from "./commands/mail.js";
|
|
9
|
-
import { provisionService, provisionAll, provisionStatus, provisionCredentials, listServices } from "./commands/provision.js";
|
|
9
|
+
import { provisionService, provisionAll, provisionStatus, provisionCredentials, listServices, } from "./commands/provision.js";
|
|
10
|
+
import { kgRegister, kgLogin, kgStatus } from "./commands/kg/auth.js";
|
|
11
|
+
import { kgSearch } from "./commands/kg/search.js";
|
|
12
|
+
import { kgEntity } from "./commands/kg/entity.js";
|
|
13
|
+
import { kgAsk } from "./commands/kg/ask.js";
|
|
14
|
+
import { kgMatch } from "./commands/kg/match.js";
|
|
15
|
+
import { kgPopularity } from "./commands/kg/popularity.js";
|
|
16
|
+
import { kgTrending } from "./commands/kg/trending.js";
|
|
17
|
+
import { kgAgentContext } from "./commands/kg/agent-context.js";
|
|
18
|
+
import { kgArticleContext } from "./commands/kg/article-context.js";
|
|
19
|
+
import { webGet } from "./commands/web.js";
|
|
20
|
+
import { searchCommand } from "./commands/search.js";
|
|
21
|
+
import { mcpStdioCommand, mcpServeCommand } from "./commands/mcp.js";
|
|
22
|
+
import { vaultLogin, vaultStatus, vaultLogout } from "./commands/vault.js";
|
|
23
|
+
import { runCommand } from "./commands/run.js";
|
|
24
|
+
import { movLogin, movPublish, movList, movChannels, movDelete } from "./commands/mov.js";
|
|
10
25
|
import { loadConfig, getConfigPath } from "./config.js";
|
|
11
26
|
const program = new Command();
|
|
12
27
|
program
|
|
13
28
|
.name("4ort")
|
|
14
|
-
.description("CLI for 4ort
|
|
15
|
-
.version("0.
|
|
29
|
+
.description("Unified CLI for the 4ort ecosystem — hosting, knowledge graph, and more")
|
|
30
|
+
.version("0.6.0");
|
|
31
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
32
|
+
// 4ort.net subdomain hosting
|
|
33
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
16
34
|
program
|
|
17
35
|
.command("register <name>")
|
|
18
36
|
.description("Register a new agent and claim your subdomain")
|
|
@@ -23,47 +41,49 @@ program
|
|
|
23
41
|
.command("push [directory]")
|
|
24
42
|
.description("Deploy your site (defaults to current directory)")
|
|
25
43
|
.action((dir = ".") => push(dir));
|
|
44
|
+
program.command("list").description("List your sites").action(list);
|
|
45
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
46
|
+
// Secrets vault — `4ort run` resolves 4ort:// references at runtime
|
|
47
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
48
|
+
const vault = program
|
|
49
|
+
.command("vault")
|
|
50
|
+
.description("Link this machine to the 4ort.ai secrets vault");
|
|
51
|
+
vault
|
|
52
|
+
.command("login [token]")
|
|
53
|
+
.description("Link the vault with a token from the Secrets panel")
|
|
54
|
+
.option("-s, --server <url>", "Vault server URL", "https://4ort.ai")
|
|
55
|
+
.action((token, opts) => vaultLogin(token, opts));
|
|
56
|
+
vault.command("status").description("Show vault link status").action(vaultStatus);
|
|
57
|
+
vault.command("logout").description("Unlink the vault").action(vaultLogout);
|
|
26
58
|
program
|
|
27
|
-
.command("
|
|
28
|
-
.description("
|
|
29
|
-
.
|
|
59
|
+
.command("run")
|
|
60
|
+
.description("Run a command with 4ort:// secret references resolved into env vars")
|
|
61
|
+
.argument("[parts...]", "command and args (use -- to separate, e.g. 4ort run -- node app.js)")
|
|
62
|
+
.action((parts) => runCommand(parts));
|
|
30
63
|
program
|
|
31
64
|
.command("delete [subdomain]")
|
|
32
65
|
.description("Delete a site")
|
|
33
66
|
.action(deleteSite);
|
|
34
|
-
program
|
|
35
|
-
.command("whoami")
|
|
36
|
-
.description("Show current agent info")
|
|
37
|
-
.action(whoami);
|
|
67
|
+
program.command("whoami").description("Show current agent info").action(whoami);
|
|
38
68
|
const mail = program.command("mail").description("Manage your @4ort.net inbox");
|
|
39
69
|
mail
|
|
40
70
|
.command("inbox")
|
|
41
71
|
.description("Check your inbox")
|
|
42
72
|
.option("-u, --unread", "Show unread only")
|
|
43
73
|
.action(checkMail);
|
|
44
|
-
mail
|
|
45
|
-
.command("read <id>")
|
|
46
|
-
.description("Read a message")
|
|
47
|
-
.action(readMail);
|
|
74
|
+
mail.command("read <id>").description("Read a message").action(readMail);
|
|
48
75
|
mail
|
|
49
76
|
.command("send <to>")
|
|
50
77
|
.description("Send a message to another agent")
|
|
51
78
|
.option("-s, --subject <subject>", "Subject line")
|
|
52
79
|
.option("-b, --body <body>", "Message body")
|
|
53
80
|
.action(sendMail);
|
|
54
|
-
mail
|
|
55
|
-
|
|
56
|
-
.
|
|
57
|
-
.
|
|
58
|
-
|
|
59
|
-
provision
|
|
60
|
-
.command("run <service>")
|
|
61
|
-
.description("Provision a specific service")
|
|
62
|
-
.action(provisionService);
|
|
63
|
-
provision
|
|
64
|
-
.command("all")
|
|
65
|
-
.description("Provision all available Tier A services")
|
|
66
|
-
.action(provisionAll);
|
|
81
|
+
mail.command("delete <id>").description("Delete a message").action(deleteMail);
|
|
82
|
+
const provision = program
|
|
83
|
+
.command("provision")
|
|
84
|
+
.description("Auto-provision third-party service accounts");
|
|
85
|
+
provision.command("run <service>").description("Provision a specific service").action(provisionService);
|
|
86
|
+
provision.command("all").description("Provision all available Tier A services").action(provisionAll);
|
|
67
87
|
provision
|
|
68
88
|
.command("status [service]")
|
|
69
89
|
.description("Check provisioning status")
|
|
@@ -72,23 +92,161 @@ provision
|
|
|
72
92
|
.command("credentials [service]")
|
|
73
93
|
.description("Show stored credentials")
|
|
74
94
|
.action((service) => provisionCredentials(service));
|
|
75
|
-
provision
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
95
|
+
provision.command("services").description("List available services").action(listServices);
|
|
96
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
97
|
+
// Search — the smart router / front door (4ort.xyz entity + phonebook + web)
|
|
98
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
99
|
+
program
|
|
100
|
+
.command("search <query>")
|
|
101
|
+
.description("Smart router: KG entity + curated sources (phonebook) + web hits")
|
|
102
|
+
.option("-p, --pages <n>", "Max web-index hits", "20")
|
|
103
|
+
.option("-s, --sources <n>", "Max authoritative-source routes", "12")
|
|
104
|
+
.option("--json", "Output the full structured payload as JSON")
|
|
105
|
+
.action(searchCommand);
|
|
106
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
107
|
+
// 4ort knowledge graph (Popularity Graph)
|
|
108
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
109
|
+
const kg = program
|
|
110
|
+
.command("kg")
|
|
111
|
+
.description("Query the 4ort knowledge graph (Popularity Graph)");
|
|
112
|
+
kg.command("register")
|
|
113
|
+
.description("One-shot register a new 4ort.xyz API key")
|
|
114
|
+
.option("-n, --name <name>", "Display name for this key")
|
|
115
|
+
.option("-e, --email <email>", "Optional contact email for billing/recovery")
|
|
116
|
+
.option("-s, --server <url>", "KG server URL", "https://4ort.xyz")
|
|
117
|
+
.action(kgRegister);
|
|
118
|
+
const kgAuth = kg.command("auth").description("Manage 4ort.xyz authentication");
|
|
119
|
+
kgAuth
|
|
120
|
+
.command("login")
|
|
121
|
+
.description("Sign in by pasting an existing 4ort.xyz API key")
|
|
122
|
+
.option("-s, --server <url>", "KG server URL", "https://4ort.xyz")
|
|
123
|
+
.action(kgLogin);
|
|
124
|
+
kgAuth
|
|
125
|
+
.command("status")
|
|
126
|
+
.description("Show the current 4ort.xyz identity")
|
|
127
|
+
.action(kgStatus);
|
|
128
|
+
kg.command("search <query>")
|
|
129
|
+
.description("Hybrid search across the entity graph")
|
|
130
|
+
.option("-l, --limit <n>", "Max results", "20")
|
|
131
|
+
.option("--json", "Output JSON instead of a table")
|
|
132
|
+
.action(kgSearch);
|
|
133
|
+
kg.command("entity <key>")
|
|
134
|
+
.description("Fetch one entity (slug, UUID, or Q-id)")
|
|
135
|
+
.option("-d, --detail <level>", "tiny | small | medium | full", "medium")
|
|
136
|
+
.option("--json", "Output JSON")
|
|
137
|
+
.action(kgEntity);
|
|
138
|
+
kg.command("ask <question>")
|
|
139
|
+
.description("Ask the graph anything — streams cited tokens")
|
|
140
|
+
.option("-s, --scope <slug>", "Scope the question to one entity")
|
|
141
|
+
.option("--json", "Skip streaming, return one structured payload")
|
|
142
|
+
.option("--plain", "Strip markdown formatting (no bold, italic, code marks)")
|
|
143
|
+
.action(kgAsk);
|
|
144
|
+
kg.command("match <text>")
|
|
145
|
+
.description("Resolve a string to its canonical KG entity")
|
|
146
|
+
.option("-l, --limit <n>", "Max candidates", "5")
|
|
147
|
+
.option("-t, --types <list>", "Comma-separated entity-type filter")
|
|
148
|
+
.option("--json", "Output JSON")
|
|
149
|
+
.action(kgMatch);
|
|
150
|
+
kg.command("popularity <key>")
|
|
151
|
+
.description("Pageview-derived 'real-world search volume' for an entity")
|
|
152
|
+
.option("--json", "Output JSON")
|
|
153
|
+
.action(kgPopularity);
|
|
154
|
+
kg.command("trending")
|
|
155
|
+
.description("Top entities by Wikipedia pageview velocity")
|
|
156
|
+
.option("-h, --hours <n>", "Window size in hours", "1")
|
|
157
|
+
.option("-l, --limit <n>", "Max results", "50")
|
|
158
|
+
.option("-d, --domain <name>", "Filter to a specific domain")
|
|
159
|
+
.option("--json", "Output JSON")
|
|
160
|
+
.action(kgTrending);
|
|
161
|
+
kg.command("agent-context <key>")
|
|
162
|
+
.description("Memory-bank bundle for autonomous agents")
|
|
163
|
+
.option("--json", "Output JSON")
|
|
164
|
+
.action(kgAgentContext);
|
|
165
|
+
kg.command("article-context <key>")
|
|
166
|
+
.description("Fat bundle for SEO writers — facts, citations, hooks")
|
|
167
|
+
.option("--json", "Output JSON")
|
|
168
|
+
.action(kgArticleContext);
|
|
169
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
170
|
+
// 4ort.mov — AI-first video host (PeerTube). Publish + manage videos.
|
|
171
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
172
|
+
const mov = program.command("mov").description("Publish and manage videos on 4ort.mov");
|
|
173
|
+
mov
|
|
174
|
+
.command("login")
|
|
175
|
+
.description("Sign in to 4ort.mov (PeerTube) and store tokens")
|
|
176
|
+
.option("-s, --server <url>", "Instance URL", "https://4ort.mov")
|
|
177
|
+
.option("-u, --username <user>", "Username (non-interactive; or env FORT_MOV_USERNAME)")
|
|
178
|
+
.option("-p, --password <pass>", "Password (non-interactive; or env FORT_MOV_PASSWORD)")
|
|
179
|
+
.action(movLogin);
|
|
180
|
+
mov
|
|
181
|
+
.command("publish <file>")
|
|
182
|
+
.description("Upload a video file")
|
|
183
|
+
.requiredOption("-t, --title <title>", "Video title")
|
|
184
|
+
.option("-c, --channel <name>", "Target channel (default: first channel)")
|
|
185
|
+
.option("-d, --description <text>", "Description")
|
|
186
|
+
.option("--thumbnail <file>", "Thumbnail image file")
|
|
187
|
+
.option("-p, --privacy <level>", "public|unlisted|private|internal", "unlisted")
|
|
188
|
+
.action(movPublish);
|
|
189
|
+
mov.command("list").description("List your videos").action(movList);
|
|
190
|
+
mov
|
|
191
|
+
.command("channels")
|
|
192
|
+
.description("List your channels (or create one with --create)")
|
|
193
|
+
.option("--create <name>", "Create a channel with this name")
|
|
194
|
+
.action(movChannels);
|
|
195
|
+
mov.command("delete <id>").description("Delete a video by id").action(movDelete);
|
|
196
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
197
|
+
// Web — read the public internet (Reader-Mode fetch, no browser)
|
|
198
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
199
|
+
const web = program
|
|
200
|
+
.command("web")
|
|
201
|
+
.description("Read the public internet — Reader-Mode fetch, no browser/JS");
|
|
202
|
+
web
|
|
203
|
+
.command("get <url>")
|
|
204
|
+
.description("Fetch a URL and return its readable text (our own pages → structured)")
|
|
205
|
+
.option("--json", "Output the structured payload as JSON")
|
|
206
|
+
.option("-m, --max-chars <n>", "Cap extracted text length (default 50000)")
|
|
207
|
+
.action(webGet);
|
|
208
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
209
|
+
// MCP — expose search + web get + kg tools to MCP-native agents over stdio
|
|
210
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
211
|
+
const mcp = program
|
|
212
|
+
.command("mcp")
|
|
213
|
+
.description("4ort MCP server — stdio (default), or `mcp serve` for Streamable HTTP");
|
|
214
|
+
mcp
|
|
215
|
+
.command("stdio", { isDefault: true })
|
|
216
|
+
.description("Run over stdio — for Claude Desktop & local MCP clients that spawn the process")
|
|
217
|
+
.action(mcpStdioCommand);
|
|
218
|
+
mcp
|
|
219
|
+
.command("serve")
|
|
220
|
+
.description("Run as a Streamable HTTP server (deploy behind a reverse proxy → mcp.4ort.xyz)")
|
|
221
|
+
.option("-p, --port <n>", "Port to listen on", "8003")
|
|
222
|
+
.option("-H, --host <addr>", "Bind address", "127.0.0.1")
|
|
223
|
+
.action(mcpServeCommand);
|
|
224
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
225
|
+
// Config inspection
|
|
226
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
79
227
|
program
|
|
80
228
|
.command("config")
|
|
81
229
|
.description("Show config location and current settings")
|
|
82
230
|
.action(() => {
|
|
83
231
|
const config = loadConfig();
|
|
84
232
|
if (!config) {
|
|
85
|
-
console.log("Not configured. Run: 4ort register <name>");
|
|
233
|
+
console.log("Not configured. Run: 4ort register <name> or 4ort kg register");
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
console.log(`Config: ${getConfigPath()}`);
|
|
237
|
+
if (config.apiKey) {
|
|
238
|
+
console.log(`\n4ort.net`);
|
|
239
|
+
console.log(` agent: ${config.agentName || "(unset)"}`);
|
|
240
|
+
console.log(` server: ${config.server}`);
|
|
241
|
+
console.log(` api key: ${config.apiKey.slice(0, 12)}…`);
|
|
86
242
|
}
|
|
87
|
-
|
|
88
|
-
console.log(
|
|
89
|
-
console.log(`
|
|
90
|
-
console.log(`
|
|
91
|
-
console.log(`
|
|
243
|
+
if (config.kg?.apiKey) {
|
|
244
|
+
console.log(`\n4ort.xyz (knowledge graph)`);
|
|
245
|
+
console.log(` name: ${config.kg.name || "(unset)"}`);
|
|
246
|
+
console.log(` server: ${config.kg.server}`);
|
|
247
|
+
console.log(` api key: ${config.kg.apiKey.slice(0, 12)}…`);
|
|
248
|
+
if (config.kg.tier)
|
|
249
|
+
console.log(` tier: ${config.kg.tier}`);
|
|
92
250
|
}
|
|
93
251
|
});
|
|
94
252
|
program.parse();
|