@noodleseed/agent-kit 0.29.0 → 0.30.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/manifest.json +13 -13
- package/package.json +1 -1
- package/skills/claude-code/SKILL.md +3 -3
- package/skills/claude-code/examples/food-ordering/README.md +3 -2
- package/skills/claude-code/references/authoring-workflow.md +1 -1
- package/skills/claude-code/references/connect-an-api.md +7 -8
- package/skills/claude-code/references/embedded-assistant.md +9 -1
- package/skills/claude-code/references/troubleshooting.md +1 -1
- package/skills/codex/SKILL.md +3 -3
- package/skills/codex/examples/food-ordering/README.md +3 -2
- package/skills/codex/references/authoring-workflow.md +1 -1
- package/skills/codex/references/connect-an-api.md +7 -8
- package/skills/codex/references/embedded-assistant.md +9 -1
- package/skills/codex/references/troubleshooting.md +1 -1
package/manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"packageVersion": "0.
|
|
2
|
+
"packageVersion": "0.30.1",
|
|
3
3
|
"files": [
|
|
4
4
|
{
|
|
5
5
|
"path": "skills/codex/SKILL.md",
|
|
6
|
-
"sha256": "
|
|
6
|
+
"sha256": "4e2de1199627d9a194ed2ae0985f440288f895ee82ae65935ebf37385affe6c6",
|
|
7
7
|
"agentTarget": "codex"
|
|
8
8
|
},
|
|
9
9
|
{
|
|
@@ -28,17 +28,17 @@
|
|
|
28
28
|
},
|
|
29
29
|
{
|
|
30
30
|
"path": "skills/codex/references/authoring-workflow.md",
|
|
31
|
-
"sha256": "
|
|
31
|
+
"sha256": "719b5ba7b04ce8c96129ac00809683889552b1bb56cba3a2ce11b9f9466ae672",
|
|
32
32
|
"agentTarget": "codex"
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "skills/codex/references/embedded-assistant.md",
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "ae70a4fdac98b74c59897f16691d3655c94bdd0b06510329b84b651b2333d33a",
|
|
37
37
|
"agentTarget": "codex"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
40
40
|
"path": "skills/codex/references/connect-an-api.md",
|
|
41
|
-
"sha256": "
|
|
41
|
+
"sha256": "b2ab03691502794d0e8b328d81a906636c9a65623abeddd51ce9658a4542fc4b",
|
|
42
42
|
"agentTarget": "codex"
|
|
43
43
|
},
|
|
44
44
|
{
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
60
|
"path": "skills/codex/references/troubleshooting.md",
|
|
61
|
-
"sha256": "
|
|
61
|
+
"sha256": "238a8d0f4ff8635ed8b0bc63db734634c44ba82e78a3851dc50c85486e1fb942",
|
|
62
62
|
"agentTarget": "codex"
|
|
63
63
|
},
|
|
64
64
|
{
|
|
@@ -278,7 +278,7 @@
|
|
|
278
278
|
},
|
|
279
279
|
{
|
|
280
280
|
"path": "skills/codex/examples/food-ordering/README.md",
|
|
281
|
-
"sha256": "
|
|
281
|
+
"sha256": "013e0734831996d692c3ec314c7457156818089ace8e39ab79a5bf6d74262631",
|
|
282
282
|
"agentTarget": "codex"
|
|
283
283
|
},
|
|
284
284
|
{
|
|
@@ -378,7 +378,7 @@
|
|
|
378
378
|
},
|
|
379
379
|
{
|
|
380
380
|
"path": "skills/claude-code/SKILL.md",
|
|
381
|
-
"sha256": "
|
|
381
|
+
"sha256": "ed60e53c77c3e71d162ab1040c75ad648e51d7c7ccf867794801216afe246651",
|
|
382
382
|
"agentTarget": "claude-code"
|
|
383
383
|
},
|
|
384
384
|
{
|
|
@@ -403,17 +403,17 @@
|
|
|
403
403
|
},
|
|
404
404
|
{
|
|
405
405
|
"path": "skills/claude-code/references/authoring-workflow.md",
|
|
406
|
-
"sha256": "
|
|
406
|
+
"sha256": "719b5ba7b04ce8c96129ac00809683889552b1bb56cba3a2ce11b9f9466ae672",
|
|
407
407
|
"agentTarget": "claude-code"
|
|
408
408
|
},
|
|
409
409
|
{
|
|
410
410
|
"path": "skills/claude-code/references/embedded-assistant.md",
|
|
411
|
-
"sha256": "
|
|
411
|
+
"sha256": "ae70a4fdac98b74c59897f16691d3655c94bdd0b06510329b84b651b2333d33a",
|
|
412
412
|
"agentTarget": "claude-code"
|
|
413
413
|
},
|
|
414
414
|
{
|
|
415
415
|
"path": "skills/claude-code/references/connect-an-api.md",
|
|
416
|
-
"sha256": "
|
|
416
|
+
"sha256": "b2ab03691502794d0e8b328d81a906636c9a65623abeddd51ce9658a4542fc4b",
|
|
417
417
|
"agentTarget": "claude-code"
|
|
418
418
|
},
|
|
419
419
|
{
|
|
@@ -433,7 +433,7 @@
|
|
|
433
433
|
},
|
|
434
434
|
{
|
|
435
435
|
"path": "skills/claude-code/references/troubleshooting.md",
|
|
436
|
-
"sha256": "
|
|
436
|
+
"sha256": "238a8d0f4ff8635ed8b0bc63db734634c44ba82e78a3851dc50c85486e1fb942",
|
|
437
437
|
"agentTarget": "claude-code"
|
|
438
438
|
},
|
|
439
439
|
{
|
|
@@ -653,7 +653,7 @@
|
|
|
653
653
|
},
|
|
654
654
|
{
|
|
655
655
|
"path": "skills/claude-code/examples/food-ordering/README.md",
|
|
656
|
-
"sha256": "
|
|
656
|
+
"sha256": "013e0734831996d692c3ec314c7457156818089ace8e39ab79a5bf6d74262631",
|
|
657
657
|
"agentTarget": "claude-code"
|
|
658
658
|
},
|
|
659
659
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noodleseed/agent-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.30.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Self-checking, self-updating agent skills for the Noodle Seed CLI. Authored in this repo by @noodle-borg/agent-kit; this is the published, independently-versioned canonical skills artifact the CLI fetches and verifies.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: noodle-seed
|
|
3
3
|
description: Use when building, validating, testing, deploying, or operating a local or hosted Noodle Seed MCP server or app authored in TypeScript with the noodle CLI.
|
|
4
|
-
version: 0.
|
|
5
|
-
hash:
|
|
4
|
+
version: 0.30.1
|
|
5
|
+
hash: d16ddb93b02b757a
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Noodle Seed
|
|
@@ -24,7 +24,7 @@ Before authoring, design the experience — the funnel/handoff boundary, tools,
|
|
|
24
24
|
3. **Validate** — `noodle validate --json`; on failure `{ok:false,error:{code,message,fix,next,errors:[{code,path,message}]}}` — the per-field detail is in `error.errors[]`.
|
|
25
25
|
4. **Repair** — fix each `error.errors[]` entry at its `path`, then re-run `noodle validate --json`; `noodle validate --fix-prompt` emits ready-to-apply repair prose. Never freeform re-edit (see `references/compile-errors.md`).
|
|
26
26
|
5. **Smoke** — `noodle test --json`: local compile plus a loopback MCP smoke.
|
|
27
|
-
6. **Prove real output** — `validate`/`test` prove a connector tool *compiles and registers*, not that its response mapping returns data. Set the secret
|
|
27
|
+
6. **Prove real output** — `validate`/`test` prove a connector tool *compiles and registers*, not that its response mapping returns data. Set the secret on the same effective local target with `noodle secrets set <NAME> --runtime local --from-env <ENV>` (see `references/connect-an-api.md`), then run a live read — `noodle tools call <read_tool> --args '{...}'` executes the connector against the real API in-process — and confirm the mapped fields are populated, not `undefined`, before trusting it. Only run a live write if it is safe/approved.
|
|
28
28
|
7. **Apps/widgets/embed** — `noodle check --json` (add `--target chatgpt|claude|embedded-assistant`), then `noodle devtools`; use `references/widgets-and-apps.md` for MCP Apps and `references/embedded-assistant.md` for a SaaS embed.
|
|
29
29
|
8. **Deploy** — `noodle deploy`; auth fails clean with `error.next` = `noodle login` (see `references/deploy-and-ops.md`).
|
|
30
30
|
9. **Wire into a host** — `noodle connect <codex|claude-code|chatgpt>` (prove it in a real host per `references/test-in-hosts.md`; debug symptoms with `references/troubleshooting.md`).
|
|
@@ -20,7 +20,7 @@ private customer data.
|
|
|
20
20
|
| React app runtime kit | `@noodleseed/one/react` supplies app flow, shell/nav/view, async state, form, quantity, choice, and handoff primitives |
|
|
21
21
|
| Multi-step widget flow | One React shell navigates stores, menu, item customization, cart, review, and handoff views through `useAppFlow` |
|
|
22
22
|
| Invocation context | `server.context` sets locale/time-zone defaults, derives an ambient service area/date, and makes the same snapshot available to tools and the reserved `noodle_context` MCP adapter |
|
|
23
|
-
| Structured missing input | `plan_order` uses `ctx.elicit` to collect a fulfilment method and date
|
|
23
|
+
| Structured missing input | `plan_order` uses `ctx.elicit` to collect a fulfilment method and date through embedded/headless forms, standard bidirectional elicitation, a linked MCP App form, or an exact structured conversational retry on stateless hosts |
|
|
24
24
|
| Model-visible widget state | `useUpdateModelContext` publishes one cohesive replacement snapshot when supported; `useWidgetLifecycle` auto-publishes mounted/cancelled/dismissed and reports author-owned submitted milestones for future context (not host-presentation proof), while the user-triggered submit pairs `useSendFollowUpMessage` for an immediate reply |
|
|
25
25
|
| Handoff | `handoff.allowedDomains` allows only `https://orders.example.com` checkout URLs |
|
|
26
26
|
| Progressive enhancement | Non-Apps hosts still receive stores, featured items, and a readable fallback summary |
|
|
@@ -34,7 +34,8 @@ Like the comprehensive default `noodle init my-app` scaffold, this flagship keep
|
|
|
34
34
|
while making each individual widget view focused; server capability breadth and screen density are separate.
|
|
35
35
|
The compiled initial widget should normally remain under the 1 MiB performance recommendation; Noodle Seed's
|
|
36
36
|
hard ceilings are 10 MiB per compiled widget and 20 MiB across one deployment. Run `noodle check` to see raw
|
|
37
|
-
and gzip-estimated sizes
|
|
37
|
+
and gzip-estimated sizes. Deploy requests are gzip-compressed as one stream so repeated self-contained React
|
|
38
|
+
runtime bytes deduplicate on the wire without a cross-tenant CDN. Keep menu images or large live datasets in assets/resources and app-only tools
|
|
38
39
|
rather than embedding them into the initial HTML bundle.
|
|
39
40
|
|
|
40
41
|
## Local Author Loop
|
|
@@ -273,7 +273,7 @@ tool('prepare_time_off', {
|
|
|
273
273
|
});
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
-
Use a stable lowercase/number/underscore id and a flat form of string/number/integer/boolean, string choices or multi-select, with optional `email`, `uri`, `date`, or `date-time` formats. Nested objects and credential-shaped fields fail with `invalid_elicitation_schema`. Every interactive flow must place all `ctx.elicit` calls before its first connector operation or compilation fails with `invalid_elicitation_flow`. Embedded/headless clients receive `input_requested`; bidirectional MCP transports map the primitive to standard form `elicitation/create`.
|
|
276
|
+
Use a stable lowercase/number/underscore id and a flat form of string/number/integer/boolean, string choices or multi-select, with optional `email`, `uri`, `date`, or `date-time` formats. Nested objects and credential-shaped fields fail with `invalid_elicitation_schema`. Every interactive flow must place all `ctx.elicit` calls before its first connector operation or compilation fails with `invalid_elicitation_flow`. Embedded/headless clients receive `input_requested`; bidirectional MCP transports map the primitive to standard form `elicitation/create`. On stateless hosts, the adapter returns a structured non-executing `interaction_unavailable` result; linked Apps render its business-user form and retry in request `_meta`, while models can use the advertised reserved retry field. Accept validates and replays only the operation-free input prefix; invalid content returns `arg_invalid`, and decline/cancel stop. Elicitation gathers missing input and does not replace confirmation. In a flow marked `confirm: true`, every eligible `input_requested` precedes `tool_proposed`; the final proposal reviews the original input, elicited values, and sole exact connector action. Accept is bound to that action and only then may execution start. A confirmable flow may contain at most one connector operation; additional operations fail with `invalid_confirmation_flow`. MCP uses final standard form confirmation on capable bidirectional transports and fails closed otherwise. Setting `interactions: { confirmationFallback: "host" }` in the server options explicitly trusts native host approval only when confirmation transport is unavailable and after every elicited field is collected; it is never inferred from client name and does not replace authorization. Omitted or `false` annotations execute directly; hints alone never gate. `annotations.action({ confirm: true })` explicitly enables confirmation; `annotations.action({ confirm: false })` explicitly preserves direct execution.
|
|
277
277
|
|
|
278
278
|
## Compute connector example
|
|
279
279
|
|
|
@@ -22,7 +22,7 @@ managed secret and reference it only as `secret(...)`:
|
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
24
|
export SOME_API_KEY=… # the user sets this; it never appears in a file or prompt
|
|
25
|
-
noodle secrets set SOME_API_KEY --runtime local --
|
|
25
|
+
noodle secrets set SOME_API_KEY --runtime local --from-env SOME_API_KEY # same effective target as local dev/test/devtools
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
In `server.ts` the key is only ever `secret("SOME_API_KEY")` — keep the raw value out of code, tests,
|
|
@@ -126,17 +126,16 @@ model" section of `references/authoring-workflow.md`.
|
|
|
126
126
|
|
|
127
127
|
## Set the secret for local runs
|
|
128
128
|
|
|
129
|
-
`
|
|
129
|
+
Local `dev`, smoke commands, secrets, and variables resolve one effective target: explicit flags, then the project link, then the saved CLI target, then local defaults. Set the secret through that same target:
|
|
130
130
|
|
|
131
131
|
```sh
|
|
132
|
-
#
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
noodle secrets set SOME_API_KEY --runtime local --scope env --org local --app <app-slug> --env dev --from-env SOME_API_KEY
|
|
132
|
+
# Canonical: writes to the effective local environment used by dev/test/devtools:
|
|
133
|
+
noodle secrets set SOME_API_KEY --runtime local --from-env SOME_API_KEY
|
|
134
|
+
# Explicit flags remain available when intentionally testing a different local target:
|
|
135
|
+
noodle secrets set SOME_API_KEY --runtime local --scope env --org <org> --app <app> --env <env> --from-env SOME_API_KEY
|
|
137
136
|
```
|
|
138
137
|
|
|
139
|
-
Local secrets live in `./.env.noodle` (never commit it).
|
|
138
|
+
Local secrets live in `./.env.noodle` (never commit it). A required `secret(...)` or `variable(...)` that cannot resolve fails boot closed. `noodle tools call` / `noodle test` / `noodle dev` / `noodle devtools` stop before exposing an empty endpoint and print the exact effective target plus recovery command.
|
|
140
139
|
|
|
141
140
|
## Prove real output
|
|
142
141
|
|
|
@@ -120,6 +120,14 @@ noodle assistant clients create --name web --org <org> --app <app> --env <env>
|
|
|
120
120
|
|
|
121
121
|
The CLI writes `{ clientId, clientSecret }` to a mode-`0600` file and prints only its path. Move the values into the SaaS backend secret manager without printing or committing them. Rotation invalidates the previous secret.
|
|
122
122
|
|
|
123
|
+
Validate the active deployment, backend credential, exact origin, and delegated credential exchanges without invoking a business tool:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
noodle assistant doctor --origin "$PUBLIC_APP_ORIGIN" --org <org> --app <app> --env <env>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The doctor reads `NOODLE_ASSISTANT_CLIENT_ID` / `NOODLE_ASSISTANT_CLIENT_SECRET` or the saved mode-0600 client file and never prints the secret. Pass `--user-id <real-test-user>` only when the downstream exchange requires an existing application user.
|
|
130
|
+
|
|
123
131
|
## Integrate the customer backend
|
|
124
132
|
|
|
125
133
|
Read the customer repository lockfile or `packageManager` field and install `@noodleseed/assistant` with that existing package manager; never introduce a second lockfile.
|
|
@@ -176,7 +184,7 @@ The callback records declarative fulfilment at author time; the shared runtime e
|
|
|
176
184
|
|
|
177
185
|
## Structured missing input
|
|
178
186
|
|
|
179
|
-
A tool authored with `ctx.elicit({ id, message, input })` produces `input_requested` when it reaches missing input. Built-in and headless renderers present it and call `respond(id, { action: "accept", content })`; decline/cancel stop. Accepted content is schema-validated and completed steps are not rerun; invalid content returns `arg_invalid` and keeps the interaction pending. Elicitation gathers an input and does not approve a later write. Every interactive flow collects elicited input before its first connector operation; every eligible `input_requested` precedes `tool_proposed`. In a `confirm: true` flow, the final proposal reviews original input, elicited values, and the sole exact connector action; a confirmable flow has at most one connector operation. Accept is bound to that action. Bidirectional MCP
|
|
187
|
+
A tool authored with `ctx.elicit({ id, message, input })` produces `input_requested` when it reaches missing input. Built-in and headless renderers present it and call `respond(id, { action: "accept", content })`; decline/cancel stop. Accepted content is schema-validated and completed steps are not rerun; invalid content returns `arg_invalid` and keeps the interaction pending. Elicitation gathers an input and does not approve a later write. Every interactive flow collects elicited input before its first connector operation; every eligible `input_requested` precedes `tool_proposed`. In a `confirm: true` flow, the final proposal reviews original input, elicited values, and the sole exact connector action; a confirmable flow has at most one connector operation. Accept is bound to that action. Bidirectional MCP maps missing input to standard `elicitation/create`. On a stateless host, a linked MCP App presents the same normal-user form and re-calls the tool through standard `tools/call`, carrying replay answers in request `_meta` so approval copy contains only business fields; without Apps, the model receives the exact structured schema and an advertised reserved retry field. Both paths replay only the operation-free input prefix and never expose runtime continuation or environment state. Setting `interactions: { confirmationFallback: "host" }` explicitly trusts native host approval only after every elicited field is collected and only when confirmation transport is unavailable; embedded/headless confirmation remains Noodle-owned. Omitted or false annotations execute directly; hints never gate.
|
|
180
188
|
|
|
181
189
|
## Verified session context (identity and claims)
|
|
182
190
|
|
|
@@ -27,6 +27,6 @@ For protocol/conformance checks, the headless harness is `@mcpjam/cli`, not a `n
|
|
|
27
27
|
| Tools error only after deploy | Runtime/config differences surface hosted (secrets, connector reachability) | Run `noodle smoke`, then `noodle metrics --agent-output` and `noodle events --tool <name> --status tool_error --json`; check `noodle secrets list` scope |
|
|
28
28
|
| A connector tool validates and lists, but returns empty or `undefined` fields | The `response` mapping references a path the API does not return — usually the wrong root (a `.body` segment, when the parsed body is bound directly to `${response}`) or the wrong shape | Run `noodle tools call <name> --args <json>` with the secret set and compare the mapped result to the API’s real JSON; map from `${response.<path>}` (the body is `${response}`, there is no `.body`) and use bracket array indices (`${response.items[0].id}`) |
|
|
29
29
|
| A connector should return a list but returns one item, `undefined`, or the whole raw objects | A `${response.arr[0]…}` mapping picks ONE element; a response mapping cannot reshape array items and a tool’s Zod output does not strip them at runtime | Bind the whole array with `${response.<arr>}`, then narrow each element in a compute connector (`references/connect-an-api.md` → “Return a list”) |
|
|
30
|
-
| `noodle dev` boots but the loopback returns `-32600 "not found"` (or 404) for a valid server | A required `secret(...)` is unresolved — a missing secret fails compile *closed* at boot so nothing is served; the local secret was set at a scope `noodle dev` does not read |
|
|
30
|
+
| `noodle dev` boots but the loopback returns `-32600 "not found"` (or 404) for a valid server | A required `secret(...)` is unresolved — a missing secret fails compile *closed* at boot so nothing is served; the local secret was set at a scope `noodle dev` does not read | Run `noodle secrets set NAME --runtime local --from-env NAME`; local config and dev resolve the same effective target, and every author-loop command stops with the exact target/recovery command before exposing an empty endpoint (`references/connect-an-api.md` → “Set the secret for local runs”) |
|
|
31
31
|
| Need to invoke a tool from the terminal | Local tools run in-process; the `noodle` CLI is not a general MCP client for **deployed** URLs (there is no `call <url>` verb) | Locally, `noodle tools call <name> --args <json>` (also `noodle resources read` / `noodle prompts get`) runs the tool against the in-process runtime — with the secret set it executes the connector against the real API, so use it to prove mapped output. For a **deployed** URL use MCP Inspector or `npx @mcpjam/cli@latest tools call --url <url> ...` |
|
|
32
32
|
| One customer/session reports a bad answer or protocol error | The failure may be a model/tool error, host protocol error, or connector/runtime error | Run `noodle metrics --agent-output`, then `noodle events --tool <name> --status tool_error --json`; copy the `sessionId` into `noodle events --session <id> --json`, then match timestamps with `noodle logs` |
|
package/skills/codex/SKILL.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: noodle-seed
|
|
3
3
|
description: Use when building, validating, testing, deploying, or operating a local or hosted Noodle Seed MCP server or app authored in TypeScript with the noodle CLI.
|
|
4
|
-
version: 0.
|
|
5
|
-
hash:
|
|
4
|
+
version: 0.30.1
|
|
5
|
+
hash: c2a03a8059656742
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
# Noodle Seed
|
|
@@ -24,7 +24,7 @@ Before authoring, design the experience — the funnel/handoff boundary, tools,
|
|
|
24
24
|
3. **Validate** — `noodle validate --json`; on failure `{ok:false,error:{code,message,fix,next,errors:[{code,path,message}]}}` — the per-field detail is in `error.errors[]`.
|
|
25
25
|
4. **Repair** — fix each `error.errors[]` entry at its `path`, then re-run `noodle validate --json`; `noodle validate --fix-prompt` emits ready-to-apply repair prose. Never freeform re-edit (see `references/compile-errors.md`).
|
|
26
26
|
5. **Smoke** — `noodle test --json`: local compile plus a loopback MCP smoke.
|
|
27
|
-
6. **Prove real output** — `validate`/`test` prove a connector tool *compiles and registers*, not that its response mapping returns data. Set the secret
|
|
27
|
+
6. **Prove real output** — `validate`/`test` prove a connector tool *compiles and registers*, not that its response mapping returns data. Set the secret on the same effective local target with `noodle secrets set <NAME> --runtime local --from-env <ENV>` (see `references/connect-an-api.md`), then run a live read — `noodle tools call <read_tool> --args '{...}'` executes the connector against the real API in-process — and confirm the mapped fields are populated, not `undefined`, before trusting it. Only run a live write if it is safe/approved.
|
|
28
28
|
7. **Apps/widgets/embed** — `noodle check --json` (add `--target chatgpt|claude|embedded-assistant`), then `noodle devtools`; use `references/widgets-and-apps.md` for MCP Apps and `references/embedded-assistant.md` for a SaaS embed.
|
|
29
29
|
8. **Deploy** — `noodle deploy`; auth fails clean with `error.next` = `noodle login` (see `references/deploy-and-ops.md`).
|
|
30
30
|
9. **Wire into a host** — `noodle connect <codex|claude-code|chatgpt>` (prove it in a real host per `references/test-in-hosts.md`; debug symptoms with `references/troubleshooting.md`).
|
|
@@ -20,7 +20,7 @@ private customer data.
|
|
|
20
20
|
| React app runtime kit | `@noodleseed/one/react` supplies app flow, shell/nav/view, async state, form, quantity, choice, and handoff primitives |
|
|
21
21
|
| Multi-step widget flow | One React shell navigates stores, menu, item customization, cart, review, and handoff views through `useAppFlow` |
|
|
22
22
|
| Invocation context | `server.context` sets locale/time-zone defaults, derives an ambient service area/date, and makes the same snapshot available to tools and the reserved `noodle_context` MCP adapter |
|
|
23
|
-
| Structured missing input | `plan_order` uses `ctx.elicit` to collect a fulfilment method and date
|
|
23
|
+
| Structured missing input | `plan_order` uses `ctx.elicit` to collect a fulfilment method and date through embedded/headless forms, standard bidirectional elicitation, a linked MCP App form, or an exact structured conversational retry on stateless hosts |
|
|
24
24
|
| Model-visible widget state | `useUpdateModelContext` publishes one cohesive replacement snapshot when supported; `useWidgetLifecycle` auto-publishes mounted/cancelled/dismissed and reports author-owned submitted milestones for future context (not host-presentation proof), while the user-triggered submit pairs `useSendFollowUpMessage` for an immediate reply |
|
|
25
25
|
| Handoff | `handoff.allowedDomains` allows only `https://orders.example.com` checkout URLs |
|
|
26
26
|
| Progressive enhancement | Non-Apps hosts still receive stores, featured items, and a readable fallback summary |
|
|
@@ -34,7 +34,8 @@ Like the comprehensive default `noodle init my-app` scaffold, this flagship keep
|
|
|
34
34
|
while making each individual widget view focused; server capability breadth and screen density are separate.
|
|
35
35
|
The compiled initial widget should normally remain under the 1 MiB performance recommendation; Noodle Seed's
|
|
36
36
|
hard ceilings are 10 MiB per compiled widget and 20 MiB across one deployment. Run `noodle check` to see raw
|
|
37
|
-
and gzip-estimated sizes
|
|
37
|
+
and gzip-estimated sizes. Deploy requests are gzip-compressed as one stream so repeated self-contained React
|
|
38
|
+
runtime bytes deduplicate on the wire without a cross-tenant CDN. Keep menu images or large live datasets in assets/resources and app-only tools
|
|
38
39
|
rather than embedding them into the initial HTML bundle.
|
|
39
40
|
|
|
40
41
|
## Local Author Loop
|
|
@@ -273,7 +273,7 @@ tool('prepare_time_off', {
|
|
|
273
273
|
});
|
|
274
274
|
```
|
|
275
275
|
|
|
276
|
-
Use a stable lowercase/number/underscore id and a flat form of string/number/integer/boolean, string choices or multi-select, with optional `email`, `uri`, `date`, or `date-time` formats. Nested objects and credential-shaped fields fail with `invalid_elicitation_schema`. Every interactive flow must place all `ctx.elicit` calls before its first connector operation or compilation fails with `invalid_elicitation_flow`. Embedded/headless clients receive `input_requested`; bidirectional MCP transports map the primitive to standard form `elicitation/create`.
|
|
276
|
+
Use a stable lowercase/number/underscore id and a flat form of string/number/integer/boolean, string choices or multi-select, with optional `email`, `uri`, `date`, or `date-time` formats. Nested objects and credential-shaped fields fail with `invalid_elicitation_schema`. Every interactive flow must place all `ctx.elicit` calls before its first connector operation or compilation fails with `invalid_elicitation_flow`. Embedded/headless clients receive `input_requested`; bidirectional MCP transports map the primitive to standard form `elicitation/create`. On stateless hosts, the adapter returns a structured non-executing `interaction_unavailable` result; linked Apps render its business-user form and retry in request `_meta`, while models can use the advertised reserved retry field. Accept validates and replays only the operation-free input prefix; invalid content returns `arg_invalid`, and decline/cancel stop. Elicitation gathers missing input and does not replace confirmation. In a flow marked `confirm: true`, every eligible `input_requested` precedes `tool_proposed`; the final proposal reviews the original input, elicited values, and sole exact connector action. Accept is bound to that action and only then may execution start. A confirmable flow may contain at most one connector operation; additional operations fail with `invalid_confirmation_flow`. MCP uses final standard form confirmation on capable bidirectional transports and fails closed otherwise. Setting `interactions: { confirmationFallback: "host" }` in the server options explicitly trusts native host approval only when confirmation transport is unavailable and after every elicited field is collected; it is never inferred from client name and does not replace authorization. Omitted or `false` annotations execute directly; hints alone never gate. `annotations.action({ confirm: true })` explicitly enables confirmation; `annotations.action({ confirm: false })` explicitly preserves direct execution.
|
|
277
277
|
|
|
278
278
|
## Compute connector example
|
|
279
279
|
|
|
@@ -22,7 +22,7 @@ managed secret and reference it only as `secret(...)`:
|
|
|
22
22
|
|
|
23
23
|
```sh
|
|
24
24
|
export SOME_API_KEY=… # the user sets this; it never appears in a file or prompt
|
|
25
|
-
noodle secrets set SOME_API_KEY --runtime local --
|
|
25
|
+
noodle secrets set SOME_API_KEY --runtime local --from-env SOME_API_KEY # same effective target as local dev/test/devtools
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
In `server.ts` the key is only ever `secret("SOME_API_KEY")` — keep the raw value out of code, tests,
|
|
@@ -126,17 +126,16 @@ model" section of `references/authoring-workflow.md`.
|
|
|
126
126
|
|
|
127
127
|
## Set the secret for local runs
|
|
128
128
|
|
|
129
|
-
`
|
|
129
|
+
Local `dev`, smoke commands, secrets, and variables resolve one effective target: explicit flags, then the project link, then the saved CLI target, then local defaults. Set the secret through that same target:
|
|
130
130
|
|
|
131
131
|
```sh
|
|
132
|
-
#
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
noodle secrets set SOME_API_KEY --runtime local --scope env --org local --app <app-slug> --env dev --from-env SOME_API_KEY
|
|
132
|
+
# Canonical: writes to the effective local environment used by dev/test/devtools:
|
|
133
|
+
noodle secrets set SOME_API_KEY --runtime local --from-env SOME_API_KEY
|
|
134
|
+
# Explicit flags remain available when intentionally testing a different local target:
|
|
135
|
+
noodle secrets set SOME_API_KEY --runtime local --scope env --org <org> --app <app> --env <env> --from-env SOME_API_KEY
|
|
137
136
|
```
|
|
138
137
|
|
|
139
|
-
Local secrets live in `./.env.noodle` (never commit it).
|
|
138
|
+
Local secrets live in `./.env.noodle` (never commit it). A required `secret(...)` or `variable(...)` that cannot resolve fails boot closed. `noodle tools call` / `noodle test` / `noodle dev` / `noodle devtools` stop before exposing an empty endpoint and print the exact effective target plus recovery command.
|
|
140
139
|
|
|
141
140
|
## Prove real output
|
|
142
141
|
|
|
@@ -120,6 +120,14 @@ noodle assistant clients create --name web --org <org> --app <app> --env <env>
|
|
|
120
120
|
|
|
121
121
|
The CLI writes `{ clientId, clientSecret }` to a mode-`0600` file and prints only its path. Move the values into the SaaS backend secret manager without printing or committing them. Rotation invalidates the previous secret.
|
|
122
122
|
|
|
123
|
+
Validate the active deployment, backend credential, exact origin, and delegated credential exchanges without invoking a business tool:
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
noodle assistant doctor --origin "$PUBLIC_APP_ORIGIN" --org <org> --app <app> --env <env>
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The doctor reads `NOODLE_ASSISTANT_CLIENT_ID` / `NOODLE_ASSISTANT_CLIENT_SECRET` or the saved mode-0600 client file and never prints the secret. Pass `--user-id <real-test-user>` only when the downstream exchange requires an existing application user.
|
|
130
|
+
|
|
123
131
|
## Integrate the customer backend
|
|
124
132
|
|
|
125
133
|
Read the customer repository lockfile or `packageManager` field and install `@noodleseed/assistant` with that existing package manager; never introduce a second lockfile.
|
|
@@ -176,7 +184,7 @@ The callback records declarative fulfilment at author time; the shared runtime e
|
|
|
176
184
|
|
|
177
185
|
## Structured missing input
|
|
178
186
|
|
|
179
|
-
A tool authored with `ctx.elicit({ id, message, input })` produces `input_requested` when it reaches missing input. Built-in and headless renderers present it and call `respond(id, { action: "accept", content })`; decline/cancel stop. Accepted content is schema-validated and completed steps are not rerun; invalid content returns `arg_invalid` and keeps the interaction pending. Elicitation gathers an input and does not approve a later write. Every interactive flow collects elicited input before its first connector operation; every eligible `input_requested` precedes `tool_proposed`. In a `confirm: true` flow, the final proposal reviews original input, elicited values, and the sole exact connector action; a confirmable flow has at most one connector operation. Accept is bound to that action. Bidirectional MCP
|
|
187
|
+
A tool authored with `ctx.elicit({ id, message, input })` produces `input_requested` when it reaches missing input. Built-in and headless renderers present it and call `respond(id, { action: "accept", content })`; decline/cancel stop. Accepted content is schema-validated and completed steps are not rerun; invalid content returns `arg_invalid` and keeps the interaction pending. Elicitation gathers an input and does not approve a later write. Every interactive flow collects elicited input before its first connector operation; every eligible `input_requested` precedes `tool_proposed`. In a `confirm: true` flow, the final proposal reviews original input, elicited values, and the sole exact connector action; a confirmable flow has at most one connector operation. Accept is bound to that action. Bidirectional MCP maps missing input to standard `elicitation/create`. On a stateless host, a linked MCP App presents the same normal-user form and re-calls the tool through standard `tools/call`, carrying replay answers in request `_meta` so approval copy contains only business fields; without Apps, the model receives the exact structured schema and an advertised reserved retry field. Both paths replay only the operation-free input prefix and never expose runtime continuation or environment state. Setting `interactions: { confirmationFallback: "host" }` explicitly trusts native host approval only after every elicited field is collected and only when confirmation transport is unavailable; embedded/headless confirmation remains Noodle-owned. Omitted or false annotations execute directly; hints never gate.
|
|
180
188
|
|
|
181
189
|
## Verified session context (identity and claims)
|
|
182
190
|
|
|
@@ -27,6 +27,6 @@ For protocol/conformance checks, the headless harness is `@mcpjam/cli`, not a `n
|
|
|
27
27
|
| Tools error only after deploy | Runtime/config differences surface hosted (secrets, connector reachability) | Run `noodle smoke`, then `noodle metrics --agent-output` and `noodle events --tool <name> --status tool_error --json`; check `noodle secrets list` scope |
|
|
28
28
|
| A connector tool validates and lists, but returns empty or `undefined` fields | The `response` mapping references a path the API does not return — usually the wrong root (a `.body` segment, when the parsed body is bound directly to `${response}`) or the wrong shape | Run `noodle tools call <name> --args <json>` with the secret set and compare the mapped result to the API’s real JSON; map from `${response.<path>}` (the body is `${response}`, there is no `.body`) and use bracket array indices (`${response.items[0].id}`) |
|
|
29
29
|
| A connector should return a list but returns one item, `undefined`, or the whole raw objects | A `${response.arr[0]…}` mapping picks ONE element; a response mapping cannot reshape array items and a tool’s Zod output does not strip them at runtime | Bind the whole array with `${response.<arr>}`, then narrow each element in a compute connector (`references/connect-an-api.md` → “Return a list”) |
|
|
30
|
-
| `noodle dev` boots but the loopback returns `-32600 "not found"` (or 404) for a valid server | A required `secret(...)` is unresolved — a missing secret fails compile *closed* at boot so nothing is served; the local secret was set at a scope `noodle dev` does not read |
|
|
30
|
+
| `noodle dev` boots but the loopback returns `-32600 "not found"` (or 404) for a valid server | A required `secret(...)` is unresolved — a missing secret fails compile *closed* at boot so nothing is served; the local secret was set at a scope `noodle dev` does not read | Run `noodle secrets set NAME --runtime local --from-env NAME`; local config and dev resolve the same effective target, and every author-loop command stops with the exact target/recovery command before exposing an empty endpoint (`references/connect-an-api.md` → “Set the secret for local runs”) |
|
|
31
31
|
| Need to invoke a tool from the terminal | Local tools run in-process; the `noodle` CLI is not a general MCP client for **deployed** URLs (there is no `call <url>` verb) | Locally, `noodle tools call <name> --args <json>` (also `noodle resources read` / `noodle prompts get`) runs the tool against the in-process runtime — with the secret set it executes the connector against the real API, so use it to prove mapped output. For a **deployed** URL use MCP Inspector or `npx @mcpjam/cli@latest tools call --url <url> ...` |
|
|
32
32
|
| One customer/session reports a bad answer or protocol error | The failure may be a model/tool error, host protocol error, or connector/runtime error | Run `noodle metrics --agent-output`, then `noodle events --tool <name> --status tool_error --json`; copy the `sessionId` into `noodle events --session <id> --json`, then match timestamps with `noodle logs` |
|