@anchrd/intel-ui 0.8.7 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/package.json +5 -2
- package/src/agent/agent-avatar/agent-avatar.tsx +34 -0
- package/src/agent/agent-calendar/agent-calendar.tsx +79 -0
- package/src/agent/agent-chat/agent-chat.tsx +116 -0
- package/src/agent/agent-cron/agent-cron.ts +132 -0
- package/src/agent/agent-definition/agent-definition.ts +64 -0
- package/src/agent/agent-entry-title/agent-entry-title.ts +29 -0
- package/src/agent/agent-log/agent-log.tsx +159 -0
- package/src/agent/agent-models/agent-models.ts +63 -0
- package/src/agent/agent-profile/agent-profile.tsx +512 -0
- package/src/agent/agent-state/agent-state.ts +48 -0
- package/src/agent/agent.tsx +361 -0
- package/src/app/app-sidebar/app-sidebar.tsx +2 -2
- package/src/app/app-tree/app-tree.tsx +151 -23
- package/src/app/app.tsx +2 -2
- package/src/app/header-search/header-search.tsx +16 -16
- package/src/app/tree-move/tree-move.tsx +10 -10
- package/src/app/user-footer/user-footer.tsx +7 -1
- package/src/archive/archive.tsx +154 -0
- package/src/components/ui/avatar.tsx +39 -0
- package/src/components/ui/select.tsx +163 -0
- package/src/components/ui/tabs.tsx +52 -0
- package/src/data/agent-runtime/agent-runtime.ts +93 -0
- package/src/data/intel-data-provider/intel-data-provider.ts +206 -120
- package/src/data/intel-data-provider/intel-data-provider.types.ts +112 -54
- package/src/entry-picker/entry-picker.tsx +53 -17
- package/src/flow-runs/flow-runs.tsx +1 -1
- package/src/flows/flows.tsx +20 -20
- package/src/folder-contents/folder-contents.tsx +7 -7
- package/src/graph-pane/graph-pane.tsx +1 -1
- package/src/hooks/use-capabilities.ts +22 -0
- package/src/i18n/en.json +156 -64
- package/src/kind-icon.ts +5 -2
- package/src/{knowledge-editor/knowledge-editor.tsx → node-editor/node-editor.tsx} +20 -20
- package/src/{knowledge-graph → node-graph}/graph-notice.tsx +1 -1
- package/src/{knowledge-graph/knowledge-graph.tsx → node-graph/node-graph.tsx} +4 -4
- package/src/{knowledge-table/knowledge-table.tsx → node-table/node-table.tsx} +14 -14
- package/src/{knowledge/knowledge.tsx → nodes/nodes.tsx} +46 -29
- package/src/resource-menu/resource-menu.tsx +105 -62
- package/src/router/router.tsx +17 -5
- package/src/title-row/title-row.tsx +13 -5
- package/vite.config.ts +4 -0
- /package/src/{knowledge-graph/knowledge-graph.ts → node-graph/node-graph.ts} +0 -0
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
AppendTableRowsInput,
|
|
3
|
+
AppendTableRowsResult,
|
|
4
4
|
ArchiveFlowInput,
|
|
5
|
-
|
|
5
|
+
ArchiveNodeInput,
|
|
6
|
+
BundleImportResult,
|
|
6
7
|
CompleteFlowRunStepInput,
|
|
8
|
+
CreateAgentInput,
|
|
9
|
+
CreatedAgent,
|
|
7
10
|
CreateFlowInput,
|
|
8
|
-
|
|
9
|
-
|
|
11
|
+
CreateNodeInput,
|
|
12
|
+
DefineTableInput,
|
|
10
13
|
Flow,
|
|
11
14
|
FlowDocument,
|
|
12
15
|
FlowList,
|
|
@@ -16,40 +19,50 @@ import {
|
|
|
16
19
|
FlowRunList,
|
|
17
20
|
FlowRunStep,
|
|
18
21
|
FlowValidation,
|
|
19
|
-
|
|
20
|
-
KnowledgeGraph,
|
|
21
|
-
KnowledgeLinkList,
|
|
22
|
-
KnowledgeNode,
|
|
23
|
-
KnowledgeNodeList,
|
|
24
|
-
KnowledgeTable,
|
|
25
|
-
KnowledgeVersionList,
|
|
22
|
+
IntelCapabilities,
|
|
26
23
|
ListFlowRunsInput,
|
|
27
24
|
ListFlowsInput,
|
|
28
|
-
|
|
25
|
+
ListNodesInput,
|
|
26
|
+
Node,
|
|
27
|
+
NodeAgent,
|
|
28
|
+
NodeDocument,
|
|
29
|
+
NodeGraph,
|
|
30
|
+
NodeLinkList,
|
|
31
|
+
NodeList,
|
|
32
|
+
NodeTable,
|
|
33
|
+
NodeVersionList,
|
|
29
34
|
PreviewFlowPublishInput,
|
|
30
35
|
ProblemDetails,
|
|
31
36
|
PublishFlowInput,
|
|
32
37
|
RelationGraph,
|
|
33
38
|
RelationGraphInput,
|
|
34
|
-
|
|
35
|
-
|
|
39
|
+
ResolveNodeLinksInput,
|
|
40
|
+
ResolveNodeLinksResult,
|
|
36
41
|
ResourceGrantList,
|
|
42
|
+
RevokeGrantInput,
|
|
37
43
|
RevokeGrantResult,
|
|
38
|
-
|
|
44
|
+
SaveAgentDefinitionInput,
|
|
45
|
+
SaveAttachmentInput,
|
|
39
46
|
SaveFlowVersionInput,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
SearchKnowledgeResult,
|
|
47
|
+
SaveNodeVersionInput,
|
|
48
|
+
SearchInput,
|
|
49
|
+
SearchResult,
|
|
44
50
|
SessionUser,
|
|
45
|
-
|
|
46
|
-
|
|
51
|
+
ShareInput,
|
|
52
|
+
ShareResult,
|
|
47
53
|
StartFlowRunInput,
|
|
48
54
|
ToolCatalog,
|
|
49
55
|
UpdateFlowInput,
|
|
50
|
-
|
|
56
|
+
UpdateNodeInput,
|
|
51
57
|
} from "@anchrd/intel-contract";
|
|
52
58
|
import type { z } from "zod";
|
|
59
|
+
import {
|
|
60
|
+
AgentManualRun,
|
|
61
|
+
AgentRunDetail,
|
|
62
|
+
AgentRunList,
|
|
63
|
+
AgentState,
|
|
64
|
+
agentRuntimePath,
|
|
65
|
+
} from "@/data/agent-runtime/agent-runtime.ts";
|
|
53
66
|
import { createBrowserSignIn } from "@/data/sign-in/sign-in.ts";
|
|
54
67
|
import type { IntelDataProvider, TreeEntry } from "./intel-data-provider.types.ts";
|
|
55
68
|
|
|
@@ -82,10 +95,10 @@ export function loginPath(returnTo?: string): string {
|
|
|
82
95
|
* copies of this would keep returning something plausible and slowly stop agreeing on what a flow
|
|
83
96
|
* row is (#30).
|
|
84
97
|
*/
|
|
85
|
-
// ⚠️ `openable`
|
|
86
|
-
// (`listTreeChildren`);
|
|
87
|
-
//
|
|
88
|
-
//
|
|
98
|
+
// ⚠️ `openable` defaults to false here — more precisely: unknown. Whoever knows the level sets it
|
|
99
|
+
// (`listTreeChildren`); whoever only builds a single row does not know and therefore claims the
|
|
100
|
+
// more reserved of the two. An arrow that is wrongly missing costs a click on the row; one that
|
|
101
|
+
// is wrongly there costs trust (#59).
|
|
89
102
|
export function flowEntry(flow: Flow, openable = false): TreeEntry {
|
|
90
103
|
return { type: "flow", id: flow.id, title: flow.title, kind: "flow", openable, flow };
|
|
91
104
|
}
|
|
@@ -165,39 +178,42 @@ export function createIntelDataProvider(
|
|
|
165
178
|
// Same rule as `parentId`: only the asked-for case is sent. The default is the server's, and a
|
|
166
179
|
// provider that spells it out anyway would have to be changed whenever the server's is.
|
|
167
180
|
if (query.includeArchived) params.set("includeArchived", "true");
|
|
181
|
+
if (query.archivedOnly) params.set("archivedOnly", "true");
|
|
168
182
|
const search = params.toString();
|
|
169
183
|
return await request(`/flows${search ? `?${search}` : ""}`, FlowList);
|
|
170
184
|
}
|
|
171
185
|
|
|
172
|
-
async function
|
|
173
|
-
|
|
174
|
-
): Promise<z.infer<typeof KnowledgeNodeList>> {
|
|
175
|
-
const query = ListKnowledgeNodesInput.parse(input);
|
|
186
|
+
async function listNodes(input: Partial<ListNodesInput> = {}): Promise<z.infer<typeof NodeList>> {
|
|
187
|
+
const query = ListNodesInput.parse(input);
|
|
176
188
|
const params = new URLSearchParams({ includeArchived: String(query.includeArchived) });
|
|
177
189
|
if (query.parentId !== null) params.set("parentId", query.parentId);
|
|
178
|
-
|
|
190
|
+
// Only the asked-for case travels: `archivedOnly` overrides the folder on the server, so
|
|
191
|
+
// sending it as `false` on every tree read would be noise on the one request it never applies
|
|
192
|
+
// to (#113).
|
|
193
|
+
if (query.archivedOnly) params.set("archivedOnly", "true");
|
|
194
|
+
return await request(`/nodes?${params}`, NodeList);
|
|
179
195
|
}
|
|
180
196
|
|
|
181
197
|
return {
|
|
182
198
|
async getSession() {
|
|
183
199
|
return await request("/session", SessionUser);
|
|
184
200
|
},
|
|
185
|
-
|
|
201
|
+
async getCapabilities() {
|
|
202
|
+
return await request("/capabilities", IntelCapabilities);
|
|
203
|
+
},
|
|
204
|
+
listNodes,
|
|
186
205
|
async listTreeChildren(parentId) {
|
|
187
206
|
// Both sides of one folder, asked for in parallel and merged here rather than on the server:
|
|
188
207
|
// the folder is shared, the two records are not, and no endpoint may return a row that is a
|
|
189
208
|
// bit of both (ADR-0004).
|
|
190
|
-
const [
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
// Leser. Der Baum weiß es damit beim Zeichnen, ohne die Ebene darunter vorzuladen: Das wäre
|
|
196
|
-
// ein Ladevorgang pro Zeile statt pro Ordner.
|
|
197
|
-
const openable = new Set([...knowledge.withChildren, ...flows.withCalls]);
|
|
209
|
+
const [nodes, flows] = await Promise.all([listNodes({ parentId }), listFlows({ parentId })]);
|
|
210
|
+
// ⚠️ Both sides say which of their rows have something to expand (#59) — for THIS reader.
|
|
211
|
+
// The tree therefore knows it while drawing, without preloading the level below: that would
|
|
212
|
+
// be one load per row instead of per folder.
|
|
213
|
+
const openable = new Set([...nodes.withChildren, ...flows.withCalls]);
|
|
198
214
|
const entries: TreeEntry[] = [
|
|
199
|
-
...
|
|
200
|
-
type: "
|
|
215
|
+
...nodes.items.map((node) => ({
|
|
216
|
+
type: "node" as const,
|
|
201
217
|
id: node.id,
|
|
202
218
|
title: node.title,
|
|
203
219
|
kind: node.kind,
|
|
@@ -215,115 +231,125 @@ export function createIntelDataProvider(
|
|
|
215
231
|
left.id.localeCompare(right.id),
|
|
216
232
|
);
|
|
217
233
|
},
|
|
218
|
-
async
|
|
219
|
-
return await request(`/
|
|
234
|
+
async getNode(nodeId) {
|
|
235
|
+
return await request(`/nodes/${encodeURIComponent(nodeId)}`, NodeDocument);
|
|
220
236
|
},
|
|
221
|
-
async
|
|
222
|
-
return await request("/
|
|
237
|
+
async createNodes(input) {
|
|
238
|
+
return await request("/nodes", Node, {
|
|
223
239
|
method: "POST",
|
|
224
|
-
body: JSON.stringify(
|
|
240
|
+
body: JSON.stringify(CreateNodeInput.parse(input)),
|
|
225
241
|
});
|
|
226
242
|
},
|
|
227
|
-
async
|
|
228
|
-
return await request(`/
|
|
243
|
+
async getNodeGraph(limit = 250) {
|
|
244
|
+
return await request(`/nodes/graph?limit=${encodeURIComponent(limit)}`, NodeGraph);
|
|
229
245
|
},
|
|
230
|
-
async
|
|
231
|
-
return await request(`/
|
|
246
|
+
async listNodeLinks(nodeId) {
|
|
247
|
+
return await request(`/nodes/${encodeURIComponent(nodeId)}/links`, NodeLinkList);
|
|
232
248
|
},
|
|
233
249
|
// ⚠️ POST, not GET. The identifiers of the documents a text links to belong in a body: a
|
|
234
250
|
// query string of them would end up in logs and referrers.
|
|
235
|
-
async
|
|
236
|
-
return await request("/
|
|
251
|
+
async resolveNodeLinks(input) {
|
|
252
|
+
return await request("/nodes/links/resolve", ResolveNodeLinksResult, {
|
|
237
253
|
method: "POST",
|
|
238
|
-
body: JSON.stringify(
|
|
254
|
+
body: JSON.stringify(ResolveNodeLinksInput.parse(input)),
|
|
239
255
|
});
|
|
240
256
|
},
|
|
241
|
-
async
|
|
242
|
-
const parsed =
|
|
243
|
-
return await request(
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
);
|
|
257
|
+
async saveNode(input) {
|
|
258
|
+
const parsed = SaveNodeVersionInput.parse(input);
|
|
259
|
+
return await request(`/nodes/${encodeURIComponent(parsed.nodeId)}/versions`, NodeDocument, {
|
|
260
|
+
method: "POST",
|
|
261
|
+
body: JSON.stringify(parsed),
|
|
262
|
+
});
|
|
248
263
|
},
|
|
249
|
-
async
|
|
250
|
-
const parsed =
|
|
251
|
-
return await request(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
);
|
|
264
|
+
async saveNodeAttachment(input) {
|
|
265
|
+
const parsed = SaveAttachmentInput.parse(input);
|
|
266
|
+
return await request(`/nodes/${encodeURIComponent(parsed.nodeId)}/attachment`, NodeDocument, {
|
|
267
|
+
method: "POST",
|
|
268
|
+
body: JSON.stringify(parsed),
|
|
269
|
+
});
|
|
256
270
|
},
|
|
257
|
-
async
|
|
258
|
-
return await (await response(`/
|
|
271
|
+
async getNodeAttachment(nodeId) {
|
|
272
|
+
return await (await response(`/nodes/${encodeURIComponent(nodeId)}/attachment`)).blob();
|
|
273
|
+
},
|
|
274
|
+
async exportNodeBundle(nodeId) {
|
|
275
|
+
const path =
|
|
276
|
+
nodeId === null ? "/nodes/export" : `/nodes/${encodeURIComponent(nodeId)}/export`;
|
|
277
|
+
return await (await response(path)).blob();
|
|
278
|
+
},
|
|
279
|
+
async exportFlowBundle(flowId) {
|
|
280
|
+
return await (await response(`/flows/${encodeURIComponent(flowId)}/export`)).blob();
|
|
281
|
+
},
|
|
282
|
+
// The body IS the zip, so the idempotency key travels as a header — the same reading the
|
|
283
|
+
// server does (#137).
|
|
284
|
+
async importNodeBundle(input) {
|
|
285
|
+
const path =
|
|
286
|
+
input.nodeId === null
|
|
287
|
+
? "/nodes/import"
|
|
288
|
+
: `/nodes/${encodeURIComponent(input.nodeId)}/import`;
|
|
289
|
+
return await request(path, BundleImportResult, {
|
|
290
|
+
method: "POST",
|
|
291
|
+
body: input.zip,
|
|
292
|
+
headers: {
|
|
293
|
+
"content-type": "application/zip",
|
|
294
|
+
"idempotency-key": input.idempotencyKey,
|
|
295
|
+
},
|
|
296
|
+
});
|
|
259
297
|
},
|
|
260
|
-
async
|
|
261
|
-
return await request(`/
|
|
298
|
+
async getNodeTable(nodeId) {
|
|
299
|
+
return await request(`/nodes/${encodeURIComponent(nodeId)}/table`, NodeTable);
|
|
262
300
|
},
|
|
263
|
-
async
|
|
264
|
-
const parsed =
|
|
265
|
-
return await request(
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
method: "POST",
|
|
270
|
-
body: JSON.stringify(parsed),
|
|
271
|
-
},
|
|
272
|
-
);
|
|
301
|
+
async defineTable(input) {
|
|
302
|
+
const parsed = DefineTableInput.parse(input);
|
|
303
|
+
return await request(`/nodes/${encodeURIComponent(parsed.nodeId)}/table`, NodeTable, {
|
|
304
|
+
method: "POST",
|
|
305
|
+
body: JSON.stringify(parsed),
|
|
306
|
+
});
|
|
273
307
|
},
|
|
274
|
-
async
|
|
275
|
-
const parsed =
|
|
308
|
+
async appendTableRows(input) {
|
|
309
|
+
const parsed = AppendTableRowsInput.parse(input);
|
|
276
310
|
return await request(
|
|
277
|
-
`/
|
|
278
|
-
|
|
311
|
+
`/nodes/${encodeURIComponent(parsed.nodeId)}/table/rows`,
|
|
312
|
+
AppendTableRowsResult,
|
|
279
313
|
{ method: "POST", body: JSON.stringify(parsed) },
|
|
280
314
|
);
|
|
281
315
|
},
|
|
282
|
-
async
|
|
283
|
-
return await request(
|
|
284
|
-
`/knowledge/${encodeURIComponent(nodeId)}/versions`,
|
|
285
|
-
KnowledgeVersionList,
|
|
286
|
-
);
|
|
316
|
+
async listNodeVersions(nodeId) {
|
|
317
|
+
return await request(`/nodes/${encodeURIComponent(nodeId)}/versions`, NodeVersionList);
|
|
287
318
|
},
|
|
288
|
-
async
|
|
289
|
-
const parsed =
|
|
290
|
-
return await request(`/
|
|
319
|
+
async updateNode(input) {
|
|
320
|
+
const parsed = UpdateNodeInput.parse(input);
|
|
321
|
+
return await request(`/nodes/${encodeURIComponent(parsed.nodeId)}`, Node, {
|
|
291
322
|
method: "PATCH",
|
|
292
323
|
body: JSON.stringify(parsed),
|
|
293
324
|
});
|
|
294
325
|
},
|
|
295
|
-
async
|
|
296
|
-
const parsed =
|
|
297
|
-
return await request(
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
);
|
|
326
|
+
async archiveNode(input) {
|
|
327
|
+
const parsed = ArchiveNodeInput.parse(input);
|
|
328
|
+
return await request(`/nodes/${encodeURIComponent(parsed.nodeId)}/archive`, Node, {
|
|
329
|
+
method: "POST",
|
|
330
|
+
body: JSON.stringify(parsed),
|
|
331
|
+
});
|
|
302
332
|
},
|
|
303
|
-
async
|
|
304
|
-
return await request("/
|
|
333
|
+
async searchNodes(input) {
|
|
334
|
+
return await request("/nodes/search", SearchResult, {
|
|
305
335
|
method: "POST",
|
|
306
|
-
body: JSON.stringify(
|
|
336
|
+
body: JSON.stringify(SearchInput.parse(input)),
|
|
307
337
|
});
|
|
308
338
|
},
|
|
309
|
-
async
|
|
310
|
-
return await request(
|
|
311
|
-
`/knowledge/${encodeURIComponent(resourceId)}/grants`,
|
|
312
|
-
ResourceGrantList,
|
|
313
|
-
);
|
|
339
|
+
async listGrants(resourceId) {
|
|
340
|
+
return await request(`/nodes/${encodeURIComponent(resourceId)}/grants`, ResourceGrantList);
|
|
314
341
|
},
|
|
315
|
-
async
|
|
316
|
-
const parsed =
|
|
317
|
-
return await request(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
);
|
|
342
|
+
async shareNode(input) {
|
|
343
|
+
const parsed = ShareInput.parse(input);
|
|
344
|
+
return await request(`/nodes/${encodeURIComponent(parsed.resourceId)}/grants`, ShareResult, {
|
|
345
|
+
method: "POST",
|
|
346
|
+
body: JSON.stringify(parsed),
|
|
347
|
+
});
|
|
322
348
|
},
|
|
323
|
-
async
|
|
324
|
-
const parsed =
|
|
349
|
+
async revokeGrant(input) {
|
|
350
|
+
const parsed = RevokeGrantInput.parse(input);
|
|
325
351
|
return await request(
|
|
326
|
-
`/
|
|
352
|
+
`/nodes/${encodeURIComponent(parsed.resourceId)}/grants/${encodeURIComponent(parsed.grantId)}/revoke`,
|
|
327
353
|
RevokeGrantResult,
|
|
328
354
|
{ method: "POST", body: JSON.stringify(parsed) },
|
|
329
355
|
);
|
|
@@ -435,6 +461,66 @@ export function createIntelDataProvider(
|
|
|
435
461
|
async listTools() {
|
|
436
462
|
return await request("/tools", ToolCatalog);
|
|
437
463
|
},
|
|
464
|
+
async getAgent(nodeId) {
|
|
465
|
+
return await request(`/nodes/${encodeURIComponent(nodeId)}/agent`, NodeAgent);
|
|
466
|
+
},
|
|
467
|
+
// ⚠️ `CreatedAgent`, not `NodeAgent`: the create answer carries the Gate application key once
|
|
468
|
+
// (#182), and the read schema is strict — parsing this response with it would reject the one
|
|
469
|
+
// response in the product that has a credential in it.
|
|
470
|
+
async createAgent(input) {
|
|
471
|
+
return await request("/nodes/agents", CreatedAgent, {
|
|
472
|
+
method: "POST",
|
|
473
|
+
body: JSON.stringify(CreateAgentInput.parse(input)),
|
|
474
|
+
});
|
|
475
|
+
},
|
|
476
|
+
async saveAgentDefinition(input) {
|
|
477
|
+
const parsed = SaveAgentDefinitionInput.parse(input);
|
|
478
|
+
return await request(`/nodes/${encodeURIComponent(parsed.nodeId)}/agent`, NodeAgent, {
|
|
479
|
+
method: "POST",
|
|
480
|
+
body: JSON.stringify(parsed),
|
|
481
|
+
});
|
|
482
|
+
},
|
|
483
|
+
/**
|
|
484
|
+
* The agent runtime, asked through intel (#178).
|
|
485
|
+
*
|
|
486
|
+
* ⚠️ Plain `request`, with no second origin and no bearer of its own — that is the whole change.
|
|
487
|
+
* The runtime used to be a Worker this page called directly, which meant CORS it does not
|
|
488
|
+
* answer and a Gate token the browser cannot have. Intel now proxies `/agents/:agentId/*` and
|
|
489
|
+
* attaches the caller's own token server-side, so a 401 from here really is intel's session
|
|
490
|
+
* expiring and the sign-in that follows is the right one.
|
|
491
|
+
*
|
|
492
|
+
* ⚠️ A 403 is NOT that. It means the reader may not drive agents, which the agent page renders
|
|
493
|
+
* as an answer rather than as a failure.
|
|
494
|
+
*/
|
|
495
|
+
async listAgentRuns(agentId) {
|
|
496
|
+
return await request(agentRuntimePath(agentId, "/runs"), AgentRunList);
|
|
497
|
+
},
|
|
498
|
+
async getAgentRun(agentId, runId) {
|
|
499
|
+
return await request(
|
|
500
|
+
agentRuntimePath(agentId, `/runs/${encodeURIComponent(runId)}`),
|
|
501
|
+
AgentRunDetail,
|
|
502
|
+
);
|
|
503
|
+
},
|
|
504
|
+
async getAgentState(agentId) {
|
|
505
|
+
return await request(agentRuntimePath(agentId, "/state"), AgentState);
|
|
506
|
+
},
|
|
507
|
+
async pauseAgent(agentId) {
|
|
508
|
+
return await request(agentRuntimePath(agentId, "/pause"), AgentState, { method: "POST" });
|
|
509
|
+
},
|
|
510
|
+
async resumeAgent(agentId) {
|
|
511
|
+
return await request(agentRuntimePath(agentId, "/resume"), AgentState, { method: "POST" });
|
|
512
|
+
},
|
|
513
|
+
async runAgentNow(agentId, target) {
|
|
514
|
+
return await request(agentRuntimePath(agentId, "/run"), AgentManualRun, {
|
|
515
|
+
method: "POST",
|
|
516
|
+
body: JSON.stringify({ target }),
|
|
517
|
+
});
|
|
518
|
+
},
|
|
519
|
+
agentChatApi(agentId) {
|
|
520
|
+
// assistant-ui dials this itself, so it needs the path a browser can use — the same one every
|
|
521
|
+
// other call above goes to, intel's own `/api/v1`.
|
|
522
|
+
return `${baseUrl}/api/v1${agentRuntimePath(agentId, "/chat")}`;
|
|
523
|
+
},
|
|
438
524
|
|
|
439
525
|
// The Worker serves the connect route, so this navigation belongs to the data layer for the
|
|
440
526
|
// same reason `loginPath` does. `silent=1` is what makes it a redirect nobody has to watch.
|