@noodleseed/agent-kit 0.81.0 → 0.83.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/manifest.json +269 -269
  2. package/package.json +1 -1
  3. package/skills/claude-code/SKILL.md +1 -1
  4. package/skills/claude-code/authoring-mcp-servers/SKILL.md +1 -1
  5. package/skills/claude-code/building-mcp-apps/SKILL.md +1 -1
  6. package/skills/claude-code/connecting-apis-to-mcp/SKILL.md +1 -1
  7. package/skills/claude-code/creating-product-agent-guides/SKILL.md +1 -1
  8. package/skills/claude-code/debugging-mcp-delivery/SKILL.md +1 -1
  9. package/skills/claude-code/deploying-mcp-services/SKILL.md +1 -1
  10. package/skills/claude-code/designing-mcp-products/SKILL.md +1 -1
  11. package/skills/claude-code/embedding-mcp-assistants/SKILL.md +1 -1
  12. package/skills/claude-code/examples/acme-discovery/README.md +6 -2
  13. package/skills/claude-code/examples/acme-discovery/src/server.ts +2 -8
  14. package/skills/claude-code/examples/acme-discovery/test/server.test.ts +1 -0
  15. package/skills/claude-code/examples/customer-auth/README.md +25 -8
  16. package/skills/claude-code/executing-noodle-plans/SKILL.md +1 -1
  17. package/skills/claude-code/publishing-mcp-integrations/SKILL.md +1 -1
  18. package/skills/claude-code/references/embedded-assistant.md +22 -13
  19. package/skills/claude-code/references/sdk-surface.md +1 -0
  20. package/skills/claude-code/reporting-noodle-feedback/SKILL.md +1 -1
  21. package/skills/claude-code/verifying-mcp-delivery/SKILL.md +1 -1
  22. package/skills/claude-code/wrapping-existing-applications/SKILL.md +1 -1
  23. package/skills/codex/SKILL.md +1 -1
  24. package/skills/codex/authoring-mcp-servers/SKILL.md +1 -1
  25. package/skills/codex/building-mcp-apps/SKILL.md +1 -1
  26. package/skills/codex/connecting-apis-to-mcp/SKILL.md +1 -1
  27. package/skills/codex/creating-product-agent-guides/SKILL.md +1 -1
  28. package/skills/codex/debugging-mcp-delivery/SKILL.md +1 -1
  29. package/skills/codex/deploying-mcp-services/SKILL.md +1 -1
  30. package/skills/codex/designing-mcp-products/SKILL.md +1 -1
  31. package/skills/codex/embedding-mcp-assistants/SKILL.md +1 -1
  32. package/skills/codex/examples/acme-discovery/README.md +6 -2
  33. package/skills/codex/examples/acme-discovery/src/server.ts +2 -8
  34. package/skills/codex/examples/acme-discovery/test/server.test.ts +1 -0
  35. package/skills/codex/examples/customer-auth/README.md +25 -8
  36. package/skills/codex/executing-noodle-plans/SKILL.md +1 -1
  37. package/skills/codex/publishing-mcp-integrations/SKILL.md +1 -1
  38. package/skills/codex/references/embedded-assistant.md +22 -13
  39. package/skills/codex/references/sdk-surface.md +1 -0
  40. package/skills/codex/reporting-noodle-feedback/SKILL.md +1 -1
  41. package/skills/codex/verifying-mcp-delivery/SKILL.md +1 -1
  42. package/skills/codex/wrapping-existing-applications/SKILL.md +1 -1
@@ -541,9 +541,15 @@ then aborts and clears the prior session and transcript. The sample fails closed
541
541
  fallback is replaced with a form generated from `requestedSchema`. A production renderer must show the
542
542
  complete confirmation review and both decisions. For `data-view`, map `resourceUri` or `tool` and the
543
543
  bounded/redacted result to a component already trusted by this application only when intentionally replacing
