@contractspec/example.agent-console 3.7.6 → 3.8.2

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 (288) hide show
  1. package/.turbo/turbo-build.log +126 -105
  2. package/AGENTS.md +52 -31
  3. package/CHANGELOG.md +29 -0
  4. package/README.md +112 -83
  5. package/dist/agent/agent.event.js +1 -1
  6. package/dist/agent/agent.handler.d.ts +3 -0
  7. package/dist/agent/agent.handler.js +730 -1
  8. package/dist/agent/agent.operation.js +1 -1
  9. package/dist/agent/index.d.ts +5 -5
  10. package/dist/agent/index.js +74 -73
  11. package/dist/agent.feature.js +179 -0
  12. package/dist/browser/agent/agent.event.js +1 -1
  13. package/dist/browser/agent/agent.handler.js +730 -1
  14. package/dist/browser/agent/agent.operation.js +1 -1
  15. package/dist/browser/agent/index.js +74 -73
  16. package/dist/browser/agent.feature.js +179 -0
  17. package/dist/browser/docs/agent-console.docblock.js +11 -8
  18. package/dist/browser/docs/index.js +11 -8
  19. package/dist/browser/example.js +2 -3
  20. package/dist/browser/handlers/agent.handlers.js +1883 -2
  21. package/dist/browser/handlers/index.js +2142 -8
  22. package/dist/browser/index.js +4075 -3161
  23. package/dist/browser/presentations/index.js +51 -51
  24. package/dist/browser/run/index.js +380 -374
  25. package/dist/browser/run/run.event.js +2 -2
  26. package/dist/browser/run/run.handler.js +666 -1
  27. package/dist/browser/run/run.presentation.js +2 -2
  28. package/dist/browser/shared/index.js +293 -1
  29. package/dist/browser/shared/mock-runs.js +5 -0
  30. package/dist/browser/tool/index.js +161 -161
  31. package/dist/browser/tool/tool.event.js +1 -1
  32. package/dist/browser/tool/tool.handler.js +479 -3
  33. package/dist/browser/tool/tool.presentation.js +2 -2
  34. package/dist/browser/ui/AgentDashboard.js +1816 -931
  35. package/dist/browser/ui/AgentDashboard.visualizations.js +217 -0
  36. package/dist/browser/ui/AgentRunList.js +360 -128
  37. package/dist/browser/ui/AgentToolRegistry.js +9 -9
  38. package/dist/browser/ui/hooks/index.js +611 -161
  39. package/dist/browser/ui/hooks/useAgentList.js +1 -1
  40. package/dist/browser/ui/hooks/useAgentMutations.js +444 -9
  41. package/dist/browser/ui/hooks/useRunList.js +26 -11
  42. package/dist/browser/ui/hooks/useToolList.js +1 -1
  43. package/dist/browser/ui/index.js +2161 -1258
  44. package/dist/browser/ui/modals/AgentActionsModal.js +13 -13
  45. package/dist/browser/ui/modals/CreateAgentModal.js +15 -15
  46. package/dist/browser/ui/modals/index.js +297 -297
  47. package/dist/browser/ui/renderers/agent-list.markdown.js +14 -5
  48. package/dist/browser/ui/renderers/agent-list.renderer.js +7 -7
  49. package/dist/browser/ui/renderers/dashboard.markdown.js +207 -36
  50. package/dist/browser/ui/renderers/index.js +359 -163
  51. package/dist/browser/ui/renderers/run-list.markdown.js +9 -4
  52. package/dist/browser/ui/renderers/tool-registry.markdown.js +15 -4
  53. package/dist/browser/ui/views/AgentListView.js +7 -7
  54. package/dist/browser/ui/views/RunDataTable.js +326 -0
  55. package/dist/browser/ui/views/RunListView.js +360 -128
  56. package/dist/browser/ui/views/ToolRegistryView.js +9 -9
  57. package/dist/browser/ui/views/index.js +478 -246
  58. package/dist/browser/ui/views/run-data-table.columns.js +271 -0
  59. package/dist/browser/ui/views/run-list.shared.js +177 -0
  60. package/dist/browser/visualizations/catalog.js +134 -0
  61. package/dist/browser/visualizations/index.js +187 -0
  62. package/dist/browser/visualizations/selectors.js +181 -0
  63. package/dist/docs/agent-console.docblock.js +11 -8
  64. package/dist/docs/index.js +11 -8
  65. package/dist/example.js +2 -3
  66. package/dist/example.test.d.ts +1 -0
  67. package/dist/handlers/agent.handlers.d.ts +2 -0
  68. package/dist/handlers/agent.handlers.js +1883 -2
  69. package/dist/handlers/index.d.ts +2 -4
  70. package/dist/handlers/index.js +2142 -8
  71. package/dist/handlers/mock-handlers.test.d.ts +1 -0
  72. package/dist/index.d.ts +6 -4
  73. package/dist/index.js +4075 -3161
  74. package/dist/node/agent/agent.event.js +1 -1
  75. package/dist/node/agent/agent.handler.js +730 -1
  76. package/dist/node/agent/agent.operation.js +1 -1
  77. package/dist/node/agent/index.js +74 -73
  78. package/dist/node/agent.feature.js +179 -0
  79. package/dist/node/docs/agent-console.docblock.js +11 -8
  80. package/dist/node/docs/index.js +11 -8
  81. package/dist/node/example.js +2 -3
  82. package/dist/node/handlers/agent.handlers.js +1883 -2
  83. package/dist/node/handlers/index.js +2142 -8
  84. package/dist/node/index.js +4075 -3161
  85. package/dist/node/presentations/index.js +51 -51
  86. package/dist/node/run/index.js +380 -374
  87. package/dist/node/run/run.event.js +2 -2
  88. package/dist/node/run/run.handler.js +666 -1
  89. package/dist/node/run/run.presentation.js +2 -2
  90. package/dist/node/shared/index.js +293 -1
  91. package/dist/node/shared/mock-runs.js +5 -0
  92. package/dist/node/tool/index.js +161 -161
  93. package/dist/node/tool/tool.event.js +1 -1
  94. package/dist/node/tool/tool.handler.js +479 -3
  95. package/dist/node/tool/tool.presentation.js +2 -2
  96. package/dist/node/ui/AgentDashboard.js +1816 -931
  97. package/dist/node/ui/AgentDashboard.visualizations.js +217 -0
  98. package/dist/node/ui/AgentRunList.js +360 -128
  99. package/dist/node/ui/AgentToolRegistry.js +9 -9
  100. package/dist/node/ui/hooks/index.js +611 -161
  101. package/dist/node/ui/hooks/useAgentList.js +1 -1
  102. package/dist/node/ui/hooks/useAgentMutations.js +444 -9
  103. package/dist/node/ui/hooks/useRunList.js +26 -11
  104. package/dist/node/ui/hooks/useToolList.js +1 -1
  105. package/dist/node/ui/index.js +2161 -1258
  106. package/dist/node/ui/modals/AgentActionsModal.js +13 -13
  107. package/dist/node/ui/modals/CreateAgentModal.js +15 -15
  108. package/dist/node/ui/modals/index.js +297 -297
  109. package/dist/node/ui/renderers/agent-list.markdown.js +14 -5
  110. package/dist/node/ui/renderers/agent-list.renderer.js +7 -7
  111. package/dist/node/ui/renderers/dashboard.markdown.js +207 -36
  112. package/dist/node/ui/renderers/index.js +359 -163
  113. package/dist/node/ui/renderers/run-list.markdown.js +9 -4
  114. package/dist/node/ui/renderers/tool-registry.markdown.js +15 -4
  115. package/dist/node/ui/views/AgentListView.js +7 -7
  116. package/dist/node/ui/views/RunDataTable.js +326 -0
  117. package/dist/node/ui/views/RunListView.js +360 -128
  118. package/dist/node/ui/views/ToolRegistryView.js +9 -9
  119. package/dist/node/ui/views/index.js +478 -246
  120. package/dist/node/ui/views/run-data-table.columns.js +271 -0
  121. package/dist/node/ui/views/run-list.shared.js +177 -0
  122. package/dist/node/visualizations/catalog.js +134 -0
  123. package/dist/node/visualizations/index.js +187 -0
  124. package/dist/node/visualizations/selectors.js +181 -0
  125. package/dist/presentations/index.d.ts +3 -5
  126. package/dist/presentations/index.js +51 -51
  127. package/dist/proof/index.d.ts +2 -0
  128. package/dist/proof/meetup-proof.d.ts +10 -0
  129. package/dist/proof/meetup-proof.runtime.d.ts +22 -0
  130. package/dist/proof/meetup-proof.scenario.d.ts +2 -0
  131. package/dist/proof/meetup-proof.suite.d.ts +1 -0
  132. package/dist/proof/meetup-proof.test.d.ts +1 -0
  133. package/dist/run/index.d.ts +7 -7
  134. package/dist/run/index.js +380 -374
  135. package/dist/run/run.event.js +2 -2
  136. package/dist/run/run.handler.d.ts +7 -0
  137. package/dist/run/run.handler.js +666 -1
  138. package/dist/run/run.presentation.js +2 -2
  139. package/dist/shared/demo-dashboard-data.d.ts +16 -0
  140. package/dist/shared/demo-runtime-seed.d.ts +17 -0
  141. package/dist/shared/demo-runtime.d.ts +8 -0
  142. package/dist/shared/demo-runtime.test.d.ts +1 -0
  143. package/dist/shared/index.d.ts +4 -1
  144. package/dist/shared/index.js +293 -1
  145. package/dist/shared/mock-runs.d.ts +4 -0
  146. package/dist/shared/mock-runs.js +5 -0
  147. package/dist/tool/index.d.ts +7 -7
  148. package/dist/tool/index.js +161 -161
  149. package/dist/tool/tool.event.js +1 -1
  150. package/dist/tool/tool.handler.d.ts +3 -0
  151. package/dist/tool/tool.handler.js +479 -3
  152. package/dist/tool/tool.presentation.js +2 -2
  153. package/dist/ui/AgentDashboard.js +1816 -931
  154. package/dist/ui/AgentDashboard.sandbox.test.d.ts +1 -0
  155. package/dist/ui/AgentDashboard.visualizations.d.ts +4 -0
  156. package/dist/ui/AgentDashboard.visualizations.js +218 -0
  157. package/dist/ui/AgentRunList.js +360 -128
  158. package/dist/ui/AgentToolRegistry.js +9 -9
  159. package/dist/ui/hooks/index.d.ts +4 -4
  160. package/dist/ui/hooks/index.js +611 -161
  161. package/dist/ui/hooks/useAgentList.d.ts +5 -0
  162. package/dist/ui/hooks/useAgentList.js +1 -1
  163. package/dist/ui/hooks/useAgentMutations.d.ts +9 -2
  164. package/dist/ui/hooks/useAgentMutations.js +444 -9
  165. package/dist/ui/hooks/useRunList.d.ts +13 -2
  166. package/dist/ui/hooks/useRunList.js +26 -11
  167. package/dist/ui/hooks/useToolList.d.ts +5 -0
  168. package/dist/ui/hooks/useToolList.js +1 -1
  169. package/dist/ui/index.d.ts +3 -3
  170. package/dist/ui/index.js +2161 -1258
  171. package/dist/ui/modals/AgentActionsModal.js +13 -13
  172. package/dist/ui/modals/CreateAgentModal.js +15 -15
  173. package/dist/ui/modals/index.d.ts +1 -1
  174. package/dist/ui/modals/index.js +297 -297
  175. package/dist/ui/renderers/agent-list.markdown.d.ts +5 -0
  176. package/dist/ui/renderers/agent-list.markdown.js +14 -5
  177. package/dist/ui/renderers/agent-list.renderer.js +7 -7
  178. package/dist/ui/renderers/dashboard.markdown.d.ts +5 -0
  179. package/dist/ui/renderers/dashboard.markdown.js +207 -36
  180. package/dist/ui/renderers/index.d.ts +2 -2
  181. package/dist/ui/renderers/index.js +359 -163
  182. package/dist/ui/renderers/run-list.markdown.d.ts +5 -0
  183. package/dist/ui/renderers/run-list.markdown.js +9 -4
  184. package/dist/ui/renderers/tool-registry.markdown.d.ts +6 -1
  185. package/dist/ui/renderers/tool-registry.markdown.js +15 -4
  186. package/dist/ui/views/AgentListView.js +7 -7
  187. package/dist/ui/views/RunDataTable.d.ts +18 -0
  188. package/dist/ui/views/RunDataTable.js +327 -0
  189. package/dist/ui/views/RunListView.js +360 -128
  190. package/dist/ui/views/ToolRegistryView.js +9 -9
  191. package/dist/ui/views/index.js +478 -246
  192. package/dist/ui/views/run-data-table.columns.d.ts +3 -0
  193. package/dist/ui/views/run-data-table.columns.js +272 -0
  194. package/dist/ui/views/run-list.shared.d.ts +14 -0
  195. package/dist/ui/views/run-list.shared.js +178 -0
  196. package/dist/visualizations/catalog.d.ts +10 -0
  197. package/dist/visualizations/catalog.js +135 -0
  198. package/dist/visualizations/index.d.ts +2 -0
  199. package/dist/visualizations/index.js +188 -0
  200. package/dist/visualizations/selectors.d.ts +3 -0
  201. package/dist/visualizations/selectors.js +182 -0
  202. package/dist/visualizations/selectors.test.d.ts +1 -0
  203. package/package.json +114 -12
  204. package/proofs/agent-console-meetup.replay.json +220 -0
  205. package/src/agent/agent.entity.ts +111 -111
  206. package/src/agent/agent.enum.ts +12 -12
  207. package/src/agent/agent.event.ts +91 -91
  208. package/src/agent/agent.handler.ts +144 -127
  209. package/src/agent/agent.operation.ts +400 -400
  210. package/src/agent/agent.presentation.ts +62 -62
  211. package/src/agent/agent.schema.ts +175 -175
  212. package/src/agent/agent.test-spec.ts +48 -48
  213. package/src/agent/index.ts +46 -51
  214. package/src/agent.capability.ts +11 -11
  215. package/src/agent.feature.ts +134 -131
  216. package/src/docs/agent-console.docblock.ts +52 -49
  217. package/src/example.test.ts +75 -0
  218. package/src/example.ts +34 -35
  219. package/src/handlers/agent.handlers.ts +576 -522
  220. package/src/handlers/index.ts +30 -14
  221. package/src/handlers/mock-handlers.test.ts +77 -0
  222. package/src/index.ts +10 -9
  223. package/src/presentations/index.ts +11 -13
  224. package/src/proof/index.ts +2 -0
  225. package/src/proof/meetup-proof.runtime.ts +196 -0
  226. package/src/proof/meetup-proof.scenario.ts +99 -0
  227. package/src/proof/meetup-proof.suite.ts +29 -0
  228. package/src/proof/meetup-proof.test.ts +28 -0
  229. package/src/proof/meetup-proof.ts +130 -0
  230. package/src/run/index.ts +49 -54
  231. package/src/run/run.entity.ts +137 -137
  232. package/src/run/run.enum.ts +18 -18
  233. package/src/run/run.event.ts +174 -174
  234. package/src/run/run.handler.ts +113 -96
  235. package/src/run/run.operation.ts +474 -474
  236. package/src/run/run.presentation.ts +42 -42
  237. package/src/run/run.schema.ts +126 -126
  238. package/src/run/run.test-spec.ts +48 -48
  239. package/src/seeders/index.ts +21 -21
  240. package/src/shared/demo-dashboard-data.ts +58 -0
  241. package/src/shared/demo-runtime-seed.ts +139 -0
  242. package/src/shared/demo-runtime.test.ts +169 -0
  243. package/src/shared/demo-runtime.ts +260 -0
  244. package/src/shared/index.ts +12 -1
  245. package/src/shared/mock-agents.ts +76 -76
  246. package/src/shared/mock-runs.ts +107 -102
  247. package/src/shared/mock-tools.ts +140 -140
  248. package/src/shared/overlay-types.ts +23 -23
  249. package/src/tool/index.ts +39 -44
  250. package/src/tool/tool.entity.ts +73 -73
  251. package/src/tool/tool.enum.ts +13 -13
  252. package/src/tool/tool.event.ts +80 -80
  253. package/src/tool/tool.handler.ts +124 -107
  254. package/src/tool/tool.operation.ts +328 -328
  255. package/src/tool/tool.presentation.ts +43 -43
  256. package/src/tool/tool.schema.ts +106 -106
  257. package/src/tool/tool.test-spec.ts +48 -48
  258. package/src/ui/AgentDashboard.sandbox.test.tsx +312 -0
  259. package/src/ui/AgentDashboard.tsx +351 -348
  260. package/src/ui/AgentDashboard.visualizations.tsx +35 -0
  261. package/src/ui/hooks/index.ts +7 -7
  262. package/src/ui/hooks/useAgentList.ts +57 -56
  263. package/src/ui/hooks/useAgentMutations.ts +168 -159
  264. package/src/ui/hooks/useRunList.ts +90 -57
  265. package/src/ui/hooks/useToolList.ts +102 -101
  266. package/src/ui/index.ts +6 -9
  267. package/src/ui/modals/AgentActionsModal.tsx +262 -262
  268. package/src/ui/modals/CreateAgentModal.tsx +232 -232
  269. package/src/ui/modals/index.ts +1 -1
  270. package/src/ui/overlays/demo-overlays.ts +52 -52
  271. package/src/ui/renderers/agent-list.markdown.ts +81 -61
  272. package/src/ui/renderers/agent-list.renderer.tsx +14 -14
  273. package/src/ui/renderers/dashboard.markdown.ts +135 -139
  274. package/src/ui/renderers/index.ts +3 -4
  275. package/src/ui/renderers/run-list.markdown.ts +56 -47
  276. package/src/ui/renderers/tool-registry.markdown.ts +79 -66
  277. package/src/ui/views/AgentListView.tsx +90 -90
  278. package/src/ui/views/RunDataTable.tsx +74 -0
  279. package/src/ui/views/RunListView.tsx +84 -158
  280. package/src/ui/views/ToolRegistryView.tsx +113 -113
  281. package/src/ui/views/run-data-table.columns.tsx +102 -0
  282. package/src/ui/views/run-list.shared.tsx +139 -0
  283. package/src/visualizations/catalog.ts +132 -0
  284. package/src/visualizations/index.ts +2 -0
  285. package/src/visualizations/selectors.test.ts +12 -0
  286. package/src/visualizations/selectors.ts +70 -0
  287. package/tsconfig.json +7 -8
  288. package/tsdown.config.js +24 -3
