@stigmer/react 0.0.67 → 0.0.69

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 (108) hide show
  1. package/README.md +1 -1
  2. package/composer/SessionComposer.d.ts.map +1 -1
  3. package/composer/SessionComposer.js +12 -3
  4. package/composer/SessionComposer.js.map +1 -1
  5. package/demo/__tests__/demo-client.test.d.ts +2 -0
  6. package/demo/__tests__/demo-client.test.d.ts.map +1 -0
  7. package/demo/__tests__/demo-client.test.js +133 -0
  8. package/demo/__tests__/demo-client.test.js.map +1 -0
  9. package/demo/__tests__/fixtures.test.d.ts +2 -0
  10. package/demo/__tests__/fixtures.test.d.ts.map +1 -0
  11. package/demo/__tests__/fixtures.test.js +135 -0
  12. package/demo/__tests__/fixtures.test.js.map +1 -0
  13. package/demo/__tests__/samples.test.d.ts +2 -0
  14. package/demo/__tests__/samples.test.d.ts.map +1 -0
  15. package/demo/__tests__/samples.test.js +152 -0
  16. package/demo/__tests__/samples.test.js.map +1 -0
  17. package/demo/client.d.ts +29 -0
  18. package/demo/client.d.ts.map +1 -0
  19. package/demo/client.js +52 -0
  20. package/demo/client.js.map +1 -0
  21. package/demo/fixtures.d.ts +190 -0
  22. package/demo/fixtures.d.ts.map +1 -0
  23. package/demo/fixtures.js +263 -0
  24. package/demo/fixtures.js.map +1 -0
  25. package/demo/index.d.ts +6 -0
  26. package/demo/index.d.ts.map +1 -0
  27. package/demo/index.js +6 -0
  28. package/demo/index.js.map +1 -0
  29. package/demo/samples.d.ts +166 -0
  30. package/demo/samples.d.ts.map +1 -0
  31. package/demo/samples.js +308 -0
  32. package/demo/samples.js.map +1 -0
  33. package/demo/transport.d.ts +59 -0
  34. package/demo/transport.d.ts.map +1 -0
  35. package/demo/transport.js +75 -0
  36. package/demo/transport.js.map +1 -0
  37. package/demo/types.d.ts +62 -0
  38. package/demo/types.d.ts.map +1 -0
  39. package/demo/types.js +16 -0
  40. package/demo/types.js.map +1 -0
  41. package/environment/EnvVarForm.d.ts.map +1 -1
  42. package/environment/EnvVarForm.js +1 -1
  43. package/environment/EnvVarForm.js.map +1 -1
  44. package/environment/__tests__/systemEnvVars.test.d.ts +2 -0
  45. package/environment/__tests__/systemEnvVars.test.d.ts.map +1 -0
  46. package/environment/__tests__/systemEnvVars.test.js +76 -0
  47. package/environment/__tests__/systemEnvVars.test.js.map +1 -0
  48. package/environment/index.d.ts +1 -0
  49. package/environment/index.d.ts.map +1 -1
  50. package/environment/index.js +1 -0
  51. package/environment/index.js.map +1 -1
  52. package/environment/systemEnvVars.d.ts +52 -0
  53. package/environment/systemEnvVars.d.ts.map +1 -0
  54. package/environment/systemEnvVars.js +91 -0
  55. package/environment/systemEnvVars.js.map +1 -0
  56. package/execution/ApprovalCard.d.ts.map +1 -1
  57. package/execution/ApprovalCard.js +3 -3
  58. package/execution/ApprovalCard.js.map +1 -1
  59. package/index.d.ts +1 -1
  60. package/index.d.ts.map +1 -1
  61. package/index.js +2 -2
  62. package/index.js.map +1 -1
  63. package/internal/Tabs.d.ts +41 -0
  64. package/internal/Tabs.d.ts.map +1 -0
  65. package/internal/Tabs.js +65 -0
  66. package/internal/Tabs.js.map +1 -0
  67. package/mcp-server/McpServerDetailView.d.ts +33 -7
  68. package/mcp-server/McpServerDetailView.d.ts.map +1 -1
  69. package/mcp-server/McpServerDetailView.js +53 -37
  70. package/mcp-server/McpServerDetailView.js.map +1 -1
  71. package/mcp-server/useMcpServerCredentials.d.ts.map +1 -1
  72. package/mcp-server/useMcpServerCredentials.js +2 -1
  73. package/mcp-server/useMcpServerCredentials.js.map +1 -1
  74. package/models/index.d.ts +1 -1
  75. package/models/index.d.ts.map +1 -1
  76. package/models/index.js +1 -1
  77. package/models/index.js.map +1 -1
  78. package/models/registry.d.ts +10 -0
  79. package/models/registry.d.ts.map +1 -1
  80. package/models/registry.js +13 -0
  81. package/models/registry.js.map +1 -1
  82. package/models/useModelRegistry.d.ts.map +1 -1
  83. package/models/useModelRegistry.js +7 -3
  84. package/models/useModelRegistry.js.map +1 -1
  85. package/package.json +9 -5
  86. package/src/composer/SessionComposer.tsx +21 -3
  87. package/src/demo/__tests__/demo-client.test.tsx +213 -0
  88. package/src/demo/__tests__/fixtures.test.ts +214 -0
  89. package/src/demo/__tests__/samples.test.ts +171 -0
  90. package/src/demo/client.ts +78 -0
  91. package/src/demo/fixtures.ts +401 -0
  92. package/src/demo/index.ts +12 -0
  93. package/src/demo/samples.ts +470 -0
  94. package/src/demo/transport.ts +116 -0
  95. package/src/demo/types.ts +69 -0
  96. package/src/environment/EnvVarForm.tsx +1 -0
  97. package/src/environment/__tests__/systemEnvVars.test.ts +120 -0
  98. package/src/environment/index.ts +6 -0
  99. package/src/environment/systemEnvVars.ts +104 -0
  100. package/src/execution/ApprovalCard.tsx +4 -0
  101. package/src/index.ts +5 -1
  102. package/src/internal/Tabs.tsx +166 -0
  103. package/src/mcp-server/McpServerDetailView.tsx +273 -204
  104. package/src/mcp-server/useMcpServerCredentials.ts +4 -1
  105. package/src/models/index.ts +1 -1
  106. package/src/models/registry.ts +14 -0
  107. package/src/models/useModelRegistry.ts +7 -2
  108. package/styles.css +1 -1
