@anchrd/intel-api 0.6.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.
Files changed (58) hide show
  1. package/README.md +63 -3
  2. package/dist/adapters/cloudflare/cloudflare.js +102 -37
  3. package/dist/adapters/cloudflare/cloudflare.types.d.ts +20 -0
  4. package/dist/adapters/content/content.d.ts +1 -1
  5. package/dist/adapters/db/db-flows.js +148 -20
  6. package/dist/adapters/db/db-grants.d.ts +13 -2
  7. package/dist/adapters/db/db-grants.js +25 -8
  8. package/dist/adapters/db/db-indexing.d.ts +2 -2
  9. package/dist/adapters/db/db-indexing.js +26 -19
  10. package/dist/adapters/db/db.d.ts +3 -3
  11. package/dist/adapters/db/db.js +442 -118
  12. package/dist/adapters/gate-applications/gate-applications.d.ts +23 -0
  13. package/dist/adapters/gate-applications/gate-applications.js +88 -0
  14. package/dist/adapters/index-queue/index-queue.d.ts +1 -1
  15. package/dist/adapters/index-queue/index-queue.js +2 -2
  16. package/dist/adapters/semantic-index/semantic-index.types.d.ts +2 -2
  17. package/dist/adapters/tool-delegation/tool-delegation.d.ts +22 -0
  18. package/dist/adapters/tool-delegation/tool-delegation.js +90 -0
  19. package/dist/agent-runtime/agent-runtime.d.ts +16 -0
  20. package/dist/agent-runtime/agent-runtime.js +150 -0
  21. package/dist/agent-runtime/agent-runtime.types.d.ts +122 -0
  22. package/dist/bundle/bundle.d.ts +4 -0
  23. package/dist/bundle/bundle.js +1048 -0
  24. package/dist/bundle/bundle.types.d.ts +33 -0
  25. package/dist/bundle/bundle.types.js +1 -0
  26. package/dist/cli/cli.js +10 -1
  27. package/dist/flows/flows.d.ts +8 -8
  28. package/dist/flows/flows.js +158 -42
  29. package/dist/flows/flows.types.d.ts +40 -7
  30. package/dist/http/http.d.ts +1 -0
  31. package/dist/http/http.js +348 -61
  32. package/dist/http/http.types.d.ts +6 -2
  33. package/dist/indexing/indexing.js +14 -2
  34. package/dist/indexing/indexing.types.d.ts +2 -2
  35. package/dist/intel/intel.js +12 -3
  36. package/dist/intel/intel.types.d.ts +6 -2
  37. package/dist/mcp/mcp.js +519 -124
  38. package/dist/mcp/mcp.types.d.ts +11 -2
  39. package/dist/nodes/nodes.d.ts +2 -0
  40. package/dist/nodes/nodes.js +1466 -0
  41. package/dist/nodes/nodes.types.d.ts +402 -0
  42. package/dist/nodes/nodes.types.js +1 -0
  43. package/dist/tools/tool-servers/tool-servers.d.ts +46 -0
  44. package/dist/tools/tool-servers/tool-servers.js +114 -0
  45. package/dist/tools/tools.js +190 -31
  46. package/dist/tools/tools.types.d.ts +23 -1
  47. package/migrations/0011_one_name_for_the_tree.sql +53 -0
  48. package/migrations/0012_table_snapshots.sql +29 -0
  49. package/migrations/0013_agents_in_the_tree.sql +76 -0
  50. package/migrations/0014_agent_applications.sql +25 -0
  51. package/migrations/0015_tools_delegated_from_a_connection.sql +15 -0
  52. package/package.json +3 -2
  53. package/dist/knowledge/knowledge.d.ts +0 -2
  54. package/dist/knowledge/knowledge.js +0 -761
  55. package/dist/knowledge/knowledge.types.d.ts +0 -198
  56. /package/dist/{knowledge/knowledge.types.js → agent-runtime/agent-runtime.types.js} +0 -0
  57. /package/dist/{knowledge → nodes}/document-links/document-links.d.ts +0 -0
  58. /package/dist/{knowledge → nodes}/document-links/document-links.js +0 -0
