@noodleseed/agent-kit 0.46.0 → 0.47.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/manifest.json +241 -241
- package/package.json +1 -1
- package/skills/claude-code/SKILL.md +1 -1
- package/skills/claude-code/authoring-mcp-servers/SKILL.md +1 -1
- package/skills/claude-code/building-mcp-apps/SKILL.md +1 -1
- package/skills/claude-code/connecting-apis-to-mcp/SKILL.md +1 -1
- package/skills/claude-code/debugging-mcp-delivery/SKILL.md +1 -1
- package/skills/claude-code/deploying-mcp-services/SKILL.md +1 -1
- package/skills/claude-code/designing-mcp-products/SKILL.md +1 -1
- package/skills/claude-code/embedding-mcp-assistants/SKILL.md +1 -1
- package/skills/claude-code/examples/customer-auth/README.md +27 -1
- package/skills/claude-code/executing-noodle-plans/SKILL.md +1 -1
- package/skills/claude-code/publishing-mcp-integrations/SKILL.md +1 -1
- package/skills/claude-code/references/embedded-assistant.md +38 -2
- package/skills/claude-code/reporting-noodle-feedback/SKILL.md +1 -1
- package/skills/claude-code/verifying-mcp-delivery/SKILL.md +1 -1
- package/skills/codex/SKILL.md +1 -1
- package/skills/codex/authoring-mcp-servers/SKILL.md +1 -1
- package/skills/codex/building-mcp-apps/SKILL.md +1 -1
- package/skills/codex/connecting-apis-to-mcp/SKILL.md +1 -1
- package/skills/codex/debugging-mcp-delivery/SKILL.md +1 -1
- package/skills/codex/deploying-mcp-services/SKILL.md +1 -1
- package/skills/codex/designing-mcp-products/SKILL.md +1 -1
- package/skills/codex/embedding-mcp-assistants/SKILL.md +1 -1
- package/skills/codex/examples/customer-auth/README.md +27 -1
- package/skills/codex/executing-noodle-plans/SKILL.md +1 -1
- package/skills/codex/publishing-mcp-integrations/SKILL.md +1 -1
- package/skills/codex/references/embedded-assistant.md +38 -2
- package/skills/codex/reporting-noodle-feedback/SKILL.md +1 -1
- package/skills/codex/verifying-mcp-delivery/SKILL.md +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noodleseed/agent-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.47.0",
|
|
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",
|
|
@@ -3,7 +3,7 @@ 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
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:cd6ca0d915e6acb9 -->
|
|
7
7
|
|
|
8
8
|
# Noodle Seed
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: authoring-mcp-servers
|
|
|
3
3
|
description: "Use when creating or extending a headless Noodle Seed MCP server, tool, resource, prompt, or typed model-facing capability."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:0b2fd8c7e43fc69f -->
|
|
7
7
|
|
|
8
8
|
# authoring-mcp-servers
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: building-mcp-apps
|
|
|
3
3
|
description: "Use when a Noodle Seed MCP App, widget, interactive card, visual interaction, or host-visible UI is the primary requested outcome."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:f7fa54992c8d7692 -->
|
|
7
7
|
|
|
8
8
|
# building-mcp-apps
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: connecting-apis-to-mcp
|
|
|
3
3
|
description: "Use when credentials, an API URL, an OpenAPI document, or an observed response must become real Noodle Seed MCP behavior."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:1e86b8704f407bd3 -->
|
|
7
7
|
|
|
8
8
|
# connecting-apis-to-mcp
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: debugging-mcp-delivery
|
|
|
3
3
|
description: "Use when an existing Noodle Seed MCP project has a concrete validation, runtime, connector, App, host, deployment, or production failure."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:aa715bae12041d7c -->
|
|
7
7
|
|
|
8
8
|
# debugging-mcp-delivery
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: deploying-mcp-services
|
|
|
3
3
|
description: "Use when the user explicitly requests a Noodle Seed hosted link, configuration write, deployment, access change, rollback, or connection write."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:93e735b7ffb45df1 -->
|
|
7
7
|
|
|
8
8
|
# deploying-mcp-services
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: designing-mcp-products
|
|
|
3
3
|
description: "Use when a Noodle Seed MCP product idea needs conversational fit, user benefit, scope, interaction, or evidence design before implementation."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:76cce86729cffbee -->
|
|
7
7
|
|
|
8
8
|
# designing-mcp-products
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: embedding-mcp-assistants
|
|
|
3
3
|
description: "Use when embedding a Noodle assistant into an existing SaaS or web application with browser, identity, session, and credential boundaries."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:5d8f40f904d6ab4b -->
|
|
7
7
|
|
|
8
8
|
# embedding-mcp-assistants
|
|
9
9
|
|
|
@@ -207,7 +207,7 @@ and returns the AI SDK transcript plus the canonical client commands:
|
|
|
207
207
|
```tsx
|
|
208
208
|
'use client';
|
|
209
209
|
|
|
210
|
-
import { useState } from 'react';
|
|
210
|
+
import { useEffect, useState } from 'react';
|
|
211
211
|
import { NoodleAppView } from '@noodleseed/assistant/react';
|
|
212
212
|
import { useNoodleAssistant } from '@noodleseed/assistant/react/client';
|
|
213
213
|
|
|
@@ -335,6 +335,32 @@ rerenders keep the iframe and only a different view or unmount tears down the br
|
|
|
335
335
|
Never inject `part.data.html`, assign it to `srcdoc`, fetch a `ui://` URI, or reproduce the bridge directly. Pages with a
|
|
336
336
|
Content-Security-Policy must include the Noodle service origin in both `connect-src` and `frame-src`.
|
|
337
337
|
|
|
338
|
+
If the application deliberately sends a first turn on mount, do not combine a persistent "sent" ref with a
|
|
339
|
+
mount effect. React Strict Mode can abort that provisional request and then suppress the stable remount.
|
|
340
|
+
Schedule the send after the provisional cleanup and settle its promise:
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
useEffect(() => {
|
|
344
|
+
let active = true;
|
|
345
|
+
queueMicrotask(() => {
|
|
346
|
+
if (active) settle(client.sendMessage(initialMessage));
|
|
347
|
+
});
|
|
348
|
+
return () => {
|
|
349
|
+
active = false;
|
|
350
|
+
};
|
|
351
|
+
}, [client, initialMessage]);
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
For a chat-first custom host, raw `tool_started` supplies the direct call `id` and technical tool name. Map
|
|
355
|
+
known tools to concise application copy and use a neutral fallback. Reserve a stable `role="status"` region
|
|
356
|
+
for thinking, tool activity, and the view skeleton; switch to the ready `NoodleAppView` on `view_available`
|
|
357
|
+
or to `role="alert"` on error. Decorative skeleton shapes stay hidden from assistive technology, and shimmer
|
|
358
|
+
or transition motion is disabled under `prefers-reduced-motion`.
|
|
359
|
+
|
|
360
|
+
Use `${view.id}:${view.resourceUri}` as transport identity. Different call IDs are distinct invocations and
|
|
361
|
+
must not be deduplicated generically. If this application intentionally owns one current panel for a known
|
|
362
|
+
resource, declare an application-owned slot for that resource and replace only that slot.
|
|
363
|
+
|
|
338
364
|
Outside React, subscribe to the DOM-free client directly. It exposes the same conversation as headless AI
|
|
339
365
|
SDK `UIMessage` state, including typed confirmation, input, tool-result, and linked-view parts:
|
|
340
366
|
|
|
@@ -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.
|
|
6
|
+
<!-- noodle-skill version:0.47.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.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:efffbf82007f935d -->
|
|
7
7
|
|
|
8
8
|
# publishing-mcp-integrations
|
|
9
9
|
|
|
@@ -255,7 +255,7 @@ For a customer-owned React renderer, use the renderer-free hook. It owns client
|
|
|
255
255
|
```tsx
|
|
256
256
|
"use client";
|
|
257
257
|
|
|
258
|
-
import { useState } from "react";
|
|
258
|
+
import { useEffect, useState } from "react";
|
|
259
259
|
import { NoodleAppView } from "@noodleseed/assistant/react";
|
|
260
260
|
import { useNoodleAssistant } from "@noodleseed/assistant/react/client";
|
|
261
261
|
|
|
@@ -370,6 +370,22 @@ export function CustomAssistant({ principalKey, resolvedTheme }: { principalKey:
|
|
|
370
370
|
|
|
371
371
|
`principalKey` is a browser-local identity for the authenticated user/tenant and is never sent to Noodle. Change it whenever that principal changes; the hook then aborts and clears the previous session and transcript. The hook does not register `<noodle-assistant>` or render Noodle markup.
|
|
372
372
|
|
|
373
|
+
If the product deliberately sends a first turn on mount, make the effect cleanup-aware. React Strict Mode discards the provisional effect, so a persistent "already sent" ref can suppress the stable remount:
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
useEffect(() => {
|
|
377
|
+
let active = true;
|
|
378
|
+
queueMicrotask(() => {
|
|
379
|
+
if (active) settle(client.sendMessage(initialMessage));
|
|
380
|
+
});
|
|
381
|
+
return () => {
|
|
382
|
+
active = false;
|
|
383
|
+
};
|
|
384
|
+
}, [client, initialMessage]);
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
`settle` must await or catch the command promise; the same structured failure also appears in the hook `error` state.
|
|
388
|
+
|
|
373
389
|
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.
|
|
374
390
|
|
|
375
391
|
`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`.
|
|
@@ -424,7 +440,27 @@ if (pending) {
|
|
|
424
440
|
|
|
425
441
|
`subscribeChat` immediately emits a detached `{ messages, status, error? }` snapshot and then emits as `UIMessage.parts` change. Text uses `text`; Noodle confirmations, input requests, tool results, and linked views use `data-confirmation`, `data-input-request`, `data-tool-result`, and `data-view`. Interaction data moves through pending/submitting/accepted/declined/cancelled. Use raw `subscribe(...)` only for transport/session lifecycle events that are not transcript content.
|
|
426
442
|
|
|
427
|
-
|
|
443
|
+
For a chat-first custom host, raw `tool_started` carries the direct invocation call `id` and technical `tool` name before execution. Map known tools through a finite application-owned label table and use a neutral fallback such as "Working"; never mechanically expose an internal identifier as customer copy. Reserve one stable region with `role="status"` and `aria-live="polite"` for thinking, the mapped activity label, and the linked-view skeleton. `view_available` makes the view ready; raw `error` or chat `error` replaces it with `role="alert"`. Mark decorative skeleton shapes `aria-hidden="true"` and disable shimmer/transitions under `@media (prefers-reduced-motion: reduce)`.
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
const activityByTool: Readonly<Record<string, string>> = {
|
|
447
|
+
list_open_items: "Loading open items",
|
|
448
|
+
};
|
|
449
|
+
const viewSlots = new Map([["ui://workspace/current", "current-workspace"]]);
|
|
450
|
+
|
|
451
|
+
assistant.subscribe((event) => {
|
|
452
|
+
if (event.event === "tool_started") {
|
|
453
|
+
showActivity(event.data.id, activityByTool[event.data.tool] ?? "Working");
|
|
454
|
+
}
|
|
455
|
+
if (event.event === "view_available") {
|
|
456
|
+
const key = viewSlots.get(event.data.resourceUri) ?? `${event.data.id}:${event.data.resourceUri}`;
|
|
457
|
+
showReadyView(key, event.data);
|
|
458
|
+
}
|
|
459
|
+
if (event.event === "error") showActivityError(event.data.code);
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
`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.
|
|
428
464
|
|
|
429
465
|
`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.
|
|
430
466
|
|
|
@@ -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.
|
|
6
|
+
<!-- noodle-skill version:0.47.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.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:6ef6ef551e26b78e -->
|
|
7
7
|
|
|
8
8
|
# verifying-mcp-delivery
|
|
9
9
|
|
package/skills/codex/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ 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
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:cd6ca0d915e6acb9 -->
|
|
7
7
|
|
|
8
8
|
# Noodle Seed
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: authoring-mcp-servers
|
|
|
3
3
|
description: "Use when creating or extending a headless Noodle Seed MCP server, tool, resource, prompt, or typed model-facing capability."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:0b2fd8c7e43fc69f -->
|
|
7
7
|
|
|
8
8
|
# authoring-mcp-servers
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: building-mcp-apps
|
|
|
3
3
|
description: "Use when a Noodle Seed MCP App, widget, interactive card, visual interaction, or host-visible UI is the primary requested outcome."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:f7fa54992c8d7692 -->
|
|
7
7
|
|
|
8
8
|
# building-mcp-apps
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: connecting-apis-to-mcp
|
|
|
3
3
|
description: "Use when credentials, an API URL, an OpenAPI document, or an observed response must become real Noodle Seed MCP behavior."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:1e86b8704f407bd3 -->
|
|
7
7
|
|
|
8
8
|
# connecting-apis-to-mcp
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: debugging-mcp-delivery
|
|
|
3
3
|
description: "Use when an existing Noodle Seed MCP project has a concrete validation, runtime, connector, App, host, deployment, or production failure."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:aa715bae12041d7c -->
|
|
7
7
|
|
|
8
8
|
# debugging-mcp-delivery
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: deploying-mcp-services
|
|
|
3
3
|
description: "Use when the user explicitly requests a Noodle Seed hosted link, configuration write, deployment, access change, rollback, or connection write."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:93e735b7ffb45df1 -->
|
|
7
7
|
|
|
8
8
|
# deploying-mcp-services
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: designing-mcp-products
|
|
|
3
3
|
description: "Use when a Noodle Seed MCP product idea needs conversational fit, user benefit, scope, interaction, or evidence design before implementation."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:76cce86729cffbee -->
|
|
7
7
|
|
|
8
8
|
# designing-mcp-products
|
|
9
9
|
|
|
@@ -3,7 +3,7 @@ name: embedding-mcp-assistants
|
|
|
3
3
|
description: "Use when embedding a Noodle assistant into an existing SaaS or web application with browser, identity, session, and credential boundaries."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
<!-- noodle-skill version:0.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:5d8f40f904d6ab4b -->
|
|
7
7
|
|
|
8
8
|
# embedding-mcp-assistants
|
|
9
9
|
|
|
@@ -207,7 +207,7 @@ and returns the AI SDK transcript plus the canonical client commands:
|
|
|
207
207
|
```tsx
|
|
208
208
|
'use client';
|
|
209
209
|
|
|
210
|
-
import { useState } from 'react';
|
|
210
|
+
import { useEffect, useState } from 'react';
|
|
211
211
|
import { NoodleAppView } from '@noodleseed/assistant/react';
|
|
212
212
|
import { useNoodleAssistant } from '@noodleseed/assistant/react/client';
|
|
213
213
|
|
|
@@ -335,6 +335,32 @@ rerenders keep the iframe and only a different view or unmount tears down the br
|
|
|
335
335
|
Never inject `part.data.html`, assign it to `srcdoc`, fetch a `ui://` URI, or reproduce the bridge directly. Pages with a
|
|
336
336
|
Content-Security-Policy must include the Noodle service origin in both `connect-src` and `frame-src`.
|
|
337
337
|
|
|
338
|
+
If the application deliberately sends a first turn on mount, do not combine a persistent "sent" ref with a
|
|
339
|
+
mount effect. React Strict Mode can abort that provisional request and then suppress the stable remount.
|
|
340
|
+
Schedule the send after the provisional cleanup and settle its promise:
|
|
341
|
+
|
|
342
|
+
```tsx
|
|
343
|
+
useEffect(() => {
|
|
344
|
+
let active = true;
|
|
345
|
+
queueMicrotask(() => {
|
|
346
|
+
if (active) settle(client.sendMessage(initialMessage));
|
|
347
|
+
});
|
|
348
|
+
return () => {
|
|
349
|
+
active = false;
|
|
350
|
+
};
|
|
351
|
+
}, [client, initialMessage]);
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
For a chat-first custom host, raw `tool_started` supplies the direct call `id` and technical tool name. Map
|
|
355
|
+
known tools to concise application copy and use a neutral fallback. Reserve a stable `role="status"` region
|
|
356
|
+
for thinking, tool activity, and the view skeleton; switch to the ready `NoodleAppView` on `view_available`
|
|
357
|
+
or to `role="alert"` on error. Decorative skeleton shapes stay hidden from assistive technology, and shimmer
|
|
358
|
+
or transition motion is disabled under `prefers-reduced-motion`.
|
|
359
|
+
|
|
360
|
+
Use `${view.id}:${view.resourceUri}` as transport identity. Different call IDs are distinct invocations and
|
|
361
|
+
must not be deduplicated generically. If this application intentionally owns one current panel for a known
|
|
362
|
+
resource, declare an application-owned slot for that resource and replace only that slot.
|
|
363
|
+
|
|
338
364
|
Outside React, subscribe to the DOM-free client directly. It exposes the same conversation as headless AI
|
|
339
365
|
SDK `UIMessage` state, including typed confirmation, input, tool-result, and linked-view parts:
|
|
340
366
|
|
|
@@ -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.
|
|
6
|
+
<!-- noodle-skill version:0.47.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.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:efffbf82007f935d -->
|
|
7
7
|
|
|
8
8
|
# publishing-mcp-integrations
|
|
9
9
|
|
|
@@ -255,7 +255,7 @@ For a customer-owned React renderer, use the renderer-free hook. It owns client
|
|
|
255
255
|
```tsx
|
|
256
256
|
"use client";
|
|
257
257
|
|
|
258
|
-
import { useState } from "react";
|
|
258
|
+
import { useEffect, useState } from "react";
|
|
259
259
|
import { NoodleAppView } from "@noodleseed/assistant/react";
|
|
260
260
|
import { useNoodleAssistant } from "@noodleseed/assistant/react/client";
|
|
261
261
|
|
|
@@ -370,6 +370,22 @@ export function CustomAssistant({ principalKey, resolvedTheme }: { principalKey:
|
|
|
370
370
|
|
|
371
371
|
`principalKey` is a browser-local identity for the authenticated user/tenant and is never sent to Noodle. Change it whenever that principal changes; the hook then aborts and clears the previous session and transcript. The hook does not register `<noodle-assistant>` or render Noodle markup.
|
|
372
372
|
|
|
373
|
+
If the product deliberately sends a first turn on mount, make the effect cleanup-aware. React Strict Mode discards the provisional effect, so a persistent "already sent" ref can suppress the stable remount:
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
useEffect(() => {
|
|
377
|
+
let active = true;
|
|
378
|
+
queueMicrotask(() => {
|
|
379
|
+
if (active) settle(client.sendMessage(initialMessage));
|
|
380
|
+
});
|
|
381
|
+
return () => {
|
|
382
|
+
active = false;
|
|
383
|
+
};
|
|
384
|
+
}, [client, initialMessage]);
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
`settle` must await or catch the command promise; the same structured failure also appears in the hook `error` state.
|
|
388
|
+
|
|
373
389
|
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.
|
|
374
390
|
|
|
375
391
|
`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`.
|
|
@@ -424,7 +440,27 @@ if (pending) {
|
|
|
424
440
|
|
|
425
441
|
`subscribeChat` immediately emits a detached `{ messages, status, error? }` snapshot and then emits as `UIMessage.parts` change. Text uses `text`; Noodle confirmations, input requests, tool results, and linked views use `data-confirmation`, `data-input-request`, `data-tool-result`, and `data-view`. Interaction data moves through pending/submitting/accepted/declined/cancelled. Use raw `subscribe(...)` only for transport/session lifecycle events that are not transcript content.
|
|
426
442
|
|
|
427
|
-
|
|
443
|
+
For a chat-first custom host, raw `tool_started` carries the direct invocation call `id` and technical `tool` name before execution. Map known tools through a finite application-owned label table and use a neutral fallback such as "Working"; never mechanically expose an internal identifier as customer copy. Reserve one stable region with `role="status"` and `aria-live="polite"` for thinking, the mapped activity label, and the linked-view skeleton. `view_available` makes the view ready; raw `error` or chat `error` replaces it with `role="alert"`. Mark decorative skeleton shapes `aria-hidden="true"` and disable shimmer/transitions under `@media (prefers-reduced-motion: reduce)`.
|
|
444
|
+
|
|
445
|
+
```ts
|
|
446
|
+
const activityByTool: Readonly<Record<string, string>> = {
|
|
447
|
+
list_open_items: "Loading open items",
|
|
448
|
+
};
|
|
449
|
+
const viewSlots = new Map([["ui://workspace/current", "current-workspace"]]);
|
|
450
|
+
|
|
451
|
+
assistant.subscribe((event) => {
|
|
452
|
+
if (event.event === "tool_started") {
|
|
453
|
+
showActivity(event.data.id, activityByTool[event.data.tool] ?? "Working");
|
|
454
|
+
}
|
|
455
|
+
if (event.event === "view_available") {
|
|
456
|
+
const key = viewSlots.get(event.data.resourceUri) ?? `${event.data.id}:${event.data.resourceUri}`;
|
|
457
|
+
showReadyView(key, event.data);
|
|
458
|
+
}
|
|
459
|
+
if (event.event === "error") showActivityError(event.data.code);
|
|
460
|
+
});
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
`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.
|
|
428
464
|
|
|
429
465
|
`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.
|
|
430
466
|
|
|
@@ -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.
|
|
6
|
+
<!-- noodle-skill version:0.47.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.
|
|
6
|
+
<!-- noodle-skill version:0.47.0 hash:6ef6ef551e26b78e -->
|
|
7
7
|
|
|
8
8
|
# verifying-mcp-delivery
|
|
9
9
|
|