@tuongaz/seeflow 0.1.91 → 0.1.97

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 (69) hide show
  1. package/dist/web/assets/{architectureDiagram-3BPJPVTR-CLQb7I2I.js → architectureDiagram-3BPJPVTR-XQzgHME4.js} +1 -1
  2. package/dist/web/assets/{blockDiagram-GPEHLZMM-DN0OjtOL.js → blockDiagram-GPEHLZMM-D79pgdno.js} +1 -1
  3. package/dist/web/assets/{c4Diagram-AAUBKEIU-DMVbVbvl.js → c4Diagram-AAUBKEIU-DdpMasob.js} +1 -1
  4. package/dist/web/assets/channel-l7nIO4lY.js +1 -0
  5. package/dist/web/assets/{chart-Bx3ReVE3.js → chart-BS3qBv6b.js} +1 -1
  6. package/dist/web/assets/{chunk-2J33WTMH-9vQ1xqy3.js → chunk-2J33WTMH-DMiLaW3V.js} +1 -1
  7. package/dist/web/assets/{chunk-4BX2VUAB-DRGxmqVG.js → chunk-4BX2VUAB-BxRQSTSU.js} +1 -1
  8. package/dist/web/assets/{chunk-55IACEB6-DlboNFJr.js → chunk-55IACEB6-B8VO9ECP.js} +1 -1
  9. package/dist/web/assets/{chunk-727SXJPM-2Se8RGwW.js → chunk-727SXJPM-CtI4DnVU.js} +1 -1
  10. package/dist/web/assets/{chunk-AQP2D5EJ-DqZEBh23.js → chunk-AQP2D5EJ-BUDEtGcc.js} +1 -1
  11. package/dist/web/assets/{chunk-FMBD7UC4-BJX_21R2.js → chunk-FMBD7UC4-XRBBZk8O.js} +1 -1
  12. package/dist/web/assets/{chunk-ND2GUHAM-DFBKXknR.js → chunk-ND2GUHAM-D0exlO6X.js} +1 -1
  13. package/dist/web/assets/{chunk-QZHKN3VN-CHnWLNTw.js → chunk-QZHKN3VN-CnyiTlpq.js} +1 -1
  14. package/dist/web/assets/classDiagram-4FO5ZUOK-BPFTU8oh.js +1 -0
  15. package/dist/web/assets/classDiagram-v2-Q7XG4LA2-BPFTU8oh.js +1 -0
  16. package/dist/web/assets/{code-block-IJZcqBQa.js → code-block-CLrCA7Xe.js} +1 -1
  17. package/dist/web/assets/{cose-bilkent-S5V4N54A-B0LjjLKu.js → cose-bilkent-S5V4N54A-B4D1urlH.js} +1 -1
  18. package/dist/web/assets/{dagre-BM42HDAG-mMg_Ia_X.js → dagre-BM42HDAG-CNe7Uulx.js} +1 -1
  19. package/dist/web/assets/{diagram-2AECGRRQ-BUy1Taew.js → diagram-2AECGRRQ--mgpxm9o.js} +1 -1
  20. package/dist/web/assets/{diagram-5GNKFQAL-DH_tg4Cb.js → diagram-5GNKFQAL-CGHMTFDB.js} +1 -1
  21. package/dist/web/assets/{diagram-KO2AKTUF-CE1rkBey.js → diagram-KO2AKTUF-D31GLzm7.js} +1 -1
  22. package/dist/web/assets/{diagram-LMA3HP47-DS7ee5II.js → diagram-LMA3HP47-Bs2BLtxH.js} +1 -1
  23. package/dist/web/assets/{diagram-OG6HWLK6-DzCf3KBM.js → diagram-OG6HWLK6-CXUZ873r.js} +1 -1
  24. package/dist/web/assets/{erDiagram-TEJ5UH35-Spog-6po.js → erDiagram-TEJ5UH35-DL-eedkW.js} +1 -1
  25. package/dist/web/assets/{flowDiagram-I6XJVG4X-0VAojPZO.js → flowDiagram-I6XJVG4X-BQCu7G6G.js} +1 -1
  26. package/dist/web/assets/{ganttDiagram-6RSMTGT7-DcjKkuMU.js → ganttDiagram-6RSMTGT7-CyBhrhQa.js} +1 -1
  27. package/dist/web/assets/{gitGraphDiagram-PVQCEYII-Bq9UIINL.js → gitGraphDiagram-PVQCEYII-D9OqlmQL.js} +1 -1
  28. package/dist/web/assets/index-BKZTnCOL.js +8624 -0
  29. package/dist/web/assets/{index-CWGdrwRY.css → index-I8_SAWCr.css} +1 -1
  30. package/dist/web/assets/{index.es-BUxcZ9iL.js → index.es-BpDX3yd0.js} +1 -1
  31. package/dist/web/assets/{infoDiagram-5YYISTIA-yxIJiF1X.js → infoDiagram-5YYISTIA-CMxwx_2B.js} +1 -1
  32. package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-BkcKepSB.js → ishikawaDiagram-YF4QCWOH-DD1y6qVy.js} +1 -1
  33. package/dist/web/assets/{journeyDiagram-JHISSGLW-KfXgvDdv.js → journeyDiagram-JHISSGLW-CHo991VZ.js} +1 -1
  34. package/dist/web/assets/{jspdf.es.min-BPfxcczM.js → jspdf.es.min-C8_HZhlK.js} +3 -3
  35. package/dist/web/assets/{kanban-definition-UN3LZRKU-B2m52Unk.js → kanban-definition-UN3LZRKU-CoYkI8Ob.js} +1 -1
  36. package/dist/web/assets/{linear-D-pwAWPr.js → linear-CQGcGLyB.js} +1 -1
  37. package/dist/web/assets/{markdown-lr17R9FO.js → markdown-Bud9JO0j.js} +1 -1
  38. package/dist/web/assets/{mermaid.core-CRo4rzDL.js → mermaid.core-1G8gw6AK.js} +4 -4
  39. package/dist/web/assets/{mindmap-definition-RKZ34NQL-DUpVPXgC.js → mindmap-definition-RKZ34NQL-CJHnwtSU.js} +1 -1
  40. package/dist/web/assets/{pieDiagram-4H26LBE5-CatVLCYi.js → pieDiagram-4H26LBE5-CXrXwuPG.js} +1 -1
  41. package/dist/web/assets/{quadrantDiagram-W4KKPZXB-TJ5_ZxiK.js → quadrantDiagram-W4KKPZXB-BVJKIfMF.js} +1 -1
  42. package/dist/web/assets/{requirementDiagram-4Y6WPE33-B7CTMFGC.js → requirementDiagram-4Y6WPE33-ZFgLHB2Y.js} +1 -1
  43. package/dist/web/assets/{sankeyDiagram-5OEKKPKP-C56xsvrm.js → sankeyDiagram-5OEKKPKP-cP9rHdFK.js} +1 -1
  44. package/dist/web/assets/{sequenceDiagram-3UESZ5HK-EPKxvTJ9.js → sequenceDiagram-3UESZ5HK-BbruCi6T.js} +1 -1
  45. package/dist/web/assets/{stateDiagram-AJRCARHV-Cma2F0T8.js → stateDiagram-AJRCARHV-CqGbTDXI.js} +1 -1
  46. package/dist/web/assets/stateDiagram-v2-BHNVJYJU-e0EPpmUp.js +1 -0
  47. package/dist/web/assets/{time-D6UR1Qac.js → time-CXSgtiIX.js} +1 -1
  48. package/dist/web/assets/{timeline-definition-PNZ67QCA-iYUvK9JO.js → timeline-definition-PNZ67QCA-B4in6942.js} +1 -1
  49. package/dist/web/assets/{vennDiagram-CIIHVFJN-CkLxULtS.js → vennDiagram-CIIHVFJN-D3Esdgtc.js} +1 -1
  50. package/dist/web/assets/{wardley-L42UT6IY-DPcFqZu2.js → wardley-L42UT6IY-CqOLhiLD.js} +1 -1
  51. package/dist/web/assets/{wardleyDiagram-YWT4CUSO-BKqSvb-r.js → wardleyDiagram-YWT4CUSO-DalbSLu7.js} +1 -1
  52. package/dist/web/assets/{xychartDiagram-2RQKCTM6-0L00Xzr6.js → xychartDiagram-2RQKCTM6-Bgnuf0j-.js} +1 -1
  53. package/dist/web/index.html +2 -2
  54. package/package.json +1 -1
  55. package/src/api.ts +63 -8
  56. package/src/cli-manifest.ts +50 -25
  57. package/src/cli.ts +34 -9
  58. package/src/mcp.ts +16 -2
  59. package/src/merge.ts +0 -1
  60. package/src/node-files.ts +39 -1
  61. package/src/operations.ts +81 -55
  62. package/src/schema-catalog.ts +167 -3
  63. package/src/schema.ts +11 -7
  64. package/src/server.ts +6 -1
  65. package/dist/web/assets/channel-CilAQwI4.js +0 -1
  66. package/dist/web/assets/classDiagram-4FO5ZUOK-fiT0MjXY.js +0 -1
  67. package/dist/web/assets/classDiagram-v2-Q7XG4LA2-fiT0MjXY.js +0 -1
  68. package/dist/web/assets/index-DFpY3RpV.js +0 -8624
  69. package/dist/web/assets/stateDiagram-v2-BHNVJYJU-DRP_iswg.js +0 -1
