melchizedek-agents 0.17.0 → 0.19.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 (290) hide show
  1. package/.env.example +35 -3
  2. package/AGENT_SETUP.md +2 -1
  3. package/CHANGELOG.md +929 -0
  4. package/DOCUMENTATION.md +290 -66
  5. package/README.md +42 -1
  6. package/config/agents/examples/harness.yaml +3 -1
  7. package/config/agents/examples/model_zoo.yaml +10 -9
  8. package/config/agents/syndicateSchema.yaml +63 -16
  9. package/config/agents/templates/account_memory.yaml +2 -6
  10. package/config/agents/templates/case_desk.yaml +3 -9
  11. package/config/agents/templates/draft_review.yaml +3 -9
  12. package/config/agents/templates/intake_extractor.yaml +1 -3
  13. package/config/agents/templates/research_brief.yaml +3 -9
  14. package/config/agents/templates/research_desk.yaml +3 -9
  15. package/config/agents/templates/review_panel.yaml +4 -12
  16. package/config/agents/templates/support_triage.yaml +4 -12
  17. package/config/agents/templates/systems_operator.yaml +2 -6
  18. package/db/hardening.sql +10 -3
  19. package/db/migrations/0012_audit_log.sql +98 -0
  20. package/db/migrations/0013_tool_credentials.sql +260 -0
  21. package/dist/lib/a2a/app.d.ts +90 -6
  22. package/dist/lib/a2a/app.js +201 -6
  23. package/dist/lib/a2a/executor.d.ts +54 -7
  24. package/dist/lib/a2a/executor.js +134 -16
  25. package/dist/lib/a2a/remoteAgent.d.ts +24 -9
  26. package/dist/lib/a2a/remoteAgent.js +31 -14
  27. package/dist/lib/compile.d.ts +121 -31
  28. package/dist/lib/compile.js +153 -113
  29. package/dist/lib/compileAdk.d.ts +29 -0
  30. package/dist/lib/compileAdk.js +132 -0
  31. package/dist/lib/compileNative.d.ts +85 -0
  32. package/dist/lib/compileNative.js +222 -0
  33. package/dist/lib/config.d.ts +13 -5
  34. package/dist/lib/config.js +13 -5
  35. package/dist/lib/doctor.js +1 -0
  36. package/dist/lib/index.d.ts +2 -1
  37. package/dist/lib/index.js +2 -1
  38. package/dist/lib/loadEnv.d.ts +5 -0
  39. package/dist/lib/loadEnv.js +7 -0
  40. package/dist/lib/loadSyndicate.d.ts +22 -0
  41. package/dist/lib/memory/erase.d.ts +5 -3
  42. package/dist/lib/memory/erase.js +5 -2
  43. package/dist/lib/memory/namespace.d.ts +8 -1
  44. package/dist/lib/memory/namespace.js +12 -6
  45. package/dist/lib/memory/providers.d.ts +27 -0
  46. package/dist/lib/memory/providers.js +30 -1
  47. package/dist/lib/memory/supabaseMemoryService.d.ts +37 -3
  48. package/dist/lib/memory/supabaseMemoryService.js +42 -2
  49. package/dist/lib/model.d.ts +47 -0
  50. package/dist/lib/model.js +37 -0
  51. package/dist/lib/models/adapterResolver.d.ts +113 -0
  52. package/dist/lib/models/adapterResolver.js +136 -0
  53. package/dist/lib/models/adkGeminiAdapter.d.ts +90 -0
  54. package/dist/lib/models/adkGeminiAdapter.js +367 -0
  55. package/dist/lib/models/adkShim.d.ts +111 -0
  56. package/dist/lib/models/adkShim.js +136 -0
  57. package/dist/lib/models/capabilities.d.ts +3 -0
  58. package/dist/lib/models/capabilities.js +20 -13
  59. package/dist/lib/models/chatCompletionsAdapter.d.ts +279 -0
  60. package/dist/lib/models/chatCompletionsAdapter.js +854 -0
  61. package/dist/lib/models/circuitBreaker.d.ts +42 -0
  62. package/dist/lib/models/circuitBreaker.js +70 -0
  63. package/dist/lib/models/claudeAdapter.d.ts +103 -0
  64. package/dist/lib/models/claudeAdapter.js +669 -0
  65. package/dist/lib/models/claudeLlm.d.ts +39 -62
  66. package/dist/lib/models/claudeLlm.js +44 -349
  67. package/dist/lib/models/claudeModels.d.ts +127 -0
  68. package/dist/lib/models/claudeModels.js +237 -0
  69. package/dist/lib/models/contract.d.ts +395 -0
  70. package/dist/lib/models/contract.js +39 -0
  71. package/dist/lib/models/endpoints.js +2 -1
  72. package/dist/lib/models/errorResponse.d.ts +50 -0
  73. package/dist/lib/models/errorResponse.js +48 -0
  74. package/dist/lib/models/fallback.d.ts +48 -0
  75. package/dist/lib/models/fallback.js +116 -0
  76. package/dist/lib/models/fallbackAdapter.d.ts +55 -0
  77. package/dist/lib/models/fallbackAdapter.js +62 -0
  78. package/dist/lib/models/gateway.js +2 -1
  79. package/dist/lib/models/gatewayAdapter.d.ts +51 -0
  80. package/dist/lib/models/gatewayAdapter.js +81 -0
  81. package/dist/lib/models/gatewayLlm.d.ts +12 -33
  82. package/dist/lib/models/gatewayLlm.js +14 -75
  83. package/dist/lib/models/geminiAdapter.d.ts +123 -0
  84. package/dist/lib/models/geminiAdapter.js +831 -0
  85. package/dist/lib/models/geminiState.d.ts +25 -0
  86. package/dist/lib/models/geminiState.js +25 -0
  87. package/dist/lib/models/genaiMapping.d.ts +263 -0
  88. package/dist/lib/models/genaiMapping.js +862 -0
  89. package/dist/lib/models/gptAdapter.d.ts +240 -0
  90. package/dist/lib/models/gptAdapter.js +804 -0
  91. package/dist/lib/models/gptLlm.d.ts +63 -123
  92. package/dist/lib/models/gptLlm.js +88 -602
  93. package/dist/lib/models/grokAdapter.d.ts +86 -0
  94. package/dist/lib/models/grokAdapter.js +142 -0
  95. package/dist/lib/models/grokLlm.d.ts +22 -45
  96. package/dist/lib/models/grokLlm.js +22 -67
  97. package/dist/lib/models/kimiAdapter.d.ts +157 -0
  98. package/dist/lib/models/kimiAdapter.js +203 -0
  99. package/dist/lib/models/kimiLlm.d.ts +15 -107
  100. package/dist/lib/models/kimiLlm.js +17 -153
  101. package/dist/lib/models/ollamaAdapter.d.ts +125 -0
  102. package/dist/lib/models/ollamaAdapter.js +155 -0
  103. package/dist/lib/models/ollamaLlm.d.ts +11 -107
  104. package/dist/lib/models/ollamaLlm.js +13 -151
  105. package/dist/lib/models/openAiCompatibleLlm.d.ts +73 -216
  106. package/dist/lib/models/openAiCompatibleLlm.js +109 -671
  107. package/dist/lib/models/providerState.d.ts +63 -0
  108. package/dist/lib/models/providerState.js +61 -0
  109. package/dist/lib/models/reasoning.d.ts +26 -0
  110. package/dist/lib/models/reasoning.js +59 -0
  111. package/dist/lib/models/registry.d.ts +58 -35
  112. package/dist/lib/models/registry.js +89 -118
  113. package/dist/lib/models/retry.d.ts +2 -1
  114. package/dist/lib/models/retry.js +3 -2
  115. package/dist/lib/models/schemaNormalize.d.ts +98 -0
  116. package/dist/lib/models/schemaNormalize.js +321 -1
  117. package/dist/lib/models/tracedGemini.d.ts +41 -0
  118. package/dist/lib/models/tracedGemini.js +98 -0
  119. package/dist/lib/models/urls.d.ts +11 -0
  120. package/dist/lib/models/urls.js +16 -0
  121. package/dist/lib/net/redirects.d.ts +21 -2
  122. package/dist/lib/net/redirects.js +11 -34
  123. package/dist/lib/observability/audit.d.ts +25 -0
  124. package/dist/lib/observability/audit.js +39 -0
  125. package/dist/lib/observability/lineage.d.ts +14 -0
  126. package/dist/lib/observability/lineage.js +33 -0
  127. package/dist/lib/observability/metrics.d.ts +6 -0
  128. package/dist/lib/observability/supabaseSpanExporter.d.ts +10 -4
  129. package/dist/lib/observability/supabaseSpanExporter.js +17 -9
  130. package/dist/lib/observability/tracer.d.ts +39 -8
  131. package/dist/lib/observability/tracer.js +59 -20
  132. package/dist/lib/runtime/adkMemoryBridge.d.ts +46 -0
  133. package/dist/lib/runtime/adkMemoryBridge.js +68 -0
  134. package/dist/lib/runtime/adkSessionBridge.d.ts +78 -0
  135. package/dist/lib/runtime/adkSessionBridge.js +176 -0
  136. package/dist/lib/runtime/credentials.d.ts +59 -0
  137. package/dist/lib/runtime/credentials.js +62 -0
  138. package/dist/lib/runtime/events.d.ts +229 -0
  139. package/dist/lib/runtime/events.js +274 -0
  140. package/dist/lib/runtime/logging.d.ts +32 -0
  141. package/dist/lib/runtime/logging.js +55 -0
  142. package/dist/lib/runtime/memoryService.d.ts +72 -0
  143. package/dist/lib/runtime/memoryService.js +25 -0
  144. package/dist/lib/runtime/native/agentLoop.d.ts +203 -0
  145. package/dist/lib/runtime/native/agentLoop.js +687 -0
  146. package/dist/lib/runtime/native/compaction.d.ts +103 -0
  147. package/dist/lib/runtime/native/compaction.js +191 -0
  148. package/dist/lib/runtime/native/delegate.d.ts +98 -0
  149. package/dist/lib/runtime/native/delegate.js +173 -0
  150. package/dist/lib/runtime/native/history.d.ts +83 -0
  151. package/dist/lib/runtime/native/history.js +312 -0
  152. package/dist/lib/runtime/native/interrupts.d.ts +126 -0
  153. package/dist/lib/runtime/native/interrupts.js +291 -0
  154. package/dist/lib/runtime/native/request.d.ts +215 -0
  155. package/dist/lib/runtime/native/request.js +585 -0
  156. package/dist/lib/runtime/native/selfCorrection.d.ts +106 -0
  157. package/dist/lib/runtime/native/selfCorrection.js +253 -0
  158. package/dist/lib/runtime/native/step.d.ts +148 -0
  159. package/dist/lib/runtime/native/step.js +239 -0
  160. package/dist/lib/runtime/native/taskMode.d.ts +64 -0
  161. package/dist/lib/runtime/native/taskMode.js +126 -0
  162. package/dist/lib/runtime/native/telemetry.d.ts +75 -0
  163. package/dist/lib/runtime/native/telemetry.js +299 -0
  164. package/dist/lib/runtime/native/tempState.d.ts +31 -0
  165. package/dist/lib/runtime/native/tempState.js +56 -0
  166. package/dist/lib/runtime/nativeTurn.d.ts +86 -0
  167. package/dist/lib/runtime/nativeTurn.js +107 -0
  168. package/dist/lib/runtime/questions.d.ts +29 -7
  169. package/dist/lib/runtime/questions.js +47 -32
  170. package/dist/lib/runtime/runtimeFlag.d.ts +30 -0
  171. package/dist/lib/runtime/runtimeFlag.js +50 -0
  172. package/dist/lib/runtime/sessions.d.ts +166 -0
  173. package/dist/lib/runtime/sessions.js +201 -0
  174. package/dist/lib/runtime/syndicateTurn.d.ts +44 -6
  175. package/dist/lib/runtime/syndicateTurn.js +205 -33
  176. package/dist/lib/session/supabaseSessionService.d.ts +64 -17
  177. package/dist/lib/session/supabaseSessionService.js +148 -105
  178. package/dist/lib/session/transcript.d.ts +68 -22
  179. package/dist/lib/session/transcript.js +102 -28
  180. package/dist/lib/skills.js +33 -7
  181. package/dist/lib/storage/postgres/credentialStore.d.ts +20 -0
  182. package/dist/lib/storage/postgres/credentialStore.js +82 -0
  183. package/dist/lib/storage/postgres/index.d.ts +15 -0
  184. package/dist/lib/storage/postgres/index.js +7 -0
  185. package/dist/lib/storage/postgres/sessionService.d.ts +43 -15
  186. package/dist/lib/storage/postgres/sessionService.js +128 -66
  187. package/dist/lib/syndicateSchema.d.ts +55 -0
  188. package/dist/lib/syndicateSchema.js +91 -7
  189. package/dist/lib/toolRegistry.d.ts +15 -2
  190. package/dist/lib/toolRegistry.js +33 -17
  191. package/dist/lib/tools/adkTool.d.ts +81 -0
  192. package/dist/lib/tools/adkTool.js +268 -0
  193. package/dist/lib/tools/auth.d.ts +118 -0
  194. package/dist/lib/tools/auth.js +89 -0
  195. package/dist/lib/tools/collectionsSearchTool.d.ts +7 -6
  196. package/dist/lib/tools/collectionsSearchTool.js +11 -26
  197. package/dist/lib/tools/credentialCipher.d.ts +58 -0
  198. package/dist/lib/tools/credentialCipher.js +116 -0
  199. package/dist/lib/tools/credentialStore.d.ts +77 -0
  200. package/dist/lib/tools/credentialStore.js +246 -0
  201. package/dist/lib/tools/examples.d.ts +43 -0
  202. package/dist/lib/tools/examples.js +62 -0
  203. package/dist/lib/tools/generateImageTool.d.ts +15 -6
  204. package/dist/lib/tools/generateImageTool.js +19 -29
  205. package/dist/lib/tools/inspectImageTool.d.ts +9 -6
  206. package/dist/lib/tools/inspectImageTool.js +13 -17
  207. package/dist/lib/tools/mcpToolFactory.d.ts +68 -1
  208. package/dist/lib/tools/mcpToolFactory.js +106 -50
  209. package/dist/lib/tools/memoryTools.d.ts +61 -0
  210. package/dist/lib/tools/memoryTools.js +119 -0
  211. package/dist/lib/tools/nativeTools.d.ts +38 -0
  212. package/dist/lib/tools/nativeTools.js +43 -0
  213. package/dist/lib/tools/oauthConsent.d.ts +181 -0
  214. package/dist/lib/tools/oauthConsent.js +330 -0
  215. package/dist/lib/tools/openapi/call.d.ts +108 -0
  216. package/dist/lib/tools/openapi/call.js +295 -0
  217. package/dist/lib/tools/openapi/parse.d.ts +147 -0
  218. package/dist/lib/tools/openapi/parse.js +570 -0
  219. package/dist/lib/tools/openapiTools.d.ts +31 -17
  220. package/dist/lib/tools/openapiTools.js +150 -117
  221. package/dist/lib/tools/scienceTools.d.ts +14 -14
  222. package/dist/lib/tools/skillToolset.d.ts +58 -87
  223. package/dist/lib/tools/skillToolset.js +61 -142
  224. package/dist/lib/tools/skills/env.d.ts +58 -0
  225. package/dist/lib/tools/skills/env.js +165 -0
  226. package/dist/lib/tools/skills/executor.d.ts +114 -0
  227. package/dist/lib/tools/skills/executor.js +331 -0
  228. package/dist/lib/tools/skills/frontmatter.d.ts +79 -0
  229. package/dist/lib/tools/skills/frontmatter.js +215 -0
  230. package/dist/lib/tools/skills/loader.d.ts +91 -0
  231. package/dist/lib/tools/skills/loader.js +257 -0
  232. package/dist/lib/tools/skills/tools.d.ts +187 -0
  233. package/dist/lib/tools/skills/tools.js +386 -0
  234. package/dist/lib/tools/taskTools.d.ts +15 -15
  235. package/dist/lib/tools/tool.d.ts +354 -0
  236. package/dist/lib/tools/tool.js +304 -0
  237. package/dist/lib/tools/toolContract.d.ts +89 -33
  238. package/dist/lib/tools/toolContract.js +104 -82
  239. package/dist/lib/tools/urlContextTool.d.ts +3 -0
  240. package/dist/lib/tools/urlContextTool.js +5 -1
  241. package/dist/lib/tools/webExtractTool.d.ts +2 -2
  242. package/dist/lib/tools/webExtractTool.js +2 -1
  243. package/dist/lib/tools/webSearchTool.d.ts +6 -9
  244. package/dist/lib/tools/webSearchTool.js +14 -59
  245. package/dist/lib/tools/wikiTools.d.ts +19 -19
  246. package/dist/lib/tools/wikiTools.js +13 -9
  247. package/dist/lib/tools/xApiSearchTool.d.ts +2 -2
  248. package/dist/lib/tools/xApiSearchTool.js +2 -1
  249. package/dist/lib/tools/xSearchTool.d.ts +7 -9
  250. package/dist/lib/tools/xSearchTool.js +11 -62
  251. package/dist/lib/tools/xaiSearchParams.d.ts +41 -0
  252. package/dist/lib/tools/xaiSearchParams.js +126 -0
  253. package/dist/lib/wiki/agentRun.d.ts +12 -0
  254. package/dist/lib/wiki/agentRun.js +72 -34
  255. package/dist/lib/wiki/entities.d.ts +12 -0
  256. package/dist/lib/wiki/entities.js +45 -3
  257. package/dist/lib/workflow/agentNode.d.ts +136 -0
  258. package/dist/lib/workflow/agentNode.js +274 -0
  259. package/dist/lib/workflow/graph.d.ts +177 -0
  260. package/dist/lib/workflow/graph.js +458 -0
  261. package/dist/lib/workflow/nodeEvents.d.ts +50 -0
  262. package/dist/lib/workflow/nodeEvents.js +101 -0
  263. package/dist/lib/workflow/pause.d.ts +122 -0
  264. package/dist/lib/workflow/pause.js +180 -0
  265. package/dist/lib/workflow/resume.d.ts +165 -0
  266. package/dist/lib/workflow/resume.js +440 -0
  267. package/dist/lib/workflow/route.d.ts +58 -0
  268. package/dist/lib/workflow/route.js +69 -0
  269. package/dist/lib/workflow/scheduler.d.ts +415 -0
  270. package/dist/lib/workflow/scheduler.js +743 -0
  271. package/dist/lib/workflow/toolNode.d.ts +127 -0
  272. package/dist/lib/workflow/toolNode.js +236 -0
  273. package/dist/lib/workflow/turn.d.ts +118 -0
  274. package/dist/lib/workflow/turn.js +216 -0
  275. package/dist/lib/workflowConfig.d.ts +3 -2
  276. package/dist/lib/workflowConfig.js +3 -12
  277. package/dist/scripts/a2a_server.js +55 -11
  278. package/dist/scripts/assistant_worker.d.ts +2 -1
  279. package/dist/scripts/assistant_worker.js +9 -4
  280. package/dist/scripts/db.d.ts +9 -0
  281. package/dist/scripts/db.js +30 -15
  282. package/dist/scripts/syndicate_chat.js +19 -10
  283. package/package.json +6 -3
  284. package/skills/briefs/melchizedek-author.md +3 -2
  285. package/skills/briefs/melchizedek-models.md +13 -9
  286. package/skills/briefs/melchizedek.md +3 -3
  287. package/skills/melchizedek/SKILL.md +2 -1
  288. package/skills/melchizedek-author/SKILL.md +2 -1
  289. package/skills/melchizedek-author/assets/minimal.yaml +2 -0
  290. package/skills/melchizedek-models/SKILL.md +23 -6
