@anchrd/intel-api 0.14.0 → 0.15.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.
Files changed (51) hide show
  1. package/dist/adapters/cloudflare/cloudflare.js +0 -68
  2. package/dist/adapters/cloudflare/cloudflare.types.d.ts +0 -39
  3. package/dist/adapters/db/db-flows.js +1 -1
  4. package/dist/adapters/db/db-grants.js +1 -1
  5. package/dist/adapters/db/db.js +16 -113
  6. package/dist/bundle/bundle.js +28 -141
  7. package/dist/cli/cli.js +3 -9
  8. package/dist/http/http.js +1 -206
  9. package/dist/http/http.types.d.ts +0 -8
  10. package/dist/indexing/indexing.js +18 -89
  11. package/dist/intel/intel.js +4 -9
  12. package/dist/intel/intel.types.d.ts +0 -6
  13. package/dist/mcp/mcp.js +3 -292
  14. package/dist/mcp/mcp.types.d.ts +2 -7
  15. package/dist/nodes/document-links/document-links.d.ts +6 -8
  16. package/dist/nodes/document-links/document-links.js +8 -31
  17. package/dist/nodes/nodes.js +20 -886
  18. package/dist/nodes/nodes.types.d.ts +10 -169
  19. package/dist/tools/tools.js +37 -148
  20. package/dist/tools/tools.types.d.ts +0 -21
  21. package/migrations/0018_no_context_policy_at_last.sql +13 -6
  22. package/migrations/0019_one_name_for_the_grants.sql +52 -0
  23. package/package.json +2 -2
  24. package/dist/adapters/cloudflare-api/cloudflare-api.d.ts +0 -22
  25. package/dist/adapters/cloudflare-api/cloudflare-api.js +0 -306
  26. package/dist/adapters/cloudflare-api/cloudflare-api.types.d.ts +0 -64
  27. package/dist/adapters/cloudflare-api/cloudflare-api.types.js +0 -1
  28. package/dist/adapters/gate-applications/gate-applications.d.ts +0 -23
  29. package/dist/adapters/gate-applications/gate-applications.js +0 -88
  30. package/dist/adapters/tool-delegation/tool-delegation.d.ts +0 -22
  31. package/dist/adapters/tool-delegation/tool-delegation.js +0 -90
  32. package/dist/agent-costs/agent-costs.d.ts +0 -16
  33. package/dist/agent-costs/agent-costs.js +0 -105
  34. package/dist/agent-costs/agent-costs.types.d.ts +0 -30
  35. package/dist/agent-costs/agent-costs.types.js +0 -1
  36. package/dist/agent-runtime/agent-runtime.d.ts +0 -16
  37. package/dist/agent-runtime/agent-runtime.js +0 -150
  38. package/dist/agent-runtime/agent-runtime.types.d.ts +0 -122
  39. package/dist/agent-runtime/agent-runtime.types.js +0 -1
  40. package/dist/model-catalog/model-catalog.d.ts +0 -2
  41. package/dist/model-catalog/model-catalog.js +0 -99
  42. package/dist/model-catalog/model-catalog.types.d.ts +0 -15
  43. package/dist/model-catalog/model-catalog.types.js +0 -1
  44. package/dist/nodes/board/board.d.ts +0 -61
  45. package/dist/nodes/board/board.js +0 -826
  46. package/dist/nodes/board/board.types.d.ts +0 -38
  47. package/dist/nodes/board/board.types.js +0 -1
  48. package/migrations/0013_agents_in_the_tree.sql +0 -76
  49. package/migrations/0014_agent_applications.sql +0 -25
  50. package/migrations/0015_tools_delegated_from_a_connection.sql +0 -15
  51. package/migrations/0016_boards_in_the_tree.sql +0 -80
