@contractspec/example.agent-console 3.7.7 → 3.8.4

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 (191) hide show
  1. package/.turbo/turbo-build.log +126 -105
  2. package/AGENTS.md +3 -1
  3. package/CHANGELOG.md +57 -0
  4. package/README.md +46 -9
  5. package/dist/agent/agent.handler.d.ts +3 -0
  6. package/dist/agent/agent.handler.js +730 -1
  7. package/dist/agent/index.js +73 -72
  8. package/dist/agent.feature.js +179 -0
  9. package/dist/browser/agent/agent.handler.js +730 -1
  10. package/dist/browser/agent/index.js +73 -72
  11. package/dist/browser/agent.feature.js +179 -0
  12. package/dist/browser/docs/agent-console.docblock.js +11 -8
  13. package/dist/browser/docs/index.js +11 -8
  14. package/dist/browser/example.js +2 -3
  15. package/dist/browser/handlers/agent.handlers.js +1883 -2
  16. package/dist/browser/handlers/index.js +2142 -8
  17. package/dist/browser/index.js +3347 -2433
  18. package/dist/browser/presentations/index.js +49 -49
  19. package/dist/browser/run/index.js +818 -812
  20. package/dist/browser/run/run.handler.js +666 -1
  21. package/dist/browser/shared/index.js +293 -1
  22. package/dist/browser/shared/mock-runs.js +5 -0
  23. package/dist/browser/tool/index.js +331 -331
  24. package/dist/browser/tool/tool.handler.js +479 -3
  25. package/dist/browser/ui/AgentDashboard.js +1204 -319
  26. package/dist/browser/ui/AgentDashboard.visualizations.js +217 -0
  27. package/dist/browser/ui/AgentRunList.js +359 -127
  28. package/dist/browser/ui/hooks/index.js +468 -18
  29. package/dist/browser/ui/hooks/useAgentMutations.js +443 -8
  30. package/dist/browser/ui/hooks/useRunList.js +25 -10
  31. package/dist/browser/ui/index.js +1293 -390
  32. package/dist/browser/ui/renderers/agent-list.markdown.js +14 -5
  33. package/dist/browser/ui/renderers/dashboard.markdown.js +207 -36
  34. package/dist/browser/ui/renderers/index.js +245 -49
  35. package/dist/browser/ui/renderers/run-list.markdown.js +9 -4
  36. package/dist/browser/ui/renderers/tool-registry.markdown.js +15 -4
  37. package/dist/browser/ui/views/RunDataTable.js +326 -0
  38. package/dist/browser/ui/views/RunListView.js +359 -127
  39. package/dist/browser/ui/views/index.js +406 -174
  40. package/dist/browser/ui/views/run-data-table.columns.js +271 -0
  41. package/dist/browser/ui/views/run-list.shared.js +177 -0
  42. package/dist/browser/visualizations/catalog.js +134 -0
  43. package/dist/browser/visualizations/index.js +187 -0
  44. package/dist/browser/visualizations/selectors.js +181 -0
  45. package/dist/docs/agent-console.docblock.js +11 -8
  46. package/dist/docs/index.js +11 -8
  47. package/dist/example.js +2 -3
  48. package/dist/example.test.d.ts +1 -0
  49. package/dist/handlers/agent.handlers.d.ts +2 -0
  50. package/dist/handlers/agent.handlers.js +1883 -2
  51. package/dist/handlers/index.d.ts +1 -3
  52. package/dist/handlers/index.js +2142 -8
  53. package/dist/handlers/mock-handlers.test.d.ts +1 -0
  54. package/dist/index.d.ts +2 -0
  55. package/dist/index.js +3347 -2433
  56. package/dist/node/agent/agent.handler.js +730 -1
  57. package/dist/node/agent/index.js +73 -72
  58. package/dist/node/agent.feature.js +179 -0
  59. package/dist/node/docs/agent-console.docblock.js +11 -8
  60. package/dist/node/docs/index.js +11 -8
  61. package/dist/node/example.js +2 -3
  62. package/dist/node/handlers/agent.handlers.js +1883 -2
  63. package/dist/node/handlers/index.js +2142 -8
  64. package/dist/node/index.js +3347 -2433
  65. package/dist/node/presentations/index.js +49 -49
  66. package/dist/node/run/index.js +818 -812
  67. package/dist/node/run/run.handler.js +666 -1
  68. package/dist/node/shared/index.js +293 -1
  69. package/dist/node/shared/mock-runs.js +5 -0
  70. package/dist/node/tool/index.js +331 -331
  71. package/dist/node/tool/tool.handler.js +479 -3
  72. package/dist/node/ui/AgentDashboard.js +1204 -319
  73. package/dist/node/ui/AgentDashboard.visualizations.js +217 -0
  74. package/dist/node/ui/AgentRunList.js +359 -127
  75. package/dist/node/ui/hooks/index.js +468 -18
  76. package/dist/node/ui/hooks/useAgentMutations.js +443 -8
  77. package/dist/node/ui/hooks/useRunList.js +25 -10
  78. package/dist/node/ui/index.js +1293 -390
  79. package/dist/node/ui/renderers/agent-list.markdown.js +14 -5
  80. package/dist/node/ui/renderers/dashboard.markdown.js +207 -36
  81. package/dist/node/ui/renderers/index.js +245 -49
  82. package/dist/node/ui/renderers/run-list.markdown.js +9 -4
  83. package/dist/node/ui/renderers/tool-registry.markdown.js +15 -4
  84. package/dist/node/ui/views/RunDataTable.js +326 -0
  85. package/dist/node/ui/views/RunListView.js +359 -127
  86. package/dist/node/ui/views/index.js +406 -174
  87. package/dist/node/ui/views/run-data-table.columns.js +271 -0
  88. package/dist/node/ui/views/run-list.shared.js +177 -0
  89. package/dist/node/visualizations/catalog.js +134 -0
  90. package/dist/node/visualizations/index.js +187 -0
  91. package/dist/node/visualizations/selectors.js +181 -0
  92. package/dist/presentations/index.js +49 -49
  93. package/dist/proof/index.d.ts +2 -0
  94. package/dist/proof/meetup-proof.d.ts +10 -0
  95. package/dist/proof/meetup-proof.runtime.d.ts +22 -0
  96. package/dist/proof/meetup-proof.scenario.d.ts +2 -0
  97. package/dist/proof/meetup-proof.suite.d.ts +1 -0
  98. package/dist/proof/meetup-proof.test.d.ts +1 -0
  99. package/dist/run/index.js +818 -812
  100. package/dist/run/run.handler.d.ts +4 -0
  101. package/dist/run/run.handler.js +666 -1
  102. package/dist/shared/demo-dashboard-data.d.ts +16 -0
  103. package/dist/shared/demo-runtime-seed.d.ts +17 -0
  104. package/dist/shared/demo-runtime.d.ts +8 -0
  105. package/dist/shared/demo-runtime.test.d.ts +1 -0
  106. package/dist/shared/index.d.ts +3 -0
  107. package/dist/shared/index.js +293 -1
  108. package/dist/shared/mock-runs.d.ts +4 -0
  109. package/dist/shared/mock-runs.js +5 -0
  110. package/dist/tool/index.js +331 -331
  111. package/dist/tool/tool.handler.d.ts +4 -1
  112. package/dist/tool/tool.handler.js +479 -3
  113. package/dist/ui/AgentDashboard.js +1204 -319
  114. package/dist/ui/AgentDashboard.sandbox.test.d.ts +1 -0
  115. package/dist/ui/AgentDashboard.visualizations.d.ts +4 -0
  116. package/dist/ui/AgentDashboard.visualizations.js +218 -0
  117. package/dist/ui/AgentRunList.js +359 -127
  118. package/dist/ui/hooks/index.js +468 -18
  119. package/dist/ui/hooks/useAgentMutations.js +443 -8
  120. package/dist/ui/hooks/useRunList.d.ts +8 -2
  121. package/dist/ui/hooks/useRunList.js +25 -10
  122. package/dist/ui/index.js +1293 -390
  123. package/dist/ui/renderers/agent-list.markdown.d.ts +1 -1
  124. package/dist/ui/renderers/agent-list.markdown.js +14 -5
  125. package/dist/ui/renderers/agent-list.renderer.d.ts +1 -1
  126. package/dist/ui/renderers/dashboard.markdown.d.ts +1 -1
  127. package/dist/ui/renderers/dashboard.markdown.js +207 -36
  128. package/dist/ui/renderers/index.js +245 -49
  129. package/dist/ui/renderers/run-list.markdown.d.ts +1 -1
  130. package/dist/ui/renderers/run-list.markdown.js +9 -4
  131. package/dist/ui/renderers/tool-registry.markdown.d.ts +2 -2
  132. package/dist/ui/renderers/tool-registry.markdown.js +15 -4
  133. package/dist/ui/views/RunDataTable.d.ts +18 -0
  134. package/dist/ui/views/RunDataTable.js +327 -0
  135. package/dist/ui/views/RunListView.js +359 -127
  136. package/dist/ui/views/index.js +406 -174
  137. package/dist/ui/views/run-data-table.columns.d.ts +3 -0
  138. package/dist/ui/views/run-data-table.columns.js +272 -0
  139. package/dist/ui/views/run-list.shared.d.ts +14 -0
  140. package/dist/ui/views/run-list.shared.js +178 -0
  141. package/dist/visualizations/catalog.d.ts +10 -0
  142. package/dist/visualizations/catalog.js +135 -0
  143. package/dist/visualizations/index.d.ts +2 -0
  144. package/dist/visualizations/index.js +188 -0
  145. package/dist/visualizations/selectors.d.ts +3 -0
  146. package/dist/visualizations/selectors.js +182 -0
  147. package/dist/visualizations/selectors.test.d.ts +1 -0
  148. package/package.json +114 -11
  149. package/proofs/agent-console-meetup.replay.json +220 -0
  150. package/src/agent/agent.handler.ts +18 -1
  151. package/src/agent.feature.ts +3 -0
  152. package/src/docs/agent-console.docblock.ts +11 -8
  153. package/src/example.test.ts +75 -0
  154. package/src/example.ts +2 -3
  155. package/src/handlers/agent.handlers.ts +55 -2
  156. package/src/handlers/index.ts +18 -2
  157. package/src/handlers/mock-handlers.test.ts +77 -0
  158. package/src/index.ts +2 -0
  159. package/src/proof/index.ts +2 -0
  160. package/src/proof/meetup-proof.runtime.ts +196 -0
  161. package/src/proof/meetup-proof.scenario.ts +99 -0
  162. package/src/proof/meetup-proof.suite.ts +29 -0
  163. package/src/proof/meetup-proof.test.ts +28 -0
  164. package/src/proof/meetup-proof.ts +130 -0
  165. package/src/run/run.handler.ts +17 -1
  166. package/src/shared/demo-dashboard-data.ts +58 -0
  167. package/src/shared/demo-runtime-seed.ts +139 -0
  168. package/src/shared/demo-runtime.test.ts +169 -0
  169. package/src/shared/demo-runtime.ts +260 -0
  170. package/src/shared/index.ts +11 -0
  171. package/src/shared/mock-runs.ts +5 -0
  172. package/src/tool/tool.handler.ts +21 -4
  173. package/src/ui/AgentDashboard.sandbox.test.tsx +312 -0
  174. package/src/ui/AgentDashboard.tsx +4 -1
  175. package/src/ui/AgentDashboard.visualizations.tsx +35 -0
  176. package/src/ui/hooks/useAgentMutations.ts +19 -11
  177. package/src/ui/hooks/useRunList.ts +41 -9
  178. package/src/ui/renderers/agent-list.markdown.ts +32 -13
  179. package/src/ui/renderers/agent-list.renderer.tsx +1 -1
  180. package/src/ui/renderers/dashboard.markdown.ts +38 -43
  181. package/src/ui/renderers/run-list.markdown.ts +17 -9
  182. package/src/ui/renderers/tool-registry.markdown.ts +22 -10
  183. package/src/ui/views/RunDataTable.tsx +74 -0
  184. package/src/ui/views/RunListView.tsx +37 -111
  185. package/src/ui/views/run-data-table.columns.tsx +102 -0
  186. package/src/ui/views/run-list.shared.tsx +139 -0
  187. package/src/visualizations/catalog.ts +132 -0
  188. package/src/visualizations/index.ts +2 -0
  189. package/src/visualizations/selectors.test.ts +12 -0
  190. package/src/visualizations/selectors.ts +70 -0
  191. package/tsdown.config.js +17 -0
