@indexnetwork/cli 0.17.0-rc.66.1 → 0.28.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 +181 -57
- package/dist/index.js +717 -1214
- package/package.json +5 -5
package/dist/index.js
CHANGED
|
@@ -1,25 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __returnValue = (v) => v;
|
|
4
|
-
function __exportSetter(name, newValue) {
|
|
5
|
-
this[name] = __returnValue.bind(null, newValue);
|
|
6
|
-
}
|
|
7
|
-
var __export = (target, all) => {
|
|
8
|
-
for (var name in all)
|
|
9
|
-
__defProp(target, name, {
|
|
10
|
-
get: all[name],
|
|
11
|
-
enumerable: true,
|
|
12
|
-
configurable: true,
|
|
13
|
-
set: __exportSetter.bind(all, name)
|
|
14
|
-
});
|
|
15
|
-
};
|
|
16
2
|
|
|
17
3
|
// src/main.ts
|
|
18
4
|
import { spawn } from "node:child_process";
|
|
19
5
|
// package.json
|
|
20
6
|
var package_default = {
|
|
21
7
|
name: "@indexnetwork/cli",
|
|
22
|
-
version: "0.
|
|
8
|
+
version: "0.28.0",
|
|
23
9
|
description: "Command-line interface for Index Network",
|
|
24
10
|
license: "MIT",
|
|
25
11
|
type: "module",
|
|
@@ -39,10 +25,10 @@ var package_default = {
|
|
|
39
25
|
"publish:all": "bun scripts/publish.ts"
|
|
40
26
|
},
|
|
41
27
|
optionalDependencies: {
|
|
42
|
-
"@indexnetwork/cli-linux-x64": "0.
|
|
43
|
-
"@indexnetwork/cli-linux-arm64": "0.
|
|
44
|
-
"@indexnetwork/cli-darwin-x64": "0.
|
|
45
|
-
"@indexnetwork/cli-darwin-arm64": "0.
|
|
28
|
+
"@indexnetwork/cli-linux-x64": "0.28.0",
|
|
29
|
+
"@indexnetwork/cli-linux-arm64": "0.28.0",
|
|
30
|
+
"@indexnetwork/cli-darwin-x64": "0.28.0",
|
|
31
|
+
"@indexnetwork/cli-darwin-arm64": "0.28.0"
|
|
46
32
|
},
|
|
47
33
|
devDependencies: {
|
|
48
34
|
"@types/bun": "1.3.14"
|
|
@@ -50,15 +36,15 @@ var package_default = {
|
|
|
50
36
|
};
|
|
51
37
|
|
|
52
38
|
// src/args.parser.ts
|
|
53
|
-
var KNOWN_COMMANDS = new Set(["login", "logout", "profile", "intent", "opportunity", "negotiation", "network", "conversation", "
|
|
54
|
-
var OPPORTUNITY_SUBCOMMANDS = new Set(["list", "show", "accept", "reject"]);
|
|
55
|
-
var NEGOTIATION_SUBCOMMANDS = new Set(["list", "show"]);
|
|
56
|
-
var NETWORK_SUBCOMMANDS = new Set(["list", "create", "show", "join", "leave", "invite", "update", "delete"]);
|
|
57
|
-
var CONVERSATION_SUBCOMMANDS = new Set(["list", "with", "show", "send", "stream", "help"]);
|
|
39
|
+
var KNOWN_COMMANDS = new Set(["docs", "agent", "login", "logout", "profile", "intent", "opportunity", "negotiation", "network", "conversation", "scrape", "onboarding", "sync", "help", "version"]);
|
|
40
|
+
var OPPORTUNITY_SUBCOMMANDS = new Set(["list", "show", "accept", "reject", "start-chat"]);
|
|
41
|
+
var NEGOTIATION_SUBCOMMANDS = new Set(["list", "show", "turn"]);
|
|
42
|
+
var NETWORK_SUBCOMMANDS = new Set(["list", "create", "show", "join", "leave", "invite", "update", "delete", "discover", "requests", "request-update", "request-dismiss"]);
|
|
43
|
+
var CONVERSATION_SUBCOMMANDS = new Set(["list", "with", "show", "send", "answer", "stream", "help"]);
|
|
58
44
|
function parseArgs(args) {
|
|
59
45
|
const result = {
|
|
60
46
|
command: "help",
|
|
61
|
-
|
|
47
|
+
json: args.includes("--json")
|
|
62
48
|
};
|
|
63
49
|
if (args.length === 0) {
|
|
64
50
|
return result;
|
|
@@ -67,6 +53,8 @@ function parseArgs(args) {
|
|
|
67
53
|
for (let j = 0;j < args.length; j++) {
|
|
68
54
|
const a = args[j];
|
|
69
55
|
if (a === "--api-url" || a === "--app-url") {
|
|
56
|
+
if (!args[j + 1] || args[j + 1].startsWith("--"))
|
|
57
|
+
throw new Error(`Missing value for ${a}`);
|
|
70
58
|
if (a === "--api-url")
|
|
71
59
|
result.apiUrl = args[j + 1];
|
|
72
60
|
else
|
|
@@ -78,7 +66,11 @@ function parseArgs(args) {
|
|
|
78
66
|
} else if (a === "--version" || a === "-v") {
|
|
79
67
|
result.command = "version";
|
|
80
68
|
return result;
|
|
81
|
-
} else if (
|
|
69
|
+
} else if (a === "--json") {
|
|
70
|
+
continue;
|
|
71
|
+
} else if (a.startsWith("-")) {
|
|
72
|
+
throw new Error(`Unknown option: ${a}`);
|
|
73
|
+
} else {
|
|
82
74
|
commandIndex = j;
|
|
83
75
|
break;
|
|
84
76
|
}
|
|
@@ -97,10 +89,66 @@ function parseArgs(args) {
|
|
|
97
89
|
const positionals = [];
|
|
98
90
|
while (i < args.length) {
|
|
99
91
|
const arg = args[i];
|
|
100
|
-
if (arg === "--
|
|
101
|
-
result
|
|
102
|
-
|
|
103
|
-
|
|
92
|
+
if (arg === "--help" || arg === "-h")
|
|
93
|
+
return { ...result, command: "help" };
|
|
94
|
+
if (arg === "--version" || arg === "-v")
|
|
95
|
+
return { ...result, command: "version" };
|
|
96
|
+
if (["--api-url", "--app-url", "--status", "--limit", "--prompt", "-p", "--objective", "--title"].includes(arg) && (!args[i + 1] || args[i + 1].startsWith("--")))
|
|
97
|
+
throw new Error(`Missing value for ${arg}`);
|
|
98
|
+
if (["--query", "--state", "--action", "--message", "--intent-id", "--question-id", "--expected-turn-count", "--receipt", "--name", "--intro", "--location", "--statuses", "--answer", "--social"].includes(arg)) {
|
|
99
|
+
const value = args[i + 1];
|
|
100
|
+
if (value === undefined || value.startsWith("--"))
|
|
101
|
+
throw new Error(`Missing value for ${arg}`);
|
|
102
|
+
switch (arg) {
|
|
103
|
+
case "--query":
|
|
104
|
+
result.query = value;
|
|
105
|
+
break;
|
|
106
|
+
case "--state":
|
|
107
|
+
result.state = value;
|
|
108
|
+
break;
|
|
109
|
+
case "--action":
|
|
110
|
+
result.action = value;
|
|
111
|
+
break;
|
|
112
|
+
case "--message":
|
|
113
|
+
result.message = value;
|
|
114
|
+
break;
|
|
115
|
+
case "--intent-id":
|
|
116
|
+
result.intentId = value;
|
|
117
|
+
break;
|
|
118
|
+
case "--question-id":
|
|
119
|
+
result.questionId = value;
|
|
120
|
+
break;
|
|
121
|
+
case "--expected-turn-count":
|
|
122
|
+
result.expectedTurnCount = Number(value);
|
|
123
|
+
break;
|
|
124
|
+
case "--receipt":
|
|
125
|
+
result.receipt = value;
|
|
126
|
+
break;
|
|
127
|
+
case "--name":
|
|
128
|
+
result.name = value;
|
|
129
|
+
break;
|
|
130
|
+
case "--intro":
|
|
131
|
+
result.intro = value;
|
|
132
|
+
break;
|
|
133
|
+
case "--location":
|
|
134
|
+
result.location = value;
|
|
135
|
+
break;
|
|
136
|
+
case "--statuses":
|
|
137
|
+
result.statuses = value;
|
|
138
|
+
break;
|
|
139
|
+
case "--answer":
|
|
140
|
+
case "--social": {
|
|
141
|
+
const at = value.indexOf("=");
|
|
142
|
+
if (at < 1 || !value.slice(at + 1).trim())
|
|
143
|
+
throw new Error(`${arg} needs key=value`);
|
|
144
|
+
const pair = { key: value.slice(0, at), value: value.slice(at + 1) };
|
|
145
|
+
if (arg === "--answer")
|
|
146
|
+
(result.answers ??= []).push(pair);
|
|
147
|
+
else
|
|
148
|
+
(result.socials ??= []).push({ label: pair.key, value: pair.value });
|
|
149
|
+
break;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
104
152
|
i += 2;
|
|
105
153
|
} else if (arg === "--api-url") {
|
|
106
154
|
result.apiUrl = args[i + 1];
|
|
@@ -115,7 +163,9 @@ function parseArgs(args) {
|
|
|
115
163
|
result.status = args[i + 1];
|
|
116
164
|
i += 2;
|
|
117
165
|
} else if (arg === "--limit") {
|
|
118
|
-
result.limit =
|
|
166
|
+
result.limit = Number(args[i + 1]);
|
|
167
|
+
if (!Number.isSafeInteger(result.limit) || result.limit < 1)
|
|
168
|
+
throw new Error("--limit must be a positive integer");
|
|
119
169
|
i += 2;
|
|
120
170
|
} else if (arg === "--prompt" || arg === "-p") {
|
|
121
171
|
result.prompt = args[i + 1];
|
|
@@ -126,34 +176,45 @@ function parseArgs(args) {
|
|
|
126
176
|
} else if (arg === "--objective") {
|
|
127
177
|
result.objective = args[i + 1];
|
|
128
178
|
i += 2;
|
|
129
|
-
} else if (arg === "--linkedin") {
|
|
130
|
-
result.linkedin = args[i + 1];
|
|
131
|
-
i += 2;
|
|
132
|
-
} else if (arg === "--github") {
|
|
133
|
-
result.github = args[i + 1];
|
|
134
|
-
i += 2;
|
|
135
|
-
} else if (arg === "--twitter") {
|
|
136
|
-
result.twitter = args[i + 1];
|
|
137
|
-
i += 2;
|
|
138
179
|
} else if (arg === "--title") {
|
|
139
180
|
result.title = args[i + 1];
|
|
140
181
|
i += 2;
|
|
141
|
-
} else if (arg
|
|
142
|
-
|
|
143
|
-
i += 2;
|
|
144
|
-
} else if (arg === "--since") {
|
|
145
|
-
result.since = args[i + 1];
|
|
146
|
-
i += 2;
|
|
147
|
-
} else if (arg === "--acknowledge-uptake") {
|
|
148
|
-
result.acknowledgeUptake = (args[i + 1] ?? "").split(",").map((id) => id.trim()).filter(Boolean);
|
|
149
|
-
i += 2;
|
|
150
|
-
} else if (arg.startsWith("--")) {
|
|
151
|
-
i++;
|
|
182
|
+
} else if (arg.startsWith("-")) {
|
|
183
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
152
184
|
} else {
|
|
153
185
|
positionals.push(arg);
|
|
154
186
|
i++;
|
|
155
187
|
}
|
|
156
188
|
}
|
|
189
|
+
const subcommands = {
|
|
190
|
+
agent: new Set(["me"]),
|
|
191
|
+
opportunity: OPPORTUNITY_SUBCOMMANDS,
|
|
192
|
+
negotiation: NEGOTIATION_SUBCOMMANDS,
|
|
193
|
+
network: NETWORK_SUBCOMMANDS,
|
|
194
|
+
conversation: CONVERSATION_SUBCOMMANDS,
|
|
195
|
+
intent: INTENT_SUBCOMMANDS,
|
|
196
|
+
profile: new Set(["show", "sync", "update"]),
|
|
197
|
+
onboarding: new Set(["confirm-profile", "complete"])
|
|
198
|
+
};
|
|
199
|
+
const allowed = subcommands[result.command];
|
|
200
|
+
if (allowed && result.command !== "profile" && !positionals[0]) {
|
|
201
|
+
throw new Error(`Missing subcommand for index ${result.command}. Run index --help.`);
|
|
202
|
+
}
|
|
203
|
+
if (allowed && positionals[0] && !allowed.has(positionals[0])) {
|
|
204
|
+
throw new Error(`Unknown command: ${result.command} ${positionals[0]}`);
|
|
205
|
+
}
|
|
206
|
+
if (result.command === "agent") {
|
|
207
|
+
result.subcommand = positionals[0];
|
|
208
|
+
result.positionals = positionals.slice(1);
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
211
|
+
if (result.command === "login") {
|
|
212
|
+
if (positionals.length > 1 || positionals[0] && !["local", "dev", "prod"].includes(positionals[0])) {
|
|
213
|
+
throw new Error("Usage: index login [local|dev|prod] [--api-url <origin>] [--app-url <origin>]");
|
|
214
|
+
}
|
|
215
|
+
result.loginTarget = positionals[0];
|
|
216
|
+
return result;
|
|
217
|
+
}
|
|
157
218
|
if (result.command === "opportunity") {
|
|
158
219
|
const sub = positionals[0];
|
|
159
220
|
if (sub && OPPORTUNITY_SUBCOMMANDS.has(sub)) {
|
|
@@ -168,6 +229,9 @@ function parseArgs(args) {
|
|
|
168
229
|
return result;
|
|
169
230
|
}
|
|
170
231
|
if (result.command === "negotiation") {
|
|
232
|
+
if (result.limit !== undefined || result.status !== undefined) {
|
|
233
|
+
throw new Error("Negotiation filters are --intent-id and --state only");
|
|
234
|
+
}
|
|
171
235
|
const sub = positionals[0];
|
|
172
236
|
if (sub && NEGOTIATION_SUBCOMMANDS.has(sub)) {
|
|
173
237
|
result.subcommand = sub;
|
|
@@ -198,20 +262,11 @@ function parseArgs(args) {
|
|
|
198
262
|
}
|
|
199
263
|
if (result.command === "onboarding" && positionals.length > 0) {
|
|
200
264
|
const sub = positionals[0];
|
|
201
|
-
if (sub === "complete") {
|
|
202
|
-
result.subcommand =
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
if (result.command === "contact") {
|
|
206
|
-
if (positionals.length > 0) {
|
|
207
|
-
const sub = positionals[0];
|
|
208
|
-
if (["list", "add", "remove", "import"].includes(sub)) {
|
|
209
|
-
result.subcommand = sub;
|
|
210
|
-
result.positionals = positionals.slice(1);
|
|
211
|
-
}
|
|
265
|
+
if (sub === "complete" || sub === "confirm-profile") {
|
|
266
|
+
result.subcommand = sub;
|
|
212
267
|
}
|
|
213
268
|
}
|
|
214
|
-
if (result.command === "scrape") {
|
|
269
|
+
if (result.command === "scrape" || result.command === "docs") {
|
|
215
270
|
result.positionals = positionals;
|
|
216
271
|
}
|
|
217
272
|
if (result.command === "intent") {
|
|
@@ -233,7 +288,7 @@ function parseArgs(args) {
|
|
|
233
288
|
}
|
|
234
289
|
return result;
|
|
235
290
|
}
|
|
236
|
-
var INTENT_SUBCOMMANDS = new Set(["list", "show", "create", "archive", "update", "
|
|
291
|
+
var INTENT_SUBCOMMANDS = new Set(["list", "show", "create", "prepare", "archive", "pause", "resume", "update", "networks", "add-to-network", "remove-from-network"]);
|
|
237
292
|
function parseIntentArgs(positionals, result) {
|
|
238
293
|
if (positionals.length === 0)
|
|
239
294
|
return;
|
|
@@ -245,9 +300,13 @@ function parseIntentArgs(positionals, result) {
|
|
|
245
300
|
switch (result.subcommand) {
|
|
246
301
|
case "show":
|
|
247
302
|
case "archive":
|
|
303
|
+
case "pause":
|
|
304
|
+
case "resume":
|
|
305
|
+
case "networks":
|
|
248
306
|
result.intentId = rest[0];
|
|
249
307
|
break;
|
|
250
308
|
case "create":
|
|
309
|
+
case "prepare":
|
|
251
310
|
if (rest.length > 0) {
|
|
252
311
|
result.intentContent = rest.join(" ");
|
|
253
312
|
}
|
|
@@ -258,8 +317,8 @@ function parseIntentArgs(positionals, result) {
|
|
|
258
317
|
result.intentContent = rest.slice(1).join(" ");
|
|
259
318
|
}
|
|
260
319
|
break;
|
|
261
|
-
case "
|
|
262
|
-
case "
|
|
320
|
+
case "add-to-network":
|
|
321
|
+
case "remove-from-network":
|
|
263
322
|
result.intentId = rest[0];
|
|
264
323
|
result.targetId = rest[1];
|
|
265
324
|
break;
|
|
@@ -283,7 +342,7 @@ class CredentialStore {
|
|
|
283
342
|
try {
|
|
284
343
|
const raw = await readFile(this.filePath, "utf-8");
|
|
285
344
|
const parsed = JSON.parse(raw);
|
|
286
|
-
if (parsed.token && parsed.apiUrl && parsed.authKind === "
|
|
345
|
+
if (parsed.token && parsed.apiUrl && parsed.authKind === "session") {
|
|
287
346
|
return parsed;
|
|
288
347
|
}
|
|
289
348
|
return null;
|
|
@@ -327,21 +386,16 @@ function isEarlyAccessNetworkCreationError(error) {
|
|
|
327
386
|
}
|
|
328
387
|
|
|
329
388
|
class ApiClient {
|
|
389
|
+
credentialKind;
|
|
330
390
|
baseUrl;
|
|
331
391
|
token;
|
|
332
|
-
constructor(baseUrl, token) {
|
|
392
|
+
constructor(baseUrl, token, credentialKind = "session") {
|
|
393
|
+
this.credentialKind = credentialKind;
|
|
333
394
|
this.baseUrl = baseUrl.replace(/\/$/, "");
|
|
334
395
|
this.token = token;
|
|
335
396
|
}
|
|
336
397
|
authHeaders() {
|
|
337
|
-
return { "x-api-key": this.token };
|
|
338
|
-
}
|
|
339
|
-
async revokeApiKey(keyId, targetKey = this.token) {
|
|
340
|
-
const res = await this.post("/api/auth/cli-credential/revoke", { keyId, targetKey });
|
|
341
|
-
const body = await res.json();
|
|
342
|
-
if (body.success !== true) {
|
|
343
|
-
throw new Error("API-key revocation was not confirmed");
|
|
344
|
-
}
|
|
398
|
+
return this.credentialKind === "apiKey" ? { "x-api-key": this.token } : { Authorization: `Bearer ${this.token}` };
|
|
345
399
|
}
|
|
346
400
|
async getMe() {
|
|
347
401
|
const res = await this.get("/api/auth/me");
|
|
@@ -357,10 +411,13 @@ class ApiClient {
|
|
|
357
411
|
const params = new URLSearchParams;
|
|
358
412
|
if (opts?.status)
|
|
359
413
|
params.set("status", opts.status);
|
|
414
|
+
if (opts?.statuses)
|
|
415
|
+
params.set("statuses", opts.statuses);
|
|
360
416
|
if (opts?.limit)
|
|
361
417
|
params.set("limit", String(opts.limit));
|
|
362
418
|
const qs = params.toString();
|
|
363
|
-
const
|
|
419
|
+
const base = opts?.intentId ? `/api/intents/${encodeURIComponent(opts.intentId)}/opportunities` : "/api/opportunities";
|
|
420
|
+
const path = qs ? `${base}?${qs}` : base;
|
|
364
421
|
const res = await this.get(path);
|
|
365
422
|
const body = await res.json();
|
|
366
423
|
return body.opportunities;
|
|
@@ -369,11 +426,12 @@ class ApiClient {
|
|
|
369
426
|
const res = await this.get(`/api/opportunities/${id}`);
|
|
370
427
|
return await res.json();
|
|
371
428
|
}
|
|
372
|
-
async updateOpportunityStatus(id, status
|
|
373
|
-
const res = await this.patch(`/api/opportunities/${id}/status`, {
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
429
|
+
async updateOpportunityStatus(id, status) {
|
|
430
|
+
const res = await this.patch(`/api/opportunities/${encodeURIComponent(id)}/status`, { status });
|
|
431
|
+
return await res.json();
|
|
432
|
+
}
|
|
433
|
+
async startOpportunityChat(id) {
|
|
434
|
+
const res = await this.post(`/api/opportunities/${encodeURIComponent(id)}/start-chat`, {});
|
|
377
435
|
return await res.json();
|
|
378
436
|
}
|
|
379
437
|
async listIntents(options = {}) {
|
|
@@ -386,6 +444,8 @@ class ApiClient {
|
|
|
386
444
|
body.sourceType = options.sourceType;
|
|
387
445
|
if (options.page !== undefined)
|
|
388
446
|
body.page = options.page;
|
|
447
|
+
if (options.query !== undefined)
|
|
448
|
+
body.q = options.query;
|
|
389
449
|
const res = await this.post("/api/intents/list", body);
|
|
390
450
|
return await res.json();
|
|
391
451
|
}
|
|
@@ -394,17 +454,38 @@ class ApiClient {
|
|
|
394
454
|
const body = await res.json();
|
|
395
455
|
return body.intent;
|
|
396
456
|
}
|
|
397
|
-
async
|
|
398
|
-
const res = await this.post("/api/intents
|
|
399
|
-
proposalId,
|
|
457
|
+
async createIntent(description, networkIds, preparationReceipt) {
|
|
458
|
+
const res = await this.post("/api/intents", {
|
|
400
459
|
description,
|
|
401
|
-
...
|
|
460
|
+
...networkIds?.length ? { networkIds } : {},
|
|
461
|
+
...preparationReceipt ? { preparationReceipt } : {}
|
|
402
462
|
});
|
|
403
|
-
|
|
404
|
-
|
|
463
|
+
return await res.json();
|
|
464
|
+
}
|
|
465
|
+
async prepareIntent(payload, answers = []) {
|
|
466
|
+
const res = await this.post("/api/intents/prepare", { payload, answers });
|
|
467
|
+
return await res.json();
|
|
468
|
+
}
|
|
469
|
+
async updateIntentStatus(id, status) {
|
|
470
|
+
await this.patch(`/api/intents/${encodeURIComponent(id)}/status`, { status });
|
|
405
471
|
}
|
|
406
472
|
async updateIntent(intentId, description) {
|
|
407
|
-
|
|
473
|
+
const res = await this.patch(`/api/intents/${encodeURIComponent(intentId)}`, { description });
|
|
474
|
+
return await res.json();
|
|
475
|
+
}
|
|
476
|
+
async archiveIntent(intentId) {
|
|
477
|
+
await this.patch(`/api/intents/${encodeURIComponent(intentId)}/archive`);
|
|
478
|
+
}
|
|
479
|
+
async listIntentNetworks(intentId) {
|
|
480
|
+
const res = await this.get(`/api/intents/${encodeURIComponent(intentId)}/networks`);
|
|
481
|
+
const body = await res.json();
|
|
482
|
+
return body.networkIds;
|
|
483
|
+
}
|
|
484
|
+
async addIntentToNetwork(intentId, networkId) {
|
|
485
|
+
await this.post(`/api/intents/${encodeURIComponent(intentId)}/networks`, { networkId });
|
|
486
|
+
}
|
|
487
|
+
async removeIntentFromNetwork(intentId, networkId) {
|
|
488
|
+
await this.del(`/api/intents/${encodeURIComponent(intentId)}/networks/${encodeURIComponent(networkId)}`);
|
|
408
489
|
}
|
|
409
490
|
async listNetworks() {
|
|
410
491
|
const res = await this.get("/api/networks");
|
|
@@ -414,14 +495,26 @@ class ApiClient {
|
|
|
414
495
|
joinPolicy: n.joinPolicy ?? n.permissions?.joinPolicy
|
|
415
496
|
}));
|
|
416
497
|
}
|
|
498
|
+
async discoverNetworks() {
|
|
499
|
+
return await (await this.get("/api/networks/discovery/public?page=1&limit=50")).json();
|
|
500
|
+
}
|
|
501
|
+
async listNetworkRequests() {
|
|
502
|
+
return await (await this.get("/api/network-requests")).json();
|
|
503
|
+
}
|
|
504
|
+
async updateNetworkRequest(id, name, purpose) {
|
|
505
|
+
return await (await this.patch(`/api/network-requests/${encodeURIComponent(id)}`, { name, ...purpose ? { purpose } : {} })).json();
|
|
506
|
+
}
|
|
507
|
+
async dismissNetworkRequest(id) {
|
|
508
|
+
await this.del(`/api/network-requests/${encodeURIComponent(id)}`);
|
|
509
|
+
}
|
|
417
510
|
async createNetworkOrRequest(title, prompt) {
|
|
418
511
|
try {
|
|
419
|
-
const
|
|
512
|
+
const res = await this.post("/api/networks", {
|
|
420
513
|
title,
|
|
421
514
|
...prompt ? { prompt } : {}
|
|
422
515
|
});
|
|
423
|
-
const
|
|
424
|
-
return { kind: "created", network:
|
|
516
|
+
const body = await res.json();
|
|
517
|
+
return { kind: "created", network: body.network };
|
|
425
518
|
} catch (error) {
|
|
426
519
|
if (!isEarlyAccessNetworkCreationError(error))
|
|
427
520
|
throw error;
|
|
@@ -452,6 +545,14 @@ class ApiClient {
|
|
|
452
545
|
async leaveNetwork(id) {
|
|
453
546
|
await this.post(`/api/networks/${id}/leave`, {});
|
|
454
547
|
}
|
|
548
|
+
async updateNetwork(id, settings) {
|
|
549
|
+
const res = await this.put(`/api/networks/${id}`, settings);
|
|
550
|
+
const body = await res.json();
|
|
551
|
+
return body.network;
|
|
552
|
+
}
|
|
553
|
+
async deleteNetwork(id) {
|
|
554
|
+
await this.del(`/api/networks/${id}`);
|
|
555
|
+
}
|
|
455
556
|
async inviteNetworkMember(networkId, email, name) {
|
|
456
557
|
const res = await this.post(`/api/networks/${networkId}/members/invite`, {
|
|
457
558
|
email,
|
|
@@ -481,18 +582,23 @@ class ApiClient {
|
|
|
481
582
|
const body = await res.json();
|
|
482
583
|
return body.messages;
|
|
483
584
|
}
|
|
484
|
-
async sendMessage(conversationId, text) {
|
|
585
|
+
async sendMessage(conversationId, text, intentId, questionId) {
|
|
485
586
|
const res = await this.post(`/api/conversations/${conversationId}/messages`, {
|
|
486
|
-
parts: [{
|
|
587
|
+
parts: [{ kind: "text", text }],
|
|
588
|
+
...intentId ? { metadata: { intentId } } : {},
|
|
589
|
+
...questionId ? { questionId } : {}
|
|
487
590
|
});
|
|
488
591
|
const body = await res.json();
|
|
489
592
|
return body.message;
|
|
490
593
|
}
|
|
594
|
+
async answerAgentQuestions(intentId, answers) {
|
|
595
|
+
return await (await this.post("/api/conversations/agent/answers", { intentId, answers })).json();
|
|
596
|
+
}
|
|
491
597
|
async hideConversation(conversationId) {
|
|
492
598
|
await this.del(`/api/conversations/${conversationId}`);
|
|
493
599
|
}
|
|
494
|
-
async
|
|
495
|
-
const res = await fetch(`${this.baseUrl}/api/
|
|
600
|
+
async streamEvents() {
|
|
601
|
+
const res = await fetch(`${this.baseUrl}/api/events`, {
|
|
496
602
|
headers: {
|
|
497
603
|
...this.authHeaders(),
|
|
498
604
|
Accept: "text/event-stream"
|
|
@@ -504,16 +610,13 @@ class ApiClient {
|
|
|
504
610
|
return res;
|
|
505
611
|
}
|
|
506
612
|
async listNegotiations(opts) {
|
|
507
|
-
const me = await this.getMe();
|
|
508
613
|
const params = new URLSearchParams;
|
|
509
|
-
if (opts?.
|
|
510
|
-
params.set("
|
|
511
|
-
if (opts?.
|
|
512
|
-
params.set("
|
|
513
|
-
if (opts?.since)
|
|
514
|
-
params.set("since", opts.since);
|
|
614
|
+
if (opts?.intentId)
|
|
615
|
+
params.set("intentId", opts.intentId);
|
|
616
|
+
if (opts?.state)
|
|
617
|
+
params.set("state", opts.state);
|
|
515
618
|
const qs = params.toString();
|
|
516
|
-
const path =
|
|
619
|
+
const path = `/api/negotiations${qs ? `?${qs}` : ""}`;
|
|
517
620
|
const res = await this.get(path);
|
|
518
621
|
const body = await res.json();
|
|
519
622
|
return body.negotiations;
|
|
@@ -522,18 +625,37 @@ class ApiClient {
|
|
|
522
625
|
const res = await this.post("/api/enrichment/enrich", {});
|
|
523
626
|
return await res.json();
|
|
524
627
|
}
|
|
525
|
-
async
|
|
526
|
-
|
|
628
|
+
async updateProfile(fields) {
|
|
629
|
+
const body = await (await this.patch("/api/auth/profile/update", fields)).json();
|
|
630
|
+
return body.user;
|
|
527
631
|
}
|
|
528
|
-
async
|
|
529
|
-
|
|
632
|
+
async scrapeUrl(url, objective) {
|
|
633
|
+
const res = await this.post("/api/scrape", { url, ...objective ? { objective } : {} });
|
|
634
|
+
return await res.json();
|
|
530
635
|
}
|
|
531
|
-
async
|
|
532
|
-
|
|
636
|
+
async readDocs(topic) {
|
|
637
|
+
const path = topic ? `/api/docs?${new URLSearchParams({ topic })}` : "/api/docs";
|
|
638
|
+
return (await this.get(path)).json();
|
|
533
639
|
}
|
|
534
|
-
async
|
|
535
|
-
|
|
536
|
-
|
|
640
|
+
async getAgent() {
|
|
641
|
+
return (await this.get("/api/agents/me")).json();
|
|
642
|
+
}
|
|
643
|
+
async getNegotiation(opportunityId) {
|
|
644
|
+
const body = await (await this.get(`/api/opportunities/${encodeURIComponent(opportunityId)}/negotiation`)).json();
|
|
645
|
+
return body.negotiation;
|
|
646
|
+
}
|
|
647
|
+
async submitNegotiationTurn(opportunityId, turn) {
|
|
648
|
+
const body = await (await this.post(`/api/opportunities/${encodeURIComponent(opportunityId)}/negotiation/turns`, turn)).json();
|
|
649
|
+
return body.negotiation;
|
|
650
|
+
}
|
|
651
|
+
async getAgentConversation(intentId) {
|
|
652
|
+
return (await this.get(`/api/conversations/agent/messages?${new URLSearchParams({ intentId })}`)).json();
|
|
653
|
+
}
|
|
654
|
+
async confirmProfile() {
|
|
655
|
+
return (await this.post("/api/auth/onboarding/confirm-profile", {})).json();
|
|
656
|
+
}
|
|
657
|
+
async completeOnboarding(intentId) {
|
|
658
|
+
return (await this.post("/api/auth/onboarding/complete", { intentId })).json();
|
|
537
659
|
}
|
|
538
660
|
async get(path) {
|
|
539
661
|
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
@@ -558,6 +680,19 @@ class ApiClient {
|
|
|
558
680
|
}
|
|
559
681
|
return res;
|
|
560
682
|
}
|
|
683
|
+
async put(path, body) {
|
|
684
|
+
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
685
|
+
method: "PUT",
|
|
686
|
+
headers: {
|
|
687
|
+
"Content-Type": "application/json",
|
|
688
|
+
...this.authHeaders()
|
|
689
|
+
},
|
|
690
|
+
...body !== undefined ? { body: JSON.stringify(body) } : {}
|
|
691
|
+
});
|
|
692
|
+
if (!res.ok)
|
|
693
|
+
await this.handleError(res);
|
|
694
|
+
return res;
|
|
695
|
+
}
|
|
561
696
|
async patch(path, body) {
|
|
562
697
|
const res = await fetch(`${this.baseUrl}${path}`, {
|
|
563
698
|
method: "PATCH",
|
|
@@ -582,9 +717,6 @@ class ApiClient {
|
|
|
582
717
|
return res;
|
|
583
718
|
}
|
|
584
719
|
async handleError(res) {
|
|
585
|
-
if (res.status === 401) {
|
|
586
|
-
throw new ApiError("Session expired or invalid. Run `index login` to re-authenticate.", res.status);
|
|
587
|
-
}
|
|
588
720
|
let message = `HTTP ${res.status}`;
|
|
589
721
|
let response;
|
|
590
722
|
try {
|
|
@@ -603,23 +735,33 @@ class ApiClient {
|
|
|
603
735
|
import { randomBytes } from "node:crypto";
|
|
604
736
|
import { createServer } from "node:http";
|
|
605
737
|
|
|
606
|
-
// src/auth.
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
738
|
+
// src/auth.session.ts
|
|
739
|
+
var DEVICE_CLIENT_ID = "index-device";
|
|
740
|
+
async function redeemDeviceCode(baseUrl, deviceCode) {
|
|
741
|
+
const response = await fetch(`${baseUrl}/api/auth/device/token`, {
|
|
742
|
+
method: "POST",
|
|
743
|
+
headers: { "Content-Type": "application/json", "User-Agent": "index-cli" },
|
|
744
|
+
body: JSON.stringify({
|
|
745
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
746
|
+
device_code: deviceCode,
|
|
747
|
+
client_id: DEVICE_CLIENT_ID
|
|
748
|
+
})
|
|
749
|
+
});
|
|
750
|
+
const body = await response.json().catch(() => null);
|
|
751
|
+
if (!response.ok || !body?.access_token) {
|
|
752
|
+
throw new Error(body?.error_description ?? "Could not complete device sign-in.");
|
|
753
|
+
}
|
|
754
|
+
return body.access_token;
|
|
755
|
+
}
|
|
756
|
+
async function revokeSession(baseUrl, token) {
|
|
615
757
|
try {
|
|
616
|
-
await
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
return
|
|
621
|
-
|
|
622
|
-
|
|
758
|
+
const response = await fetch(`${baseUrl}/api/auth/sign-out`, {
|
|
759
|
+
method: "POST",
|
|
760
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
761
|
+
});
|
|
762
|
+
return response.ok;
|
|
763
|
+
} catch {
|
|
764
|
+
return false;
|
|
623
765
|
}
|
|
624
766
|
}
|
|
625
767
|
|
|
@@ -676,33 +818,28 @@ async function handleLogin(apiUrl, appUrl, store, options = {}) {
|
|
|
676
818
|
return;
|
|
677
819
|
}
|
|
678
820
|
stateConsumed = true;
|
|
679
|
-
const
|
|
680
|
-
|
|
681
|
-
if (apiKey && keyId) {
|
|
821
|
+
const deviceCode = url.searchParams.get("device_code");
|
|
822
|
+
if (deviceCode) {
|
|
682
823
|
try {
|
|
683
|
-
const
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
resolveCallback({ success: false, error: "Failed to save CLI credentials." });
|
|
824
|
+
const token = await redeemDeviceCode(baseUrl, deviceCode);
|
|
825
|
+
await store.save({ token, apiUrl: baseUrl, authKind: "session" });
|
|
826
|
+
if (previousCredentials)
|
|
827
|
+
await revokeSession(previousCredentials.apiUrl, previousCredentials.token);
|
|
828
|
+
resolveCallback({ success: true });
|
|
829
|
+
} catch (error) {
|
|
830
|
+
const message = error instanceof Error ? error.message : "Failed to save CLI credentials.";
|
|
831
|
+
resolveCallback({ success: false, error: message });
|
|
692
832
|
res.writeHead(500, { "Content-Type": "text/html" });
|
|
693
|
-
res.end(callbackHtml("Authorization failed", "CLI
|
|
833
|
+
res.end(callbackHtml("Authorization failed", "CLI sign-in could not be completed. Return to the terminal and try again."));
|
|
694
834
|
return;
|
|
695
835
|
}
|
|
696
836
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
697
|
-
res.end(callbackHtml("
|
|
837
|
+
res.end(callbackHtml("Authentication complete", "You can close this window and return to the terminal.", true));
|
|
698
838
|
return;
|
|
699
839
|
}
|
|
700
|
-
resolveCallback({
|
|
701
|
-
success: false,
|
|
702
|
-
error: apiKey ? "CLI API-key callback did not include its key ID." : "No CLI credential received in callback."
|
|
703
|
-
});
|
|
840
|
+
resolveCallback({ success: false, error: "No device code received in callback." });
|
|
704
841
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
705
|
-
res.end(callbackHtml("Authorization failed", "Incomplete
|
|
842
|
+
res.end(callbackHtml("Authorization failed", "Incomplete sign-in received. Please try again."));
|
|
706
843
|
});
|
|
707
844
|
let listenSettled = false;
|
|
708
845
|
let rejectListen = null;
|
|
@@ -813,168 +950,64 @@ p{font-size:14px;font-weight:500;margin:0;color:rgba(244,251,246,0.78)}
|
|
|
813
950
|
}
|
|
814
951
|
|
|
815
952
|
// src/logout.command.ts
|
|
816
|
-
async function handleLogout(store
|
|
953
|
+
async function handleLogout(store) {
|
|
817
954
|
const credentials = await store.load();
|
|
818
955
|
if (!credentials) {
|
|
819
956
|
return { success: true, message: "Already logged out." };
|
|
820
957
|
}
|
|
821
|
-
const
|
|
822
|
-
try {
|
|
823
|
-
await createClient(credentials.apiUrl, credentials.token).revokeApiKey(credentials.keyId, credentials.token);
|
|
824
|
-
} catch (error) {
|
|
825
|
-
const detail = error instanceof Error ? ` ${error.message}` : "";
|
|
826
|
-
return {
|
|
827
|
-
success: false,
|
|
828
|
-
warning: `Logout could not revoke the stored CLI API key, so credentials were retained.${detail}`
|
|
829
|
-
};
|
|
830
|
-
}
|
|
958
|
+
const revoked = await revokeSession(credentials.apiUrl, credentials.token);
|
|
831
959
|
try {
|
|
832
960
|
await store.clear();
|
|
833
961
|
} catch {
|
|
834
962
|
return {
|
|
835
963
|
success: false,
|
|
836
|
-
warning: "
|
|
964
|
+
warning: "Local credential cleanup failed. Remove the local credentials file manually before signing in again."
|
|
837
965
|
};
|
|
838
966
|
}
|
|
839
|
-
return {
|
|
967
|
+
return {
|
|
968
|
+
success: true,
|
|
969
|
+
message: revoked ? "Logged out." : "Logged out locally. The session could not be reached — revoke it in Index web settings if this machine is not yours."
|
|
970
|
+
};
|
|
840
971
|
}
|
|
841
972
|
|
|
842
|
-
// src/output/index.ts
|
|
843
|
-
var exports_output = {};
|
|
844
|
-
__export(exports_output, {
|
|
845
|
-
wordWrap: () => wordWrap,
|
|
846
|
-
warn: () => warn,
|
|
847
|
-
toolActivity: () => toolActivity,
|
|
848
|
-
success: () => success,
|
|
849
|
-
stripAnsi: () => stripAnsi,
|
|
850
|
-
status: () => status,
|
|
851
|
-
raw: () => raw,
|
|
852
|
-
profileCard: () => profileCard,
|
|
853
|
-
padTo: () => padTo,
|
|
854
|
-
opportunityTable: () => opportunityTable,
|
|
855
|
-
opportunityCard: () => opportunityCard,
|
|
856
|
-
networkTable: () => networkTable,
|
|
857
|
-
networkCard: () => networkCard,
|
|
858
|
-
messageList: () => messageList,
|
|
859
|
-
memberTable: () => memberTable,
|
|
860
|
-
intentTable: () => intentTable,
|
|
861
|
-
intentCard: () => intentCard,
|
|
862
|
-
info: () => info,
|
|
863
|
-
humanizeToolName: () => humanizeToolName,
|
|
864
|
-
heading: () => heading,
|
|
865
|
-
error: () => error,
|
|
866
|
-
dim: () => dim,
|
|
867
|
-
conversationTable: () => conversationTable,
|
|
868
|
-
conversationCard: () => conversationCard,
|
|
869
|
-
contactTable: () => contactTable,
|
|
870
|
-
confidenceBar: () => confidenceBar,
|
|
871
|
-
clearStatus: () => clearStatus,
|
|
872
|
-
chatHeader: () => chatHeader,
|
|
873
|
-
YELLOW: () => YELLOW,
|
|
874
|
-
WHITE: () => WHITE,
|
|
875
|
-
USER_PROMPT: () => USER_PROMPT,
|
|
876
|
-
RESET: () => RESET,
|
|
877
|
-
RED: () => RED,
|
|
878
|
-
PROMPT_STR: () => PROMPT_STR,
|
|
879
|
-
ORANGE: () => ORANGE,
|
|
880
|
-
MarkdownRenderer: () => MarkdownRenderer,
|
|
881
|
-
MAGENTA: () => MAGENTA,
|
|
882
|
-
ITALIC: () => ITALIC,
|
|
883
|
-
GREEN: () => GREEN,
|
|
884
|
-
GRAY: () => GRAY,
|
|
885
|
-
DIM: () => DIM,
|
|
886
|
-
CYAN: () => CYAN,
|
|
887
|
-
BOLD: () => BOLD,
|
|
888
|
-
BLUE: () => BLUE,
|
|
889
|
-
AGENT_TEXT: () => AGENT_TEXT
|
|
890
|
-
});
|
|
891
|
-
|
|
892
973
|
// src/output/base.ts
|
|
893
974
|
var RESET = "\x1B[0m";
|
|
894
975
|
var BOLD = "\x1B[1m";
|
|
895
976
|
var DIM = "\x1B[2m";
|
|
896
|
-
var ITALIC = "\x1B[3m";
|
|
897
977
|
var RED = "\x1B[31m";
|
|
898
978
|
var GREEN = "\x1B[32m";
|
|
899
979
|
var YELLOW = "\x1B[33m";
|
|
900
980
|
var BLUE = "\x1B[34m";
|
|
901
|
-
var MAGENTA = "\x1B[35m";
|
|
902
981
|
var CYAN = "\x1B[36m";
|
|
903
982
|
var WHITE = "\x1B[37m";
|
|
904
983
|
var GRAY = "\x1B[90m";
|
|
905
|
-
var ORANGE = "\x1B[38;5;208m";
|
|
906
984
|
var AGENT_TEXT = "\x1B[38;5;252m";
|
|
907
985
|
var USER_PROMPT = CYAN;
|
|
908
986
|
function error(message, exitCode) {
|
|
987
|
+
if (process.argv.includes("--json"))
|
|
988
|
+
throw new Error(message);
|
|
909
989
|
console.error(`${RED}${BOLD}error${RESET}${RED}: ${message}${RESET}`);
|
|
910
|
-
|
|
990
|
+
process.exitCode = exitCode ?? 1;
|
|
991
|
+
if (exitCode !== undefined)
|
|
911
992
|
process.exit(exitCode);
|
|
912
|
-
}
|
|
913
993
|
}
|
|
914
994
|
function success(message) {
|
|
915
995
|
console.log(`${GREEN}${BOLD}+${RESET} ${message}`);
|
|
916
996
|
}
|
|
917
997
|
function info(message) {
|
|
918
|
-
console.
|
|
998
|
+
console.error(`${CYAN}${message}${RESET}`);
|
|
919
999
|
}
|
|
920
1000
|
function warn(message) {
|
|
921
1001
|
console.warn(`${YELLOW}${message}${RESET}`);
|
|
922
1002
|
}
|
|
923
1003
|
function dim(message) {
|
|
924
|
-
console.
|
|
1004
|
+
console.error(`${GRAY}${message}${RESET}`);
|
|
925
1005
|
}
|
|
926
1006
|
function heading(message) {
|
|
927
1007
|
console.log(`
|
|
928
1008
|
${BOLD}${message}${RESET}`);
|
|
929
1009
|
}
|
|
930
|
-
function chatHeader() {
|
|
931
|
-
console.log();
|
|
932
|
-
console.log(` ${BOLD}${CYAN}I N D E X${RESET} ${GRAY}chat${RESET}`);
|
|
933
|
-
console.log(` ${GRAY}─────────────────────────────────────${RESET}`);
|
|
934
|
-
console.log(` ${GRAY}Type your message. "exit" or Ctrl+C to quit.${RESET}`);
|
|
935
|
-
console.log();
|
|
936
|
-
}
|
|
937
1010
|
var PROMPT_STR = `${USER_PROMPT}${BOLD}> ${RESET}`;
|
|
938
|
-
function raw(text) {
|
|
939
|
-
process.stdout.write(text);
|
|
940
|
-
}
|
|
941
|
-
function status(message) {
|
|
942
|
-
process.stderr.write(`\r ${GRAY}${message}${RESET}\x1B[K`);
|
|
943
|
-
}
|
|
944
|
-
function clearStatus() {
|
|
945
|
-
process.stderr.write("\r\x1B[K");
|
|
946
|
-
}
|
|
947
|
-
function toolActivity(description) {
|
|
948
|
-
process.stderr.write(`\r\x1B[K${ORANGE}> ${description}${RESET}
|
|
949
|
-
`);
|
|
950
|
-
}
|
|
951
|
-
var TOOL_DESCRIPTIONS = {
|
|
952
|
-
read_user_contexts: "Reading your profile...",
|
|
953
|
-
create_user_context: "Creating your profile...",
|
|
954
|
-
update_user_context: "Updating your profile...",
|
|
955
|
-
read_intents: "Fetching your active signals...",
|
|
956
|
-
create_intent: "Creating a new signal...",
|
|
957
|
-
update_intent: "Updating signal...",
|
|
958
|
-
delete_intent: "Removing signal...",
|
|
959
|
-
create_intent_index: "Saving signal to index...",
|
|
960
|
-
read_intent_indexes: "Fetching signals in index...",
|
|
961
|
-
delete_intent_index: "Removing signal from index...",
|
|
962
|
-
read_networks: "Checking your communities...",
|
|
963
|
-
create_network: "Creating a new community...",
|
|
964
|
-
update_network: "Updating community...",
|
|
965
|
-
delete_network: "Deleting community...",
|
|
966
|
-
create_network_membership: "Adding member to community...",
|
|
967
|
-
read_network_memberships: "Fetching community memberships...",
|
|
968
|
-
list_opportunities: "Listing your opportunities...",
|
|
969
|
-
update_opportunity: "Updating opportunity status...",
|
|
970
|
-
scrape_url: "Reading content from URL...",
|
|
971
|
-
read_docs: "Looking up documentation...",
|
|
972
|
-
list_contacts: "Listing your contacts...",
|
|
973
|
-
remove_contact: "Removing contact..."
|
|
974
|
-
};
|
|
975
|
-
function humanizeToolName(name) {
|
|
976
|
-
return TOOL_DESCRIPTIONS[name] ?? name.replace(/_/g, " ") + "...";
|
|
977
|
-
}
|
|
978
1011
|
function wordWrap(text, maxWidth) {
|
|
979
1012
|
const lines = [];
|
|
980
1013
|
const words = text.split(/\s+/);
|
|
@@ -1005,220 +1038,6 @@ function padTo(cellWidth, plainText) {
|
|
|
1005
1038
|
function stripAnsi(str) {
|
|
1006
1039
|
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
1007
1040
|
}
|
|
1008
|
-
// src/output/markdown.ts
|
|
1009
|
-
class MarkdownRenderer {
|
|
1010
|
-
buffer = "";
|
|
1011
|
-
inCodeBlock = false;
|
|
1012
|
-
codeBlockLang = "";
|
|
1013
|
-
codeBlockContent = "";
|
|
1014
|
-
pristine = true;
|
|
1015
|
-
write(text) {
|
|
1016
|
-
this.buffer += text;
|
|
1017
|
-
this.flush();
|
|
1018
|
-
}
|
|
1019
|
-
flush() {
|
|
1020
|
-
while (this.buffer.length > 0) {
|
|
1021
|
-
if (this.inCodeBlock) {
|
|
1022
|
-
const endIdx = this.buffer.indexOf("```");
|
|
1023
|
-
if (endIdx !== -1) {
|
|
1024
|
-
this.codeBlockContent += this.buffer.slice(0, endIdx);
|
|
1025
|
-
this.buffer = this.buffer.slice(endIdx + 3);
|
|
1026
|
-
if (this.buffer.startsWith(`
|
|
1027
|
-
`)) {
|
|
1028
|
-
this.buffer = this.buffer.slice(1);
|
|
1029
|
-
}
|
|
1030
|
-
this.renderCodeBlock();
|
|
1031
|
-
this.inCodeBlock = false;
|
|
1032
|
-
this.codeBlockLang = "";
|
|
1033
|
-
this.codeBlockContent = "";
|
|
1034
|
-
continue;
|
|
1035
|
-
}
|
|
1036
|
-
this.codeBlockContent += this.buffer;
|
|
1037
|
-
this.buffer = "";
|
|
1038
|
-
return;
|
|
1039
|
-
}
|
|
1040
|
-
const codeBlockMatch = this.buffer.match(/^```([^\n]*)\n/);
|
|
1041
|
-
if (codeBlockMatch) {
|
|
1042
|
-
this.codeBlockLang = codeBlockMatch[1].trim();
|
|
1043
|
-
this.buffer = this.buffer.slice(codeBlockMatch[0].length);
|
|
1044
|
-
this.inCodeBlock = true;
|
|
1045
|
-
this.codeBlockContent = "";
|
|
1046
|
-
continue;
|
|
1047
|
-
}
|
|
1048
|
-
if (this.buffer.startsWith("```")) {
|
|
1049
|
-
return;
|
|
1050
|
-
}
|
|
1051
|
-
const nlIdx = this.buffer.indexOf(`
|
|
1052
|
-
`);
|
|
1053
|
-
if (nlIdx === -1) {
|
|
1054
|
-
return;
|
|
1055
|
-
}
|
|
1056
|
-
const line = this.buffer.slice(0, nlIdx);
|
|
1057
|
-
this.buffer = this.buffer.slice(nlIdx + 1);
|
|
1058
|
-
this.emitLine(line);
|
|
1059
|
-
}
|
|
1060
|
-
}
|
|
1061
|
-
emitLine(line) {
|
|
1062
|
-
if (this.pristine) {
|
|
1063
|
-
process.stdout.write(`
|
|
1064
|
-
`);
|
|
1065
|
-
this.pristine = false;
|
|
1066
|
-
}
|
|
1067
|
-
const rendered = this.renderLine(line);
|
|
1068
|
-
process.stdout.write(rendered + `
|
|
1069
|
-
`);
|
|
1070
|
-
}
|
|
1071
|
-
renderLine(line) {
|
|
1072
|
-
const bulletMatch = line.match(/^(\s*)([-*])\s+(.*)$/);
|
|
1073
|
-
if (bulletMatch) {
|
|
1074
|
-
const [, indent, , content] = bulletMatch;
|
|
1075
|
-
return `${indent} ${CYAN}*${RESET} ${this.renderInline(content)}`;
|
|
1076
|
-
}
|
|
1077
|
-
const numMatch = line.match(/^(\s*)(\d+)\.\s+(.*)$/);
|
|
1078
|
-
if (numMatch) {
|
|
1079
|
-
const [, indent, num, content] = numMatch;
|
|
1080
|
-
return `${indent} ${CYAN}${num}.${RESET} ${this.renderInline(content)}`;
|
|
1081
|
-
}
|
|
1082
|
-
if (line.startsWith("### ")) {
|
|
1083
|
-
return `${BOLD}${WHITE}${line.slice(4)}${RESET}`;
|
|
1084
|
-
}
|
|
1085
|
-
if (line.startsWith("## ")) {
|
|
1086
|
-
return `${BOLD}${WHITE}${line.slice(3)}${RESET}`;
|
|
1087
|
-
}
|
|
1088
|
-
if (line.startsWith("# ")) {
|
|
1089
|
-
return `${BOLD}${WHITE}${line.slice(2)}${RESET}`;
|
|
1090
|
-
}
|
|
1091
|
-
return this.renderInline(line);
|
|
1092
|
-
}
|
|
1093
|
-
renderInline(text) {
|
|
1094
|
-
text = text.replace(/\*\*\*(.+?)\*\*\*/g, `${BOLD}${ITALIC}${WHITE}$1${RESET}${AGENT_TEXT}`);
|
|
1095
|
-
text = text.replace(/\*\*(.+?)\*\*/g, `${BOLD}${WHITE}$1${RESET}${AGENT_TEXT}`);
|
|
1096
|
-
text = text.replace(/(?<!\*)\*([^*]+?)\*(?!\*)/g, `${ITALIC}$1${RESET}${AGENT_TEXT}`);
|
|
1097
|
-
text = text.replace(/`([^`]+)`/g, `${CYAN}$1${RESET}${AGENT_TEXT}`);
|
|
1098
|
-
return `${AGENT_TEXT}${text}${RESET}`;
|
|
1099
|
-
}
|
|
1100
|
-
renderCodeBlock() {
|
|
1101
|
-
const lang = this.codeBlockLang;
|
|
1102
|
-
const content = this.codeBlockContent.trimEnd();
|
|
1103
|
-
if (!this.pristine) {
|
|
1104
|
-
process.stdout.write(`
|
|
1105
|
-
`);
|
|
1106
|
-
}
|
|
1107
|
-
this.pristine = false;
|
|
1108
|
-
if (lang === "intent_proposal") {
|
|
1109
|
-
this.renderIntentProposal(content);
|
|
1110
|
-
return;
|
|
1111
|
-
}
|
|
1112
|
-
if (lang === "opportunity") {
|
|
1113
|
-
this.renderOpportunity(content);
|
|
1114
|
-
return;
|
|
1115
|
-
}
|
|
1116
|
-
const border = `${GRAY}|${RESET}`;
|
|
1117
|
-
if (lang) {
|
|
1118
|
-
process.stdout.write(` ${GRAY}--- ${lang} ${"─".repeat(Math.max(0, 40 - lang.length))}${RESET}
|
|
1119
|
-
`);
|
|
1120
|
-
} else {
|
|
1121
|
-
process.stdout.write(` ${GRAY}${"─".repeat(46)}${RESET}
|
|
1122
|
-
`);
|
|
1123
|
-
}
|
|
1124
|
-
for (const line of content.split(`
|
|
1125
|
-
`)) {
|
|
1126
|
-
process.stdout.write(` ${border} ${CYAN}${line}${RESET}
|
|
1127
|
-
`);
|
|
1128
|
-
}
|
|
1129
|
-
process.stdout.write(` ${GRAY}${"─".repeat(46)}${RESET}
|
|
1130
|
-
|
|
1131
|
-
`);
|
|
1132
|
-
}
|
|
1133
|
-
renderIntentProposal(content) {
|
|
1134
|
-
try {
|
|
1135
|
-
const data = JSON.parse(content);
|
|
1136
|
-
const desc = data.description ?? content;
|
|
1137
|
-
const confidence = data.confidence;
|
|
1138
|
-
process.stdout.write(` ${MAGENTA}+${"─".repeat(56)}+${RESET}
|
|
1139
|
-
`);
|
|
1140
|
-
process.stdout.write(` ${MAGENTA}|${RESET} ${BOLD}${MAGENTA}Signal Proposal${RESET}${" ".repeat(40)}${MAGENTA}|${RESET}
|
|
1141
|
-
`);
|
|
1142
|
-
process.stdout.write(` ${MAGENTA}|${RESET}${" ".repeat(56)}${MAGENTA}|${RESET}
|
|
1143
|
-
`);
|
|
1144
|
-
const wrapped = wordWrap(desc, 52);
|
|
1145
|
-
for (const line of wrapped) {
|
|
1146
|
-
const pad = Math.max(0, 54 - line.length);
|
|
1147
|
-
process.stdout.write(` ${MAGENTA}|${RESET} ${AGENT_TEXT}${line}${RESET}${" ".repeat(pad)}${MAGENTA}|${RESET}
|
|
1148
|
-
`);
|
|
1149
|
-
}
|
|
1150
|
-
if (confidence !== undefined) {
|
|
1151
|
-
process.stdout.write(` ${MAGENTA}|${RESET}${" ".repeat(56)}${MAGENTA}|${RESET}
|
|
1152
|
-
`);
|
|
1153
|
-
const bar = confidenceBar(confidence);
|
|
1154
|
-
process.stdout.write(` ${MAGENTA}|${RESET} ${GRAY}Confidence: ${bar}${RESET}${" ".repeat(24)}${MAGENTA}|${RESET}
|
|
1155
|
-
`);
|
|
1156
|
-
}
|
|
1157
|
-
process.stdout.write(` ${MAGENTA}+${"─".repeat(56)}+${RESET}
|
|
1158
|
-
|
|
1159
|
-
`);
|
|
1160
|
-
} catch {
|
|
1161
|
-
process.stdout.write(` ${GRAY}${content}${RESET}
|
|
1162
|
-
|
|
1163
|
-
`);
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
renderOpportunity(content) {
|
|
1167
|
-
try {
|
|
1168
|
-
const data = JSON.parse(content);
|
|
1169
|
-
process.stdout.write(` ${BLUE}+${"─".repeat(56)}+${RESET}
|
|
1170
|
-
`);
|
|
1171
|
-
process.stdout.write(` ${BLUE}|${RESET} ${BOLD}${BLUE}Opportunity${RESET}${" ".repeat(44)}${BLUE}|${RESET}
|
|
1172
|
-
`);
|
|
1173
|
-
if (data.title) {
|
|
1174
|
-
const pad = Math.max(0, 54 - data.title.length);
|
|
1175
|
-
process.stdout.write(` ${BLUE}|${RESET} ${BOLD}${data.title}${RESET}${" ".repeat(pad)}${BLUE}|${RESET}
|
|
1176
|
-
`);
|
|
1177
|
-
}
|
|
1178
|
-
if (data.description) {
|
|
1179
|
-
process.stdout.write(` ${BLUE}|${RESET}${" ".repeat(56)}${BLUE}|${RESET}
|
|
1180
|
-
`);
|
|
1181
|
-
const wrapped = wordWrap(data.description, 52);
|
|
1182
|
-
for (const line of wrapped) {
|
|
1183
|
-
const pad = Math.max(0, 54 - line.length);
|
|
1184
|
-
process.stdout.write(` ${BLUE}|${RESET} ${AGENT_TEXT}${line}${RESET}${" ".repeat(pad)}${BLUE}|${RESET}
|
|
1185
|
-
`);
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
process.stdout.write(` ${BLUE}+${"─".repeat(56)}+${RESET}
|
|
1189
|
-
|
|
1190
|
-
`);
|
|
1191
|
-
} catch {
|
|
1192
|
-
process.stdout.write(` ${GRAY}${content}${RESET}
|
|
1193
|
-
|
|
1194
|
-
`);
|
|
1195
|
-
}
|
|
1196
|
-
}
|
|
1197
|
-
reset(reason) {
|
|
1198
|
-
if (this.buffer.length > 0 || this.inCodeBlock) {
|
|
1199
|
-
this.buffer = "";
|
|
1200
|
-
this.inCodeBlock = false;
|
|
1201
|
-
this.codeBlockContent = "";
|
|
1202
|
-
this.codeBlockLang = "";
|
|
1203
|
-
}
|
|
1204
|
-
if (!this.pristine) {
|
|
1205
|
-
process.stdout.write(`
|
|
1206
|
-
${GRAY}--- retrying${reason ? `: ${reason}` : ""} ---${RESET}
|
|
1207
|
-
`);
|
|
1208
|
-
}
|
|
1209
|
-
this.pristine = true;
|
|
1210
|
-
}
|
|
1211
|
-
finalize() {
|
|
1212
|
-
if (this.inCodeBlock) {
|
|
1213
|
-
this.renderCodeBlock();
|
|
1214
|
-
this.inCodeBlock = false;
|
|
1215
|
-
}
|
|
1216
|
-
if (this.buffer.length > 0) {
|
|
1217
|
-
this.emitLine(this.buffer);
|
|
1218
|
-
this.buffer = "";
|
|
1219
|
-
}
|
|
1220
|
-
}
|
|
1221
|
-
}
|
|
1222
1041
|
// src/output/formatters.ts
|
|
1223
1042
|
function profileCard(data) {
|
|
1224
1043
|
const lines = [];
|
|
@@ -1264,18 +1083,6 @@ function profileCard(data) {
|
|
|
1264
1083
|
console.log(output);
|
|
1265
1084
|
return output;
|
|
1266
1085
|
}
|
|
1267
|
-
function contactTable(contacts) {
|
|
1268
|
-
if (contacts.length === 0) {
|
|
1269
|
-
console.log(" No contacts yet.");
|
|
1270
|
-
return;
|
|
1271
|
-
}
|
|
1272
|
-
const nameWidth = Math.max(6, ...contacts.map((c) => c.name.length));
|
|
1273
|
-
const header = ` ${"Name".padEnd(nameWidth)} Email`;
|
|
1274
|
-
console.log(`${BOLD}${header}${RESET}`);
|
|
1275
|
-
for (const c of contacts) {
|
|
1276
|
-
console.log(` ${c.name.padEnd(nameWidth)} ${c.email}`);
|
|
1277
|
-
}
|
|
1278
|
-
}
|
|
1279
1086
|
function intentTable(intents) {
|
|
1280
1087
|
if (intents.length === 0) {
|
|
1281
1088
|
dim(" No signals found.");
|
|
@@ -1291,7 +1098,7 @@ function intentTable(intents) {
|
|
|
1291
1098
|
for (const intent of intents) {
|
|
1292
1099
|
const shortId = intent.id.slice(0, 8);
|
|
1293
1100
|
const desc = (intent.summary ?? intent.payload).slice(0, descWidth);
|
|
1294
|
-
const
|
|
1101
|
+
const status = (intent.status ?? "").padEnd(statusWidth);
|
|
1295
1102
|
const source = (intent.sourceType ?? "-").padEnd(sourceWidth);
|
|
1296
1103
|
const date = new Date(intent.createdAt).toLocaleDateString("en-US", {
|
|
1297
1104
|
year: "numeric",
|
|
@@ -1299,7 +1106,7 @@ function intentTable(intents) {
|
|
|
1299
1106
|
day: "numeric"
|
|
1300
1107
|
});
|
|
1301
1108
|
const sColor = intent.status === "ACTIVE" ? GREEN : GRAY;
|
|
1302
|
-
console.log(` ${CYAN}${shortId}${RESET} ${desc.padEnd(descWidth)} ${sColor}${
|
|
1109
|
+
console.log(` ${CYAN}${shortId}${RESET} ${desc.padEnd(descWidth)} ${sColor}${status}${RESET} ${GRAY}${source}${RESET} ${GRAY}${date}${RESET}`);
|
|
1303
1110
|
}
|
|
1304
1111
|
}
|
|
1305
1112
|
function intentCard(intent) {
|
|
@@ -1339,10 +1146,10 @@ function intentCard(intent) {
|
|
|
1339
1146
|
if (intent.archivedAt) {
|
|
1340
1147
|
console.log(` ${BOLD}Archived${RESET} ${GRAY}${new Date(intent.archivedAt).toLocaleString()}${RESET}`);
|
|
1341
1148
|
}
|
|
1342
|
-
if (intent.
|
|
1149
|
+
if (intent.networks && intent.networks.length > 0) {
|
|
1343
1150
|
console.log();
|
|
1344
|
-
console.log(` ${BOLD}
|
|
1345
|
-
for (const idx of intent.
|
|
1151
|
+
console.log(` ${BOLD}Networks${RESET}`);
|
|
1152
|
+
for (const idx of intent.networks) {
|
|
1346
1153
|
const score = idx.relevancyScore !== undefined ? ` (${idx.relevancyScore.toFixed(2)})` : "";
|
|
1347
1154
|
console.log(` ${CYAN}*${RESET} ${idx.title}${GRAY}${score}${RESET}`);
|
|
1348
1155
|
}
|
|
@@ -1368,35 +1175,25 @@ function opportunityTable(opportunities) {
|
|
|
1368
1175
|
}
|
|
1369
1176
|
const idW = 8;
|
|
1370
1177
|
const nameW = 20;
|
|
1371
|
-
const
|
|
1372
|
-
const
|
|
1373
|
-
|
|
1374
|
-
const dateW = 20;
|
|
1375
|
-
process.stdout.write(` ${BOLD}${"ID".padEnd(idW)} ${"Counterparty".padEnd(nameW)} ${"Category".padEnd(catW)} ${"Status".padEnd(statusW)} ${"Conf".padEnd(confW)} ${"Created".padEnd(dateW)}${RESET}
|
|
1178
|
+
const statusW = 12;
|
|
1179
|
+
const headlineW = 48;
|
|
1180
|
+
process.stdout.write(` ${BOLD}${"ID".padEnd(idW)} ${"Counterparty".padEnd(nameW)} ${"Status".padEnd(statusW)} Headline${RESET}
|
|
1376
1181
|
`);
|
|
1377
|
-
process.stdout.write(` ${GRAY}${"-".repeat(idW)} ${"-".repeat(nameW)} ${"-".repeat(
|
|
1182
|
+
process.stdout.write(` ${GRAY}${"-".repeat(idW)} ${"-".repeat(nameW)} ${"-".repeat(statusW)} ${"-".repeat(headlineW)}${RESET}
|
|
1378
1183
|
`);
|
|
1379
1184
|
for (const opp of opportunities) {
|
|
1380
|
-
const shortId = opp.
|
|
1381
|
-
const
|
|
1382
|
-
const name = (opp.counterpartName ?? fallbackName ?? "Unknown").slice(0, nameW);
|
|
1383
|
-
const category = (opp.interpretation?.category ?? "-").slice(0, catW);
|
|
1185
|
+
const shortId = opp.opportunityId.slice(0, idW);
|
|
1186
|
+
const name = opp.peer.name.slice(0, nameW);
|
|
1384
1187
|
const st = opp.status.slice(0, statusW);
|
|
1385
|
-
const
|
|
1386
|
-
|
|
1387
|
-
const date = opp.createdAt ? new Date(opp.createdAt).toLocaleDateString("en-US", {
|
|
1388
|
-
year: "numeric",
|
|
1389
|
-
month: "short",
|
|
1390
|
-
day: "numeric"
|
|
1391
|
-
}) : "-";
|
|
1392
|
-
process.stdout.write(` ${CYAN}${shortId}${RESET} ${name.padEnd(nameW)} ${GRAY}${category.padEnd(catW)}${RESET} ${statusColor(st)}${st.padEnd(statusW)}${RESET} ${GRAY}${conf.padEnd(confW)}${RESET} ${GRAY}${date.padEnd(dateW)}${RESET}
|
|
1188
|
+
const headline = (opp.headline ?? opp.mainText).slice(0, headlineW);
|
|
1189
|
+
process.stdout.write(` ${CYAN}${shortId}${RESET} ${name.padEnd(nameW)} ${statusColor(st)}${st.padEnd(statusW)}${RESET} ${headline}
|
|
1393
1190
|
`);
|
|
1394
1191
|
}
|
|
1395
1192
|
}
|
|
1396
1193
|
function opportunityCard(opp) {
|
|
1397
1194
|
const width = 58;
|
|
1398
1195
|
const innerWidth = width - 2;
|
|
1399
|
-
const title = opp.
|
|
1196
|
+
const title = opp.headline ?? "Opportunity";
|
|
1400
1197
|
process.stdout.write(`
|
|
1401
1198
|
${BLUE}+${"─".repeat(width)}+${RESET}
|
|
1402
1199
|
`);
|
|
@@ -1407,13 +1204,15 @@ function opportunityCard(opp) {
|
|
|
1407
1204
|
cardLine(`${BOLD}Status:${RESET} ${statusColor(st)}${st}${RESET}`);
|
|
1408
1205
|
if (opp.category)
|
|
1409
1206
|
cardLine(`${BOLD}Category:${RESET} ${opp.category}`);
|
|
1410
|
-
if (opp.
|
|
1411
|
-
cardLine(`${BOLD}Network:${RESET} ${opp.
|
|
1207
|
+
if (opp.network?.title)
|
|
1208
|
+
cardLine(`${BOLD}Network:${RESET} ${opp.network.title}`);
|
|
1412
1209
|
if (opp.confidence != null)
|
|
1413
1210
|
cardLine(`${BOLD}Confidence:${RESET} ${confidenceBar(opp.confidence)}`);
|
|
1414
1211
|
if (opp.myRole)
|
|
1415
1212
|
cardLine(`${BOLD}Your role:${RESET} ${roleLabel(opp.myRole)}`);
|
|
1416
|
-
if (opp.
|
|
1213
|
+
if (opp.peer?.name)
|
|
1214
|
+
cardLine(`${BOLD}With:${RESET} ${opp.peer.name}`);
|
|
1215
|
+
else if (opp.otherParties && opp.otherParties.length > 0) {
|
|
1417
1216
|
process.stdout.write(` ${BLUE}|${RESET}
|
|
1418
1217
|
`);
|
|
1419
1218
|
cardLine(`${BOLD}With:${RESET}`);
|
|
@@ -1421,11 +1220,11 @@ function opportunityCard(opp) {
|
|
|
1421
1220
|
cardLine(` ${p.name ?? p.id} ${roleLabel(p.role)}`);
|
|
1422
1221
|
}
|
|
1423
1222
|
}
|
|
1424
|
-
if (opp.
|
|
1223
|
+
if (opp.mainText) {
|
|
1425
1224
|
process.stdout.write(` ${BLUE}|${RESET}
|
|
1426
1225
|
`);
|
|
1427
1226
|
cardLine(`${BOLD}Details:${RESET}`);
|
|
1428
|
-
for (const line of wordWrap(opp.
|
|
1227
|
+
for (const line of wordWrap(opp.mainText, innerWidth - 4)) {
|
|
1429
1228
|
cardLine(` ${AGENT_TEXT}${line}${RESET}`);
|
|
1430
1229
|
}
|
|
1431
1230
|
}
|
|
@@ -1588,7 +1387,7 @@ function messageList(messages) {
|
|
|
1588
1387
|
month: "short",
|
|
1589
1388
|
day: "numeric"
|
|
1590
1389
|
});
|
|
1591
|
-
const textParts = msg.parts.filter((p) => p.
|
|
1390
|
+
const textParts = msg.parts.filter((p) => p.kind === "text" && p.text).map((p) => p.text).join("");
|
|
1592
1391
|
console.log(` ${CYAN}${sender}${RESET} ${GRAY}${date} ${time}${RESET}`);
|
|
1593
1392
|
console.log(` ${textParts}`);
|
|
1594
1393
|
console.log();
|
|
@@ -1596,17 +1395,20 @@ function messageList(messages) {
|
|
|
1596
1395
|
}
|
|
1597
1396
|
// src/profile.command.ts
|
|
1598
1397
|
async function handleProfile(client, subcommand, positionals, options = {}) {
|
|
1599
|
-
if (subcommand === "create") {
|
|
1600
|
-
await profileCreate(client, options, options?.json);
|
|
1601
|
-
return;
|
|
1602
|
-
}
|
|
1603
1398
|
if (subcommand === "update") {
|
|
1604
|
-
const
|
|
1605
|
-
if (
|
|
1606
|
-
|
|
1607
|
-
return;
|
|
1399
|
+
const { name, intro, location, socials } = options;
|
|
1400
|
+
if (name === undefined && intro === undefined && location === undefined && socials === undefined) {
|
|
1401
|
+
throw new Error("Usage: index profile update [--name <text>] [--intro <text>] [--location <text>] [--social label=value]");
|
|
1608
1402
|
}
|
|
1609
|
-
await
|
|
1403
|
+
const user = await client.updateProfile({ name, intro, location, socials });
|
|
1404
|
+
if (options.json)
|
|
1405
|
+
console.log(JSON.stringify(user));
|
|
1406
|
+
else
|
|
1407
|
+
success("Profile updated.");
|
|
1408
|
+
return;
|
|
1409
|
+
}
|
|
1410
|
+
if (subcommand === "create" || subcommand === "search") {
|
|
1411
|
+
error(`profile ${subcommand} is not available; use "index profile sync" for public research prefill`, 1);
|
|
1610
1412
|
return;
|
|
1611
1413
|
}
|
|
1612
1414
|
if (subcommand === "sync") {
|
|
@@ -1622,35 +1424,6 @@ async function handleProfile(client, subcommand, positionals, options = {}) {
|
|
|
1622
1424
|
await profileShow(client, userId, options?.json);
|
|
1623
1425
|
return;
|
|
1624
1426
|
}
|
|
1625
|
-
if (subcommand === "search") {
|
|
1626
|
-
const query = positionals.join(" ");
|
|
1627
|
-
if (!query) {
|
|
1628
|
-
error("Usage: index profile search <query>", 1);
|
|
1629
|
-
return;
|
|
1630
|
-
}
|
|
1631
|
-
const result = await client.readUserContexts({ query });
|
|
1632
|
-
if (options.json) {
|
|
1633
|
-
console.log(JSON.stringify(result));
|
|
1634
|
-
return;
|
|
1635
|
-
}
|
|
1636
|
-
if (!result.success) {
|
|
1637
|
-
error(result.error ?? "Search failed", 1);
|
|
1638
|
-
return;
|
|
1639
|
-
}
|
|
1640
|
-
const data = result.data;
|
|
1641
|
-
heading("Search Results");
|
|
1642
|
-
if (!data.profiles?.length) {
|
|
1643
|
-
dim(" No profiles found.");
|
|
1644
|
-
} else {
|
|
1645
|
-
for (const p of data.profiles) {
|
|
1646
|
-
console.log(` ${p.name} (${p.userId.slice(0, 8)})`);
|
|
1647
|
-
if (p.bio)
|
|
1648
|
-
dim(` ${p.bio.slice(0, 100)}`);
|
|
1649
|
-
}
|
|
1650
|
-
}
|
|
1651
|
-
console.log();
|
|
1652
|
-
return;
|
|
1653
|
-
}
|
|
1654
1427
|
await profileMe(client, options?.json);
|
|
1655
1428
|
}
|
|
1656
1429
|
async function profileMe(client, json) {
|
|
@@ -1685,61 +1458,26 @@ async function profileSync(client, json) {
|
|
|
1685
1458
|
return;
|
|
1686
1459
|
}
|
|
1687
1460
|
success("Profile enriched.");
|
|
1688
|
-
if (result.profile
|
|
1461
|
+
if (result.profile?.name)
|
|
1689
1462
|
dim(` Name: ${result.profile.name}`);
|
|
1690
|
-
if (result.profile
|
|
1463
|
+
if (result.profile?.location)
|
|
1691
1464
|
dim(` Location: ${result.profile.location}`);
|
|
1692
|
-
dim(` Social links: ${result.profile
|
|
1693
|
-
}
|
|
1694
|
-
async function profileCreate(client, options, json) {
|
|
1695
|
-
if (!json)
|
|
1696
|
-
info("Creating profile...");
|
|
1697
|
-
const query = { confirm: true };
|
|
1698
|
-
if (options.linkedin)
|
|
1699
|
-
query.linkedinUrl = options.linkedin;
|
|
1700
|
-
if (options.github)
|
|
1701
|
-
query.githubUrl = options.github;
|
|
1702
|
-
if (options.twitter)
|
|
1703
|
-
query.twitterUrl = options.twitter;
|
|
1704
|
-
const result = await client.createUserContext(query);
|
|
1705
|
-
if (json) {
|
|
1706
|
-
console.log(JSON.stringify(result));
|
|
1707
|
-
return;
|
|
1708
|
-
}
|
|
1709
|
-
if (!result.success) {
|
|
1710
|
-
error(result.error ?? "Profile creation failed", 1);
|
|
1711
|
-
return;
|
|
1712
|
-
}
|
|
1713
|
-
success("Profile created.");
|
|
1714
|
-
}
|
|
1715
|
-
async function profileUpdate(client, action, details, json) {
|
|
1716
|
-
if (!json)
|
|
1717
|
-
info("Updating profile...");
|
|
1718
|
-
const query = { action };
|
|
1719
|
-
if (details)
|
|
1720
|
-
query.details = details;
|
|
1721
|
-
const result = await client.updateUserContext(query);
|
|
1722
|
-
if (json) {
|
|
1723
|
-
console.log(JSON.stringify(result));
|
|
1724
|
-
return;
|
|
1725
|
-
}
|
|
1726
|
-
if (!result.success) {
|
|
1727
|
-
error(result.error ?? "Profile update failed", 1);
|
|
1728
|
-
return;
|
|
1729
|
-
}
|
|
1730
|
-
success("Profile updated.");
|
|
1465
|
+
dim(` Social links: ${result.profile?.socials?.length ?? 0}`);
|
|
1731
1466
|
}
|
|
1732
1467
|
|
|
1733
1468
|
// src/intent.command.ts
|
|
1734
1469
|
var INTENT_HELP = `
|
|
1735
1470
|
Usage:
|
|
1736
|
-
index intent list [--archived] [--limit <n>] List your signals
|
|
1471
|
+
index intent list [--archived] [--limit <n>] [--query <text>] List your signals
|
|
1737
1472
|
index intent show <id> Show signal details (accepts short ID)
|
|
1738
|
-
index intent
|
|
1473
|
+
index intent prepare <content> [--answer 'prompt=reply'] Review and repair a draft
|
|
1474
|
+
index intent create <content> [--receipt <token>] Create an admitted signal
|
|
1475
|
+
index intent pause <id> | resume <id> Hold or restart its agent
|
|
1739
1476
|
index intent update <id> <content> Update a signal's description
|
|
1740
1477
|
index intent archive <id> Archive a signal (accepts short ID)
|
|
1741
|
-
index intent
|
|
1742
|
-
index intent
|
|
1478
|
+
index intent networks <id> List the networks a signal is shared in
|
|
1479
|
+
index intent add-to-network <id> <network-id> Add a signal to a network
|
|
1480
|
+
index intent remove-from-network <id> <network-id> Remove a signal from a network
|
|
1743
1481
|
`;
|
|
1744
1482
|
async function handleIntent(client, subcommand, options) {
|
|
1745
1483
|
if (!subcommand) {
|
|
@@ -1754,7 +1492,8 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1754
1492
|
case "list": {
|
|
1755
1493
|
const result = await client.listIntents({
|
|
1756
1494
|
archived: options.archived,
|
|
1757
|
-
limit: options.limit
|
|
1495
|
+
limit: options.limit,
|
|
1496
|
+
query: options.query
|
|
1758
1497
|
});
|
|
1759
1498
|
if (options.json) {
|
|
1760
1499
|
console.log(JSON.stringify(result));
|
|
@@ -1782,6 +1521,13 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1782
1521
|
intentCard(intent);
|
|
1783
1522
|
return;
|
|
1784
1523
|
}
|
|
1524
|
+
case "prepare": {
|
|
1525
|
+
if (!options.intentContent)
|
|
1526
|
+
throw new Error("Usage: index intent prepare <content> [--answer 'prompt=reply']");
|
|
1527
|
+
const prepared = await client.prepareIntent(options.intentContent, (options.answers ?? []).map(({ key, value }) => ({ prompt: key, answer: value })));
|
|
1528
|
+
console.log(JSON.stringify(prepared, null, options.json ? undefined : 2));
|
|
1529
|
+
return;
|
|
1530
|
+
}
|
|
1785
1531
|
case "create": {
|
|
1786
1532
|
if (!options.intentContent) {
|
|
1787
1533
|
error("Missing content. Usage: index intent create <content>", 1);
|
|
@@ -1789,27 +1535,13 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1789
1535
|
}
|
|
1790
1536
|
if (!options.json)
|
|
1791
1537
|
info("Processing signal...");
|
|
1792
|
-
const result = await client.
|
|
1793
|
-
description: options.intentContent
|
|
1794
|
-
});
|
|
1538
|
+
const result = await client.createIntent(options.intentContent, options.targetId ? [options.targetId] : undefined, options.receipt);
|
|
1795
1539
|
if (options.json) {
|
|
1796
1540
|
console.log(JSON.stringify(result));
|
|
1797
1541
|
return;
|
|
1798
1542
|
}
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
return;
|
|
1802
|
-
}
|
|
1803
|
-
const proposals = parseIntentProposals(result.data?.message);
|
|
1804
|
-
if (proposals.length === 0) {
|
|
1805
|
-
error("Signal proposal could not be parsed from the response.", 1);
|
|
1806
|
-
return;
|
|
1807
|
-
}
|
|
1808
|
-
for (const proposal of proposals) {
|
|
1809
|
-
await client.confirmIntent(proposal.proposalId, proposal.description);
|
|
1810
|
-
success("Signal created.");
|
|
1811
|
-
dim(` ${proposal.description}`);
|
|
1812
|
-
}
|
|
1543
|
+
success("Signal created.");
|
|
1544
|
+
dim(` shared in ${result.networkIds.length} network${result.networkIds.length === 1 ? "" : "s"}`);
|
|
1813
1545
|
return;
|
|
1814
1546
|
}
|
|
1815
1547
|
case "update": {
|
|
@@ -1828,102 +1560,90 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1828
1560
|
console.log(JSON.stringify(result));
|
|
1829
1561
|
return;
|
|
1830
1562
|
}
|
|
1831
|
-
if (!result.success) {
|
|
1832
|
-
error(result.error ?? "Failed to update signal", 1);
|
|
1833
|
-
return;
|
|
1834
|
-
}
|
|
1835
1563
|
success("Signal updated.");
|
|
1836
1564
|
return;
|
|
1837
1565
|
}
|
|
1566
|
+
case "pause":
|
|
1567
|
+
case "resume": {
|
|
1568
|
+
if (!options.intentId)
|
|
1569
|
+
throw new Error(`Usage: index intent ${subcommand} <id>`);
|
|
1570
|
+
const status = subcommand === "pause" ? "PAUSED" : "ACTIVE";
|
|
1571
|
+
await client.updateIntentStatus(options.intentId, status);
|
|
1572
|
+
if (options.json)
|
|
1573
|
+
console.log(JSON.stringify({ intentId: options.intentId, status }));
|
|
1574
|
+
else
|
|
1575
|
+
success(`Signal ${status.toLowerCase()}.`);
|
|
1576
|
+
return;
|
|
1577
|
+
}
|
|
1838
1578
|
case "archive": {
|
|
1839
1579
|
if (!options.intentId) {
|
|
1840
1580
|
error("Missing signal ID. Usage: index intent archive <id>", 1);
|
|
1841
1581
|
return;
|
|
1842
1582
|
}
|
|
1843
|
-
|
|
1844
|
-
const result = await client.callTool("delete_intent", { intentId: intent.id });
|
|
1583
|
+
await client.archiveIntent(options.intentId);
|
|
1845
1584
|
if (options.json) {
|
|
1846
|
-
console.log(JSON.stringify(
|
|
1847
|
-
return;
|
|
1848
|
-
}
|
|
1849
|
-
if (!result.success) {
|
|
1850
|
-
error(result.error ?? "Failed to archive signal", 1);
|
|
1585
|
+
console.log(JSON.stringify({ success: true }));
|
|
1851
1586
|
return;
|
|
1852
1587
|
}
|
|
1853
1588
|
success(`Signal ${options.intentId} archived.`);
|
|
1854
1589
|
return;
|
|
1855
1590
|
}
|
|
1856
|
-
case "
|
|
1857
|
-
if (!options.intentId
|
|
1858
|
-
error("Usage: index intent
|
|
1591
|
+
case "networks": {
|
|
1592
|
+
if (!options.intentId) {
|
|
1593
|
+
error("Usage: index intent networks <intent-id>", 1);
|
|
1859
1594
|
return;
|
|
1860
1595
|
}
|
|
1861
|
-
const
|
|
1862
|
-
const result = await client.callTool("create_intent_index", {
|
|
1863
|
-
intentId: intent.id,
|
|
1864
|
-
networkId: options.targetId
|
|
1865
|
-
});
|
|
1596
|
+
const networkIds = await client.listIntentNetworks(options.intentId);
|
|
1866
1597
|
if (options.json) {
|
|
1867
|
-
console.log(JSON.stringify(
|
|
1868
|
-
return;
|
|
1869
|
-
}
|
|
1870
|
-
if (!result.success) {
|
|
1871
|
-
error(result.error ?? "Failed to link signal", 1);
|
|
1598
|
+
console.log(JSON.stringify({ networkIds }));
|
|
1872
1599
|
return;
|
|
1873
1600
|
}
|
|
1874
|
-
|
|
1601
|
+
heading("Networks");
|
|
1602
|
+
for (const networkId of networkIds)
|
|
1603
|
+
dim(` ${networkId}`);
|
|
1604
|
+
console.log();
|
|
1875
1605
|
return;
|
|
1876
1606
|
}
|
|
1877
|
-
case "
|
|
1607
|
+
case "add-to-network": {
|
|
1878
1608
|
if (!options.intentId || !options.targetId) {
|
|
1879
|
-
error("Usage: index intent
|
|
1609
|
+
error("Usage: index intent add-to-network <intent-id> <network-id>", 1);
|
|
1880
1610
|
return;
|
|
1881
1611
|
}
|
|
1882
|
-
|
|
1883
|
-
const result = await client.callTool("delete_intent_index", {
|
|
1884
|
-
intentId: intent.id,
|
|
1885
|
-
networkId: options.targetId
|
|
1886
|
-
});
|
|
1612
|
+
await client.addIntentToNetwork(options.intentId, options.targetId);
|
|
1887
1613
|
if (options.json) {
|
|
1888
|
-
console.log(JSON.stringify(
|
|
1614
|
+
console.log(JSON.stringify({ success: true }));
|
|
1615
|
+
return;
|
|
1616
|
+
}
|
|
1617
|
+
success("Signal added to network.");
|
|
1618
|
+
return;
|
|
1619
|
+
}
|
|
1620
|
+
case "remove-from-network": {
|
|
1621
|
+
if (!options.intentId || !options.targetId) {
|
|
1622
|
+
error("Usage: index intent remove-from-network <intent-id> <network-id>", 1);
|
|
1889
1623
|
return;
|
|
1890
1624
|
}
|
|
1891
|
-
|
|
1892
|
-
|
|
1625
|
+
await client.removeIntentFromNetwork(options.intentId, options.targetId);
|
|
1626
|
+
if (options.json) {
|
|
1627
|
+
console.log(JSON.stringify({ success: true }));
|
|
1893
1628
|
return;
|
|
1894
1629
|
}
|
|
1895
|
-
success("Signal
|
|
1630
|
+
success("Signal removed from network.");
|
|
1896
1631
|
return;
|
|
1897
1632
|
}
|
|
1898
1633
|
}
|
|
1899
1634
|
}
|
|
1900
|
-
function parseIntentProposals(message) {
|
|
1901
|
-
if (!message)
|
|
1902
|
-
return [];
|
|
1903
|
-
const proposals = [];
|
|
1904
|
-
const blockRegex = /```intent_proposal\s*\n([\s\S]*?)\n```/g;
|
|
1905
|
-
let match;
|
|
1906
|
-
while ((match = blockRegex.exec(message)) !== null) {
|
|
1907
|
-
try {
|
|
1908
|
-
const parsed = JSON.parse(match[1]);
|
|
1909
|
-
if (parsed.proposalId && parsed.description) {
|
|
1910
|
-
proposals.push({ proposalId: parsed.proposalId, description: parsed.description });
|
|
1911
|
-
}
|
|
1912
|
-
} catch {}
|
|
1913
|
-
}
|
|
1914
|
-
return proposals;
|
|
1915
|
-
}
|
|
1916
1635
|
|
|
1917
1636
|
// src/opportunity.command.ts
|
|
1918
1637
|
var OPPORTUNITY_HELP = `
|
|
1919
1638
|
Usage:
|
|
1920
1639
|
index opportunity list List your opportunities
|
|
1921
|
-
index opportunity list --
|
|
1640
|
+
index opportunity list --intent-id <id> --statuses negotiating,pending,accepted,expired
|
|
1641
|
+
index opportunity list --status <s> Filter by one settled or actionable status
|
|
1922
1642
|
index opportunity list --limit <n> Limit results
|
|
1923
1643
|
index opportunity show <id> Show full opportunity details (accepts short ID)
|
|
1924
1644
|
index opportunity accept <id> Accept an opportunity (accepts short ID)
|
|
1925
|
-
index opportunity accept <id> --acknowledge-uptake <id,id> Continue after an uptake advisory
|
|
1926
1645
|
index opportunity reject <id> Reject an opportunity (accepts short ID)
|
|
1646
|
+
index opportunity start-chat <id> Open the chat through this opportunity
|
|
1927
1647
|
`;
|
|
1928
1648
|
async function handleOpportunity(client, subcommand, options) {
|
|
1929
1649
|
if (!subcommand) {
|
|
@@ -1936,7 +1656,7 @@ async function handleOpportunity(client, subcommand, options) {
|
|
|
1936
1656
|
}
|
|
1937
1657
|
switch (subcommand) {
|
|
1938
1658
|
case "list":
|
|
1939
|
-
await opportunityList(client, options.status, options.limit, options.json);
|
|
1659
|
+
await opportunityList(client, options.status, options.statuses, options.intentId, options.limit, options.json);
|
|
1940
1660
|
return;
|
|
1941
1661
|
case "show":
|
|
1942
1662
|
if (!options.targetId) {
|
|
@@ -1950,7 +1670,7 @@ async function handleOpportunity(client, subcommand, options) {
|
|
|
1950
1670
|
error("Missing opportunity ID. Usage: index opportunity accept <id>", 1);
|
|
1951
1671
|
return;
|
|
1952
1672
|
}
|
|
1953
|
-
await opportunityStatusUpdate(client, options.targetId, "accepted", options.json
|
|
1673
|
+
await opportunityStatusUpdate(client, options.targetId, "accepted", options.json);
|
|
1954
1674
|
return;
|
|
1955
1675
|
case "reject":
|
|
1956
1676
|
if (!options.targetId) {
|
|
@@ -1959,13 +1679,23 @@ async function handleOpportunity(client, subcommand, options) {
|
|
|
1959
1679
|
}
|
|
1960
1680
|
await opportunityStatusUpdate(client, options.targetId, "rejected", options.json);
|
|
1961
1681
|
return;
|
|
1682
|
+
case "start-chat": {
|
|
1683
|
+
if (!options.targetId)
|
|
1684
|
+
throw new Error("Usage: index opportunity start-chat <id>");
|
|
1685
|
+
const result = await client.startOpportunityChat(options.targetId);
|
|
1686
|
+
if (options.json)
|
|
1687
|
+
console.log(JSON.stringify(result));
|
|
1688
|
+
else
|
|
1689
|
+
success(`Chat opened: ${result.conversationId}`);
|
|
1690
|
+
return;
|
|
1691
|
+
}
|
|
1962
1692
|
default:
|
|
1963
1693
|
error(`Unknown subcommand: ${subcommand}`, 1);
|
|
1964
1694
|
return;
|
|
1965
1695
|
}
|
|
1966
1696
|
}
|
|
1967
|
-
async function opportunityList(client,
|
|
1968
|
-
const opportunities = await client.listOpportunities({ status
|
|
1697
|
+
async function opportunityList(client, status, statuses, intentId, limit, json) {
|
|
1698
|
+
const opportunities = await client.listOpportunities({ status, statuses, intentId, limit });
|
|
1969
1699
|
if (json) {
|
|
1970
1700
|
console.log(JSON.stringify(opportunities));
|
|
1971
1701
|
return;
|
|
@@ -1982,225 +1712,55 @@ async function opportunityShow(client, id, json) {
|
|
|
1982
1712
|
}
|
|
1983
1713
|
opportunityCard(opportunity);
|
|
1984
1714
|
}
|
|
1985
|
-
async function opportunityStatusUpdate(client, id,
|
|
1715
|
+
async function opportunityStatusUpdate(client, id, status, json) {
|
|
1986
1716
|
const opportunity = await client.getOpportunity(id);
|
|
1987
|
-
|
|
1988
|
-
try {
|
|
1989
|
-
const result2 = await client.updateOpportunityStatus(opportunity.id, "accepted", acknowledgedUptakeQuestionIds);
|
|
1990
|
-
if (json) {
|
|
1991
|
-
console.log(JSON.stringify(result2));
|
|
1992
|
-
return;
|
|
1993
|
-
}
|
|
1994
|
-
success("Opportunity accepted.");
|
|
1995
|
-
} catch (error2) {
|
|
1996
|
-
const advisory = uptakeAdvisoryFromError(error2);
|
|
1997
|
-
if (json && error2 instanceof ApiError) {
|
|
1998
|
-
console.log(JSON.stringify(error2.response ?? { error: error2.message }));
|
|
1999
|
-
return;
|
|
2000
|
-
}
|
|
2001
|
-
if (!advisory)
|
|
2002
|
-
throw error2;
|
|
2003
|
-
heading("Questions before accepting");
|
|
2004
|
-
for (const question of advisory.advisory.questions) {
|
|
2005
|
-
console.log(`
|
|
2006
|
-
${question.title}`);
|
|
2007
|
-
console.log(question.prompt);
|
|
2008
|
-
for (const option of question.options) {
|
|
2009
|
-
console.log(` - ${option.label}${option.description ? ` — ${option.description}` : ""}`);
|
|
2010
|
-
}
|
|
2011
|
-
dim(` Question ID: ${question.id}`);
|
|
2012
|
-
}
|
|
2013
|
-
const ids = advisory.advisory.questions.map((question) => question.id).join(",");
|
|
2014
|
-
info(`Answer or dismiss these questions, then retry. To continue anyway, run:
|
|
2015
|
-
index opportunity accept ${opportunity.id} --acknowledge-uptake ${ids}`);
|
|
2016
|
-
}
|
|
2017
|
-
return;
|
|
2018
|
-
}
|
|
2019
|
-
const result = await client.updateOpportunityStatus(opportunity.id, "rejected");
|
|
1717
|
+
const result = await client.updateOpportunityStatus(opportunity.id, status);
|
|
2020
1718
|
if (json) {
|
|
2021
1719
|
console.log(JSON.stringify(result));
|
|
2022
1720
|
return;
|
|
2023
1721
|
}
|
|
2024
|
-
success(
|
|
2025
|
-
}
|
|
2026
|
-
function uptakeAdvisoryFromError(error2) {
|
|
2027
|
-
if (!(error2 instanceof ApiError) || error2.status !== 409)
|
|
2028
|
-
return null;
|
|
2029
|
-
const body = error2.response;
|
|
2030
|
-
return body?.advisory?.code === "unresolved_uptake_questions" ? body : null;
|
|
1722
|
+
success(`Opportunity ${status}.`);
|
|
2031
1723
|
}
|
|
2032
1724
|
|
|
2033
1725
|
// src/negotiation.command.ts
|
|
2034
|
-
var NEGOTIATION_HELP = `
|
|
2035
|
-
Usage:
|
|
2036
|
-
index negotiation list List your agent's negotiations
|
|
2037
|
-
index negotiation list --limit <n> Limit results
|
|
2038
|
-
index negotiation list --since <date|duration> Filter by time (ISO date or duration like 1h, 2d, 1w)
|
|
2039
|
-
index negotiation show <id> Show negotiation turn-by-turn details
|
|
2040
|
-
`;
|
|
2041
1726
|
async function handleNegotiation(client, subcommand, options) {
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
1727
|
+
let result;
|
|
1728
|
+
if (subcommand === "list") {
|
|
1729
|
+
if (options.state !== undefined && options.state !== "open" && options.state !== "settled")
|
|
1730
|
+
throw new Error("--state must be open or settled");
|
|
1731
|
+
result = await client.listNegotiations({ intentId: options.intentId, state: options.state });
|
|
1732
|
+
} else if (subcommand === "show" || subcommand === "turn") {
|
|
1733
|
+
if (!options.targetId)
|
|
1734
|
+
throw new Error("An opportunity ID is required");
|
|
1735
|
+
if (subcommand === "show") {
|
|
1736
|
+
result = await client.getNegotiation(options.targetId);
|
|
2045
1737
|
} else {
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
await
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
error("Missing negotiation ID. Usage: index negotiation show <id>", 1);
|
|
2057
|
-
return;
|
|
2058
|
-
}
|
|
2059
|
-
await negotiationShow(client, options.targetId, options.json);
|
|
2060
|
-
return;
|
|
2061
|
-
default:
|
|
2062
|
-
error(`Unknown subcommand: ${subcommand}`, 1);
|
|
2063
|
-
return;
|
|
2064
|
-
}
|
|
2065
|
-
}
|
|
2066
|
-
function resolveSince(input) {
|
|
2067
|
-
const match = input.match(/^(\d+)([smhdw])$/);
|
|
2068
|
-
if (match) {
|
|
2069
|
-
const n = parseInt(match[1], 10);
|
|
2070
|
-
const unit = match[2];
|
|
2071
|
-
const ms = { s: 1000, m: 60000, h: 3600000, d: 86400000, w: 604800000 }[unit];
|
|
2072
|
-
return new Date(Date.now() - n * ms).toISOString();
|
|
2073
|
-
}
|
|
2074
|
-
const d = new Date(input);
|
|
2075
|
-
if (isNaN(d.getTime()))
|
|
2076
|
-
throw new Error(`Invalid --since value: "${input}". Use ISO date or duration like 1h, 2d, 1w.`);
|
|
2077
|
-
return d.toISOString();
|
|
2078
|
-
}
|
|
2079
|
-
async function negotiationList(client, limit, since, json) {
|
|
2080
|
-
const sinceIso = since ? resolveSince(since) : undefined;
|
|
2081
|
-
const negotiations = await client.listNegotiations({ limit, since: sinceIso });
|
|
2082
|
-
if (json) {
|
|
2083
|
-
console.log(JSON.stringify(negotiations));
|
|
2084
|
-
return;
|
|
2085
|
-
}
|
|
2086
|
-
heading("Negotiations");
|
|
2087
|
-
negotiationTable(negotiations);
|
|
2088
|
-
console.log();
|
|
2089
|
-
}
|
|
2090
|
-
async function negotiationShow(client, id, json) {
|
|
2091
|
-
const negotiations = await client.listNegotiations({ limit: 50 });
|
|
2092
|
-
const match = negotiations.find((n) => n.id === id || n.id.startsWith(id));
|
|
2093
|
-
if (!match) {
|
|
2094
|
-
error(`Negotiation not found: ${id}`, 1);
|
|
2095
|
-
return;
|
|
2096
|
-
}
|
|
2097
|
-
if (json) {
|
|
2098
|
-
console.log(JSON.stringify(match));
|
|
2099
|
-
return;
|
|
2100
|
-
}
|
|
2101
|
-
negotiationCard(match);
|
|
2102
|
-
}
|
|
2103
|
-
var { BOLD: BOLD2, RESET: RESET2, CYAN: CYAN2, GRAY: GRAY2, GREEN: GREEN2, YELLOW: YELLOW2, BLUE: BLUE2, DIM: DIM2 } = exports_output;
|
|
2104
|
-
function outcomeLabel(outcome) {
|
|
2105
|
-
if (!outcome)
|
|
2106
|
-
return `${GRAY2}unknown${RESET2}`;
|
|
2107
|
-
return outcome.hasOpportunity ? `${GREEN2}opportunity${RESET2}` : `${GRAY2}no match${RESET2}`;
|
|
2108
|
-
}
|
|
2109
|
-
function roleLabel2(role) {
|
|
2110
|
-
switch (role) {
|
|
2111
|
-
case "agent":
|
|
2112
|
-
return `${GREEN2}helper${RESET2}`;
|
|
2113
|
-
case "patient":
|
|
2114
|
-
return `${YELLOW2}seeker${RESET2}`;
|
|
2115
|
-
case "peer":
|
|
2116
|
-
return `${CYAN2}peer${RESET2}`;
|
|
2117
|
-
default:
|
|
2118
|
-
return `${GRAY2}-${RESET2}`;
|
|
2119
|
-
}
|
|
2120
|
-
}
|
|
2121
|
-
function actionColorFor(action) {
|
|
2122
|
-
switch (action) {
|
|
2123
|
-
case "accept":
|
|
2124
|
-
return GREEN2;
|
|
2125
|
-
case "reject":
|
|
2126
|
-
return RED;
|
|
2127
|
-
default:
|
|
2128
|
-
return BLUE2;
|
|
2129
|
-
}
|
|
2130
|
-
}
|
|
2131
|
-
function negotiationTable(negotiations) {
|
|
2132
|
-
if (negotiations.length === 0) {
|
|
2133
|
-
dim(" No negotiations found.");
|
|
2134
|
-
return;
|
|
2135
|
-
}
|
|
2136
|
-
const idW = 8;
|
|
2137
|
-
const nameW = 22;
|
|
2138
|
-
const outcomeW = 14;
|
|
2139
|
-
const roleW = 8;
|
|
2140
|
-
const turnsW = 6;
|
|
2141
|
-
const dateW = 20;
|
|
2142
|
-
process.stdout.write(` ${BOLD2}${"ID".padEnd(idW)} ${"Counterparty".padEnd(nameW)} ${"Outcome".padEnd(outcomeW)} ${"Role".padEnd(roleW)} ${"Turns".padEnd(turnsW)} ${"Created".padEnd(dateW)}${RESET2}
|
|
2143
|
-
`);
|
|
2144
|
-
process.stdout.write(` ${GRAY2}${"-".repeat(idW)} ${"-".repeat(nameW)} ${"-".repeat(outcomeW)} ${"-".repeat(roleW)} ${"-".repeat(turnsW)} ${"-".repeat(dateW)}${RESET2}
|
|
2145
|
-
`);
|
|
2146
|
-
for (const n of negotiations) {
|
|
2147
|
-
const shortId = n.id.slice(0, 8);
|
|
2148
|
-
const name = (n.counterparty?.name ?? "Unknown").slice(0, nameW);
|
|
2149
|
-
const turns = String(n.outcome?.turnCount ?? n.turns?.length ?? "-");
|
|
2150
|
-
const date = n.createdAt ? new Date(n.createdAt).toLocaleDateString("en-US", {
|
|
2151
|
-
year: "numeric",
|
|
2152
|
-
month: "short",
|
|
2153
|
-
day: "numeric"
|
|
2154
|
-
}) : "-";
|
|
2155
|
-
const outcomeStr = outcomeLabel(n.outcome);
|
|
2156
|
-
const roleStr = roleLabel2(n.outcome?.role);
|
|
2157
|
-
process.stdout.write(` ${CYAN2}${shortId}${RESET2} ${name.padEnd(nameW)} ${outcomeStr}${padTo(outcomeW, stripAnsi(outcomeStr))} ${roleStr}${padTo(roleW, stripAnsi(roleStr))} ${turns.padEnd(turnsW)} ${GRAY2}${date}${RESET2}
|
|
2158
|
-
`);
|
|
2159
|
-
}
|
|
2160
|
-
}
|
|
2161
|
-
function negotiationCard(n) {
|
|
2162
|
-
console.log();
|
|
2163
|
-
console.log(` ${BOLD2}${CYAN2}Negotiation Details${RESET2}`);
|
|
2164
|
-
console.log(` ${GRAY2}${"─".repeat(60)}${RESET2}`);
|
|
2165
|
-
console.log(` ${BOLD2}ID${RESET2} ${GRAY2}${n.id}${RESET2}`);
|
|
2166
|
-
console.log(` ${BOLD2}Counterparty${RESET2} ${n.counterparty?.name ?? "Unknown"}`);
|
|
2167
|
-
console.log(` ${BOLD2}Outcome${RESET2} ${outcomeLabel(n.outcome)}`);
|
|
2168
|
-
console.log(` ${BOLD2}Your Role${RESET2} ${roleLabel2(n.outcome?.role)}`);
|
|
2169
|
-
console.log(` ${BOLD2}Turns${RESET2} ${n.outcome?.turnCount ?? n.turns?.length ?? "-"}`);
|
|
2170
|
-
console.log(` ${BOLD2}Created${RESET2} ${GRAY2}${new Date(n.createdAt).toLocaleString()}${RESET2}`);
|
|
2171
|
-
if (n.turns && n.turns.length > 0) {
|
|
2172
|
-
console.log();
|
|
2173
|
-
console.log(` ${BOLD2}Turn-by-Turn${RESET2}`);
|
|
2174
|
-
console.log(` ${GRAY2}${"─".repeat(60)}${RESET2}`);
|
|
2175
|
-
for (let i = 0;i < n.turns.length; i++) {
|
|
2176
|
-
const t = n.turns[i];
|
|
2177
|
-
const time = new Date(t.createdAt).toLocaleTimeString("en-US", {
|
|
2178
|
-
hour: "2-digit",
|
|
2179
|
-
minute: "2-digit",
|
|
2180
|
-
second: "2-digit"
|
|
1738
|
+
if (!options.action || !["propose", "counter", "accept", "decline"].includes(options.action))
|
|
1739
|
+
throw new Error("--action must be propose, counter, accept, or decline");
|
|
1740
|
+
if (!options.message?.trim())
|
|
1741
|
+
throw new Error("--message is required");
|
|
1742
|
+
if (options.expectedTurnCount === undefined || !Number.isSafeInteger(options.expectedTurnCount) || options.expectedTurnCount < 0)
|
|
1743
|
+
throw new Error("--expected-turn-count must be the observed nonnegative integer turn count");
|
|
1744
|
+
result = await client.submitNegotiationTurn(options.targetId, {
|
|
1745
|
+
action: options.action,
|
|
1746
|
+
message: options.message,
|
|
1747
|
+
expectedTurnCount: options.expectedTurnCount
|
|
2181
1748
|
});
|
|
2182
|
-
const actionColor = actionColorFor(t.action);
|
|
2183
|
-
console.log(` ${DIM2}Turn ${i + 1}${RESET2} ${CYAN2}${t.speaker?.name ?? "?"}${RESET2} ${actionColor}${t.action}${RESET2} ${GRAY2}${time}${RESET2}`);
|
|
2184
|
-
if (t.suggestedRoles) {
|
|
2185
|
-
console.log(` ${DIM2} roles: own=${t.suggestedRoles.ownUser ?? "?"} other=${t.suggestedRoles.otherUser ?? "?"}${RESET2}`);
|
|
2186
|
-
}
|
|
2187
|
-
if (t.reasoning) {
|
|
2188
|
-
const lines = wordWrap(t.reasoning, 72);
|
|
2189
|
-
for (const line of lines) {
|
|
2190
|
-
console.log(` ${DIM2} ${line}${RESET2}`);
|
|
2191
|
-
}
|
|
2192
|
-
}
|
|
2193
|
-
console.log();
|
|
2194
1749
|
}
|
|
1750
|
+
} else {
|
|
1751
|
+
throw new Error("Usage: index negotiation list [--intent-id <id>] [--state open|settled], show <opportunity-id>, or turn <opportunity-id> --action <action> --message <text> --expected-turn-count <n>");
|
|
2195
1752
|
}
|
|
2196
|
-
console.log(
|
|
2197
|
-
console.log();
|
|
1753
|
+
console.log(JSON.stringify(result, null, options.json ? undefined : 2));
|
|
2198
1754
|
}
|
|
2199
1755
|
|
|
2200
1756
|
// src/network.command.ts
|
|
2201
1757
|
var NETWORK_HELP = `
|
|
2202
1758
|
Network Commands:
|
|
2203
1759
|
index network list List your networks
|
|
1760
|
+
index network discover Find public networks to join
|
|
1761
|
+
index network requests See your network creation requests
|
|
1762
|
+
index network request-update <id> --title <name> [--prompt <purpose>]
|
|
1763
|
+
index network request-dismiss <id> Dismiss your request
|
|
2204
1764
|
index network create <name> Create directly or submit an early-access request
|
|
2205
1765
|
index network create <name> --prompt Create directly or request early access with a description
|
|
2206
1766
|
index network show <id|key> Show network details and members
|
|
@@ -2220,6 +1780,47 @@ async function handleNetwork(client, subcommand, positionals, options) {
|
|
|
2220
1780
|
case "list":
|
|
2221
1781
|
await networkList(client, options.json);
|
|
2222
1782
|
return;
|
|
1783
|
+
case "discover": {
|
|
1784
|
+
const result = await client.discoverNetworks();
|
|
1785
|
+
if (options.json)
|
|
1786
|
+
console.log(JSON.stringify(result));
|
|
1787
|
+
else {
|
|
1788
|
+
heading("Public networks");
|
|
1789
|
+
networkTable(result.networks);
|
|
1790
|
+
}
|
|
1791
|
+
return;
|
|
1792
|
+
}
|
|
1793
|
+
case "requests": {
|
|
1794
|
+
const result = await client.listNetworkRequests();
|
|
1795
|
+
if (options.json)
|
|
1796
|
+
console.log(JSON.stringify(result));
|
|
1797
|
+
else {
|
|
1798
|
+
heading("Your network requests");
|
|
1799
|
+
for (const request of result.requests)
|
|
1800
|
+
dim(` ${request.id} · ${request.title} · ${request.status}`);
|
|
1801
|
+
}
|
|
1802
|
+
return;
|
|
1803
|
+
}
|
|
1804
|
+
case "request-update": {
|
|
1805
|
+
if (!positionals[0] || !options.title)
|
|
1806
|
+
throw new Error("Usage: index network request-update <id> --title <name> [--prompt <purpose>]");
|
|
1807
|
+
const result = await client.updateNetworkRequest(positionals[0], options.title, options.prompt);
|
|
1808
|
+
if (options.json)
|
|
1809
|
+
console.log(JSON.stringify(result));
|
|
1810
|
+
else
|
|
1811
|
+
success("Network request resubmitted.");
|
|
1812
|
+
return;
|
|
1813
|
+
}
|
|
1814
|
+
case "request-dismiss": {
|
|
1815
|
+
if (!positionals[0])
|
|
1816
|
+
throw new Error("Usage: index network request-dismiss <id>");
|
|
1817
|
+
await client.dismissNetworkRequest(positionals[0]);
|
|
1818
|
+
if (options.json)
|
|
1819
|
+
console.log(JSON.stringify({ success: true }));
|
|
1820
|
+
else
|
|
1821
|
+
success("Network request dismissed.");
|
|
1822
|
+
return;
|
|
1823
|
+
}
|
|
2223
1824
|
case "create":
|
|
2224
1825
|
await networkCreate(client, positionals[0], options.prompt, options.json);
|
|
2225
1826
|
return;
|
|
@@ -2247,13 +1848,12 @@ async function handleNetwork(client, subcommand, positionals, options) {
|
|
|
2247
1848
|
}
|
|
2248
1849
|
async function networkList(client, json) {
|
|
2249
1850
|
const networks = await client.listNetworks();
|
|
2250
|
-
const filtered = networks.filter((n) => !n.isPersonal);
|
|
2251
1851
|
if (json) {
|
|
2252
|
-
console.log(JSON.stringify(
|
|
1852
|
+
console.log(JSON.stringify(networks));
|
|
2253
1853
|
return;
|
|
2254
1854
|
}
|
|
2255
1855
|
heading("Networks");
|
|
2256
|
-
networkTable(
|
|
1856
|
+
networkTable(networks);
|
|
2257
1857
|
console.log();
|
|
2258
1858
|
}
|
|
2259
1859
|
async function networkCreate(client, name, prompt, json) {
|
|
@@ -2334,13 +1934,9 @@ async function networkUpdate(client, id, options, json) {
|
|
|
2334
1934
|
error("Provide at least --title or --prompt. Usage: index network update <id> [--title <t>] [--prompt <p>]", 1);
|
|
2335
1935
|
return;
|
|
2336
1936
|
}
|
|
2337
|
-
const
|
|
1937
|
+
const network = await client.updateNetwork(id, settings);
|
|
2338
1938
|
if (json) {
|
|
2339
|
-
console.log(JSON.stringify(
|
|
2340
|
-
return;
|
|
2341
|
-
}
|
|
2342
|
-
if (!result.success) {
|
|
2343
|
-
error(result.error ?? "Network update failed", 1);
|
|
1939
|
+
console.log(JSON.stringify({ network }));
|
|
2344
1940
|
return;
|
|
2345
1941
|
}
|
|
2346
1942
|
success("Network updated.");
|
|
@@ -2350,13 +1946,9 @@ async function networkDelete(client, id, json) {
|
|
|
2350
1946
|
error("Usage: index network delete <id>", 1);
|
|
2351
1947
|
return;
|
|
2352
1948
|
}
|
|
2353
|
-
|
|
1949
|
+
await client.deleteNetwork(id);
|
|
2354
1950
|
if (json) {
|
|
2355
|
-
console.log(JSON.stringify(
|
|
2356
|
-
return;
|
|
2357
|
-
}
|
|
2358
|
-
if (!result.success) {
|
|
2359
|
-
error(result.error ?? "Network deletion failed", 1);
|
|
1951
|
+
console.log(JSON.stringify({ success: true }));
|
|
2360
1952
|
return;
|
|
2361
1953
|
}
|
|
2362
1954
|
success("Network deleted.");
|
|
@@ -2380,6 +1972,47 @@ async function networkInvite(client, id, email, json) {
|
|
|
2380
1972
|
dim(" Created a pending account for this invitee.");
|
|
2381
1973
|
}
|
|
2382
1974
|
|
|
1975
|
+
// src/sse.parser.ts
|
|
1976
|
+
function parseSSEEvents(chunk) {
|
|
1977
|
+
if (!chunk)
|
|
1978
|
+
return [];
|
|
1979
|
+
const events = [];
|
|
1980
|
+
const rawEvents = chunk.split(`
|
|
1981
|
+
|
|
1982
|
+
`);
|
|
1983
|
+
for (let i = 0;i < rawEvents.length; i++) {
|
|
1984
|
+
const raw = rawEvents[i].trim();
|
|
1985
|
+
if (!raw)
|
|
1986
|
+
continue;
|
|
1987
|
+
if (i === rawEvents.length - 1 && !chunk.endsWith(`
|
|
1988
|
+
|
|
1989
|
+
`)) {
|
|
1990
|
+
continue;
|
|
1991
|
+
}
|
|
1992
|
+
let eventType;
|
|
1993
|
+
const dataLines = [];
|
|
1994
|
+
for (const line of raw.split(`
|
|
1995
|
+
`)) {
|
|
1996
|
+
if (line.startsWith(":")) {
|
|
1997
|
+
continue;
|
|
1998
|
+
}
|
|
1999
|
+
if (line.startsWith("event:")) {
|
|
2000
|
+
eventType = line.slice("event:".length).trim();
|
|
2001
|
+
} else if (line.startsWith("data:")) {
|
|
2002
|
+
dataLines.push(line.slice("data:".length).trim());
|
|
2003
|
+
}
|
|
2004
|
+
}
|
|
2005
|
+
if (dataLines.length > 0) {
|
|
2006
|
+
events.push({
|
|
2007
|
+
event: eventType,
|
|
2008
|
+
data: dataLines.join(`
|
|
2009
|
+
`)
|
|
2010
|
+
});
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
return events;
|
|
2014
|
+
}
|
|
2015
|
+
|
|
2383
2016
|
// src/conversation.command.ts
|
|
2384
2017
|
var CONVERSATION_HELP = `
|
|
2385
2018
|
Conversation Commands:
|
|
@@ -2388,13 +2021,37 @@ Conversation Commands:
|
|
|
2388
2021
|
index conversation show <id> Show messages (accepts short ID)
|
|
2389
2022
|
index conversation show <id> --limit <n> Limit number of messages
|
|
2390
2023
|
index conversation send <id> <message> Send a message (accepts short ID)
|
|
2024
|
+
index conversation show agent --intent-id <id> Read scoped agent state
|
|
2025
|
+
index conversation send agent <text> --intent-id <id> [--question-id <id>]
|
|
2026
|
+
index conversation answer agent --intent-id <id> --answer 'question-id=text' [--answer ...]
|
|
2391
2027
|
index conversation stream Listen for real-time events (SSE)
|
|
2392
2028
|
`;
|
|
2393
2029
|
async function handleConversation(client, subcommand, positionals, options) {
|
|
2394
|
-
if (
|
|
2395
|
-
|
|
2030
|
+
if (positionals[0] === "agent" && (subcommand === "show" || subcommand === "send")) {
|
|
2031
|
+
if (!options?.intentId)
|
|
2032
|
+
throw new Error("Personal-agent conversations require --intent-id <id>");
|
|
2033
|
+
let result;
|
|
2034
|
+
if (subcommand === "show")
|
|
2035
|
+
result = await client.getAgentConversation(options.intentId);
|
|
2036
|
+
else {
|
|
2037
|
+
const text = positionals.slice(1).join(" ");
|
|
2038
|
+
if (!text.trim())
|
|
2039
|
+
throw new Error("A message is required");
|
|
2040
|
+
result = options.questionId ? await client.answerAgentQuestions(options.intentId, [{ questionId: options.questionId, text }]) : await client.sendMessage("agent", text, options.intentId);
|
|
2041
|
+
}
|
|
2042
|
+
console.log(JSON.stringify(result, null, options.json ? undefined : 2));
|
|
2043
|
+
return;
|
|
2044
|
+
}
|
|
2045
|
+
if (subcommand === "answer") {
|
|
2046
|
+
if (positionals[0] !== "agent" || !options?.intentId || !options.answers?.length) {
|
|
2047
|
+
throw new Error("Usage: index conversation answer agent --intent-id <id> --answer 'question-id=text' [--answer ...]");
|
|
2048
|
+
}
|
|
2049
|
+
const result = await client.answerAgentQuestions(options.intentId, options.answers.map(({ key, value }) => ({ questionId: key, text: value })));
|
|
2050
|
+
console.log(JSON.stringify(result, null, options.json ? undefined : 2));
|
|
2396
2051
|
return;
|
|
2397
2052
|
}
|
|
2053
|
+
if (!subcommand)
|
|
2054
|
+
throw new Error(CONVERSATION_HELP.trim());
|
|
2398
2055
|
switch (subcommand) {
|
|
2399
2056
|
case "list":
|
|
2400
2057
|
await conversationList(client, options?.json);
|
|
@@ -2409,10 +2066,10 @@ async function handleConversation(client, subcommand, positionals, options) {
|
|
|
2409
2066
|
await conversationSend(client, positionals[0], positionals.slice(1), options?.json);
|
|
2410
2067
|
return;
|
|
2411
2068
|
case "stream":
|
|
2412
|
-
await conversationStream(client);
|
|
2069
|
+
await conversationStream(client, options?.json);
|
|
2413
2070
|
return;
|
|
2414
2071
|
case "help":
|
|
2415
|
-
console.log(CONVERSATION_HELP);
|
|
2072
|
+
console.log(options?.json ? JSON.stringify({ help: CONVERSATION_HELP.trim() }) : CONVERSATION_HELP);
|
|
2416
2073
|
return;
|
|
2417
2074
|
default:
|
|
2418
2075
|
error(`Unknown conversation subcommand: ${subcommand}`, 1);
|
|
@@ -2470,11 +2127,11 @@ async function conversationSend(client, id, messageParts, json) {
|
|
|
2470
2127
|
}
|
|
2471
2128
|
success(`Message sent (${msg.id})`);
|
|
2472
2129
|
}
|
|
2473
|
-
async function conversationStream(client) {
|
|
2130
|
+
async function conversationStream(client, json) {
|
|
2474
2131
|
info("Connecting to conversation stream...");
|
|
2475
2132
|
dim(`Press Ctrl+C to stop.
|
|
2476
2133
|
`);
|
|
2477
|
-
const response = await client.
|
|
2134
|
+
const response = await client.streamEvents();
|
|
2478
2135
|
if (!response.body) {
|
|
2479
2136
|
error("No response body from stream endpoint.", 1);
|
|
2480
2137
|
return;
|
|
@@ -2488,33 +2145,21 @@ async function conversationStream(client) {
|
|
|
2488
2145
|
if (done)
|
|
2489
2146
|
break;
|
|
2490
2147
|
buffer += decoder.decode(value, { stream: true });
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
`
|
|
2494
|
-
const idx = buffer.indexOf(`
|
|
2148
|
+
buffer = buffer.replace(/\r\n/g, `
|
|
2149
|
+
`);
|
|
2150
|
+
const boundary = buffer.lastIndexOf(`
|
|
2495
2151
|
|
|
2496
2152
|
`);
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
continue;
|
|
2508
|
-
try {
|
|
2509
|
-
const event = JSON.parse(jsonStr);
|
|
2510
|
-
const type = event.type;
|
|
2511
|
-
if (type === "connected") {
|
|
2512
|
-
success("Connected to conversation stream.");
|
|
2513
|
-
} else {
|
|
2514
|
-
dim(`[${type}] ${JSON.stringify(event)}`);
|
|
2515
|
-
}
|
|
2516
|
-
} catch {}
|
|
2517
|
-
}
|
|
2153
|
+
if (boundary < 0)
|
|
2154
|
+
continue;
|
|
2155
|
+
const complete = buffer.slice(0, boundary + 2);
|
|
2156
|
+
buffer = buffer.slice(boundary + 2);
|
|
2157
|
+
for (const event of parseSSEEvents(complete)) {
|
|
2158
|
+
const data = JSON.parse(event.data);
|
|
2159
|
+
if (json)
|
|
2160
|
+
console.log(JSON.stringify({ event: event.event, data }));
|
|
2161
|
+
else
|
|
2162
|
+
dim(JSON.stringify(data));
|
|
2518
2163
|
}
|
|
2519
2164
|
}
|
|
2520
2165
|
} finally {
|
|
@@ -2522,81 +2167,6 @@ async function conversationStream(client) {
|
|
|
2522
2167
|
}
|
|
2523
2168
|
}
|
|
2524
2169
|
|
|
2525
|
-
// src/contact.command.ts
|
|
2526
|
-
var CONTACT_HELP = `
|
|
2527
|
-
Usage:
|
|
2528
|
-
index contact list List your contacts
|
|
2529
|
-
index contact remove <email> Remove a contact
|
|
2530
|
-
`;
|
|
2531
|
-
async function handleContact(client, subcommand, positionals, options) {
|
|
2532
|
-
if (!subcommand) {
|
|
2533
|
-
if (options.json) {
|
|
2534
|
-
console.log(JSON.stringify({ error: "No subcommand provided" }));
|
|
2535
|
-
} else {
|
|
2536
|
-
console.log(CONTACT_HELP);
|
|
2537
|
-
}
|
|
2538
|
-
return;
|
|
2539
|
-
}
|
|
2540
|
-
switch (subcommand) {
|
|
2541
|
-
case "list": {
|
|
2542
|
-
const result = await client.callTool("list_contacts", {});
|
|
2543
|
-
if (options.json) {
|
|
2544
|
-
console.log(JSON.stringify(result));
|
|
2545
|
-
return;
|
|
2546
|
-
}
|
|
2547
|
-
if (!result.success) {
|
|
2548
|
-
error(result.error ?? "Failed to list contacts", 1);
|
|
2549
|
-
return;
|
|
2550
|
-
}
|
|
2551
|
-
const data = result.data;
|
|
2552
|
-
heading("Contacts");
|
|
2553
|
-
contactTable(data.contacts);
|
|
2554
|
-
dim(`
|
|
2555
|
-
${data.count} contact${data.count !== 1 ? "s" : ""}`);
|
|
2556
|
-
console.log();
|
|
2557
|
-
return;
|
|
2558
|
-
}
|
|
2559
|
-
case "remove": {
|
|
2560
|
-
const email = positionals[0];
|
|
2561
|
-
if (!email) {
|
|
2562
|
-
error("Missing email. Usage: index contact remove <email>", 1);
|
|
2563
|
-
return;
|
|
2564
|
-
}
|
|
2565
|
-
const listResult = await client.callTool("list_contacts", {});
|
|
2566
|
-
if (!listResult.success) {
|
|
2567
|
-
error("Failed to resolve contact", 1);
|
|
2568
|
-
return;
|
|
2569
|
-
}
|
|
2570
|
-
const contacts = listResult.data.contacts;
|
|
2571
|
-
const match = contacts.find((c) => c.email.toLowerCase() === email.toLowerCase());
|
|
2572
|
-
if (!match) {
|
|
2573
|
-
error(`No contact found with email: ${email}`, 1);
|
|
2574
|
-
return;
|
|
2575
|
-
}
|
|
2576
|
-
const result = await client.callTool("remove_contact", { contactUserId: match.userId });
|
|
2577
|
-
if (options.json) {
|
|
2578
|
-
console.log(JSON.stringify(result));
|
|
2579
|
-
return;
|
|
2580
|
-
}
|
|
2581
|
-
if (!result.success) {
|
|
2582
|
-
error(result.error ?? "Failed to remove contact", 1);
|
|
2583
|
-
return;
|
|
2584
|
-
}
|
|
2585
|
-
success(`Removed ${email} from contacts.`);
|
|
2586
|
-
return;
|
|
2587
|
-
}
|
|
2588
|
-
default: {
|
|
2589
|
-
if (options.json) {
|
|
2590
|
-
console.log(JSON.stringify({ error: `Unknown subcommand: ${subcommand}` }));
|
|
2591
|
-
} else {
|
|
2592
|
-
error(`Unknown subcommand: ${subcommand}`);
|
|
2593
|
-
console.log(CONTACT_HELP);
|
|
2594
|
-
}
|
|
2595
|
-
return;
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
}
|
|
2599
|
-
|
|
2600
2170
|
// src/scrape.command.ts
|
|
2601
2171
|
async function handleScrape(client, positionals, options) {
|
|
2602
2172
|
const url = positionals[0];
|
|
@@ -2606,20 +2176,15 @@ async function handleScrape(client, positionals, options) {
|
|
|
2606
2176
|
}
|
|
2607
2177
|
if (!options.json)
|
|
2608
2178
|
info(`Scraping ${url}...`);
|
|
2609
|
-
const result = await client.
|
|
2179
|
+
const result = await client.scrapeUrl(url, options.objective);
|
|
2610
2180
|
if (options.json) {
|
|
2611
2181
|
console.log(JSON.stringify(result));
|
|
2612
2182
|
return;
|
|
2613
2183
|
}
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
return;
|
|
2617
|
-
}
|
|
2618
|
-
const data = result.data;
|
|
2619
|
-
heading(`Content from ${data.url}`);
|
|
2620
|
-
console.log(data.content);
|
|
2184
|
+
heading(`Content from ${result.url}`);
|
|
2185
|
+
console.log(result.content);
|
|
2621
2186
|
dim(`
|
|
2622
|
-
${
|
|
2187
|
+
${result.contentLength} characters extracted`);
|
|
2623
2188
|
console.log();
|
|
2624
2189
|
}
|
|
2625
2190
|
|
|
@@ -2630,18 +2195,17 @@ import { join as join2 } from "node:path";
|
|
|
2630
2195
|
async function handleSync(client, options) {
|
|
2631
2196
|
if (!options.json)
|
|
2632
2197
|
info("Syncing context...");
|
|
2633
|
-
const
|
|
2634
|
-
|
|
2635
|
-
client.
|
|
2636
|
-
client.
|
|
2637
|
-
client.
|
|
2198
|
+
const me = await client.getMe();
|
|
2199
|
+
const [profile, networks, intents] = await Promise.all([
|
|
2200
|
+
client.getUser(me.id),
|
|
2201
|
+
client.listNetworks(),
|
|
2202
|
+
client.listIntents({ limit: 100 })
|
|
2638
2203
|
]);
|
|
2639
2204
|
const context = {
|
|
2640
2205
|
syncedAt: new Date().toISOString(),
|
|
2641
|
-
profile
|
|
2642
|
-
networks
|
|
2643
|
-
intents: intents.
|
|
2644
|
-
contacts: contacts.success ? contacts.data : null
|
|
2206
|
+
profile,
|
|
2207
|
+
networks,
|
|
2208
|
+
intents: intents.intents
|
|
2645
2209
|
};
|
|
2646
2210
|
if (options.json) {
|
|
2647
2211
|
console.log(JSON.stringify(context));
|
|
@@ -2653,190 +2217,100 @@ async function handleSync(client, options) {
|
|
|
2653
2217
|
success("Context synced to ~/.index/context.json");
|
|
2654
2218
|
}
|
|
2655
2219
|
|
|
2656
|
-
// src/
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
index onboarding complete Mark onboarding as complete
|
|
2660
|
-
`;
|
|
2661
|
-
async function handleOnboarding(client, subcommand, options) {
|
|
2662
|
-
if (subcommand === "complete") {
|
|
2663
|
-
await onboardingComplete(client, options?.json);
|
|
2664
|
-
return;
|
|
2665
|
-
}
|
|
2666
|
-
console.log(ONBOARDING_HELP);
|
|
2667
|
-
}
|
|
2668
|
-
async function onboardingComplete(client, json) {
|
|
2669
|
-
if (!json) {
|
|
2670
|
-
info("Completing onboarding...");
|
|
2671
|
-
}
|
|
2672
|
-
const result = await client.callTool("complete_onboarding", {});
|
|
2220
|
+
// src/docs.command.ts
|
|
2221
|
+
async function handleDocs(client, topic, json) {
|
|
2222
|
+
const result = await client.readDocs(topic);
|
|
2673
2223
|
if (json) {
|
|
2674
2224
|
console.log(JSON.stringify(result));
|
|
2675
2225
|
return;
|
|
2676
2226
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2227
|
+
console.log(result.content);
|
|
2228
|
+
if (result.topics)
|
|
2229
|
+
dim(`
|
|
2230
|
+
Topics: ${result.topics.join(", ")}`);
|
|
2231
|
+
}
|
|
2232
|
+
|
|
2233
|
+
// src/onboarding.command.ts
|
|
2234
|
+
async function handleOnboarding(client, subcommand, options) {
|
|
2235
|
+
let result;
|
|
2236
|
+
if (subcommand === "confirm-profile")
|
|
2237
|
+
result = await client.confirmProfile();
|
|
2238
|
+
else if (subcommand === "complete")
|
|
2239
|
+
result = await client.completeOnboarding(options?.intentId);
|
|
2240
|
+
else
|
|
2241
|
+
throw new Error("Usage: index onboarding confirm-profile | complete [--intent-id <id>]");
|
|
2242
|
+
console.log(JSON.stringify(result, null, options?.json ? undefined : 2));
|
|
2682
2243
|
}
|
|
2683
2244
|
|
|
2684
2245
|
// src/main.ts
|
|
2685
2246
|
var DEFAULT_API_URL = "https://protocol.index.network";
|
|
2686
|
-
var
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
}
|
|
2695
|
-
|
|
2696
|
-
const
|
|
2697
|
-
|
|
2698
|
-
const innerTop = `${BOX.h} ${title} ${BOX.h.repeat(dashRun)}`;
|
|
2699
|
-
console.log(`${GRAY}${BOX.tl}${innerTop}${BOX.tr}${RESET}`);
|
|
2700
|
-
for (const row of rows) {
|
|
2701
|
-
console.log(`${GRAY}${BOX.v}${RESET}${padVisual(row, innerW)}${GRAY}${BOX.v}${RESET}`);
|
|
2702
|
-
}
|
|
2703
|
-
console.log(`${GRAY}${BOX.bl}${BOX.h.repeat(innerW)}${BOX.br}${RESET}
|
|
2704
|
-
`);
|
|
2247
|
+
var LOGIN_API_URLS = {
|
|
2248
|
+
local: "http://localhost:3001",
|
|
2249
|
+
dev: "https://protocol.dev.index.network",
|
|
2250
|
+
prod: DEFAULT_API_URL
|
|
2251
|
+
};
|
|
2252
|
+
function webOriginForApi(apiUrl) {
|
|
2253
|
+
const url = new URL(apiUrl);
|
|
2254
|
+
if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
|
|
2255
|
+
return `${url.protocol}//${url.hostname}:3000`;
|
|
2256
|
+
}
|
|
2257
|
+
const hostname = url.hostname.startsWith("protocol.") ? url.hostname.slice("protocol.".length) : url.hostname;
|
|
2258
|
+
return `https://${hostname}`;
|
|
2705
2259
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
]
|
|
2725
|
-
|
|
2726
|
-
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2737
|
-
|
|
2738
|
-
|
|
2739
|
-
|
|
2740
|
-
|
|
2741
|
-
|
|
2742
|
-
"profile",
|
|
2743
|
-
"conversation",
|
|
2744
|
-
"network",
|
|
2745
|
-
"contact",
|
|
2746
|
-
"scrape",
|
|
2747
|
-
"sync",
|
|
2748
|
-
"onboarding"
|
|
2749
|
-
];
|
|
2750
|
-
const cmdLW = Math.max(...cmdLefts.map((s) => s.length));
|
|
2751
|
-
const optLefts = [
|
|
2752
|
-
"--api-url <url>",
|
|
2753
|
-
"--app-url <url>",
|
|
2754
|
-
"--archived",
|
|
2755
|
-
"--status <status>",
|
|
2756
|
-
"--limit <n>",
|
|
2757
|
-
"--since <date>",
|
|
2758
|
-
"--json",
|
|
2759
|
-
"--objective <text>",
|
|
2760
|
-
"--linkedin <url>",
|
|
2761
|
-
"--github <url>",
|
|
2762
|
-
"--twitter <url>",
|
|
2763
|
-
"--title <text>",
|
|
2764
|
-
"--details <text>",
|
|
2765
|
-
"--help",
|
|
2766
|
-
"--version"
|
|
2767
|
-
];
|
|
2768
|
-
const optLW = Math.max(...optLefts.map((s) => s.length));
|
|
2769
|
-
console.log();
|
|
2770
|
-
console.log(` ${BOLD}${CYAN}I N D E X${RESET} ${GRAY}cli${RESET}`);
|
|
2771
|
-
console.log(` ${GRAY}v${VERSION}${RESET}
|
|
2772
|
-
`);
|
|
2773
|
-
panel("getting started", [
|
|
2774
|
-
helpRowCmd(gsLW, "index login", "authenticate via browser"),
|
|
2775
|
-
helpRowCmd(gsLW, "index logout", "clear stored session"),
|
|
2776
|
-
helpRowCmd(gsLW, 'index intent create "..."', "describe what you're looking for"),
|
|
2777
|
-
helpRowCmd(gsLW, "index negotiation list", "see agent debates in progress"),
|
|
2778
|
-
helpRowCmd(gsLW, "index opportunity list", "see what was found for you")
|
|
2779
|
-
]);
|
|
2780
|
-
panel("common forms", [
|
|
2781
|
-
helpRowCmd(formsLW, "index conversation list", "list your conversations"),
|
|
2782
|
-
helpRowCmd(formsLW, "index sync --json", "print synced context as JSON"),
|
|
2783
|
-
"",
|
|
2784
|
-
helpRowCmd(formsLW, "index profile create", "use social URL flags"),
|
|
2785
|
-
helpRowCmd(formsLW, "index profile update", "use action text or --details"),
|
|
2786
|
-
helpRowCmd(formsLW, "index intent list", "supports --archived and --limit"),
|
|
2787
|
-
helpRowCmd(formsLW, "index negotiation list", "supports --since and --limit"),
|
|
2788
|
-
helpRowCmd(formsLW, "index opportunity list", "supports --status and --limit")
|
|
2789
|
-
]);
|
|
2790
|
-
panel("commands", [
|
|
2791
|
-
helpRowDim(cmdLW, "pattern", "index <command> [args] [options]"),
|
|
2792
|
-
helpRowDim(cmdLW, "example", 'index intent create "looking for a CTO"'),
|
|
2793
|
-
"",
|
|
2794
|
-
helpRowCmd(cmdLW, "intent", "list · show · create · update · archive"),
|
|
2795
|
-
helpRowCont(cmdLW, "link · unlink · links"),
|
|
2796
|
-
helpRowCmd(cmdLW, "negotiation", "list · show"),
|
|
2797
|
-
"",
|
|
2798
|
-
helpRowCmd(cmdLW, "profile", "show · sync · search · create · update"),
|
|
2799
|
-
helpRowCmd(cmdLW, "conversation", "list · with · show · send · stream"),
|
|
2800
|
-
helpRowCmd(cmdLW, "network", "list · create · show · update · delete"),
|
|
2801
|
-
helpRowCont(cmdLW, "join · leave · invite"),
|
|
2802
|
-
helpRowCmd(cmdLW, "contact", "list · remove"),
|
|
2803
|
-
"",
|
|
2804
|
-
helpRowCmd(cmdLW, "scrape", "extract content from a URL"),
|
|
2805
|
-
helpRowCmd(cmdLW, "sync", "download your context locally"),
|
|
2806
|
-
helpRowCmd(cmdLW, "onboarding", "finish account setup")
|
|
2807
|
-
]);
|
|
2808
|
-
panel("options", [
|
|
2809
|
-
helpRowDim(optLW, "--api-url <url>", "override API server URL"),
|
|
2810
|
-
helpRowDim(optLW, "--app-url <url>", "override app URL for login"),
|
|
2811
|
-
helpRowDim(optLW, "--archived", "include archived signals"),
|
|
2812
|
-
helpRowDim(optLW, "--status <status>", "filter opportunities by status"),
|
|
2813
|
-
helpRowDim(optLW, "--limit <n>", "limit number of results"),
|
|
2814
|
-
helpRowDim(optLW, "--since <date>", "filter by ISO date or duration"),
|
|
2815
|
-
helpRowDim(optLW, "--json", "output raw JSON"),
|
|
2816
|
-
helpRowDim(optLW, "--objective <text>", "objective for scrape command"),
|
|
2817
|
-
helpRowDim(optLW, "--linkedin <url>", "LinkedIn URL for profile create"),
|
|
2818
|
-
helpRowDim(optLW, "--github <url>", "GitHub URL for profile create"),
|
|
2819
|
-
helpRowDim(optLW, "--twitter <url>", "Twitter URL for profile create"),
|
|
2820
|
-
helpRowDim(optLW, "--title <text>", "title for network update"),
|
|
2821
|
-
helpRowDim(optLW, "--details <text>", "details for profile update"),
|
|
2822
|
-
helpRowDim(optLW, "--help", "show help for any command"),
|
|
2823
|
-
helpRowDim(optLW, "--version", "show version")
|
|
2824
|
-
]);
|
|
2260
|
+
var VERSION = package_default.version;
|
|
2261
|
+
function renderHelp(json) {
|
|
2262
|
+
const help = `Usage: index <command> [args] [options]
|
|
2263
|
+
|
|
2264
|
+
login [local|dev|prod] [--app-url <url>] Authenticate through the matching web app
|
|
2265
|
+
logout Revoke and clear the stored session
|
|
2266
|
+
docs [topic] Read the protocol's canonical guidance
|
|
2267
|
+
agent me Read your selected personal agent
|
|
2268
|
+
profile [show <user-id>|sync|update] Read, research, or edit your profile
|
|
2269
|
+
intent list|show|prepare|create|update|pause|resume|archive|networks|add-to-network|remove-from-network
|
|
2270
|
+
network list|discover|requests|request-update|request-dismiss|show|create|update|delete|join|leave|invite
|
|
2271
|
+
opportunity list|show|accept|reject|start-chat
|
|
2272
|
+
negotiation list [--intent-id <id>] [--state open|settled]
|
|
2273
|
+
negotiation show <opportunity-id>
|
|
2274
|
+
negotiation turn <opportunity-id> --action propose|counter|accept|decline
|
|
2275
|
+
--message <text> --expected-turn-count <n>
|
|
2276
|
+
conversation list|with|show|send|answer|stream
|
|
2277
|
+
conversation show agent --intent-id <id>
|
|
2278
|
+
conversation send agent <text> --intent-id <id> [--question-id <id>]
|
|
2279
|
+
onboarding confirm-profile
|
|
2280
|
+
onboarding complete [--intent-id <id>]
|
|
2281
|
+
scrape <url> [--objective <text>]
|
|
2282
|
+
sync Download profile, networks, and intents
|
|
2283
|
+
|
|
2284
|
+
Global options: --api-url <origin>, --json, --help, --version
|
|
2285
|
+
List options: --archived (intents), --status (opportunities), --limit <n>
|
|
2286
|
+
Intent list options: --query <text> (matches description and summary)
|
|
2287
|
+
Network options: --prompt <text> (create), --title <text> (update)
|
|
2288
|
+
|
|
2289
|
+
Auth: INDEX_SESSION_TOKEN or INDEX_API_KEY, otherwise stored browser login.
|
|
2290
|
+
API origin: --api-url, INDEX_API_URL, stored login URL, production default.
|
|
2291
|
+
Login target: local (localhost:3001), dev (protocol.dev.index.network), prod (default).
|
|
2292
|
+
--json emits one result/error; conversation stream emits NDJSON events.`;
|
|
2293
|
+
console.log(json ? JSON.stringify({ version: VERSION, help }) : `Index CLI ${VERSION}
|
|
2294
|
+
|
|
2295
|
+
${help}`);
|
|
2825
2296
|
}
|
|
2826
2297
|
async function requireAuth(apiUrlOverride) {
|
|
2827
2298
|
const store = new CredentialStore;
|
|
2828
2299
|
const creds = await store.load();
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
const
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2300
|
+
const session = process.env.INDEX_SESSION_TOKEN || undefined;
|
|
2301
|
+
const apiKey = process.env.INDEX_API_KEY || undefined;
|
|
2302
|
+
if (session && apiKey)
|
|
2303
|
+
throw new Error("Set only one of INDEX_SESSION_TOKEN and INDEX_API_KEY");
|
|
2304
|
+
const token = session ?? apiKey ?? creds?.token;
|
|
2305
|
+
if (!token)
|
|
2306
|
+
throw new Error("Not logged in. Run `index login` or set INDEX_SESSION_TOKEN or INDEX_API_KEY.");
|
|
2307
|
+
const apiUrl = apiUrlOverride ?? process.env.INDEX_API_URL ?? creds?.apiUrl ?? DEFAULT_API_URL;
|
|
2308
|
+
return new ApiClient(apiUrl, token, apiKey ? "apiKey" : "session");
|
|
2309
|
+
}
|
|
2310
|
+
async function runLogin(target, apiUrlOverride, appUrlOverride, json) {
|
|
2837
2311
|
const store = new CredentialStore;
|
|
2838
|
-
const apiUrl = apiUrlOverride ?? DEFAULT_API_URL;
|
|
2839
|
-
const appUrl = appUrlOverride ??
|
|
2312
|
+
const apiUrl = apiUrlOverride ?? (target ? LOGIN_API_URLS[target] : undefined) ?? process.env.INDEX_API_URL ?? (await store.load())?.apiUrl ?? DEFAULT_API_URL;
|
|
2313
|
+
const appUrl = appUrlOverride ?? webOriginForApi(apiUrl);
|
|
2840
2314
|
info(`Authenticating with ${apiUrl}...`);
|
|
2841
2315
|
const { authUrl, callbackPromise } = await handleLogin(apiUrl, appUrl, store);
|
|
2842
2316
|
info("Opening browser for authentication...");
|
|
@@ -2863,6 +2337,12 @@ async function runLogin(apiUrlOverride, appUrlOverride) {
|
|
|
2863
2337
|
} catch {}
|
|
2864
2338
|
dim("Waiting for authentication callback...");
|
|
2865
2339
|
const result = await callbackPromise;
|
|
2340
|
+
if (json) {
|
|
2341
|
+
if (!result.success)
|
|
2342
|
+
throw new Error(result.error ?? "Login failed.");
|
|
2343
|
+
console.log(JSON.stringify(result));
|
|
2344
|
+
return;
|
|
2345
|
+
}
|
|
2866
2346
|
if (result.success) {
|
|
2867
2347
|
try {
|
|
2868
2348
|
const creds = await store.load();
|
|
@@ -2880,8 +2360,14 @@ async function runLogin(apiUrlOverride, appUrlOverride) {
|
|
|
2880
2360
|
error(result.error ?? "Login failed.", 1);
|
|
2881
2361
|
}
|
|
2882
2362
|
}
|
|
2883
|
-
async function runLogout() {
|
|
2363
|
+
async function runLogout(json) {
|
|
2884
2364
|
const result = await handleLogout(new CredentialStore);
|
|
2365
|
+
if (json) {
|
|
2366
|
+
console.log(JSON.stringify(result));
|
|
2367
|
+
if (!result.success)
|
|
2368
|
+
process.exitCode = 1;
|
|
2369
|
+
return;
|
|
2370
|
+
}
|
|
2885
2371
|
if (result.success) {
|
|
2886
2372
|
success(result.message);
|
|
2887
2373
|
return;
|
|
@@ -2893,30 +2379,38 @@ async function main() {
|
|
|
2893
2379
|
const args = parseArgs(process.argv.slice(2));
|
|
2894
2380
|
switch (args.command) {
|
|
2895
2381
|
case "help":
|
|
2896
|
-
renderHelp();
|
|
2382
|
+
renderHelp(args.json);
|
|
2897
2383
|
return;
|
|
2898
2384
|
case "version":
|
|
2899
|
-
console.log(VERSION);
|
|
2385
|
+
console.log(args.json ? JSON.stringify({ version: VERSION }) : VERSION);
|
|
2900
2386
|
return;
|
|
2901
2387
|
case "unknown":
|
|
2902
2388
|
error(`Unknown command: ${args.unknown}`, 1);
|
|
2903
2389
|
return;
|
|
2904
2390
|
case "login":
|
|
2905
|
-
await runLogin(args.apiUrl, args.appUrl);
|
|
2391
|
+
await runLogin(args.loginTarget, args.apiUrl, args.appUrl, args.json);
|
|
2906
2392
|
return;
|
|
2907
2393
|
case "logout":
|
|
2908
|
-
await runLogout();
|
|
2394
|
+
await runLogout(args.json);
|
|
2909
2395
|
return;
|
|
2910
2396
|
}
|
|
2911
2397
|
const client = await requireAuth(args.apiUrl);
|
|
2912
2398
|
switch (args.command) {
|
|
2399
|
+
case "docs":
|
|
2400
|
+
await handleDocs(client, args.positionals?.[0], args.json);
|
|
2401
|
+
return;
|
|
2402
|
+
case "agent":
|
|
2403
|
+
if (args.subcommand !== "me")
|
|
2404
|
+
throw new Error("Usage: index agent me");
|
|
2405
|
+
console.log(JSON.stringify(await client.getAgent(), null, args.json ? undefined : 2));
|
|
2406
|
+
return;
|
|
2913
2407
|
case "profile":
|
|
2914
2408
|
await handleProfile(client, args.subcommand, args.subcommand === "search" || args.subcommand === "update" ? args.positionals ?? [] : args.userId ? [args.userId] : [], {
|
|
2915
2409
|
json: args.json,
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2410
|
+
name: args.name,
|
|
2411
|
+
intro: args.intro,
|
|
2412
|
+
location: args.location,
|
|
2413
|
+
socials: args.socials
|
|
2920
2414
|
});
|
|
2921
2415
|
return;
|
|
2922
2416
|
case "intent":
|
|
@@ -2926,24 +2420,31 @@ async function main() {
|
|
|
2926
2420
|
archived: args.archived,
|
|
2927
2421
|
limit: args.limit,
|
|
2928
2422
|
json: args.json,
|
|
2929
|
-
targetId: args.targetId
|
|
2423
|
+
targetId: args.targetId,
|
|
2424
|
+
query: args.query,
|
|
2425
|
+
receipt: args.receipt,
|
|
2426
|
+
answers: args.answers
|
|
2930
2427
|
});
|
|
2931
2428
|
return;
|
|
2932
2429
|
case "opportunity":
|
|
2933
2430
|
await handleOpportunity(client, args.subcommand, {
|
|
2934
2431
|
targetId: args.targetId,
|
|
2935
2432
|
status: args.status,
|
|
2433
|
+
statuses: args.statuses,
|
|
2434
|
+
intentId: args.intentId,
|
|
2936
2435
|
limit: args.limit,
|
|
2937
2436
|
json: args.json,
|
|
2938
|
-
positionals: args.positionals
|
|
2939
|
-
acknowledgeUptake: args.acknowledgeUptake
|
|
2437
|
+
positionals: args.positionals
|
|
2940
2438
|
});
|
|
2941
2439
|
return;
|
|
2942
2440
|
case "negotiation":
|
|
2943
2441
|
await handleNegotiation(client, args.subcommand, {
|
|
2944
2442
|
targetId: args.targetId,
|
|
2945
|
-
|
|
2946
|
-
|
|
2443
|
+
intentId: args.intentId,
|
|
2444
|
+
state: args.state,
|
|
2445
|
+
action: args.action,
|
|
2446
|
+
message: args.message,
|
|
2447
|
+
expectedTurnCount: args.expectedTurnCount,
|
|
2947
2448
|
json: args.json
|
|
2948
2449
|
});
|
|
2949
2450
|
return;
|
|
@@ -2957,12 +2458,10 @@ async function main() {
|
|
|
2957
2458
|
case "conversation":
|
|
2958
2459
|
await handleConversation(client, args.subcommand, args.positionals ?? [], {
|
|
2959
2460
|
limit: args.limit,
|
|
2960
|
-
json: args.json
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
await handleContact(client, args.subcommand, args.positionals ?? [], {
|
|
2965
|
-
json: args.json
|
|
2461
|
+
json: args.json,
|
|
2462
|
+
intentId: args.intentId,
|
|
2463
|
+
questionId: args.questionId,
|
|
2464
|
+
answers: args.answers
|
|
2966
2465
|
});
|
|
2967
2466
|
return;
|
|
2968
2467
|
case "scrape":
|
|
@@ -2972,7 +2471,7 @@ async function main() {
|
|
|
2972
2471
|
});
|
|
2973
2472
|
return;
|
|
2974
2473
|
case "onboarding":
|
|
2975
|
-
await handleOnboarding(client, args.subcommand, { json: args.json });
|
|
2474
|
+
await handleOnboarding(client, args.subcommand, { json: args.json, intentId: args.intentId });
|
|
2976
2475
|
return;
|
|
2977
2476
|
case "sync":
|
|
2978
2477
|
await handleSync(client, { json: args.json });
|
|
@@ -2980,5 +2479,9 @@ async function main() {
|
|
|
2980
2479
|
}
|
|
2981
2480
|
}
|
|
2982
2481
|
main().catch((err) => {
|
|
2983
|
-
|
|
2482
|
+
if (process.argv.includes("--json")) {
|
|
2483
|
+
console.log(JSON.stringify(err instanceof ApiError ? { error: err.message, status: err.status, response: err.response } : { error: err instanceof Error ? err.message : String(err) }));
|
|
2484
|
+
process.exitCode = 1;
|
|
2485
|
+
} else
|
|
2486
|
+
error(err instanceof Error ? err.message : String(err), 1);
|
|
2984
2487
|
});
|