@@ -0,0 +1,470 @@
1
+ import { create } from "@bufbuild/protobuf";
2
+ import { AgentSchema, type Agent } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/api_pb";
3
+ import { AgentSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agent/v1/spec_pb";
4
+ import {
5
+ AgentExecutionSchema,
6
+ AgentExecutionStatusSchema,
7
+ type AgentExecution,
8
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/api_pb";
9
+ import {
10
+ ExecutionArtifactSchema,
11
+ type ExecutionArtifact,
12
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/artifact_pb";
13
+ import {
14
+ ExecutionArtifactKind,
15
+ ExecutionPhase,
16
+ MessageType,
17
+ ToolCallStatus,
18
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/enum_pb";
19
+ import {
20
+ AgentExecutionListSchema,
21
+ type AgentExecutionList,
22
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/io_pb";
23
+ import {
24
+ AgentMessageSchema,
25
+ ToolCallSchema,
26
+ type AgentMessage,
27
+ type ToolCall,
28
+ } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/message_pb";
29
+ import { AgentExecutionSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agentexecution/v1/spec_pb";
30
+ import {
31
+ AgentInstanceSchema,
32
+ type AgentInstance,
33
+ } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/api_pb";
34
+ import { AgentInstanceSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/agentinstance/v1/spec_pb";
35
+ import {
36
+ EnvironmentSchema,
37
+ type Environment,
38
+ } from "@stigmer/protos/ai/stigmer/agentic/environment/v1/api_pb";
39
+ import {
40
+ ApiKeySchema,
41
+ ApiKeyStatusSchema,
42
+ type ApiKey,
43
+ } from "@stigmer/protos/ai/stigmer/iam/apikey/v1/api_pb";
44
+ import { ApiKeySpecSchema } from "@stigmer/protos/ai/stigmer/iam/apikey/v1/spec_pb";
45
+ import {
46
+ ApiKeysSchema,
47
+ type ApiKeys,
48
+ } from "@stigmer/protos/ai/stigmer/iam/apikey/v1/io_pb";
49
+ import {
50
+ ApiResourceAuditSchema,
51
+ ApiResourceAuditInfoSchema,
52
+ } from "@stigmer/protos/ai/stigmer/commons/apiresource/status_pb";
53
+ import {
54
+ McpServerSchema,
55
+ type McpServer,
56
+ } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/api_pb";
57
+ import { McpServerSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/mcpserver/v1/spec_pb";
58
+ import {
59
+ SessionSchema,
60
+ type Session,
61
+ } from "@stigmer/protos/ai/stigmer/agentic/session/v1/api_pb";
62
+ import {
63
+ SessionListSchema,
64
+ type SessionList,
65
+ } from "@stigmer/protos/ai/stigmer/agentic/session/v1/io_pb";
66
+ import { SessionSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/session/v1/spec_pb";
67
+ import { SkillSchema, type Skill } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/api_pb";
68
+ import { SkillSpecSchema } from "@stigmer/protos/ai/stigmer/agentic/skill/v1/spec_pb";
69
+ import { ApiResourceKind } from "@stigmer/protos/ai/stigmer/commons/apiresource/apiresourcekind/api_resource_kind_pb";
70
+ import { ApiResourceMetadataSchema } from "@stigmer/protos/ai/stigmer/commons/apiresource/metadata_pb";
71
+ import {
72
+ SearchResponseSchema,
73
+ SearchResultSchema,
74
+ type SearchResponse,
75
+ type SearchResult,
76
+ } from "@stigmer/protos/ai/stigmer/search/v1/io_pb";
77
+
78
+ // ---------------------------------------------------------------------------
79
+ // Override interfaces — flat projections of commonly-customized fields
80
+ // ---------------------------------------------------------------------------
81
+
82
+ export interface SessionOverrides {
83
+ readonly id?: string;
84
+ readonly name?: string;
85
+ readonly org?: string;
86
+ readonly slug?: string;
87
+ readonly subject?: string;
88
+ readonly agentInstanceId?: string;
89
+ }
90
+
91
+ export interface AgentOverrides {
92
+ readonly id?: string;
93
+ readonly name?: string;
94
+ readonly org?: string;
95
+ readonly slug?: string;
96
+ readonly description?: string;
97
+ readonly instructions?: string;
98
+ }
99
+
100
+ export interface AgentExecutionOverrides {
101
+ readonly id?: string;
102
+ readonly sessionId?: string;
103
+ readonly agentId?: string;
104
+ readonly phase?: ExecutionPhase;
105
+ readonly messages?: AgentMessage[];
106
+ readonly artifacts?: ExecutionArtifact[];
107
+ }
108
+
109
+ export interface SkillOverrides {
110
+ readonly id?: string;
111
+ readonly name?: string;
112
+ readonly org?: string;
113
+ readonly slug?: string;
114
+ readonly description?: string;
115
+ readonly skillMd?: string;
116
+ }
117
+
118
+ export interface McpServerOverrides {
119
+ readonly id?: string;
120
+ readonly name?: string;
121
+ readonly org?: string;
122
+ readonly slug?: string;
123
+ readonly description?: string;
124
+ }
125
+
126
+ export interface EnvironmentOverrides {
127
+ readonly id?: string;
128
+ readonly name?: string;
129
+ readonly org?: string;
130
+ readonly slug?: string;
131
+ }
132
+
133
+ export interface AgentInstanceOverrides {
134
+ readonly id?: string;
135
+ readonly name?: string;
136
+ readonly org?: string;
137
+ readonly slug?: string;
138
+ readonly agentId?: string;
139
+ }
140
+
141
+ export interface ApiKeyOverrides {
142
+ readonly id?: string;
143
+ readonly name?: string;
144
+ readonly slug?: string;
145
+ readonly fingerprint?: string;
146
+ readonly neverExpires?: boolean;
147
+ readonly keyHash?: string;
148
+ }
149
+
150
+ export interface SearchResultOverrides {
151
+ readonly id?: string;
152
+ readonly name?: string;
153
+ readonly org?: string;
154
+ readonly slug?: string;
155
+ readonly kind?: ApiResourceKind;
156
+ readonly description?: string;
157
+ }
158
+
159
+ // ---------------------------------------------------------------------------
160
+ // Resource factories
161
+ // ---------------------------------------------------------------------------
162
+
163
+ /**
164
+ * Sample data factories for building demo fixtures.
165
+ *
166
+ * Each factory returns a realistic protobuf object with sensible defaults.
167
+ * Pass an overrides object to customize the most commonly-needed fields.
168
+ * For deeper customization, modify the returned object directly — protobuf
169
+ * messages from `create()` are mutable plain objects.
170
+ *
171
+ * @example
172
+ * ```ts
173
+ * import { samples, fixtures, buildScenario } from "@stigmer/react/demo";
174
+ *
175
+ * const scenario = buildScenario(
176
+ * fixtures.session.get(() => samples.session({ subject: "My topic" })),
177
+ * fixtures.agent.getByReference(() => samples.agent({ name: "My Agent" })),
178
+ * );
179
+ * ```
180
+ */
181
+ export const samples = {
182
+ /**
183
+ * A session resource with metadata and spec.
184
+ * Default: `demo-session` in org `demo` with subject "Demo conversation".
185
+ */
186
+ session(o?: SessionOverrides): Session {
187
+ return create(SessionSchema, {
188
+ apiVersion: "agentic.stigmer.ai/v1",
189
+ kind: "Session",
190
+ metadata: create(ApiResourceMetadataSchema, {
191
+ id: o?.id ?? "ses-00000000-0000-0000-0000-000000000001",
192
+ name: o?.name ?? "demo-session",
193
+ slug: o?.slug ?? o?.name ?? "demo-session",
194
+ org: o?.org ?? "demo",
195
+ }),
196
+ spec: create(SessionSpecSchema, {
197
+ subject: o?.subject ?? "Demo conversation",
198
+ agentInstanceId:
199
+ o?.agentInstanceId ?? "ain-00000000-0000-0000-0000-000000000001",
200
+ }),
201
+ });
202
+ },
203
+
204
+ /**
205
+ * An agent blueprint with metadata and spec.
206
+ * Default: `Demo Agent` in org `demo`.
207
+ */
208
+ agent(o?: AgentOverrides): Agent {
209
+ return create(AgentSchema, {
210
+ apiVersion: "agentic.stigmer.ai/v1",
211
+ kind: "Agent",
212
+ metadata: create(ApiResourceMetadataSchema, {
213
+ id: o?.id ?? "agt-00000000-0000-0000-0000-000000000001",
214
+ name: o?.name ?? "Demo Agent",
215
+ slug: o?.slug ?? o?.name?.toLowerCase().replace(/\s+/g, "-") ?? "demo-agent",
216
+ org: o?.org ?? "demo",
217
+ }),
218
+ spec: create(AgentSpecSchema, {
219
+ description: o?.description ?? "A sample agent for demo and documentation purposes.",
220
+ instructions:
221
+ o?.instructions ??
222
+ "You are a helpful assistant. Answer questions clearly and concisely.",
223
+ }),
224
+ });
225
+ },
226
+
227
+ /**
228
+ * An agent execution with status, messages, and optional artifacts.
229
+ * Default: completed execution with a short human/AI exchange.
230
+ */
231
+ agentExecution(o?: AgentExecutionOverrides): AgentExecution {
232
+ const msgs =
233
+ o?.messages ?? [
234
+ samples.humanMessage("Hello! Can you help me get started?"),
235
+ samples.aiMessage(
236
+ "Of course! I'd be happy to help you get started. What would you like to work on?",
237
+ ),
238
+ ];
239
+
240
+ return create(AgentExecutionSchema, {
241
+ apiVersion: "agentic.stigmer.ai/v1",
242
+ kind: "AgentExecution",
243
+ metadata: create(ApiResourceMetadataSchema, {
244
+ id: o?.id ?? "aex-00000000-0000-0000-0000-000000000001",
245
+ name: "demo-execution",
246
+ slug: "demo-execution",
247
+ org: "demo",
248
+ }),
249
+ spec: create(AgentExecutionSpecSchema, {
250
+ sessionId: o?.sessionId ?? "ses-00000000-0000-0000-0000-000000000001",
251
+ agentId: o?.agentId ?? "agt-00000000-0000-0000-0000-000000000001",
252
+ message: msgs[0]?.content ?? "",
253
+ }),
254
+ status: create(AgentExecutionStatusSchema, {
255
+ phase: o?.phase ?? ExecutionPhase.EXECUTION_COMPLETED,
256
+ messages: msgs,
257
+ artifacts: o?.artifacts ?? [],
258
+ }),
259
+ });
260
+ },
261
+
262
+ /**
263
+ * A skill resource with SKILL.md content.
264
+ * Default: `Demo Skill` in org `demo`.
265
+ */
266
+ skill(o?: SkillOverrides): Skill {
267
+ return create(SkillSchema, {
268
+ apiVersion: "agentic.stigmer.ai/v1",
269
+ kind: "Skill",
270
+ metadata: create(ApiResourceMetadataSchema, {
271
+ id: o?.id ?? "skl-00000000-0000-0000-0000-000000000001",
272
+ name: o?.name ?? "Demo Skill",
273
+ slug: o?.slug ?? o?.name?.toLowerCase().replace(/\s+/g, "-") ?? "demo-skill",
274
+ org: o?.org ?? "demo",
275
+ }),
276
+ spec: create(SkillSpecSchema, {
277
+ description: o?.description ?? "A sample skill for demo purposes.",
278
+ skillMd:
279
+ o?.skillMd ??
280
+ "# Demo Skill\n\nThis skill provides sample domain knowledge for demonstrations.",
281
+ }),
282
+ });
283
+ },
284
+
285
+ /**
286
+ * An MCP server resource.
287
+ * Default: `Demo MCP Server` in org `demo`.
288
+ */
289
+ mcpServer(o?: McpServerOverrides): McpServer {
290
+ return create(McpServerSchema, {
291
+ apiVersion: "agentic.stigmer.ai/v1",
292
+ kind: "McpServer",
293
+ metadata: create(ApiResourceMetadataSchema, {
294
+ id: o?.id ?? "mcp-00000000-0000-0000-0000-000000000001",
295
+ name: o?.name ?? "Demo MCP Server",
296
+ slug:
297
+ o?.slug ?? o?.name?.toLowerCase().replace(/\s+/g, "-") ?? "demo-mcp-server",
298
+ org: o?.org ?? "demo",
299
+ }),
300
+ spec: create(McpServerSpecSchema, {
301
+ description:
302
+ o?.description ?? "A sample MCP server for demo purposes.",
303
+ }),
304
+ });
305
+ },
306
+
307
+ /**
308
+ * An environment resource.
309
+ * Default: `demo-env` in org `demo`.
310
+ */
311
+ environment(o?: EnvironmentOverrides): Environment {
312
+ return create(EnvironmentSchema, {
313
+ apiVersion: "agentic.stigmer.ai/v1",
314
+ kind: "Environment",
315
+ metadata: create(ApiResourceMetadataSchema, {
316
+ id: o?.id ?? "env-00000000-0000-0000-0000-000000000001",
317
+ name: o?.name ?? "demo-env",
318
+ slug: o?.slug ?? o?.name ?? "demo-env",
319
+ org: o?.org ?? "demo",
320
+ }),
321
+ });
322
+ },
323
+
324
+ /**
325
+ * An agent instance resource.
326
+ * Default: `demo-instance` in org `demo` referencing the default demo agent.
327
+ */
328
+ agentInstance(o?: AgentInstanceOverrides): AgentInstance {
329
+ return create(AgentInstanceSchema, {
330
+ apiVersion: "agentic.stigmer.ai/v1",
331
+ kind: "AgentInstance",
332
+ metadata: create(ApiResourceMetadataSchema, {
333
+ id: o?.id ?? "ain-00000000-0000-0000-0000-000000000001",
334
+ name: o?.name ?? "demo-instance",
335
+ slug: o?.slug ?? o?.name ?? "demo-instance",
336
+ org: o?.org ?? "demo",
337
+ }),
338
+ spec: create(AgentInstanceSpecSchema, {
339
+ agentId: o?.agentId ?? "agt-00000000-0000-0000-0000-000000000001",
340
+ }),
341
+ });
342
+ },
343
+
344
+ /**
345
+ * An API key resource with metadata, spec, and status.
346
+ * Default: `demo-api-key` with fingerprint `Ab1c2D` and no expiry.
347
+ */
348
+ apiKey(o?: ApiKeyOverrides): ApiKey {
349
+ return create(ApiKeySchema, {
350
+ apiVersion: "iam.stigmer.ai/v1",
351
+ kind: "ApiKey",
352
+ metadata: create(ApiResourceMetadataSchema, {
353
+ id: o?.id ?? "apk-00000000-0000-0000-0000-000000000001",
354
+ name: o?.name ?? "demo-api-key",
355
+ slug: o?.slug ?? o?.name?.toLowerCase().replace(/\s+/g, "-") ?? "demo-api-key",
356
+ }),
357
+ spec: create(ApiKeySpecSchema, {
358
+ fingerprint: o?.fingerprint ?? "Ab1c2D",
359
+ neverExpires: o?.neverExpires ?? true,
360
+ keyHash: o?.keyHash ?? "",
361
+ }),
362
+ status: create(ApiKeyStatusSchema, {
363
+ audit: create(ApiResourceAuditSchema, {
364
+ specAudit: create(ApiResourceAuditInfoSchema, {
365
+ createdAt: { seconds: BigInt(Math.floor(Date.now() / 1000)), nanos: 0 },
366
+ }),
367
+ }),
368
+ }),
369
+ });
370
+ },
371
+
372
+ // ---- Message & artifact primitives ----
373
+
374
+ /** A human (user) message. */
375
+ humanMessage(content: string): AgentMessage {
376
+ return create(AgentMessageSchema, {
377
+ type: MessageType.MESSAGE_HUMAN,
378
+ content,
379
+ timestamp: new Date().toISOString(),
380
+ });
381
+ },
382
+
383
+ /** An AI (assistant) message, optionally with tool calls. */
384
+ aiMessage(content: string, toolCalls?: ToolCall[]): AgentMessage {
385
+ return create(AgentMessageSchema, {
386
+ type: MessageType.MESSAGE_AI,
387
+ content,
388
+ timestamp: new Date().toISOString(),
389
+ toolCalls: toolCalls ?? [],
390
+ });
391
+ },
392
+
393
+ /** A completed tool call with a result. */
394
+ toolCall(name: string, result: string): ToolCall {
395
+ return create(ToolCallSchema, {
396
+ id: `tc-${name}-${Date.now()}`,
397
+ name,
398
+ result,
399
+ status: ToolCallStatus.TOOL_CALL_COMPLETED,
400
+ startedAt: new Date().toISOString(),
401
+ completedAt: new Date().toISOString(),
402
+ });
403
+ },
404
+
405
+ /** A file artifact produced by an execution. */
406
+ artifact(name: string, kind?: ExecutionArtifactKind): ExecutionArtifact {
407
+ return create(ExecutionArtifactSchema, {
408
+ name,
409
+ kind: kind ?? ExecutionArtifactKind.FILE,
410
+ storageKey: `demo-artifact-${name}`,
411
+ createdAt: new Date().toISOString(),
412
+ });
413
+ },
414
+
415
+ // ---- List response factories ----
416
+
417
+ /** A session list response. Defaults to one demo session. */
418
+ sessionList(entries?: Session[]): SessionList {
419
+ const items = entries ?? [samples.session()];
420
+ return create(SessionListSchema, {
421
+ entries: items,
422
+ totalPages: 1,
423
+ });
424
+ },
425
+
426
+ /** An agent execution list response. Defaults to one demo execution. */
427
+ agentExecutionList(entries?: AgentExecution[]): AgentExecutionList {
428
+ const items = entries ?? [samples.agentExecution()];
429
+ return create(AgentExecutionListSchema, {
430
+ entries: items,
431
+ totalPages: 1,
432
+ });
433
+ },
434
+
435
+ /**
436
+ * A search response for list hooks (`useAgentList`, `useSkillList`, etc.).
437
+ * Defaults to one search result matching the specified kind.
438
+ */
439
+ searchResponse(
440
+ entries?: SearchResult[],
441
+ totalCount?: number,
442
+ ): SearchResponse {
443
+ const items = entries ?? [samples.searchResult()];
444
+ return create(SearchResponseSchema, {
445
+ entries: items,
446
+ totalCount: totalCount ?? items.length,
447
+ totalPages: 1,
448
+ });
449
+ },
450
+
451
+ /** An API key list response. Defaults to one demo API key. */
452
+ apiKeyList(entries?: ApiKey[]): ApiKeys {
453
+ const items = entries ?? [samples.apiKey()];
454
+ return create(ApiKeysSchema, { entries: items });
455
+ },
456
+
457
+ /** A single search result entry. */
458
+ searchResult(o?: SearchResultOverrides): SearchResult {
459
+ return create(SearchResultSchema, {
460
+ kind: o?.kind ?? ApiResourceKind.agent,
461
+ id: o?.id ?? "agt-00000000-0000-0000-0000-000000000001",
462
+ name: o?.name ?? "Demo Agent",
463
+ slug: o?.slug ?? "demo-agent",
464
+ qualifiedSlug: `${o?.org ?? "demo"}/${o?.slug ?? "demo-agent"}`,
465
+ org: o?.org ?? "demo",
466
+ description: o?.description ?? "A sample resource for demo purposes.",
467
+ score: 1.0,
468
+ });
469
+ },
470
+ } as const;
@@ -0,0 +1,116 @@
1
+ import type { FixtureRegistry } from "./types";
2
+
3
+ /**
4
+ * Minimal shape of a Connect-RPC method descriptor.
5
+ *
6
+ * Matches the relevant fields of `DescMethodUnary` and `DescMethodStreaming`
7
+ * from `@bufbuild/protobuf` without importing the full generic types.
8
+ * The transport only needs the service type name and method name to
9
+ * look up fixture handlers.
10
+ */
11
+ interface RpcMethodDescriptor {
12
+ readonly parent: { readonly typeName: string };
13
+ readonly name: string;
14
+ }
15
+
16
+ function fixtureKey(method: RpcMethodDescriptor): string {
17
+ return `${method.parent.typeName}/${method.name}`;
18
+ }
19
+
20
+ function shortServiceName(method: RpcMethodDescriptor): string {
21
+ return method.parent.typeName.split(".").pop() ?? method.parent.typeName;
22
+ }
23
+
24
+ /**
25
+ * A Connect-RPC `Transport` backed by in-memory fixture data.
26
+ *
27
+ * Implements the two-method `Transport` interface (`unary` and `stream`)
28
+ * from `@connectrpc/connect`. When a generated client issues an RPC,
29
+ * the transport looks up the matching fixture handler by
30
+ * `"<service typeName>/<method name>"` and returns its result.
31
+ *
32
+ * Methods without registered fixtures throw a descriptive error
33
+ * identifying the missing key and how to register it.
34
+ *
35
+ * This class is not typed as `implements Transport` because the interface
36
+ * uses complex generics from `@bufbuild/protobuf` that would force a
37
+ * runtime dependency on `@connectrpc/connect` in `@stigmer/react`.
38
+ * The runtime shape is fully compatible — the client factory casts the
39
+ * instance to `Transport` at the single point where it is passed to
40
+ * generated client constructors.
41
+ */
42
+ export class DemoTransport {
43
+ private readonly fixtures: FixtureRegistry;
44
+
45
+ constructor(fixtures: FixtureRegistry) {
46
+ this.fixtures = fixtures;
47
+ }
48
+
49
+ async unary(
50
+ method: RpcMethodDescriptor,
51
+ _signal: AbortSignal | undefined,
52
+ _timeoutMs: number | undefined,
53
+ _header: HeadersInit | undefined,
54
+ input: unknown,
55
+ ) {
56
+ const key = fixtureKey(method);
57
+ const entry = this.fixtures.get(key);
58
+
59
+ if (!entry?.unary) {
60
+ throw new Error(
61
+ `No demo fixture for ${shortServiceName(method)}/${method.name}. ` +
62
+ `Add a fixture with key "${key}" to your DemoScenario.`,
63
+ );
64
+ }
65
+
66
+ return {
67
+ stream: false as const,
68
+ message: entry.unary(input),
69
+ method,
70
+ service: method.parent,
71
+ header: new Headers(),
72
+ trailer: new Headers(),
73
+ };
74
+ }
75
+
76
+ async stream(
77
+ method: RpcMethodDescriptor,
78
+ _signal: AbortSignal | undefined,
79
+ _timeoutMs: number | undefined,
80
+ _header: HeadersInit | undefined,
81
+ input: AsyncIterable<unknown>,
82
+ ) {
83
+ const key = fixtureKey(method);
84
+ const entry = this.fixtures.get(key);
85
+
86
+ if (!entry?.stream) {
87
+ throw new Error(
88
+ `No demo fixture for ${shortServiceName(method)}/${method.name}. ` +
89
+ `Add a fixture with key "${key}" to your DemoScenario.`,
90
+ );
91
+ }
92
+
93
+ // Server-streaming RPCs send a single request message wrapped in an
94
+ // async iterable by createClient. Extract it for the fixture handler.
95
+ let request: unknown;
96
+ for await (const msg of input) {
97
+ request = msg;
98
+ break;
99
+ }
100
+
101
+ return {
102
+ stream: true as const,
103
+ message: toAsyncIterable(entry.stream(request)),
104
+ method,
105
+ service: method.parent,
106
+ header: new Headers(),
107
+ trailer: new Headers(),
108
+ };
109
+ }
110
+ }
111
+
112
+ async function* toAsyncIterable<T>(items: T[]): AsyncGenerator<T> {
113
+ for (const item of items) {
114
+ yield item;
115
+ }
116
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Handler for a unary (request-response) RPC fixture.
3
+ *
4
+ * Receives the protobuf request message and returns the response message.
5
+ * Build responses with `create()` from `@bufbuild/protobuf` to ensure
6
+ * correct message shapes.
7
+ */
8
+ export type UnaryFixtureHandler = (request: unknown) => unknown;
9
+
10
+ /**
11
+ * Handler for a server-streaming RPC fixture.
12
+ *
13
+ * Receives the protobuf request message and returns an array of response
14
+ * messages that the transport yields as an async stream.
15
+ */
16
+ export type StreamFixtureHandler = (request: unknown) => unknown[];
17
+
18
+ /**
19
+ * Fixture configuration for a single RPC method.
20
+ *
21
+ * Register `unary` for request-response RPCs, or `stream` for
22
+ * server-streaming RPCs. The transport checks the appropriate handler
23
+ * based on how the generated client invokes the method.
24
+ */
25
+ export interface FixtureEntry {
26
+ readonly unary?: UnaryFixtureHandler;
27
+ readonly stream?: StreamFixtureHandler;
28
+ }
29
+
30
+ /**
31
+ * Map of fully-qualified RPC method keys to fixture handlers.
32
+ *
33
+ * Keys use the format `"<proto service typeName>/<method name>"`, e.g.:
34
+ * ```
35
+ * "ai.stigmer.agentic.session.v1.SessionQueryController/get"
36
+ * ```
37
+ *
38
+ * Use {@link rpcKey} to construct keys from proto service descriptors.
39
+ */
40
+ export type FixtureRegistry = ReadonlyMap<string, FixtureEntry>;
41
+
42
+ /**
43
+ * A collection of RPC fixture handlers that powers a demo client.
44
+ *
45
+ * Pass to {@link createDemoClient} to obtain a `Stigmer`-compatible
46
+ * client that resolves RPCs from in-memory data instead of a live backend.
47
+ */
48
+ export interface DemoScenario {
49
+ readonly fixtures: FixtureRegistry;
50
+ }
51
+
52
+ /**
53
+ * Construct a fixture registry key from a proto service descriptor
54
+ * and method name.
55
+ *
56
+ * @example
57
+ * ```ts
58
+ * import { SessionQueryController } from "@stigmer/protos/ai/stigmer/agentic/session/v1/query_pb";
59
+ *
60
+ * rpcKey(SessionQueryController, "get")
61
+ * // → "ai.stigmer.agentic.session.v1.SessionQueryController/get"
62
+ * ```
63
+ */
64
+ export function rpcKey(
65
+ service: { readonly typeName: string },
66
+ method: string,
67
+ ): string {
68
+ return `${service.typeName}/${method}`;
69
+ }
@@ -397,6 +397,7 @@ export function EnvVarForm({
397
397
  <button
398
398
  type="submit"
399
399
  disabled={!allFilled || isDisabled}
400
+ data-cursor-target="env-form-submit"
400
401
  className={cn(
401
402
  "inline-flex items-center gap-1.5 rounded-md px-3 py-1.5 text-xs font-medium",
402
403
  "bg-primary text-primary-foreground",