package/dist/mcp/mcp.js CHANGED
@@ -1,5 +1,5 @@
1
- import { AddBoardTaskInput, AppendTableRowsInput, ArchiveFlowInput, ArchiveNodeInput, CancelFlowRunInput, CompleteFlowRunStepInput, ConfigureBoardInput, CreateAgentInput, CreateFlowInput, CreateNodeInput, DefineTableInput, DeleteBoardTaskInput, DeleteTableRowsInput, ExecuteToolInput, GetAgentInput, GetBoardInput, GetFlowInput, GetFlowRunInput, GetFlowVersionInput, GetNodeInput, GetNodeVersionInput, GetTableInput, IntelId, ListAgentsInput, ListFlowRunsInput, ListFlowsInput, ListGrantsInput, ListNodesInput, MoveBoardTaskInput, NodeGraphInput, PauseAgentInput, PreviewFlowPublishInput, PublishFlowInput, RedefineTableInput, RelationGraphInput, RepairBoardTaskIdsInput, ResolveNodeLinksInput, RevokeGrantInput, RotateAgentKeyInput, RunAgentNowInput, SaveAgentDefinitionInput, SaveAttachmentInput, SaveFlowVersionInput, SaveNodeVersionInput, SearchInput, ShareInput, StartFlowRunInput, TestToolInput, UnpublishFlowInput, UpdateBoardTaskInput, UpdateFlowInput, UpdateNodeInput, UpdateTableRowsInput, } from "@anchrd/intel-contract";
2
- import { McpServer, ResourceTemplate, } from "@modelcontextprotocol/sdk/server/mcp.js";
1
+ import { AppendTableRowsInput, ArchiveFlowInput, ArchiveNodeInput, CancelFlowRunInput, CompleteFlowRunStepInput, CreateFlowInput, CreateNodeInput, DefineTableInput, DeleteTableRowsInput, ExecuteToolInput, GetFlowInput, GetFlowRunInput, GetFlowVersionInput, GetNodeInput, GetNodeVersionInput, GetTableInput, IntelId, ListFlowRunsInput, ListFlowsInput, ListGrantsInput, ListNodesInput, NodeGraphInput, PreviewFlowPublishInput, PublishFlowInput, RedefineTableInput, RelationGraphInput, ResolveNodeLinksInput, RevokeGrantInput, SaveAttachmentInput, SaveFlowVersionInput, SaveNodeVersionInput, SearchInput, ShareInput, StartFlowRunInput, TestToolInput, UnpublishFlowInput, UpdateFlowInput, UpdateNodeInput, UpdateTableRowsInput, } from "@anchrd/intel-contract";
2
+ import { McpServer, ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { WebStandardStreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
4
4
  import { z } from "zod";
5
5
  import { permits } from "../shared/gate-authorization/gate-authorization.js";
@@ -61,12 +61,6 @@ export async function handleMcp(request, deps) {
61
61
  canReadFlows: permits(deps.authorization, "flows", "read"),
62
62
  canCreateFlows: permits(deps.authorization, "flows", "create"),
63
63
  };
64
- const agentActor = {
65
- id: deps.authorization.identity.id,
66
- email: deps.authorization.identity.email,
67
- isAdmin: deps.authorization.can("intel", "admin"),
68
- canRun: permits(deps.authorization, "agents", "run"),
69
- };
70
64
  const server = new McpServer({ name: "intel", version: "0.1.0" });
71
65
  const EmptyInput = z.strictObject({});
72
66
  // `null` is the root: the whole tree as this caller may read it. The field is required rather
@@ -213,33 +207,6 @@ export async function handleMcp(request, deps) {
213
207
  openWorldHint: false,
214
208
  },
215
209
  }, async (input) => text(await deps.nodes.search(actor, input)));