@@ -0,0 +1,260 @@
1
+ -- ============================================================================
2
+ -- 0013_tool_credentials.sql — third-party OAuth tokens held for tools (ADR 0072)
3
+ -- ============================================================================
4
+ -- A tool that acts for an end user against a third-party API (a calendar, a
5
+ -- repository host, a CRM) needs that user's delegated access, not the
6
+ -- server's own key. melchizedek_tool_credentials holds one token set per
7
+ -- app, end user and provider:
8
+ --
9
+ -- app_name the app the run pins (the root syndicate's memory namespace)
10
+ -- user_id the A2A server's scope key, as sessions and tasks store it
11
+ -- provider the provider's name as the tool asks for it ('github')
12
+ -- scopes what the user granted
13
+ -- access_token_enc, refresh_token_enc
14
+ -- ciphertext only, in the engine's envelope ('mzc1.<key id>.…',
15
+ -- AES-256-GCM by default, lib/tools/credentialCipher.ts). The
16
+ -- CHECK refuses anything else, so a plaintext token cannot be
17
+ -- written by mistake. The key never reaches the database.
18
+ -- key_id which key sealed the row, so a wrong key fails closed by name
19
+ -- expires_at when the access token stops working (NULL: not stated)
20
+ -- version bumped by every write; a refresh writes only over the version
21
+ -- it read, so two instances refreshing at once keep one result
22
+ --
23
+ -- The server's role reads and writes it; no API role can (RLS on, grants
24
+ -- revoked, as db/hardening.sql repeats). melchizedek_erase_scope is replaced
25
+ -- with the 0011 function plus a `credentials` store, so one erase of a user
26
+ -- also removes their tokens (ADR 0020 item 7). Idempotent.
27
+ -- ============================================================================
28
+
29
+ CREATE TABLE IF NOT EXISTS melchizedek_tool_credentials (
30
+ app_name TEXT NOT NULL,
31
+ user_id TEXT NOT NULL,
32
+ provider TEXT NOT NULL,
33
+ scopes TEXT[] NOT NULL DEFAULT '{}',
34
+ access_token_enc TEXT NOT NULL CHECK (access_token_enc ~ '^mzc1[.]'),
35
+ refresh_token_enc TEXT CHECK (refresh_token_enc IS NULL OR refresh_token_enc ~ '^mzc1[.]'),
36
+ key_id TEXT NOT NULL,
37
+ expires_at TIMESTAMPTZ,
38
+ version INTEGER NOT NULL DEFAULT 1,
39
+ created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
40
+ updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
41
+ refreshed_at TIMESTAMPTZ,
42
+ PRIMARY KEY (app_name, user_id, provider)
43
+ );
44
+ -- Erase finds a user's rows across apps.
45
+ CREATE INDEX IF NOT EXISTS idx_melchizedek_tool_credentials_user
46
+ ON melchizedek_tool_credentials (user_id);
47
+
48
+ ALTER TABLE melchizedek_tool_credentials ENABLE ROW LEVEL SECURITY;
49
+ DO $$
50
+ BEGIN
51
+ REVOKE ALL ON melchizedek_tool_credentials FROM PUBLIC;
52
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'anon') THEN
53
+ REVOKE ALL ON melchizedek_tool_credentials FROM anon;
54
+ END IF;
55
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN
56
+ REVOKE ALL ON melchizedek_tool_credentials FROM authenticated;
57
+ END IF;
58
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role') THEN
59
+ GRANT SELECT, INSERT, UPDATE, DELETE ON melchizedek_tool_credentials TO service_role;
60
+ END IF;
61
+ END $$;
62
+
63
+ -- One erase covers the credentials too: the 0011 function, plus the
64
+ -- `credentials` store at the end.
65
+ CREATE OR REPLACE FUNCTION melchizedek_erase_scope(
66
+ p_scope_key text,
67
+ p_namespace text DEFAULT NULL,
68
+ p_include_nested boolean DEFAULT false
69
+ ) RETURNS TABLE(store text, deleted bigint)
70
+ LANGUAGE plpgsql
71
+ SECURITY INVOKER
72
+ SET search_path = public
73
+ AS $$
74
+ DECLARE
75
+ -- LIKE pattern for scopes nested beneath this one, with the scope's own
76
+ -- wildcard characters escaped.
77
+ nested_like text := replace(replace(replace(p_scope_key, '\', '\\'), '%', '\%'), '_', '\_') || '/%';
78
+ contexts text[];
79
+ kept text[];
80
+ traces text[];
81
+ n bigint;
82
+ BEGIN
83
+ IF p_scope_key IS NULL OR btrim(p_scope_key) = '' THEN
84
+ RAISE EXCEPTION 'melchizedek_erase_scope: scope_key is required';
85
+ END IF;
86
+
87
+ -- The conversations (context ids) being erased. With a namespace, they are
88
+ -- the namespace's own session rows; without one, every row of the scope.
89
+ -- adk_sessions.id is '<app_name>:<user_id>:<context id>'.
90
+ SELECT coalesce(array_agg(DISTINCT substr(s.id, length(s.app_name) + length(s.user_id) + 3)), '{}')
91
+ INTO contexts
92
+ FROM adk_sessions s
93
+ WHERE (s.user_id = p_scope_key OR (p_include_nested AND s.user_id LIKE nested_like))
94
+ AND (p_namespace IS NULL OR s.app_name = p_namespace);
95
+
96
+ -- With a namespace: the conversations still live in another namespace,
97
+ -- which are the only ones a namespace erase keeps. Sub-agent rows share
98
+ -- their conversation's id, so excluding `contexts` keeps them with it.
99
+ SELECT coalesce(array_agg(DISTINCT substr(s.id, length(s.app_name) + length(s.user_id) + 3)), '{}')
100
+ INTO kept
101
+ FROM adk_sessions s
102
+ WHERE p_namespace IS NOT NULL
103
+ AND (s.user_id = p_scope_key OR (p_include_nested AND s.user_id LIKE nested_like))
104
+ AND s.app_name <> p_namespace
105
+ AND NOT (substr(s.id, length(s.app_name) + length(s.user_id) + 3) = ANY(contexts));
106
+
107
+ -- Ledger traces of the turns being erased, collected before anything is deleted.
108
+ IF to_regclass('public.adk_turns') IS NOT NULL THEN
109
+ EXECUTE $q$
110
+ SELECT coalesce(array_agg(DISTINCT trace_id), '{}') FROM adk_turns
111
+ WHERE (user_id = $1 OR ($2 AND user_id LIKE $3))
112
+ AND ($4 IS NULL OR session_id IS NULL OR NOT (session_id = ANY($5)))
113
+ $q$ INTO traces USING p_scope_key, p_include_nested, nested_like, p_namespace, kept;
114
+ ELSE
115
+ traces := '{}';
116
+ END IF;
117
+
118
+ -- Memory facts. user_key is '<namespace>/<scope>' and a namespace never
119
+ -- contains '/', so the scope is exactly what follows the first slash.
120
+ DELETE FROM adk_memory_facts f
121
+ WHERE (p_namespace IS NULL OR split_part(f.user_key, '/', 1) = p_namespace)
122
+ AND (substr(f.user_key, strpos(f.user_key, '/') + 1) = p_scope_key
123
+ OR (p_include_nested AND substr(f.user_key, strpos(f.user_key, '/') + 1) LIKE nested_like));
124
+ GET DIAGNOSTICS n = ROW_COUNT;
125
+ store := 'memory_facts'; deleted := n; RETURN NEXT;
126
+
127
+ -- Sessions: every row of the scope in those conversations, whatever app
128
+ -- name ADK gave it (subagents run under their own agent name).
129
+ DELETE FROM adk_sessions s
130
+ WHERE (s.user_id = p_scope_key OR (p_include_nested AND s.user_id LIKE nested_like))
131
+ AND substr(s.id, length(s.app_name) + length(s.user_id) + 3) = ANY(contexts);
132
+ GET DIAGNOSTICS n = ROW_COUNT;
133
+ store := 'sessions'; deleted := n; RETURN NEXT;
134
+
135
+ -- The ledger, when installed.
136
+ IF to_regclass('public.adk_turns') IS NOT NULL THEN
137
+ EXECUTE $q$
138
+ DELETE FROM adk_turns
139
+ WHERE (user_id = $1 OR ($2 AND user_id LIKE $3))
140
+ AND ($4 IS NULL OR session_id IS NULL OR NOT (session_id = ANY($5)))
141
+ $q$ USING p_scope_key, p_include_nested, nested_like, p_namespace, kept;
142
+ GET DIAGNOSTICS n = ROW_COUNT;
143
+ ELSE
144
+ n := 0;
145
+ END IF;
146
+ store := 'turns'; deleted := n; RETURN NEXT;
147
+
148
+ IF to_regclass('public.adk_telemetry') IS NOT NULL THEN
149
+ EXECUTE 'DELETE FROM adk_telemetry WHERE trace_id = ANY($1)' USING traces;
150
+ GET DIAGNOSTICS n = ROW_COUNT;
151
+ ELSE
152
+ n := 0;
153
+ END IF;
154
+ store := 'spans'; deleted := n; RETURN NEXT;
155
+
156
+ IF to_regclass('public.adk_payloads') IS NOT NULL THEN
157
+ EXECUTE 'DELETE FROM adk_payloads WHERE trace_id = ANY($1)' USING traces;
158
+ GET DIAGNOSTICS n = ROW_COUNT;
159
+ ELSE
160
+ n := 0;
161
+ END IF;
162
+ store := 'payloads'; deleted := n; RETURN NEXT;
163
+
164
+ IF to_regclass('public.adk_verdicts') IS NOT NULL THEN
165
+ EXECUTE 'DELETE FROM adk_verdicts WHERE trace_id = ANY($1)' USING traces;
166
+ GET DIAGNOSTICS n = ROW_COUNT;
167
+ ELSE
168
+ n := 0;
169
+ END IF;
170
+ store := 'verdicts'; deleted := n; RETURN NEXT;
171
+
172
+ IF EXISTS (
173
+ SELECT 1 FROM information_schema.columns
174
+ WHERE table_schema = 'public' AND table_name = 'adk_labels' AND column_name = 'trace_id'
175
+ ) THEN
176
+ EXECUTE 'DELETE FROM adk_labels WHERE trace_id = ANY($1)' USING traces;
177
+ GET DIAGNOSTICS n = ROW_COUNT;
178
+ ELSE
179
+ n := 0;
180
+ END IF;
181
+ store := 'labels'; deleted := n; RETURN NEXT;
182
+
183
+ IF to_regclass('public.adk_a2a_tasks') IS NOT NULL THEN
184
+ EXECUTE $q$
185
+ DELETE FROM adk_a2a_tasks
186
+ WHERE (owner = $1 OR ($2 AND owner LIKE $3))
187
+ AND ($4 IS NULL OR context_id IS NULL OR NOT (context_id = ANY($5)))
188
+ $q$ USING p_scope_key, p_include_nested, nested_like, p_namespace, kept;
189
+ GET DIAGNOSTICS n = ROW_COUNT;
190
+ ELSE
191
+ n := 0;
192
+ END IF;
193
+ store := 'tasks'; deleted := n; RETURN NEXT;
194
+
195
+ -- Memory ingestion markers (migration 0007): how far each conversation was
196
+ -- distilled. They carry the scope's key and its conversation ids.
197
+ IF to_regclass('public.melchizedek_memory_ingest') IS NOT NULL THEN
198
+ EXECUTE $q$
199
+ DELETE FROM melchizedek_memory_ingest m
200
+ WHERE ($1 IS NULL OR split_part(m.user_key, '/', 1) = $1)
201
+ AND (substr(m.user_key, strpos(m.user_key, '/') + 1) = $2
202
+ OR ($3 AND substr(m.user_key, strpos(m.user_key, '/') + 1) LIKE $4))
203
+ $q$ USING p_namespace, p_scope_key, p_include_nested, nested_like;
204
+ GET DIAGNOSTICS n = ROW_COUNT;
205
+ ELSE
206
+ n := 0;
207
+ END IF;
208
+ store := 'memory_markers'; deleted := n; RETURN NEXT;
209
+
210
+ -- The task tools' list and job queue (migration 0009), per caller across
211
+ -- every syndicate: erased with the whole scope, kept by a namespace erase.
212
+ n := 0;
213
+ IF p_namespace IS NULL AND to_regclass('public.melchizedek_tasks') IS NOT NULL THEN
214
+ EXECUTE $q$
215
+ DELETE FROM melchizedek_tasks WHERE owner = $1 OR ($2 AND owner LIKE $3)
216
+ $q$ USING p_scope_key, p_include_nested, nested_like;
217
+ GET DIAGNOSTICS n = ROW_COUNT;
218
+ EXECUTE $q$
219
+ DELETE FROM melchizedek_task_owners WHERE owner = $1 OR ($2 AND owner LIKE $3)
220
+ $q$ USING p_scope_key, p_include_nested, nested_like;
221
+ END IF;
222
+ store := 'task_tools'; deleted := n; RETURN NEXT;
223
+
224
+ -- Third-party credentials held for the scope's tools (this migration).
225
+ -- They are filed per app (the memory namespace the run pins), so a
226
+ -- namespace erase removes that app's and keeps the others; an erase
227
+ -- without one removes every app's.
228
+ IF to_regclass('public.melchizedek_tool_credentials') IS NOT NULL THEN
229
+ EXECUTE $q$
230
+ DELETE FROM melchizedek_tool_credentials c
231
+ WHERE ($1 IS NULL OR c.app_name = $1)
232
+ AND (c.user_id = $2 OR ($3 AND c.user_id LIKE $4))
233
+ $q$ USING p_namespace, p_scope_key, p_include_nested, nested_like;
234
+ GET DIAGNOSTICS n = ROW_COUNT;
235
+ ELSE
236
+ n := 0;
237
+ END IF;
238
+ store := 'credentials'; deleted := n; RETURN NEXT;
239
+ END;
240
+ $$;
241
+
242
+ -- No API role may execute it (db/hardening.sql repeats this for every
243
+ -- melchizedek function); the server's role gets it back.
244
+ DO $$
245
+ BEGIN
246
+ REVOKE ALL ON FUNCTION melchizedek_erase_scope(text, text, boolean) FROM PUBLIC;
247
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'anon') THEN
248
+ REVOKE ALL ON FUNCTION melchizedek_erase_scope(text, text, boolean) FROM anon;
249
+ END IF;
250
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'authenticated') THEN
251
+ REVOKE ALL ON FUNCTION melchizedek_erase_scope(text, text, boolean) FROM authenticated;
252
+ END IF;
253
+ IF EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'service_role') THEN
254
+ GRANT EXECUTE ON FUNCTION melchizedek_erase_scope(text, text, boolean) TO service_role;
255
+ END IF;
256
+ END $$;
257
+
258
+ INSERT INTO melchizedek_schema_version (version, name)
259
+ VALUES (13, '0013_tool_credentials')
260
+ ON CONFLICT (version) DO NOTHING;
@@ -8,6 +8,10 @@
8
8
  * Middleware order, and why:
