@indexnetwork/cli 0.17.0-rc.66.1 → 0.29.0-rc.88.2
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 +194 -70
- package/dist/index.js +1001 -1221
- 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.29.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.29.0",
|
|
29
|
+
"@indexnetwork/cli-linux-arm64": "0.29.0",
|
|
30
|
+
"@indexnetwork/cli-darwin-x64": "0.29.0",
|
|
31
|
+
"@indexnetwork/cli-darwin-arm64": "0.29.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;
|
|
631
|
+
}
|
|
632
|
+
async scrapeUrl(url, objective) {
|
|
633
|
+
const res = await this.post("/api/scrape", { url, ...objective ? { objective } : {} });
|
|
634
|
+
return await res.json();
|
|
635
|
+
}
|
|
636
|
+
async readDocs(topic) {
|
|
637
|
+
const path = topic ? `/api/docs?${new URLSearchParams({ topic })}` : "/api/docs";
|
|
638
|
+
return (await this.get(path)).json();
|
|
527
639
|
}
|
|
528
|
-
async
|
|
529
|
-
return this.
|
|
640
|
+
async getAgent() {
|
|
641
|
+
return await (await this.get("/api/agents/me")).json();
|
|
530
642
|
}
|
|
531
|
-
async
|
|
532
|
-
|
|
643
|
+
async getNegotiation(opportunityId) {
|
|
644
|
+
const body = await (await this.get(`/api/opportunities/${encodeURIComponent(opportunityId)}/negotiation`)).json();
|
|
645
|
+
return body.negotiation;
|
|
533
646
|
}
|
|
534
|
-
async
|
|
535
|
-
const
|
|
536
|
-
return
|
|
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 (await this.get(`/api/conversations/agent/messages?${new URLSearchParams({ intentId })}`)).json();
|
|
653
|
+
}
|
|
654
|
+
async confirmProfile() {
|
|
655
|
+
return await (await this.post("/api/auth/onboarding/confirm-profile", {})).json();
|
|
656
|
+
}
|
|
657
|
+
async completeOnboarding(intentId) {
|
|
658
|
+
return await (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,21 +1083,9 @@ 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
|
-
dim(" No
|
|
1088
|
+
dim(" No intents found.");
|
|
1282
1089
|
return;
|
|
1283
1090
|
}
|
|
1284
1091
|
const idWidth = 8;
|
|
@@ -1286,12 +1093,12 @@ function intentTable(intents) {
|
|
|
1286
1093
|
const statusWidth = 10;
|
|
1287
1094
|
const sourceWidth = 16;
|
|
1288
1095
|
const dateWidth = 20;
|
|
1289
|
-
console.log(` ${BOLD}${"ID".padEnd(idWidth)} ${"
|
|
1096
|
+
console.log(` ${BOLD}${"ID".padEnd(idWidth)} ${"Intent".padEnd(descWidth)} ${"Status".padEnd(statusWidth)} ${"Source".padEnd(sourceWidth)} ${"Created".padEnd(dateWidth)}${RESET}`);
|
|
1290
1097
|
console.log(` ${GRAY}${"-".repeat(idWidth)} ${"-".repeat(descWidth)} ${"-".repeat(statusWidth)} ${"-".repeat(sourceWidth)} ${"-".repeat(dateWidth)}${RESET}`);
|
|
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,12 +1106,48 @@ 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
|
}
|
|
1112
|
+
function intentPreparation(prepared) {
|
|
1113
|
+
if (prepared.status === "ready") {
|
|
1114
|
+
success("Intent is ready to create.");
|
|
1115
|
+
console.log();
|
|
1116
|
+
for (const line of wordWrap(prepared.payload, 72))
|
|
1117
|
+
console.log(` ${line}`);
|
|
1118
|
+
console.log();
|
|
1119
|
+
console.log(` ${BOLD}Create it:${RESET}`);
|
|
1120
|
+
console.log(` index intent create ${shellQuote(prepared.payload)} --receipt ${shellQuote(prepared.preparationReceipt)}`);
|
|
1121
|
+
console.log();
|
|
1122
|
+
return;
|
|
1123
|
+
}
|
|
1124
|
+
console.log();
|
|
1125
|
+
console.log(` ${BOLD}${YELLOW}Needs revision${RESET}`);
|
|
1126
|
+
for (const line of wordWrap(prepared.feedback, 72))
|
|
1127
|
+
console.log(` ${line}`);
|
|
1128
|
+
console.log();
|
|
1129
|
+
console.log(` ${BOLD}Answer these:${RESET}`);
|
|
1130
|
+
for (const field of prepared.recovery) {
|
|
1131
|
+
console.log(` ${CYAN}*${RESET} ${field.label}`);
|
|
1132
|
+
for (const option of field.options ?? []) {
|
|
1133
|
+
const description = option.description ? `${GRAY} — ${option.description}${RESET}` : "";
|
|
1134
|
+
console.log(` ${option.label}${description}`);
|
|
1135
|
+
}
|
|
1136
|
+
if (field.placeholder)
|
|
1137
|
+
console.log(` ${GRAY}${field.placeholder}${RESET}`);
|
|
1138
|
+
}
|
|
1139
|
+
console.log();
|
|
1140
|
+
const answerFlags = prepared.recovery.map((field) => `--answer ${shellQuote(`${field.label}=<reply>`)}`);
|
|
1141
|
+
console.log(` ${BOLD}Then run:${RESET}`);
|
|
1142
|
+
console.log(` index intent prepare ${shellQuote(prepared.payload)} ${answerFlags.join(" ")}`);
|
|
1143
|
+
console.log();
|
|
1144
|
+
}
|
|
1145
|
+
function shellQuote(value) {
|
|
1146
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
1147
|
+
}
|
|
1305
1148
|
function intentCard(intent) {
|
|
1306
1149
|
console.log();
|
|
1307
|
-
console.log(` ${BOLD}${CYAN}
|
|
1150
|
+
console.log(` ${BOLD}${CYAN}Intent Details${RESET}`);
|
|
1308
1151
|
console.log(` ${GRAY}${"─".repeat(50)}${RESET}`);
|
|
1309
1152
|
console.log(` ${BOLD}ID${RESET} ${GRAY}${intent.id}${RESET}`);
|
|
1310
1153
|
console.log(` ${BOLD}Status${RESET} ${intent.status === "ACTIVE" ? GREEN : GRAY}${intent.status}${RESET}`);
|
|
@@ -1339,10 +1182,10 @@ function intentCard(intent) {
|
|
|
1339
1182
|
if (intent.archivedAt) {
|
|
1340
1183
|
console.log(` ${BOLD}Archived${RESET} ${GRAY}${new Date(intent.archivedAt).toLocaleString()}${RESET}`);
|
|
1341
1184
|
}
|
|
1342
|
-
if (intent.
|
|
1185
|
+
if (intent.networks && intent.networks.length > 0) {
|
|
1343
1186
|
console.log();
|
|
1344
|
-
console.log(` ${BOLD}
|
|
1345
|
-
for (const idx of intent.
|
|
1187
|
+
console.log(` ${BOLD}Networks${RESET}`);
|
|
1188
|
+
for (const idx of intent.networks) {
|
|
1346
1189
|
const score = idx.relevancyScore !== undefined ? ` (${idx.relevancyScore.toFixed(2)})` : "";
|
|
1347
1190
|
console.log(` ${CYAN}*${RESET} ${idx.title}${GRAY}${score}${RESET}`);
|
|
1348
1191
|
}
|
|
@@ -1368,35 +1211,25 @@ function opportunityTable(opportunities) {
|
|
|
1368
1211
|
}
|
|
1369
1212
|
const idW = 8;
|
|
1370
1213
|
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}
|
|
1214
|
+
const statusW = 12;
|
|
1215
|
+
const headlineW = 48;
|
|
1216
|
+
process.stdout.write(` ${BOLD}${"ID".padEnd(idW)} ${"Counterparty".padEnd(nameW)} ${"Status".padEnd(statusW)} Headline${RESET}
|
|
1376
1217
|
`);
|
|
1377
|
-
process.stdout.write(` ${GRAY}${"-".repeat(idW)} ${"-".repeat(nameW)} ${"-".repeat(
|
|
1218
|
+
process.stdout.write(` ${GRAY}${"-".repeat(idW)} ${"-".repeat(nameW)} ${"-".repeat(statusW)} ${"-".repeat(headlineW)}${RESET}
|
|
1378
1219
|
`);
|
|
1379
1220
|
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);
|
|
1221
|
+
const shortId = opp.opportunityId.slice(0, idW);
|
|
1222
|
+
const name = opp.peer.name.slice(0, nameW);
|
|
1384
1223
|
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}
|
|
1224
|
+
const headline = (opp.headline ?? opp.mainText).slice(0, headlineW);
|
|
1225
|
+
process.stdout.write(` ${CYAN}${shortId}${RESET} ${name.padEnd(nameW)} ${statusColor(st)}${st.padEnd(statusW)}${RESET} ${headline}
|
|
1393
1226
|
`);
|
|
1394
1227
|
}
|
|
1395
1228
|
}
|
|
1396
1229
|
function opportunityCard(opp) {
|
|
1397
1230
|
const width = 58;
|
|
1398
1231
|
const innerWidth = width - 2;
|
|
1399
|
-
const title = opp.
|
|
1232
|
+
const title = opp.headline ?? "Opportunity";
|
|
1400
1233
|
process.stdout.write(`
|
|
1401
1234
|
${BLUE}+${"─".repeat(width)}+${RESET}
|
|
1402
1235
|
`);
|
|
@@ -1407,13 +1240,15 @@ function opportunityCard(opp) {
|
|
|
1407
1240
|
cardLine(`${BOLD}Status:${RESET} ${statusColor(st)}${st}${RESET}`);
|
|
1408
1241
|
if (opp.category)
|
|
1409
1242
|
cardLine(`${BOLD}Category:${RESET} ${opp.category}`);
|
|
1410
|
-
if (opp.
|
|
1411
|
-
cardLine(`${BOLD}Network:${RESET} ${opp.
|
|
1243
|
+
if (opp.network?.title)
|
|
1244
|
+
cardLine(`${BOLD}Network:${RESET} ${opp.network.title}`);
|
|
1412
1245
|
if (opp.confidence != null)
|
|
1413
1246
|
cardLine(`${BOLD}Confidence:${RESET} ${confidenceBar(opp.confidence)}`);
|
|
1414
1247
|
if (opp.myRole)
|
|
1415
1248
|
cardLine(`${BOLD}Your role:${RESET} ${roleLabel(opp.myRole)}`);
|
|
1416
|
-
if (opp.
|
|
1249
|
+
if (opp.peer?.name)
|
|
1250
|
+
cardLine(`${BOLD}With:${RESET} ${opp.peer.name}`);
|
|
1251
|
+
else if (opp.otherParties && opp.otherParties.length > 0) {
|
|
1417
1252
|
process.stdout.write(` ${BLUE}|${RESET}
|
|
1418
1253
|
`);
|
|
1419
1254
|
cardLine(`${BOLD}With:${RESET}`);
|
|
@@ -1421,11 +1256,11 @@ function opportunityCard(opp) {
|
|
|
1421
1256
|
cardLine(` ${p.name ?? p.id} ${roleLabel(p.role)}`);
|
|
1422
1257
|
}
|
|
1423
1258
|
}
|
|
1424
|
-
if (opp.
|
|
1259
|
+
if (opp.mainText) {
|
|
1425
1260
|
process.stdout.write(` ${BLUE}|${RESET}
|
|
1426
1261
|
`);
|
|
1427
1262
|
cardLine(`${BOLD}Details:${RESET}`);
|
|
1428
|
-
for (const line of wordWrap(opp.
|
|
1263
|
+
for (const line of wordWrap(opp.mainText, innerWidth - 4)) {
|
|
1429
1264
|
cardLine(` ${AGENT_TEXT}${line}${RESET}`);
|
|
1430
1265
|
}
|
|
1431
1266
|
}
|
|
@@ -1463,6 +1298,173 @@ function statusColor(st) {
|
|
|
1463
1298
|
return "";
|
|
1464
1299
|
}
|
|
1465
1300
|
}
|
|
1301
|
+
var ACTION_COLORS = {
|
|
1302
|
+
propose: CYAN,
|
|
1303
|
+
counter: BLUE,
|
|
1304
|
+
accept: GREEN,
|
|
1305
|
+
decline: RED
|
|
1306
|
+
};
|
|
1307
|
+
function shortDateTime(iso) {
|
|
1308
|
+
return new Date(iso).toLocaleString("en-US", {
|
|
1309
|
+
month: "short",
|
|
1310
|
+
day: "numeric",
|
|
1311
|
+
hour: "2-digit",
|
|
1312
|
+
minute: "2-digit"
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1315
|
+
function outcomeLabel(outcome) {
|
|
1316
|
+
switch (outcome) {
|
|
1317
|
+
case "agreed":
|
|
1318
|
+
return `${GREEN}agreed${RESET}`;
|
|
1319
|
+
case "declined":
|
|
1320
|
+
return `${RED}declined${RESET}`;
|
|
1321
|
+
case "closed":
|
|
1322
|
+
return `${GRAY}closed${RESET}`;
|
|
1323
|
+
case null:
|
|
1324
|
+
return `${YELLOW}open${RESET}`;
|
|
1325
|
+
}
|
|
1326
|
+
}
|
|
1327
|
+
function whoseTurn(negotiation) {
|
|
1328
|
+
if (negotiation.awaitingUserId === null)
|
|
1329
|
+
return "nobody";
|
|
1330
|
+
return negotiation.awaitingUserId === negotiation.counterparty.userId ? "them" : "you";
|
|
1331
|
+
}
|
|
1332
|
+
function counterpartyName(negotiation) {
|
|
1333
|
+
return negotiation.counterparty.name ?? "(unnamed)";
|
|
1334
|
+
}
|
|
1335
|
+
function negotiationTable(negotiations) {
|
|
1336
|
+
if (negotiations.length === 0) {
|
|
1337
|
+
dim(" No negotiations found.");
|
|
1338
|
+
return;
|
|
1339
|
+
}
|
|
1340
|
+
const idW = 8;
|
|
1341
|
+
const nameW = 22;
|
|
1342
|
+
const turnsW = 5;
|
|
1343
|
+
const turnW = 10;
|
|
1344
|
+
const outcomeW = 8;
|
|
1345
|
+
const dateW = 12;
|
|
1346
|
+
console.log(` ${BOLD}${"ID".padEnd(idW)} ${"Counterparty".padEnd(nameW)} ${"Turns".padEnd(turnsW)} ${"Whose turn".padEnd(turnW)} ${"Outcome".padEnd(outcomeW)} ${"Updated".padEnd(dateW)}${RESET}`);
|
|
1347
|
+
console.log(` ${GRAY}${"-".repeat(idW)} ${"-".repeat(nameW)} ${"-".repeat(turnsW)} ${"-".repeat(turnW)} ${"-".repeat(outcomeW)} ${"-".repeat(dateW)}${RESET}`);
|
|
1348
|
+
for (const negotiation of negotiations) {
|
|
1349
|
+
const shortId = negotiation.opportunityId.slice(0, idW);
|
|
1350
|
+
const name = counterpartyName(negotiation).slice(0, nameW);
|
|
1351
|
+
const turns = String(negotiation.turnCount);
|
|
1352
|
+
const turn = whoseTurn(negotiation);
|
|
1353
|
+
let turnCell = `${GRAY}${"—".padEnd(turnW)}${RESET}`;
|
|
1354
|
+
if (turn === "you")
|
|
1355
|
+
turnCell = `${YELLOW}${BOLD}${"you".padEnd(turnW)}${RESET}`;
|
|
1356
|
+
if (turn === "them")
|
|
1357
|
+
turnCell = `${GRAY}${"them".padEnd(turnW)}${RESET}`;
|
|
1358
|
+
const outcome = outcomeLabel(negotiation.outcome);
|
|
1359
|
+
const date = new Date(negotiation.updatedAt).toLocaleDateString("en-US", {
|
|
1360
|
+
year: "numeric",
|
|
1361
|
+
month: "short",
|
|
1362
|
+
day: "numeric"
|
|
1363
|
+
});
|
|
1364
|
+
console.log(` ${CYAN}${shortId}${RESET} ${name.padEnd(nameW)} ${turns.padEnd(turnsW)} ${turnCell} ${outcome}${padTo(outcomeW, stripAnsi(outcome))} ${GRAY}${date}${RESET}`);
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
function negotiationCard(negotiation) {
|
|
1368
|
+
const name = counterpartyName(negotiation);
|
|
1369
|
+
const rule = ` ${GRAY}${"─".repeat(60)}${RESET}`;
|
|
1370
|
+
let turnLabel = `${GRAY}— settled${RESET}`;
|
|
1371
|
+
if (whoseTurn(negotiation) === "you")
|
|
1372
|
+
turnLabel = `${YELLOW}${BOLD}you${RESET}`;
|
|
1373
|
+
if (whoseTurn(negotiation) === "them")
|
|
1374
|
+
turnLabel = name;
|
|
1375
|
+
console.log();
|
|
1376
|
+
console.log(` ${BOLD}${CYAN}Negotiation with ${name}${RESET}`);
|
|
1377
|
+
console.log(rule);
|
|
1378
|
+
console.log(` ${BOLD}Opportunity${RESET} ${GRAY}${negotiation.opportunityId}${RESET}`);
|
|
1379
|
+
console.log(` ${BOLD}Outcome${RESET} ${outcomeLabel(negotiation.outcome)}`);
|
|
1380
|
+
console.log(` ${BOLD}Turn${RESET} ${negotiation.turnCount} of ${negotiation.protocol.maxTurns}`);
|
|
1381
|
+
console.log(` ${BOLD}Whose turn${RESET} ${turnLabel}`);
|
|
1382
|
+
const [firstLine, ...moreLines] = wordWrap(negotiation.counterparty.statement, 58);
|
|
1383
|
+
console.log(` ${BOLD}Their intent${RESET} ${firstLine}`);
|
|
1384
|
+
for (const line of moreLines)
|
|
1385
|
+
console.log(` ${line}`);
|
|
1386
|
+
console.log();
|
|
1387
|
+
console.log(` ${BOLD}Transcript${RESET}`);
|
|
1388
|
+
if (negotiation.turns.length === 0)
|
|
1389
|
+
console.log(` ${GRAY}No turns yet.${RESET}`);
|
|
1390
|
+
for (const turn of negotiation.turns) {
|
|
1391
|
+
const seat = turn.seatUserId === negotiation.counterparty.userId ? name : "You";
|
|
1392
|
+
console.log(` ${GRAY}${turn.turnIndex + 1}.${RESET} ${BOLD}${seat}${RESET} ${ACTION_COLORS[turn.action]}${turn.action}${RESET} ${GRAY}${shortDateTime(turn.createdAt)}${RESET}`);
|
|
1393
|
+
for (const line of wordWrap(turn.message, 66))
|
|
1394
|
+
console.log(` ${line}`);
|
|
1395
|
+
}
|
|
1396
|
+
const { availableActions, blockedReason, messageLimit } = negotiation.protocol;
|
|
1397
|
+
console.log();
|
|
1398
|
+
if (availableActions.length > 0) {
|
|
1399
|
+
const actions = availableActions.map((action) => `${ACTION_COLORS[action]}${action}${RESET}`).join(", ");
|
|
1400
|
+
console.log(` ${BOLD}Available actions:${RESET} ${actions} ${GRAY}(message up to ${messageLimit} characters)${RESET}`);
|
|
1401
|
+
} else {
|
|
1402
|
+
console.log(` ${BOLD}Available actions:${RESET} ${GRAY}none${RESET}`);
|
|
1403
|
+
}
|
|
1404
|
+
if (blockedReason)
|
|
1405
|
+
console.log(` ${BOLD}Blocked:${RESET} ${YELLOW}${blockedReason}${RESET}`);
|
|
1406
|
+
console.log(rule);
|
|
1407
|
+
if (availableActions.length > 0) {
|
|
1408
|
+
dim(` Reply: index negotiation turn ${negotiation.opportunityId.slice(0, 8)} --action <action> --message <text> --expected-turn-count ${negotiation.turnCount}`);
|
|
1409
|
+
}
|
|
1410
|
+
console.log();
|
|
1411
|
+
}
|
|
1412
|
+
function agentCard(selected) {
|
|
1413
|
+
const { agent, onboardingCompletedAt } = selected;
|
|
1414
|
+
const rule = ` ${GRAY}${"─".repeat(50)}${RESET}`;
|
|
1415
|
+
console.log();
|
|
1416
|
+
console.log(` ${BOLD}${CYAN}${agent.name}${RESET}`);
|
|
1417
|
+
console.log(rule);
|
|
1418
|
+
console.log(` ${BOLD}Seat${RESET} External negotiator (negotiates instead of Index's hosted agent)`);
|
|
1419
|
+
console.log(` ${BOLD}Status${RESET} ${agent.status === "active" ? GREEN : GRAY}${agent.status}${RESET}`);
|
|
1420
|
+
if (agent.description)
|
|
1421
|
+
console.log(` ${BOLD}Description${RESET} ${agent.description}`);
|
|
1422
|
+
console.log(` ${BOLD}Last seen${RESET} ${GRAY}${agent.lastSeenAt ? shortDateTime(agent.lastSeenAt) : "never"}${RESET}`);
|
|
1423
|
+
const onboarding = onboardingCompletedAt ? `${GREEN}complete${RESET} ${GRAY}(${shortDateTime(onboardingCompletedAt)})${RESET}` : `${YELLOW}not complete${RESET}`;
|
|
1424
|
+
console.log(` ${BOLD}Onboarding${RESET} ${onboarding}`);
|
|
1425
|
+
console.log(` ${BOLD}ID${RESET} ${GRAY}${agent.id}${RESET}`);
|
|
1426
|
+
console.log(rule);
|
|
1427
|
+
console.log();
|
|
1428
|
+
}
|
|
1429
|
+
function agentConversation(conversation) {
|
|
1430
|
+
const seat = conversation.agent.status === "hosted" ? "Index's hosted agent" : "your external negotiator";
|
|
1431
|
+
const rule = ` ${GRAY}${"─".repeat(60)}${RESET}`;
|
|
1432
|
+
console.log();
|
|
1433
|
+
console.log(` ${BOLD}${CYAN}Personal agent${RESET} ${GRAY}answered by ${seat}${RESET}`);
|
|
1434
|
+
console.log(rule);
|
|
1435
|
+
if (conversation.messages.length === 0)
|
|
1436
|
+
console.log(` ${GRAY}No messages yet.${RESET}`);
|
|
1437
|
+
for (const message of conversation.messages) {
|
|
1438
|
+
const author = message.role === "user" ? `${BOLD}${CYAN}you${RESET}` : `${BOLD}${BLUE}agent${RESET}`;
|
|
1439
|
+
const text = message.parts.filter((part) => part.kind === "text" && part.text).map((part) => part.text).join(`
|
|
1440
|
+
`);
|
|
1441
|
+
console.log(` ${author} ${GRAY}${shortDateTime(message.createdAt)}${RESET}`);
|
|
1442
|
+
for (const line of wordWrap(text, 70))
|
|
1443
|
+
console.log(` ${line}`);
|
|
1444
|
+
console.log();
|
|
1445
|
+
}
|
|
1446
|
+
const { questions } = conversation.agent;
|
|
1447
|
+
if (questions.length === 0) {
|
|
1448
|
+
console.log(` ${GRAY}No questions waiting for you.${RESET}`);
|
|
1449
|
+
console.log();
|
|
1450
|
+
return;
|
|
1451
|
+
}
|
|
1452
|
+
console.log(` ${BOLD}${YELLOW}Waiting for your answer (${questions.length})${RESET}`);
|
|
1453
|
+
for (const question of questions) {
|
|
1454
|
+
const [firstLine, ...moreLines] = wordWrap(question.question, 66);
|
|
1455
|
+
console.log(` ${YELLOW}?${RESET} ${BOLD}${firstLine}${RESET}`);
|
|
1456
|
+
for (const line of moreLines)
|
|
1457
|
+
console.log(` ${BOLD}${line}${RESET}`);
|
|
1458
|
+
console.log(` ${GRAY}Question ID${RESET} ${CYAN}${question.id}${RESET}`);
|
|
1459
|
+
if (question.options?.length)
|
|
1460
|
+
console.log(` ${GRAY}Options${RESET} ${question.options.join(" / ")}`);
|
|
1461
|
+
if (question.matches.length > 0) {
|
|
1462
|
+
const about = question.matches.map((match) => `${match.counterparty.name ?? "(unnamed)"} ${GRAY}(${match.opportunityId.slice(0, 8)})${RESET}`).join(", ");
|
|
1463
|
+
console.log(` ${GRAY}About${RESET} ${about}`);
|
|
1464
|
+
}
|
|
1465
|
+
console.log();
|
|
1466
|
+
}
|
|
1467
|
+
}
|
|
1466
1468
|
function networkTable(networks) {
|
|
1467
1469
|
if (networks.length === 0) {
|
|
1468
1470
|
dim(" No networks found.");
|
|
@@ -1588,7 +1590,7 @@ function messageList(messages) {
|
|
|
1588
1590
|
month: "short",
|
|
1589
1591
|
day: "numeric"
|
|
1590
1592
|
});
|
|
1591
|
-
const textParts = msg.parts.filter((p) => p.
|
|
1593
|
+
const textParts = msg.parts.filter((p) => p.kind === "text" && p.text).map((p) => p.text).join("");
|
|
1592
1594
|
console.log(` ${CYAN}${sender}${RESET} ${GRAY}${date} ${time}${RESET}`);
|
|
1593
1595
|
console.log(` ${textParts}`);
|
|
1594
1596
|
console.log();
|
|
@@ -1596,17 +1598,20 @@ function messageList(messages) {
|
|
|
1596
1598
|
}
|
|
1597
1599
|
// src/profile.command.ts
|
|
1598
1600
|
async function handleProfile(client, subcommand, positionals, options = {}) {
|
|
1599
|
-
if (subcommand === "create") {
|
|
1600
|
-
await profileCreate(client, options, options?.json);
|
|
1601
|
-
return;
|
|
1602
|
-
}
|
|
1603
1601
|
if (subcommand === "update") {
|
|
1604
|
-
const
|
|
1605
|
-
if (
|
|
1606
|
-
|
|
1607
|
-
return;
|
|
1602
|
+
const { name, intro, location, socials } = options;
|
|
1603
|
+
if (name === undefined && intro === undefined && location === undefined && socials === undefined) {
|
|
1604
|
+
throw new Error("Usage: index profile update [--name <text>] [--intro <text>] [--location <text>] [--social label=value]");
|
|
1608
1605
|
}
|
|
1609
|
-
await
|
|
1606
|
+
const user = await client.updateProfile({ name, intro, location, socials });
|
|
1607
|
+
if (options.json)
|
|
1608
|
+
console.log(JSON.stringify(user));
|
|
1609
|
+
else
|
|
1610
|
+
success("Profile updated.");
|
|
1611
|
+
return;
|
|
1612
|
+
}
|
|
1613
|
+
if (subcommand === "create" || subcommand === "search") {
|
|
1614
|
+
error(`profile ${subcommand} is not available; use "index profile sync" for public research prefill`, 1);
|
|
1610
1615
|
return;
|
|
1611
1616
|
}
|
|
1612
1617
|
if (subcommand === "sync") {
|
|
@@ -1622,35 +1627,6 @@ async function handleProfile(client, subcommand, positionals, options = {}) {
|
|
|
1622
1627
|
await profileShow(client, userId, options?.json);
|
|
1623
1628
|
return;
|
|
1624
1629
|
}
|
|
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
1630
|
await profileMe(client, options?.json);
|
|
1655
1631
|
}
|
|
1656
1632
|
async function profileMe(client, json) {
|
|
@@ -1685,61 +1661,26 @@ async function profileSync(client, json) {
|
|
|
1685
1661
|
return;
|
|
1686
1662
|
}
|
|
1687
1663
|
success("Profile enriched.");
|
|
1688
|
-
if (result.profile
|
|
1664
|
+
if (result.profile?.name)
|
|
1689
1665
|
dim(` Name: ${result.profile.name}`);
|
|
1690
|
-
if (result.profile
|
|
1666
|
+
if (result.profile?.location)
|
|
1691
1667
|
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.");
|
|
1668
|
+
dim(` Social links: ${result.profile?.socials?.length ?? 0}`);
|
|
1731
1669
|
}
|
|
1732
1670
|
|
|
1733
1671
|
// src/intent.command.ts
|
|
1734
1672
|
var INTENT_HELP = `
|
|
1735
1673
|
Usage:
|
|
1736
|
-
index intent list [--archived] [--limit <n>] List your
|
|
1737
|
-
index intent show <id> Show
|
|
1738
|
-
index intent
|
|
1739
|
-
index intent
|
|
1740
|
-
index intent
|
|
1741
|
-
index intent
|
|
1742
|
-
index intent
|
|
1674
|
+
index intent list [--archived] [--limit <n>] [--query <text>] List your intents
|
|
1675
|
+
index intent show <id> Show intent details (accepts short ID)
|
|
1676
|
+
index intent prepare <content> [--answer 'prompt=reply'] Review and repair a draft
|
|
1677
|
+
index intent create <content> [--receipt <token>] Create an admitted intent
|
|
1678
|
+
index intent pause <id> | resume <id> Hold or restart its agent
|
|
1679
|
+
index intent update <id> <content> Update an intent's description
|
|
1680
|
+
index intent archive <id> Archive an intent (accepts short ID)
|
|
1681
|
+
index intent networks <id> List the networks an intent is shared in
|
|
1682
|
+
index intent add-to-network <id> <network-id> Add an intent to a network
|
|
1683
|
+
index intent remove-from-network <id> <network-id> Remove an intent from a network
|
|
1743
1684
|
`;
|
|
1744
1685
|
async function handleIntent(client, subcommand, options) {
|
|
1745
1686
|
if (!subcommand) {
|
|
@@ -1754,13 +1695,14 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1754
1695
|
case "list": {
|
|
1755
1696
|
const result = await client.listIntents({
|
|
1756
1697
|
archived: options.archived,
|
|
1757
|
-
limit: options.limit
|
|
1698
|
+
limit: options.limit,
|
|
1699
|
+
query: options.query
|
|
1758
1700
|
});
|
|
1759
1701
|
if (options.json) {
|
|
1760
1702
|
console.log(JSON.stringify(result));
|
|
1761
1703
|
return;
|
|
1762
1704
|
}
|
|
1763
|
-
heading("
|
|
1705
|
+
heading("Intents");
|
|
1764
1706
|
intentTable(result.intents);
|
|
1765
1707
|
if (result.pagination.totalCount > 0) {
|
|
1766
1708
|
dim(`
|
|
@@ -1771,7 +1713,7 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1771
1713
|
}
|
|
1772
1714
|
case "show": {
|
|
1773
1715
|
if (!options.intentId) {
|
|
1774
|
-
error("Missing
|
|
1716
|
+
error("Missing intent ID. Usage: index intent show <id>", 1);
|
|
1775
1717
|
return;
|
|
1776
1718
|
}
|
|
1777
1719
|
const intent = await client.getIntent(options.intentId);
|
|
@@ -1782,39 +1724,36 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1782
1724
|
intentCard(intent);
|
|
1783
1725
|
return;
|
|
1784
1726
|
}
|
|
1727
|
+
case "prepare": {
|
|
1728
|
+
if (!options.intentContent)
|
|
1729
|
+
throw new Error("Usage: index intent prepare <content> [--answer 'prompt=reply']");
|
|
1730
|
+
const prepared = await client.prepareIntent(options.intentContent, (options.answers ?? []).map(({ key, value }) => ({ prompt: key, answer: value })));
|
|
1731
|
+
if (options.json) {
|
|
1732
|
+
console.log(JSON.stringify(prepared));
|
|
1733
|
+
return;
|
|
1734
|
+
}
|
|
1735
|
+
intentPreparation(prepared);
|
|
1736
|
+
return;
|
|
1737
|
+
}
|
|
1785
1738
|
case "create": {
|
|
1786
1739
|
if (!options.intentContent) {
|
|
1787
1740
|
error("Missing content. Usage: index intent create <content>", 1);
|
|
1788
1741
|
return;
|
|
1789
1742
|
}
|
|
1790
1743
|
if (!options.json)
|
|
1791
|
-
info("Processing
|
|
1792
|
-
const result = await client.
|
|
1793
|
-
description: options.intentContent
|
|
1794
|
-
});
|
|
1744
|
+
info("Processing intent...");
|
|
1745
|
+
const result = await client.createIntent(options.intentContent, options.targetId ? [options.targetId] : undefined, options.receipt);
|
|
1795
1746
|
if (options.json) {
|
|
1796
1747
|
console.log(JSON.stringify(result));
|
|
1797
1748
|
return;
|
|
1798
1749
|
}
|
|
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
|
-
}
|
|
1750
|
+
success("Intent created.");
|
|
1751
|
+
dim(` shared in ${result.networkIds.length} network${result.networkIds.length === 1 ? "" : "s"}`);
|
|
1813
1752
|
return;
|
|
1814
1753
|
}
|
|
1815
1754
|
case "update": {
|
|
1816
1755
|
if (!options.intentId) {
|
|
1817
|
-
error("Missing
|
|
1756
|
+
error("Missing intent ID. Usage: index intent update <id> <content>", 1);
|
|
1818
1757
|
return;
|
|
1819
1758
|
}
|
|
1820
1759
|
if (!options.intentContent) {
|
|
@@ -1822,108 +1761,96 @@ async function handleIntent(client, subcommand, options) {
|
|
|
1822
1761
|
return;
|
|
1823
1762
|
}
|
|
1824
1763
|
if (!options.json)
|
|
1825
|
-
info("Updating
|
|
1764
|
+
info("Updating intent...");
|
|
1826
1765
|
const result = await client.updateIntent(options.intentId, options.intentContent);
|
|
1827
1766
|
if (options.json) {
|
|
1828
1767
|
console.log(JSON.stringify(result));
|
|
1829
1768
|
return;
|
|
1830
1769
|
}
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1770
|
+
success("Intent updated.");
|
|
1771
|
+
return;
|
|
1772
|
+
}
|
|
1773
|
+
case "pause":
|
|
1774
|
+
case "resume": {
|
|
1775
|
+
if (!options.intentId)
|
|
1776
|
+
throw new Error(`Usage: index intent ${subcommand} <id>`);
|
|
1777
|
+
const status = subcommand === "pause" ? "PAUSED" : "ACTIVE";
|
|
1778
|
+
await client.updateIntentStatus(options.intentId, status);
|
|
1779
|
+
if (options.json)
|
|
1780
|
+
console.log(JSON.stringify({ intentId: options.intentId, status }));
|
|
1781
|
+
else
|
|
1782
|
+
success(`Intent ${status.toLowerCase()}.`);
|
|
1836
1783
|
return;
|
|
1837
1784
|
}
|
|
1838
1785
|
case "archive": {
|
|
1839
1786
|
if (!options.intentId) {
|
|
1840
|
-
error("Missing
|
|
1787
|
+
error("Missing intent ID. Usage: index intent archive <id>", 1);
|
|
1841
1788
|
return;
|
|
1842
1789
|
}
|
|
1843
|
-
|
|
1844
|
-
const result = await client.callTool("delete_intent", { intentId: intent.id });
|
|
1790
|
+
await client.archiveIntent(options.intentId);
|
|
1845
1791
|
if (options.json) {
|
|
1846
|
-
console.log(JSON.stringify(
|
|
1792
|
+
console.log(JSON.stringify({ success: true }));
|
|
1847
1793
|
return;
|
|
1848
1794
|
}
|
|
1849
|
-
|
|
1850
|
-
|
|
1795
|
+
success(`Intent ${options.intentId} archived.`);
|
|
1796
|
+
return;
|
|
1797
|
+
}
|
|
1798
|
+
case "networks": {
|
|
1799
|
+
if (!options.intentId) {
|
|
1800
|
+
error("Usage: index intent networks <intent-id>", 1);
|
|
1851
1801
|
return;
|
|
1852
1802
|
}
|
|
1853
|
-
|
|
1803
|
+
const networkIds = await client.listIntentNetworks(options.intentId);
|
|
1804
|
+
if (options.json) {
|
|
1805
|
+
console.log(JSON.stringify({ networkIds }));
|
|
1806
|
+
return;
|
|
1807
|
+
}
|
|
1808
|
+
heading("Networks");
|
|
1809
|
+
for (const networkId of networkIds)
|
|
1810
|
+
dim(` ${networkId}`);
|
|
1811
|
+
console.log();
|
|
1854
1812
|
return;
|
|
1855
1813
|
}
|
|
1856
|
-
case "
|
|
1814
|
+
case "add-to-network": {
|
|
1857
1815
|
if (!options.intentId || !options.targetId) {
|
|
1858
|
-
error("Usage: index intent
|
|
1816
|
+
error("Usage: index intent add-to-network <intent-id> <network-id>", 1);
|
|
1859
1817
|
return;
|
|
1860
1818
|
}
|
|
1861
|
-
|
|
1862
|
-
const result = await client.callTool("create_intent_index", {
|
|
1863
|
-
intentId: intent.id,
|
|
1864
|
-
networkId: options.targetId
|
|
1865
|
-
});
|
|
1819
|
+
await client.addIntentToNetwork(options.intentId, options.targetId);
|
|
1866
1820
|
if (options.json) {
|
|
1867
|
-
console.log(JSON.stringify(
|
|
1821
|
+
console.log(JSON.stringify({ success: true }));
|
|
1868
1822
|
return;
|
|
1869
1823
|
}
|
|
1870
|
-
|
|
1871
|
-
error(result.error ?? "Failed to link signal", 1);
|
|
1872
|
-
return;
|
|
1873
|
-
}
|
|
1874
|
-
success("Signal linked to network.");
|
|
1824
|
+
success("Intent added to network.");
|
|
1875
1825
|
return;
|
|
1876
1826
|
}
|
|
1877
|
-
case "
|
|
1827
|
+
case "remove-from-network": {
|
|
1878
1828
|
if (!options.intentId || !options.targetId) {
|
|
1879
|
-
error("Usage: index intent
|
|
1829
|
+
error("Usage: index intent remove-from-network <intent-id> <network-id>", 1);
|
|
1880
1830
|
return;
|
|
1881
1831
|
}
|
|
1882
|
-
|
|
1883
|
-
const result = await client.callTool("delete_intent_index", {
|
|
1884
|
-
intentId: intent.id,
|
|
1885
|
-
networkId: options.targetId
|
|
1886
|
-
});
|
|
1832
|
+
await client.removeIntentFromNetwork(options.intentId, options.targetId);
|
|
1887
1833
|
if (options.json) {
|
|
1888
|
-
console.log(JSON.stringify(
|
|
1889
|
-
return;
|
|
1890
|
-
}
|
|
1891
|
-
if (!result.success) {
|
|
1892
|
-
error(result.error ?? "Failed to unlink signal", 1);
|
|
1834
|
+
console.log(JSON.stringify({ success: true }));
|
|
1893
1835
|
return;
|
|
1894
1836
|
}
|
|
1895
|
-
success("
|
|
1837
|
+
success("Intent removed from network.");
|
|
1896
1838
|
return;
|
|
1897
1839
|
}
|
|
1898
1840
|
}
|
|
1899
1841
|
}
|
|
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
1842
|
|
|
1917
1843
|
// src/opportunity.command.ts
|
|
1918
1844
|
var OPPORTUNITY_HELP = `
|
|
1919
1845
|
Usage:
|
|
1920
1846
|
index opportunity list List your opportunities
|
|
1921
|
-
index opportunity list --
|
|
1847
|
+
index opportunity list --intent-id <id> --statuses negotiating,pending,accepted,expired
|
|
1848
|
+
index opportunity list --status <s> Filter by one settled or actionable status
|
|
1922
1849
|
index opportunity list --limit <n> Limit results
|
|
1923
1850
|
index opportunity show <id> Show full opportunity details (accepts short ID)
|
|
1924
1851
|
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
1852
|
index opportunity reject <id> Reject an opportunity (accepts short ID)
|
|
1853
|
+
index opportunity start-chat <id> Open the chat through this opportunity
|
|
1927
1854
|
`;
|
|
1928
1855
|
async function handleOpportunity(client, subcommand, options) {
|
|
1929
1856
|
if (!subcommand) {
|
|
@@ -1936,7 +1863,7 @@ async function handleOpportunity(client, subcommand, options) {
|
|
|
1936
1863
|
}
|
|
1937
1864
|
switch (subcommand) {
|
|
1938
1865
|
case "list":
|
|
1939
|
-
await opportunityList(client, options.status, options.limit, options.json);
|
|
1866
|
+
await opportunityList(client, options.status, options.statuses, options.intentId, options.limit, options.json);
|
|
1940
1867
|
return;
|
|
1941
1868
|
case "show":
|
|
1942
1869
|
if (!options.targetId) {
|
|
@@ -1950,7 +1877,7 @@ async function handleOpportunity(client, subcommand, options) {
|
|
|
1950
1877
|
error("Missing opportunity ID. Usage: index opportunity accept <id>", 1);
|
|
1951
1878
|
return;
|
|
1952
1879
|
}
|
|
1953
|
-
await opportunityStatusUpdate(client, options.targetId, "accepted", options.json
|
|
1880
|
+
await opportunityStatusUpdate(client, options.targetId, "accepted", options.json);
|
|
1954
1881
|
return;
|
|
1955
1882
|
case "reject":
|
|
1956
1883
|
if (!options.targetId) {
|
|
@@ -1959,13 +1886,23 @@ async function handleOpportunity(client, subcommand, options) {
|
|
|
1959
1886
|
}
|
|
1960
1887
|
await opportunityStatusUpdate(client, options.targetId, "rejected", options.json);
|
|
1961
1888
|
return;
|
|
1889
|
+
case "start-chat": {
|
|
1890
|
+
if (!options.targetId)
|
|
1891
|
+
throw new Error("Usage: index opportunity start-chat <id>");
|
|
1892
|
+
const result = await client.startOpportunityChat(options.targetId);
|
|
1893
|
+
if (options.json)
|
|
1894
|
+
console.log(JSON.stringify(result));
|
|
1895
|
+
else
|
|
1896
|
+
success(`Chat opened: ${result.conversationId}`);
|
|
1897
|
+
return;
|
|
1898
|
+
}
|
|
1962
1899
|
default:
|
|
1963
1900
|
error(`Unknown subcommand: ${subcommand}`, 1);
|
|
1964
1901
|
return;
|
|
1965
1902
|
}
|
|
1966
1903
|
}
|
|
1967
|
-
async function opportunityList(client,
|
|
1968
|
-
const opportunities = await client.listOpportunities({ status
|
|
1904
|
+
async function opportunityList(client, status, statuses, intentId, limit, json) {
|
|
1905
|
+
const opportunities = await client.listOpportunities({ status, statuses, intentId, limit });
|
|
1969
1906
|
if (json) {
|
|
1970
1907
|
console.log(JSON.stringify(opportunities));
|
|
1971
1908
|
return;
|
|
@@ -1982,225 +1919,74 @@ async function opportunityShow(client, id, json) {
|
|
|
1982
1919
|
}
|
|
1983
1920
|
opportunityCard(opportunity);
|
|
1984
1921
|
}
|
|
1985
|
-
async function opportunityStatusUpdate(client, id,
|
|
1922
|
+
async function opportunityStatusUpdate(client, id, status, json) {
|
|
1986
1923
|
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");
|
|
1924
|
+
const result = await client.updateOpportunityStatus(opportunity.id, status);
|
|
2020
1925
|
if (json) {
|
|
2021
1926
|
console.log(JSON.stringify(result));
|
|
2022
1927
|
return;
|
|
2023
1928
|
}
|
|
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;
|
|
1929
|
+
success(`Opportunity ${status}.`);
|
|
2031
1930
|
}
|
|
2032
1931
|
|
|
2033
1932
|
// 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
1933
|
async function handleNegotiation(client, subcommand, options) {
|
|
2042
|
-
if (
|
|
1934
|
+
if (subcommand === "list") {
|
|
1935
|
+
if (options.state !== undefined && options.state !== "open" && options.state !== "settled")
|
|
1936
|
+
throw new Error("--state must be open or settled");
|
|
1937
|
+
const negotiations = await client.listNegotiations({ intentId: options.intentId, state: options.state });
|
|
2043
1938
|
if (options.json) {
|
|
2044
|
-
console.log(JSON.stringify(
|
|
2045
|
-
} else {
|
|
2046
|
-
console.log(NEGOTIATION_HELP);
|
|
2047
|
-
}
|
|
2048
|
-
return;
|
|
2049
|
-
}
|
|
2050
|
-
switch (subcommand) {
|
|
2051
|
-
case "list":
|
|
2052
|
-
await negotiationList(client, options.limit, options.since, options.json);
|
|
1939
|
+
console.log(JSON.stringify(negotiations));
|
|
2053
1940
|
return;
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
1941
|
+
}
|
|
1942
|
+
heading("Negotiations");
|
|
1943
|
+
negotiationTable(negotiations);
|
|
1944
|
+
if (negotiations.length > 0)
|
|
1945
|
+
dim(`
|
|
1946
|
+
Details: index negotiation show <id> (the short ID works)`);
|
|
1947
|
+
console.log();
|
|
1948
|
+
} else if (subcommand === "show" || subcommand === "turn") {
|
|
1949
|
+
if (!options.targetId)
|
|
1950
|
+
throw new Error("An opportunity ID is required");
|
|
1951
|
+
if (subcommand === "show") {
|
|
1952
|
+
const negotiation = await client.getNegotiation(options.targetId);
|
|
1953
|
+
if (options.json) {
|
|
1954
|
+
console.log(JSON.stringify(negotiation));
|
|
2057
1955
|
return;
|
|
2058
1956
|
}
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
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"
|
|
1957
|
+
negotiationCard(negotiation);
|
|
1958
|
+
} else {
|
|
1959
|
+
if (!options.action || !["propose", "counter", "accept", "decline"].includes(options.action))
|
|
1960
|
+
throw new Error("--action must be propose, counter, accept, or decline");
|
|
1961
|
+
if (!options.message?.trim())
|
|
1962
|
+
throw new Error("--message is required");
|
|
1963
|
+
if (options.expectedTurnCount === undefined || !Number.isSafeInteger(options.expectedTurnCount) || options.expectedTurnCount < 0)
|
|
1964
|
+
throw new Error("--expected-turn-count must be the observed nonnegative integer turn count");
|
|
1965
|
+
const negotiation = await client.submitNegotiationTurn(options.targetId, {
|
|
1966
|
+
action: options.action,
|
|
1967
|
+
message: options.message,
|
|
1968
|
+
expectedTurnCount: options.expectedTurnCount
|
|
2181
1969
|
});
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
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
|
-
}
|
|
1970
|
+
if (options.json) {
|
|
1971
|
+
console.log(JSON.stringify(negotiation));
|
|
1972
|
+
return;
|
|
2192
1973
|
}
|
|
2193
|
-
|
|
1974
|
+
success(`Turn submitted: ${options.action}`);
|
|
1975
|
+
negotiationCard(negotiation);
|
|
2194
1976
|
}
|
|
1977
|
+
} else {
|
|
1978
|
+
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
1979
|
}
|
|
2196
|
-
console.log(` ${GRAY2}${"─".repeat(60)}${RESET2}`);
|
|
2197
|
-
console.log();
|
|
2198
1980
|
}
|
|
2199
1981
|
|
|
2200
1982
|
// src/network.command.ts
|
|
2201
1983
|
var NETWORK_HELP = `
|
|
2202
1984
|
Network Commands:
|
|
2203
1985
|
index network list List your networks
|
|
1986
|
+
index network discover Find public networks to join
|
|
1987
|
+
index network requests See your network creation requests
|
|
1988
|
+
index network request-update <id> --title <name> [--prompt <purpose>]
|
|
1989
|
+
index network request-dismiss <id> Dismiss your request
|
|
2204
1990
|
index network create <name> Create directly or submit an early-access request
|
|
2205
1991
|
index network create <name> --prompt Create directly or request early access with a description
|
|
2206
1992
|
index network show <id|key> Show network details and members
|
|
@@ -2220,6 +2006,47 @@ async function handleNetwork(client, subcommand, positionals, options) {
|
|
|
2220
2006
|
case "list":
|
|
2221
2007
|
await networkList(client, options.json);
|
|
2222
2008
|
return;
|
|
2009
|
+
case "discover": {
|
|
2010
|
+
const result = await client.discoverNetworks();
|
|
2011
|
+
if (options.json)
|
|
2012
|
+
console.log(JSON.stringify(result));
|
|
2013
|
+
else {
|
|
2014
|
+
heading("Public networks");
|
|
2015
|
+
networkTable(result.networks);
|
|
2016
|
+
}
|
|
2017
|
+
return;
|
|
2018
|
+
}
|
|
2019
|
+
case "requests": {
|
|
2020
|
+
const result = await client.listNetworkRequests();
|
|
2021
|
+
if (options.json)
|
|
2022
|
+
console.log(JSON.stringify(result));
|
|
2023
|
+
else {
|
|
2024
|
+
heading("Your network requests");
|
|
2025
|
+
for (const request of result.requests)
|
|
2026
|
+
dim(` ${request.id} · ${request.title} · ${request.status}`);
|
|
2027
|
+
}
|
|
2028
|
+
return;
|
|
2029
|
+
}
|
|
2030
|
+
case "request-update": {
|
|
2031
|
+
if (!positionals[0] || !options.title)
|
|
2032
|
+
throw new Error("Usage: index network request-update <id> --title <name> [--prompt <purpose>]");
|
|
2033
|
+
const result = await client.updateNetworkRequest(positionals[0], options.title, options.prompt);
|
|
2034
|
+
if (options.json)
|
|
2035
|
+
console.log(JSON.stringify(result));
|
|
2036
|
+
else
|
|
2037
|
+
success("Network request resubmitted.");
|
|
2038
|
+
return;
|
|
2039
|
+
}
|
|
2040
|
+
case "request-dismiss": {
|
|
2041
|
+
if (!positionals[0])
|
|
2042
|
+
throw new Error("Usage: index network request-dismiss <id>");
|
|
2043
|
+
await client.dismissNetworkRequest(positionals[0]);
|
|
2044
|
+
if (options.json)
|
|
2045
|
+
console.log(JSON.stringify({ success: true }));
|
|
2046
|
+
else
|
|
2047
|
+
success("Network request dismissed.");
|
|
2048
|
+
return;
|
|
2049
|
+
}
|
|
2223
2050
|
case "create":
|
|
2224
2051
|
await networkCreate(client, positionals[0], options.prompt, options.json);
|
|
2225
2052
|
return;
|
|
@@ -2247,13 +2074,12 @@ async function handleNetwork(client, subcommand, positionals, options) {
|
|
|
2247
2074
|
}
|
|
2248
2075
|
async function networkList(client, json) {
|
|
2249
2076
|
const networks = await client.listNetworks();
|
|
2250
|
-
const filtered = networks.filter((n) => !n.isPersonal);
|
|
2251
2077
|
if (json) {
|
|
2252
|
-
console.log(JSON.stringify(
|
|
2078
|
+
console.log(JSON.stringify(networks));
|
|
2253
2079
|
return;
|
|
2254
2080
|
}
|
|
2255
2081
|
heading("Networks");
|
|
2256
|
-
networkTable(
|
|
2082
|
+
networkTable(networks);
|
|
2257
2083
|
console.log();
|
|
2258
2084
|
}
|
|
2259
2085
|
async function networkCreate(client, name, prompt, json) {
|
|
@@ -2334,13 +2160,9 @@ async function networkUpdate(client, id, options, json) {
|
|
|
2334
2160
|
error("Provide at least --title or --prompt. Usage: index network update <id> [--title <t>] [--prompt <p>]", 1);
|
|
2335
2161
|
return;
|
|
2336
2162
|
}
|
|
2337
|
-
const
|
|
2163
|
+
const network = await client.updateNetwork(id, settings);
|
|
2338
2164
|
if (json) {
|
|
2339
|
-
console.log(JSON.stringify(
|
|
2340
|
-
return;
|
|
2341
|
-
}
|
|
2342
|
-
if (!result.success) {
|
|
2343
|
-
error(result.error ?? "Network update failed", 1);
|
|
2165
|
+
console.log(JSON.stringify({ network }));
|
|
2344
2166
|
return;
|
|
2345
2167
|
}
|
|
2346
2168
|
success("Network updated.");
|
|
@@ -2350,13 +2172,9 @@ async function networkDelete(client, id, json) {
|
|
|
2350
2172
|
error("Usage: index network delete <id>", 1);
|
|
2351
2173
|
return;
|
|
2352
2174
|
}
|
|
2353
|
-
|
|
2175
|
+
await client.deleteNetwork(id);
|
|
2354
2176
|
if (json) {
|
|
2355
|
-
console.log(JSON.stringify(
|
|
2356
|
-
return;
|
|
2357
|
-
}
|
|
2358
|
-
if (!result.success) {
|
|
2359
|
-
error(result.error ?? "Network deletion failed", 1);
|
|
2177
|
+
console.log(JSON.stringify({ success: true }));
|
|
2360
2178
|
return;
|
|
2361
2179
|
}
|
|
2362
2180
|
success("Network deleted.");
|
|
@@ -2380,6 +2198,47 @@ async function networkInvite(client, id, email, json) {
|
|
|
2380
2198
|
dim(" Created a pending account for this invitee.");
|
|
2381
2199
|
}
|
|
2382
2200
|
|
|
2201
|
+
// src/sse.parser.ts
|
|
2202
|
+
function parseSSEEvents(chunk) {
|
|
2203
|
+
if (!chunk)
|
|
2204
|
+
return [];
|
|
2205
|
+
const events = [];
|
|
2206
|
+
const rawEvents = chunk.split(`
|
|
2207
|
+
|
|
2208
|
+
`);
|
|
2209
|
+
for (let i = 0;i < rawEvents.length; i++) {
|
|
2210
|
+
const raw = rawEvents[i].trim();
|
|
2211
|
+
if (!raw)
|
|
2212
|
+
continue;
|
|
2213
|
+
if (i === rawEvents.length - 1 && !chunk.endsWith(`
|
|
2214
|
+
|
|
2215
|
+
`)) {
|
|
2216
|
+
continue;
|
|
2217
|
+
}
|
|
2218
|
+
let eventType;
|
|
2219
|
+
const dataLines = [];
|
|
2220
|
+
for (const line of raw.split(`
|
|
2221
|
+
`)) {
|
|
2222
|
+
if (line.startsWith(":")) {
|
|
2223
|
+
continue;
|
|
2224
|
+
}
|
|
2225
|
+
if (line.startsWith("event:")) {
|
|
2226
|
+
eventType = line.slice("event:".length).trim();
|
|
2227
|
+
} else if (line.startsWith("data:")) {
|
|
2228
|
+
dataLines.push(line.slice("data:".length).trim());
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
if (dataLines.length > 0) {
|
|
2232
|
+
events.push({
|
|
2233
|
+
event: eventType,
|
|
2234
|
+
data: dataLines.join(`
|
|
2235
|
+
`)
|
|
2236
|
+
});
|
|
2237
|
+
}
|
|
2238
|
+
}
|
|
2239
|
+
return events;
|
|
2240
|
+
}
|
|
2241
|
+
|
|
2383
2242
|
// src/conversation.command.ts
|
|
2384
2243
|
var CONVERSATION_HELP = `
|
|
2385
2244
|
Conversation Commands:
|
|
@@ -2388,13 +2247,63 @@ Conversation Commands:
|
|
|
2388
2247
|
index conversation show <id> Show messages (accepts short ID)
|
|
2389
2248
|
index conversation show <id> --limit <n> Limit number of messages
|
|
2390
2249
|
index conversation send <id> <message> Send a message (accepts short ID)
|
|
2250
|
+
index conversation show agent --intent-id <id> Read scoped agent state
|
|
2251
|
+
index conversation send agent <text> --intent-id <id> [--question-id <id>]
|
|
2252
|
+
index conversation answer agent --intent-id <id> --answer 'question-id=text' [--answer ...]
|
|
2391
2253
|
index conversation stream Listen for real-time events (SSE)
|
|
2392
2254
|
`;
|
|
2393
2255
|
async function handleConversation(client, subcommand, positionals, options) {
|
|
2394
|
-
if (
|
|
2395
|
-
|
|
2256
|
+
if (positionals[0] === "agent" && (subcommand === "show" || subcommand === "send")) {
|
|
2257
|
+
if (!options?.intentId)
|
|
2258
|
+
throw new Error("Personal-agent conversations require --intent-id <id>");
|
|
2259
|
+
if (subcommand === "show") {
|
|
2260
|
+
const conversation = await client.getAgentConversation(options.intentId);
|
|
2261
|
+
if (options.json) {
|
|
2262
|
+
console.log(JSON.stringify(conversation));
|
|
2263
|
+
return;
|
|
2264
|
+
}
|
|
2265
|
+
agentConversation(conversation);
|
|
2266
|
+
if (conversation.agent.questions.length > 0) {
|
|
2267
|
+
dim(` Answer: index conversation answer agent --intent-id ${options.intentId} --answer '<question-id>=<reply>'`);
|
|
2268
|
+
}
|
|
2269
|
+
return;
|
|
2270
|
+
}
|
|
2271
|
+
const text = positionals.slice(1).join(" ");
|
|
2272
|
+
if (!text.trim())
|
|
2273
|
+
throw new Error("A message is required");
|
|
2274
|
+
if (options.questionId) {
|
|
2275
|
+
const answers = [{ questionId: options.questionId, text }];
|
|
2276
|
+
const result = await client.answerAgentQuestions(options.intentId, answers);
|
|
2277
|
+
if (options.json) {
|
|
2278
|
+
console.log(JSON.stringify(result));
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
printAgentAnswers(answers, result.messages);
|
|
2282
|
+
return;
|
|
2283
|
+
}
|
|
2284
|
+
const message = await client.sendMessage("agent", text, options.intentId);
|
|
2285
|
+
if (options.json) {
|
|
2286
|
+
console.log(JSON.stringify(message));
|
|
2287
|
+
return;
|
|
2288
|
+
}
|
|
2289
|
+
success(`Message sent to your agent (${message.id})`);
|
|
2290
|
+
return;
|
|
2291
|
+
}
|
|
2292
|
+
if (subcommand === "answer") {
|
|
2293
|
+
if (positionals[0] !== "agent" || !options?.intentId || !options.answers?.length) {
|
|
2294
|
+
throw new Error("Usage: index conversation answer agent --intent-id <id> --answer 'question-id=text' [--answer ...]");
|
|
2295
|
+
}
|
|
2296
|
+
const answers = options.answers.map(({ key, value }) => ({ questionId: key, text: value }));
|
|
2297
|
+
const result = await client.answerAgentQuestions(options.intentId, answers);
|
|
2298
|
+
if (options.json) {
|
|
2299
|
+
console.log(JSON.stringify(result));
|
|
2300
|
+
return;
|
|
2301
|
+
}
|
|
2302
|
+
printAgentAnswers(answers, result.messages);
|
|
2396
2303
|
return;
|
|
2397
2304
|
}
|
|
2305
|
+
if (!subcommand)
|
|
2306
|
+
throw new Error(CONVERSATION_HELP.trim());
|
|
2398
2307
|
switch (subcommand) {
|
|
2399
2308
|
case "list":
|
|
2400
2309
|
await conversationList(client, options?.json);
|
|
@@ -2409,15 +2318,25 @@ async function handleConversation(client, subcommand, positionals, options) {
|
|
|
2409
2318
|
await conversationSend(client, positionals[0], positionals.slice(1), options?.json);
|
|
2410
2319
|
return;
|
|
2411
2320
|
case "stream":
|
|
2412
|
-
await conversationStream(client);
|
|
2321
|
+
await conversationStream(client, options?.json);
|
|
2413
2322
|
return;
|
|
2414
2323
|
case "help":
|
|
2415
|
-
console.log(CONVERSATION_HELP);
|
|
2324
|
+
console.log(options?.json ? JSON.stringify({ help: CONVERSATION_HELP.trim() }) : CONVERSATION_HELP);
|
|
2416
2325
|
return;
|
|
2417
2326
|
default:
|
|
2418
2327
|
error(`Unknown conversation subcommand: ${subcommand}`, 1);
|
|
2419
2328
|
}
|
|
2420
2329
|
}
|
|
2330
|
+
function printAgentAnswers(answers, messages) {
|
|
2331
|
+
for (const [index, message] of messages.entries()) {
|
|
2332
|
+
const { questionId } = answers[index];
|
|
2333
|
+
if (message.metadata.principalMessage.kind === "answer") {
|
|
2334
|
+
success(`Answered question ${questionId}`);
|
|
2335
|
+
} else {
|
|
2336
|
+
success(`Question ${questionId} is no longer waiting; your reply was sent to your agent as a message`);
|
|
2337
|
+
}
|
|
2338
|
+
}
|
|
2339
|
+
}
|
|
2421
2340
|
async function conversationList(client, json) {
|
|
2422
2341
|
const conversations = await client.listConversations();
|
|
2423
2342
|
if (json) {
|
|
@@ -2470,11 +2389,11 @@ async function conversationSend(client, id, messageParts, json) {
|
|
|
2470
2389
|
}
|
|
2471
2390
|
success(`Message sent (${msg.id})`);
|
|
2472
2391
|
}
|
|
2473
|
-
async function conversationStream(client) {
|
|
2392
|
+
async function conversationStream(client, json) {
|
|
2474
2393
|
info("Connecting to conversation stream...");
|
|
2475
2394
|
dim(`Press Ctrl+C to stop.
|
|
2476
2395
|
`);
|
|
2477
|
-
const response = await client.
|
|
2396
|
+
const response = await client.streamEvents();
|
|
2478
2397
|
if (!response.body) {
|
|
2479
2398
|
error("No response body from stream endpoint.", 1);
|
|
2480
2399
|
return;
|
|
@@ -2488,33 +2407,21 @@ async function conversationStream(client) {
|
|
|
2488
2407
|
if (done)
|
|
2489
2408
|
break;
|
|
2490
2409
|
buffer += decoder.decode(value, { stream: true });
|
|
2491
|
-
|
|
2492
|
-
|
|
2493
|
-
`
|
|
2494
|
-
const idx = buffer.indexOf(`
|
|
2410
|
+
buffer = buffer.replace(/\r\n/g, `
|
|
2411
|
+
`);
|
|
2412
|
+
const boundary = buffer.lastIndexOf(`
|
|
2495
2413
|
|
|
2496
2414
|
`);
|
|
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
|
-
}
|
|
2415
|
+
if (boundary < 0)
|
|
2416
|
+
continue;
|
|
2417
|
+
const complete = buffer.slice(0, boundary + 2);
|
|
2418
|
+
buffer = buffer.slice(boundary + 2);
|
|
2419
|
+
for (const event of parseSSEEvents(complete)) {
|
|
2420
|
+
const data = JSON.parse(event.data);
|
|
2421
|
+
if (json)
|
|
2422
|
+
console.log(JSON.stringify({ event: event.event, data }));
|
|
2423
|
+
else
|
|
2424
|
+
dim(JSON.stringify(data));
|
|
2518
2425
|
}
|
|
2519
2426
|
}
|
|
2520
2427
|
} finally {
|
|
@@ -2522,81 +2429,6 @@ async function conversationStream(client) {
|
|
|
2522
2429
|
}
|
|
2523
2430
|
}
|
|
2524
2431
|
|
|
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
2432
|
// src/scrape.command.ts
|
|
2601
2433
|
async function handleScrape(client, positionals, options) {
|
|
2602
2434
|
const url = positionals[0];
|
|
@@ -2606,20 +2438,15 @@ async function handleScrape(client, positionals, options) {
|
|
|
2606
2438
|
}
|
|
2607
2439
|
if (!options.json)
|
|
2608
2440
|
info(`Scraping ${url}...`);
|
|
2609
|
-
const result = await client.
|
|
2441
|
+
const result = await client.scrapeUrl(url, options.objective);
|
|
2610
2442
|
if (options.json) {
|
|
2611
2443
|
console.log(JSON.stringify(result));
|
|
2612
2444
|
return;
|
|
2613
2445
|
}
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
return;
|
|
2617
|
-
}
|
|
2618
|
-
const data = result.data;
|
|
2619
|
-
heading(`Content from ${data.url}`);
|
|
2620
|
-
console.log(data.content);
|
|
2446
|
+
heading(`Content from ${result.url}`);
|
|
2447
|
+
console.log(result.content);
|
|
2621
2448
|
dim(`
|
|
2622
|
-
${
|
|
2449
|
+
${result.contentLength} characters extracted`);
|
|
2623
2450
|
console.log();
|
|
2624
2451
|
}
|
|
2625
2452
|
|
|
@@ -2630,18 +2457,17 @@ import { join as join2 } from "node:path";
|
|
|
2630
2457
|
async function handleSync(client, options) {
|
|
2631
2458
|
if (!options.json)
|
|
2632
2459
|
info("Syncing context...");
|
|
2633
|
-
const
|
|
2634
|
-
|
|
2635
|
-
client.
|
|
2636
|
-
client.
|
|
2637
|
-
client.
|
|
2460
|
+
const me = await client.getMe();
|
|
2461
|
+
const [profile, networks, intents] = await Promise.all([
|
|
2462
|
+
client.getUser(me.id),
|
|
2463
|
+
client.listNetworks(),
|
|
2464
|
+
client.listIntents({ limit: 100 })
|
|
2638
2465
|
]);
|
|
2639
2466
|
const context = {
|
|
2640
2467
|
syncedAt: new Date().toISOString(),
|
|
2641
|
-
profile
|
|
2642
|
-
networks
|
|
2643
|
-
intents: intents.
|
|
2644
|
-
contacts: contacts.success ? contacts.data : null
|
|
2468
|
+
profile,
|
|
2469
|
+
networks,
|
|
2470
|
+
intents: intents.intents
|
|
2645
2471
|
};
|
|
2646
2472
|
if (options.json) {
|
|
2647
2473
|
console.log(JSON.stringify(context));
|
|
@@ -2653,190 +2479,109 @@ async function handleSync(client, options) {
|
|
|
2653
2479
|
success("Context synced to ~/.index/context.json");
|
|
2654
2480
|
}
|
|
2655
2481
|
|
|
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", {});
|
|
2482
|
+
// src/docs.command.ts
|
|
2483
|
+
async function handleDocs(client, topic, json) {
|
|
2484
|
+
const result = await client.readDocs(topic);
|
|
2673
2485
|
if (json) {
|
|
2674
2486
|
console.log(JSON.stringify(result));
|
|
2675
2487
|
return;
|
|
2676
2488
|
}
|
|
2677
|
-
|
|
2678
|
-
|
|
2489
|
+
console.log(result.content);
|
|
2490
|
+
if (result.topics)
|
|
2491
|
+
dim(`
|
|
2492
|
+
Topics: ${result.topics.join(", ")}`);
|
|
2493
|
+
}
|
|
2494
|
+
|
|
2495
|
+
// src/onboarding.command.ts
|
|
2496
|
+
async function handleOnboarding(client, subcommand, options) {
|
|
2497
|
+
if (subcommand === "confirm-profile") {
|
|
2498
|
+
const result = await client.confirmProfile();
|
|
2499
|
+
if (options?.json) {
|
|
2500
|
+
console.log(JSON.stringify(result));
|
|
2501
|
+
return;
|
|
2502
|
+
}
|
|
2503
|
+
success("Profile confirmed.");
|
|
2504
|
+
} else if (subcommand === "complete") {
|
|
2505
|
+
const result = await client.completeOnboarding(options?.intentId);
|
|
2506
|
+
if (options?.json) {
|
|
2507
|
+
console.log(JSON.stringify(result));
|
|
2508
|
+
return;
|
|
2509
|
+
}
|
|
2510
|
+
success(`Onboarding complete (first intent ${result.intentId}).`);
|
|
2679
2511
|
} else {
|
|
2680
|
-
|
|
2512
|
+
throw new Error("Usage: index onboarding confirm-profile | complete [--intent-id <id>]");
|
|
2681
2513
|
}
|
|
2682
2514
|
}
|
|
2683
2515
|
|
|
2684
2516
|
// src/main.ts
|
|
2685
2517
|
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
|
-
`);
|
|
2518
|
+
var LOGIN_API_URLS = {
|
|
2519
|
+
local: "http://localhost:3001",
|
|
2520
|
+
dev: "https://protocol.dev.index.network",
|
|
2521
|
+
prod: DEFAULT_API_URL
|
|
2522
|
+
};
|
|
2523
|
+
function webOriginForApi(apiUrl) {
|
|
2524
|
+
const url = new URL(apiUrl);
|
|
2525
|
+
if (url.hostname === "localhost" || url.hostname === "127.0.0.1") {
|
|
2526
|
+
return `${url.protocol}//${url.hostname}:3000`;
|
|
2527
|
+
}
|
|
2528
|
+
const hostname = url.hostname.startsWith("protocol.") ? url.hostname.slice("protocol.".length) : url.hostname;
|
|
2529
|
+
return `https://${hostname}`;
|
|
2705
2530
|
}
|
|
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
|
-
]);
|
|
2531
|
+
var VERSION = package_default.version;
|
|
2532
|
+
function renderHelp(json) {
|
|
2533
|
+
const help = `Usage: index <command> [args] [options]
|
|
2534
|
+
|
|
2535
|
+
login [local|dev|prod] [--app-url <url>] Authenticate through the matching web app
|
|
2536
|
+
logout Revoke and clear the stored session
|
|
2537
|
+
docs [topic] Read the protocol's canonical guidance
|
|
2538
|
+
agent me Read your selected personal agent
|
|
2539
|
+
profile [show <user-id>|sync|update] Read, research, or edit your profile
|
|
2540
|
+
intent list|show|prepare|create|update|pause|resume|archive|networks|add-to-network|remove-from-network
|
|
2541
|
+
network list|discover|requests|request-update|request-dismiss|show|create|update|delete|join|leave|invite
|
|
2542
|
+
opportunity list|show|accept|reject|start-chat
|
|
2543
|
+
negotiation list [--intent-id <id>] [--state open|settled]
|
|
2544
|
+
negotiation show <opportunity-id>
|
|
2545
|
+
negotiation turn <opportunity-id> --action propose|counter|accept|decline
|
|
2546
|
+
--message <text> --expected-turn-count <n>
|
|
2547
|
+
conversation list|with|show|send|answer|stream
|
|
2548
|
+
conversation show agent --intent-id <id>
|
|
2549
|
+
conversation send agent <text> --intent-id <id> [--question-id <id>]
|
|
2550
|
+
onboarding confirm-profile
|
|
2551
|
+
onboarding complete [--intent-id <id>]
|
|
2552
|
+
scrape <url> [--objective <text>]
|
|
2553
|
+
sync Download profile, networks, and intents
|
|
2554
|
+
|
|
2555
|
+
Global options: --api-url <origin>, --json, --help, --version
|
|
2556
|
+
List options: --archived (intents), --status (opportunities), --limit <n>
|
|
2557
|
+
Intent list options: --query <text> (matches description and summary)
|
|
2558
|
+
Network options: --prompt <text> (create), --title <text> (update)
|
|
2559
|
+
|
|
2560
|
+
Auth: INDEX_SESSION_TOKEN or INDEX_API_KEY, otherwise stored browser login.
|
|
2561
|
+
API origin: --api-url, INDEX_API_URL, stored login URL, production default.
|
|
2562
|
+
Login target: local (localhost:3001), dev (protocol.dev.index.network), prod (default).
|
|
2563
|
+
--json emits one result/error; conversation stream emits NDJSON events.`;
|
|
2564
|
+
console.log(json ? JSON.stringify({ version: VERSION, help }) : `Index CLI ${VERSION}
|
|
2565
|
+
|
|
2566
|
+
${help}`);
|
|
2825
2567
|
}
|
|
2826
2568
|
async function requireAuth(apiUrlOverride) {
|
|
2827
2569
|
const store = new CredentialStore;
|
|
2828
2570
|
const creds = await store.load();
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
const
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2571
|
+
const session = process.env.INDEX_SESSION_TOKEN || undefined;
|
|
2572
|
+
const apiKey = process.env.INDEX_API_KEY || undefined;
|
|
2573
|
+
if (session && apiKey)
|
|
2574
|
+
throw new Error("Set only one of INDEX_SESSION_TOKEN and INDEX_API_KEY");
|
|
2575
|
+
const token = session ?? apiKey ?? creds?.token;
|
|
2576
|
+
if (!token)
|
|
2577
|
+
throw new Error("Not logged in. Run `index login` or set INDEX_SESSION_TOKEN or INDEX_API_KEY.");
|
|
2578
|
+
const apiUrl = apiUrlOverride ?? process.env.INDEX_API_URL ?? creds?.apiUrl ?? DEFAULT_API_URL;
|
|
2579
|
+
return new ApiClient(apiUrl, token, apiKey ? "apiKey" : "session");
|
|
2580
|
+
}
|
|
2581
|
+
async function runLogin(target, apiUrlOverride, appUrlOverride, json) {
|
|
2837
2582
|
const store = new CredentialStore;
|
|
2838
|
-
const apiUrl = apiUrlOverride ?? DEFAULT_API_URL;
|
|
2839
|
-
const appUrl = appUrlOverride ??
|
|
2583
|
+
const apiUrl = apiUrlOverride ?? (target ? LOGIN_API_URLS[target] : undefined) ?? process.env.INDEX_API_URL ?? (await store.load())?.apiUrl ?? DEFAULT_API_URL;
|
|
2584
|
+
const appUrl = appUrlOverride ?? webOriginForApi(apiUrl);
|
|
2840
2585
|
info(`Authenticating with ${apiUrl}...`);
|
|
2841
2586
|
const { authUrl, callbackPromise } = await handleLogin(apiUrl, appUrl, store);
|
|
2842
2587
|
info("Opening browser for authentication...");
|
|
@@ -2863,6 +2608,12 @@ async function runLogin(apiUrlOverride, appUrlOverride) {
|
|
|
2863
2608
|
} catch {}
|
|
2864
2609
|
dim("Waiting for authentication callback...");
|
|
2865
2610
|
const result = await callbackPromise;
|
|
2611
|
+
if (json) {
|
|
2612
|
+
if (!result.success)
|
|
2613
|
+
throw new Error(result.error ?? "Login failed.");
|
|
2614
|
+
console.log(JSON.stringify(result));
|
|
2615
|
+
return;
|
|
2616
|
+
}
|
|
2866
2617
|
if (result.success) {
|
|
2867
2618
|
try {
|
|
2868
2619
|
const creds = await store.load();
|
|
@@ -2880,8 +2631,14 @@ async function runLogin(apiUrlOverride, appUrlOverride) {
|
|
|
2880
2631
|
error(result.error ?? "Login failed.", 1);
|
|
2881
2632
|
}
|
|
2882
2633
|
}
|
|
2883
|
-
async function runLogout() {
|
|
2634
|
+
async function runLogout(json) {
|
|
2884
2635
|
const result = await handleLogout(new CredentialStore);
|
|
2636
|
+
if (json) {
|
|
2637
|
+
console.log(JSON.stringify(result));
|
|
2638
|
+
if (!result.success)
|
|
2639
|
+
process.exitCode = 1;
|
|
2640
|
+
return;
|
|
2641
|
+
}
|
|
2885
2642
|
if (result.success) {
|
|
2886
2643
|
success(result.message);
|
|
2887
2644
|
return;
|
|
@@ -2893,30 +2650,44 @@ async function main() {
|
|
|
2893
2650
|
const args = parseArgs(process.argv.slice(2));
|
|
2894
2651
|
switch (args.command) {
|
|
2895
2652
|
case "help":
|
|
2896
|
-
renderHelp();
|
|
2653
|
+
renderHelp(args.json);
|
|
2897
2654
|
return;
|
|
2898
2655
|
case "version":
|
|
2899
|
-
console.log(VERSION);
|
|
2656
|
+
console.log(args.json ? JSON.stringify({ version: VERSION }) : VERSION);
|
|
2900
2657
|
return;
|
|
2901
2658
|
case "unknown":
|
|
2902
2659
|
error(`Unknown command: ${args.unknown}`, 1);
|
|
2903
2660
|
return;
|
|
2904
2661
|
case "login":
|
|
2905
|
-
await runLogin(args.apiUrl, args.appUrl);
|
|
2662
|
+
await runLogin(args.loginTarget, args.apiUrl, args.appUrl, args.json);
|
|
2906
2663
|
return;
|
|
2907
2664
|
case "logout":
|
|
2908
|
-
await runLogout();
|
|
2665
|
+
await runLogout(args.json);
|
|
2909
2666
|
return;
|
|
2910
2667
|
}
|
|
2911
2668
|
const client = await requireAuth(args.apiUrl);
|
|
2912
2669
|
switch (args.command) {
|
|
2670
|
+
case "docs":
|
|
2671
|
+
await handleDocs(client, args.positionals?.[0], args.json);
|
|
2672
|
+
return;
|
|
2673
|
+
case "agent": {
|
|
2674
|
+
if (args.subcommand !== "me")
|
|
2675
|
+
throw new Error("Usage: index agent me");
|
|
2676
|
+
const selected = await client.getAgent();
|
|
2677
|
+
if (args.json) {
|
|
2678
|
+
console.log(JSON.stringify(selected));
|
|
2679
|
+
return;
|
|
2680
|
+
}
|
|
2681
|
+
agentCard(selected);
|
|
2682
|
+
return;
|
|
2683
|
+
}
|
|
2913
2684
|
case "profile":
|
|
2914
2685
|
await handleProfile(client, args.subcommand, args.subcommand === "search" || args.subcommand === "update" ? args.positionals ?? [] : args.userId ? [args.userId] : [], {
|
|
2915
2686
|
json: args.json,
|
|
2916
|
-
|
|
2917
|
-
|
|
2918
|
-
|
|
2919
|
-
|
|
2687
|
+
name: args.name,
|
|
2688
|
+
intro: args.intro,
|
|
2689
|
+
location: args.location,
|
|
2690
|
+
socials: args.socials
|
|
2920
2691
|
});
|
|
2921
2692
|
return;
|
|
2922
2693
|
case "intent":
|
|
@@ -2926,24 +2697,31 @@ async function main() {
|
|
|
2926
2697
|
archived: args.archived,
|
|
2927
2698
|
limit: args.limit,
|
|
2928
2699
|
json: args.json,
|
|
2929
|
-
targetId: args.targetId
|
|
2700
|
+
targetId: args.targetId,
|
|
2701
|
+
query: args.query,
|
|
2702
|
+
receipt: args.receipt,
|
|
2703
|
+
answers: args.answers
|
|
2930
2704
|
});
|
|
2931
2705
|
return;
|
|
2932
2706
|
case "opportunity":
|
|
2933
2707
|
await handleOpportunity(client, args.subcommand, {
|
|
2934
2708
|
targetId: args.targetId,
|
|
2935
2709
|
status: args.status,
|
|
2710
|
+
statuses: args.statuses,
|
|
2711
|
+
intentId: args.intentId,
|
|
2936
2712
|
limit: args.limit,
|
|
2937
2713
|
json: args.json,
|
|
2938
|
-
positionals: args.positionals
|
|
2939
|
-
acknowledgeUptake: args.acknowledgeUptake
|
|
2714
|
+
positionals: args.positionals
|
|
2940
2715
|
});
|
|
2941
2716
|
return;
|
|
2942
2717
|
case "negotiation":
|
|
2943
2718
|
await handleNegotiation(client, args.subcommand, {
|
|
2944
2719
|
targetId: args.targetId,
|
|
2945
|
-
|
|
2946
|
-
|
|
2720
|
+
intentId: args.intentId,
|
|
2721
|
+
state: args.state,
|
|
2722
|
+
action: args.action,
|
|
2723
|
+
message: args.message,
|
|
2724
|
+
expectedTurnCount: args.expectedTurnCount,
|
|
2947
2725
|
json: args.json
|
|
2948
2726
|
});
|
|
2949
2727
|
return;
|
|
@@ -2957,12 +2735,10 @@ async function main() {
|
|
|
2957
2735
|
case "conversation":
|
|
2958
2736
|
await handleConversation(client, args.subcommand, args.positionals ?? [], {
|
|
2959
2737
|
limit: args.limit,
|
|
2960
|
-
json: args.json
|
|
2961
|
-
|
|
2962
|
-
|
|
2963
|
-
|
|
2964
|
-
await handleContact(client, args.subcommand, args.positionals ?? [], {
|
|
2965
|
-
json: args.json
|
|
2738
|
+
json: args.json,
|
|
2739
|
+
intentId: args.intentId,
|
|
2740
|
+
questionId: args.questionId,
|
|
2741
|
+
answers: args.answers
|
|
2966
2742
|
});
|
|
2967
2743
|
return;
|
|
2968
2744
|
case "scrape":
|
|
@@ -2972,7 +2748,7 @@ async function main() {
|
|
|
2972
2748
|
});
|
|
2973
2749
|
return;
|
|
2974
2750
|
case "onboarding":
|
|
2975
|
-
await handleOnboarding(client, args.subcommand, { json: args.json });
|
|
2751
|
+
await handleOnboarding(client, args.subcommand, { json: args.json, intentId: args.intentId });
|
|
2976
2752
|
return;
|
|
2977
2753
|
case "sync":
|
|
2978
2754
|
await handleSync(client, { json: args.json });
|
|
@@ -2980,5 +2756,9 @@ async function main() {
|
|
|
2980
2756
|
}
|
|
2981
2757
|
}
|
|
2982
2758
|
main().catch((err) => {
|
|
2983
|
-
|
|
2759
|
+
if (process.argv.includes("--json")) {
|
|
2760
|
+
console.log(JSON.stringify(err instanceof ApiError ? { error: err.message, status: err.status, response: err.response } : { error: err instanceof Error ? err.message : String(err) }));
|
|
2761
|
+
process.exitCode = 1;
|
|
2762
|
+
} else
|
|
2763
|
+
error(err instanceof Error ? err.message : String(err), 1);
|
|
2984
2764
|
});
|