216
- // ⚠️ Plain `registerTool` and no alias: these tools are new with #139 and never had a
217
- // `knowledge_` name, so inventing one would create a deprecated name that was never used —
218
- // and #149, which removes the aliases, would then have one more thing to remove.
219
- server.registerTool("agent_list", {
220
- title: "List agents",
221
- description: "List the authorized agents, over the whole tree or under one folder. Omit parentId for every agent, pass null for the root level.",
222
- inputSchema: ListAgentsInput,
223
- annotations: {
224
- title: "List agents",
225
- readOnlyHint: true,
226
- destructiveHint: false,
227
- idempotentHint: true,
228
- openWorldHint: false,
229
- },
230
- }, async (input) => text(await deps.nodes.listAgents(actor, input)));
231
- server.registerTool("agent_get", {
232
- title: "Get agent",
233
- description: "Read one authorized agent with its current definition: the nodes it references and their role, its schedules, and its model.",
234
- inputSchema: GetAgentInput,
235
- annotations: {
236
- title: "Get agent",
237
- readOnlyHint: true,
238
- destructiveHint: false,
239
- idempotentHint: true,
240
- openWorldHint: false,
241
- },
242
- }, async (input) => text(await deps.nodes.getAgent(actor, input)));
243
210
  server.registerTool("node_table_get", {
244
211
  title: "Get node table",
245
212
  description: "Read one authorized table as column names and rows.",
@@ -252,21 +219,6 @@ export async function handleMcp(request, deps) {
252
219
  openWorldHint: false,
253
220
  },
254
221
  }, async (input) => text(await deps.nodes.getTable(actor, input.nodeId)));
255
- // A board answers whole: the statuses and every task, in one read. There is no per-task read
256
- // beside it, because a card is small and the interesting question is almost always about
257
- // several of them at once — what is in review, what waits for what (#285).
258
- server.registerTool("board_get", {
259
- title: "Get board",
260
- description: "Read one authorized board: its status list and every task with its full field set. A board that has never been written answers with the default statuses and no tasks.",
261
- inputSchema: GetBoardInput,
262
- annotations: {
263
- title: "Get board",
264
- readOnlyHint: true,
265
- destructiveHint: false,
266
- idempotentHint: true,
267
- openWorldHint: false,
268
- },
269
- }, async (input) => text(await deps.nodes.getBoard(actor, input)));
270
222
  server.registerTool("node_links_list", {
271
223
  title: "List node links",
272
224
  description: "List authorized outgoing links and backlinks for one node.",
@@ -356,65 +308,8 @@ export async function handleMcp(request, deps) {
356
308
  openWorldHint: false,
357
309
  },
358
310
  }, async (input) => text(await deps.nodes.create(actor, input)));
359
- /**
360
- * ⚠️ There is no longer ANY tool result in Intel that contains a secret, and that is the whole
361
- * of D29 seen from here. Until #207 this one tool answered with the Application key in plain
362
- * text — a deliberate exception, because the result WAS the credential and a redacted answer
363
- * would have meant "an agent you can create but never run". The exception is gone rather than
364
- * weakened: the key now travels from Gate into the agent runtime over Intel's service binding
365
- * inside this call, so there is nothing left to hand to a model. `agent_create`, `agent_get`,
366
- * `agent_list` and every node read answer with `applicationId` alone, which names the principal
367
- * without authenticating it.
368
- */
369
- server.registerTool("agent_create", {
370
- title: "Create agent",
371
- description: "Create an agent node with its first definition, and the Gate application it runs as. The definition names nodes and their role, schedules and a model — never accounts, secrets or channels. The agent's application key is handed to the agent runtime internally and never appears in this result; the agent can run straight away. A repeated idempotency key returns the existing agent and mints nothing.",
372
- inputSchema: CreateAgentInput,
373
- annotations: {
374
- title: "Create agent",
375
- readOnlyHint: false,
376
- destructiveHint: false,
377
- idempotentHint: true,
378
- // Creating an agent creates a principal in Gate, which is a system outside Intel.
379
- openWorldHint: true,
380
- },
381
- }, async (input) => text(await deps.nodes.createAgent(actor, input, { token: deps.bearer })));
382
311
  }