9
9
  * 1. /healthz, /readyz — unauthenticated, so a load balancer or
10
10
  * Kubernetes probe needs no secret. They reveal nothing but liveness.
11
+ * 1b. The OAuth consent callback, when `toolCredentials.consent` is set
12
+ * (ADR 0085): a provider redirects the person's browser to it, so it
13
+ * cannot carry the bearer. Its own rate limit; the single-use state
14
+ * nonce admits it.
11
15
  * 2. Failed-auth limiter — counts only 401s per IP, so the shared secret
12
16
  * cannot be guessed online at whatever rate the host allows.
13
17
  * 3. Bearer check (when a secret is configured), constant-time.
@@ -22,24 +26,53 @@
22
26
  * the handler cache, the rate-limiter counters. Sessions and memory are
23
27
  * durable when Supabase is configured. Run one replica, or put sticky
24
28
  * routing in front, until the task store is durable.
29
+ *
30
+ * Stores (ADR 0080): `storage` takes a session store and a memory service
31
+ * with either face, the engine's or ADK's. In-process sessions are the
32
+ * engine's InProcessSessionService. A `resolveModel` may still return an ADK
33
+ * model instance: its type is CompileOptions'.
25
34
  */
26
- import type { Express, Request } from 'express';
35
+ import type { Express, Request, RequestHandler } from 'express';
27
36
  import type { Store } from 'express-rate-limit';