544
- the linked App with a native UI. Otherwise use `NoodleAppView`; JSON result data is not the App UI. Its
545
- semantic lifecycle identity is the client plus `view.id` plus `view.resourceUri`, so parent payload/callback
546
- rerenders keep the iframe and only a different view or unmount tears down the bridge.
544
+ the linked App with a native UI. Otherwise use `<noodle-app-view>` or its React `NoodleAppView` adapter;
545
+ JSON result data is not the App UI. The element's semantic lifecycle identity is the client plus `view.id`
546
+ plus `view.resourceUri`, so parent payload/callback rerenders keep the iframe and only a different view,
547
+ disconnect, or App teardown request retires the bridge.
548
+ App views remain inline by default: the host advertises only inline presentation and rejects a widget's
549
+ fullscreen request. A customer-owned renderer may opt in explicitly with `allowFullscreen` on
550
+ `NoodleAppView` or `allow-fullscreen` on `<noodle-app-view>` only when fullscreen is part of its intended
551
+ experience. When fullscreen is accepted, the shared host adds a top-right exit control that returns the same
552
+ mounted App to inline mode without discarding its state.
547
553
  Never inject `part.data.html`, assign it to `srcdoc`, fetch a `ui://` URI, or reproduce the bridge directly. Pages with a
548
554
  Content-Security-Policy must include the Noodle service origin in both `connect-src` and `frame-src`.
549
555
 