383
312
  if (permits(deps.authorization, "knowledge", "write")) {
384
- server.registerTool("agent_update", {
385
- title: "Update agent definition",
386
- description: "Append an immutable definition version to an agent using an optimistic base version.",
387
- inputSchema: SaveAgentDefinitionInput,
388
- annotations: {
389
- title: "Update agent definition",
390
- readOnlyHint: false,
391
- destructiveHint: false,
392
- idempotentHint: true,
393
- openWorldHint: false,
394
- },
395
- }, async (input) => text(await deps.nodes.saveAgentDefinition(actor, input, { token: deps.bearer })));
396
- /**
397
- * The MCP half of the "Replace key" action in the agent profile (D29, #207).
398
- *
399
- * ⚠️ `knowledge/write` like `agent_update`, not `agents/run`: which principal an agent acts as
400
- * is a property of the agent, changed by whoever may change the agent. And the result names the
401
- * principal and the moment — never the key, which went to the runtime and nowhere else.
402
- */
403
- server.registerTool("agent_rotate_key", {
404
- title: "Replace an agent's application key",
405
- description: "Issue a new Gate application key for an agent and give it to the agent runtime. The previous key stops working immediately. Use it when a run fails with agent_key_missing, or when a key may have been exposed. The key itself is never returned.",
406
- inputSchema: RotateAgentKeyInput,
407
- annotations: {
408
- title: "Replace an agent's application key",
409
- readOnlyHint: false,
410
- // The old key stops working the moment this runs, and anything still using it breaks.
411
- destructiveHint: true,
412
- // Asking twice issues twice, and the second answer invalidates the first key.
413
- idempotentHint: false,
414
- // The principal lives in Gate, which is a system outside Intel.
415
- openWorldHint: true,
416
- },
417
- }, async (input) => text(await deps.nodes.rotateAgentKey(actor, input, { token: deps.bearer })));
418
313
  server.registerTool("node_save", {
419
314
  title: "Save node version",
420
315
  description: "Append an immutable content version using an optimistic base version.",
@@ -528,93 +423,6 @@ export async function handleMcp(request, deps) {
528
423
  openWorldHint: false,
529
424
  },
530
425
  }, async (input) => text(await deps.nodes.redefineTable(actor, input)));
531
- /**
532
- * The board's write surface (#285). No `knowledge_*` alias on any of them — these are new under
533
- * the post-#125 naming.
534
- *
535
- * ⚠️ Not one of them takes a `baseVersionId`, and the descriptions say so. That is the property
536
- * an agent has to be able to rely on: two agents working the same board at the same time touch
537
- * different tasks, and neither is asked to read the whole board first or to retry a conflict
538
- * that says nothing about what they were doing. The server applies each call by task id to the
539
- * board as it stands at that moment.
540
- */
541
- server.registerTool("board_configure", {
542
- title: "Configure board statuses",
543
- description: 'Write the board\'s whole status list, in the order it should be drawn. Adding, renaming and reordering columns are all this call. The "archived" status is part of every board and cannot be removed, and a status that tasks still sit in cannot be removed either. Set "terminal" on a column to say that standing in it means the work is finished — that is what decides whether a task waiting on another is still blocked. Several columns may be terminal; "archived" always is and cannot be set otherwise. Omitting it leaves an ordinary column not terminal.',
544
- inputSchema: ConfigureBoardInput,
545
- annotations: {
546
- title: "Configure board statuses",
547
- readOnlyHint: false,
548
- // Removing a column is possible here, so this is not a purely additive write.
549
- destructiveHint: true,
550
- idempotentHint: true,
551
- openWorldHint: false,
552
- },
553
- }, async (input) => text(await deps.nodes.configureBoard(actor, input)));
554
- server.registerTool("board_task_add", {
555
- title: "Add board task",
556
- description: "Add one task to a board. The server assigns its id and its place in the order; name afterTaskId or beforeTaskId to put it between two cards, or neither to put it last in its column. parentId makes it a subtask of another task on the same board, dependsOn names tasks of the same board it waits for, and references names Intel nodes. dependsOn, labels and references are sets: naming the same task, word or node twice is refused rather than quietly folded together. Needs no baseVersionId: tasks are addressed by id, so parallel writers do not collide.",
557
- inputSchema: AddBoardTaskInput,
558
- annotations: {
559
- title: "Add board task",
560
- readOnlyHint: false,
561
- destructiveHint: false,
562
- idempotentHint: true,
563
- openWorldHint: false,
564
- },
565
- }, async (input) => text(await deps.nodes.addBoardTask(actor, input)));
566
- server.registerTool("board_task_update", {
567
- title: "Update board task",
568
- description: "Change what a task says: title, assignee, labels, dates, dependencies, description or references. Where a task SITS — its status, its parent, its order — is board_task_move instead. Every named field replaces its current value whole; fields that are not named stay as they are. dependsOn, labels and references are sets: appending to a list this task already holds is refused rather than quietly folded together, so read the current value before you write it back.",
569
- inputSchema: UpdateBoardTaskInput,
570
- annotations: {
571
- title: "Update board task",
572
- readOnlyHint: false,
573
- // Every named field replaces what stood there; the version history keeps it, the task
574
- // does not.
575
- destructiveHint: true,
576
- idempotentHint: true,
577
- openWorldHint: false,
578
- },
579
- }, async (input) => text(await deps.nodes.updateBoardTask(actor, input)));
580
- server.registerTool("board_task_move", {
581
- title: "Move board task",
582
- description: 'Move one task: into another status, under another parent, or between two neighbours. Archiving a task is this call with status "archived" — there is no separate verb, and nothing is deleted by it. Two moves on two different tasks both go through.',
583
- inputSchema: MoveBoardTaskInput,
584
- annotations: {
585
- title: "Move board task",
586
- readOnlyHint: false,
587
- destructiveHint: false,
588
- idempotentHint: true,
589
- openWorldHint: false,
590
- },
591
- }, async (input) => text(await deps.nodes.moveBoardTask(actor, input)));
592
- server.registerTool("board_task_delete", {
593
- title: "Delete board task",
594
- description: 'Remove a task AND every subtask under it, recursively. The answer counts everything that went, and dependsOn entries in the remaining tasks that pointed at a deleted one are removed with it. To take a task off the board without losing it, move it to the "archived" status instead.',
595
- inputSchema: DeleteBoardTaskInput,
596
- annotations: {
597
- title: "Delete board task",
598
- readOnlyHint: false,
599
- destructiveHint: true,
600
- idempotentHint: true,
601
- openWorldHint: false,
602
- },
603
- }, async (input) => text(await deps.nodes.deleteBoardTask(actor, input)));
604
- server.registerTool("board_repair_task_ids", {
605
- title: "Repair repeated board task ids",
606
- description: "Give a fresh id to every task entry on a board that repeats an id another entry already used. Only a board imported from a hand-written or foreign bundle can hold such a pair, and it cannot be repaired with the other calls: they address a task by id, so they would read, write or remove both entries at once. The first entry under an id keeps it — that is the one every parentId and dependsOn on the board already means — and each later one becomes its own task with everything else it carries, so nothing is lost and no edge is invented. The answer names each pair. A board that names every task once is refused rather than rewritten. Repeated STATUS ids are repaired with board_configure instead, by writing the status list with distinct ids.",
607
- inputSchema: RepairBoardTaskIdsInput,
608
- annotations: {
609
- title: "Repair repeated board task ids",
610
- readOnlyHint: false,
611
- // Nothing is removed and nothing is overwritten: one entry gains an id of its own and
612
- // every other field on every task stays exactly as it stood.
613
- destructiveHint: false,
614
- idempotentHint: true,
615
- openWorldHint: false,
616
- },
617
- }, async (input) => text(await deps.nodes.repairBoardTaskIds(actor, input)));
618
426
  server.registerTool("node_update", {
619
427
  title: "Update node",
620
428
  description: "Rename, move, or describe a node.",
@@ -965,101 +773,6 @@ export async function handleMcp(request, deps) {
965
773
  },
966
774
  }, async (input) => text(await deps.flows.cancelRun(flowActor, input)));
967
775
  }