@@ -1,7 +1,185 @@
1
1
  // @bun
2
+ // src/visualizations/catalog.ts
3
+ import {
4
+ defineVisualization,
5
+ VisualizationRegistry
6
+ } from "@contractspec/lib.contracts-spec/visualizations";
7
+ var RUN_LIST_REF = { key: "agent.run.list", version: "1.0.0" };
8
+ var META = {
9
+ version: "1.0.0",
10
+ domain: "ai-ops",
11
+ stability: "experimental",
12
+ owners: ["@example.agent-console"],
13
+ tags: ["agent-console", "visualization", "operations"]
14
+ };
15
+ var AgentRunStatusVisualization = defineVisualization({
16
+ meta: {
17
+ ...META,
18
+ key: "agent-console.visualization.run-status",
19
+ title: "Run Status Breakdown",
20
+ description: "Distribution of run outcomes across the current sample.",
21
+ goal: "Make operational success and failure mix visible at a glance.",
22
+ context: "Agent operations overview."
23
+ },
24
+ source: { primary: RUN_LIST_REF, resultPath: "data" },
25
+ visualization: {
26
+ kind: "pie",
27
+ nameDimension: "status",
28
+ valueMeasure: "runs",
29
+ dimensions: [
30
+ { key: "status", label: "Status", dataPath: "status", type: "category" }
31
+ ],
32
+ measures: [
33
+ { key: "runs", label: "Runs", dataPath: "runs", format: "number" }
34
+ ],
35
+ table: { caption: "Run counts by status." }
36
+ }
37
+ });
38
+ var AgentRunActivityVisualization = defineVisualization({
39
+ meta: {
40
+ ...META,
41
+ key: "agent-console.visualization.run-activity",
42
+ title: "Recent Run Activity",
43
+ description: "Daily run volume across the current sample.",
44
+ goal: "Show whether agent activity is rising or slowing down.",
45
+ context: "Operations trend monitoring."
46
+ },
47
+ source: { primary: RUN_LIST_REF, resultPath: "data" },
48
+ visualization: {
49
+ kind: "cartesian",
50
+ variant: "line",
51
+ xDimension: "day",
52
+ yMeasures: ["runs"],
53
+ dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
54
+ measures: [
55
+ {
56
+ key: "runs",
57
+ label: "Runs",
58
+ dataPath: "runs",
59
+ format: "number",
60
+ color: "#0f766e"
61
+ }
62
+ ],
63
+ table: { caption: "Daily run counts." }
64
+ }
65
+ });
66
+ var AgentRunEfficiencyVisualization = defineVisualization({
67
+ meta: {
68
+ ...META,
69
+ key: "agent-console.visualization.run-efficiency",
70
+ title: "Duration vs Tokens",
71
+ description: "Scatter chart comparing token consumption and runtime.",
72
+ goal: "Reveal outlier runs that are slow relative to their token usage.",
73
+ context: "Operational performance diagnostics."
74
+ },
75
+ source: { primary: RUN_LIST_REF, resultPath: "data" },
76
+ visualization: {
77
+ kind: "cartesian",
78
+ variant: "scatter",
79
+ xDimension: "totalTokens",
80
+ yMeasures: ["durationMs"],
81
+ dimensions: [
82
+ {
83
+ key: "totalTokens",
84
+ label: "Total Tokens",
85
+ dataPath: "totalTokens",
86
+ type: "number"
87
+ }
88
+ ],
89
+ measures: [
90
+ {
91
+ key: "durationMs",
92
+ label: "Duration",
93
+ dataPath: "durationMs",
94
+ format: "duration",
95
+ color: "#7c3aed"
96
+ },
97
+ {
98
+ key: "estimatedCostUsd",
99
+ label: "Cost",
100
+ dataPath: "estimatedCostUsd",
101
+ format: "currency"
102
+ }
103
+ ],
104
+ series: [
105
+ {
106
+ key: "runs",
107
+ label: "Runs",
108
+ measure: "durationMs",
109
+ type: "scatter",
110
+ color: "#7c3aed"
111
+ }
112
+ ],
113
+ table: { caption: "Run duration versus token usage." }
114
+ }
115
+ });
116
+ var AgentVisualizationSpecs = [
117
+ AgentRunStatusVisualization,
118
+ AgentRunActivityVisualization,
119
+ AgentRunEfficiencyVisualization
120
+ ];
121
+ var AgentVisualizationRegistry = new VisualizationRegistry([
122
+ ...AgentVisualizationSpecs
123
+ ]);
124
+ var AgentVisualizationRefs = AgentVisualizationSpecs.map((spec) => ({
125
+ key: spec.meta.key,
126
+ version: spec.meta.version
127
+ }));
128
+
129
+ // src/visualizations/selectors.ts
130
+ function dayKey(value) {
131
+ if (!value)
132
+ return "unknown";
133
+ return value.toISOString().slice(0, 10);
134
+ }
135
+ function createAgentVisualizationItems(runs) {
136
+ const statusCounts = new Map;
137
+ const activityCounts = new Map;
138
+ for (const run of runs) {
139
+ statusCounts.set(run.status, (statusCounts.get(run.status) ?? 0) + 1);
140
+ activityCounts.set(dayKey(run.startedAt ?? run.queuedAt), (activityCounts.get(dayKey(run.startedAt ?? run.queuedAt)) ?? 0) + 1);
141
+ }
142
+ return [
143
+ {
144
+ key: "run-status",
145
+ spec: AgentRunStatusVisualization,
146
+ data: {
147
+ data: Array.from(statusCounts.entries()).map(([status, count]) => ({
148
+ status,
149
+ runs: count
150
+ }))
151
+ },
152
+ title: "Run Status Breakdown",
153
+ description: "Completed, failed, running, and cancelled runs in the sample.",
154
+ height: 260
155
+ },
156
+ {
157
+ key: "run-activity",
158
+ spec: AgentRunActivityVisualization,
159
+ data: {
160
+ data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, runs: count }))
161
+ },
162
+ title: "Recent Run Activity",
163
+ description: "Daily run volume derived from run start times."
164
+ },
165
+ {
166
+ key: "run-efficiency",
167
+ spec: AgentRunEfficiencyVisualization,
168
+ data: {
169
+ data: runs.filter((run) => typeof run.durationMs === "number").map((run) => ({
170
+ totalTokens: run.totalTokens,
171
+ durationMs: run.durationMs ?? 0,
172
+ estimatedCostUsd: run.estimatedCostUsd
173
+ }))
174
+ },
175
+ title: "Duration vs Tokens",
176
+ description: "Operational scatter plot for spotting inefficient runs."
177
+ }
178
+ ];
179
+ }
2
180
  // src/ui/hooks/useAgentList.ts