28
37
  import type { AgentCard } from '@a2a-js/sdk';
29
38
  import type { TaskStore } from '@a2a-js/sdk/server';
30
- import type { BaseLlm, BaseMemoryService, BaseSessionService } from '@google/adk';
39
+ import type { CompileOptions } from '../compile.ts';
40
+ import type { EitherSessionService } from '../runtime/adkSessionBridge.ts';
41
+ import type { EitherMemoryService } from '../runtime/adkMemoryBridge.ts';
31
42
  import type { SyndicateYamlConfig } from '../loadSyndicate.ts';
32
43
  import type { ProviderEndpoint, ProviderId } from '../models/registry.ts';
33
44
  import type { TurnLock } from './turnLock.ts';
34
45
  import type { RlsHardeningStatus } from '../storage/rlsStatus.ts';
46
+ import type { AuditSink } from '../observability/audit.ts';
47
+ /** One end user's concurrent tasks, unless maxConcurrentPerScope says otherwise (ADR 0039). */
48
+ export declare const DEFAULT_MAX_CONCURRENT_PER_SCOPE = 4;
35
49
  import type { EraseCounts } from '../memory/erase.ts';
36
50
  import type { Embedder, MemoryExtractor } from '../memory/providers.ts';
37
51
  import type { A2AContext } from './executor.ts';