968
- /**
969
- * Driving an agent, over the same door the screen uses.
970
- *
971
- * ⚠️ The three below are the MCP half of the two head actions on the agent page — the repository's
972
- * "one business layer, three thin surfaces" rule, kept in the same delivery. They call the runtime
973
- * through `deps.agents`, which resolves the resource ACL and forwards the CALLER's bearer; a tool
974
- * that reached the runtime with anything else would be Intel acting as somebody it is not.
975
- */
976
- if (permits(deps.authorization, "agents", "run")) {
977
- server.registerTool("agent_pause", {
978
- title: "Pause agent",
979
- description: "Stop an agent from acting on its own: no schedule fires, no task and no mail is taken. Its chat keeps answering, and nothing is queued up for later.",
980
- inputSchema: PauseAgentInput,
981
- annotations: {
982
- title: "Pause agent",
983
- readOnlyHint: false,
984
- // Nothing is deleted, and yet work that would have happened does not — a client deciding
985
- // whether to ask first has to be told that.
986
- destructiveHint: true,
987
- idempotentHint: true,
988
- openWorldHint: false,
989
- },
990
- }, async (input) => text(await deps.agents.request({
991
- actor: agentActor,
992
- token: deps.bearer,
993
- agentId: input.nodeId,
994
- method: "POST",
995
- path: "/pause",
996
- body: "{}",
997
- })));
998
- server.registerTool("agent_resume", {
999
- title: "Resume agent",
1000
- description: "Let a paused agent act again. Its schedules are armed from the definition as it stands now; nothing that was due while it stood still is caught up.",
1001
- inputSchema: PauseAgentInput,
1002
- annotations: {
1003
- title: "Resume agent",
1004
- readOnlyHint: false,
1005
- destructiveHint: false,
1006
- idempotentHint: true,
1007
- openWorldHint: false,
1008
- },
1009
- }, async (input) => text(await deps.agents.request({
1010
- actor: agentActor,
1011
- token: deps.bearer,
1012
- agentId: input.nodeId,
1013
- method: "POST",
1014
- path: "/resume",
1015
- body: "{}",
1016
- })));
1017
- /**
1018
- * ⚠️ The MCP half of the profile's cost figures, in the same delivery slice — the repository's
1019
- * "every user-visible capability has an Intel MCP equivalent" rule.
1020
- *
1021
- * ⚠️ Under `agents/run` beside pause and resume, not under `knowledge/read`. What an agent
1022
- * spends is as sensitive as what it did, and this answer stands beside the run list rather than
1023
- * beside the node.
1024
- *
1025
- * ⚠️ `status` travels with the numbers and is not flattened away. A client that read an empty
1026
- * `runs` list as "this agent is free" would be reporting a Cloudflare outage as a saving.
1027
- */
1028
- server.registerTool("agent_costs", {
1029
- title: "Agent costs",
1030
- description: "What one agent has actually cost, read from Cloudflare's AI Gateway log: per run, and as a total over the last 7 and 30 days. `status` says whether the numbers were read at all — `not_configured` and `unreadable` both mean no figures, never zero cost. `partial` means the read hit its page limit, so the totals are a floor.",
1031
- inputSchema: PauseAgentInput,
1032
- annotations: {
1033
- title: "Agent costs",
1034
- readOnlyHint: true,
1035
- destructiveHint: false,
1036
- idempotentHint: true,
1037
- openWorldHint: false,
1038
- },
1039
- }, async (input) => text(await deps.agentCosts.read(agentActor, input.nodeId)));
1040
- server.registerTool("agent_run_now", {
1041
- title: "Run agent now",
1042
- description: "Fire one of the agent's own schedules straight away, against the document or flow it names. The run appears in the agent's run list; a target the agent does not schedule is refused.",
1043
- inputSchema: RunAgentNowInput,
1044
- annotations: {
1045
- title: "Run agent now",
1046
- readOnlyHint: false,
1047
- destructiveHint: false,
1048
- // Every run is a new run, so asking twice runs it twice.
1049
- idempotentHint: false,
1050
- // The agent may reach whatever its own definition grants it, so what a run touches is not
1051
- // knowable from this schema.
1052
- openWorldHint: true,
1053
- },
1054
- }, async (input) => text(await deps.agents.request({
1055
- actor: agentActor,
1056
- token: deps.bearer,
1057
- agentId: input.nodeId,
1058
- method: "POST",
1059
- path: "/run",
1060
- body: JSON.stringify({ target: input.target }),
1061
- })));
1062
- }
1063
776
  if (permits(deps.authorization, "tools", "read")) {
1064
777
  server.registerTool("tools_catalog_list", {
1065
778
  title: "List tools",
@@ -1073,9 +786,7 @@ export async function handleMcp(request, deps) {
1073
786
  openWorldHint: false,
1074
787
  },
1075
788
  }, async () => text(await deps.tools.catalog(toolActor)));
1076
- // The MCP twin of the picker in the agent profile (D30): whole servers, so an agent can be
1077
- // given tools from a client instead of from the screen. Assigning and removing is
1078
- // `agent_update` — a delegation is a field of the definition, not a surface of its own.
789
+ // The servers behind the same live list (D30), as the portal itself names them.
1079
790
  server.registerTool("tools_servers_list", {
1080
791
  title: "List tool servers",
1081
792
  description: "List the MCP servers the calling user reaches through the portal, as the portal itself names them. These are the handles an agent definition may delegate.",
@@ -1,6 +1,4 @@
1
1
  import type { Authorized } from "@anchrd/gate-sdk";
2
- import type { AgentCostsService } from "../agent-costs/agent-costs.types.js";
3
- import type { AgentRuntimeService } from "../agent-runtime/agent-runtime.types.js";
4
2
  import type { BundleService } from "../bundle/bundle.types.js";
5
3
  import type { FlowService } from "../flows/flows.types.js";
6
4
  import type { NodeService } from "../nodes/nodes.types.js";
@@ -8,15 +6,12 @@ import type { ToolService } from "../tools/tools.types.js";
8
6
  export interface McpDeps {
9
7
  authorization: Authorized;
10
8
  /**
11
- * The bearer this call was authorized with, forwarded to the agent runtime so a run is driven by
12
- * the caller and not by Intel. Nothing else reads it, and nothing writes it anywhere.
9
+ * The bearer this call was authorized with, passed on where Intel has to speak to Gate as the
10
+ * person asking rather than as itself. Nothing else reads it, and nothing writes it anywhere.
13
11
  */
14
12
  bearer: string;
15
13
  nodes: NodeService;
16
14
  flows: FlowService;
17
15
  tools: ToolService;
18
16
  bundle: BundleService;
19
- agents: AgentRuntimeService;
20
- /** What an agent has cost, out of the AI Gateway log — the MCP half of the profile's figures (#251). */
21
- agentCosts: AgentCostsService;
22
17
  }
@@ -9,14 +9,12 @@
9
9
  * newer editor wrote; a strict parse would turn "I do not recognise this block" into "this document
10
10
  * cannot be saved". What it does not recognise contributes no link, which is the safe half.
11
11
  *
12
- * ⚠️ A board reaches the same link graph, through the same `text` origin (#285). Its links are not
13
- * inline elements but the `references` of its tasks, which is a difference in where they are
14
- * written and not in what they are: somebody put a node id into a body, and the graph has to see it
15
- * from the other side. Reading it here rather than in the board service is what keeps ONE answer to
16
- * "what does this body point at" — the writer (`reconcileTextLinks`) asks this function and does
17
- * not care which kind it is holding.
12
+ * ⚠️ ONE answer to "what does this body point at", whatever kind holds the body: the writer
13
+ * (`reconcileTextLinks`) asks this function and does not care. Until #390 a board answered here
14
+ * too, through the `references` of its tasks a difference in where the ids were written and not
15
+ * in what they were.
18
16
  *
19
- * Content that is neither has no links at all: an attachment, a CSV table or plain markdown carries
20
- * nothing to read.
17
+ * Content that is not a BlockNote document has no links at all: an attachment, a CSV table or plain
18
+ * markdown carries nothing to read.
21
19
  */
22
20
  export declare function documentLinkTargets(mediaType: string, content: string): string[];
@@ -1,5 +1,4 @@
1
- import { BlockNoteDocument, BlockNoteMediaType, BoardDocument, BoardMediaType, DocumentLinkInlineType, } from "@anchrd/intel-contract";
2
- import { upgradeStoredBoard } from "../board/board.js";
1
+ import { BlockNoteDocument, BlockNoteMediaType, DocumentLinkInlineType, } from "@anchrd/intel-contract";
3
2
  function isRecord(value) {
4
3
  return typeof value === "object" && value !== null;
5
4
  }
@@ -31,18 +30,16 @@ function collect(value, found) {
31
30
  * newer editor wrote; a strict parse would turn "I do not recognise this block" into "this document
32
31
  * cannot be saved". What it does not recognise contributes no link, which is the safe half.
33
32
  *
34
- * ⚠️ A board reaches the same link graph, through the same `text` origin (#285). Its links are not
35
- * inline elements but the `references` of its tasks, which is a difference in where they are
36
- * written and not in what they are: somebody put a node id into a body, and the graph has to see it
37
- * from the other side. Reading it here rather than in the board service is what keeps ONE answer to
38
- * "what does this body point at" — the writer (`reconcileTextLinks`) asks this function and does
39
- * not care which kind it is holding.
33
+ * ⚠️ ONE answer to "what does this body point at", whatever kind holds the body: the writer
34
+ * (`reconcileTextLinks`) asks this function and does not care. Until #390 a board answered here
35
+ * too, through the `references` of its tasks a difference in where the ids were written and not
36
+ * in what they were.
40
37
  *
41
- * Content that is neither has no links at all: an attachment, a CSV table or plain markdown carries
42
- * nothing to read.
38
+ * Content that is not a BlockNote document has no links at all: an attachment, a CSV table or plain
39
+ * markdown carries nothing to read.
43
40
  */
44
41
  export function documentLinkTargets(mediaType, content) {
45
- if (mediaType !== BlockNoteMediaType && mediaType !== BoardMediaType)
42
+ if (mediaType !== BlockNoteMediaType)
46
43
  return [];
47
44
  let parsed;
48
45
  try {
@@ -52,26 +49,6 @@ export function documentLinkTargets(mediaType, content) {
52
49
  return [];
53
50
  }
54
51
  const found = new Set();
55
- if (mediaType === BoardMediaType) {
56
- /**
57
- * ⚠️ Upgraded first, like `parseStoredBoard` and `indexing.ts` — this is the FOURTH place a
58
- * board body is parsed, and the only one that cannot complain (anchrd/intel#321).
59
- *
60
- * A board it fails to parse simply has no links, which reads exactly like a board that points
61
- * at nothing — and the reconciliation this feeds removes the links a body no longer names, so
62
- * an unparsed old board would quietly leave the link graph. Every caller hands it a body written
63
- * moments earlier today, so it has never met one; the upgrade is what keeps that from being the
64
- * only reason.
65
- */
66
- const board = BoardDocument.safeParse(upgradeStoredBoard(parsed));
67
- if (!board.success)
68
- return [];
69
- for (const task of board.data.tasks) {
70
- for (const reference of task.references)
71
- found.add(reference);
72
- }
73
- return [...found];
74
- }
75
52
  const document = BlockNoteDocument.safeParse(parsed);
76
53
  if (!document.success)
77
54
  return [];