@@ -26,13 +26,13 @@ function grantBindings(actor, verb, now) {
26
26
  function subtreeWalk(name) {
27
27
  return `${name}(id, parent_id) AS (
28
28
  SELECT seed.id, seed.parent_id
29
- FROM knowledge_nodes seed
29
+ FROM nodes seed
30
30
  WHERE ? = 1
31
31
  OR seed.owner_id = ?
32
32
  OR ${grantExists("seed.id")}
33
33
  UNION
34
34
  SELECT child.id, child.parent_id
35
- FROM knowledge_nodes child
35
+ FROM nodes child
36
36
  JOIN ${name} parent ON child.parent_id = parent.id
37
37
  )`;
38
38
  }
@@ -42,6 +42,23 @@ export const subtreeCte = `WITH RECURSIVE ${subtreeWalk("allowed")}`;
42
42
  export function subtreeBindings(actor, verb, now) {
43
43
  return [actor.isAdmin ? 1 : 0, actor.id, ...grantBindings(actor, verb, now)];
44
44
  }
45
+ /**
46
+ * One named folder and everything filed beneath it, appended to a statement that already carries
47
+ * `subtreeCte`. It answers "where", never "whether": a statement joins `descendants` *in addition
48
+ * to* `allowed`, so the scope can only take rows away from an answer the actor was already entitled
49
+ * to. Joining it instead of `allowed` would turn a search argument into a permission, which is
50
+ * exactly what ADR-0004 forbids — the caller supplies the id, and a caller is not a grant.
51
+ *
52
+ * ⚠️ `UNION`, never `UNION ALL`, for the reason `nodeVerbQuery` gives: a cycle in `parent_id` can
53
+ * reach the table and this walks downwards into it.
54
+ */
55
+ export const descendantsCte = `descendants(id) AS (
56
+ SELECT scope.id FROM nodes scope WHERE scope.id = ?
57
+ UNION
58
+ SELECT child.id
59
+ FROM nodes child
60
+ JOIN descendants parent ON child.parent_id = parent.id
61
+ )`;
45
62
  /**
46
63
  * Both walks in one statement: what the actor may open, and what they may run. Its bindings are
47
64
  * `subtreeBindings(actor, "read", now)` followed by `subtreeBindings(actor, "execute", now)`, in
@@ -62,7 +79,7 @@ export const flowCallable = `(
62
79
  OR flow.parent_id IN (SELECT id FROM runnable)
63
80
  )`;
64
81
  /**
65
- * The point check for one Knowledge node: the node itself and every ancestor above it. Cheaper than
82
+ * The point check for one node: the node itself and every ancestor above it. Cheaper than
66
83
  * the subtree walk and the same answer, because a grant reaches down and never sideways.
67
84
  *
68
85
  * ⚠️ `UNION`, never `UNION ALL`. The service refuses to move a node into its own descendant, but a
@@ -72,10 +89,10 @@ export const flowCallable = `(
72
89
  * row away and the recursion stops on its own.
73
90
  */
74
91
  export const nodeVerbQuery = `WITH RECURSIVE ancestors(id, parent_id, owner_id) AS (
75
- SELECT id, parent_id, owner_id FROM knowledge_nodes WHERE id = ?
92
+ SELECT id, parent_id, owner_id FROM nodes WHERE id = ?
76
93
  UNION
77
94
  SELECT parent.id, parent.parent_id, parent.owner_id
78
- FROM knowledge_nodes parent
95
+ FROM nodes parent
79
96
  JOIN ancestors child ON child.parent_id = parent.id
80
97
  )
81
98
  SELECT 1 AS allowed
@@ -89,18 +106,18 @@ export function nodeVerbBindings(nodeId, actor, verb, now) {
89
106
  }
90
107
  /**
91
108
  * The same question for a flow. A flow carries no grant of its own any more: what reaches it is the
92
- * folder it is filed in and that folder's ancestors. Its owner keeps it, the way a Knowledge node's
109
+ * folder it is filed in and that folder's ancestors. Its owner keeps it, the way a node's
93
110
  * owner keeps theirs — otherwise a flow at the root of the tree would be unreachable by the person
94
111
  * who created it. `UNION` for the same reason as above.
95
112
  */
96
113
  export const flowVerbQuery = `WITH RECURSIVE ancestors(id, parent_id) AS (
97
114
  SELECT folder.id, folder.parent_id
98
- FROM knowledge_nodes folder
115
+ FROM nodes folder
99
116
  JOIN flows flow ON flow.parent_id = folder.id
100
117
  WHERE flow.id = ?
101
118
  UNION
102
119
  SELECT parent.id, parent.parent_id
103
- FROM knowledge_nodes parent
120
+ FROM nodes parent
104
121
  JOIN ancestors child ON child.parent_id = parent.id
105
122
  )
106
123
  SELECT 1 AS allowed
@@ -1,3 +1,3 @@
1
- import type { KnowledgeIndexRepository } from "../../knowledge/knowledge.types.js";
1
+ import type { NodeIndexRepository } from "../../nodes/nodes.types.js";
2
2
  import type { D1Database } from "./db.types.js";
3
- export declare function createKnowledgeIndexRepository(db: D1Database): KnowledgeIndexRepository;
3
+ export declare function createNodeIndexRepository(db: D1Database): NodeIndexRepository;
@@ -3,20 +3,21 @@ function mapTarget(row, contentKeys) {
3
3
  nodeId: row.node_id,
4
4
  versionId: row.version_id,
5
5
  title: row.title,
6
+ description: row.description,
6
7
  contentKeys,
7
8
  mediaType: row.media_type,
8
9
  kind: row.kind,
9
10
  updatedAt: row.updated_at,
10
11
  };
11
12
  }