@@ -5,6 +5,7 @@
5
5
  // module load — each call returns a fresh shallow copy so callers can't
6
6
  // mutate the cached payload.
7
7
 
8
+ import { componentCatalog } from '@seeflow/canvas/catalog';
8
9
  import type { ZodTypeAny } from 'zod';
9
10
  import { zodToJsonSchema } from 'zod-to-json-schema';
10
11
  import {
@@ -37,6 +38,9 @@ import {
37
38
  export interface SchemaCategory {
38
39
  name: string;
39
40
  description: string;
41
+ // Every drill target valid for `seeflow schema <name> <subname>`. Lets the
42
+ // agent pick a variant without a second round-trip to listCategorySubnames.
43
+ subnames: string[];
40
44
  }
41
45
 
42
46
  export interface SchemaPayload {
@@ -44,13 +48,52 @@ export interface SchemaPayload {
44
48
  notes: string[];
45
49
  }
46
50
 
51
+ // Hint payload attached to every schema response so the agent can drill in
52
+ // further without round-tripping. `examples` are ready-to-paste jq paths;
53
+ // `dataFields` lists the node-variant `data.<field>` keys (single-variant
54
+ // lookups only — undefined for non-node categories or category-level
55
+ // responses). `rootPath` is the jq prefix that reaches the schema body at
56
+ // this response level (`.categories` on the index, `.schemas` on a category,
57
+ // `.schemas.<subname>` on a drill) — present in the plain (non-`--jq`)
58
+ // response the agent reads first, so it never has to guess the prefix.
59
+ export interface JqHints {
60
+ dataFields?: string[];
61
+ examples: string[];
62
+ rootPath: string;
63
+ tip?: string;
64
+ }
65
+
66
+ // Appended to every `jqHints.tip`. The `--jq` filter runs against the schema
67
+ // object itself; the `{ result }` wrapper the CLI prints under `--jq` is
68
+ // presentational, so a filter must never be prefixed with `.result`.
69
+ const JQ_RESULT_TIP =
70
+ '`--jq` runs against this object directly; the `result` wrapper in `--jq` output is presentational — never prefix your filter with `.result`.';
71
+
72
+ const withResultTip = (hint: string): string => `${hint} ${JQ_RESULT_TIP}`;
73
+
47
74
  // Draft-07 pin matches the widest tool support; the same target string is
48
75
  // used by the MCP `tools/list` JSON Schemas (default in zod-to-json-schema)
49
76
  // so consumers see one consistent dialect across the whole surface.
50
77
  const toJsonSchema = (schema: ZodTypeAny): unknown =>
51
78
  zodToJsonSchema(schema, { $refStrategy: 'none', target: 'jsonSchema7' });
52
79
 
53
- const CATEGORIES: SchemaCategory[] = [
80
+ // Recipe block returned on the schema index (CLI / REST / MCP) so the agent
81
+ // sees the drill + filter pattern in the response itself, not just in
82
+ // `seeflow help schema`.
83
+ export const SCHEMA_INDEX_USAGE = {
84
+ drill: 'seeflow schema <category> [<subname>]',
85
+ filter: 'seeflow schema <category> [<subname>] --jq <jq-path>',
86
+ examples: [
87
+ 'seeflow schema node',
88
+ 'seeflow schema node rectangle',
89
+ 'seeflow schema node rectangle --jq .schemas.rectangle.properties.data.properties.playAction',
90
+ 'seeflow schema action playAction',
91
+ ],
92
+ } as const;
93
+
94
+ // Description metadata. `subnames` are filled in by listSchemaCategories()
95
+ // at call time from PAYLOADS, so the two stay in lockstep automatically.
96
+ const CATEGORY_META: Array<Omit<SchemaCategory, 'subnames'>> = [
54
97
  { name: 'flow', description: 'Top-level flow.json envelope.' },
55
98
  {
56
99
  name: 'node',
@@ -71,6 +114,11 @@ const CATEGORIES: SchemaCategory[] = [
71
114
  description:
72
115
  "Sidecar shape written to <project>/nodes/<id>/spec.json for type:'component' nodes. Carries the json-render element tree, initial state, and named actions the renderer dispatches on user input.",
73
116
  },
117
+ {
118
+ name: 'componentCatalog',
119
+ description:
120
+ 'The legal values for componentSpec.elements[].type and the props each accepts. Drill: seeflow schema componentCatalog <Name>.',
121
+ },
74
122
  { name: 'style', description: 'style.json (studio-owned).' },
75
123
  ];
76
124
 
@@ -101,6 +149,7 @@ const PAYLOADS: Record<string, SchemaPayload> = {
101
149
  "type:'image' data.path must start with 'nodes/<id>/'.",
102
150
  "scriptPath in playAction/statusAction is relative to nodes/<nodeId>/ and may not contain '..' or absolute paths.",
103
151
  "type:'component' nodes have no `spec` field on disk — the spec lives in <project>/nodes/<id>/spec.json (see `seeflow schema componentSpec`). The resolver inlines it into data.spec for runtime / SSE broadcasts.",
152
+ 'The legal `elements[].type` values and their props are listed under `seeflow schema componentCatalog`.',
104
153
  "stateSource SHOULD be set on every node that has a statusAction — kind:'request' for poll-based (REST, healthcheck, DB query), kind:'event' for push-based (SSE, webhook, queue, message bus).",
105
154
  'stateSource may also be set without a statusAction on representational/architecture diagrams to signal data-flow intent (poll vs push) without wiring a runtime probe.',
106
155
  ],
@@ -132,6 +181,22 @@ const PAYLOADS: Record<string, SchemaPayload> = {
132
181
  "spec.json is the on-disk source of truth for type:'component' nodes; the resolver inlines it into data.spec at read time and splitFlow strips it back out before writing flow.json so the sidecar is never double-stored.",
133
182
  'elements is keyed by element id; `root` names the entry element. Element ids referenced from children / actions must exist in elements.',
134
183
  'state and actions are both keyed by user-chosen names. Action handles in the rendered UI reference these names; see `seeflow schema action` for the per-action shape.',
184
+ 'The legal `elements[].type` values and their props are listed under `seeflow schema componentCatalog`.',
185
+ ],
186
+ },
187
+ componentCatalog: {
188
+ // One subname per catalog entry; schema body = the props object that
189
+ // element type accepts. Built dynamically so adding a catalog component
190
+ // surfaces here automatically (the canvas catalog is the single source).
191
+ schemas: Object.fromEntries(
192
+ Object.entries(componentCatalog.components).map(([name, def]) => [
193
+ name,
194
+ toJsonSchema(def.props),
195
+ ]),
196
+ ),
197
+ notes: [
198
+ "Each key is a legal componentSpec.elements[].type; its schema is the props object that element type accepts. Set them on the element's `props` field.",
199
+ 'Any prop value may instead be a { $state } / { $action } / { $cond,$then,$else } ref resolved by the json-render runtime at render time — the per-prop schema shows the concrete (non-ref) shape.',
135
200
  ],
136
201
  },
137
202
  style: {
@@ -141,7 +206,10 @@ const PAYLOADS: Record<string, SchemaPayload> = {
141
206
  };
142
207
 
143
208
  export function listSchemaCategories(): SchemaCategory[] {
144
- return CATEGORIES.map((c) => ({ ...c }));
209
+ return CATEGORY_META.map((c) => ({
210
+ ...c,
211
+ subnames: Object.keys(PAYLOADS[c.name]?.schemas ?? {}),
212
+ }));
145
213
  }
146
214
 
147
215
  export function getSchemaCategory(name: string): SchemaPayload | null {
@@ -151,7 +219,7 @@ export function getSchemaCategory(name: string): SchemaPayload | null {
151
219
  }
152
220
 
153
221
  export function schemaCategoryNames(): string[] {
154
- return CATEGORIES.map((c) => c.name);
222
+ return CATEGORY_META.map((c) => c.name);
155
223
  }
156
224
 
157
225
  // Drill into one named schema inside a category — e.g. ('node', 'rectangle')
@@ -176,3 +244,99 @@ export function listCategorySubnames(category: string): string[] | null {
176
244
  if (!payload) return null;
177
245
  return Object.keys(payload.schemas);
178
246
  }
247
+
248
+ // Top-level keys under `data.properties` for a single node variant — i.e.
249
+ // the per-shape data fields an author actually sets on a flow.json node
250
+ // (`name`, `icon`, `playAction`, etc.). Returns null when the variant has
251
+ // no `data.properties` wrapper (action / connector / style / componentSpec
252
+ // schemas, plus anything malformed). Pure helper consumed by buildJqHints
253
+ // to surface concrete drill-down paths.
254
+ export function getDataFieldNames(category: string, subname: string): string[] | null {
255
+ const sub = PAYLOADS[category]?.schemas[subname] as
256
+ | { properties?: { data?: { properties?: Record<string, unknown> } } }
257
+ | undefined;
258
+ const dataProps = sub?.properties?.data?.properties;
259
+ if (!dataProps) return null;
260
+ return Object.keys(dataProps);
261
+ }
262
+
263
+ // Build ready-to-paste jq path examples for a schema response. When `subname`
264
+ // is provided, the examples drill into that single variant — including one
265
+ // path per `data.<field>` so the agent can `--jq` straight to (say)
266
+ // `.schemas.rectangle.properties.data.properties.playAction` without first
267
+ // reading the whole envelope. When `subname` is omitted, the hints cover the
268
+ // whole category (iteration, one sample variant, notes). `dataFields` only
269
+ // surfaces on single-variant lookups for shapes that actually carry a
270
+ // `data.properties` wrapper.
271
+ export function buildJqHints(category: string, subname?: string): JqHints | null {
272
+ const payload = PAYLOADS[category];
273
+ if (!payload) return null;
274
+ if (subname) {
275
+ if (payload.schemas[subname] === undefined) return null;
276
+ const dataFields = getDataFieldNames(category, subname);
277
+ const examples = [
278
+ `.schemas.${subname}`,
279
+ `.schemas.${subname}.required`,
280
+ ...(dataFields && dataFields.length > 0
281
+ ? [
282
+ `.schemas.${subname}.properties.data.properties`,
283
+ ...dataFields
284
+ .slice(0, 6)
285
+ .map((f) => `.schemas.${subname}.properties.data.properties.${f}`),
286
+ ]
287
+ : [`.schemas.${subname}.properties`]),
288
+ '.notes',
289
+ '.notes[]',
290
+ ];
291
+ const hint = dataFields
292
+ ? `dataFields lists every \`data.<field>\` available on this variant — point \`--jq\` at any of them with \`.schemas.${subname}.properties.data.properties.<field>\`.`
293
+ : `Use \`--jq\` to pluck a single property — e.g. \`.schemas.${subname}.required\`.`;
294
+ return {
295
+ ...(dataFields ? { dataFields } : {}),
296
+ examples,
297
+ rootPath: `.schemas.${subname}`,
298
+ tip: withResultTip(hint),
299
+ };
300
+ }
301
+ const subs = Object.keys(payload.schemas);
302
+ const sample = subs[0];
303
+ if (!sample) {
304
+ return {
305
+ examples: ['.schemas', '.notes', '.notes[]'],
306
+ rootPath: '.schemas',
307
+ tip: JQ_RESULT_TIP,
308
+ };
309
+ }
310
+ const examples = [
311
+ '.schemas',
312
+ `.schemas.${sample}`,
313
+ `.schemas.${sample}.required`,
314
+ `.schemas.${sample}.properties.data.properties`,
315
+ '.schemas[]',
316
+ '.notes',
317
+ '.notes[]',
318
+ ];
319
+ return {
320
+ examples,
321
+ rootPath: '.schemas',
322
+ tip: withResultTip(
323
+ subs.length > 1
324
+ ? `Pass \`seeflow schema ${category} <subname>\` (one of: ${subs.join(', ')}) to drop the other ${subs.length - 1} variant(s) from the payload before \`--jq\`-ing.`
325
+ : `Single-variant category — \`--jq\` paths drill straight into \`.schemas.${sample}\`.`,
326
+ ),
327
+ };
328
+ }
329
+
330
+ // jqHints for the schema index (`seeflow schema` with no category). The index
331
+ // payload is `{ categories, usage }`, so `--jq` filters root at `.categories`.
332
+ // Surfaced so the index carries the same `rootPath` affordance as every drill
333
+ // level — the agent never has to guess the prefix.
334
+ export function buildIndexJqHints(): JqHints {
335
+ return {
336
+ examples: ['.categories', '.categories[].name', '.usage', '.usage.examples'],
337
+ rootPath: '.categories',
338
+ tip: withResultTip(
339
+ 'Each entry under `.categories` names a drill target — pass its `name` as `<category>`.',
340
+ ),
341
+ };
342
+ }
package/src/schema.ts CHANGED
@@ -14,25 +14,26 @@ const HttpMethodSchema = z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
14
14
  // them to actual CSS values (theme-aware, light + dark).
15
15
  export const ColorTokenSchema = z.enum([
16
16
  // `'none'` renders transparent border / fill on nodes (no stroke, no fill).
17
- // Hidden from the text-color and connector-color pickers — invisible text
18
- // and edges aren't useful, and `'default'` already covers "inherit".
17
+ // Hidden from the connector-color picker — invisible edges aren't useful,
18
+ // and `'default'` already covers "inherit".
19
19
  'none',
20
20
  'default',
21
21
  'white',
22
22
  'slate',
23
23
  'gray',
24
24
  'red',
25
- 'rose',
26
25
  'orange',
27
26
  'amber',
27
+ 'yellow',
28
28
  'lime',
29
29
  'green',
30
30
  'teal',
31
31
  'cyan',
32
+ 'sky',
32
33
  'blue',
33
34
  'indigo',
34
35
  'violet',
35
- 'purple',
36
+ 'fuchsia',
36
37
  'pink',
37
38
  ]);
38
39
 
@@ -47,7 +48,6 @@ const NodeVisualBaseShape = {
47
48
  borderSize: z.number().min(0).optional(),
48
49
  borderStyle: z.enum(['solid', 'dashed', 'dotted']).optional(),
49
50
  fontSize: z.number().positive().optional(),
50
- textColor: ColorTokenSchema.optional(),
51
51
  // Horizontal alignment for the node's text content. Defaults to 'center'
52
52
  // at render time when omitted; explicit picks from the toolbar's Align
53
53
  // toggle persist here.
@@ -218,7 +218,12 @@ export const NodeTypeSchema = z.enum([
218
218
  // superRefine wired in a later story.
219
219
 
220
220
  export const ComponentSpecElementSchema = z.object({
221
- type: z.string().min(1),
221
+ type: z
222
+ .string()
223
+ .min(1)
224
+ .describe(
225
+ 'Component name from the catalog — see `seeflow schema componentCatalog` for the legal values and the props each type accepts.',
226
+ ),
222
227
  props: z.record(z.string(), z.unknown()).optional(),
223
228
  children: z.array(z.string()).optional(),
224
229
  watch: z.record(z.string(), z.unknown()).optional(),
@@ -711,7 +716,6 @@ const NodeStyleSchema = z
711
716
  borderSize: z.number().min(0).optional(),
712
717
  borderStyle: z.enum(['solid', 'dashed', 'dotted']).optional(),
713
718
  fontSize: z.number().positive().optional(),
714
- textColor: ColorTokenSchema.optional(),
715
719
  textAlign: z.enum(['left', 'center', 'right']).optional(),
716
720
  cornerRadius: z.number().min(0).optional(),
717
721
  shadow: z.number().int().min(0).max(5).optional(),
package/src/server.ts CHANGED
@@ -227,7 +227,12 @@ export function serve(options: ServeOptions = {}) {
227
227
  const hostname = options.hostname ?? '0.0.0.0';
228
228
  mkdirSync(seeflowHome(), { recursive: true });
229
229
  const app = createApp(options);
230
- return Bun.serve({ port, hostname, fetch: app.fetch });
230
+ // Bun's default per-connection idle timeout (~10s) reaps long-lived SSE
231
+ // streams between heartbeats, forcing the browser's EventSource to reconnect
232
+ // (each reconnect re-fires `hello` → a client refetch). Raise it well above
233
+ // the SSE heartbeat cadence so the keep-alive lands first and the stream
234
+ // stays warm. Max accepted by Bun is 255s.
235
+ return Bun.serve({ port, hostname, idleTimeout: 120, fetch: app.fetch });
231
236
  }
232
237
 
233
238
  if (import.meta.main) {
@@ -1 +0,0 @@
1
- import{U as a,C as n}from"./mermaid.core-CRo4rzDL.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,a as s,c as e,C as t}from"./chunk-727SXJPM-2Se8RGwW.js";import{a as i}from"./mermaid.core-CRo4rzDL.js";import"./index-DFpY3RpV.js";import"./chunk-FMBD7UC4-BJX_21R2.js";import"./chunk-ND2GUHAM-DFBKXknR.js";import"./chunk-55IACEB6-DlboNFJr.js";import"./chunk-2J33WTMH-9vQ1xqy3.js";import"./purify.es-CLGrRn1w.js";import"./step-CWvwoXpJ.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};
@@ -1 +0,0 @@
1
- import{s as a,a as s,c as e,C as t}from"./chunk-727SXJPM-2Se8RGwW.js";import{a as i}from"./mermaid.core-CRo4rzDL.js";import"./index-DFpY3RpV.js";import"./chunk-FMBD7UC4-BJX_21R2.js";import"./chunk-ND2GUHAM-DFBKXknR.js";import"./chunk-55IACEB6-DlboNFJr.js";import"./chunk-2J33WTMH-9vQ1xqy3.js";import"./purify.es-CLGrRn1w.js";import"./step-CWvwoXpJ.js";var b={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{b as diagram};