38
52
  import type { IdentityScheme } from './identity.ts';
39
53
  import type { Policy } from './policy.ts';
40
54
  import type { TaskRecord } from '../observability/metrics.ts';
55
+ import type { OAuthConsent, ToolCredentials } from '../tools/oauthConsent.ts';
41
56
  /** Agent ids address a config (file or "registry:<id>"): a safe charset only. */
42
57
  export declare function isValidAgentId(agentId: string): boolean;
58
+ /**
59
+ * The consent callback (ADR 0085): the provider's redirect, carrying `code`
60
+ * and `state` (or `error`). It never reads a redirect URI from the request,
61
+ * never logs the query, and answers a page that carries no value. The
62
+ * response is never cached and sends no referrer, since its URL holds the
63
+ * code.
64
+ */
65
+ export declare function consentCallback(consent: Pick<OAuthConsent, 'complete'>, opts?: {
66
+ resolveRequest?: A2AAppOptions['resolveRequest'];
67
+ /** The server's bearer secret, when it has one: the authenticator is consulted only behind it. */
68
+ serverSecret?: string;
69
+ /** Refuse a callback whose request the authenticator does not accept. Default true (ADR 0085). */
70
+ requireCallerIdentity?: boolean;
71
+ log?: (m: string) => void;
72
+ warn?: (m: string) => void;
73
+ }): RequestHandler;
74
+ /** What a model resolver returns, as the compiler takes it. */
75
+ type ResolvedModel = ReturnType<NonNullable<CompileOptions['resolveModel']>>;
43
76
  export interface A2AAppOptions {
44
77
  /** The syndicate served at /a2a/*: a YAML name or "registry:<id>". */
45
78
  defaultSyndicate: string;
@@ -55,8 +88,10 @@ export interface A2AAppOptions {
55
88
  * agent id (default: in-process).
56
89
  */
57
90
  storage?: {
58
- sessionService: BaseSessionService;
59
- memoryService?: BaseMemoryService;
91
+ /** The engine's SessionService or ADK's BaseSessionService (ADR 0080). */
92
+ sessionService: EitherSessionService;
93
+ /** The engine's MemoryService or ADK's BaseMemoryService. */
94
+ memoryService?: EitherMemoryService;
60
95
  taskStore?: (agentId: string) => TaskStore;
61
96
  /** Erase everything stored for a scope (DELETE /memory). Without it the route answers 501. */
62
97
  erase?: (scopeKey: string, options: {
@@ -75,6 +110,8 @@ export interface A2AAppOptions {
75
110
  * fatal with `requireHardenedDb`, a warning otherwise.
76
111
  */
77
112
  rlsHardening?: () => Promise<RlsHardeningStatus>;
113
+ /** Appends audit events (postgresStorage supplies one; ADR 0042). */
114
+ audit?: AuditSink;
78
115
  /**
79
116
  * One turn at a time per conversation across instances (postgresStorage
80
117
  * supplies an advisory lock). Default: a lock in this process.
@@ -150,6 +187,35 @@ export interface A2AAppOptions {
150
187
  };
151
188
  /** Adopter routes, mounted after authentication and before the A2A routes. */
152
189
  routes?: (app: Express) => void;
190
+ /**
191
+ * Tool credentials for every turn (ADR 0072): the sealed per-user store,
192
+ * and the OAuth consent step (ADR 0085, lib/tools/oauthConsent.ts). With
193
+ * `consent`, a call whose provider the user has not granted ends its task
194
+ * input-required with a `consent_request` data part, and the server mounts
195
+ * the consent callback (GET at the path of the consent's configured
196
+ * redirect URI): it completes the authorization-code flow with PKCE and
197
+ * stores the grant. The callback is reached by the person's browser, so it
198
+ * sits before the bearer check; it has its own rate limit, and when the
199
+ * request carries a credential the authenticator accepts, the caller must
200
+ * be the user the flow is for.
201
+ */
202
+ toolCredentials?: ToolCredentials & {
203
+ /** Callback requests per window per client IP. Default 30 per 15 minutes. */
204
+ callbackLimit?: {
205
+ windowMs: number;
206
+ max: number;
207
+ };
208
+ /**
209
+ * Refuse a callback whose request the authenticator does not accept.
210
+ * Default true: the browser that completes the grant must carry the
211
+ * flow's user's identity (a session cookie or a gateway header that
212
+ * resolveRequest reads), so a forwarded authorization link cannot link
213
+ * someone else's account (ADR 0085). false lets the state nonce alone
214
+ * bind the flow to its user, for a deployment whose browsers carry no
215
+ * identity and that accepts that risk.
216
+ */
217
+ requireCallerIdentity?: boolean;
218
+ };
153
219
  /** Refuse to start when Supabase hardening is missing (public deployments). */
154
220
  requireHardenedDb?: boolean;
155
221
  /** Wall-clock budget per task, ms. 0 = none. */
@@ -162,6 +228,15 @@ export interface A2AAppOptions {
162
228
  streamText?: boolean;
163
229
  /** Concurrent tasks across all agents. 0 = unlimited. */
164
230
  maxConcurrentTasks?: number;
231
+ /**
232
+ * Where audit events go: failed authentications, task outcomes, erasures
233
+ * (ADR 0042). Default: the storage's sink when it has one, else none.
234
+ */
235
+ audit?: AuditSink;
236
+ /** Concurrent tasks for one scope (one end user). Default 4; 0 = unlimited. */
237
+ maxConcurrentPerScope?: number;
238
+ /** Concurrent tasks for one authenticated caller. Default 0 (unlimited). */
239
+ maxConcurrentPerCaller?: number;
165
240
  /** Task submissions (POST) per window per client IP. */
166
241
  rateLimit?: {
167
242
  windowMs: number;
@@ -192,9 +267,11 @@ export interface A2AAppOptions {
192
267
  /**
193
268
  * Model resolution per request. Default: lib/models/registry.ts with the
194
269
  * caller's X-API-Key scoped to its X-Provider. Override to route through
195
- * your own gateway or credential store.
270
+ * your own gateway or credential store. Returns what
271
+ * CompileOptions.resolveModel returns: a model id, or a model instance
272
+ * (an ADK BaseLlm while the ADK runtime ships).
196
273
  */
197
- resolveModel?: (modelName: string | undefined, ctx: A2AContext) => string | BaseLlm | undefined;
274
+ resolveModel?: (modelName: string | undefined, ctx: A2AContext) => ResolvedModel;
198
275
  /** Bindings applied at every config load (e.g. current_date). */
199
276
  bindings?: () => Record<string, string>;
200
277
  log?: (message: string) => void;
@@ -232,6 +309,12 @@ export interface A2AApp {
232
309
  /** Stop admitting tasks, wait up to `graceMs` for running ones, cancel the rest.
233
310
  * Resolves with the number of tasks that had to be canceled. */
234
311
  shutdown(graceMs: number): Promise<number>;
312
+ /**
313
+ * Fail `/readyz` from now on while still serving every request, so a load
314
+ * balancer stops routing here before the listener closes. The first step of
315
+ * a graceful stop; `shutdown()` is the last.
316
+ */
317
+ markUnready(): void;
235
318
  }
236
319
  /**
237
320
  * Build the agent card for one syndicate at one route prefix, in the A2A 1.0
@@ -258,3 +341,4 @@ export declare function compileAgentCard(config: SyndicateYamlConfig, opts: {
258
341
  */
259
342
  export declare function memoryAppName(cfg: SyndicateYamlConfig): string;
260
343
  export declare function createA2AApp(options: A2AAppOptions): Promise<A2AApp>;
344
+ export {};