@@ -0,0 +1,220 @@
1
+ {
2
+ "version": "1",
3
+ "createdAt": "2026-03-20T09:48:00.000Z",
4
+ "run": {
5
+ "runId": "proof-1",
6
+ "status": "completed",
7
+ "mode": "code-execution",
8
+ "scenarioKey": "agent-console.meetup.proof",
9
+ "target": {
10
+ "targetId": "sandbox-agent-console",
11
+ "kind": "sandbox",
12
+ "isolation": "sandbox",
13
+ "environment": "local",
14
+ "baseUrl": "https://sandbox.contractspec.local/agent-console",
15
+ "allowlistedDomains": ["sandbox.contractspec.local"]
16
+ },
17
+ "steps": [
18
+ {
19
+ "stepId": "proof-2",
20
+ "stepKey": "open-dashboard",
21
+ "runId": "proof-1",
22
+ "mode": "code-execution",
23
+ "actionClass": "code-exec-read",
24
+ "verdict": "autonomous",
25
+ "requiresApproval": false,
26
+ "status": "completed",
27
+ "startedAt": "2026-03-20T09:32:00.000Z",
28
+ "output": {
29
+ "agentCount": 4,
30
+ "runCount": 5,
31
+ "toolCount": 5
32
+ },
33
+ "completedAt": "2026-03-20T09:34:00.000Z",
34
+ "summary": "Seeded dashboard ready with 4 agents, 5 tools, and 5 runs.",
35
+ "metadata": {
36
+ "output": {
37
+ "agentCount": 4,
38
+ "runCount": 5,
39
+ "toolCount": 5
40
+ }
41
+ }
42
+ },
43
+ {
44
+ "stepId": "proof-4",
45
+ "stepKey": "create-agent",
46
+ "runId": "proof-1",
47
+ "mode": "code-execution",
48
+ "actionClass": "code-exec-mutate",
49
+ "verdict": "assist",
50
+ "requiresApproval": true,
51
+ "status": "completed",
52
+ "startedAt": "2026-03-20T09:35:00.000Z",
53
+ "output": {
54
+ "agentId": "agent-meetup-1",
55
+ "status": "DRAFT"
56
+ },
57
+ "completedAt": "2026-03-20T09:37:00.000Z",
58
+ "summary": "Created Paris Meetup Demo Agent as agent-meetup-1.",
59
+ "metadata": {
60
+ "output": {
61
+ "agentId": "agent-meetup-1",
62
+ "status": "DRAFT"
63
+ }
64
+ }
65
+ },
66
+ {
67
+ "stepId": "proof-6",
68
+ "stepKey": "activate-agent",
69
+ "runId": "proof-1",
70
+ "mode": "code-execution",
71
+ "actionClass": "code-exec-mutate",
72
+ "verdict": "assist",
73
+ "requiresApproval": true,
74
+ "status": "completed",
75
+ "startedAt": "2026-03-20T09:38:00.000Z",
76
+ "output": {
77
+ "agentId": "agent-meetup-1",
78
+ "status": "ACTIVE"
79
+ },
80
+ "completedAt": "2026-03-20T09:40:00.000Z",
81
+ "summary": "Activated Paris Meetup Demo Agent.",
82
+ "metadata": {
83
+ "output": {
84
+ "agentId": "agent-meetup-1",
85
+ "status": "ACTIVE"
86
+ }
87
+ }
88
+ },
89
+ {
90
+ "stepId": "proof-8",
91
+ "stepKey": "execute-agent",
92
+ "runId": "proof-1",
93
+ "mode": "code-execution",
94
+ "actionClass": "code-exec-mutate",
95
+ "verdict": "assist",
96
+ "requiresApproval": true,
97
+ "status": "completed",
98
+ "startedAt": "2026-03-20T09:41:00.000Z",
99
+ "output": {
100
+ "runId": "run-meetup-1",
101
+ "status": "COMPLETED",
102
+ "totalTokens": 1028
103
+ },
104
+ "completedAt": "2026-03-20T09:43:00.000Z",
105
+ "summary": "Executed Paris Meetup Demo Agent and completed run-meetup-1.",
106
+ "metadata": {
107
+ "output": {
108
+ "runId": "run-meetup-1",
109
+ "status": "COMPLETED",
110
+ "totalTokens": 1028
111
+ }
112
+ }
113
+ },
114
+ {
115
+ "stepId": "proof-10",
116
+ "stepKey": "inspect-dashboard",
117
+ "runId": "proof-1",
118
+ "mode": "code-execution",
119
+ "actionClass": "code-exec-read",
120
+ "verdict": "autonomous",
121
+ "requiresApproval": false,
122
+ "status": "completed",
123
+ "startedAt": "2026-03-20T09:44:00.000Z",
124
+ "output": {
125
+ "agentCount": 5,
126
+ "runCount": 6,
127
+ "toolCount": 5,
128
+ "latestAgentName": "Paris Meetup Demo Agent",
129
+ "latestRunId": "run-meetup-1",
130
+ "successRate": 0.6666666666666666
131
+ },
132
+ "completedAt": "2026-03-20T09:46:00.000Z",
133
+ "summary": "Paris Meetup Demo Agent is visible with 5 agents and 6 runs.",
134
+ "metadata": {
135
+ "output": {
136
+ "agentCount": 5,
137
+ "runCount": 6,
138
+ "toolCount": 5,
139
+ "latestAgentName": "Paris Meetup Demo Agent",
140
+ "latestRunId": "run-meetup-1",
141
+ "successRate": 0.6666666666666666
142
+ }
143
+ }
144
+ }
145
+ ],
146
+ "createdAt": "2026-03-20T09:30:00.000Z",
147
+ "updatedAt": "2026-03-20T09:47:00.000Z",
148
+ "evidenceCount": 5
149
+ },
150
+ "assertions": [
151
+ {
152
+ "assertionKey": "captured-step-summaries",
153
+ "status": "passed"
154
+ },
155
+ {
156
+ "assertionKey": "execution-completed",
157
+ "status": "passed"
158
+ },
159
+ {
160
+ "assertionKey": "final-summary-mentions-meetup-agent",
161
+ "status": "passed"
162
+ },
163
+ {
164
+ "assertionKey": "final-dashboard-shape",
165
+ "status": "passed"
166
+ }
167
+ ],
168
+ "artifacts": [
169
+ {
170
+ "artifactId": "proof-3",
171
+ "kind": "step-summary",
172
+ "runId": "proof-1",
173
+ "stepId": "proof-2",
174
+ "uri": "artifact://proof-3",
175
+ "hash": "815b21629e7e8a82376bd9c47e49192f9c4d5ff3b81bfd23d149b2922834b802",
176
+ "summary": "Seeded dashboard agents=4 tools=5 runs=5",
177
+ "createdAt": "2026-03-20T09:33:00.000Z"
178
+ },
179
+ {
180
+ "artifactId": "proof-5",
181
+ "kind": "step-summary",
182
+ "runId": "proof-1",
183
+ "stepId": "proof-4",
184
+ "uri": "artifact://proof-5",
185
+ "hash": "6deb2379988765661f26baaddaf5d3dd8d6115097c3f318f257b2f0fd71b8041",
186
+ "summary": "Created Paris Meetup Demo Agent (agent-meetup-1)",
187
+ "createdAt": "2026-03-20T09:36:00.000Z"
188
+ },
189
+ {
190
+ "artifactId": "proof-7",
191
+ "kind": "step-summary",
192
+ "runId": "proof-1",
193
+ "stepId": "proof-6",
194
+ "uri": "artifact://proof-7",
195
+ "hash": "eedef831df5bd02593572bcd979efbf9155d3aef4b6bba3bb4b5444ba6f59f6a",
196
+ "summary": "Activated Paris Meetup Demo Agent",
197
+ "createdAt": "2026-03-20T09:39:00.000Z"
198
+ },
199
+ {
200
+ "artifactId": "proof-9",
201
+ "kind": "step-summary",
202
+ "runId": "proof-1",
203
+ "stepId": "proof-8",
204
+ "uri": "artifact://proof-9",
205
+ "hash": "6939940cd8a2219f6387ea2fb1341b33aee5ab2c2b11f6e4755f157c37afa572",
206
+ "summary": "Completed run-meetup-1 for Paris Meetup Demo Agent",
207
+ "createdAt": "2026-03-20T09:42:00.000Z"
208
+ },
209
+ {
210
+ "artifactId": "proof-11",
211
+ "kind": "step-summary",
212
+ "runId": "proof-1",
213
+ "stepId": "proof-10",
214
+ "uri": "artifact://proof-11",
215
+ "hash": "d62d67ef87eb4dc831ab2bb7cd4ab30bd02b88e832c22f338d89ecdfe425db06",
216
+ "summary": "Final dashboard agents=5 runs=6",
217
+ "createdAt": "2026-03-20T09:45:00.000Z"
218
+ }
219
+ ]
220
+ }
@@ -1,8 +1,25 @@
1
1
  /**
2
2
  * Mock handlers for Agent contracts.
3
3
  */
