@noodleseed/agent-kit 0.21.0 → 0.21.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 +7 -7
- package/package.json +1 -1
- package/skills/claude-code/SKILL.md +1 -1
- package/skills/claude-code/examples/hello/src/server.ts +3 -1
- package/skills/claude-code/references/embedded-assistant.md +50 -2
- package/skills/codex/SKILL.md +1 -1
- package/skills/codex/examples/hello/src/server.ts +3 -1
- package/skills/codex/references/embedded-assistant.md +50 -2
package/manifest.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
|
-
"packageVersion": "0.21.
|
|
2
|
+
"packageVersion": "0.21.1",
|
|
3
3
|
"files": [
|
|
4
4
|
{
|
|
5
5
|
"path": "skills/codex/SKILL.md",
|
|
6
|
-
"sha256": "
|
|
6
|
+
"sha256": "4a48b0a357c2dfab02ff191d68a9ebb47ad8396a63f476a0f60ba69cc7b943ad",
|
|
7
7
|
"agentTarget": "codex"
|
|
8
8
|
},
|
|
9
9
|
{
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
},
|
|
34
34
|
{
|
|
35
35
|
"path": "skills/codex/references/embedded-assistant.md",
|
|
36
|
-
"sha256": "
|
|
36
|
+
"sha256": "687666010deb32bb605ccc23aeac8778fd1d02c53d7d8e232b6d0b8aeef77668",
|
|
37
37
|
"agentTarget": "codex"
|
|
38
38
|
},
|
|
39
39
|
{
|
|
@@ -318,7 +318,7 @@
|
|
|
318
318
|
},
|
|
319
319
|
{
|
|
320
320
|
"path": "skills/codex/examples/hello/src/server.ts",
|
|
321
|
-
"sha256": "
|
|
321
|
+
"sha256": "5b7dd35428128cfe0f506054e80b060d8a87ef157b03d2ce94d304b14df6e521",
|
|
322
322
|
"agentTarget": "codex"
|
|
323
323
|
},
|
|
324
324
|
{
|
|
@@ -353,7 +353,7 @@
|
|
|
353
353
|
},
|
|
354
354
|
{
|
|
355
355
|
"path": "skills/claude-code/SKILL.md",
|
|
356
|
-
"sha256": "
|
|
356
|
+
"sha256": "23754f0386b77f112249ca8b948b479792895303f0257ab0961cbbb81a857693",
|
|
357
357
|
"agentTarget": "claude-code"
|
|
358
358
|
},
|
|
359
359
|
{
|
|
@@ -383,7 +383,7 @@
|
|
|
383
383
|
},
|
|
384
384
|
{
|
|
385
385
|
"path": "skills/claude-code/references/embedded-assistant.md",
|
|
386
|
-
"sha256": "
|
|
386
|
+
"sha256": "687666010deb32bb605ccc23aeac8778fd1d02c53d7d8e232b6d0b8aeef77668",
|
|
387
387
|
"agentTarget": "claude-code"
|
|
388
388
|
},
|
|
389
389
|
{
|
|
@@ -668,7 +668,7 @@
|
|
|
668
668
|
},
|
|
669
669
|
{
|
|
670
670
|
"path": "skills/claude-code/examples/hello/src/server.ts",
|
|
671
|
-
"sha256": "
|
|
671
|
+
"sha256": "5b7dd35428128cfe0f506054e80b060d8a87ef157b03d2ce94d304b14df6e521",
|
|
672
672
|
"agentTarget": "claude-code"
|
|
673
673
|
},
|
|
674
674
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noodleseed/agent-kit",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.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,4 +1,4 @@
|
|
|
1
|
-
import { server, tool, z } from '@noodleseed/one';
|
|
1
|
+
import { annotations, server, tool, z } from '@noodleseed/one';
|
|
2
2
|
|
|
3
3
|
export default server(
|
|
4
4
|
'hello',
|
|
@@ -22,6 +22,8 @@ export default server(
|
|
|
22
22
|
output: z.object({
|
|
23
23
|
message: z.string(),
|
|
24
24
|
}),
|
|
25
|
+
// Read-only, closed-world: assistant surfaces run this without a consent prompt.
|
|
26
|
+
annotations: annotations.readOnly(),
|
|
25
27
|
fulfil: ({ input }) => {
|
|
26
28
|
return { message: `Hello, ${input.name}!` };
|
|
27
29
|
},
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- Access modes and customer auth
|
|
9
9
|
- Create the backend client
|
|
10
10
|
- Integrate the customer backend
|
|
11
|
+
- Verified session context (identity and claims)
|
|
11
12
|
- The session response
|
|
12
13
|
- Mount the browser component
|
|
13
14
|
- Toolchain requirements
|
|
@@ -113,6 +114,48 @@ Authenticate before exchange. Source `origin` from trusted server configuration
|
|
|
113
114
|
|
|
114
115
|
`serviceUrl` is the Noodle Seed control-plane base URL: the value `noodle assistant clients create` prints, also stored as `serviceUrl` in `deployment.json`. It is NOT the deployment MCP endpoint (`url`, which ends in `/v1/mcp` and rejects session exchange). Never probe or guess endpoints with real credentials.
|
|
115
116
|
|
|
117
|
+
## Verified session context (identity and claims)
|
|
118
|
+
|
|
119
|
+
The embedding developer defines what authenticated session context the assistant receives. One mechanism, three hops:
|
|
120
|
+
|
|
121
|
+
1. The authenticated backend passes standard identity and any verified claims at session exchange (flat scalars only):
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
const session = await createAssistantSession({
|
|
125
|
+
serviceUrl, clientId, clientSecret, origin,
|
|
126
|
+
user: { id: user.id, email: user.email, name: user.name },
|
|
127
|
+
claims: { displayName: user.name, accountTier: account.tier, region: account.region },
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
2. The server author declares the allowlist in `server.ts` — undeclared claims are dropped at session exchange (never rejected, so backend and server deploys may skew safely):
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
assistant: embeddedAssistant({
|
|
135
|
+
model, allowedOrigins,
|
|
136
|
+
sessionClaims: {
|
|
137
|
+
displayName: { exposeToModel: true },
|
|
138
|
+
accountTier: { exposeToModel: true },
|
|
139
|
+
region: {}, // tools only, never in the prompt
|
|
140
|
+
},
|
|
141
|
+
}),
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
3. Consumption. Tools read the verified identity and declared claims through the `user` scope:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
tool("greet", {
|
|
148
|
+
description: "Greet the signed-in user.",
|
|
149
|
+
input: z.object({}),
|
|
150
|
+
annotations: annotations.readOnly(),
|
|
151
|
+
fulfil: ({ user }) => ({ message: `Hello, ${user.name}!`, tier: user.claims.accountTier }),
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Manifest expressions use `${user.name}`, `${user.email}`, `${user.subject}`, `${user.claims.<key>}`. The model receives one platform identity line automatically: standard identity (name/email) whenever present, plus only the claims marked `exposeToModel: true` — so the assistant greets the actual user and can pass identity into tool arguments. `noodle check --target embedded-assistant` lists the declared claim contract.
|
|
156
|
+
|
|
157
|
+
Page `context` from the widget remains untrusted hint data; verified facts belong in `claims`, never in `context`.
|
|
158
|
+
|
|
116
159
|
## The session response
|
|
117
160
|
|
|
118
161
|
The exchange returns the versioned Embedded Assistant v1 contract. `token`, `expiresAt`, and `endpoints.turns` / `endpoints.toolConfirmations` (absolute URLs) are always present; `configuration` is optional theming data. Forward the body unchanged; the widget posts turns to `endpoints.turns` itself. Do not rebuild, filter, or rewrite the response.
|
|
@@ -142,7 +185,7 @@ The component renders a custom element and must mount client-side. In a Next.js
|
|
|
142
185
|
- Signed-out session exchange returns `401`.
|
|
143
186
|
- The browser network/DOM/storage contains no client secret or model key.
|
|
144
187
|
- The local and production origins match `allowedOrigins` character-for-character.
|
|
145
|
-
-
|
|
188
|
+
- Auto-run requires the full safe-read annotation (`annotations.readOnly()`: read-only, non-destructive, closed-world); unannotated or partially annotated tools always confirm. Writes require confirmation by design.
|
|
146
189
|
- An expired turn re-exchanges once; confirmations never replay.
|
|
147
190
|
- Wrong-origin and malformed-origin requests fail closed.
|
|
148
191
|
|
|
@@ -157,4 +200,9 @@ The component renders a custom element and must mount client-side. In a Next.js
|
|
|
157
200
|
| Validate rejects an origin | Non-loopback HTTP origin in `allowedOrigins` | Use the exact HTTPS production origin; HTTP is only for `localhost`/`127.0.0.1` |
|
|
158
201
|
| Session exchange returns 404 | `serviceUrl` points at the deployment MCP endpoint | Use the control-plane service URL printed by `noodle assistant clients create` |
|
|
159
202
|
| Session exchange returns 403 `origin is not allowed` | Request origin differs from `allowedOrigins` character-for-character | Align the exact scheme/host/port on both sides and redeploy |
|
|
160
|
-
| Hydration or `HTMLElement is not defined` errors | The component mounted during server rendering | Mount client-only (`"use client"` or `next/dynamic` with `ssr: false`) |
|
|
203
|
+
| Hydration or `HTMLElement is not defined` errors | The component mounted during server rendering | Mount client-only (`"use client"` or `next/dynamic` with `ssr: false`) |
|
|
204
|
+
| A read-only tool still asks for confirmation | Its annotations fail the safe-read rule: auto-run requires `readOnlyHint: true`, `destructiveHint: false`, AND `openWorldHint: false` (use `annotations.readOnly()`; `readOnly({ openWorld: true })` confirm-gates) | Fix the annotations; `noodle check --target embedded-assistant` lists every confirm-gated tool |
|
|
205
|
+
| `${user.claims.<key>}` is empty | Claim not declared in `sessionClaims` (or key typo) — undeclared claims are dropped at exchange | Declare the key in `embeddedAssistant({ sessionClaims })` and redeploy |
|
|
206
|
+
| `${user.name}` is empty | Backend did not pass `user.name` to `createAssistantSession` | Pass the verified name from the authenticated backend session |
|
|
207
|
+
| The model does not know a claim you passed | Claim is tools-only | Mark it `exposeToModel: true` in `sessionClaims` |
|
|
208
|
+
| Behavior does not change after `noodle deploy` | Outdated platform: before the 2026-07 fix, clients were pinned to their creation-time deployment | Update the platform; sessions now follow the tenant's active deployment |
|
package/skills/codex/SKILL.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { server, tool, z } from '@noodleseed/one';
|
|
1
|
+
import { annotations, server, tool, z } from '@noodleseed/one';
|
|
2
2
|
|
|
3
3
|
export default server(
|
|
4
4
|
'hello',
|
|
@@ -22,6 +22,8 @@ export default server(
|
|
|
22
22
|
output: z.object({
|
|
23
23
|
message: z.string(),
|
|
24
24
|
}),
|
|
25
|
+
// Read-only, closed-world: assistant surfaces run this without a consent prompt.
|
|
26
|
+
annotations: annotations.readOnly(),
|
|
25
27
|
fulfil: ({ input }) => {
|
|
26
28
|
return { message: `Hello, ${input.name}!` };
|
|
27
29
|
},
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
- Access modes and customer auth
|
|
9
9
|
- Create the backend client
|
|
10
10
|
- Integrate the customer backend
|
|
11
|
+
- Verified session context (identity and claims)
|
|
11
12
|
- The session response
|
|
12
13
|
- Mount the browser component
|
|
13
14
|
- Toolchain requirements
|
|
@@ -113,6 +114,48 @@ Authenticate before exchange. Source `origin` from trusted server configuration
|
|
|
113
114
|
|
|
114
115
|
`serviceUrl` is the Noodle Seed control-plane base URL: the value `noodle assistant clients create` prints, also stored as `serviceUrl` in `deployment.json`. It is NOT the deployment MCP endpoint (`url`, which ends in `/v1/mcp` and rejects session exchange). Never probe or guess endpoints with real credentials.
|
|
115
116
|
|
|
117
|
+
## Verified session context (identity and claims)
|
|
118
|
+
|
|
119
|
+
The embedding developer defines what authenticated session context the assistant receives. One mechanism, three hops:
|
|
120
|
+
|
|
121
|
+
1. The authenticated backend passes standard identity and any verified claims at session exchange (flat scalars only):
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
const session = await createAssistantSession({
|
|
125
|
+
serviceUrl, clientId, clientSecret, origin,
|
|
126
|
+
user: { id: user.id, email: user.email, name: user.name },
|
|
127
|
+
claims: { displayName: user.name, accountTier: account.tier, region: account.region },
|
|
128
|
+
});
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
2. The server author declares the allowlist in `server.ts` — undeclared claims are dropped at session exchange (never rejected, so backend and server deploys may skew safely):
|
|
132
|
+
|
|
133
|
+
```ts
|
|
134
|
+
assistant: embeddedAssistant({
|
|
135
|
+
model, allowedOrigins,
|
|
136
|
+
sessionClaims: {
|
|
137
|
+
displayName: { exposeToModel: true },
|
|
138
|
+
accountTier: { exposeToModel: true },
|
|
139
|
+
region: {}, // tools only, never in the prompt
|
|
140
|
+
},
|
|
141
|
+
}),
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
3. Consumption. Tools read the verified identity and declared claims through the `user` scope:
|
|
145
|
+
|
|
146
|
+
```ts
|
|
147
|
+
tool("greet", {
|
|
148
|
+
description: "Greet the signed-in user.",
|
|
149
|
+
input: z.object({}),
|
|
150
|
+
annotations: annotations.readOnly(),
|
|
151
|
+
fulfil: ({ user }) => ({ message: `Hello, ${user.name}!`, tier: user.claims.accountTier }),
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Manifest expressions use `${user.name}`, `${user.email}`, `${user.subject}`, `${user.claims.<key>}`. The model receives one platform identity line automatically: standard identity (name/email) whenever present, plus only the claims marked `exposeToModel: true` — so the assistant greets the actual user and can pass identity into tool arguments. `noodle check --target embedded-assistant` lists the declared claim contract.
|
|
156
|
+
|
|
157
|
+
Page `context` from the widget remains untrusted hint data; verified facts belong in `claims`, never in `context`.
|
|
158
|
+
|
|
116
159
|
## The session response
|
|
117
160
|
|
|
118
161
|
The exchange returns the versioned Embedded Assistant v1 contract. `token`, `expiresAt`, and `endpoints.turns` / `endpoints.toolConfirmations` (absolute URLs) are always present; `configuration` is optional theming data. Forward the body unchanged; the widget posts turns to `endpoints.turns` itself. Do not rebuild, filter, or rewrite the response.
|
|
@@ -142,7 +185,7 @@ The component renders a custom element and must mount client-side. In a Next.js
|
|
|
142
185
|
- Signed-out session exchange returns `401`.
|
|
143
186
|
- The browser network/DOM/storage contains no client secret or model key.
|
|
144
187
|
- The local and production origins match `allowedOrigins` character-for-character.
|
|
145
|
-
-
|
|
188
|
+
- Auto-run requires the full safe-read annotation (`annotations.readOnly()`: read-only, non-destructive, closed-world); unannotated or partially annotated tools always confirm. Writes require confirmation by design.
|
|
146
189
|
- An expired turn re-exchanges once; confirmations never replay.
|
|
147
190
|
- Wrong-origin and malformed-origin requests fail closed.
|
|
148
191
|
|
|
@@ -157,4 +200,9 @@ The component renders a custom element and must mount client-side. In a Next.js
|
|
|
157
200
|
| Validate rejects an origin | Non-loopback HTTP origin in `allowedOrigins` | Use the exact HTTPS production origin; HTTP is only for `localhost`/`127.0.0.1` |
|
|
158
201
|
| Session exchange returns 404 | `serviceUrl` points at the deployment MCP endpoint | Use the control-plane service URL printed by `noodle assistant clients create` |
|
|
159
202
|
| Session exchange returns 403 `origin is not allowed` | Request origin differs from `allowedOrigins` character-for-character | Align the exact scheme/host/port on both sides and redeploy |
|
|
160
|
-
| Hydration or `HTMLElement is not defined` errors | The component mounted during server rendering | Mount client-only (`"use client"` or `next/dynamic` with `ssr: false`) |
|
|
203
|
+
| Hydration or `HTMLElement is not defined` errors | The component mounted during server rendering | Mount client-only (`"use client"` or `next/dynamic` with `ssr: false`) |
|
|
204
|
+
| A read-only tool still asks for confirmation | Its annotations fail the safe-read rule: auto-run requires `readOnlyHint: true`, `destructiveHint: false`, AND `openWorldHint: false` (use `annotations.readOnly()`; `readOnly({ openWorld: true })` confirm-gates) | Fix the annotations; `noodle check --target embedded-assistant` lists every confirm-gated tool |
|
|
205
|
+
| `${user.claims.<key>}` is empty | Claim not declared in `sessionClaims` (or key typo) — undeclared claims are dropped at exchange | Declare the key in `embeddedAssistant({ sessionClaims })` and redeploy |
|
|
206
|
+
| `${user.name}` is empty | Backend did not pass `user.name` to `createAssistantSession` | Pass the verified name from the authenticated backend session |
|
|
207
|
+
| The model does not know a claim you passed | Claim is tools-only | Mark it `exposeToModel: true` in `sessionClaims` |
|
|
208
|
+
| Behavior does not change after `noodle deploy` | Outdated platform: before the 2026-07 fix, clients were pinned to their creation-time deployment | Update the platform; sessions now follow the tenant's active deployment |
|