@anchrd/intel-api 0.2.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 (114) hide show
  1. package/README.md +96 -0
  2. package/bin/intel.mjs +134 -0
  3. package/dist/adapters/cloudflare/cloudflare-flow-workflow.d.ts +21 -0
  4. package/dist/adapters/cloudflare/cloudflare-flow-workflow.js +39 -0
  5. package/dist/adapters/cloudflare/cloudflare.d.ts +8 -0
  6. package/dist/adapters/cloudflare/cloudflare.js +200 -0
  7. package/dist/adapters/cloudflare/cloudflare.types.d.ts +29 -0
  8. package/dist/adapters/cloudflare/cloudflare.types.js +1 -0
  9. package/dist/adapters/content/content.d.ts +3 -0
  10. package/dist/adapters/content/content.js +22 -0
  11. package/dist/adapters/content/content.types.d.ts +14 -0
  12. package/dist/adapters/content/content.types.js +1 -0
  13. package/dist/adapters/db/db-flows.d.ts +6 -0
  14. package/dist/adapters/db/db-flows.js +466 -0
  15. package/dist/adapters/db/db-indexing.d.ts +3 -0
  16. package/dist/adapters/db/db-indexing.js +70 -0
  17. package/dist/adapters/db/db-oauth.d.ts +3 -0
  18. package/dist/adapters/db/db-oauth.js +26 -0
  19. package/dist/adapters/db/db-tools.d.ts +6 -0
  20. package/dist/adapters/db/db-tools.js +200 -0
  21. package/dist/adapters/db/db.d.ts +6 -0
  22. package/dist/adapters/db/db.js +755 -0
  23. package/dist/adapters/db/db.types.d.ts +16 -0
  24. package/dist/adapters/db/db.types.js +1 -0
  25. package/dist/adapters/document-converter/document-converter.d.ts +2 -0
  26. package/dist/adapters/document-converter/document-converter.js +25 -0
  27. package/dist/adapters/document-converter/document-converter.types.d.ts +9 -0
  28. package/dist/adapters/document-converter/document-converter.types.js +1 -0
  29. package/dist/adapters/flow-runtime/flow-runtime.d.ts +3 -0
  30. package/dist/adapters/flow-runtime/flow-runtime.js +22 -0
  31. package/dist/adapters/flow-runtime/flow-runtime.types.d.ts +19 -0
  32. package/dist/adapters/flow-runtime/flow-runtime.types.js +1 -0
  33. package/dist/adapters/index-queue/index-queue.d.ts +10 -0
  34. package/dist/adapters/index-queue/index-queue.js +12 -0
  35. package/dist/adapters/index-queue/index-queue.types.d.ts +11 -0
  36. package/dist/adapters/index-queue/index-queue.types.js +1 -0
  37. package/dist/adapters/json-schema/json-schema.d.ts +2 -0
  38. package/dist/adapters/json-schema/json-schema.js +31 -0
  39. package/dist/adapters/openid/openid.d.ts +5 -0
  40. package/dist/adapters/openid/openid.js +159 -0
  41. package/dist/adapters/portal-tokens/portal-tokens.d.ts +8 -0
  42. package/dist/adapters/portal-tokens/portal-tokens.js +71 -0
  43. package/dist/adapters/remote-tools/remote-tools.d.ts +5 -0
  44. package/dist/adapters/remote-tools/remote-tools.js +109 -0
  45. package/dist/adapters/semantic-index/semantic-index.d.ts +2 -0
  46. package/dist/adapters/semantic-index/semantic-index.js +57 -0
  47. package/dist/adapters/semantic-index/semantic-index.types.d.ts +32 -0
  48. package/dist/adapters/semantic-index/semantic-index.types.js +1 -0
  49. package/dist/adapters/session-cookie/session-cookie.d.ts +5 -0
  50. package/dist/adapters/session-cookie/session-cookie.js +81 -0
  51. package/dist/adapters/tool-source-policy/tool-source-policy.d.ts +1 -0
  52. package/dist/adapters/tool-source-policy/tool-source-policy.js +22 -0
  53. package/dist/auth/auth.d.ts +2 -0
  54. package/dist/auth/auth.js +176 -0
  55. package/dist/auth/auth.types.d.ts +104 -0
  56. package/dist/auth/auth.types.js +1 -0
  57. package/dist/build/build.d.ts +2 -0
  58. package/dist/build/build.js +125 -0
  59. package/dist/build/build.types.d.ts +17 -0
  60. package/dist/build/build.types.js +1 -0
  61. package/dist/cli/cli.d.ts +4 -0
  62. package/dist/cli/cli.js +141 -0
  63. package/dist/cli/cli.types.d.ts +14 -0
  64. package/dist/cli/cli.types.js +1 -0
  65. package/dist/flows/flows.d.ts +4 -0
  66. package/dist/flows/flows.js +409 -0
  67. package/dist/flows/flows.types.d.ts +108 -0
  68. package/dist/flows/flows.types.js +1 -0
  69. package/dist/http/http.d.ts +8 -0
  70. package/dist/http/http.js +286 -0
  71. package/dist/http/http.types.d.ts +14 -0
  72. package/dist/http/http.types.js +1 -0
  73. package/dist/indexing/indexing.d.ts +6 -0
  74. package/dist/indexing/indexing.js +48 -0
  75. package/dist/indexing/indexing.types.d.ts +10 -0
  76. package/dist/indexing/indexing.types.js +1 -0
  77. package/dist/intel/intel.d.ts +3 -0
  78. package/dist/intel/intel.js +77 -0
  79. package/dist/intel/intel.types.d.ts +14 -0
  80. package/dist/intel/intel.types.js +1 -0
  81. package/dist/knowledge/knowledge.d.ts +2 -0
  82. package/dist/knowledge/knowledge.js +479 -0
  83. package/dist/knowledge/knowledge.types.d.ts +162 -0
  84. package/dist/knowledge/knowledge.types.js +1 -0
  85. package/dist/mcp/mcp.d.ts +2 -0
  86. package/dist/mcp/mcp.js +484 -0
  87. package/dist/mcp/mcp.types.d.ts +10 -0
  88. package/dist/mcp/mcp.types.js +1 -0
  89. package/dist/prepare/prepare.d.ts +4 -0
  90. package/dist/prepare/prepare.js +16 -0
  91. package/dist/prepare/prepare.types.d.ts +9 -0
  92. package/dist/prepare/prepare.types.js +1 -0
  93. package/dist/shared/gate-authorization/gate-authorization.d.ts +4 -0
  94. package/dist/shared/gate-authorization/gate-authorization.js +19 -0
  95. package/dist/shared/intel-error/intel-error.d.ts +5 -0
  96. package/dist/shared/intel-error/intel-error.js +10 -0
  97. package/dist/shared/problem-details/problem-details.d.ts +8 -0
  98. package/dist/shared/problem-details/problem-details.js +4 -0
  99. package/dist/shared/safe-return-path/safe-return-path.d.ts +2 -0
  100. package/dist/shared/safe-return-path/safe-return-path.js +11 -0
  101. package/dist/shared/sha256/sha256.d.ts +1 -0
  102. package/dist/shared/sha256/sha256.js +9 -0
  103. package/dist/tools/tools.d.ts +2 -0
  104. package/dist/tools/tools.js +107 -0
  105. package/dist/tools/tools.types.d.ts +56 -0
  106. package/dist/tools/tools.types.js +1 -0
  107. package/examples/branding/favicon.svg +5 -0
  108. package/examples/branding/logo.svg +5 -0
  109. package/examples/branding/theme.css +16 -0
  110. package/examples/dev.vars.example +7 -0
  111. package/examples/intel.json +9 -0
  112. package/migrations/0000_intel_foundation.sql +203 -0
  113. package/migrations/0001_portal_native_tools.sql +21 -0
  114. package/package.json +62 -0