@@ -588,23 +594,33 @@ useEffect(() => {
588
594
 
589
595
  For a chat-first custom host, raw `tool_started` supplies the direct call `id` and technical tool name. Map
590
596
  known tools to concise application copy and use a neutral fallback. Reserve a stable `role="status"` region
591
- for thinking, tool activity, and the view skeleton; switch to the ready `NoodleAppView` on `view_available`
592
- or to `role="alert"` on error. Decorative skeleton shapes stay hidden from assistive technology, and shimmer
597
+ for thinking, tool activity, and the view skeleton; switch to the ready `<noodle-app-view>` (or React
598
+ `NoodleAppView`) on `view_available` or to `role="alert"` on error. Decorative skeleton shapes stay hidden from assistive technology, and shimmer
593
599
  or transition motion is disabled under `prefers-reduced-motion`.
594
600
 
595
601
  Use `${view.id}:${view.resourceUri}` as transport identity. Different call IDs are distinct invocations and
596
602
  must not be deduplicated generically. If this application intentionally owns one current panel for a known
597
603
  resource, declare an application-owned slot for that resource and replace only that slot.
598
604
 
599
- Outside React, subscribe to the DOM-free client directly. It exposes the same conversation as headless AI
600
- SDK `UIMessage` state, including typed confirmation, input, tool-result, and linked-view parts:
605
+ Outside React, subscribe to the DOM-free client directly and use the isolated framework-neutral App host.
606
+ It exposes the same conversation as headless AI SDK `UIMessage` state, including typed confirmation, input,
607
+ tool-result, and linked-view parts, without installing React:
608
+
609
+ ```html
610
+ <noodle-app-view id="assistant-app-view"></noodle-app-view>
611
+ ```
601
612
 
602
613
  ```ts
614
+ import '@noodleseed/assistant/app-view';
603
615
  import { createAssistantClient } from '@noodleseed/assistant/client';
604
616
 
605
617
  const assistant = createAssistantClient({
606
618
  sessionEndpoint: '/api/noodle-assistant/session',
607
619
  });
620
+ const appView = document.querySelector('#assistant-app-view');
621
+ if (!appView) throw new Error('Missing App view host');
622
+ appView.client = assistant;
623
+ appView.theme = resolvedTheme;
608
624
 
609
625
  assistant.subscribeChat((state) => {
610
626
  renderUIMessageState(state);
@@ -613,13 +629,14 @@ assistant.subscribeChat((state) => {
613
629
  if (part.type === 'data-confirmation' && part.data.status === 'pending') {
614
630
  renderConfirmation(part.data, (response) => assistant.respond(part.data.id, response));
615
631
  }
632
+ if (part.type === 'data-view') appView.view = part.data;
616
633
  }
617
634
  }
618
635
  });
619
636
  ```
620
637
 
621
638
  `theme="auto"` follows the operating-system preference, not a SaaS-owned toggle. Pass the resolved
622
- `light`/`dark` theme to `NoodleAssistant` and `NoodleAppView`; updates reach mounted MCP Apps without a
639
+ `light`/`dark` theme to `NoodleAssistant` and `<noodle-app-view>`/`NoodleAppView`; updates reach mounted MCP Apps without a
623
640
  remount. CSS custom properties inherit through the host, and documented `--ns-assistant-*` variables remain
624
641
  the final integration escape hatch. Server `branding` is shared by widgets and the assistant; there is no
625
642
  second branding declaration. Text streams progressively. Expired turns re-exchange and retry once;
@@ -3,7 +3,7 @@ name: executing-noodle-plans
3
3
  description: "Use when the user asks to execute an approved, decision-complete implementation plan for a Noodle Seed project task by task with test-first changes, review, recovery, and final verification."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.81.0 hash:6a9f132ddb79352e -->
6
+ <!-- noodle-skill version:0.83.0 hash:6a9f132ddb79352e -->
7
7
 
8
8
  # Execute a Noodle Seed implementation plan
9
9
 
@@ -3,7 +3,7 @@ name: publishing-mcp-integrations
3
3
  description: "Use when preparing, reviewing, or submitting a Noodle Seed MCP integration to a host or app directory."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.81.0 hash:efffbf82007f935d -->
6
+ <!-- noodle-skill version:0.83.0 hash:efffbf82007f935d -->
7
7
 
8
8
  # publishing-mcp-integrations
9
9
 
@@ -29,7 +29,8 @@ Keep every credential and identity layer separate:
29
29
  | Owner | Values | Destination |
30
30
  | --- | --- | --- |
31
31
  | Noodle operator | Login, selected org/app/env | Plugin-managed CLI profile and explicit target; never the SaaS runtime |
32
- | Noodle deployment | `ASSISTANT_MODEL_BASE_URL`, `ASSISTANT_MODEL`, `ASSISTANT_MODEL_API_KEY` | `noodle variables set` / `noodle secrets set`; never the SaaS environment |
32
+ | Noodle-managed model | No authored provider, model id, URL, or key | Hosted operator state; available only when Noodle has enrolled the exact org/app/env |
33
+ | Operator-provided model | `ASSISTANT_MODEL_BASE_URL`, `ASSISTANT_MODEL`, `ASSISTANT_MODEL_API_KEY` | `noodle variables set` / `noodle secrets set`; never the SaaS environment |
33
34
  | Connector/delegated exchange | Connector credentials and any customer-owned token-exchange client | Noodle managed configuration plus the matching customer backend secret manager |
34
35
  | SaaS backend | `NOODLE_SERVICE_URL`, `NOODLE_ASSISTANT_CLIENT_ID`, `NOODLE_ASSISTANT_CLIENT_SECRET`, `PUBLIC_APP_ORIGIN` | Backend-only environment or secret manager; never browser code or public-prefixed variables |
35
36
  | Browser | Short-lived assistant session only | In memory; never a client secret, model key, connector credential, or raw application session |
@@ -48,11 +49,7 @@ Use the same server tools in the embed; do not create a second tool set. Declare
48
49
  branding: { name: "Acme", accent: "#3157D5" },
49
50
  context: { defaults: { locale: "en-GB", timeZone: "Europe/London" } },
50
51
  assistant: embeddedAssistant({
51
- model: openAICompatible({
52
- baseUrl: variable("ASSISTANT_MODEL_BASE_URL"),
53
- model: variable("ASSISTANT_MODEL"),
54
- apiKey: secret("ASSISTANT_MODEL_API_KEY"),
55
- }),
52
+ model: noodleManaged(),
56
53
  access: authenticatedWebsite({
57
54
  origins: ["http://localhost:3000", "https://app.example.com"],
58
55
  }),
@@ -60,6 +57,8 @@ assistant: embeddedAssistant({
60
57
  }),
61
58
  ```
62
59
 
60
+ `noodleManaged()` is the zero-configuration Cloud path: the public artifact contains only `{ kind: "noodle-managed" }`. It never exposes a provider or model identifier, and it fails closed unless Noodle has enrolled that exact deployment target. For a customer- or self-hosted model, replace it with `openAICompatible({ baseUrl: variable("ASSISTANT_MODEL_BASE_URL"), model: variable("ASSISTANT_MODEL"), apiKey: secret("ASSISTANT_MODEL_API_KEY") })`; that remains the portable BYO path.
61
+
63
62
  Origins are exact: scheme, host, and optional port, with no path, trailing slash, or wildcard. Production origins must be HTTPS; plain HTTP is accepted only for loopback development origins (`http://localhost:<port>`, `http://127.0.0.1:<port>`). `noodle dev` serves the MCP project, not the embedding SaaS. For a public surface it also prints a process-local Embed ID and script; mount that script on the separately running loopback website to test anonymous mint, chat, widgets, and confirmation. The local ID is ephemeral, while a hosted deploy provisions the stable ID behind durable admission counters.
64
63
 
65
64
  ## Product workflow guidance
@@ -166,7 +165,7 @@ Local MCP authoring and tests need no account, but an external browser embed nee
166
165
  noodle deploy --org <org> --app <app> --env <env>
167
166
  ```
168
167
 
169
- Deploy preflights the complete target before upload. In an interactive terminal it collects all missing model variables and secrets, then continues. In a non-interactive run it reports every missing name and safe `noodle variables set ... --from-env` / `noodle secrets set ... --from-env` action; perform every action and repeat the same deploy command. Values never appear in the preflight report or resume state. Do not put these model values in the embedding SaaS environment. A production deployment may omit a local origin; include a loopback origin only when local browser integration is required.
168
+ Deploy preflights the complete target before upload. `noodleManaged()` has no customer model variables or secrets; enrollment is hosted operator state and an unenrolled target fails closed at serving time. `openAICompatible()` preflight collects or reports every missing model variable and secret with safe `noodle variables set ... --from-env` / `noodle secrets set ... --from-env` actions. Values never appear in the preflight report or resume state. Do not put BYO model values in the embedding SaaS environment. A production deployment may omit a local origin; include a loopback origin only when local browser integration is required.
170
169
 
171
170
  ## Access modes and customer auth
172
171
 
@@ -513,14 +512,19 @@ useEffect(() => {
513
512
 
514
513
  `settle` must await or catch the command promise; the same structured failure also appears in the hook `error` state.
515
514
 
516
- The sample fails closed on input requests until you replace that branch with a form generated from `requestedSchema`. A custom renderer must show the complete confirmation review and both decisions, handle every part it supports, and surface an explicit unsupported state for the rest. For `data-view`, use `NoodleAppView` to render the linked App or deliberately map `resourceUri`/tool plus the bounded redacted `result` to an application-trusted native component. JSON result data is not the linked App UI. Never inject `part.data.html`, assign it to `srcdoc`, fetch a `ui://` URI, or reproduce the bridge with a direct Ext Apps dependency. Do not wrap this client in another chat transport or invent user messages for interaction continuations.
515
+ The sample fails closed on input requests until you replace that branch with a form generated from `requestedSchema`. A custom renderer must show the complete confirmation review and both decisions, handle every part it supports, and surface an explicit unsupported state for the rest. For `data-view`, use the canonical `<noodle-app-view>` host (or its React `NoodleAppView` adapter) to render the linked App, or deliberately map `resourceUri`/tool plus the bounded redacted `result` to an application-trusted native component. JSON result data is not the linked App UI. Never inject `part.data.html`, assign it to `srcdoc`, fetch a `ui://` URI, or reproduce the bridge with a direct Ext Apps dependency. Do not wrap this client in another chat transport or invent user messages for interaction continuations.
516
+
517
+ `<noodle-app-view>` owns one bridge for the semantic view identity: client + `view.id` + `view.resourceUri`; `NoodleAppView` delegates to it. The host retains the iframe across fresh payload/callback/theme rerenders, publishes later resolved-theme changes through MCP Apps host context, and sends standard App teardown when that semantic identity changes, the element disconnects, or the App requests teardown. App views remain inline by default; the host advertises only inline presentation and rejects widget fullscreen requests. Opt in with `allowFullscreen` on `NoodleAppView` or `allow-fullscreen` on `<noodle-app-view>` only when fullscreen is an intentional part of the customer-owned experience. When fullscreen is accepted, the shared host adds an accessible top-right exit control that returns the same mounted App to inline mode without losing its state. Pass the same resolved application theme used by the conversation shell. Do not key an ancestor by a view object or callback. If the embedding page sets Content-Security-Policy, include the Noodle service origin in both `connect-src` and `frame-src`.
517
518
 
518
- `NoodleAppView` owns one bridge for the semantic view identity: client + `view.id` + `view.resourceUri`. It retains the iframe across fresh payload/callback/theme rerenders, reads current payloads through refs, publishes later resolved-theme changes through MCP Apps host context, and sends standard App teardown only when that semantic identity changes or the component unmounts. Pass the same resolved application theme used by the conversation shell. Do not key an ancestor by a view object or callback. If the embedding page sets Content-Security-Policy, include the Noodle service origin in both `connect-src` and `frame-src`.
519
+ Outside React, use the same DOM-free client directly and import the isolated App-view entry only when rendering linked Apps. The client keeps the session token in memory, the transcript stays React-free, and the element owns only App presentation:
519
520
 
520
- Outside React, use the same DOM-free client directly. It keeps the session token in memory, exposes a React-free `UIMessage` transcript with typed parts, and never registers a custom element:
521
+ ```html
522
+ <noodle-app-view id="assistant-app-view"></noodle-app-view>
523
+ ```
521
524
 
522
525
  ```ts
523
526
  import { createAssistantClient } from "@noodleseed/assistant/client";
527
+ import "@noodleseed/assistant/app-view";
524
528
 
525
529
  const assistant = createAssistantClient({
526
530
  sessionEndpoint: "/api/assistant/session",
@@ -530,6 +534,11 @@ const assistant = createAssistantClient({
530
534
  }),
531
535
  });
532
536
 
537
+ const appView = document.querySelector("#assistant-app-view");
538
+ if (!appView) throw new Error("Missing App view host");
539
+ appView.client = assistant;
540
+ appView.theme = document.documentElement.classList.contains('dark') ? 'dark' : 'light';
541
+
533
542
  assistant.updateModelContext({
534
543
  content: [{ type: 'text', text: 'The time-off form is mounted.' }],
535
544
  structuredContent: { widget: { name: 'time-off', lifecycle: 'mounted' } },
@@ -548,7 +557,7 @@ assistant.subscribeChat((state) => {
548
557
  pending = { id: part.data.id, requestedSchema: part.data.requestedSchema };
549
558
  }
550
559
  if (part.type === 'data-view') {
551
- renderRegisteredView(part.data.resourceUri, part.data.result);
560
+ appView.view = part.data;
552
561
  }
553
562
  }
554
563
  }
@@ -587,7 +596,7 @@ assistant.subscribe((event) => {
587
596
  });
588
597
  ```
589
598
 
590
- `data-view` means a completed tool has a linked MCP App view. In a customer-owned React renderer, pass that typed part and the existing client to `NoodleAppView`; it retains one bridge for client + `view.id` + `view.resourceUri` and requests standard App teardown on semantic replacement or unmount. That pair is transport identity: different call ids are distinct invocations and must not be deduplicated generically. If the product intentionally owns one current panel for a known resource, declare an application-owned slot map and replace only that slot. Deliberately map the bounded result to an application-trusted native component only when replacing the linked App UI.
599
+ `data-view` means a completed tool has a linked MCP App view. Pass that typed part and the existing client to `<noodle-app-view>` in Vue, Angular, or plain DOM, or to its `NoodleAppView` React adapter. It retains one bridge for client + `view.id` + `view.resourceUri` and requests standard App teardown on semantic replacement, disconnect, or App request. That pair is transport identity: different call ids are distinct invocations and must not be deduplicated generically. If the product intentionally owns one current panel for a known resource, declare an application-owned slot map and replace only that slot. Deliberately map the bounded result to an application-trusted native component only when replacing the linked App UI.
591
600
 
592
601
  `clientContext` and typed `pageContext` are recomputed for each turn. `updateContext(...)` remains the legacy session-exchange context; `updatePageContext(...)` replaces the fresh per-turn application hint. `updateModelContext({ content, structuredContent })` publishes one cohesive renderer snapshot for later message turns without starting a turn; every call replaces the prior snapshot rather than merging fields. These are untrusted data, not conversation history or authorization input, and the boundaries reject credential-shaped or unbounded updates. A message may re-exchange once after a pre-execution `401`; the client never auto-retries interaction decisions. `tool_proposed.arguments` is a complete schema-aware review projection and, for connector-backed tools, names the sole exact connector version/operation/resolved arguments. Sensitive/write-only fields are redacted; truncating or omitting any non-sensitive action field fails closed. Accept is bound to the server-held action and claims at most one execution attempt—clients cannot replace it. Normal terminal outcomes scrub private arguments and continuations immediately; only an accepted action still executing retains them for the one-hour unknown-outcome recovery window, after which it records `interaction_outcome_unknown` and scrubs. Without downstream idempotency this is not an exactly-once business-effect guarantee. To reconcile a lost response, explicitly repeat the same id and decision: the service returns its durable stored outcome without re-execution.
593
602
 
@@ -612,7 +621,7 @@ Devtools privacy gate: default model and connector exercises to synthetic or moc
612
621
 
613
622
  - Node.js 20+ for `@noodleseed/assistant/server`.
614
623
  - The package ships ESM and CommonJS with full export conditions; no bundler aliases, `transpilePackages`, or ambient type shims are needed. If resolution fails, the installed package version is outdated: update `@noodleseed/assistant` instead of adding workarounds.
615
- - TypeScript `moduleResolution` `bundler` or `node16` recommended; classic `node` also resolves the `/client`, `/react`, `/react/client`, and `/server` subpaths.
624
+ - TypeScript `moduleResolution` `bundler` or `node16` recommended; classic `node` also resolves the `/app-view`, `/client`, `/react`, `/react/client`, and `/server` subpaths.
616
625
 
617
626
  ## Verify the boundary
618
627
 
@@ -65,6 +65,7 @@ Platform helper connectors are explicit subpath imports from `@noodleseed/one/pl
65
65
  - `knowledge`
66
66
  - `managedSecret`
67
67
  - `meilisearch`
68
+ - `noodleManaged`
68
69
  - `openAICompatible`
69
70
  - `publicWebsite`
70
71
  - `site`
@@ -3,7 +3,7 @@ name: reporting-noodle-feedback
3
3
  description: "Use when a Noodle Seed bug, misleading instruction, missing capability, or concrete product improvement should be proposed to the user."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.81.0 hash:0f404109f4845683 -->
6
+ <!-- noodle-skill version:0.83.0 hash:0f404109f4845683 -->
7
7
 
8
8
  # reporting-noodle-feedback
9
9
 
@@ -3,7 +3,7 @@ name: verifying-mcp-delivery
3
3
  description: "Use when proving a Noodle Seed MCP project works at a named compile, local, connector, App, host, deployment, or production evidence level."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.81.0 hash:6ef6ef551e26b78e -->
6
+ <!-- noodle-skill version:0.83.0 hash:6ef6ef551e26b78e -->
7
7
 
8
8
  # verifying-mcp-delivery
9
9
 
@@ -3,7 +3,7 @@ name: wrapping-existing-applications
3
3
  description: "Use when an existing application has no stable usable API and needs a read-only, identity-first Noodle Seed integration plan before implementation."
4
4
  ---
5
5
 
6
- <!-- noodle-skill version:0.81.0 hash:eccc3c158dcafba8 -->
6
+ <!-- noodle-skill version:0.83.0 hash:eccc3c158dcafba8 -->
7
7
 
8
8
  # wrapping-existing-applications
9
9