melchizedek-agents 0.15.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +277 -0
- package/AGENT_SETUP.md +19 -14
- package/CHANGELOG.md +633 -0
- package/DOCUMENTATION.md +375 -109
- package/QUICKSTART.md +55 -10
- package/README.md +23 -3
- package/config/agents/README.md +34 -0
- package/config/agents/examples/ares.yaml +116 -40
- package/config/agents/examples/assistant.yaml +74 -24
- package/config/agents/examples/augustin.yaml +105 -44
- package/config/agents/examples/cartographers.yaml +90 -23
- package/config/agents/examples/claude.yaml +44 -6
- package/config/agents/examples/council.yaml +22 -8
- package/config/agents/examples/critic.yaml +56 -21
- package/config/agents/examples/delegation.yaml +75 -9
- package/config/agents/examples/hierarchical.yaml +54 -8
- package/config/agents/examples/image_production.yaml +53 -16
- package/config/agents/examples/librarian.yaml +69 -14
- package/config/agents/examples/model_zoo.yaml +102 -27
- package/config/agents/examples/patient_advocate.yaml +101 -34
- package/config/agents/examples/research.yaml +49 -8
- package/config/agents/examples/scribe.yaml +111 -79
- package/config/agents/examples/scriptorium.yaml +86 -24
- package/config/agents/examples/style_council.yaml +30 -9
- package/config/agents/examples/syndicate.yaml +28 -10
- package/config/agents/examples/tutor.yaml +9 -3
- package/config/agents/syndicateSchema.yaml +39 -9
- package/config/agents/templates/README.md +7 -2
- package/config/agents/templates/account_memory.yaml +76 -18
- package/config/agents/templates/case_desk.yaml +84 -13
- package/config/agents/templates/conversational.yaml +38 -9
- package/config/agents/templates/draft_review.yaml +40 -13
- package/config/agents/templates/intake_extractor.yaml +33 -16
- package/config/agents/templates/research_brief.yaml +72 -26
- package/config/agents/templates/research_desk.yaml +74 -30
- package/config/agents/templates/review_panel.yaml +65 -30
- package/config/agents/templates/support_triage.yaml +107 -40
- package/config/agents/templates/systems_operator.yaml +76 -25
- package/db/hardening.sql +202 -0
- package/db/memory_v2.sql +77 -0
- package/db/migrations/0001_base.sql +167 -0
- package/db/migrations/0002_erase_scope.sql +172 -0
- package/db/migrations/0003_postgres_storage.sql +58 -0
- package/db/migrations/0004_usage.sql +94 -0
- package/db/migrations/0005_agent_registry.sql +200 -0
- package/db/migrations/0006_task_leases.sql +25 -0
- package/db/migrations/0007_memory_commit.sql +134 -0
- package/db/migrations/0008_memory_retention.sql +37 -0
- package/db/migrations/0009_task_queue.sql +51 -0
- package/db/migrations/0010_erase_complete.sql +180 -0
- package/db/telemetry.sql +401 -0
- package/demo/README.md +77 -0
- package/demo/a2a_demo.mjs +95 -0
- package/dist/lib/a2a/app.d.ts +253 -0
- package/dist/lib/a2a/app.js +751 -0
- package/dist/lib/a2a/executor.d.ts +167 -0
- package/dist/lib/a2a/executor.js +548 -0
- package/dist/lib/a2a/identity.d.ts +122 -0
- package/dist/lib/a2a/identity.js +254 -0
- package/dist/lib/a2a/policy.d.ts +110 -0
- package/dist/lib/a2a/policy.js +178 -0
- package/dist/lib/a2a/redisLimits.d.ts +26 -0
- package/dist/lib/a2a/redisLimits.js +31 -0
- package/dist/lib/a2a/remoteAgent.d.ts +91 -0
- package/dist/lib/a2a/remoteAgent.js +268 -0
- package/dist/lib/a2a/turnLock.d.ts +28 -0
- package/dist/lib/a2a/turnLock.js +76 -0
- package/dist/lib/compile.d.ts +11 -1
- package/dist/lib/compile.js +92 -9
- package/dist/lib/config.d.ts +2 -2
- package/dist/lib/config.js +2 -2
- package/dist/lib/doctor.d.ts +49 -2
- package/dist/lib/doctor.js +159 -12
- package/dist/lib/grounding.d.ts +2 -2
- package/dist/lib/grounding.js +2 -2
- package/dist/lib/guards/index.d.ts +12 -3
- package/dist/lib/guards/index.js +19 -4
- package/dist/lib/guards/science.js +1 -1
- package/dist/lib/index.d.ts +37 -2
- package/dist/lib/index.js +35 -4
- package/dist/lib/loadEnv.d.ts +23 -11
- package/dist/lib/loadEnv.js +77 -29
- package/dist/lib/loadSyndicate.d.ts +69 -5
- package/dist/lib/loadSyndicate.js +127 -71
- package/dist/lib/memory/erase.d.ts +24 -0
- package/dist/lib/memory/erase.js +47 -0
- package/dist/lib/memory/namespace.d.ts +37 -0
- package/dist/lib/memory/namespace.js +74 -0
- package/dist/lib/memory/providers.d.ts +99 -0
- package/dist/lib/memory/providers.js +240 -0
- package/dist/lib/memory/store.d.ts +74 -0
- package/dist/lib/memory/store.js +108 -0
- package/dist/lib/memory/supabaseMemoryService.d.ts +69 -9
- package/dist/lib/memory/supabaseMemoryService.js +239 -125
- package/dist/lib/models/capabilities.d.ts +50 -0
- package/dist/lib/models/capabilities.js +214 -4
- package/dist/lib/models/claudeLlm.d.ts +10 -1
- package/dist/lib/models/claudeLlm.js +57 -27
- package/dist/lib/models/endpoints.d.ts +100 -0
- package/dist/lib/models/endpoints.js +282 -0
- package/dist/lib/models/gateway.d.ts +1 -1
- package/dist/lib/models/gateway.js +4 -3
- package/dist/lib/models/gatewayLlm.d.ts +2 -2
- package/dist/lib/models/gatewayLlm.js +5 -5
- package/dist/lib/models/gptLlm.d.ts +22 -1
- package/dist/lib/models/gptLlm.js +77 -23
- package/dist/lib/models/grokLlm.d.ts +13 -4
- package/dist/lib/models/grokLlm.js +22 -7
- package/dist/lib/models/ollamaLlm.d.ts +26 -0
- package/dist/lib/models/ollamaLlm.js +43 -1
- package/dist/lib/models/openAiCompatibleLlm.d.ts +60 -2
- package/dist/lib/models/openAiCompatibleLlm.js +185 -36
- package/dist/lib/models/providerMap.js +9 -2
- package/dist/lib/models/registry.d.ts +24 -3
- package/dist/lib/models/registry.js +83 -23
- package/dist/lib/models/retry.d.ts +146 -0
- package/dist/lib/models/retry.js +305 -0
- package/dist/lib/models/schemaNormalize.d.ts +20 -0
- package/dist/lib/models/schemaNormalize.js +43 -0
- package/dist/lib/net/addressGuard.d.ts +60 -0
- package/dist/lib/net/addressGuard.js +216 -0
- package/dist/lib/observability/embeddings.d.ts +11 -2
- package/dist/lib/observability/embeddings.js +18 -14
- package/dist/lib/observability/metrics.d.ts +36 -0
- package/dist/lib/observability/metrics.js +86 -0
- package/dist/lib/observability/otlpFilter.d.ts +18 -0
- package/dist/lib/observability/otlpFilter.js +91 -0
- package/dist/lib/observability/redact.d.ts +29 -0
- package/dist/lib/observability/redact.js +102 -0
- package/dist/lib/observability/supabaseSpanExporter.d.ts +2 -0
- package/dist/lib/observability/supabaseSpanExporter.js +22 -6
- package/dist/lib/observability/tracer.d.ts +2 -0
- package/dist/lib/observability/tracer.js +42 -5
- package/dist/lib/persistence/supabaseProvider.d.ts +11 -0
- package/dist/lib/persistence/supabaseProvider.js +32 -6
- package/dist/lib/registry.d.ts +87 -0
- package/dist/lib/registry.js +146 -0
- package/dist/lib/runtime/approvals.d.ts +44 -0
- package/dist/lib/runtime/approvals.js +67 -0
- package/dist/lib/runtime/syndicateTurn.d.ts +233 -0
- package/dist/lib/runtime/syndicateTurn.js +597 -0
- package/dist/lib/runtime/turnControl.d.ts +90 -0
- package/dist/lib/runtime/turnControl.js +131 -0
- package/dist/lib/session/supabaseSessionService.js +1 -1
- package/dist/lib/session/transcript.d.ts +9 -1
- package/dist/lib/session/transcript.js +15 -7
- package/dist/lib/storage/postgres/index.d.ts +98 -0
- package/dist/lib/storage/postgres/index.js +146 -0
- package/dist/lib/storage/postgres/memoryStore.d.ts +11 -0
- package/dist/lib/storage/postgres/memoryStore.js +82 -0
- package/dist/lib/storage/postgres/sessionService.d.ts +51 -0
- package/dist/lib/storage/postgres/sessionService.js +225 -0
- package/dist/lib/storage/postgres/taskQueue.d.ts +22 -0
- package/dist/lib/storage/postgres/taskQueue.js +101 -0
- package/dist/lib/storage/postgres/taskStore.d.ts +55 -0
- package/dist/lib/storage/postgres/taskStore.js +168 -0
- package/dist/lib/storage/schema.d.ts +27 -0
- package/dist/lib/storage/schema.js +50 -0
- package/dist/lib/storage/schemaVersion.d.ts +25 -0
- package/dist/lib/storage/schemaVersion.js +46 -0
- package/dist/lib/syndicateSchema.d.ts +275 -0
- package/dist/lib/syndicateSchema.js +534 -0
- package/dist/lib/toolRegistry.d.ts +15 -0
- package/dist/lib/toolRegistry.js +48 -15
- package/dist/lib/tools/collectionsSearchTool.js +1 -1
- package/dist/lib/tools/mcpServe.d.ts +2 -3
- package/dist/lib/tools/mcpServe.js +3 -4
- package/dist/lib/tools/mcpToolFactory.d.ts +1 -0
- package/dist/lib/tools/mcpToolFactory.js +13 -21
- package/dist/lib/tools/science/corrections.js +2 -2
- package/dist/lib/tools/science/europepmc.js +2 -2
- package/dist/lib/tools/science/openalex.js +2 -2
- package/dist/lib/tools/science/trials.d.ts +1 -1
- package/dist/lib/tools/science/trials.js +2 -2
- package/dist/lib/tools/scienceTools.d.ts +5 -5
- package/dist/lib/tools/scienceTools.js +5 -5
- package/dist/lib/tools/taskTools.d.ts +75 -26
- package/dist/lib/tools/taskTools.js +83 -51
- package/dist/lib/tools/toolContract.d.ts +17 -4
- package/dist/lib/tools/toolContract.js +13 -5
- package/dist/lib/tools/webExtractTool.d.ts +7 -10
- package/dist/lib/tools/webExtractTool.js +15 -51
- package/dist/lib/tools/webSearchTool.d.ts +2 -1
- package/dist/lib/tools/webSearchTool.js +4 -3
- package/dist/lib/tools/wikiTools.d.ts +2 -2
- package/dist/lib/tools/wikiTools.js +12 -12
- package/dist/lib/tools/xApiSearchTool.d.ts +10 -10
- package/dist/lib/tools/xApiSearchTool.js +6 -6
- package/dist/lib/tools/xSearchTool.js +1 -1
- package/dist/lib/wiki/agentRun.js +1 -1
- package/dist/lib/wiki/builder.js +21 -6
- package/dist/lib/wiki/dive.js +2 -2
- package/dist/lib/wiki/entities.d.ts +2 -2
- package/dist/lib/wiki/entities.js +7 -7
- package/dist/lib/wiki/extract.js +5 -1
- package/dist/lib/wiki/fill.js +5 -5
- package/dist/lib/wiki/format.d.ts +7 -5
- package/dist/lib/wiki/format.js +2 -2
- package/dist/lib/wiki/graph.js +2 -2
- package/dist/lib/wiki/lint.js +2 -2
- package/dist/lib/wiki/markdown.d.ts +1 -1
- package/dist/lib/wiki/markdown.js +6 -1
- package/dist/lib/wiki/pipeline.js +2 -2
- package/dist/lib/wiki/vault.js +2 -2
- package/dist/scripts/a2a_server.d.ts +17 -11
- package/dist/scripts/a2a_server.js +405 -1094
- package/dist/scripts/assistant_worker.d.ts +5 -3
- package/dist/scripts/assistant_worker.js +88 -58
- package/dist/scripts/db.d.ts +26 -0
- package/dist/scripts/db.js +179 -0
- package/dist/scripts/doctor.d.ts +2 -0
- package/dist/scripts/doctor.js +45 -2
- package/dist/scripts/init.d.ts +43 -0
- package/dist/scripts/init.js +152 -0
- package/dist/scripts/registry.d.ts +25 -0
- package/dist/scripts/registry.js +182 -0
- package/dist/scripts/skills_install.js +1 -1
- package/dist/scripts/syndicate_chat.js +159 -276
- package/package.json +75 -13
- package/skills/README.md +1 -1
- package/skills/briefs/melchizedek-author.md +3 -3
- package/skills/briefs/melchizedek-memory.md +3 -1
- package/skills/briefs/melchizedek-models.md +2 -2
- package/skills/briefs/melchizedek-serve.md +16 -12
- package/skills/briefs/skills-readme.md +2 -2
- package/skills/melchizedek-author/SKILL.md +2 -2
- package/skills/melchizedek-author/templates/minimal.yaml +1 -1
- package/skills/melchizedek-memory/SKILL.md +2 -0
- package/skills/melchizedek-models/SKILL.md +1 -1
- package/skills/melchizedek-serve/SKILL.md +18 -9
- package/dist/lib/tools/xPacket.d.ts +0 -102
- package/dist/lib/tools/xPacket.js +0 -226
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,633 @@
|
|
|
1
|
+
# Changelog — melchizedek-agents (the npm package)
|
|
2
|
+
|
|
3
|
+
Consumers of the package read this file; it records changes to the
|
|
4
|
+
**published API surface** (the exports map in `package.json`, the bins,
|
|
5
|
+
the starter pack and the templates), not the repo's full history.
|
|
6
|
+
|
|
7
|
+
## 0.16.1 — 2026-10-02
|
|
8
|
+
|
|
9
|
+
- **OTLP export is filtered before it leaves** (`OTEL_EXPORT_CONTENT`).
|
|
10
|
+
Spans sent to `OTEL_EXPORTER_OTLP_ENDPOINT` carried the conversation
|
|
11
|
+
unredacted, while the ledger scrubs it (`TELEMETRY_REDACT`). The exporter
|
|
12
|
+
now applies the same redactor by default; `OTEL_EXPORT_CONTENT=off` drops
|
|
13
|
+
every conversation attribute (input, output, thinking, tool arguments and
|
|
14
|
+
results, payloads) and hashes `user.id`, keeping timings, models, token
|
|
15
|
+
counts, routes and errors; `raw` restores the old behaviour.
|
|
16
|
+
|
|
17
|
+
## 0.16.0 — 2026-10-02
|
|
18
|
+
|
|
19
|
+
### Breaking — read before upgrading
|
|
20
|
+
|
|
21
|
+
- **The server refuses to start on a database behind its migrations.** With
|
|
22
|
+
durable storage it reads `melchizedek_schema_version` at boot; below the
|
|
23
|
+
highest migration this release ships (0010), it stops and names
|
|
24
|
+
`npx melchizedek-db apply`. `ALLOW_SCHEMA_MISMATCH=true` starts anyway. A
|
|
25
|
+
newer database only warns. supabase-js storage now logs its deprecation
|
|
26
|
+
(ADR 0021); set `DATABASE_URL` to move to `postgresStorage`.
|
|
27
|
+
- **The default Gemini model is `gemini-3.5-flash-lite`** (was
|
|
28
|
+
`gemini-3.1-flash-lite`): `DEFAULT_GEMINI_MODEL` in `lib/config.ts`, and every
|
|
29
|
+
starter-pack, template and schema example that named the old id. An agent
|
|
30
|
+
that omits `model:` now runs on 3.5 Flash Lite; pin the old id in the YAML
|
|
31
|
+
to keep it.
|
|
32
|
+
- **`@google/adk` peer is now `^2.2.0`** (was `^1.3.0`), and `@google/genai`
|
|
33
|
+
is `2.25.0`. Install `@google/adk@2.2.0` beside the package. ADK and genai
|
|
34
|
+
now share one genai copy, and ADK's database drivers and GCP exporters are
|
|
35
|
+
optional peers, so the install is about 40% smaller.
|
|
36
|
+
- **The A2A server's key mode defaults to `server`.** The server's own
|
|
37
|
+
provider keys pay; `X-API-Key` is no longer required; sessions and memory
|
|
38
|
+
are stored under `X-User-Id` (else `default`). The old behaviour — the
|
|
39
|
+
caller's `X-API-Key` pays and its hash scopes the data — is
|
|
40
|
+
`A2A_KEY_MODE=byok` (`keyMode: 'byok'`). **A deployment holding data
|
|
41
|
+
written by an earlier version must set `byok`, or that data is no longer
|
|
42
|
+
found.**
|
|
43
|
+
- **A bare agent id is a file.** `/<agentId>/…` loads `<agentId>.yaml` from
|
|
44
|
+
your agents directory. The registry answers only `registry:<id>`, or bare
|
|
45
|
+
ids listed in `A2A_REGISTRY_AGENTS`; a registry miss is a 404 and a
|
|
46
|
+
registry failure a 503, never a silent fallback to the file. The shipped
|
|
47
|
+
`examples/` and `templates/` answer only ids listed in `A2A_SERVED_AGENTS`.
|
|
48
|
+
- **Syndicate YAML is validated at load.** Unknown keys, an invalid
|
|
49
|
+
`memory_system`, a
|
|
50
|
+
`dispatch.default_route` naming no subagent, and similar mistakes now
|
|
51
|
+
throw one error listing every problem with its key path and a did-you-mean
|
|
52
|
+
suggestion. They used to load and fail later, or silently. `subagents:`
|
|
53
|
+
may be omitted for a single-agent syndicate; it reads as `[]`.
|
|
54
|
+
- **`runSyndicateTurn` registers the framework's model adapters** when the
|
|
55
|
+
caller passes no `compile.resolveModel`, so `max_steps` and cancellation
|
|
56
|
+
hold for a string model id too (ADK's own Gemini class bypassed both).
|
|
57
|
+
- **The agent card is A2A 1.0** (`supportedInterfaces`), served to 0.3
|
|
58
|
+
clients in the 0.3 shape; requests in either version work
|
|
59
|
+
(`@a2a-js/sdk` 1.3 with 0.3 compatibility). File parts are rejected
|
|
60
|
+
(`rejected` state) instead of arriving as empty text.
|
|
61
|
+
- **Without `A2A_SERVER_SECRET` the server binds 127.0.0.1.** Binding another
|
|
62
|
+
`HOST` needs the secret or `ALLOW_UNAUTHENTICATED=true`; the `.env.example`
|
|
63
|
+
placeholder is refused as a secret.
|
|
64
|
+
- **The server no longer prints conversation content** (`[OTEL_SPAN_JSON]`
|
|
65
|
+
lines) unless `OTEL_CONSOLE_SPANS=true`.
|
|
66
|
+
- **Node `>=22.6`** (type stripping); production runs the compiled bins.
|
|
67
|
+
- **`POST /v1/x-packet` and `lib/tools/xPacket.ts` left the engine.** They
|
|
68
|
+
were one deployment's route. Mount your own routes with `routes`, or with
|
|
69
|
+
`startServer(name, { routes })` from the new `melchizedek-agents/server`.
|
|
70
|
+
|
|
71
|
+
### The engine as a library
|
|
72
|
+
|
|
73
|
+
- **`runSyndicateTurn(options)`** — the one turn runner. The server, the
|
|
74
|
+
CLI, the worker and the eval harness all call it, so plan-dispatch,
|
|
75
|
+
delegation, nested syndicates, guards and the step cap behave the same
|
|
76
|
+
everywhere (the CLI used to run dispatch syndicates in delegate mode).
|
|
77
|
+
Plain data in and out; also `ingestTurnMemory`, `compileGraph`,
|
|
78
|
+
`compileSubagent`.
|
|
79
|
+
- **`createA2AApp(options)`** — the A2A server as a mountable Express app,
|
|
80
|
+
with plug points: `resolveRequest` (your identity system returns the
|
|
81
|
+
scope key), `keyMode`, `credentials` (a provider key per request from your
|
|
82
|
+
secret manager), `storage` (sessions, memory, task store, erase),
|
|
83
|
+
`memory` (extractor, embedder), `routes`, limits. `melchizedek-serve` is a
|
|
84
|
+
thin bin over it.
|
|
85
|
+
- **`registerTool(name, tool)` and `registerGuard(guard)`** — extend what a
|
|
86
|
+
YAML can name, from your own code.
|
|
87
|
+
- **Root exports** now include the capability and gateway helpers the 0.12.0
|
|
88
|
+
entry listed (`describeCapabilities`, `capabilitySummary`, `planTransport`,
|
|
89
|
+
`gatewayConfig`, `gatewayProblem`, `gatewayUsable`, `GATEWAYS`,
|
|
90
|
+
`GatewayLlm`), `validateSyndicateConfig`, `syndicateJsonSchema`, the
|
|
91
|
+
memory providers, `eraseScope` and `namespacedMemoryService`. New subpaths:
|
|
92
|
+
`./compile`, `./runtime`, `./runtime/turnControl`, `./a2a`, `./a2a/remote`,
|
|
93
|
+
`./guards`.
|
|
94
|
+
|
|
95
|
+
### Fixed — behaviour the docs promised
|
|
96
|
+
|
|
97
|
+
- **The Postgres turn lock works with the server's keys.** It hashed the
|
|
98
|
+
key with Postgres' `hashtextextended`, and the server's keys are joined
|
|
99
|
+
with NUL separators, which Postgres text rejects: with `DATABASE_URL` set,
|
|
100
|
+
every A2A turn failed taking its lock. Keys are now hashed in Node to a
|
|
101
|
+
64-bit advisory-lock id.
|
|
102
|
+
- **Moving to `DATABASE_URL` keeps conversation history.** The Supabase
|
|
103
|
+
session service stores events as a JSON array on `adk_sessions`; the
|
|
104
|
+
Postgres adapter stores rows, and read none of the array, so following the
|
|
105
|
+
deprecation notice cut every conversation off from its history (and shifted
|
|
106
|
+
memory ingestion's event counts). The first read or append of such a
|
|
107
|
+
conversation now copies its array into rows, once, in order; the array
|
|
108
|
+
stays, so moving back still works.
|
|
109
|
+
- **Erase reaches every store** (migration `0010_erase_complete.sql`).
|
|
110
|
+
`DELETE /memory` and `erase()` left the memory ingestion markers (scope key
|
|
111
|
+
and conversation ids) and the task tools' list and jobs behind; they are now
|
|
112
|
+
deleted too and reported as `memory_markers` and `task_tools`. A namespace
|
|
113
|
+
erase keeps the task list, which belongs to the caller.
|
|
114
|
+
**`npx melchizedek-db apply`** before upgrading.
|
|
115
|
+
- **Non-Gemini orchestrators delegate.** Claude, GPT, Grok, Ollama and
|
|
116
|
+
gateway adapters sent every subagent (and `load_memory`) an empty
|
|
117
|
+
parameter schema; they now send the tool's real declaration.
|
|
118
|
+
- **`max_steps` is enforced**, across the whole turn — orchestrator,
|
|
119
|
+
subagents and nested syndicates share one budget — and exceeding it fails
|
|
120
|
+
the turn with `STEP_LIMIT`. It was passed to a parameter ADK does not have.
|
|
121
|
+
- **`includeContents`, `outputKey`, `globalInstruction`,
|
|
122
|
+
`disallowTransferToParent`, `disallowTransferToPeers`** reach ADK; they
|
|
123
|
+
were parsed and dropped.
|
|
124
|
+
- **`tasks/cancel` cancels**, including the model call in flight; every task
|
|
125
|
+
has a deadline (`A2A_TASK_TIMEOUT_MS`, default 15 minutes).
|
|
126
|
+
- **Per-agent cards advertise their own URLs**, declare their security
|
|
127
|
+
schemes, and are readable without a model key; without `PUBLIC_URL` the
|
|
128
|
+
card uses the host the request reached.
|
|
129
|
+
- **`memory_system: internal-only` keeps transcripts in process memory on the
|
|
130
|
+
server**, as documented.
|
|
131
|
+
- **Memory ingestion is at-least-once**: a failed extraction, embedding or
|
|
132
|
+
insert leaves the turns pending for the next task instead of dropping them.
|
|
133
|
+
- **`.env.example` ships no placeholder values**, and the loader ignores
|
|
134
|
+
`your_..._here` values: copying the template no longer crashes the
|
|
135
|
+
quickstart, funds no provider in the doctor, and cannot become a live
|
|
136
|
+
secret. Installed bins read `.env` from the directory you run them in.
|
|
137
|
+
- **SSRF guard** (`web_extract`, MCP clients, remote A2A agents): one
|
|
138
|
+
implementation that parses every IP encoding the URL parser emits
|
|
139
|
+
(IPv4-mapped, NAT64, 6to4, trailing-dot names) and resolves names, refusing
|
|
140
|
+
any that resolve to a non-public address.
|
|
141
|
+
- **Transient provider failures are retried** on Gemini and the
|
|
142
|
+
chat-completions path (Ollama, gateways): 408/409/425/429/5xx and connection
|
|
143
|
+
resets, jittered backoff, `Retry-After` honoured, never after output has
|
|
144
|
+
started (`MODEL_RETRY_MAX_ATTEMPTS`). Grok's per-attempt timeout is 10
|
|
145
|
+
minutes (`XAI_TIMEOUT_MS`).
|
|
146
|
+
- **`db/hardening.sql` revokes function execution from `PUBLIC`**, so the
|
|
147
|
+
anon key cannot call `SECURITY DEFINER` functions. **Re-run it.**
|
|
148
|
+
- **A thinking model that runs out of room says so instead of answering
|
|
149
|
+
empty.** On the chat-completions path (Ollama, gateways) a turn that ends
|
|
150
|
+
with reasoning but no reply now yields `<PROVIDER>_MAX_TOKENS` when
|
|
151
|
+
`finish_reason` is `length` (the reply never started), or
|
|
152
|
+
`<PROVIDER>_EMPTY_RESPONSE` when the model stopped after thinking. Before,
|
|
153
|
+
ADK dropped the empty final, logged "The last event is partial", and the
|
|
154
|
+
turn returned empty text while still billing the thinking tokens. On Ollama
|
|
155
|
+
the cause is usually its 4,096-token context window, which `/v1` cannot
|
|
156
|
+
raise (`num_ctx` is ignored); the error names the remedies. A `<think>`
|
|
157
|
+
block that never closed is scratchpad, never reply text, and a reply cut
|
|
158
|
+
short keeps its text with `finishReason: MAX_TOKENS`.
|
|
159
|
+
The `model_zoo` example's `qwen_local` agent sets
|
|
160
|
+
`generateContentConfig.reasoningEffort: "none"`, so `npm run demo:models`
|
|
161
|
+
gets an answer from the local model (ADR 0027).
|
|
162
|
+
|
|
163
|
+
### New
|
|
164
|
+
|
|
165
|
+
- **A local model that thinks without answering is retried once with
|
|
166
|
+
thinking off** (ADR 0027). An Ollama turn that ends in `OLLAMA_MAX_TOKENS`
|
|
167
|
+
(the context window filled while thinking) or `OLLAMA_EMPTY_RESPONSE` is
|
|
168
|
+
sent again with `reasoning_effort: "none"`; the named error reaches the
|
|
169
|
+
caller only if that fails too. Both attempts' tokens are counted. Skipped
|
|
170
|
+
for an agent already running with `reasoningEffort: "none"`; off with
|
|
171
|
+
`OLLAMA_RETRY_WITHOUT_THINKING=false`.
|
|
172
|
+
- The comment on `adk_session_events.ts` now says milliseconds (ADK's
|
|
173
|
+
`Date.now()`), which is what it has always held.
|
|
174
|
+
- **Pool sizes for the server** (ADR 0021). `DATABASE_POOL_MAX` (default 10)
|
|
175
|
+
and `A2A_TURN_LOCK_POOL_MAX` (default 20) bound the connections one
|
|
176
|
+
instance opens, so it fits a session-mode pooler's client limit.
|
|
177
|
+
- **Approval gates** (ADR 0028). `require_approval: [tool]` on an agent makes
|
|
178
|
+
that tool run only after a person approves the exact call: the A2A task
|
|
179
|
+
ends `input-required` with the pending call (text and an
|
|
180
|
+
`approval_request` data part), and `approve` / `reject` (or
|
|
181
|
+
`{ approval: { id, approved } }`) on the conversation resumes it. Allowed on
|
|
182
|
+
the orchestrator and plan-dispatch routes. `runSyndicateTurn` returns
|
|
183
|
+
`status: 'input-required'` with `approval`; `approvalResponsePart` answers
|
|
184
|
+
it. Stored function-call parts now keep Gemini's
|
|
185
|
+
`skip_thought_signature_validator` signature instead of none.
|
|
186
|
+
- **Cloud platforms and proxies** (ADR 0023). `GEMINI_PLATFORM=vertex`,
|
|
187
|
+
`ANTHROPIC_PLATFORM=bedrock|vertex` and `OPENAI_PLATFORM=azure` reach the
|
|
188
|
+
provider through Vertex AI, Bedrock or Azure OpenAI with the cloud's own
|
|
189
|
+
credentials (Google ADC, the AWS chain, an Azure key or Entra ID);
|
|
190
|
+
`ANTHROPIC_BASE_URL` / `OPENAI_BASE_URL` put a proxy in front of the vendor
|
|
191
|
+
API; `<PROVIDER>_MODEL_MAP` maps ids to platform ids or deployments. The A2A
|
|
192
|
+
`credentials` plug point may return a partial endpoint as well as a key.
|
|
193
|
+
`@anthropic-ai/bedrock-sdk`, `@anthropic-ai/vertex-sdk` and `@azure/identity`
|
|
194
|
+
are optional peers. The doctor lists each configured endpoint. Native web
|
|
195
|
+
search is not sent on Bedrock, Claude-on-Vertex or Azure. Tested against
|
|
196
|
+
mocks only; not live-verified.
|
|
197
|
+
- **A private schema** (ADR 0021). `MELCHIZEDEK_DB_SCHEMA=melchizedek` (or
|
|
198
|
+
`melchizedek-db apply --schema melchizedek`) installs every table and
|
|
199
|
+
function into that schema instead of `public`, so a Supabase REST layer
|
|
200
|
+
never sees them; `postgresStorage({ schema })` (the bin reads the same
|
|
201
|
+
variable) points its connections there. The default stays `public`, so an
|
|
202
|
+
existing database needs nothing. A private schema requires `DATABASE_URL`
|
|
203
|
+
(supabase-js reaches only exposed schemas).
|
|
204
|
+
- **Rate limits across replicas** (ADR 0021). `A2A_REDIS_URL` (with the
|
|
205
|
+
optional `redis` package) counts the request limit and the failed-login
|
|
206
|
+
limit in Redis, one window for every replica; in code, `limitStore` with
|
|
207
|
+
`redisRateLimitStore({ command })` from `melchizedek-agents/a2a/limits`.
|
|
208
|
+
- **The task tools on Postgres** (migration `0009_task_queue.sql`). With
|
|
209
|
+
`DATABASE_URL`, the to-do list and job queue live in Postgres: each caller
|
|
210
|
+
has their own list (tool calls now carry their caller, `ToolCallContext`,
|
|
211
|
+
and the task tools file records under the scope key), and any number of
|
|
212
|
+
`melchizedek-worker`s claim jobs with `FOR UPDATE SKIP LOCKED` under a
|
|
213
|
+
renewed lease. The JSON file stays the default. `setTaskBackend()` plugs
|
|
214
|
+
in any other store.
|
|
215
|
+
- **Per-syndicate memory settings** (ADR 0020). `memory_extraction_model`
|
|
216
|
+
picks the model that distils a syndicate's turns (default
|
|
217
|
+
`MEMORY_EXTRACTION_MODEL`); `memory_retention_days` deletes facts in the
|
|
218
|
+
syndicate's own `memory_namespace` older than the window, when the server
|
|
219
|
+
loads it and daily after (migration `0008_memory_retention.sql`).
|
|
220
|
+
- **Memory ingestion commits as one unit** (migration
|
|
221
|
+
`0007_memory_commit.sql`, ADR 0020). New facts, the rows they supersede
|
|
222
|
+
and the session's processed marker are written in one transaction
|
|
223
|
+
(`melchizedek_memory_commit`); the marker is stored, so a restart never
|
|
224
|
+
re-extracts a turn. The server refuses to start when the embedder's
|
|
225
|
+
dimension differs from the stored column. **`npx melchizedek-db apply`.**
|
|
226
|
+
- **A task whose server died is failed, not stuck** (migration
|
|
227
|
+
`0006_task_leases.sql`, Postgres storage). A running task is leased to the
|
|
228
|
+
instance running it and renewed on a heartbeat; when the lease expires
|
|
229
|
+
another instance marks it `failed` with a message saying the server
|
|
230
|
+
stopped. Apply the migration (`npx melchizedek-db apply`); the boot check
|
|
231
|
+
requires it.
|
|
232
|
+
- **One turn at a time per conversation.** A second message on a
|
|
233
|
+
conversation whose turn is still running waits for it (up to
|
|
234
|
+
`A2A_TURN_LOCK_WAIT_MS`, default 30 s) and runs after it, seeing its
|
|
235
|
+
exchange; past the wait it is `rejected` ("still running"). In-process by
|
|
236
|
+
default; with `DATABASE_URL`, a Postgres advisory lock shared by every
|
|
237
|
+
instance (`postgresStorage().turnLock`, its own pool, `lockPoolMax`).
|
|
238
|
+
- **Token streaming on `message/stream`** (`A2A_STREAM_TEXT=true`,
|
|
239
|
+
`streamText` in `createA2AApp`). The answer arrives as chunks of an
|
|
240
|
+
`answer` artifact as the model writes it; narration before a tool call is
|
|
241
|
+
withdrawn, and the artifact is closed with the text the user receives
|
|
242
|
+
(relay fallback and dispatch included). A syndicate with guards never
|
|
243
|
+
streams. Off by default; the final status message is unchanged. The
|
|
244
|
+
runtime exposes the same as `TurnEvents.onTextDelta` / `onTextReset`.
|
|
245
|
+
- **A versioned agent registry** (migration `0005_agent_registry.sql`, ADR
|
|
246
|
+
0018). Every definition an id has held is kept in an append-only
|
|
247
|
+
`adk_agent_registry_versions`, with its author, note and config hash, and
|
|
248
|
+
the database records a version on every write to the active row, whoever
|
|
249
|
+
writes it. `npx melchizedek-registry publish|versions|show|diff|rollback|retire`
|
|
250
|
+
(library: `melchizedek-agents/registry`) validates before it writes;
|
|
251
|
+
rollback re-activates a stored version. `registry:<id>@<version>` loads one
|
|
252
|
+
version. Existing rows become version 1 when the migration runs:
|
|
253
|
+
**`npx melchizedek-db apply`** to install it. A syndicate is versioned as a
|
|
254
|
+
unit: `publish` (and `publishAgent`) stores every nested `yaml_reference` it
|
|
255
|
+
reaches under `bundled_references`, and the server loads that version's
|
|
256
|
+
nested syndicates from the bundle, not from files (`--no-bundle` /
|
|
257
|
+
`bundle: false` opts out). Republish a nesting syndicate after changing a
|
|
258
|
+
nested file.
|
|
259
|
+
- **The source moved to [github.com/jhwadman/melch-ai](https://github.com/jhwadman/melch-ai).**
|
|
260
|
+
The package name stays `melchizedek-agents`; `repository`, `homepage` and
|
|
261
|
+
`bugs` point at the new repository, which now holds the engine, its tests
|
|
262
|
+
and its wiki directly. `npx skills add jhwadman/melch-ai` installs the skills.
|
|
263
|
+
- **Built-in authenticators** (`melchizedek-agents/a2a/identity`, ADR
|
|
264
|
+
0025), chosen in the bin with `A2A_AUTH`:
|
|
265
|
+
- `callers`: one bearer token per calling backend. `A2A_CALLERS` holds
|
|
266
|
+
`name:sha256[:scope]`, so the config stores only token hashes. A caller
|
|
267
|
+
owns a scope that does not depend on any model key, so rotating a
|
|
268
|
+
provider key no longer strands sessions and memory. Mint a caller with
|
|
269
|
+
`melchizedek-serve --new-caller <name> [--scope s] [--token-file f]`. A
|
|
270
|
+
still-set `A2A_SERVER_SECRET` keeps working beside the tokens with its
|
|
271
|
+
old scoping, so callers move over one at a time; give a caller its
|
|
272
|
+
existing `a2a-<hash>` silo as its scope and no data moves.
|
|
273
|
+
- `jwt`: your identity provider's tokens, verified with `jose` (JWKS or
|
|
274
|
+
HS256; issuer, audience and expiry required); the scope is the user
|
|
275
|
+
claim, optionally under a tenant claim.
|
|
276
|
+
- `header`: a trusted user header from an authenticating gateway, accepted
|
|
277
|
+
only together with the server secret.
|
|
278
|
+
- In code: `createA2AApp({ ...callerTokens(parseCallers(spec)) })`, or
|
|
279
|
+
`jwtIdentity`, `trustedHeader`, `sharedSecret`, `firstOf`.
|
|
280
|
+
- `RequestIdentity.operator` marks an operator-issued credential (a caller
|
|
281
|
+
token, the server secret); an adopter route reads it through
|
|
282
|
+
`currentRequestContext()` to refuse end users (a JWT, a gateway identity).
|
|
283
|
+
- **Governance** (ADR 0026):
|
|
284
|
+
- `runSyndicateTurn` returns `usage`: model calls plus input, output and
|
|
285
|
+
thinking tokens, summed over every agent in the turn.
|
|
286
|
+
- Budgets: `policy: budgets(config)` (env `A2A_BUDGETS`) sets daily limits per
|
|
287
|
+
caller and per scope on tasks, calls and tokens; a task over budget ends
|
|
288
|
+
`rejected` with the reason. Counters: `memoryUsageStore`,
|
|
289
|
+
`postgresUsageStore`, `supabaseUsageStore` (table from
|
|
290
|
+
`db/migrations/0004_usage.sql`).
|
|
291
|
+
- `onTaskEnd` gives one `TaskRecord` per task; `A2A_LOG_FORMAT=json` makes
|
|
292
|
+
every server line JSON.
|
|
293
|
+
- `GET /metrics` serves Prometheus text behind `A2A_METRICS_TOKEN`
|
|
294
|
+
(`createMetrics`).
|
|
295
|
+
- With an authenticator, the rate limit counts per caller or per scope
|
|
296
|
+
instead of per IP.
|
|
297
|
+
- The telemetry ledger is redacted before it is written: key-shaped
|
|
298
|
+
credentials by default (`TELEMETRY_REDACT`), emails, phones, cards and SSNs
|
|
299
|
+
on request, or your own `setTelemetryRedactor`.
|
|
300
|
+
- **`keyMode: 'byok'` now holds under any authenticator**: the caller's
|
|
301
|
+
`X-API-Key` pays whoever the caller is. A `resolveRequest` used to switch
|
|
302
|
+
BYOK billing off. The key-hash scope applies only without an authenticator.
|
|
303
|
+
- **Remote agents: `a2a_agent_url:` on a subagent** — an agent served over
|
|
304
|
+
A2A (1.0 or 0.3) becomes a delegation tool or a plan-dispatch route.
|
|
305
|
+
Credentials from `A2A_AGENT_TOKENS`; `ALLOW_PRIVATE_A2A` for local hosts.
|
|
306
|
+
- **`melchizedek-init`**: start a project from any template or example in one
|
|
307
|
+
command — writes `config/agents/<name>.yaml` (and what it nests) with a
|
|
308
|
+
schema modeline, gives a long-term syndicate its own `memory_namespace`,
|
|
309
|
+
creates `.env` from the template, and prints the next commands.
|
|
310
|
+
`--list` shows what ships.
|
|
311
|
+
- **Database tooling: `melchizedek-db print | apply | status |
|
|
312
|
+
prune-sessions`** over numbered, idempotent migrations in
|
|
313
|
+
`db/migrations/` (base schema, nightly session expiry, scope erasure), then
|
|
314
|
+
`hardening.sql`.
|
|
315
|
+
- **`DELETE /memory` erases everything stored for the calling scope** —
|
|
316
|
+
facts, sessions with their subagent rows, ledger rows — with per-store
|
|
317
|
+
counts; `?all=1` covers every memory namespace.
|
|
318
|
+
- **`memory_namespace`** (YAML): where a syndicate's long-term memory lives;
|
|
319
|
+
memory tools on subagents read the root syndicate's facts.
|
|
320
|
+
- **Memory providers**: extraction on any model id
|
|
321
|
+
(`MEMORY_EXTRACTION_MODEL`), embeddings from Gemini, OpenAI, Ollama or any
|
|
322
|
+
OpenAI-compatible endpoint (`MEMORY_EMBEDDING_*`).
|
|
323
|
+
- **Capability matrix** (`lib/models/capabilities.ts`): provider × delegation,
|
|
324
|
+
memory tools, structured output, thinking with tools, streaming, vision,
|
|
325
|
+
native search — each cell backed by a request-shape test;
|
|
326
|
+
`melchizedek-doctor --matrix` prints it and flags gaps per agent.
|
|
327
|
+
- **Server operations**: `/healthz`, `/readyz`, SIGTERM drain
|
|
328
|
+
(`A2A_SHUTDOWN_GRACE_MS`), a concurrency cap, configurable rate limits,
|
|
329
|
+
trust-proxy and body limit, a failed-login limiter, a boot summary.
|
|
330
|
+
- **Published JSON Schema** for syndicate YAML:
|
|
331
|
+
`config/agents/syndicate.schema.json` (editor modeline in
|
|
332
|
+
`syndicateSchema.yaml`).
|
|
333
|
+
- **Deploy artefacts**: `Dockerfile`, `compose.yaml` (optional Ollama and
|
|
334
|
+
Phoenix), CI, `SECURITY.md`.
|
|
335
|
+
- The package now ships `db/`, `demo/`, `.env.example` and this changelog,
|
|
336
|
+
and `package.json` names the repository.
|
|
337
|
+
|
|
338
|
+
## 0.15.0 — 2026-09-27
|
|
339
|
+
|
|
340
|
+
- **Production templates: `config/agents/templates/`.** Ten job-shaped
|
|
341
|
+
syndicates built to be adapted and shipped, beside the starter pack that
|
|
342
|
+
teaches: `conversational` (a keyless conversational agent),
|
|
343
|
+
`support_triage` (plan-dispatch with a `handoff` fallback),
|
|
344
|
+
`research_brief` (three layers, nesting `research_desk`), `review_panel`
|
|
345
|
+
(ship, fix or hold a change), `draft_review` (a policy-checked loop), one
|
|
346
|
+
per memory tier (`intake_extractor`, `case_desk`, `account_memory`), and
|
|
347
|
+
`systems_operator` (your systems over MCP; read, plan, confirm, write).
|
|
348
|
+
The package now ships the directory; `templates/README.md` maps it, and
|
|
349
|
+
`npm run syndicate:conversational` runs the first.
|
|
350
|
+
- **The loader looks in `templates/` too.** A bare name resolves at the
|
|
351
|
+
agents root, then `examples/`, then `templates/`, so an A2A route
|
|
352
|
+
(`/support_triage/…`) and a nested `yaml_reference` find a template
|
|
353
|
+
without a path.
|
|
354
|
+
- **`web_extract` names where a redirect landed.** A URL that redirects (a
|
|
355
|
+
search engine's grounding link, for one) now carries a `Resolved:` line
|
|
356
|
+
with the final address, so a note can cite the publisher, not the
|
|
357
|
+
redirect. Output for a URL that did not redirect is unchanged.
|
|
358
|
+
- **The compile tier of `npm test` walks subdirectories.** It loaded only
|
|
359
|
+
the root before, which in this package meant the schema file alone; it
|
|
360
|
+
now compiles every shipped syndicate.
|
|
361
|
+
|
|
362
|
+
## 0.14.0 — 2026-09-25
|
|
363
|
+
|
|
364
|
+
- **Starter pack: `assistant.yaml`, the Assistant.** The generic starting
|
|
365
|
+
point for your own agent, keyless (`ollama/qwen3:8b`): the orchestrator
|
|
366
|
+
converses, a Summarizer reads pasted text or up to five URLs
|
|
367
|
+
(`web_extract`), a task list outlives the conversation, and longer work is
|
|
368
|
+
queued as background jobs. `npm run syndicate:assistant`.
|
|
369
|
+
- **Five task tools.** `task_add`, `task_queue`, `task_list`, `task_get`,
|
|
370
|
+
`task_update` (`lib/tools/taskTools.ts`), registered by name in the tool
|
|
371
|
+
registry. One local JSON store for to-dos and jobs:
|
|
372
|
+
`MELCHIZEDEK_TASKS_FILE`, default `outputs/tasks.json`. Single-user by
|
|
373
|
+
design; do not serve them on a shared A2A endpoint.
|
|
374
|
+
- **`melchizedek-worker`: the background worker.** A fifth bin (and
|
|
375
|
+
`npm run assistant:worker`) claims queued jobs one at a time, runs each
|
|
376
|
+
through one agent compiled from YAML (default `--syndicate assistant
|
|
377
|
+
--agent Worker`; any syndicate and agent), and writes the result back for
|
|
378
|
+
`task_get`. `--once` drains the queue and exits (cron); otherwise it polls
|
|
379
|
+
(`--interval`, default 30 s). The tools only write the queue; they never
|
|
380
|
+
run a job.
|
|
381
|
+
|
|
382
|
+
## 0.13.0 — 2026-09-24
|
|
383
|
+
|
|
384
|
+
- **Starter pack: `research.yaml`, Research.** Questions about clinical and
|
|
385
|
+
biomedical evidence, answered from trial registries and the peer-reviewed
|
|
386
|
+
literature. Plan-dispatch: a triage model names one of three routes
|
|
387
|
+
(`define`, `lookup`, `landscape`), and each route holds its own tools, so
|
|
388
|
+
every tool call is on the answering turn's stream. `guards: [science]`
|
|
389
|
+
marks any DOI, PMID or NCT number no tool returned, checks retractions, and
|
|
390
|
+
catches a trial acronym attached to the wrong identifier.
|
|
391
|
+
- **Seven science tools, keyless.** `search_literature`, `search_preprints`,
|
|
392
|
+
`search_trials`, `resolve_identifier`, `cited_by`, `survey_field`,
|
|
393
|
+
`check_retraction` (`lib/tools/scienceTools.ts`), reading Europe PMC,
|
|
394
|
+
ClinicalTrials.gov, Crossref and OpenAlex. Registered by name in the tool
|
|
395
|
+
registry, and served to MCP clients by `npm run mcp:science`
|
|
396
|
+
(`scripts/science_mcp_server.ts`, :8934). Set `SCIENCE_API_CONTACT` to an
|
|
397
|
+
address you read to join the sources' polite request pools.
|
|
398
|
+
- **The `science` guard** is now registered in `lib/guards/index.ts`.
|
|
399
|
+
- **`melchizedek-skills`: the framework as a skills suite.** A fourth bin
|
|
400
|
+
(and `npm run skills:install`) copies `skills/` — six Agent Skills in the
|
|
401
|
+
open SKILL.md standard — into the directories coding agents read:
|
|
402
|
+
`.claude/skills/` and `.agents/skills/` by default (between them, Claude
|
|
403
|
+
Code, Codex, Cursor, OpenCode and Gemini CLI), or `--for
|
|
404
|
+
claude,codex,cursor,opencode,gemini,agents,all`, `--global`, `--dir`,
|
|
405
|
+
`--only`, `--force`, `--dry-run`; `list` and `paths` subcommands. The
|
|
406
|
+
suite: `melchizedek` (where the syndicates are, what each costs, run one,
|
|
407
|
+
delegate a task from a coding agent), `melchizedek-author`,
|
|
408
|
+
`melchizedek-serve`, `melchizedek-memory`, `melchizedek-models`,
|
|
409
|
+
`melchizedek-scribe`. `skills` joins `files`; engine: `lib/skills.ts`.
|
|
410
|
+
- **Starter pack: `scribe.yaml`, The Scribe.** A Gemini syndicate that
|
|
411
|
+
writes one document from a technical brief and audits it against the
|
|
412
|
+
brief through a JSON-schema leaf (the Auditor) before returning it.
|
|
413
|
+
`npm run syndicate:scribe`. The skills suite above was written with it,
|
|
414
|
+
one brief per skill.
|
|
415
|
+
|
|
416
|
+
## 0.12.0 — 2026-09-23
|
|
417
|
+
|
|
418
|
+
- **`melchizedek-doctor`: which keys do I need?** A third bin (and
|
|
419
|
+
`npm run doctor`) reads every syndicate YAML the loader can see, resolves
|
|
420
|
+
each agent's model to its provider under the current `.env`, and prints
|
|
421
|
+
one table — agent, model, provider, which declared server-side tools the
|
|
422
|
+
path keeps or drops, and whether the path is funded — with one verdict
|
|
423
|
+
per syndicate and the variables that would unlock the most. Read-only:
|
|
424
|
+
nothing is sent, nothing is written, no key value is printed. `--json`,
|
|
425
|
+
`--check`. Engine: `lib/doctor.ts`.
|
|
426
|
+
- **The gateway fallback (`lib/models/gatewayLlm.ts`, `lib/models/gateway.ts`).**
|
|
427
|
+
`MODEL_GATEWAY=vercel|openrouter` + `MODEL_GATEWAY_API_KEY` serve any
|
|
428
|
+
cloud model id whose direct key is ABSENT through that gateway's
|
|
429
|
+
OpenAI-compatible endpoint. Direct adapters stay canonical: a present
|
|
430
|
+
provider key always wins, Ollama never routes through a gateway, and a
|
|
431
|
+
BYOK `X-API-Key` on the A2A server never selects it. Attribution stays
|
|
432
|
+
with the upstream provider (`llm.provider`); the transport is recorded
|
|
433
|
+
separately (`llm.transport = gateway:<id>`). Optional dials:
|
|
434
|
+
`MODEL_GATEWAY_BASE_URL` (self-hosted proxy), `MODEL_GATEWAY_MODEL_MAP`
|
|
435
|
+
(wire-name overrides). `registerAvailableProviders()` registers the
|
|
436
|
+
stand-in for uncovered providers; `providerStatuses()` gains
|
|
437
|
+
`transport` and `gateway`; `resolveModel()` applies the same rule.
|
|
438
|
+
- **Capability report (`lib/models/capabilities.ts`).** `describeCapabilities`
|
|
439
|
+
states, per agent and on the RESOLVED path, which server-side tool
|
|
440
|
+
sentinels (`web_search`, `google_search`, `x_search`,
|
|
441
|
+
`collections_search`) run natively and which are dropped. The compiler
|
|
442
|
+
logs one `capability ·` line per affected agent; the chat-completions
|
|
443
|
+
base records `llm.transport` and `llm.capability.dropped` on the span.
|
|
444
|
+
New exports from the package root: `describeCapabilities`,
|
|
445
|
+
`capabilitySummary`, `planTransport`, `gatewayConfig`, `gatewayProblem`,
|
|
446
|
+
`gatewayUsable`, `GATEWAYS`, `GatewayLlm`.
|
|
447
|
+
- **Starter pack: `# tier:` headers.** Every example opens with `keyless`,
|
|
448
|
+
a single provider (`gemini`, `anthropic`), or `multi-provider`; the
|
|
449
|
+
doctor checks the claim against the models.
|
|
450
|
+
|
|
451
|
+
## 0.11.0 — 2026-09-20
|
|
452
|
+
|
|
453
|
+
- **`x_api_search`: the X channel without a Grok dependency.** A new
|
|
454
|
+
client-side tool (`lib/tools/xApiSearchTool.ts`, registered in
|
|
455
|
+
`TOOL_MAP`) searches X's last seven days through the X API v2 recent
|
|
456
|
+
search and transcribes every PHOTO attached to a post through a Gemini
|
|
457
|
+
vision pass, pasted beneath the post. It runs on any provider and needs
|
|
458
|
+
`X_BEARER_TOKEN` (a read-only app token) plus the Gemini key the engine
|
|
459
|
+
already uses; without the token it reports itself unavailable to the
|
|
460
|
+
agent instead of failing the turn. The starter pack's `augustin.yaml`
|
|
461
|
+
moves its XResearcher onto it (`gemini-3.8-flash` + `x_api_search` +
|
|
462
|
+
`web_extract`), so the fact-checking arbiter no longer requires
|
|
463
|
+
`XAI_API_KEY`. `x_search` stays registered for grok-* agents that want
|
|
464
|
+
xAI's semantic ranker. Dials, all environment: `X_API_IMAGE_MAX`
|
|
465
|
+
(photos read per page, default 8), `X_API_MAX_RESULTS` (page ceiling,
|
|
466
|
+
default 50), `X_API_VISION_MODEL` (default `gemini-3.8-flash`).
|
|
467
|
+
|
|
468
|
+
## 0.10.0 — 2026-09-09
|
|
469
|
+
|
|
470
|
+
- **Post-answer guards.** A syndicate YAML may now carry an optional
|
|
471
|
+
`guards:` list of guard NAMES, run after the answering turn and before
|
|
472
|
+
the reply is published. A guard receives the final text plus every
|
|
473
|
+
tool-result text of that turn and returns the text to ship along with
|
|
474
|
+
notes for the `[STATUS]` stream; it rewrites in place rather than
|
|
475
|
+
re-asking the model. Three shape changes to the published surface:
|
|
476
|
+
|
|
477
|
+
- `SyndicateYamlConfig` (`./loadSyndicate`) gains `guards?: string[]`.
|
|
478
|
+
Optional, so every existing config still typechecks.
|
|
479
|
+
- `./loadSyndicate` gains `collectGuards(config, loadNested?)`, which
|
|
480
|
+
returns the union of guard names declared by a syndicate **and by
|
|
481
|
+
every syndicate it nests through `yaml_reference:`**. Read guards
|
|
482
|
+
with this rather than off `config.guards`: a guard belongs to the
|
|
483
|
+
syndicate that declared it, not to the position it occupies in a
|
|
484
|
+
graph, and reading the top-level field alone silently dropped a
|
|
485
|
+
nested syndicate's guards.
|
|
486
|
+
- A new `lib/guards/index.ts` publishes the `Guard` / `GuardResult`
|
|
487
|
+
interfaces and `resolveGuards(names, onUnknown?)`. The registry ships
|
|
488
|
+
EMPTY — the guards this deployment runs are domain modules that stay
|
|
489
|
+
private, the same arrangement `lib/toolRegistry.ts` uses. Register
|
|
490
|
+
your own by adding it to that file's `GUARD_MAP`; an unregistered
|
|
491
|
+
name warns and is skipped rather than failing the run.
|
|
492
|
+
|
|
493
|
+
`config/agents/syndicateSchema.yaml` documents the field. No bin
|
|
494
|
+
changes; no existing export changes shape.
|
|
495
|
+
|
|
496
|
+
- **`lib/tools/mcpServe.ts` (new, internal).** The express/SSE scaffold
|
|
497
|
+
behind `npm run mcp:wiki` — `serveContracts({ name, label, port,
|
|
498
|
+
contracts })` — extracted from three byte-identical copies that had
|
|
499
|
+
begun to drift on error signalling and on whether they read `.env`.
|
|
500
|
+
Not in the exports map and not a bin, but it now ships because
|
|
501
|
+
`scripts/wiki/mcp_server.ts` imports it. Behaviour change for MCP
|
|
502
|
+
clients: a failed tool call is returned with the spec's `isError`
|
|
503
|
+
flag set instead of as an ordinary successful result, so a client can
|
|
504
|
+
tell "the tool answered" from "the tool failed".
|
|
505
|
+
|
|
506
|
+
## 0.9.6 — 2026-09-02
|
|
507
|
+
|
|
508
|
+
- **`web_extract` joins the public tool registry.** The tool's source
|
|
509
|
+
(`lib/tools/webExtractTool.ts`) has shipped in the package since
|
|
510
|
+
2026-08-09, but the sanitized `lib/toolRegistry.ts` never mapped the
|
|
511
|
+
YAML name, so `augustin.yaml`'s two researchers logged an unknown-tool
|
|
512
|
+
warning and ruled from search snippets. Declaring `web_extract` in a
|
|
513
|
+
syndicate now resolves to the client-side page reader on every
|
|
514
|
+
provider, local Ollama included. Additive: no export, bin, or starter
|
|
515
|
+
file changes shape.
|
|
516
|
+
|
|
517
|
+
## 0.9.5 — 2026-09-02
|
|
518
|
+
|
|
519
|
+
- **The default production Gemini is now `gemini-3.8-flash`.** Two
|
|
520
|
+
exported constants change VALUE (not shape): `MEMORY_EXTRACTION_MODEL`
|
|
521
|
+
and `WIKI_AGENT_MODEL` in `lib/config.ts`, plus the internal
|
|
522
|
+
`VISION_MODEL` behind `inspect_image`. Every starter-pack syndicate
|
|
523
|
+
that shipped on `gemini-3.7-flash` now ships on `gemini-3.8-flash`.
|
|
524
|
+
The cheap tier is untouched: `DEFAULT_GEMINI_MODEL` stays
|
|
525
|
+
`gemini-3.1-flash-lite`, and `ares` / `model_zoo` keep their flash-lite
|
|
526
|
+
pins. Nothing in the exports map or the two bins changes.
|
|
527
|
+
|
|
528
|
+
The id was verified against the live endpoint before pinning:
|
|
529
|
+
`models/gemini-3.8-flash` publishes exactly 3.7's envelope —
|
|
530
|
+
1,048,576 input, 65,536 output, `thinking: true`, identical
|
|
531
|
+
`supportedGenerationMethods` — so no `maxOutputTokens` in any shipped
|
|
532
|
+
YAML changes and none is an over-ask.
|
|
533
|
+
|
|
534
|
+
If you pin a model explicitly in your own YAML, nothing changes for
|
|
535
|
+
you. If you rely on the defaults and want the old behaviour, set
|
|
536
|
+
`WIKI_AGENT_MODEL=gemini-3.7-flash` (env) or pin `model:` in your
|
|
537
|
+
syndicate.
|
|
538
|
+
|
|
539
|
+
## 0.9.4 — 2026-09-02
|
|
540
|
+
|
|
541
|
+
- **Thinking and replies stream live.** The OpenAI-compatible adapter
|
|
542
|
+
(Ollama, xAI) now honours ADK's `stream` flag instead of ignoring it:
|
|
543
|
+
it sends `stream: true`, parses the SSE frames, and yields each
|
|
544
|
+
reasoning and text delta as a display-only partial. `melchizedek-chat`
|
|
545
|
+
runs with `streamingMode: SSE`, so a local qwen3 turn shows its
|
|
546
|
+
scratchpad token by token from ~1.5s rather than dumping the whole
|
|
547
|
+
turn after ~15s. `CHAT_STREAMING=false` restores one-block output —
|
|
548
|
+
useful when piping a transcript or for structured-output agents.
|
|
549
|
+
Reasoning is read from a discrete `reasoning` / `reasoning_content`
|
|
550
|
+
delta field where the provider sends one (Ollama does), and otherwise
|
|
551
|
+
from inline `<think>` tags via a new exported `ThinkStreamSplitter`,
|
|
552
|
+
which tracks block state across frames so a tag split mid-delta
|
|
553
|
+
("<thi" + "nk>") is not mistaken for reply text.
|
|
554
|
+
- **Fix: a streamed Claude turn no longer vanishes from session
|
|
555
|
+
history.** ADK's runner persists only NON-partial events, and the
|
|
556
|
+
Claude streaming path built its final response with the text omitted,
|
|
557
|
+
so a reply would render on screen and leave no record — the next turn
|
|
558
|
+
saw no assistant message. The final response now carries the full
|
|
559
|
+
text; printers skip text on a `turnComplete` event whose partials they
|
|
560
|
+
already rendered. This path was unreachable before this release, since
|
|
561
|
+
nothing requested SSE.
|
|
562
|
+
- **Chat is silent about telemetry.** `melchizedek-chat` and every
|
|
563
|
+
`syndicate:*` script no longer print `[OTEL_SPAN_JSON]` lines; set
|
|
564
|
+
`OTEL_CONSOLE_SPANS=true` (shell or `.env`) to see them, and
|
|
565
|
+
`OTEL_CONSOLE_SPANS=false` to silence them in other scripts. In-process
|
|
566
|
+
span listeners and the Supabase sink are unaffected either way, so no
|
|
567
|
+
telemetry is lost.
|
|
568
|
+
|
|
569
|
+
## 0.9.3 — 2026-08-22
|
|
570
|
+
|
|
571
|
+
- **`outputSchema` is enforced on every provider, not just Gemini** —
|
|
572
|
+
the Claude adapter now carries an agent's `outputSchema` as a forced
|
|
573
|
+
tool call (`tool_choice` on a synthetic `structured_output` tool whose
|
|
574
|
+
`input_schema` is the schema) and turns the validated `tool_use` block
|
|
575
|
+
back into JSON text, so the keys arrive as declared instead of drifting
|
|
576
|
+
(`"grade"` for `"correctness"`); the OpenAI adapter sends
|
|
577
|
+
`json_schema` with `strict: true` over a schema where every object
|
|
578
|
+
forbids extra properties and requires all of its own
|
|
579
|
+
(`toStrictJsonSchema`), which the API previously rejected; the
|
|
580
|
+
OpenAI-compatible adapter (xAI) does the same, while Ollama keeps
|
|
581
|
+
`json_object`. Anything that reads structured fields by name — critic
|
|
582
|
+
loops, plan-dispatch routers on non-Gemini models, LLM judges — now
|
|
583
|
+
works across providers.
|
|
584
|
+
- **Engine additions behind the A2A server**: the shared YAML→ADK compiler
|
|
585
|
+
(`lib/compile.ts`), provenance stamps (`lib/observability/lineage.ts`),
|
|
586
|
+
embeddings (`lib/observability/embeddings.ts`), the three-tier
|
|
587
|
+
observability ledger in `db/telemetry.sql` with identity and
|
|
588
|
+
provenance on every span, and `scripts/telemetry_admin.ts`. New
|
|
589
|
+
optional dependency `@opentelemetry/exporter-trace-otlp-http` for
|
|
590
|
+
`OTEL_EXPORTER_OTLP_ENDPOINT`.
|
|
591
|
+
|
|
592
|
+
## 0.9.2 — 2026-08-20
|
|
593
|
+
|
|
594
|
+
- **The starter pack gains Augustin** —
|
|
595
|
+
`config/agents/examples/augustin.yaml`, a fact-checking arbiter of
|
|
596
|
+
world events: a grok X-sweep researcher and a Gemini web-verification
|
|
597
|
+
researcher under a tool-free Arbiter that writes a conversational
|
|
598
|
+
lead plus sourced bullet facts. Multi-provider (needs `XAI_API_KEY`
|
|
599
|
+
and `GOOGLE_GENAI_API_KEY`); `npm run syndicate:augustin` in a clone.
|
|
600
|
+
The pattern is taught as a standalone lesson in the curriculum.
|
|
601
|
+
|
|
602
|
+
## 0.9.1 — 2026-08-19
|
|
603
|
+
|
|
604
|
+
- **Fix: `melchizedek-serve` actually starts.** The run-as-main guard
|
|
605
|
+
compared `import.meta.url` to argv[1] literally; through the npm bin
|
|
606
|
+
symlink they never match, so the 0.9.0 bin imported everything and
|
|
607
|
+
exited silently. The guard now realpaths argv[1]. `melchizedek-chat`
|
|
608
|
+
was unaffected.
|
|
609
|
+
- `melchizedek-serve` without an argument now explains itself when no
|
|
610
|
+
`syndicate.yaml` exists (name your syndicate: `melchizedek-serve
|
|
611
|
+
<name>.yaml`) instead of failing with a bare ENOENT.
|
|
612
|
+
- QUICKSTART gains §7, the package-consumer path (docs ship in the
|
|
613
|
+
tarball, so they ride this release).
|
|
614
|
+
|
|
615
|
+
## 0.9.0 — 2026-08-19
|
|
616
|
+
|
|
617
|
+
First packaged release (pre-1.0: the API may still move; 1.0.0 lands
|
|
618
|
+
after the first external consumer migration).
|
|
619
|
+
|
|
620
|
+
- The engine is installable: `npm install melchizedek-agents` ships
|
|
621
|
+
compiled JS + type declarations for `lib/` (`loadSyndicate`, the model
|
|
622
|
+
registry, the tool registry, memory/session/persistence/observability,
|
|
623
|
+
the wiki engine) behind an explicit subpath exports map.
|
|
624
|
+
- `loadSyndicate` accepts `agentsDir` (or the `MELCHIZEDEK_AGENTS_DIR`
|
|
625
|
+
env var) so your syndicates live in **your** repo; default remains
|
|
626
|
+
`<cwd>/config/agents`. The path jail applies relative to whichever
|
|
627
|
+
root is configured.
|
|
628
|
+
- Two bins: `melchizedek-serve` (the A2A server) and `melchizedek-chat`
|
|
629
|
+
(the interactive syndicate CLI).
|
|
630
|
+
- The starter pack ships in the package: `config/agents/examples/*.yaml`
|
|
631
|
+
plus `syndicateSchema.yaml` — copy them out, they are teaching
|
|
632
|
+
material, not wiring.
|
|
633
|
+
- `@google/adk` is a peer dependency: your app owns the ADK version.
|