4
+
4
5
  import { MOCK_AGENTS } from '../shared/mock-agents';
5
6
  import { MOCK_TOOLS } from '../shared/mock-tools';
7
+ import {
8
+ CreateAgentCommand,
9
+ GetAgentQuery,
10
+ ListAgentsQuery,
11
+ UpdateAgentCommand,
12
+ } from './agent.operation';
13
+
14
+ const AGENT_HANDLER_CONTRACTS = [
15
+ CreateAgentCommand,
16
+ GetAgentQuery,
17
+ ListAgentsQuery,
18
+ UpdateAgentCommand,
19
+ ] as const;
20
+ void AGENT_HANDLER_CONTRACTS;
21
+
22
+ let nextMockAgentId = MOCK_AGENTS.length + 1;
6
23
 
7
24
  export interface ListAgentsInput {
8
25
  organizationId: string;
@@ -152,7 +169,7 @@ export async function mockCreateAgentHandler(input: {
152
169
  );
153
170
  if (exists) throw new Error('SLUG_EXISTS');
154
171
  return {
155
- id: `agent-${Date.now()}`,
172
+ id: `agent-${nextMockAgentId++}`,
156
173
  name: input.name,
157
174
  slug: input.slug,
158
175
  status: 'DRAFT' as const,
@@ -5,6 +5,7 @@
5
5
  */
6
6
  import type { FeatureModuleSpec } from '@contractspec/lib.contracts-spec';
7
7
  import { defineFeature } from '@contractspec/lib.contracts-spec';
8
+ import { AgentVisualizationRefs } from './visualizations';
8
9
 
9
10
  /**
10
11
  * Agent Console feature module that bundles all agent, tool, and run
@@ -135,6 +136,8 @@ export const AgentConsoleFeature: FeatureModuleSpec = defineFeature({
135
136
  },
136
137
  ],
137
138
 
139
+ visualizations: AgentVisualizationRefs,
140
+
138
141
  // Capability requirements
139
142
  capabilities: {
140
143
  requires: [
@@ -30,19 +30,21 @@ const agentConsoleDocBlocks: DocBlock[] = [
30
30
  visibility: 'public',
31
31
  route: '/docs/examples/agent-console/usage',
32
32
  tags: ['ai', 'agents', 'usage'],
33
- body: `## Setup
34
- 1) Seed (if available) or create tools and agents; define run configs.
35
- 2) Configure Notifications for run completion/failure; Audit for changes.
33
+ body: `## Canonical walkthrough
34
+ 1) Open the default sandbox route at \`/sandbox\` or \`/sandbox?template=agent-console\`.
35
+ 2) Inspect seeded agents, tools, runs, and metrics from the deterministic demo runtime.
36
+ 3) Create an agent, activate it, execute a run, and confirm the metrics update.
37
+ 4) Generate or inspect the replay proof at \`packages/examples/agent-console/proofs/agent-console-meetup.replay.json\`.
36
38
 
37
39
  ## Extend & regenerate
38
- 1) Adjust tool schemas (inputs/outputs), agent configs, run metrics in spec.
40
+ 1) Adjust tool schemas (inputs/outputs), agent configs, and run metrics in spec.
39
41
  2) Regenerate to sync UI/API/events/logs; mark PII paths for run payloads.
40
- 3) Use Feature Flags to gate risky tools or execution policies.
42
+ 3) Keep the demo runtime deterministic unless you are explicitly validating live providers.
41
43
 
42
44
  ## Guardrails
43
45
  - Emit events for run lifecycle; store logs with redaction where needed.
44
46
  - Enforce tool input validation; avoid unsafe arbitrary code exec in handlers.
45
- - Keep tenant/user scoping explicit for ops data.`,
47
+ - Keep tenant/user scoping explicit for ops data and keep meetup demos offline-safe by default.`,
46
48
  },
47
49
  {
48
50
  id: 'docs.examples.agent-console.reference',
@@ -63,11 +65,12 @@ const agentConsoleDocBlocks: DocBlock[] = [
63
65
  - tool.created, agent.created, run.started/completed/failed, tool.invoked.
64
66
 
65
67
  ## Presentations
66
- - Tool registry, agent list/detail, run list/detail, metrics dashboards.
68
+ - Tool registry, agent list/detail, run list/detail, metrics dashboards, and a server-mode shared table for run history.
67
69
 
68
70
  ## Notes
69
71
  - Keep tool schemas explicit; enforce validation in spec.
70
- - Use Audit Trail for agent/run changes; Notifications for run outcomes.`,
72
+ - Use the seeded demo runtime for sandbox and markdown walkthroughs.
73
+ - Generate a replay bundle before demos or talks so the walkthrough has proof output ready.`,
71
74
  },
72
75
  {
73
76
  id: 'docs.examples.agent-console.constraints',
@@ -0,0 +1,75 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import { AgentConsoleFeature } from './agent.feature';
3
+ import example from './example';
4
+ import {
5
+ AGENT_CONSOLE_MEETUP_PROOF_SCENARIO,
6
+ AgentConsoleMeetupProofSuite,
7
+ } from './proof';
8
+ import {
9
+ AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
10
+ AGENT_CONSOLE_DEMO_PROJECT_ID,
11
+ createAgentConsoleDemoHandlers,
12
+ } from './shared';
13
+
14
+ describe('@contractspec/example.agent-console', () => {
15
+ test('publishes meetup-ready example metadata', () => {
16
+ expect(example.meta.key).toBe('agent-console');
17
+ expect(example.entrypoints.packageName).toBe(
18
+ '@contractspec/example.agent-console'
19
+ );
20
+ expect(example.surfaces.templates).toBe(true);
21
+ expect(example.surfaces.sandbox?.enabled).toBe(true);
22
+ expect(AgentConsoleFeature.meta.key).toBe(example.meta.key);
23
+ });
24
+
25
+ test('exports the canonical harness scenario and suite', () => {
26
+ expect(AGENT_CONSOLE_MEETUP_PROOF_SCENARIO.meta.key).toBe(
27
+ 'agent-console.meetup.proof'
28
+ );
29
+ expect(AgentConsoleMeetupProofSuite.scenarios).toEqual([
30
+ {
31
+ scenario: {
32
+ key: AGENT_CONSOLE_MEETUP_PROOF_SCENARIO.meta.key,
33
+ version: AGENT_CONSOLE_MEETUP_PROOF_SCENARIO.meta.version,
34
+ },
35
+ required: true,
36
+ weight: 1,
37
+ },
38
+ ]);
39
+ });
40
+
41
+ test('serves the seeded agent-console happy path', async () => {
42
+ const handlers = createAgentConsoleDemoHandlers({
43
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID,
44
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
45
+ now: (() => {
46
+ let tick = 0;
47
+ const base = Date.parse('2026-03-20T09:00:00.000Z');
48
+
49
+ return () => new Date(base + tick++ * 60_000);
50
+ })(),
51
+ });
52
+
53
+ const agents = await handlers.listAgents({
54
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID,
55
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
56
+ limit: 3,
57
+ });
58
+ expect(agents.total).toBeGreaterThan(0);
59
+
60
+ const activeAgent = agents.items.find((agent) => agent.status === 'ACTIVE');
61
+ expect(activeAgent).toBeDefined();
62
+
63
+ const run = await handlers.executeAgent({
64
+ agentId: activeAgent!.id,
65
+ message: 'Summarize the current autonomous agent status.',
66
+ context: {
67
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID,
68
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
69
+ },
70
+ });
71
+ expect(run.status).toBe('COMPLETED');
72
+ expect(run.output).toContain(activeAgent!.name);
73
+ expect(run.totalTokens).toBeGreaterThan(0);
74
+ });
75
+ });
package/src/example.ts CHANGED
@@ -9,7 +9,7 @@ const example = defineExample({
9
9
  'AI agent ops console: tools, agents, runs, logs, and metrics (spec-first, regenerable).',
10
10
  kind: 'template',
11
11
  visibility: 'public',
12
- stability: 'experimental',
12
+ stability: 'beta',
13
13
  owners: ['@platform.core'],
14
14
  tags: ['ai', 'agents', 'tools', 'orchestration'],
15
15
  },
@@ -21,8 +21,7 @@ const example = defineExample({
21
21
  },
22
22
  entrypoints: {
23
23
  packageName: '@contractspec/example.agent-console',
24
- feature: './feature',
25
- contracts: './contracts',
24
+ feature: './agent.feature',
26
25
  presentations: './presentations',
27
26
  handlers: './handlers',
28
27
  docs: './docs',
@@ -3,10 +3,34 @@
3
3
  *
4
4
  * Database-backed handlers for agent management and runs.
5
5
  */
6
+
6
7
  import type { DatabasePort } from '@contractspec/lib.runtime-sandbox';
7
8
  import { web } from '@contractspec/lib.runtime-sandbox';
9
+ import {
10
+ CreateAgentCommand,
11
+ GetAgentQuery,
12
+ ListAgentsQuery,
13
+ UpdateAgentCommand,
14
+ } from '../agent/agent.operation';
15
+ import {
16
+ ExecuteAgentCommand,
17
+ GetRunMetricsQuery,
18
+ ListRunsQuery,
19
+ } from '../run/run.operation';
20
+ import { ListToolsQuery } from '../tool/tool.operation';
8
21
 
9
22
  const { generateId } = web;
23
+ const RUNTIME_AGENT_HANDLER_CONTRACTS = [
24
+ CreateAgentCommand,
25
+ GetAgentQuery,
26
+ ListAgentsQuery,
27
+ UpdateAgentCommand,
28
+ ExecuteAgentCommand,
29
+ ListToolsQuery,
30
+ ListRunsQuery,
31
+ GetRunMetricsQuery,
32
+ ] as const;
33
+ void RUNTIME_AGENT_HANDLER_CONTRACTS;
10
34
 
11
35
  // ============ Types ============
12
36
 
@@ -111,6 +135,14 @@ export interface ListRunsInput {
111
135
  organizationId?: string;
112
136
  agentId?: string;
113
137
  status?: Run['status'] | 'all';
138
+ sortBy?:
139
+ | 'queuedAt'
140
+ | 'totalTokens'
141
+ | 'durationMs'
142
+ | 'estimatedCostUsd'
143
+ | 'status'
144
+ | 'agentName';
145
+ sortDirection?: 'asc' | 'desc';
114
146
  limit?: number;
115
147
  offset?: number;
116
148
  }
@@ -190,6 +222,15 @@ interface RunRow extends Record<string, unknown> {
190
222
  completedAt: string | null;
191
223
  }
192
224
 
225
+ const RUN_SORT_COLUMNS = {
226
+ queuedAt: 'r.queuedAt',
227
+ totalTokens: 'r.totalTokens',
228
+ durationMs: 'r.durationMs',
229
+ estimatedCostUsd: 'r.estimatedCostUsd',
230
+ status: 'r.status',
231
+ agentName: 'a.name',
232
+ } as const;
233
+
193
234
  function rowToAgent(row: AgentRow): Agent {
194
235
  return {
195
236
  id: row.id,
@@ -459,7 +500,15 @@ export function createAgentHandlers(db: DatabasePort) {
459
500
  * List runs
460
501
  */
461
502
  async function listRuns(input: ListRunsInput): Promise<ListRunsOutput> {
462
- const { projectId, agentId, status, limit = 20, offset = 0 } = input;
503
+ const {
504
+ projectId,
505
+ agentId,
506
+ status,
507
+ sortBy,
508
+ sortDirection = 'desc',
509
+ limit = 20,
510
+ offset = 0,
511
+ } = input;
463
512
 
464
513
  let whereClause = 'WHERE r.projectId = ?';
465
514
  const params: (string | number)[] = [projectId];
@@ -481,6 +530,10 @@ export function createAgentHandlers(db: DatabasePort) {
481
530
  )
482
531
  ).rows as unknown as { count: number }[];
483
532
  const total = countResult[0]?.count ?? 0;
533
+ const sortColumn = sortBy
534
+ ? RUN_SORT_COLUMNS[sortBy]
535
+ : RUN_SORT_COLUMNS.queuedAt;
536
+ const direction = sortDirection === 'asc' ? 'ASC' : 'DESC';
484
537
 
485
538
  const rows = (
486
539
  await db.query(
@@ -488,7 +541,7 @@ export function createAgentHandlers(db: DatabasePort) {
488
541
  FROM agent_run r
489
542
  LEFT JOIN agent_definition a ON r.agentId = a.id
490
543
  ${whereClause}
491
- ORDER BY r.queuedAt DESC LIMIT ? OFFSET ?`,
544
+ ORDER BY ${sortColumn} ${direction}, r.queuedAt DESC LIMIT ? OFFSET ?`,
492
545
  [...params, limit, offset]
493
546
  )
494
547
  ).rows as unknown as (RunRow & { agentName: string })[];
@@ -1,6 +1,23 @@
1
1
  /**
2
2
  * Agent Console Handlers - re-exports from domain modules for backward compatibility.
3
3
  */
4
+ import {
5
+ CreateAgentCommand,
6
+ ListAgentsQuery,
7
+ UpdateAgentCommand,
8
+ } from '../agent/agent.operation';
9
+ import { ExecuteAgentCommand, ListRunsQuery } from '../run/run.operation';
10
+ import { ListToolsQuery } from '../tool/tool.operation';
11
+
12
+ const HANDLER_BARREL_CONTRACTS = [
13
+ CreateAgentCommand,
14
+ ListAgentsQuery,
15
+ UpdateAgentCommand,
16
+ ExecuteAgentCommand,
17
+ ListRunsQuery,
18
+ ListToolsQuery,
19
+ ] as const;
20
+ void HANDLER_BARREL_CONTRACTS;
4
21
 
5
22
  // Agent handlers and types
6
23
  export {
@@ -17,7 +34,7 @@ export {
17
34
  mockListRunsHandler,
18
35
  type RunSummary,
19
36
  } from '../run/run.handler';
20
-
37
+ export { createAgentConsoleDemoHandlers } from '../shared/demo-runtime';
21
38
  // Tool handlers and types
22
39
  export {
23
40
  mockCreateToolHandler,
@@ -25,6 +42,5 @@ export {
25
42
  mockListToolsHandler,
26
43
  type ToolSummary,
27
44
  } from '../tool/tool.handler';
28
-
29
45
  // Runtime handlers (PGLite)
30
46
  export * from './agent.handlers';
@@ -0,0 +1,77 @@
1
+ import { describe, expect, it } from 'bun:test';
2
+ import { mockCreateAgentHandler } from '../agent/agent.handler';
3
+ import { mockExecuteAgentHandler } from '../run/run.handler';
4
+ import {
5
+ mockCreateToolHandler,
6
+ mockTestToolHandler,
7
+ } from '../tool/tool.handler';
8
+
9
+ function numericSuffix(value: string): number {
10
+ const suffix = value.split('-').at(-1);
11
+ if (!suffix) {
12
+ throw new Error(`Missing numeric suffix in ${value}.`);
13
+ }
14
+ return Number.parseInt(suffix, 10);
15
+ }
16
+
17
+ describe('agent-console mock handlers', () => {
18
+ it('allocates monotonic mock agent and tool ids', async () => {
19
+ const createdAgentA = await mockCreateAgentHandler({
20
+ organizationId: 'demo-org',
21
+ name: 'Meetup Mock Agent A',
22
+ slug: 'meetup-mock-agent-a',
23
+ modelProvider: 'OPENAI',
24
+ modelName: 'gpt-5.4',
25
+ systemPrompt: 'Keep responses stable.',
26
+ });
27
+ const createdAgentB = await mockCreateAgentHandler({
28
+ organizationId: 'demo-org',
29
+ name: 'Meetup Mock Agent B',
30
+ slug: 'meetup-mock-agent-b',
31
+ modelProvider: 'OPENAI',
32
+ modelName: 'gpt-5.4',
33
+ systemPrompt: 'Keep responses stable.',
34
+ });
35
+ const createdToolA = await mockCreateToolHandler({
36
+ organizationId: 'demo-org',
37
+ name: 'Meetup Tool A',
38
+ slug: 'meetup-tool-a',
39
+ description: 'First deterministic tool.',
40
+ implementationType: 'function',
41
+ });
42
+ const createdToolB = await mockCreateToolHandler({
43
+ organizationId: 'demo-org',
44
+ name: 'Meetup Tool B',
45
+ slug: 'meetup-tool-b',
46
+ description: 'Second deterministic tool.',
47
+ implementationType: 'function',
48
+ });
49
+
50
+ expect(numericSuffix(createdAgentB.id)).toBe(
51
+ numericSuffix(createdAgentA.id) + 1
52
+ );
53
+ expect(numericSuffix(createdToolB.id)).toBe(
54
+ numericSuffix(createdToolA.id) + 1
55
+ );
56
+ });
57
+
58
+ it('allocates monotonic run ids and returns a stable tool test duration', async () => {
59
+ const firstRun = await mockExecuteAgentHandler({
60
+ agentId: 'agent-1',
61
+ input: { message: 'First run' },
62
+ });
63
+ const secondRun = await mockExecuteAgentHandler({
64
+ agentId: 'agent-1',
65
+ input: { message: 'Second run' },
66
+ });
67
+ const toolResult = await mockTestToolHandler({
68
+ toolId: 'tool-1',
69
+ testInput: { query: 'stable duration' },
70
+ });
71
+
72
+ expect(numericSuffix(secondRun.runId)).toBe(
73
+ numericSuffix(firstRun.runId) + 1
74
+ );
75
+ expect(toolResult.durationMs).toBe(100);
76
+ });
77
+ });
package/src/index.ts CHANGED
@@ -24,8 +24,10 @@ export {
24
24
  type AgentHandlers,
25
25
  createAgentHandlers,
26
26
  } from './handlers/agent.handlers';
27
+ export * from './proof';
27
28
  export * from './run';
28
29
  export * from './shared';
29
30
  export * from './tool';
30
31
  export * from './ui';
32
+ export * from './visualizations';
31
33
  import './docs';
@@ -0,0 +1,2 @@
1
+ export * from './meetup-proof.scenario';
2
+ export * from './meetup-proof.suite';