melchizedek-agents 1.1.0 → 1.3.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.
- package/.env.example +19 -0
- package/AGENT_SETUP.md +3 -1
- package/CHANGELOG.md +373 -0
- package/DOCUMENTATION.md +193 -21
- package/ONBOARDING.md +378 -0
- package/QUICKSTART.md +15 -2
- package/README.md +26 -3
- package/config/agents/examples/connectors.yaml +82 -0
- package/config/agents/examples/council.yaml +1 -1
- package/config/agents/examples/critic.yaml +8 -8
- package/config/agents/examples/image_production.yaml +4 -3
- package/config/agents/syndicate.schema.json +389 -33
- package/config/agents/syndicateSchema.yaml +18 -6
- package/config/agents/templates/intake_extractor.yaml +3 -2
- package/config/agents/templates/systems_operator.yaml +5 -2
- package/dist/lib/a2a/app.d.ts +12 -0
- package/dist/lib/a2a/app.js +25 -11
- package/dist/lib/a2a/executor.js +14 -6
- package/dist/lib/a2a/oauthSetup.d.ts +16 -0
- package/dist/lib/a2a/oauthSetup.js +77 -8
- package/dist/lib/agentDialect.d.ts +18 -8
- package/dist/lib/agentDialect.js +36 -19
- package/dist/lib/chatgpt/adapter.d.ts +50 -0
- package/dist/lib/chatgpt/adapter.js +107 -0
- package/dist/lib/chatgpt/cli.d.ts +23 -0
- package/dist/lib/chatgpt/cli.js +77 -0
- package/dist/lib/chatgpt/oauth.d.ts +103 -0
- package/dist/lib/chatgpt/oauth.js +448 -0
- package/dist/lib/chatgpt/state.d.ts +98 -0
- package/dist/lib/chatgpt/state.js +145 -0
- package/dist/lib/chatgpt/store.d.ts +24 -0
- package/dist/lib/chatgpt/store.js +94 -0
- package/dist/lib/compile.d.ts +38 -7
- package/dist/lib/compile.js +97 -62
- package/dist/lib/compileNative.d.ts +11 -3
- package/dist/lib/compileNative.js +18 -1
- package/dist/lib/dispatch.js +6 -2
- package/dist/lib/doctor.d.ts +107 -0
- package/dist/lib/doctor.js +217 -7
- package/dist/lib/loadSyndicate.d.ts +15 -0
- package/dist/lib/mcp/server.d.ts +195 -0
- package/dist/lib/mcp/server.js +564 -0
- package/dist/lib/memory/supabaseMemoryService.js +2 -2
- package/dist/lib/models/adapterResolver.js +6 -1
- package/dist/lib/models/capabilities.d.ts +9 -0
- package/dist/lib/models/capabilities.js +24 -0
- package/dist/lib/models/chatCompletionsAdapter.d.ts +11 -3
- package/dist/lib/models/chatCompletionsAdapter.js +19 -5
- package/dist/lib/models/claudeAdapter.js +4 -0
- package/dist/lib/models/contract.d.ts +5 -2
- package/dist/lib/models/gateway.d.ts +3 -2
- package/dist/lib/models/gateway.js +8 -4
- package/dist/lib/models/gatewayAdapter.d.ts +7 -1
- package/dist/lib/models/gatewayAdapter.js +8 -0
- package/dist/lib/models/geminiAdapter.js +8 -2
- package/dist/lib/models/genaiMapping.d.ts +8 -4
- package/dist/lib/models/genaiMapping.js +23 -9
- package/dist/lib/models/gptAdapter.d.ts +4 -2
- package/dist/lib/models/gptAdapter.js +11 -4
- package/dist/lib/models/grokAdapter.d.ts +3 -1
- package/dist/lib/models/grokAdapter.js +11 -3
- package/dist/lib/models/kimiAdapter.d.ts +2 -1
- package/dist/lib/models/kimiAdapter.js +3 -3
- package/dist/lib/models/reasoning.d.ts +30 -2
- package/dist/lib/models/reasoning.js +56 -5
- package/dist/lib/onboarding.d.ts +135 -0
- package/dist/lib/onboarding.js +578 -0
- package/dist/lib/runtime/approvals.d.ts +2 -0
- package/dist/lib/runtime/approvals.js +4 -3
- package/dist/lib/runtime/credentials.d.ts +6 -0
- package/dist/lib/runtime/native/agentLoop.d.ts +5 -2
- package/dist/lib/runtime/native/agentLoop.js +2 -0
- package/dist/lib/runtime/native/checkpoint.d.ts +12 -5
- package/dist/lib/runtime/native/checkpoint.js +13 -19
- package/dist/lib/runtime/native/delegate.d.ts +82 -1
- package/dist/lib/runtime/native/delegate.js +157 -2
- package/dist/lib/runtime/native/interrupts.d.ts +88 -5
- package/dist/lib/runtime/native/interrupts.js +220 -30
- package/dist/lib/runtime/syndicateTurn.d.ts +4 -2
- package/dist/lib/runtime/syndicateTurn.js +324 -77
- package/dist/lib/runtime/turnControl.d.ts +41 -0
- package/dist/lib/session/transcript.d.ts +9 -0
- package/dist/lib/session/transcript.js +20 -1
- package/dist/lib/skills.d.ts +18 -0
- package/dist/lib/skills.js +73 -1
- package/dist/lib/storage/postgres/index.d.ts +6 -1
- package/dist/lib/storage/postgres/index.js +1 -1
- package/dist/lib/storage/postgres/taskQueue.d.ts +7 -3
- package/dist/lib/storage/postgres/taskQueue.js +10 -3
- package/dist/lib/syndicateSchema.d.ts +184 -9
- package/dist/lib/syndicateSchema.js +143 -29
- package/dist/lib/tools/auth.d.ts +13 -1
- package/dist/lib/tools/auth.js +10 -2
- package/dist/lib/tools/credentialHosts.d.ts +88 -0
- package/dist/lib/tools/credentialHosts.js +165 -0
- package/dist/lib/tools/credentialUses.d.ts +98 -0
- package/dist/lib/tools/credentialUses.js +120 -0
- package/dist/lib/tools/generateImageTool.js +2 -1
- package/dist/lib/tools/inspectImageTool.js +1 -1
- package/dist/lib/tools/mcpToolFactory.d.ts +29 -1
- package/dist/lib/tools/mcpToolFactory.js +72 -26
- package/dist/lib/tools/mcpTransports.d.ts +12 -0
- package/dist/lib/tools/mcpTransports.js +11 -0
- package/dist/lib/tools/oauthConsent.d.ts +18 -3
- package/dist/lib/tools/oauthConsent.js +57 -15
- package/dist/lib/tools/oauthDiscovery.d.ts +202 -0
- package/dist/lib/tools/oauthDiscovery.js +616 -0
- package/dist/lib/tools/oauthHosts.d.ts +2 -0
- package/dist/lib/tools/oauthHosts.js +2 -2
- package/dist/lib/tools/oauthTools.d.ts +54 -13
- package/dist/lib/tools/oauthTools.js +106 -23
- package/dist/lib/tools/openapiTools.d.ts +7 -0
- package/dist/lib/tools/openapiTools.js +49 -3
- package/dist/lib/tools/taskTools.d.ts +32 -2
- package/dist/lib/tools/taskTools.js +93 -33
- package/dist/lib/tools/xApiSearchTool.js +2 -2
- package/dist/lib/workflow/turn.d.ts +22 -3
- package/dist/lib/workflow/turn.js +151 -31
- package/dist/lib/workflow.d.ts +10 -7
- package/dist/lib/workflow.js +10 -7
- package/dist/scripts/a2a_server.d.ts +2 -2
- package/dist/scripts/a2a_server.js +19 -2
- package/dist/scripts/assistant_worker.d.ts +2 -0
- package/dist/scripts/assistant_worker.js +24 -5
- package/dist/scripts/doctor.d.ts +4 -2
- package/dist/scripts/doctor.js +6 -4
- package/dist/scripts/mcp_server.d.ts +12 -0
- package/dist/scripts/mcp_server.js +345 -0
- package/dist/scripts/setup.d.ts +25 -0
- package/dist/scripts/setup.js +181 -0
- package/dist/scripts/skills_install.d.ts +3 -1
- package/dist/scripts/skills_install.js +17 -2
- package/dist/scripts/syndicate_chat.js +12 -3
- package/dist/scripts/yaml_codemod.d.ts +12 -2
- package/dist/scripts/yaml_codemod.js +115 -33
- package/package.json +8 -2
- package/skills/README.md +11 -2
- package/skills/briefs/_shared.md +1 -1
- package/skills/briefs/melchizedek-models.md +4 -2
- package/skills/briefs/skills-readme.md +3 -1
- package/skills/melchizedek-models/SKILL.md +6 -2
- package/skills/melchizedek-onboard/SKILL.md +71 -0
- package/skills/melchizedek-onboard-cloud/SKILL.md +38 -0
- package/skills/melchizedek-onboard-keys/SKILL.md +47 -0
- package/skills/melchizedek-onboard-local/SKILL.md +41 -0
- package/skills/melchizedek-onboard-serve/SKILL.md +43 -0
package/.env.example
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
# Not sure which of these you need? `npx melchizedek-setup` (in a clone: `npm run setup`)
|
|
2
|
+
# asks what you have and prints the names to set for it; --auto detects it.
|
|
3
|
+
# Only names and shapes live here: type the values yourself, never commit .env.
|
|
4
|
+
|
|
1
5
|
# ── Required for cloud models ─────────────────────────────────────────────────
|
|
2
6
|
# Google AI Studio API key — powers all Gemini model inference.
|
|
3
7
|
# Also required for the gemini-embedding-001 embedding model used by long-term memory.
|
|
@@ -50,6 +54,15 @@ ANTHROPIC_API_KEY=
|
|
|
50
54
|
# Get your key at: https://platform.openai.com/api-keys
|
|
51
55
|
OPENAI_API_KEY=
|
|
52
56
|
|
|
57
|
+
# ── Optional: Sign in with ChatGPT, on your own machine only (ADR 0126) ───────
|
|
58
|
+
# Instead of OPENAI_API_KEY: `npx melchizedek-setup --chatgpt-signin` opens your
|
|
59
|
+
# browser, and OpenAI ids then run on your ChatGPT plan while no key is set.
|
|
60
|
+
# The sign-in is stored OUTSIDE this file and the repository (mode 600); no
|
|
61
|
+
# variable is needed. melchizedek-serve and melchizedek-worker refuse to start
|
|
62
|
+
# while it is the OpenAI path.
|
|
63
|
+
# MELCHIZEDEK_CHATGPT_SIGNIN_FILE= # a path outside any git repository (default ~/.melchizedek/chatgpt-signin.json)
|
|
64
|
+
# MELCHIZEDEK_CHATGPT_SIGNIN=off # ignore a stored sign-in in this process (a served one on the same machine)
|
|
65
|
+
|
|
53
66
|
# ── Optional: cloud platforms and proxies (ADR 0023) ─────────────────────────
|
|
54
67
|
# The model id picks the provider; these pick how it is reached. Default:
|
|
55
68
|
# the vendor's public API with the key above. Tested against mocks only.
|
|
@@ -262,6 +275,12 @@ PUBLIC_URL=
|
|
|
262
275
|
# Unset: authorization_code grants are refused, client_credentials allowed.
|
|
263
276
|
# Set: every grant's provider is listed and every host it calls is its own.
|
|
264
277
|
# MELCHIZEDEK_OAUTH_HOSTS=tracker=api.tracker.example.com,auth.tracker.example.com
|
|
278
|
+
# The hosts each static credential variable a YAML sends may be sent to
|
|
279
|
+
# (ADR 0122): bearer_env, api_key.env and client_secret_env, each entry the
|
|
280
|
+
# variable's name, '=', then its hosts (as above). Unset: each goes to the
|
|
281
|
+
# host the YAML names, and the server and the doctor name it as unbound.
|
|
282
|
+
# Set: it is the whole list; an unlisted variable is sent nowhere.
|
|
283
|
+
# MELCHIZEDEK_CREDENTIAL_HOSTS=TRACKER_TOKEN=api.tracker.example.com;WEATHER_API_KEY=api.weather.example.com
|
|
265
284
|
|
|
266
285
|
# ── Optional: Knowledge Bundle (wiki) ─────────────────────────────────────────
|
|
267
286
|
# WIKI_ROOT: filesystem path of the OKF knowledge bundle the wiki tools serve.
|
package/AGENT_SETUP.md
CHANGED
|
@@ -26,7 +26,9 @@ Set up the melchizedek-agents framework on this machine.
|
|
|
26
26
|
it. Never ask me to paste API keys into this chat, never read keys
|
|
27
27
|
from elsewhere on my machine, and never commit .env.
|
|
28
28
|
4. Run the offline test suite (`npm test`) and confirm every shipped
|
|
29
|
-
syndicate compiles.
|
|
29
|
+
syndicate compiles. Then run `npm run setup -- --auto`: it reports
|
|
30
|
+
which authentication level my environment is at, by variable name
|
|
31
|
+
only. Follow the melchizedek-onboard skill in skills/ to pick my level.
|
|
30
32
|
5. Read README.md and QUICKSTART.md. Then report back with:
|
|
31
33
|
- what you did and the test results,
|
|
32
34
|
- the list of available syndicates (one line each, from the README
|
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,379 @@ the starter pack and the templates), not the repo's full history.
|
|
|
6
6
|
|
|
7
7
|
## Unreleased
|
|
8
8
|
|
|
9
|
+
## 1.3.0 — 2026-10-10
|
|
10
|
+
|
|
11
|
+
Release 1.3.0 connects syndicates to the MCP ecosystem in both directions
|
|
12
|
+
and adds a local sign-in for OpenAI models (ADRs 0124–0127).
|
|
13
|
+
`melchizedek-mcp` serves each syndicate as an MCP tool to Claude Code, Codex
|
|
14
|
+
and any MCP client; an agent reaches official remote MCP servers over
|
|
15
|
+
Streamable HTTP, several at once, registering itself with an OAuth server
|
|
16
|
+
that has no pre-issued client; and Sign in with ChatGPT runs OpenAI models on
|
|
17
|
+
a person's own ChatGPT plan, on their own machine only. Server logs no longer
|
|
18
|
+
carry tool arguments or a person's words.
|
|
19
|
+
|
|
20
|
+
### Upgrade first
|
|
21
|
+
|
|
22
|
+
- **Log lines changed.** A tool call logs `→ Tool: <tool> by <agent> — args:
|
|
23
|
+
<key names> (<n> bytes)` instead of `→ Tool: name(args)`; questions, routes
|
|
24
|
+
and router fallbacks no longer quote text. Anything that parses the server
|
|
25
|
+
log should read the tool name before ` by `.
|
|
26
|
+
- **A stored ChatGPT sign-in stops served surfaces.** If you sign in with
|
|
27
|
+
`--chatgpt-signin` on a machine that also runs `melchizedek-serve`,
|
|
28
|
+
`melchizedek-worker`, `createA2AApp` or `melchizedek-mcp --http`, they refuse
|
|
29
|
+
to start while the sign-in would carry OpenAI ids. Set `OPENAI_API_KEY`, or
|
|
30
|
+
`MELCHIZEDEK_CHATGPT_SIGNIN=off`, or sign out. Nothing changes without a
|
|
31
|
+
sign-in.
|
|
32
|
+
- **`melchizedek-doctor --check` exits 1 on an unrecognised `MODEL_GATEWAY`.**
|
|
33
|
+
- **MCP servers are reached over Streamable HTTP first.** An existing
|
|
34
|
+
`mcp_server_url` that only speaks SSE still works, after one extra request
|
|
35
|
+
that the server refuses; pin `mcp_transport: sse` to skip it.
|
|
36
|
+
|
|
37
|
+
### Added
|
|
38
|
+
|
|
39
|
+
- **`melchizedek-mcp`: syndicates as MCP tools** (ADR 0125). A new bin
|
|
40
|
+
serves each loaded syndicate as one MCP tool (`{ message, session_id? }`;
|
|
41
|
+
the answer, then its `session_id`; `structuredContent.output` for a
|
|
42
|
+
syndicate with an output schema) plus `melch_resume { session_id,
|
|
43
|
+
approve?, answer? }` for a turn that paused on an approval, an `ask_user`
|
|
44
|
+
question or an OAuth consent. stdio by default (`claude mcp add melch --
|
|
45
|
+
npx melchizedek-mcp`, or a Codex `[mcp_servers]` table); `--http` serves
|
|
46
|
+
Streamable HTTP at `/mcp` on 127.0.0.1:4100 and refuses a bind beyond
|
|
47
|
+
loopback without `MCP_SERVER_SECRET` (32+ characters). Every call is one
|
|
48
|
+
task through the A2A executor, so budgets, caps, the turn lock, deadlines,
|
|
49
|
+
cancel (`notifications/cancelled`), guards and the ledger match
|
|
50
|
+
`melchizedek-serve`; an approval is answered only by `melch_resume`'s
|
|
51
|
+
explicit `approve`. Surface addition: the `melchizedek-mcp` bin and the
|
|
52
|
+
`melchizedek-agents/mcp` export path (`createMcpServer`, `serveMcpStdio`,
|
|
53
|
+
`mcpHttpApp`, `mcpBindProblem`, `toolNameFor`, `RESUME_TOOL`).
|
|
54
|
+
- **MCP over Streamable HTTP, several MCP servers per agent, and dynamic
|
|
55
|
+
client registration** (ADR 0124). The MCP client posts the initialize
|
|
56
|
+
request over Streamable HTTP, the spec's current transport, and falls back
|
|
57
|
+
to the legacy SSE transport when the server answers with the spec's signal
|
|
58
|
+
(a 4xx other than 401/403); existing SSE URLs keep working unchanged.
|
|
59
|
+
`mcp_transport:` (beside `mcp_server_url`) or an entry's `transport:` pins
|
|
60
|
+
`auto`, `streamable_http` or `sse`. New `mcp_servers:` lists several
|
|
61
|
+
servers, `{ name, url, tools, auth?, transport? }`, each with the tools the
|
|
62
|
+
agent may use from it; a tool name on two servers or shared with the
|
|
63
|
+
agent's own tools is refused at load, and `require_approval` may name any
|
|
64
|
+
server's tool. An MCP server's `authorization_code` grant may say
|
|
65
|
+
`client_registration: dynamic` with no client id or endpoints: the
|
|
66
|
+
authorization server is discovered (RFC 9728, RFC 8414), the deployment
|
|
67
|
+
registers itself as a public PKCE client (RFC 7591) for
|
|
68
|
+
`OAUTH_REDIRECT_URI`, the MCP server's URI goes as the RFC 8707 `resource`
|
|
69
|
+
parameter, and the registration is kept sealed in the credential store
|
|
70
|
+
(no migration). Every discovered host must be on `MELCHIZEDEK_OAUTH_HOSTS`
|
|
71
|
+
before any request reaches it. Additive API: `lib/tools/oauthDiscovery.ts`
|
|
72
|
+
(under the existing `./tools/*` export), `isSseFallbackSignal` and
|
|
73
|
+
`McpServerConfig` in `mcpToolFactory`, `dynamicOAuthGrantsFor` in
|
|
74
|
+
`oauthTools`, `OAuthClientSource` (accepted by `oauthConsent({ providers })`
|
|
75
|
+
and `oauthRefreshProviders`), `OAuthClientConfig.resource`, and the
|
|
76
|
+
`registration_failed` consent error. `OAuth2AuthConfig.token_url` is
|
|
77
|
+
optional in its type (the schema still requires it unless the grant is
|
|
78
|
+
dynamic). New example: `config/agents/examples/connectors.yaml`.
|
|
79
|
+
- **Sign in with ChatGPT, on your own machine only** (ADR 0126). OpenAI's
|
|
80
|
+
documented plan-usage flow for open-source apps that run locally:
|
|
81
|
+
`melchizedek-setup --chatgpt-signin` (or `melchizedek-chat --chatgpt-signin`)
|
|
82
|
+
opens your browser, registers the engine as its own app with OpenAI
|
|
83
|
+
(PKCE S256, a 127.0.0.1 callback), and stores the tokens mode 600 at
|
|
84
|
+
`~/.melchizedek/chatgpt-signin.json` (`MELCHIZEDEK_CHATGPT_SIGNIN_FILE`),
|
|
85
|
+
never inside a git repository. With no `OPENAI_API_KEY`, `gpt-*` and
|
|
86
|
+
`o<digit>*` ids then run on your ChatGPT plan through the Responses API:
|
|
87
|
+
streamed, not stored, without `temperature`, `top_p` or `max_output_tokens`,
|
|
88
|
+
ranked above a gateway. Tokens refresh as they near expiry;
|
|
89
|
+
`--chatgpt-signout` revokes them and `--chatgpt-status` shows where they are.
|
|
90
|
+
`MELCHIZEDEK_CHATGPT_SIGNIN=off` ignores a stored sign-in. The engine never
|
|
91
|
+
reads another app's sign-in (the Codex CLI's included).
|
|
92
|
+
- **Served surfaces refuse a ChatGPT sign-in.** `createA2AApp`,
|
|
93
|
+
`melchizedek-serve` and `melchizedek-worker` refuse to start while a stored
|
|
94
|
+
sign-in would carry OpenAI ids, naming the fixes; a call that reaches it on
|
|
95
|
+
a served process anyway ends in `CHATGPT_SIGNIN_LOCAL_ONLY`.
|
|
96
|
+
`melchizedek-doctor` prints a `chatgpt` line (`DoctorResult.chatgpt`, and
|
|
97
|
+
`credential: 'chatgpt-signin'` on the OpenAI provider path), and `--check`
|
|
98
|
+
fails when serving variables are set beside such a sign-in.
|
|
99
|
+
- **Onboarding level 9, `chatgpt-signin`.** `melchizedek-setup` lists ten
|
|
100
|
+
levels: Sign in with ChatGPT is level 9 and detected by `--auto`; the
|
|
101
|
+
unsupported subscription entry is now level 10 (Claude.ai, Gemini CLI, the
|
|
102
|
+
Codex CLI's login) and routes OpenAI to level 9. `ONBOARDING.md` and the
|
|
103
|
+
onboarding skills follow.
|
|
104
|
+
|
|
105
|
+
### Changed
|
|
106
|
+
|
|
107
|
+
- **Releases are staged on npm for a maintainer's approval** (ADR 0127).
|
|
108
|
+
The tag-triggered `release.yml` now runs `npm stage publish --provenance`
|
|
109
|
+
through trusted publishing instead of `npm publish`; a maintainer releases
|
|
110
|
+
the staged version with `npx npm@11 stage approve <stage-id>` (2FA). No
|
|
111
|
+
change to the package itself.
|
|
112
|
+
- **`melchizedek-doctor --check` fails on an unrecognised `MODEL_GATEWAY`.**
|
|
113
|
+
The doctor already reported a `MODEL_GATEWAY` that names no gateway; `--check`
|
|
114
|
+
now exits 1 on it too (`checkProblems` adds a `gateway:` line naming the
|
|
115
|
+
accepted values, `vercel` and `openrouter`). The value is never echoed, in
|
|
116
|
+
text, `--json` or the check line, since it may be a key pasted into the wrong
|
|
117
|
+
variable. A recognised gateway without `MODEL_GATEWAY_API_KEY`, and unset
|
|
118
|
+
per-grant variables, stay a report, not a failure.
|
|
119
|
+
- **Server-side logs name tools, never their arguments.** The turn runner's
|
|
120
|
+
`log` line for a tool call (what `melchizedek-serve`, `melchizedek-mcp` and
|
|
121
|
+
`melchizedek-worker` print) is `→ Tool: <tool> by <agent> — args: <key
|
|
122
|
+
names> (<n> bytes)` instead of the arguments cut to 60 characters. A
|
|
123
|
+
question logs `⏸ <node> asks a question` without its text, a dispatch
|
|
124
|
+
route logs without the classifier's reason (the caller's progress line
|
|
125
|
+
keeps it), and a router fallback reason measures the router's text instead
|
|
126
|
+
of quoting it. The worker logs a job's size, not its title; the image,
|
|
127
|
+
inspect-image and X API tools and the memory service log sizes and ids
|
|
128
|
+
instead of prompts, paths, queries and facts. A consumer that parsed the
|
|
129
|
+
old `→ Tool: name(args)` line reads the tool name before ` by `. Results,
|
|
130
|
+
the ledger, the A2A status updates and `melchizedek-chat`'s own rendering
|
|
131
|
+
are unchanged.
|
|
132
|
+
|
|
133
|
+
### Fixed
|
|
134
|
+
|
|
135
|
+
- **Dynamic client registration finds an MCP server that publishes its
|
|
136
|
+
protected-resource metadata only in its 401** (ADR 0124). Discovery now
|
|
137
|
+
sends the MCP server an unauthenticated initialize first and, on a 401,
|
|
138
|
+
reads the Bearer challenge's `resource_metadata` in `WWW-Authenticate`
|
|
139
|
+
(RFC 9728 5.1) before the well-known URLs, which stay the fallback. The URL
|
|
140
|
+
the header names passes the operator's OAuth host allowlist and the SSRF
|
|
141
|
+
guard before any request, as every discovered host does, and is refused by
|
|
142
|
+
name when it does not. A grant that names no `scopes` registers and asks
|
|
143
|
+
with the challenge's `scope`. The header is read by a bounded, linear
|
|
144
|
+
tokenizer; a malformed or oversized one is ignored. Additive in
|
|
145
|
+
`melchizedek-agents/tools/oauthDiscovery`: `parseBearerChallenge`,
|
|
146
|
+
`BearerChallenge`, `MAX_CHALLENGE_HEADER`, and
|
|
147
|
+
`DiscoveredAuthorization.challengeScopes`. An allowlist or SSRF refusal of
|
|
148
|
+
the MCP server itself now names the role `MCP server`.
|
|
149
|
+
|
|
150
|
+
## 1.2.0 — 2026-10-09
|
|
151
|
+
|
|
152
|
+
Release 1.2.0 carries pauses and consent further down a turn and gives the
|
|
153
|
+
YAML its last v2 keys (ADRs 0117–0123). A delegated subagent may run skill
|
|
154
|
+
scripts and ask for OAuth consent; a nested workflow pauses the turn as a
|
|
155
|
+
dispatch route or a workflow node; a nested dispatch syndicate routes as it
|
|
156
|
+
does at the top; static credentials go only to hosts the operator binds;
|
|
157
|
+
`tool_choice:` and `reasoning: xhigh | max` complete the provider-neutral
|
|
158
|
+
keys; a background job's checkpoint has a cap, and a durable run resumes
|
|
159
|
+
inside a dispatch route. `melchizedek-setup` is the new onboarding command.
|
|
160
|
+
|
|
161
|
+
### Upgrade first
|
|
162
|
+
|
|
163
|
+
Read this list before deploying 1.2.0 over 1.1.0.
|
|
164
|
+
|
|
165
|
+
- **The older spelling's `reasoningEffort: xhigh` and `max` now reach the
|
|
166
|
+
provider** (ADR 0117). Since 1.0.0 they were read by nothing and sent
|
|
167
|
+
nowhere; an agent that still carries one now asks its model for that
|
|
168
|
+
effort (or the model's highest, see Added), and beside a `thinkingConfig`
|
|
169
|
+
that says `high` the word wins. Such an agent thinks harder and costs
|
|
170
|
+
more. Remove the word to keep the old behaviour.
|
|
171
|
+
- **`ReasoningLevel` (`melchizedek-agents/models/contract`) gains `xhigh`
|
|
172
|
+
and `max`**, and `REASONING_BUDGETS` gains both keys (16,384 each,
|
|
173
|
+
`high`'s budget). An exhaustive `Record<ReasoningLevel, …>` or a `switch`
|
|
174
|
+
over the levels no longer type-checks without them (ADR 0117).
|
|
175
|
+
- **A nested dispatch syndicate answers with its route's text, not its
|
|
176
|
+
classifier's JSON** (ADR 0120). A `yaml_reference` to a plan-dispatch
|
|
177
|
+
syndicate used to compile to its classifier alone, so its caller got the
|
|
178
|
+
routing verdict and its routes never ran; a prompt or parser that relied
|
|
179
|
+
on that verdict sees the specialist's answer now. A gate or skill scripts
|
|
180
|
+
on one of its routes is no longer a load error. `compileSubagentSpec`
|
|
181
|
+
refuses a reference to a dispatch syndicate by name: compile it with
|
|
182
|
+
`compileEntrySpec`.
|
|
183
|
+
- **Child session keys for routes and nodes carry their kind and the agent
|
|
184
|
+
path** (ADR 0119, ADR 0120). A nested syndicate or nested workflow run as
|
|
185
|
+
a dispatch route is filed under `<app>/route:<route>`, and as a workflow
|
|
186
|
+
node under `<walk's app>/node:<node>` (`app/route:Writer/node:Inner` two
|
|
187
|
+
levels down), no longer under the entry's name alone, so it no longer
|
|
188
|
+
shares a row with a same-named entry of another syndicate, and neither
|
|
189
|
+
can share a key with a delegated subagent's (`<app>/<caller>/<subagent>`,
|
|
190
|
+
unchanged). A session 1.1.0 stored under the entry's name, or under
|
|
191
|
+
`<app>/<entry>`, is still continued when the entry ran in that
|
|
192
|
+
conversation before; nothing stored is rewritten. Code that read the
|
|
193
|
+
walk's events at `{ appName: '<entry>' }` or `<app>/<entry>` reads them
|
|
194
|
+
at the kind key now.
|
|
195
|
+
- **`melchizedek-doctor --check` exits 1 on a grant whose hosts the OAuth
|
|
196
|
+
host allowlist refuses.** The doctor already printed each such grant
|
|
197
|
+
(`✗ … is not one of them`, `MELCHIZEDEK_OAUTH_HOSTS`, ADR 0114) and still
|
|
198
|
+
exited 0; a CI step that runs `--check` against a served syndicate now
|
|
199
|
+
fails on it. A blocked syndicate, a runtime problem and the OAuth and
|
|
200
|
+
credential setup's problems fail it as before.
|
|
201
|
+
|
|
202
|
+
### Added
|
|
203
|
+
|
|
204
|
+
- **Skill scripts on a delegated subagent.** `skills.scripts: local` is no
|
|
205
|
+
longer a load error on a delegated subagent (or a nested delegate
|
|
206
|
+
syndicate's): a `run_skill_script` call there pauses the turn
|
|
207
|
+
`input-required` with `approval.path`, and the decision runs or refuses the
|
|
208
|
+
script in the subagent before its caller continues. An agent a map node
|
|
209
|
+
runs still may not carry scripts (ADR 0118).
|
|
210
|
+
- **OAuth consent inside a delegated subagent.** A subagent's
|
|
211
|
+
`authorization_code` tool (an `mcp_auth` or OpenAPI `auth.oauth2` grant)
|
|
212
|
+
now asks for a missing grant instead of answering `not_connected`: the turn
|
|
213
|
+
ends `input-required` with `consent`, whose new optional `path` names the
|
|
214
|
+
agents from the turn's own down to the one that asked (`PendingConsent.path`;
|
|
215
|
+
the A2A `consent_request` data part carries `path` too). The callback stores
|
|
216
|
+
the grant under the conversation's app, and the next message resumes the
|
|
217
|
+
subagent's call. The host allowlist's checks are unchanged. The
|
|
218
|
+
systems_operator template's comment says authorization_code works on its
|
|
219
|
+
Systems subagent (ADR 0118).
|
|
220
|
+
- **Nested dispatch syndicates route as at the top**
|
|
221
|
+
([ADR 0120](./wiki/decisions/0120-nested-dispatch-syndicates-route-as-at-the-top.md)).
|
|
222
|
+
A `yaml_reference` to a plan-dispatch syndicate runs as a turn of its own
|
|
223
|
+
on its own conversation, wherever it appears (a delegated subagent, a
|
|
224
|
+
dispatch route, a workflow node): its classifier picks one of its routes
|
|
225
|
+
and the route answers, under the turn's `max_steps`, deadline and cancel.
|
|
226
|
+
Approvals, `ask_user` questions and OAuth consent on its routes, and
|
|
227
|
+
inside a route's own delegation, pause the turn `input-required` with
|
|
228
|
+
the path (`["Boss", "Team", "Ops"]` delegated, `["Team", "Ops"]` as a
|
|
229
|
+
route), over `runSyndicateTurn` and A2A; the answer resumes that route
|
|
230
|
+
without classifying again. Its grants are stored under the root's app.
|
|
231
|
+
As a workflow node it fails on a consent pause. A route carrying the
|
|
232
|
+
entry's own name, a `map` node over one, and a reference cycle below it
|
|
233
|
+
are refused by name before any model call. Surface:
|
|
234
|
+
`melchizedek-agents/compile` gains the `DispatchSpec` type, a
|
|
235
|
+
`{ kind: 'dispatch'; dispatch: DispatchSpec }` variant on `EntrySpec` and
|
|
236
|
+
`SpecTool`, and an optional `WorkflowSpec.dispatches`; `melchizedek-agents/runtime/turnControl`
|
|
237
|
+
gains the optional `TurnControl.nestedDispatch` hook and the
|
|
238
|
+
`NestedDispatchRun` and `NestedDispatchEnd` types. The generated
|
|
239
|
+
`syndicate.schema.json` describes `yaml_reference` accordingly.
|
|
240
|
+
- **Static credentials go only to hosts the operator binds** (ADR 0122).
|
|
241
|
+
`MELCHIZEDEK_CREDENTIAL_HOSTS="TRACKER_TOKEN=api.tracker.example.com;…"`,
|
|
242
|
+
or `createA2AApp({ credentialHosts })`, binds each credential variable a
|
|
243
|
+
YAML sends (`bearer_env`, `api_key.env`, `client_secret_env`) to its hosts.
|
|
244
|
+
Unset, nothing changes: `melchizedek-serve` warns at boot and
|
|
245
|
+
`melchizedek-doctor` shows a `credentials` warning naming each unbound
|
|
246
|
+
variable. Set, it is the whole list, checked when a syndicate loads, when
|
|
247
|
+
it compiles and before each send; a refused call sends nothing. New
|
|
248
|
+
modules `melchizedek-agents/tools/credentialHosts` and
|
|
249
|
+
`melchizedek-agents/tools/credentialUses` (through the existing
|
|
250
|
+
`./tools/*` export); `openApiServers` in `tools/openapiTools`;
|
|
251
|
+
`DoctorResult.credentials`; the server's banner gains a `creds` line,
|
|
252
|
+
and `oauthServerSetup` returns `credentialSummary`.
|
|
253
|
+
- **`tool_choice:`**, a v2 agent key (ADR 0117): `auto` (the default),
|
|
254
|
+
`none`, `required` (some tool) or `{ name: <tool> }` (that tool). It
|
|
255
|
+
replaces `generateContentConfig.toolConfig.functionCallingConfig`, may not
|
|
256
|
+
sit beside it, and is refused on a `yaml_reference` or `a2a_agent_url`
|
|
257
|
+
subagent. Each provider sends it as before, weakening a forced choice
|
|
258
|
+
where it must (`llm.tool_choice.weakened`).
|
|
259
|
+
- **`reasoning: xhigh` and `reasoning: max`** (ADR 0117). They reach the
|
|
260
|
+
models that take them: both as `output_config.effort` on Claude's adaptive
|
|
261
|
+
generations, `max` on Kimi K3 (and `xhigh` rounds up to it, so K3 can be
|
|
262
|
+
sent `max` again), `xhigh` on GPT-5.2 and later and on grok-4.7. Every
|
|
263
|
+
other path sends the model's highest setting (`high`, Gemini's `HIGH`,
|
|
264
|
+
or `high`'s 16,384-token budget on Claude 4.6 and earlier and Gemini 2.x;
|
|
265
|
+
`high` on a gateway for any id) and marks the `llm.request` span
|
|
266
|
+
`llm.reasoning.weakened` with the level asked for. The capability
|
|
267
|
+
matrix states each path: `REASONING_ABOVE_HIGH`
|
|
268
|
+
(`melchizedek-agents/models/capabilities`), rendered under
|
|
269
|
+
`npm run doctor -- --matrix`.
|
|
270
|
+
- `melchizedek-agents/models/reasoning` exports `effortCeiling(model)`,
|
|
271
|
+
`effortWord(model, setting, ceiling?)`, `isAboveHigh` and
|
|
272
|
+
`REASONING_ORDER`. `ChatCompletionsAdapter` gains the protected hooks
|
|
273
|
+
`reasoningCeiling(model)` and `effortFor(model, setting)`.
|
|
274
|
+
- **A cap on a background job's checkpoint**
|
|
275
|
+
([ADR 0121](./wiki/decisions/0121-checkpoint-cap-and-dispatch-route-resume.md)).
|
|
276
|
+
A checkpoint above `MELCHIZEDEK_CHECKPOINT_MAX_BYTES` (the worker's
|
|
277
|
+
variable; a positive whole number of bytes of JSON, default 5 MiB) is
|
|
278
|
+
not stored: the job keeps its previous checkpoint, the save still reports
|
|
279
|
+
whether the claim holds (a cancel still stops the run), and one log line
|
|
280
|
+
names the job id and the sizes. New in `melchizedek-agents/tools/taskTools`:
|
|
281
|
+
`TaskBackendOptions` (`checkpointMaxBytes`, `log`), `fileTaskBackendWith`,
|
|
282
|
+
`checkpointJson`, `checkpointMaxBytesSetting`, `DEFAULT_CHECKPOINT_MAX_BYTES`
|
|
283
|
+
and `CHECKPOINT_MAX_BYTES_ENV`; `PostgresStorageOptions.taskQueue` passes
|
|
284
|
+
the options to the Postgres queue. The file store's checkpoint sidecar is
|
|
285
|
+
written compact; one written by 1.1.0 still reads.
|
|
286
|
+
- **`melchizedek-setup`, the onboarding command** (new bin; `npm run setup`
|
|
287
|
+
in a clone). A menu of nine authentication levels (no key / local
|
|
288
|
+
Ollama, one provider's key, several, a gateway key, Vertex AI / Bedrock /
|
|
289
|
+
Azure credentials, per-caller keys when serving, caller identities
|
|
290
|
+
through `A2A_AUTH`, OAuth tool grants, and subscription sign-ins), each
|
|
291
|
+
with a startup guide: the variables to set (names and shapes only), the
|
|
292
|
+
doctor check, the shipped templates and examples that run there, and the
|
|
293
|
+
first commands. `--auto` reads the doctor's result and prints the guide
|
|
294
|
+
for the highest level it detects, never a value; `--level <id|n>` prints
|
|
295
|
+
one guide; `--write-env` creates `.env` from `.env.example` with the
|
|
296
|
+
level's names blank, never over an existing file and only when git
|
|
297
|
+
ignores `.env` (ADR 0123).
|
|
298
|
+
- **`ONBOARDING.md`** ships in the package: the same guides, generated from
|
|
299
|
+
the same code (`npm run setup -- --markdown`).
|
|
300
|
+
- **Five onboarding skills** in `skills/`: `melchizedek-onboard` (triage:
|
|
301
|
+
"what do you have?") and `melchizedek-onboard-local`, `-keys`, `-cloud`
|
|
302
|
+
and `-serve`. `npx melchizedek-skills install` puts them in
|
|
303
|
+
`.claude/skills/` and `.agents/skills/` with the rest of the suite.
|
|
304
|
+
- **`melchizedek-skills install --agents-md`** also writes a pointer to the
|
|
305
|
+
skills into the project's `AGENTS.md` (created when absent; only the
|
|
306
|
+
block between its markers is ever rewritten).
|
|
307
|
+
- **The doctor's `serving` line.** When any A2A identity or billing variable
|
|
308
|
+
is set, `npm run doctor` prints the `A2A_AUTH` mode, `A2A_KEY_MODE`,
|
|
309
|
+
which serving variables are set and what the server would refuse to start
|
|
310
|
+
on, by name. `--json` gains `providers` (the providers line as data) and
|
|
311
|
+
`serving`.
|
|
312
|
+
- **`ToolCredentialError.allowlist`** (`melchizedek-agents/tools/auth`,
|
|
313
|
+
with the `HostAllowlist` type): on a `host_refused` error, `'oauth'` when
|
|
314
|
+
the OAuth host allowlist refused a token's host (ADR 0114) and
|
|
315
|
+
`'credential'` when the credential host allowlist refused a client
|
|
316
|
+
secret's (ADR 0122). The constructor takes it as an optional third
|
|
317
|
+
argument.
|
|
318
|
+
|
|
319
|
+
### Changed
|
|
320
|
+
|
|
321
|
+
- **A nested workflow run as a dispatch route or a workflow node pauses the
|
|
322
|
+
turn** ([ADR 0119](./wiki/decisions/0119-workflow-routes-and-nodes-pause-the-turn.md)).
|
|
323
|
+
Its `ask_user` nodes and gated agent nodes (`require_approval`, skill
|
|
324
|
+
scripts) are no longer a load error there: the turn ends `input-required`
|
|
325
|
+
with `result.input` or `result.approval`, whose `path` runs from the route
|
|
326
|
+
or node down to the node that asked (`["Writer", "Send"]`, and further
|
|
327
|
+
down through a node that is itself a nested workflow), over
|
|
328
|
+
`runSyndicateTurn` and A2A. The next message answers it: a decision, or a
|
|
329
|
+
plain-text reply to the question, resumes a paused route without running
|
|
330
|
+
the classifier (`route.decidedBy` `approval` or `answer`); any other
|
|
331
|
+
message while an approval waits repeats the request and runs nothing. A
|
|
332
|
+
workflow node resumes inside the caller's walk. The conversation of a
|
|
333
|
+
paused route ends on the route's pause record (no content, the walk's
|
|
334
|
+
open interrupt ids in `longRunningToolIds`) in place of its answer.
|
|
335
|
+
- `compileEntrySpec` and `compileWorkflowSpec` still accept their
|
|
336
|
+
`delegated` argument; it no longer changes what compiles.
|
|
337
|
+
- **`melchizedek-codemod` converts the rest of `generateContentConfig`**
|
|
338
|
+
(ADR 0117): `toolConfig` becomes `tool_choice:` (mode `ANY` with several
|
|
339
|
+
allowed names becomes `required`, which is what the engine already sent,
|
|
340
|
+
with a note), `reasoningEffort: xhigh | max` becomes `reasoning:`, and
|
|
341
|
+
`thinkingConfig.includeThoughts` is dropped whatever its value: nothing
|
|
342
|
+
reads it, and the Gemini adapter asks for the thought trace whenever
|
|
343
|
+
reasoning is not `none` (a `true` gets a note). Only `toolConfig` mode
|
|
344
|
+
`VALIDATED` and `thinkingBudget: -1` stay, with a note.
|
|
345
|
+
- **The council example's Moderator consults both subagents in one step**
|
|
346
|
+
(`config/agents/examples/council.yaml`). Its instruction asks for the
|
|
347
|
+
Advocate and the Skeptic together, both function calls in one response,
|
|
348
|
+
each given the user's full claim verbatim, so the two run at once under
|
|
349
|
+
`max_concurrency` (ADR 0116). Its role, its three-part verdict and its
|
|
350
|
+
guardrails are unchanged; the YAML keeps its v2 keys. A project that
|
|
351
|
+
copied the example keeps the old prompt until it copies it again.
|
|
352
|
+
- The header comments of `examples/critic.yaml`, `examples/image_production.yaml`
|
|
353
|
+
and `templates/intake_extractor.yaml` say that a schema on a leaf is
|
|
354
|
+
their choice, not a rule: an orchestrator that delegates may hold one
|
|
355
|
+
(ADR 0109). Comments only; the agents are unchanged.
|
|
356
|
+
|
|
357
|
+
### Fixed
|
|
358
|
+
|
|
359
|
+
- **A durable dispatch run resumes inside its agent route** (ADR 0121). A
|
|
360
|
+
background job killed mid-step inside a plan-dispatch route used to start
|
|
361
|
+
over (its checkpoint was set aside); it now resumes from its checkpoint,
|
|
362
|
+
classifying again and storing what an uninterrupted run stores. A nested
|
|
363
|
+
dispatch syndicate's route resumes the same way, and checkpoints 1.1.0
|
|
364
|
+
saved inside a route restore.
|
|
365
|
+
- **An unrecognised `MODEL_GATEWAY` is never echoed.** The doctor (its
|
|
366
|
+
`gateway` line and `--json`), `gatewayProblem()` and the boot log said
|
|
367
|
+
the value back, which may be a key pasted into the wrong variable. They
|
|
368
|
+
now say `MODEL_GATEWAY is set to an unrecognised value (not shown)` and
|
|
369
|
+
name the accepted values (`vercel`, `openrouter`).
|
|
370
|
+
- **A `host_refused` refusal names the allowlist that refused.** A client
|
|
371
|
+
secret refused by the credential host allowlist was reported as the OAuth
|
|
372
|
+
host allowlist's refusal. The message now names
|
|
373
|
+
`MELCHIZEDEK_OAUTH_HOSTS` for a token's host and
|
|
374
|
+
`MELCHIZEDEK_CREDENTIAL_HOSTS` for a client secret's.
|
|
375
|
+
|
|
376
|
+
### Not supported, on purpose
|
|
377
|
+
|
|
378
|
+
- ChatGPT / Codex, Claude.ai and Gemini CLI subscription sign-ins are not a
|
|
379
|
+
way to fund the engine, and nothing reads their tokens. The setup menu's
|
|
380
|
+
level 9 says so and routes to each vendor's API key or cloud platform.
|
|
381
|
+
|
|
9
382
|
## 1.1.0 — 2026-10-09
|
|
10
383
|
|
|
11
384
|
Release 1.1.0 closes workstream 6 of the ADK-independence plan (ADRs
|