12
- export function createKnowledgeIndexRepository(db) {
13
+ export function createNodeIndexRepository(db) {
13
14
  return {
14
15
  async getTarget(versionId) {
15
16
  const row = await db
16
- .prepare(`SELECT n.id AS node_id, v.id AS version_id, n.title, v.content_key,
17
+ .prepare(`SELECT n.id AS node_id, v.id AS version_id, n.title, n.description, v.content_key,
17
18
  v.media_type, n.kind, n.updated_at
18
- FROM knowledge_versions v
19
- JOIN knowledge_nodes n ON n.id = v.node_id
19
+ FROM node_versions v
20
+ JOIN nodes n ON n.id = v.node_id
20
21
  WHERE v.id = ? AND n.current_version_id = v.id AND n.archived_at IS NULL`)
21
22
  .bind(versionId)
22
23
  .first();
@@ -24,27 +25,33 @@ export function createKnowledgeIndexRepository(db) {
24
25
  return null;
25
26
  if (row.kind !== "table")
26
27
  return mapTarget(row, [row.content_key]);
27
- // A table's rows live in every version, so indexing the newest one alone would make a search
28
- // find only what the last append added (#40).
28
+ // A table's rows live in every segment since the newest snapshot, so indexing the newest one
29
+ // alone would make a search find only what the last append added (#40) — and indexing the
30
+ // segments before a snapshot would make it find rows a mutation removed (#135). The same
31
+ // reading rule as `listVersionContentKeys`, because the index must describe what a read sees.
29
32
  const segments = await db
30
- .prepare(`SELECT content_key FROM knowledge_versions
31
- WHERE node_id = ? ORDER BY sequence`)
32
- .bind(row.node_id)
33
+ .prepare(`SELECT content_key FROM node_versions
34
+ WHERE node_id = ? AND sequence >= COALESCE((
35
+ SELECT MAX(sequence) FROM node_versions
36
+ WHERE node_id = ? AND segment = 'snapshot'
37
+ ), 0)
38
+ ORDER BY sequence`)
39
+ .bind(row.node_id, row.node_id)
33
40
  .all();
34
41
  return mapTarget(row, (segments.results ?? []).map((segment) => segment.content_key));
35
42
  },
36
43
  async replace(target, content) {
37
44
  await db.batch([
38
45
  db
39
- .prepare(`DELETE FROM knowledge_fts WHERE node_id = ? AND EXISTS (
40
- SELECT 1 FROM knowledge_nodes
46
+ .prepare(`DELETE FROM node_fts WHERE node_id = ? AND EXISTS (
47
+ SELECT 1 FROM nodes
41
48
  WHERE id = ? AND current_version_id = ? AND archived_at IS NULL
42
49
  )`)
43
50
  .bind(target.nodeId, target.nodeId, target.versionId),
44
51
  db
45
- .prepare(`INSERT INTO knowledge_fts (version_id, node_id, title, content)
52
+ .prepare(`INSERT INTO node_fts (version_id, node_id, title, content)
46
53
  SELECT ?, ?, ?, ? WHERE EXISTS (
47
- SELECT 1 FROM knowledge_nodes
54
+ SELECT 1 FROM nodes
48
55
  WHERE id = ? AND current_version_id = ? AND archived_at IS NULL
49
56
  )`)
50
57
  .bind(target.versionId, target.nodeId, target.title, content, target.nodeId, target.versionId),
@@ -52,12 +59,12 @@ export function createKnowledgeIndexRepository(db) {
52
59
  },
53
60
  async markIndexed(versionId, occurredAt) {
54
61
  await db
55
- .prepare(`UPDATE knowledge_index_state
62
+ .prepare(`UPDATE node_index_state
56
63
  SET status = 'indexed', attempt_count = attempt_count + 1,
57
64
  last_error = NULL, updated_at = ?
58
65
  WHERE version_id = ? AND EXISTS (
59
- SELECT 1 FROM knowledge_versions version
60
- JOIN knowledge_nodes node ON node.id = version.node_id
66
+ SELECT 1 FROM node_versions version
67
+ JOIN nodes node ON node.id = version.node_id
61
68
  WHERE version.id = ? AND node.current_version_id = version.id
62
69
  AND node.archived_at IS NULL
63
70
  )`)
@@ -66,11 +73,11 @@ export function createKnowledgeIndexRepository(db) {
66
73
  },
67
74
  async markError(versionId, message, occurredAt) {
68
75
  await db
69
- .prepare(`UPDATE knowledge_index_state
76
+ .prepare(`UPDATE node_index_state
70
77
  SET status = 'error', attempt_count = attempt_count + 1,
71
78
  last_error = ?, updated_at = ? WHERE version_id = ? AND EXISTS (
72
- SELECT 1 FROM knowledge_versions version
73
- JOIN knowledge_nodes node ON node.id = version.node_id
79
+ SELECT 1 FROM node_versions version
80
+ JOIN nodes node ON node.id = version.node_id
74
81
  WHERE version.id = ? AND node.current_version_id = version.id
75
82
  AND node.archived_at IS NULL
76
83
  )`)
@@ -1,6 +1,6 @@
1
- import type { KnowledgeRepository } from "../../knowledge/knowledge.types.js";
1
+ import type { NodeRepository } from "../../nodes/nodes.types.js";
2
2
  import type { D1Database } from "./db.types.js";
3
- export declare function createKnowledgeRepository(deps: {
3
+ export declare function createNodeRepository(deps: {
4
4
  db: D1Database;
5
5
  now(): Date;
6
- }): KnowledgeRepository;
6
+ }): NodeRepository;