3
- import { useCallback, useEffect, useMemo, useState } from "react";
4
181
  import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
182
+ import { useCallback, useEffect, useMemo, useState } from "react";
5
183
  function useAgentList(options = {}) {
6
184
  const { handlers, projectId } = useTemplateRuntime();
7
185
  const { agent } = handlers;
@@ -52,16 +230,78 @@ function useAgentList(options = {}) {
52
230
  };
53
231
  }
54
232
 
233
+ // src/ui/renderers/agent-list.markdown.ts
234
+ import {
235
+ AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
236
+ AGENT_CONSOLE_DEMO_PROJECT_ID,
237
+ createAgentConsoleDemoHandlers
238
+ } from "@contractspec/example.agent-console/shared";
239
+ var agentListMarkdownRenderer = {
240
+ target: "markdown",
241
+ render: async (desc, ctx) => {
242
+ if (desc.source.type !== "component" || desc.source.componentKey !== "AgentListView") {
243
+ throw new Error("agentListMarkdownRenderer: not AgentListView");
244
+ }
245
+ const data = Array.isArray(ctx?.data) ? {
246
+ items: ctx.data,
247
+ total: ctx.data.length,
248
+ hasMore: false
249
+ } : await createAgentConsoleDemoHandlers({
250
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID
251
+ }).listAgents({
252
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID,
253
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
254
+ limit: 50,
255
+ offset: 0
256
+ });
257
+ const lines = [
258
+ `# ${desc.meta.description ?? "Agent List"}`,
259
+ "",
260
+ `> ${desc.meta.key} v${desc.meta.version}`,
261
+ "",
262
+ `**Total Agents:** ${data.total}`,
263
+ "",
264
+ "## Agents",
265
+ ""
266
+ ];
267
+ const byStatus = {};
268
+ for (const agent of data.items) {
269
+ const status = agent.status;
270
+ if (byStatus[status]) {
271
+ byStatus[status].push(agent);
272
+ } else {
273
+ byStatus[status] = [agent];
274
+ }
275
+ }
276
+ for (const [status, agents] of Object.entries(byStatus)) {
277
+ lines.push(`### ${status} (${agents.length})`);
278
+ lines.push("");
279
+ for (const agent of agents) {
280
+ lines.push(`- **${agent.name}** (${agent.modelProvider}/${agent.modelName})`);
281
+ if (agent.description) {
282
+ lines.push(` > ${agent.description}`);
283
+ }
284
+ }
285
+ lines.push("");
286
+ }
287
+ return {
288
+ mimeType: "text/markdown",
289
+ body: lines.join(`
290
+ `)
291
+ };
292
+ }
293
+ };
294
+
55
295
  // src/ui/views/AgentListView.tsx