@@ -0,0 +1,200 @@
1
+ import { ToolAnnotations, ToolCapability, ToolSource, } from "@anchrd/intel-contract";
2
+ const sourceColumns = `source.id, source.name, source.url, source.connection_handle,
3
+ source.enabled, source.created_by, source.created_at, source.updated_at,
4
+ source.last_discovered_at`;
5
+ const catalogColumns = `${sourceColumns}, tool.name AS tool_name, tool.title AS tool_title,
6
+ tool.description AS tool_description, tool.input_schema_json, tool.output_schema_json,
7
+ tool.annotations_json, tool.fingerprint, tool.discovered_at`;
8
+ // Predicate and bindings are produced together: the placeholder count depends on the roles filter,
9
+ // so returning them separately would let a caller shift every binding without the compiler noticing.
10
+ // An empty roles array means "any role", because `IN ()` is invalid SQL.
11
+ function access(actor, now, roles = []) {
12
+ const role = roles.length ? `AND grant_row.role IN (${roles.map(() => "?").join(", ")})` : "";
13
+ return {
14
+ sql: `(source.created_by = ? OR EXISTS (
15
+ SELECT 1 FROM resource_grants grant_row
16
+ WHERE grant_row.resource_type = 'tool-source' AND grant_row.resource_id = source.id
17
+ AND (
18
+ (grant_row.principal_type = 'user' AND grant_row.principal_id = ?)
19
+ OR (grant_row.principal_type = 'email' AND lower(grant_row.principal_id) = lower(?))
20
+ OR (grant_row.principal_type = 'organization' AND grant_row.principal_id = '*')
21
+ )
22
+ ${role}
23
+ AND (grant_row.expires_at IS NULL OR grant_row.expires_at > ?)
24
+ ))`,
25
+ bindings: [actor.id, actor.id, actor.email, ...roles, now],
26
+ };
27
+ }
28
+ function mapSource(row) {
29
+ return ToolSource.parse({
30
+ id: row.id,
31
+ name: row.name,
32
+ url: row.url,
33
+ connectionHandle: row.connection_handle,
34
+ enabled: row.enabled === 1,
35
+ createdBy: row.created_by,
36
+ createdAt: row.created_at,
37
+ updatedAt: row.updated_at,
38
+ lastDiscoveredAt: row.last_discovered_at,
39
+ });
40
+ }
41
+ function mapCapability(row) {
42
+ return ToolCapability.parse({
43
+ sourceId: row.id,
44
+ name: row.tool_name,
45
+ title: row.tool_title,
46
+ description: row.tool_description,
47
+ inputSchema: JSON.parse(row.input_schema_json),
48
+ outputSchema: row.output_schema_json ? JSON.parse(row.output_schema_json) : null,
49
+ annotations: ToolAnnotations.parse(JSON.parse(row.annotations_json)),
50
+ fingerprint: row.fingerprint,
51
+ discoveredAt: row.discovered_at,
52
+ });
53
+ }
54
+ export function createToolRepository(deps) {
55
+ const db = deps.db;
56
+ return {
57
+ async listVisible(actor) {
58
+ const allowed = access(actor, deps.now().toISOString());
59
+ const result = await db
60
+ .prepare(`SELECT ${sourceColumns} FROM tool_sources source
61
+ WHERE ${allowed.sql} ORDER BY lower(source.name), source.id`)
62
+ .bind(...allowed.bindings)
63
+ .all();
64
+ return (result.results ?? []).map(mapSource);
65
+ },
66
+ async getVisible(actor, sourceId) {
67
+ const allowed = access(actor, deps.now().toISOString());
68
+ const row = await db
69
+ .prepare(`SELECT ${sourceColumns} FROM tool_sources source
70
+ WHERE source.id = ? AND ${allowed.sql}`)
71
+ .bind(sourceId, ...allowed.bindings)
72
+ .first();
73
+ return row ? mapSource(row) : null;
74
+ },
75
+ async canManage(actor, sourceId) {
76
+ const permitted = access(actor, deps.now().toISOString(), ["manager"]);
77
+ const row = await db
78
+ .prepare(`SELECT 1 AS allowed FROM tool_sources source
79
+ WHERE source.id = ? AND ${permitted.sql}`)
80
+ .bind(sourceId, ...permitted.bindings)
81
+ .first();
82
+ return row?.allowed === 1;
83
+ },
84
+ async findIdempotent(actorId, operation, key) {
85
+ const row = await db
86
+ .prepare(`SELECT resource_id FROM idempotency_keys
87
+ WHERE actor_id = ? AND operation = ? AND idempotency_key = ?`)
88
+ .bind(actorId, operation, key)
89
+ .first();
90
+ return row?.resource_id ?? null;
91
+ },
92
+ async insertSource(input) {
93
+ const source = input.source;
94
+ try {
95
+ await db.batch([
96
+ db
97
+ .prepare(`INSERT INTO tool_sources (
98
+ id, name, url, connection_handle, enabled, created_by,
99
+ created_at, updated_at, last_discovered_at
100
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
101
+ .bind(source.id, source.name, source.url, source.connectionHandle, source.enabled ? 1 : 0, source.createdBy, source.createdAt, source.updatedAt, source.lastDiscoveredAt),
102
+ db
103
+ .prepare(`INSERT INTO resource_grants (
104
+ id, resource_type, resource_id, principal_type, principal_id, role,
105
+ expires_at, created_by, created_at
106
+ ) VALUES (?, 'tool-source', ?, 'organization', '*', 'viewer', NULL, ?, ?)`)
107
+ .bind(input.grantId, source.id, source.createdBy, source.createdAt),
108
+ db
109
+ .prepare(`INSERT INTO idempotency_keys (
110
+ actor_id, operation, idempotency_key, resource_id, created_at
111
+ ) VALUES (?, 'tools.create', ?, ?, ?)`)
112
+ .bind(source.createdBy, input.idempotencyKey, source.id, source.createdAt),
113
+ db
114
+ .prepare(`INSERT INTO audit_events (
115
+ id, actor_id, action, resource_type, resource_id, metadata_json, occurred_at
116
+ ) VALUES (?, ?, 'tools.create', 'tool-source', ?, ?, ?)`)
117
+ .bind(input.auditId, source.createdBy, source.id, JSON.stringify({ name: source.name, url: source.url }), source.createdAt),
118
+ ]);
119
+ return source;
120
+ }
121
+ catch (error) {
122
+ const replayedId = await this.findIdempotent(source.createdBy, "tools.create", input.idempotencyKey);
123
+ const replayed = replayedId
124
+ ? await db
125
+ .prepare(`SELECT ${sourceColumns} FROM tool_sources source WHERE source.id = ?`)
126
+ .bind(replayedId)
127
+ .first()
128
+ : null;
129
+ if (replayed)
130
+ return mapSource(replayed);
131
+ throw error;
132
+ }
133
+ },
134
+ async replaceCatalog(input) {
135
+ const replayed = await this.findIdempotent(input.actorId, "tools.discover", input.idempotencyKey);
136
+ if (replayed)
137
+ return;
138
+ const statements = [
139
+ db.prepare("DELETE FROM tool_catalog WHERE source_id = ?").bind(input.sourceId),
140
+ ...input.capabilities.map((capability) => db
141
+ .prepare(`INSERT INTO tool_catalog (
142
+ source_id, name, title, description, input_schema_json, output_schema_json,
143
+ annotations_json, fingerprint, discovered_at
144
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`)
145
+ .bind(capability.sourceId, capability.name, capability.title, capability.description, JSON.stringify(capability.inputSchema), capability.outputSchema ? JSON.stringify(capability.outputSchema) : null, JSON.stringify(capability.annotations), capability.fingerprint, capability.discoveredAt)),
146
+ db
147
+ .prepare(`UPDATE tool_sources
148
+ SET last_discovered_at = ?, updated_at = ?
149
+ WHERE id = ?`)
150
+ .bind(input.discoveredAt, input.discoveredAt, input.sourceId),
151
+ db
152
+ .prepare(`INSERT INTO idempotency_keys (
153
+ actor_id, operation, idempotency_key, resource_id, created_at
154
+ ) VALUES (?, 'tools.discover', ?, ?, ?)`)
155
+ .bind(input.actorId, input.idempotencyKey, input.sourceId, input.discoveredAt),
156
+ db
157
+ .prepare(`INSERT INTO audit_events (
158
+ id, actor_id, action, resource_type, resource_id, metadata_json, occurred_at
159
+ ) VALUES (?, ?, 'tools.discover', 'tool-source', ?, ?, ?)`)
160
+ .bind(input.auditId, input.actorId, input.sourceId, JSON.stringify({ toolCount: input.capabilities.length }), input.discoveredAt),
161
+ ];
162
+ try {
163
+ await db.batch(statements);
164
+ }
165
+ catch (error) {
166
+ const concurrentReplay = await this.findIdempotent(input.actorId, "tools.discover", input.idempotencyKey);
167
+ if (concurrentReplay === input.sourceId)
168
+ return;
169
+ throw error;
170
+ }
171
+ },
172
+ async listCatalogVisible(actor) {
173
+ const allowed = access(actor, deps.now().toISOString());
174
+ const result = await db
175
+ .prepare(`SELECT ${catalogColumns}
176
+ FROM tool_catalog tool
177
+ JOIN tool_sources source ON source.id = tool.source_id
178
+ WHERE source.enabled = 1 AND ${allowed.sql}
179
+ ORDER BY lower(source.name), lower(coalesce(tool.title, tool.name)), tool.name`)
180
+ .bind(...allowed.bindings)
181
+ .all();
182
+ return (result.results ?? []).map((row) => ({
183
+ source: mapSource(row),
184
+ capability: mapCapability(row),
185
+ }));
186
+ },
187
+ async getCapabilityVisible(actor, sourceId, name) {
188
+ const allowed = access(actor, deps.now().toISOString());
189
+ const row = await db
190
+ .prepare(`SELECT ${catalogColumns}
191
+ FROM tool_catalog tool
192
+ JOIN tool_sources source ON source.id = tool.source_id
193
+ WHERE source.id = ? AND tool.name = ? AND source.enabled = 1
194
+ AND ${allowed.sql}`)
195
+ .bind(sourceId, name, ...allowed.bindings)
196
+ .first();
197
+ return row ? mapCapability(row) : null;
198
+ },
199
+ };
200
+ }
@@ -0,0 +1,6 @@
1
+ import type { KnowledgeRepository } from "../../knowledge/knowledge.types.js";
2
+ import type { D1Database } from "./db.types.js";
3
+ export declare function createKnowledgeRepository(deps: {
4
+ db: D1Database;
5
+ now(): Date;
6
+ }): KnowledgeRepository;