@seed-app-studio/cli 0.1.1-canary.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/dist/cli.d.mts +1 -0
- package/dist/cli.mjs +10 -0
- package/dist/commands-TM-KX_MV.mjs +972 -0
- package/dist/index.d.mts +139 -0
- package/dist/index.mjs +2 -0
- package/examples/react-spa-stories/README.md +44 -0
- package/examples/react-spa-stories/index.html +12 -0
- package/examples/react-spa-stories/package.json +29 -0
- package/examples/react-spa-stories/seed-app.json +74 -0
- package/examples/react-spa-stories/src/App.tsx +440 -0
- package/examples/react-spa-stories/src/main.tsx +10 -0
- package/examples/react-spa-stories/src/replayFixture.ts +60 -0
- package/examples/react-spa-stories/src/storyData.ts +661 -0
- package/examples/react-spa-stories/src/styles.css +342 -0
- package/examples/react-spa-stories/tsconfig.json +22 -0
- package/examples/react-spa-stories/vite.config.ts +24 -0
- package/package.json +49 -0
|
@@ -0,0 +1,661 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createSeedAppAgentStreamEvent,
|
|
3
|
+
type SeedAppAgentRunResult,
|
|
4
|
+
type SeedAppAgentStreamEvent,
|
|
5
|
+
type SeedAppBridgeDiagnostics,
|
|
6
|
+
type SeedAppClient,
|
|
7
|
+
type SeedAppError,
|
|
8
|
+
type SeedAppGrantResolution,
|
|
9
|
+
} from "@seed-app-studio/sdk";
|
|
10
|
+
|
|
11
|
+
export type StoryState = "idle" | "running" | "success" | "blocked" | "failed";
|
|
12
|
+
export type StoryRuntimeKind = "pending" | "live" | "mock" | "policy-block" | "runtime-error";
|
|
13
|
+
|
|
14
|
+
export type StoryResult = {
|
|
15
|
+
state: StoryState;
|
|
16
|
+
runtimeKind?: StoryRuntimeKind;
|
|
17
|
+
payload?: unknown;
|
|
18
|
+
error?: string;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type CapabilityStory = {
|
|
22
|
+
id: string;
|
|
23
|
+
title: string;
|
|
24
|
+
capability: string;
|
|
25
|
+
intent: string;
|
|
26
|
+
intentZh: string;
|
|
27
|
+
codeExample: string;
|
|
28
|
+
run(client: SeedAppClient): Promise<unknown>;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export type AgentRunAndWatchStoryPayload = {
|
|
32
|
+
runtimeKind: "live" | "mock";
|
|
33
|
+
run: SeedAppAgentRunResult;
|
|
34
|
+
events: SeedAppAgentStreamEvent[];
|
|
35
|
+
fallbackReason?: string;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type ConsoleBridgeScenarioMessage = {
|
|
39
|
+
level: "log" | "info" | "warn" | "error" | "debug";
|
|
40
|
+
marker: string;
|
|
41
|
+
payload: {
|
|
42
|
+
sequence: number;
|
|
43
|
+
area: string;
|
|
44
|
+
retryable?: boolean;
|
|
45
|
+
traceId?: string;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type ConsoleBridgeScenarioPayload = {
|
|
50
|
+
runtimeKind: "live";
|
|
51
|
+
expectedOrder: string[];
|
|
52
|
+
emitted: readonly ConsoleBridgeScenarioMessage[];
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export type UnsupportedCapabilityProbe =
|
|
56
|
+
| {
|
|
57
|
+
method: "seed.calendar.read";
|
|
58
|
+
ok: true;
|
|
59
|
+
result: unknown;
|
|
60
|
+
}
|
|
61
|
+
| {
|
|
62
|
+
method: "seed.calendar.read";
|
|
63
|
+
ok: false;
|
|
64
|
+
error: {
|
|
65
|
+
code: string;
|
|
66
|
+
message: string;
|
|
67
|
+
requestId?: string;
|
|
68
|
+
retryable?: boolean;
|
|
69
|
+
};
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
export type BridgeDiagnosticsStoryPayload = {
|
|
73
|
+
runtimeKind: "live" | "mock";
|
|
74
|
+
diagnostics: SeedAppBridgeDiagnostics;
|
|
75
|
+
unsupportedProbe: UnsupportedCapabilityProbe;
|
|
76
|
+
fallbackReason?: string;
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export type BrainBundlePreviewStoryPayload = {
|
|
80
|
+
runtimeKind: "live" | "mock";
|
|
81
|
+
response: unknown;
|
|
82
|
+
fallbackReason?: string;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const APP_ID = "seed.react-spa-stories";
|
|
86
|
+
|
|
87
|
+
export const GRANT_PRECEDENCE_ORDER = ["host", "tenant", "user", "manifest", "default"] as const;
|
|
88
|
+
|
|
89
|
+
export const CAPABILITY_GRANT_PRECEDENCE_FIXTURE: SeedAppGrantResolution[] = [
|
|
90
|
+
{ capability: "workspace.write", policy: "disabled", source: "host" },
|
|
91
|
+
{ capability: "mcp.callTool", policy: "disabled", source: "tenant" },
|
|
92
|
+
{ capability: "agent.run", policy: "enabled", source: "user" },
|
|
93
|
+
{ capability: "memory.search", policy: "enabled", source: "manifest" },
|
|
94
|
+
{ capability: "agent.stream", policy: "ask", source: "default" },
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
export const CONSOLE_BRIDGE_SCENARIO_MESSAGES: readonly ConsoleBridgeScenarioMessage[] = [
|
|
98
|
+
{ level: "log", marker: "console-order-1", payload: { sequence: 1, area: "story-start" } },
|
|
99
|
+
{ level: "info", marker: "console-order-2", payload: { sequence: 2, area: "host-event" } },
|
|
100
|
+
{ level: "warn", marker: "console-order-3", payload: { sequence: 3, area: "approval-required" } },
|
|
101
|
+
{
|
|
102
|
+
level: "error",
|
|
103
|
+
marker: "console-order-4",
|
|
104
|
+
payload: { sequence: 4, area: "runtime-error", retryable: true },
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
level: "debug",
|
|
108
|
+
marker: "console-order-5",
|
|
109
|
+
payload: { sequence: 5, area: "diagnostics", traceId: "console-story" },
|
|
110
|
+
},
|
|
111
|
+
];
|
|
112
|
+
|
|
113
|
+
export const AGENT_STREAM_REPLAY_EVENTS: SeedAppAgentStreamEvent[] = [
|
|
114
|
+
createSeedAppAgentStreamEvent({
|
|
115
|
+
type: "agent.run.started",
|
|
116
|
+
payload: {
|
|
117
|
+
runId: "replay-run",
|
|
118
|
+
sessionId: "replay-session",
|
|
119
|
+
inputSummary: "Review renewal risk",
|
|
120
|
+
},
|
|
121
|
+
}),
|
|
122
|
+
createSeedAppAgentStreamEvent({
|
|
123
|
+
type: "agent.message.delta",
|
|
124
|
+
payload: {
|
|
125
|
+
runId: "replay-run",
|
|
126
|
+
sessionId: "replay-session",
|
|
127
|
+
messageId: "msg-1",
|
|
128
|
+
text: "I will inspect CRM context.",
|
|
129
|
+
},
|
|
130
|
+
}),
|
|
131
|
+
createSeedAppAgentStreamEvent({
|
|
132
|
+
type: "agent.thought.delta",
|
|
133
|
+
payload: {
|
|
134
|
+
runId: "replay-run",
|
|
135
|
+
sessionId: "replay-session",
|
|
136
|
+
messageId: "thought-1",
|
|
137
|
+
text: "Need account status and next action.",
|
|
138
|
+
},
|
|
139
|
+
}),
|
|
140
|
+
createSeedAppAgentStreamEvent({
|
|
141
|
+
type: "agent.tool.started",
|
|
142
|
+
payload: {
|
|
143
|
+
runId: "replay-run",
|
|
144
|
+
sessionId: "replay-session",
|
|
145
|
+
toolCallId: "tool-1",
|
|
146
|
+
title: "Search account memory",
|
|
147
|
+
kind: "read",
|
|
148
|
+
status: "pending",
|
|
149
|
+
},
|
|
150
|
+
}),
|
|
151
|
+
createSeedAppAgentStreamEvent({
|
|
152
|
+
type: "agent.tool.updated",
|
|
153
|
+
payload: {
|
|
154
|
+
runId: "replay-run",
|
|
155
|
+
sessionId: "replay-session",
|
|
156
|
+
toolCallId: "tool-1",
|
|
157
|
+
status: "completed",
|
|
158
|
+
redactedOutput: { count: 3 },
|
|
159
|
+
},
|
|
160
|
+
}),
|
|
161
|
+
createSeedAppAgentStreamEvent({
|
|
162
|
+
type: "agent.permission.required",
|
|
163
|
+
payload: {
|
|
164
|
+
runId: "replay-run",
|
|
165
|
+
sessionId: "replay-session",
|
|
166
|
+
requestId: "approval-1",
|
|
167
|
+
toolCallId: "tool-2",
|
|
168
|
+
description: "Write a follow-up note to workspace.",
|
|
169
|
+
options: [{ id: "allow" }, { id: "deny" }],
|
|
170
|
+
},
|
|
171
|
+
}),
|
|
172
|
+
createSeedAppAgentStreamEvent({
|
|
173
|
+
type: "agent.elicitation.required",
|
|
174
|
+
payload: {
|
|
175
|
+
runId: "replay-run",
|
|
176
|
+
sessionId: "replay-session",
|
|
177
|
+
requestId: "elicitation-1",
|
|
178
|
+
message: "Which renewal segment should the assistant prioritize?",
|
|
179
|
+
choices: ["enterprise", "mid-market"],
|
|
180
|
+
},
|
|
181
|
+
}),
|
|
182
|
+
createSeedAppAgentStreamEvent({
|
|
183
|
+
type: "agent.subagent.anchor",
|
|
184
|
+
payload: {
|
|
185
|
+
runId: "replay-run",
|
|
186
|
+
sessionId: "replay-session",
|
|
187
|
+
parentToolCallId: "tool-3",
|
|
188
|
+
childSessionId: "child-session-1",
|
|
189
|
+
title: "Pricing analyst",
|
|
190
|
+
},
|
|
191
|
+
}),
|
|
192
|
+
createSeedAppAgentStreamEvent({
|
|
193
|
+
type: "agent.subagent.message.delta",
|
|
194
|
+
payload: {
|
|
195
|
+
runId: "replay-run",
|
|
196
|
+
sessionId: "replay-session",
|
|
197
|
+
childSessionId: "child-session-1",
|
|
198
|
+
childEntryIndex: 1,
|
|
199
|
+
text: "Discount guardrail is 8%.",
|
|
200
|
+
},
|
|
201
|
+
}),
|
|
202
|
+
createSeedAppAgentStreamEvent({
|
|
203
|
+
type: "agent.config.updated",
|
|
204
|
+
payload: {
|
|
205
|
+
runId: "replay-run",
|
|
206
|
+
sessionId: "replay-session",
|
|
207
|
+
options: [{ id: "provider_custom_signal", value: "redacted" }],
|
|
208
|
+
},
|
|
209
|
+
}),
|
|
210
|
+
createSeedAppAgentStreamEvent({
|
|
211
|
+
type: "agent.turn.completed",
|
|
212
|
+
payload: { runId: "replay-run", sessionId: "replay-session", stopReason: "end_turn" },
|
|
213
|
+
}),
|
|
214
|
+
];
|
|
215
|
+
|
|
216
|
+
export const AGENT_RUN_AND_WATCH_MOCK_EVENTS: SeedAppAgentStreamEvent[] = [
|
|
217
|
+
createSeedAppAgentStreamEvent({
|
|
218
|
+
type: "agent.run.started",
|
|
219
|
+
payload: {
|
|
220
|
+
runId: "mock-watch-run",
|
|
221
|
+
sessionId: "mock-watch-session",
|
|
222
|
+
inputSummary: "Draft renewal plan",
|
|
223
|
+
},
|
|
224
|
+
}),
|
|
225
|
+
createSeedAppAgentStreamEvent({
|
|
226
|
+
type: "agent.message.delta",
|
|
227
|
+
payload: {
|
|
228
|
+
runId: "mock-watch-run",
|
|
229
|
+
sessionId: "mock-watch-session",
|
|
230
|
+
messageId: "mock-msg-1",
|
|
231
|
+
text: "I found two renewal risks and one expansion signal.",
|
|
232
|
+
},
|
|
233
|
+
}),
|
|
234
|
+
createSeedAppAgentStreamEvent({
|
|
235
|
+
type: "agent.tool.started",
|
|
236
|
+
payload: {
|
|
237
|
+
runId: "mock-watch-run",
|
|
238
|
+
sessionId: "mock-watch-session",
|
|
239
|
+
toolCallId: "mock-tool-1",
|
|
240
|
+
title: "Read account memory",
|
|
241
|
+
kind: "read",
|
|
242
|
+
status: "pending",
|
|
243
|
+
},
|
|
244
|
+
}),
|
|
245
|
+
createSeedAppAgentStreamEvent({
|
|
246
|
+
type: "agent.tool.updated",
|
|
247
|
+
payload: {
|
|
248
|
+
runId: "mock-watch-run",
|
|
249
|
+
sessionId: "mock-watch-session",
|
|
250
|
+
toolCallId: "mock-tool-1",
|
|
251
|
+
status: "completed",
|
|
252
|
+
redactedOutput: { memories: 2 },
|
|
253
|
+
},
|
|
254
|
+
}),
|
|
255
|
+
createSeedAppAgentStreamEvent({
|
|
256
|
+
type: "agent.run.completed",
|
|
257
|
+
payload: {
|
|
258
|
+
runId: "mock-watch-run",
|
|
259
|
+
sessionId: "mock-watch-session",
|
|
260
|
+
outputSummary: "Prepared a renewal plan with risk, next action, and owner.",
|
|
261
|
+
},
|
|
262
|
+
}),
|
|
263
|
+
];
|
|
264
|
+
|
|
265
|
+
async function runAgentRunAndWatchStory(
|
|
266
|
+
client: SeedAppClient,
|
|
267
|
+
): Promise<AgentRunAndWatchStoryPayload> {
|
|
268
|
+
const events: SeedAppAgentStreamEvent[] = [];
|
|
269
|
+
try {
|
|
270
|
+
const run = await client.agent.runAndWatch(
|
|
271
|
+
{
|
|
272
|
+
assistantId: "sales-copilot",
|
|
273
|
+
input: "Watch a renewal-risk assistant run until the terminal stream event.",
|
|
274
|
+
metadata: { story: "agent-run-watch" },
|
|
275
|
+
},
|
|
276
|
+
{ onEvent: (event) => events.push(event) },
|
|
277
|
+
{ requestTimeoutMs: 8000, streamTimeoutMs: 8000 },
|
|
278
|
+
);
|
|
279
|
+
return { runtimeKind: "live", run, events };
|
|
280
|
+
} catch (error) {
|
|
281
|
+
if (!isSeedAppError(error) || error.code !== "handshake_timeout") throw error;
|
|
282
|
+
return {
|
|
283
|
+
runtimeKind: "mock",
|
|
284
|
+
run: { runId: "mock-watch-run", status: "completed", output: { previewOnly: true } },
|
|
285
|
+
events: AGENT_RUN_AND_WATCH_MOCK_EVENTS,
|
|
286
|
+
fallbackReason: error.message,
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
async function runConsoleBridgeScenario(): Promise<ConsoleBridgeScenarioPayload> {
|
|
292
|
+
CONSOLE_BRIDGE_SCENARIO_MESSAGES.forEach((entry) => {
|
|
293
|
+
console[entry.level](`[seed-app-console-scenario] ${entry.marker}`, entry.payload);
|
|
294
|
+
});
|
|
295
|
+
return {
|
|
296
|
+
runtimeKind: "live",
|
|
297
|
+
expectedOrder: CONSOLE_BRIDGE_SCENARIO_MESSAGES.map((entry) => entry.marker),
|
|
298
|
+
emitted: CONSOLE_BRIDGE_SCENARIO_MESSAGES,
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async function runBridgeDiagnosticsStory(
|
|
303
|
+
client: SeedAppClient,
|
|
304
|
+
): Promise<BridgeDiagnosticsStoryPayload> {
|
|
305
|
+
try {
|
|
306
|
+
const diagnostics = await client.diagnostics.snapshot(
|
|
307
|
+
{ includeMethods: true, includeTransports: true },
|
|
308
|
+
{ timeoutMs: 2500 },
|
|
309
|
+
);
|
|
310
|
+
return {
|
|
311
|
+
runtimeKind: "live",
|
|
312
|
+
diagnostics,
|
|
313
|
+
unsupportedProbe: await probeUnsupportedCapability(client),
|
|
314
|
+
};
|
|
315
|
+
} catch (error) {
|
|
316
|
+
if (!isSeedAppError(error)) throw error;
|
|
317
|
+
return {
|
|
318
|
+
runtimeKind: "mock",
|
|
319
|
+
diagnostics: createFallbackBridgeDiagnostics(error.message),
|
|
320
|
+
unsupportedProbe: createUnsupportedCapabilityError(
|
|
321
|
+
"seed.calendar.read",
|
|
322
|
+
"capability_denied",
|
|
323
|
+
error.requestId,
|
|
324
|
+
),
|
|
325
|
+
fallbackReason: error.message,
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function runBrainBundlePreviewStory(
|
|
331
|
+
client: SeedAppClient,
|
|
332
|
+
): Promise<BrainBundlePreviewStoryPayload> {
|
|
333
|
+
try {
|
|
334
|
+
return {
|
|
335
|
+
runtimeKind: "live",
|
|
336
|
+
response: await client.brainBundle.previewSummaries(
|
|
337
|
+
{
|
|
338
|
+
conversationId: `appstudio:${APP_ID}`,
|
|
339
|
+
format: "rollup",
|
|
340
|
+
sort: "updatedAt_desc",
|
|
341
|
+
},
|
|
342
|
+
{ timeoutMs: 2500 },
|
|
343
|
+
),
|
|
344
|
+
};
|
|
345
|
+
} catch (error) {
|
|
346
|
+
if (!isSeedAppError(error)) throw error;
|
|
347
|
+
return {
|
|
348
|
+
runtimeKind: "mock",
|
|
349
|
+
response: {
|
|
350
|
+
schemaVersion: "brain-bundle-preview-summary-rollup.v0",
|
|
351
|
+
conversationId: `appstudio:${APP_ID}`,
|
|
352
|
+
total: 0,
|
|
353
|
+
byStatus: {},
|
|
354
|
+
byState: {},
|
|
355
|
+
blockedReasons: {},
|
|
356
|
+
rawBlobIncluded: false,
|
|
357
|
+
},
|
|
358
|
+
fallbackReason: error.message,
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
async function probeUnsupportedCapability(
|
|
364
|
+
client: SeedAppClient,
|
|
365
|
+
): Promise<UnsupportedCapabilityProbe> {
|
|
366
|
+
try {
|
|
367
|
+
const result = await client.request(
|
|
368
|
+
"seed.calendar.read",
|
|
369
|
+
{ range: "today" },
|
|
370
|
+
{ timeoutMs: 2500 },
|
|
371
|
+
);
|
|
372
|
+
return { method: "seed.calendar.read", ok: true, result };
|
|
373
|
+
} catch (error) {
|
|
374
|
+
if (!isSeedAppError(error)) {
|
|
375
|
+
return createUnsupportedCapabilityError("seed.calendar.read", "host_unavailable");
|
|
376
|
+
}
|
|
377
|
+
return createUnsupportedCapabilityError(
|
|
378
|
+
"seed.calendar.read",
|
|
379
|
+
error.code,
|
|
380
|
+
error.requestId,
|
|
381
|
+
error.retryable,
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
function createFallbackBridgeDiagnostics(reason: string): SeedAppBridgeDiagnostics {
|
|
387
|
+
return {
|
|
388
|
+
appId: APP_ID,
|
|
389
|
+
hostVersion: "fallback-demo",
|
|
390
|
+
runtime: "mock",
|
|
391
|
+
transport: "mock",
|
|
392
|
+
grants: { total: 0, enabled: 0, ask: 0, disabled: 0 },
|
|
393
|
+
methods: [
|
|
394
|
+
{ method: "seed.handshake", support: "mock" },
|
|
395
|
+
{ method: "seed.capabilities.query", support: "mock" },
|
|
396
|
+
{ method: "seed.bridge.diagnostics", capability: "bridge.diagnostics", support: "mock" },
|
|
397
|
+
],
|
|
398
|
+
transports: [{ id: "mock", supportsStreaming: true, supportsBroadcast: true }],
|
|
399
|
+
unsupportedMethods: ["seed.calendar.read"],
|
|
400
|
+
checks: [
|
|
401
|
+
{
|
|
402
|
+
id: "diagnostics-fallback",
|
|
403
|
+
status: "warning",
|
|
404
|
+
message: reason,
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
id: "unsupported-method",
|
|
408
|
+
status: "blocked",
|
|
409
|
+
message: "seed.calendar.read is intentionally outside this app manifest.",
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
function createUnsupportedCapabilityError(
|
|
416
|
+
method: "seed.calendar.read",
|
|
417
|
+
code: string,
|
|
418
|
+
requestId: string = method,
|
|
419
|
+
retryable = false,
|
|
420
|
+
): UnsupportedCapabilityProbe {
|
|
421
|
+
return {
|
|
422
|
+
method,
|
|
423
|
+
ok: false,
|
|
424
|
+
error: {
|
|
425
|
+
code,
|
|
426
|
+
message: `${method} is not declared by this playground manifest.`,
|
|
427
|
+
requestId,
|
|
428
|
+
retryable,
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
export const STORIES: CapabilityStory[] = [
|
|
434
|
+
{
|
|
435
|
+
id: "handshake",
|
|
436
|
+
title: "Host handshake",
|
|
437
|
+
capability: "seed.handshake",
|
|
438
|
+
intent: "Confirms that the sandbox can talk to the SEED host.",
|
|
439
|
+
intentZh: "确认沙箱 iframe 能够与 SEED 宿主建立握手,并拿到基础授权信息。",
|
|
440
|
+
codeExample: `const handshake = await client.handshake({
|
|
441
|
+
appId: APP_ID,
|
|
442
|
+
sdkVersion: '0.1.0',
|
|
443
|
+
});`,
|
|
444
|
+
run: (client) => client.handshake({ appId: APP_ID, sdkVersion: "0.1.0" }),
|
|
445
|
+
},
|
|
446
|
+
{
|
|
447
|
+
id: "capabilities",
|
|
448
|
+
title: "Capability snapshot",
|
|
449
|
+
capability: "seed.capabilities.query",
|
|
450
|
+
intent: "Shows enabled, approval-required, and disabled grants declared by the manifest.",
|
|
451
|
+
intentZh: "展示 manifest 中声明的已启用、需要审批和已禁用能力授权快照。",
|
|
452
|
+
codeExample: `const grants = await client.capabilities.query();`,
|
|
453
|
+
run: (client) => client.capabilities.query(),
|
|
454
|
+
},
|
|
455
|
+
{
|
|
456
|
+
id: "grant-precedence",
|
|
457
|
+
title: "Grant precedence fixture",
|
|
458
|
+
capability: "seed.capabilities.query",
|
|
459
|
+
intent:
|
|
460
|
+
"Shows the host > tenant > user > manifest > default policy order with deterministic sample grants.",
|
|
461
|
+
intentZh: "用固定样例展示宿主、租户、用户、manifest、默认策略之间的授权优先级。",
|
|
462
|
+
codeExample: `const liveGrants = await client.capabilities.query();
|
|
463
|
+
|
|
464
|
+
return {
|
|
465
|
+
liveGrants,
|
|
466
|
+
precedence: ['host', 'tenant', 'user', 'manifest', 'default'],
|
|
467
|
+
fixture: CAPABILITY_GRANT_PRECEDENCE_FIXTURE,
|
|
468
|
+
};`,
|
|
469
|
+
run: async (client) => ({
|
|
470
|
+
liveGrants: await client.capabilities.query(),
|
|
471
|
+
precedence: GRANT_PRECEDENCE_ORDER,
|
|
472
|
+
fixture: CAPABILITY_GRANT_PRECEDENCE_FIXTURE,
|
|
473
|
+
}),
|
|
474
|
+
},
|
|
475
|
+
{
|
|
476
|
+
id: "console-bridge",
|
|
477
|
+
title: "Console bridge scenario",
|
|
478
|
+
capability: "host.console",
|
|
479
|
+
intent:
|
|
480
|
+
"Emits ordered console levels so App Studio can verify forwarding, serialization, and diagnostics.",
|
|
481
|
+
intentZh: "按顺序触发 log、info、warn、error、debug,验证 App Studio 的控制台转发和序列化。",
|
|
482
|
+
codeExample: `CONSOLE_BRIDGE_SCENARIO_MESSAGES.forEach((entry) => {
|
|
483
|
+
console[entry.level](
|
|
484
|
+
\`[seed-app-console-scenario] \${entry.marker}\`,
|
|
485
|
+
entry.payload
|
|
486
|
+
);
|
|
487
|
+
});`,
|
|
488
|
+
run: runConsoleBridgeScenario,
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
id: "bridge-diagnostics",
|
|
492
|
+
title: "Bridge diagnostics",
|
|
493
|
+
capability: "bridge.diagnostics",
|
|
494
|
+
intent:
|
|
495
|
+
"Reports runtime transport health and probes an unsupported capability through the same SDK path.",
|
|
496
|
+
intentZh: "报告运行时传输状态,并通过同一条 SDK 路径探测一个未声明能力。",
|
|
497
|
+
codeExample: `const diagnostics = await client.diagnostics.snapshot(
|
|
498
|
+
{ includeMethods: true, includeTransports: true },
|
|
499
|
+
{ timeoutMs: 2500 }
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
const unsupportedProbe = await client.request(
|
|
503
|
+
'seed.calendar.read',
|
|
504
|
+
{ range: 'today' },
|
|
505
|
+
{ timeoutMs: 2500 }
|
|
506
|
+
);`,
|
|
507
|
+
run: runBridgeDiagnosticsStory,
|
|
508
|
+
},
|
|
509
|
+
{
|
|
510
|
+
id: "agent-run",
|
|
511
|
+
title: "Agent run",
|
|
512
|
+
capability: "agent.run",
|
|
513
|
+
intent: "Starts a vertical assistant task through the SDK.",
|
|
514
|
+
intentZh: "通过 SDK 启动一个垂直场景助手任务,用来验证 agent.run 能力。",
|
|
515
|
+
codeExample: `const result = await client.agent.run({
|
|
516
|
+
assistantId: 'sales-copilot',
|
|
517
|
+
input: 'Draft a three-bullet account plan for a renewal risk.',
|
|
518
|
+
metadata: { story: 'agent-run' },
|
|
519
|
+
});`,
|
|
520
|
+
run: (client) =>
|
|
521
|
+
client.agent.run({
|
|
522
|
+
assistantId: "sales-copilot",
|
|
523
|
+
input: "Draft a three-bullet account plan for a renewal risk.",
|
|
524
|
+
metadata: { story: "agent-run" },
|
|
525
|
+
}),
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
id: "agent-run-watch",
|
|
529
|
+
title: "Agent run and watch",
|
|
530
|
+
capability: "agent.run",
|
|
531
|
+
intent:
|
|
532
|
+
"Starts a watched agent run and falls back to a deterministic mock stream when no terminal stream arrives.",
|
|
533
|
+
intentZh: "启动可监听的 Agent 运行;如果没有收到终态流事件,则回退到确定性的模拟流。",
|
|
534
|
+
codeExample: `const events: SeedAppAgentStreamEvent[] = [];
|
|
535
|
+
|
|
536
|
+
const run = await client.agent.runAndWatch(
|
|
537
|
+
{
|
|
538
|
+
assistantId: 'sales-copilot',
|
|
539
|
+
input: 'Watch a renewal-risk assistant run until the terminal stream event.',
|
|
540
|
+
metadata: { story: 'agent-run-watch' },
|
|
541
|
+
},
|
|
542
|
+
{ onEvent: (event) => events.push(event) },
|
|
543
|
+
{ requestTimeoutMs: 8000, streamTimeoutMs: 8000 }
|
|
544
|
+
);`,
|
|
545
|
+
run: runAgentRunAndWatchStory,
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
id: "agent-stream-replay",
|
|
549
|
+
title: "Agent stream replay",
|
|
550
|
+
capability: "agent.stream",
|
|
551
|
+
intent:
|
|
552
|
+
"Replays the Bridge-projected lifecycle: message, thought, tool, permission, elicitation, subagent, backup, and turn barrier.",
|
|
553
|
+
intentZh:
|
|
554
|
+
"回放由 Bridge 投影的生命周期事件,包括消息、思考、工具、授权、追问、子 Agent、备份和回合结束。",
|
|
555
|
+
codeExample: `return {
|
|
556
|
+
runId: 'replay-run',
|
|
557
|
+
source: 'local-fixture',
|
|
558
|
+
events: AGENT_STREAM_REPLAY_EVENTS,
|
|
559
|
+
};`,
|
|
560
|
+
run: async () => ({
|
|
561
|
+
runId: "replay-run",
|
|
562
|
+
source: "local-fixture",
|
|
563
|
+
events: AGENT_STREAM_REPLAY_EVENTS,
|
|
564
|
+
}),
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: "memory-search",
|
|
568
|
+
title: "Memory search",
|
|
569
|
+
capability: "memory.search",
|
|
570
|
+
intent: "Queries host memory without directly reading local files.",
|
|
571
|
+
intentZh: "通过宿主记忆接口查询上下文,不直接读取本地文件。",
|
|
572
|
+
codeExample: `const memories = await client.memory.search({
|
|
573
|
+
namespace: 'demo.customer',
|
|
574
|
+
query: 'renewal risk and last contact',
|
|
575
|
+
limit: 3,
|
|
576
|
+
});`,
|
|
577
|
+
run: (client) =>
|
|
578
|
+
client.memory.search({
|
|
579
|
+
namespace: "demo.customer",
|
|
580
|
+
query: "renewal risk and last contact",
|
|
581
|
+
limit: 3,
|
|
582
|
+
}),
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
id: "brain-bundle-preview",
|
|
586
|
+
title: "Brain bundle preview",
|
|
587
|
+
capability: "brain-bundle.preview-summaries",
|
|
588
|
+
intent:
|
|
589
|
+
"Reads metadata-only business brain bundle summaries through the host without exposing raw bundle blobs.",
|
|
590
|
+
intentZh: "通过宿主读取 metadata-only 的企业大脑 bundle 摘要,不暴露原始 bundle blob。",
|
|
591
|
+
codeExample: `const preview = await client.brainBundle.previewSummaries({
|
|
592
|
+
conversationId: \`appstudio:\${APP_ID}\`,
|
|
593
|
+
format: 'rollup',
|
|
594
|
+
sort: 'updatedAt_desc',
|
|
595
|
+
});`,
|
|
596
|
+
run: runBrainBundlePreviewStory,
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
id: "mcp-list-tools",
|
|
600
|
+
title: "MCP list tools",
|
|
601
|
+
capability: "mcp.listTools",
|
|
602
|
+
intent: "Lists brokered host tools without exposing server secrets.",
|
|
603
|
+
intentZh: "列出由宿主代理的 MCP 工具,同时避免暴露服务端密钥和内部配置。",
|
|
604
|
+
codeExample: `const tools = await client.mcp.listTools({
|
|
605
|
+
server: 'seed.knowledgebase',
|
|
606
|
+
});`,
|
|
607
|
+
run: (client) => client.mcp.listTools({ server: "seed.knowledgebase" }),
|
|
608
|
+
},
|
|
609
|
+
{
|
|
610
|
+
id: "mcp-call-tool",
|
|
611
|
+
title: "MCP call tool",
|
|
612
|
+
capability: "mcp.callTool",
|
|
613
|
+
intent: "Calls a brokered read-only MCP tool and exercises the approval path.",
|
|
614
|
+
intentZh: "调用一个只读 MCP 工具,并验证需要用户授权的 ask 流程。",
|
|
615
|
+
codeExample: `const result = await client.mcp.callTool({
|
|
616
|
+
server: 'seed.knowledgebase',
|
|
617
|
+
toolName: 'kb_search',
|
|
618
|
+
input: {
|
|
619
|
+
query: 'renewal risk and last contact',
|
|
620
|
+
limit: 3,
|
|
621
|
+
},
|
|
622
|
+
});`,
|
|
623
|
+
run: (client) =>
|
|
624
|
+
client.mcp.callTool({
|
|
625
|
+
server: "seed.knowledgebase",
|
|
626
|
+
toolName: "kb_search",
|
|
627
|
+
input: { query: "renewal risk and last contact", limit: 3 },
|
|
628
|
+
}),
|
|
629
|
+
},
|
|
630
|
+
{
|
|
631
|
+
id: "workspace-denied",
|
|
632
|
+
title: "Denied workspace write",
|
|
633
|
+
capability: "workspace.write",
|
|
634
|
+
intent: "Demonstrates a blocked capability that must not crash the SPA.",
|
|
635
|
+
intentZh: "演示被策略拒绝的 workspace.write 能力,确认 SPA 不会因此崩溃。",
|
|
636
|
+
codeExample: `await client.request('seed.workspace.write', {
|
|
637
|
+
path: 'notes/customer-plan.md',
|
|
638
|
+
content: 'This should be denied by default.',
|
|
639
|
+
});`,
|
|
640
|
+
run: (client) =>
|
|
641
|
+
client.request("seed.workspace.write", {
|
|
642
|
+
path: "notes/customer-plan.md",
|
|
643
|
+
content: "This should be denied by default.",
|
|
644
|
+
}),
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
id: "unknown-capability",
|
|
648
|
+
title: "Undeclared capability",
|
|
649
|
+
capability: "calendar.read",
|
|
650
|
+
intent: "Shows how the host rejects a capability missing from manifest.",
|
|
651
|
+
intentZh: "展示宿主如何拒绝 manifest 中未声明的能力调用。",
|
|
652
|
+
codeExample: `await client.request('seed.calendar.read', {
|
|
653
|
+
range: 'today',
|
|
654
|
+
});`,
|
|
655
|
+
run: (client) => client.request("seed.calendar.read", { range: "today" }),
|
|
656
|
+
},
|
|
657
|
+
];
|
|
658
|
+
|
|
659
|
+
function isSeedAppError(value: unknown): value is SeedAppError {
|
|
660
|
+
return typeof value === "object" && value !== null && "code" in value && "message" in value;
|
|
661
|
+
}
|