56
296
  import {
57
297
  Button,
58
- StatCard,
59
- StatCardGroup,
298
+ EmptyState,
60
299
  EntityCard,
61
- StatusChip,
62
- LoaderBlock,
63
300
  ErrorState,
64
- EmptyState
301
+ LoaderBlock,
302
+ StatCard,
303
+ StatCardGroup,
304
+ StatusChip
65
305
  } from "@contractspec/lib.design-system";
66
306
  import { jsxDEV } from "react/jsx-dev-runtime";
67
307
  "use client";
@@ -126,7 +366,7 @@ function AgentListView() {
126
366
  className: "flex items-center justify-between",
127
367
  children: [
128
368
  /* @__PURE__ */ jsxDEV("h3", {
129
- className: "text-lg font-semibold",
369
+ className: "font-semibold text-lg",
130
370
  children: "Agents"
131
371
  }, undefined, false, undefined, this),
132
372
  /* @__PURE__ */ jsxDEV(Button, {
@@ -177,50 +417,105 @@ var agentListReactRenderer = {
177
417
  }
178
418
  };
179
419
 
180
- // src/ui/renderers/agent-list.markdown.ts
420
+ // src/ui/renderers/dashboard.markdown.ts
181
421
  import {
182
- mockListAgentsHandler
183
- } from "@contractspec/example.agent-console/handlers";
184
- var agentListMarkdownRenderer = {
422
+ getFallbackAgentConsoleDashboardData
423
+ } from "@contractspec/example.agent-console/shared";
424
+ function formatDuration(ms) {
425
+ if (ms < 1000)
426
+ return `${ms}ms`;
427
+ if (ms < 60000)
428
+ return `${(ms / 1000).toFixed(1)}s`;
429
+ return `${(ms / 60000).toFixed(1)}m`;
430
+ }
431
+ var agentDashboardMarkdownRenderer = {
185
432
  target: "markdown",
186
- render: async (desc) => {
187
- if (desc.source.type !== "component" || desc.source.componentKey !== "AgentListView") {
188
- throw new Error("agentListMarkdownRenderer: not AgentListView");
433
+ render: async (desc, ctx) => {
434
+ if (desc.source.type !== "component" || desc.source.componentKey !== "AgentConsoleDashboard") {
435
+ throw new Error("agentDashboardMarkdownRenderer: not AgentConsoleDashboard");
189
436
  }
190
- const data = await mockListAgentsHandler({
191
- organizationId: "demo-org",
192
- limit: 50,
193
- offset: 0
194
- });
437
+ const data = ctx?.data ?? await getFallbackAgentConsoleDashboardData();
438
+ const activeAgents = data.agents.filter((a) => a.status === "ACTIVE").length;
439
+ const completedRuns = data.runs.filter((r) => r.status === "COMPLETED").length;
440
+ const failedRuns = data.runs.filter((r) => r.status === "FAILED").length;
441
+ const totalTokens = data.runs.reduce((sum, r) => sum + (r.totalTokens ?? 0), 0);
442
+ const totalCost = data.runs.reduce((sum, r) => sum + (r.estimatedCostUsd ?? 0), 0);
443
+ const activeTools = data.tools.filter((t) => t.status === "ACTIVE").length;
444
+ const visualizationItems = createAgentVisualizationItems(data.runs);
195
445
  const lines = [
196
- `# ${desc.meta.description ?? "Agent List"}`,
446
+ "# Agent Console Dashboard",
197
447
  "",
198
- `> ${desc.meta.key} v${desc.meta.version}`,
448
+ "> AI agent operations overview",
199
449
  "",
200
- `**Total Agents:** ${data.total}`,
450
+ "## Summary",
451
+ "",
452
+ "| Metric | Value |",
453
+ "|--------|-------|",
454
+ `| Total Agents | ${data.summary.totalAgents} |`,
455
+ `| Active Agents | ${activeAgents} |`,
456
+ `| Total Runs | ${data.summary.totalRuns} |`,
457
+ `| Completed Runs | ${completedRuns} |`,
458
+ `| Failed Runs | ${failedRuns} |`,
459
+ `| Total Tokens | ${totalTokens.toLocaleString()} |`,
460
+ `| Total Cost | $${totalCost.toFixed(4)} |`,
461
+ `| Total Tools | ${data.summary.totalTools} |`,
462
+ `| Active Tools | ${activeTools} |`,
201
463
  "",
202
464
  "## Agents",
203
465
  ""
204
466
  ];
205
- const byStatus = {};
206
- for (const agent of data.items) {
207
- const status = agent.status;
208
- if (byStatus[status]) {
209
- byStatus[status].push(agent);
210
- } else {
211
- byStatus[status] = [agent];
467
+ if (data.agents.length === 0) {
468
+ lines.push("_No agents configured._");
469
+ } else {
470
+ lines.push("| Agent | Model | Status | Description |");
471
+ lines.push("|-------|-------|--------|-------------|");
472
+ for (const agent of data.agents.slice(0, 5)) {
473
+ lines.push(`| ${agent.name} | ${agent.modelProvider}/${agent.modelName} | ${agent.status} | ${agent.description ?? "-"} |`);
474
+ }
475
+ if (data.agents.length > 5) {
476
+ lines.push(`| ... | ... | ... | _${data.summary.totalAgents - 5} more_ |`);
212
477
  }
213
478
  }
214
- for (const [status, agents] of Object.entries(byStatus)) {
215
- lines.push(`### ${status} (${agents.length})`);
216
- lines.push("");
217
- for (const agent of agents) {
218
- lines.push(`- **${agent.name}** (${agent.modelProvider}/${agent.modelName})`);
219
- if (agent.description) {
220
- lines.push(` > ${agent.description}`);
221
- }
479
+ lines.push("");
480
+ lines.push("## Recent Runs");
481
+ lines.push("");
482
+ if (data.runs.length === 0) {
483
+ lines.push("_No runs yet._");
484
+ } else {
485
+ lines.push("| Run ID | Agent | Status | Duration | Tokens | Cost |");
486
+ lines.push("|--------|-------|--------|----------|--------|------|");
487
+ for (const run of data.runs.slice(0, 5)) {
488
+ lines.push(`| ${run.id.slice(-8)} | ${run.agentName} | ${run.status} | ${run.durationMs ? formatDuration(run.durationMs) : "-"} | ${run.totalTokens ?? 0} | $${(run.estimatedCostUsd ?? 0).toFixed(4)} |`);
489
+ }
490
+ if (data.runs.length > 5) {
491
+ lines.push(`| ... | ... | ... | ... | ... | _${data.summary.totalRuns - 5} more_ |`);
492
+ }
493
+ }
494
+ lines.push("");
495
+ lines.push("## Visualization Overview");
496
+ lines.push("");
497
+ for (const item of visualizationItems) {
498
+ lines.push(`- **${item.title}** via \`${item.spec.meta.key}\``);
499
+ }
500
+ lines.push("");
501
+ lines.push("## Tools");
502
+ lines.push("");
503
+ const toolsByCategory = {};
504
+ for (const tool of data.tools) {
505
+ const cat = tool.category;
506
+ if (!toolsByCategory[cat])
507
+ toolsByCategory[cat] = [];
508
+ toolsByCategory[cat].push(tool);
509
+ }
510
+ if (Object.keys(toolsByCategory).length === 0) {
511
+ lines.push("_No tools registered._");
512
+ } else {
513
+ lines.push("| Category | Tools | Active |");
514
+ lines.push("|----------|-------|--------|");
515
+ for (const [category, tools] of Object.entries(toolsByCategory).sort()) {
516
+ const active = tools.filter((t) => t.status === "ACTIVE").length;
517
+ lines.push(`| ${category} | ${tools.length} | ${active} |`);
222
518
  }
223
- lines.push("");
224
519
  }
225
520
  return {
226
521
  mimeType: "text/markdown",
@@ -231,8 +526,11 @@ var agentListMarkdownRenderer = {
231
526
  };
232
527
 
233
528
  // src/ui/renderers/run-list.markdown.ts
234
- import { mockListRunsHandler } from "@contractspec/example.agent-console/handlers";
235
- function formatDuration(ms) {
529
+ import {
530
+ AGENT_CONSOLE_DEMO_PROJECT_ID as AGENT_CONSOLE_DEMO_PROJECT_ID2,
531
+ createAgentConsoleDemoHandlers as createAgentConsoleDemoHandlers2
532
+ } from "@contractspec/example.agent-console/shared";
533
+ function formatDuration2(ms) {
236
534
  if (ms < 1000)
237
535
  return `${ms}ms`;
238
536
  if (ms < 60000)
@@ -241,12 +539,14 @@ function formatDuration(ms) {
241
539
  }
242
540
  var runListMarkdownRenderer = {
243
541
  target: "markdown",
244
- render: async (desc) => {
542
+ render: async (desc, ctx) => {
245
543
  if (desc.source.type !== "component" || desc.source.componentKey !== "RunListView") {
246
544
  throw new Error("runListMarkdownRenderer: not RunListView");
247
545
  }
248
- const data = await mockListRunsHandler({
249
- organizationId: "demo-org",
546
+ const data = Array.isArray(ctx?.data) ? { items: ctx.data, total: ctx.data.length, hasMore: false } : await createAgentConsoleDemoHandlers2({
547
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID2
548
+ }).listRuns({
549
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID2,
250
550
  limit: 20,
251
551
  offset: 0
252
552
  });
@@ -263,7 +563,7 @@ var runListMarkdownRenderer = {
263
563
  "| --- | --- | --- | --- | --- | --- |"
264
564
  ];
265
565
  for (const run of data.items.slice(0, 10)) {
266
- lines.push(`| ${run.id.slice(-8)} | ${run.agentName} | ${run.status} | ${run.durationMs ? formatDuration(run.durationMs) : "-"} | ${run.totalTokens} | $${run.estimatedCostUsd?.toFixed(4) ?? "-"} |`);
566
+ lines.push(`| ${run.id.slice(-8)} | ${run.agentName} | ${run.status} | ${run.durationMs ? formatDuration2(run.durationMs) : "-"} | ${run.totalTokens} | $${run.estimatedCostUsd?.toFixed(4) ?? "-"} |`);
267
567
  }
268
568
  return {
269
569
  mimeType: "text/markdown",
@@ -274,15 +574,26 @@ var runListMarkdownRenderer = {
274
574
  };
275
575
 
276
576
  // src/ui/renderers/tool-registry.markdown.ts
277
- import { mockListToolsHandler } from "@contractspec/example.agent-console/handlers";
577
+ import {
578
+ AGENT_CONSOLE_DEMO_ORGANIZATION_ID as AGENT_CONSOLE_DEMO_ORGANIZATION_ID2,
579
+ AGENT_CONSOLE_DEMO_PROJECT_ID as AGENT_CONSOLE_DEMO_PROJECT_ID3,
580
+ createAgentConsoleDemoHandlers as createAgentConsoleDemoHandlers3
581
+ } from "@contractspec/example.agent-console/shared";
278
582
  var toolRegistryMarkdownRenderer = {
279
583
  target: "markdown",
280
- render: async (desc) => {
584
+ render: async (desc, ctx) => {
281
585
  if (desc.source.type !== "component" || desc.source.componentKey !== "ToolRegistryView") {
282
586
  throw new Error("toolRegistryMarkdownRenderer: not ToolRegistryView");
283
587
  }
284
- const data = await mockListToolsHandler({
285
- organizationId: "demo-org",
588
+ const data = Array.isArray(ctx?.data) ? {
589
+ items: ctx.data,
590
+ total: ctx.data.length,
591
+ hasMore: false
592
+ } : await createAgentConsoleDemoHandlers3({
593
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID3
594
+ }).listTools({
595
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID3,
596
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID2,
286
597
  limit: 50,
287
598
  offset: 0
288
599
  });
@@ -323,121 +634,6 @@ var toolRegistryMarkdownRenderer = {
323
634
  };
324
635
  }
325
636
  };
326
-
327
- // src/ui/renderers/dashboard.markdown.ts
328
- import {
329
- mockListAgentsHandler as mockListAgentsHandler2,
330
- mockListRunsHandler as mockListRunsHandler2,
331
- mockListToolsHandler as mockListToolsHandler2
332
- } from "@contractspec/example.agent-console/handlers";
333
- function formatDuration2(ms) {
334
- if (ms < 1000)
335
- return `${ms}ms`;
336
- if (ms < 60000)
337
- return `${(ms / 1000).toFixed(1)}s`;
338
- return `${(ms / 60000).toFixed(1)}m`;
339
- }
340
- var agentDashboardMarkdownRenderer = {
341
- target: "markdown",
342
- render: async (desc) => {
343
- if (desc.source.type !== "component" || desc.source.componentKey !== "AgentConsoleDashboard") {
344
- throw new Error("agentDashboardMarkdownRenderer: not AgentConsoleDashboard");
345
- }
346
- const [agentsData, runsData, toolsData] = await Promise.all([
347
- mockListAgentsHandler2({
348
- organizationId: "demo-org",
349
- limit: 100
350
- }),
351
- mockListRunsHandler2({
352
- limit: 100
353
- }),
354
- mockListToolsHandler2({
355
- organizationId: "demo-org",
356
- limit: 100
357
- })
358
- ]);
359
- const activeAgents = agentsData.items.filter((a) => a.status === "ACTIVE").length;
360
- const completedRuns = runsData.items.filter((r) => r.status === "COMPLETED").length;
361
- const failedRuns = runsData.items.filter((r) => r.status === "FAILED").length;
362
- const totalTokens = runsData.items.reduce((sum, r) => sum + (r.totalTokens ?? 0), 0);
363
- const totalCost = runsData.items.reduce((sum, r) => sum + (r.estimatedCostUsd ?? 0), 0);
364
- const activeTools = toolsData.items.filter((t) => t.status === "ACTIVE").length;
365
- const lines = [
366
- "# Agent Console Dashboard",
367
- "",
368
- "> AI agent operations overview",
369
- "",
370
- "## Summary",
371
- "",
372
- "| Metric | Value |",
373
- "|--------|-------|",
374
- `| Total Agents | ${agentsData.total} |`,
375
- `| Active Agents | ${activeAgents} |`,
376
- `| Total Runs | ${runsData.total} |`,
377
- `| Completed Runs | ${completedRuns} |`,
378
- `| Failed Runs | ${failedRuns} |`,
379
- `| Total Tokens | ${totalTokens.toLocaleString()} |`,
380
- `| Total Cost | $${totalCost.toFixed(4)} |`,
381
- `| Total Tools | ${toolsData.total} |`,
382
- `| Active Tools | ${activeTools} |`,
383
- "",
384
- "## Agents",
385
- ""
386
- ];
387
- if (agentsData.items.length === 0) {
388
- lines.push("_No agents configured._");
389
- } else {
390
- lines.push("| Agent | Model | Status | Description |");
391
- lines.push("|-------|-------|--------|-------------|");
392
- for (const agent of agentsData.items.slice(0, 5)) {
393
- lines.push(`| ${agent.name} | ${agent.modelProvider}/${agent.modelName} | ${agent.status} | ${agent.description ?? "-"} |`);
394
- }
395
- if (agentsData.items.length > 5) {
396
- lines.push(`| ... | ... | ... | _${agentsData.total - 5} more_ |`);
397
- }
398
- }
399
- lines.push("");
400
- lines.push("## Recent Runs");
401
- lines.push("");
402
- if (runsData.items.length === 0) {
403
- lines.push("_No runs yet._");
404
- } else {
405
- lines.push("| Run ID | Agent | Status | Duration | Tokens | Cost |");
406
- lines.push("|--------|-------|--------|----------|--------|------|");
407
- for (const run of runsData.items.slice(0, 5)) {
408
- lines.push(`| ${run.id.slice(-8)} | ${run.agentName} | ${run.status} | ${run.durationMs ? formatDuration2(run.durationMs) : "-"} | ${run.totalTokens ?? 0} | $${(run.estimatedCostUsd ?? 0).toFixed(4)} |`);
409
- }
410
- if (runsData.items.length > 5) {
411
- lines.push(`| ... | ... | ... | ... | ... | _${runsData.total - 5} more_ |`);
412
- }
413
- }
414
- lines.push("");
415
- lines.push("## Tools");
416
- lines.push("");
417
- const toolsByCategory = {};
418
- for (const tool of toolsData.items) {
419
- const cat = tool.category;
420
- if (!toolsByCategory[cat])
421
- toolsByCategory[cat] = [];
422
- toolsByCategory[cat].push(tool);
423
- }
424
- if (Object.keys(toolsByCategory).length === 0) {
425
- lines.push("_No tools registered._");
426
- } else {
427
- lines.push("| Category | Tools | Active |");
428
- lines.push("|----------|-------|--------|");
429
- for (const [category, tools] of Object.entries(toolsByCategory).sort()) {
430
- const active = tools.filter((t) => t.status === "ACTIVE").length;
431
- lines.push(`| ${category} | ${tools.length} | ${active} |`);
432
- }
433
- }
434
- return {
435
- mimeType: "text/markdown",
436
- body: lines.join(`
437
- `)
438
- };
439
- }
440
- };
441
637
  export {
442
638
  toolRegistryMarkdownRenderer,
443
639
  runListMarkdownRenderer,
@@ -1,3 +1,8 @@
1
+ /**
2
+ * Markdown Renderer for Run List Presentation
3
+ *
4
+ * Uses dynamic import for handlers to ensure correct build order.
5
+ */
1
6
  import type { PresentationRenderer } from '@contractspec/lib.contracts-spec/presentations/transform-engine';
2
7
  /**
3
8
  * Markdown renderer for agent-console.run.list presentation
@@ -1,6 +1,9 @@
1
1
  // @bun
2
2
  // src/ui/renderers/run-list.markdown.ts
3
- import { mockListRunsHandler } from "@contractspec/example.agent-console/handlers";
3
+ import {
4
+ AGENT_CONSOLE_DEMO_PROJECT_ID,
5
+ createAgentConsoleDemoHandlers
6
+ } from "@contractspec/example.agent-console/shared";
4
7
  function formatDuration(ms) {
5
8
  if (ms < 1000)
6
9
  return `${ms}ms`;
@@ -10,12 +13,14 @@ function formatDuration(ms) {
10
13
  }
11
14
  var runListMarkdownRenderer = {
12
15
  target: "markdown",
13
- render: async (desc) => {
16
+ render: async (desc, ctx) => {
14
17
  if (desc.source.type !== "component" || desc.source.componentKey !== "RunListView") {
15
18
  throw new Error("runListMarkdownRenderer: not RunListView");
16
19
  }
17
- const data = await mockListRunsHandler({
18
- organizationId: "demo-org",
20
+ const data = Array.isArray(ctx?.data) ? { items: ctx.data, total: ctx.data.length, hasMore: false } : await createAgentConsoleDemoHandlers({
21
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID
22
+ }).listRuns({
23
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID,
19
24
  limit: 20,
20
25
  offset: 0
21
26
  });
@@ -1,6 +1,11 @@
1
+ /**
2
+ * Markdown Renderer for Tool Registry Presentation
3
+ *
4
+ * Uses dynamic import for handlers to ensure correct build order.
5
+ */
1
6
  import type { PresentationRenderer } from '@contractspec/lib.contracts-spec/presentations/transform-engine';
2
7
  /**
3
- * Markdown renderer for agent-console.tool.registry presentation
8
+ * Markdown renderer for agent-console.tool.list presentation
4
9
  * Only handles ToolRegistryView component
5
10
  */
6
11
  export declare const toolRegistryMarkdownRenderer: PresentationRenderer<{
@@ -1,14 +1,25 @@
1
1
  // @bun
2
2
  // src/ui/renderers/tool-registry.markdown.ts
3
- import { mockListToolsHandler } from "@contractspec/example.agent-console/handlers";
3
+ import {
4
+ AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
5
+ AGENT_CONSOLE_DEMO_PROJECT_ID,
6
+ createAgentConsoleDemoHandlers
7
+ } from "@contractspec/example.agent-console/shared";
4
8
  var toolRegistryMarkdownRenderer = {
5
9
  target: "markdown",
6
- render: async (desc) => {
10
+ render: async (desc, ctx) => {
7
11
  if (desc.source.type !== "component" || desc.source.componentKey !== "ToolRegistryView") {
8
12
  throw new Error("toolRegistryMarkdownRenderer: not ToolRegistryView");
9
13
  }
10
- const data = await mockListToolsHandler({
11
- organizationId: "demo-org",
14
+ const data = Array.isArray(ctx?.data) ? {
15
+ items: ctx.data,
16
+ total: ctx.data.length,
17
+ hasMore: false
18
+ } : await createAgentConsoleDemoHandlers({
19
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID
20
+ }).listTools({
21
+ projectId: AGENT_CONSOLE_DEMO_PROJECT_ID,
22
+ organizationId: AGENT_CONSOLE_DEMO_ORGANIZATION_ID,
12
23
  limit: 50,
13
24
  offset: 0
14
25
  });