@tuongaz/seeflow 0.1.93 → 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.
- package/dist/web/assets/{architectureDiagram-3BPJPVTR-vgRdQoho.js → architectureDiagram-3BPJPVTR-XQzgHME4.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-D1bbs0Ix.js → blockDiagram-GPEHLZMM-D79pgdno.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-BHmsWf1o.js → c4Diagram-AAUBKEIU-DdpMasob.js} +1 -1
- package/dist/web/assets/channel-l7nIO4lY.js +1 -0
- package/dist/web/assets/{chart-CawZdlOV.js → chart-BS3qBv6b.js} +1 -1
- package/dist/web/assets/{chunk-2J33WTMH-BLQaRMqq.js → chunk-2J33WTMH-DMiLaW3V.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-DTivSBmA.js → chunk-4BX2VUAB-BxRQSTSU.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-DZ5Ond8O.js → chunk-55IACEB6-B8VO9ECP.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-CwKBkYmr.js → chunk-727SXJPM-CtI4DnVU.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-CAiwEMmH.js → chunk-AQP2D5EJ-BUDEtGcc.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-DCWBhj6w.js → chunk-FMBD7UC4-XRBBZk8O.js} +1 -1
- package/dist/web/assets/{chunk-ND2GUHAM-vLte473x.js → chunk-ND2GUHAM-D0exlO6X.js} +1 -1
- package/dist/web/assets/{chunk-QZHKN3VN-Bcu6ixss.js → chunk-QZHKN3VN-CnyiTlpq.js} +1 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-BPFTU8oh.js +1 -0
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-BPFTU8oh.js +1 -0
- package/dist/web/assets/{code-block-Q3inQ3vw.js → code-block-CLrCA7Xe.js} +1 -1
- package/dist/web/assets/{cose-bilkent-S5V4N54A-Cb8kZ6Km.js → cose-bilkent-S5V4N54A-B4D1urlH.js} +1 -1
- package/dist/web/assets/{dagre-BM42HDAG-Xws4A-Mi.js → dagre-BM42HDAG-CNe7Uulx.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-S1kziNDg.js → diagram-2AECGRRQ--mgpxm9o.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-eoeXtzaC.js → diagram-5GNKFQAL-CGHMTFDB.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-DktxY0CQ.js → diagram-KO2AKTUF-D31GLzm7.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-myBeIjhs.js → diagram-LMA3HP47-Bs2BLtxH.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-CFj88ujv.js → diagram-OG6HWLK6-CXUZ873r.js} +1 -1
- package/dist/web/assets/{erDiagram-TEJ5UH35-WaEyv1iP.js → erDiagram-TEJ5UH35-DL-eedkW.js} +1 -1
- package/dist/web/assets/{flowDiagram-I6XJVG4X-DAZ3T2Zd.js → flowDiagram-I6XJVG4X-BQCu7G6G.js} +1 -1
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-uY09PoQq.js → ganttDiagram-6RSMTGT7-CyBhrhQa.js} +1 -1
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-BSJHmF4Z.js → gitGraphDiagram-PVQCEYII-D9OqlmQL.js} +1 -1
- package/dist/web/assets/index-BKZTnCOL.js +8624 -0
- package/dist/web/assets/{index.es-BJkNyJb3.js → index.es-BpDX3yd0.js} +1 -1
- package/dist/web/assets/{infoDiagram-5YYISTIA-BJIRmQdX.js → infoDiagram-5YYISTIA-CMxwx_2B.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-Dk3i-Xkk.js → ishikawaDiagram-YF4QCWOH-DD1y6qVy.js} +1 -1
- package/dist/web/assets/{journeyDiagram-JHISSGLW-DnJaLB-P.js → journeyDiagram-JHISSGLW-CHo991VZ.js} +1 -1
- package/dist/web/assets/{jspdf.es.min-C9Avn9P2.js → jspdf.es.min-C8_HZhlK.js} +3 -3
- package/dist/web/assets/{kanban-definition-UN3LZRKU-CAvihSvB.js → kanban-definition-UN3LZRKU-CoYkI8Ob.js} +1 -1
- package/dist/web/assets/{linear-QJGLYtiK.js → linear-CQGcGLyB.js} +1 -1
- package/dist/web/assets/{markdown-umDyoRvw.js → markdown-Bud9JO0j.js} +1 -1
- package/dist/web/assets/{mermaid.core-DjNa-8Hv.js → mermaid.core-1G8gw6AK.js} +4 -4
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-DdGdY0IJ.js → mindmap-definition-RKZ34NQL-CJHnwtSU.js} +1 -1
- package/dist/web/assets/{pieDiagram-4H26LBE5-ByidPHli.js → pieDiagram-4H26LBE5-CXrXwuPG.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-3-CAwQni.js → quadrantDiagram-W4KKPZXB-BVJKIfMF.js} +1 -1
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-Bc0BnzZd.js → requirementDiagram-4Y6WPE33-ZFgLHB2Y.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-CnxTmkwV.js → sankeyDiagram-5OEKKPKP-cP9rHdFK.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-DrDm1r9r.js → sequenceDiagram-3UESZ5HK-BbruCi6T.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-Dgco9NEU.js → stateDiagram-AJRCARHV-CqGbTDXI.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-e0EPpmUp.js +1 -0
- package/dist/web/assets/{time-Yxy9gOXu.js → time-CXSgtiIX.js} +1 -1
- package/dist/web/assets/{timeline-definition-PNZ67QCA-CquekUx0.js → timeline-definition-PNZ67QCA-B4in6942.js} +1 -1
- package/dist/web/assets/{vennDiagram-CIIHVFJN-BGGVq4Mv.js → vennDiagram-CIIHVFJN-D3Esdgtc.js} +1 -1
- package/dist/web/assets/{wardley-L42UT6IY-fkIRiPsZ.js → wardley-L42UT6IY-CqOLhiLD.js} +1 -1
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-ih5pIO2M.js → wardleyDiagram-YWT4CUSO-DalbSLu7.js} +1 -1
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-Rwg_Ry62.js → xychartDiagram-2RQKCTM6-Bgnuf0j-.js} +1 -1
- package/dist/web/index.html +1 -1
- package/package.json +1 -1
- package/src/api.ts +43 -6
- package/src/cli-manifest.ts +1 -1
- package/src/cli.ts +8 -2
- package/src/mcp.ts +2 -0
- package/src/operations.ts +51 -24
- package/src/schema-catalog.ts +62 -4
- package/src/schema.ts +6 -1
- package/src/server.ts +6 -1
- package/dist/web/assets/channel-C-YVVNMU.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-BklVRjbL.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-BklVRjbL.js +0 -1
- package/dist/web/assets/index-5X7OVal6.js +0 -8624
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-F-kPNI2H.js +0 -1
package/src/operations.ts
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
removeNodeDir,
|
|
24
24
|
writeNodeFile,
|
|
25
25
|
} from './node-files.ts';
|
|
26
|
+
import { seeflowHome } from './paths.ts';
|
|
26
27
|
import { readProjectManifest, scanProject } from './project-scanner.ts';
|
|
27
28
|
import { type FlowEntry, type Registry, slugify } from './registry.ts';
|
|
28
29
|
import {
|
|
@@ -53,7 +54,9 @@ export const RegisterBodySchema = z.object({
|
|
|
53
54
|
export type RegisterBody = z.infer<typeof RegisterBodySchema>;
|
|
54
55
|
|
|
55
56
|
export const CreateProjectBodySchema = z.object({
|
|
56
|
-
|
|
57
|
+
// Optional: when omitted the project is scaffolded under
|
|
58
|
+
// <seeflowHome>/projects/<slug-of-name>. See createProjectImpl.
|
|
59
|
+
path: z.string().min(1).optional(),
|
|
57
60
|
name: z.string().min(1),
|
|
58
61
|
description: z.string().min(1).optional(),
|
|
59
62
|
});
|
|
@@ -95,15 +98,19 @@ export const NodePatchBodySchema = z
|
|
|
95
98
|
type: NodeTypeSchema.optional(),
|
|
96
99
|
position: PositionBodySchema.optional(),
|
|
97
100
|
name: z.string().optional(),
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
101
|
+
// Style/visual keys accept explicit `null` as the clear signal (mirrors
|
|
102
|
+
// `icon`): mergeNodeUpdates strips the key from disk, so undo can revert a
|
|
103
|
+
// style field back to its pre-edit "unset" default instead of being a
|
|
104
|
+
// no-op (a dropped-undefined PATCH leaves the field untouched).
|
|
105
|
+
borderColor: ColorTokenSchema.nullable().optional(),
|
|
106
|
+
backgroundColor: ColorTokenSchema.nullable().optional(),
|
|
107
|
+
borderSize: z.number().min(0).nullable().optional(),
|
|
108
|
+
borderWidth: z.number().min(0).max(8).nullable().optional(),
|
|
109
|
+
borderStyle: z.enum(['solid', 'dashed', 'dotted']).nullable().optional(),
|
|
110
|
+
fontSize: z.number().positive().nullable().optional(),
|
|
111
|
+
textAlign: z.enum(['left', 'center', 'right']).nullable().optional(),
|
|
112
|
+
cornerRadius: z.number().min(0).nullable().optional(),
|
|
113
|
+
shadow: z.number().int().min(0).max(5).nullable().optional(),
|
|
107
114
|
width: z.number().positive().optional(),
|
|
108
115
|
height: z.number().positive().optional(),
|
|
109
116
|
// type:'html'-only: when true, the renderer measures content and React Flow
|
|
@@ -112,11 +119,12 @@ export const NodePatchBodySchema = z
|
|
|
112
119
|
autoSize: z.boolean().optional(),
|
|
113
120
|
// type:'icon'-only: stroke color token. Lands at data.color; the
|
|
114
121
|
// post-merge ResolvedFlowSchema reparse gates that this is only valid on
|
|
115
|
-
// type:'icon'.
|
|
116
|
-
color: ColorTokenSchema.optional(),
|
|
122
|
+
// type:'icon'. Nullable: explicit null clears it (undo of an icon recolor).
|
|
123
|
+
color: ColorTokenSchema.nullable().optional(),
|
|
117
124
|
// type:'icon'-only: glyph stroke width. Lands at data.strokeWidth; the
|
|
118
|
-
// post-merge reparse gates the [0.5, 4] bound and arm validity.
|
|
119
|
-
|
|
125
|
+
// post-merge reparse gates the [0.5, 4] bound and arm validity. Nullable:
|
|
126
|
+
// explicit null clears it (undo back to the default stroke width).
|
|
127
|
+
strokeWidth: z.number().min(0.5).max(4).nullable().optional(),
|
|
120
128
|
// type:'icon'/type:'image'-only: accessible alt text. Lands at data.alt.
|
|
121
129
|
alt: z.string().optional(),
|
|
122
130
|
// kebab-case Lucide icon name. Lands at data.icon. The post-merge reparse
|
|
@@ -302,10 +310,12 @@ export const mergeNodeUpdates = (node: Record<string, unknown>, updates: NodePat
|
|
|
302
310
|
}
|
|
303
311
|
continue;
|
|
304
312
|
}
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
308
|
-
|
|
313
|
+
// Explicit null is the clear signal for every nullable key (style/visual
|
|
314
|
+
// tokens + US-009's `icon`): strip the key from disk so a re-parsed demo
|
|
315
|
+
// doesn't reintroduce it, and so an undo can restore a field to its
|
|
316
|
+
// pre-edit "unset" default. Only keys declared `.nullable()` in
|
|
317
|
+
// NodePatchBodySchema can reach here carrying null.
|
|
318
|
+
if (updates[key] === null) {
|
|
309
319
|
if (key in data) {
|
|
310
320
|
delete data[key];
|
|
311
321
|
touchedData = true;
|
|
@@ -1239,7 +1249,15 @@ export async function createProjectImpl(
|
|
|
1239
1249
|
body: CreateProjectBody,
|
|
1240
1250
|
): Promise<CreateProjectOutcome> {
|
|
1241
1251
|
const { registry, watcher } = deps;
|
|
1242
|
-
const {
|
|
1252
|
+
const { name, description } = body;
|
|
1253
|
+
|
|
1254
|
+
// Path is optional: when the caller omits it, scaffold under the studio's
|
|
1255
|
+
// home at <seeflowHome>/projects/<slug-of-name> so projects created from the
|
|
1256
|
+
// UI without a path land in a predictable, writable location.
|
|
1257
|
+
const folderPath =
|
|
1258
|
+
body.path && body.path.trim().length > 0
|
|
1259
|
+
? body.path
|
|
1260
|
+
: join(seeflowHome(), 'projects', slugify(name));
|
|
1243
1261
|
|
|
1244
1262
|
// Manifest-driven layout (US-018): a project is the seeflow.json manifest
|
|
1245
1263
|
// plus one flow folder under flows/<id>/. The default flow id for a
|
|
@@ -1644,8 +1662,14 @@ export async function patchNodeImpl(
|
|
|
1644
1662
|
field: string;
|
|
1645
1663
|
content: string;
|
|
1646
1664
|
kind: 'ref' | 'sidecar';
|
|
1665
|
+
value: unknown;
|
|
1647
1666
|
}> = [];
|
|
1648
|
-
|
|
1667
|
+
// Externalize against the node's *target* type: a retype-into-component
|
|
1668
|
+
// carrying `spec` in the same patch is still geometric at this point, so
|
|
1669
|
+
// keying off `node.type` would miss `spec` (only externalized for
|
|
1670
|
+
// 'component'), leaving spec.json unwritten and data.spec unpopulated.
|
|
1671
|
+
const targetType = updates.type ?? node.type;
|
|
1672
|
+
for (const spec of externalizedFieldsForNodeType(targetType)) {
|
|
1649
1673
|
const incoming = (updates as Record<string, unknown>)[spec.field];
|
|
1650
1674
|
if (incoming === undefined) continue;
|
|
1651
1675
|
const serializer = spec.serialize ?? defaultExternalizedSerializer;
|
|
@@ -1657,6 +1681,7 @@ export async function patchNodeImpl(
|
|
|
1657
1681
|
field: spec.field,
|
|
1658
1682
|
content,
|
|
1659
1683
|
kind: spec.kind ?? 'ref',
|
|
1684
|
+
value: incoming,
|
|
1660
1685
|
});
|
|
1661
1686
|
}
|
|
1662
1687
|
mergeNodeUpdates(node, updates);
|
|
@@ -1676,10 +1701,12 @@ export async function patchNodeImpl(
|
|
|
1676
1701
|
};
|
|
1677
1702
|
}
|
|
1678
1703
|
// 'ref' fields swap data[field] for a file:// pointer; 'sidecar'
|
|
1679
|
-
// fields (e.g. component spec)
|
|
1680
|
-
// post-mutation
|
|
1681
|
-
// on write and the resolver inlines it back from disk on
|
|
1682
|
-
|
|
1704
|
+
// fields (e.g. component spec) keep the incoming value in memory so the
|
|
1705
|
+
// post-mutation reparse + SSE broadcast see it — splitFlow drops it
|
|
1706
|
+
// from flow.json on write and the resolver inlines it back from disk on
|
|
1707
|
+
// read. Setting it here is required for a retype-into-component patch,
|
|
1708
|
+
// where there is no pre-inlined data.spec to fall back on.
|
|
1709
|
+
data[w.field] = w.kind === 'ref' ? w.ref : w.value;
|
|
1683
1710
|
}
|
|
1684
1711
|
node.data = data;
|
|
1685
1712
|
}
|
package/src/schema-catalog.ts
CHANGED
|
@@ -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 {
|
|
@@ -51,13 +52,25 @@ export interface SchemaPayload {
|
|
|
51
52
|
// further without round-tripping. `examples` are ready-to-paste jq paths;
|
|
52
53
|
// `dataFields` lists the node-variant `data.<field>` keys (single-variant
|
|
53
54
|
// lookups only — undefined for non-node categories or category-level
|
|
54
|
-
// responses).
|
|
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.
|
|
55
59
|
export interface JqHints {
|
|
56
60
|
dataFields?: string[];
|
|
57
61
|
examples: string[];
|
|
62
|
+
rootPath: string;
|
|
58
63
|
tip?: string;
|
|
59
64
|
}
|
|
60
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
|
+
|
|
61
74
|
// Draft-07 pin matches the widest tool support; the same target string is
|
|
62
75
|
// used by the MCP `tools/list` JSON Schemas (default in zod-to-json-schema)
|
|
63
76
|
// so consumers see one consistent dialect across the whole surface.
|
|
@@ -101,6 +114,11 @@ const CATEGORY_META: Array<Omit<SchemaCategory, 'subnames'>> = [
|
|
|
101
114
|
description:
|
|
102
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.",
|
|
103
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
|
+
},
|
|
104
122
|
{ name: 'style', description: 'style.json (studio-owned).' },
|
|
105
123
|
];
|
|
106
124
|
|
|
@@ -131,6 +149,7 @@ const PAYLOADS: Record<string, SchemaPayload> = {
|
|
|
131
149
|
"type:'image' data.path must start with 'nodes/<id>/'.",
|
|
132
150
|
"scriptPath in playAction/statusAction is relative to nodes/<nodeId>/ and may not contain '..' or absolute paths.",
|
|
133
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`.',
|
|
134
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).",
|
|
135
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.',
|
|
136
155
|
],
|
|
@@ -162,6 +181,22 @@ const PAYLOADS: Record<string, SchemaPayload> = {
|
|
|
162
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.",
|
|
163
182
|
'elements is keyed by element id; `root` names the entry element. Element ids referenced from children / actions must exist in elements.',
|
|
164
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.',
|
|
165
200
|
],
|
|
166
201
|
},
|
|
167
202
|
style: {
|
|
@@ -259,12 +294,19 @@ export function buildJqHints(category: string, subname?: string): JqHints | null
|
|
|
259
294
|
return {
|
|
260
295
|
...(dataFields ? { dataFields } : {}),
|
|
261
296
|
examples,
|
|
262
|
-
|
|
297
|
+
rootPath: `.schemas.${subname}`,
|
|
298
|
+
tip: withResultTip(hint),
|
|
263
299
|
};
|
|
264
300
|
}
|
|
265
301
|
const subs = Object.keys(payload.schemas);
|
|
266
302
|
const sample = subs[0];
|
|
267
|
-
if (!sample)
|
|
303
|
+
if (!sample) {
|
|
304
|
+
return {
|
|
305
|
+
examples: ['.schemas', '.notes', '.notes[]'],
|
|
306
|
+
rootPath: '.schemas',
|
|
307
|
+
tip: JQ_RESULT_TIP,
|
|
308
|
+
};
|
|
309
|
+
}
|
|
268
310
|
const examples = [
|
|
269
311
|
'.schemas',
|
|
270
312
|
`.schemas.${sample}`,
|
|
@@ -276,9 +318,25 @@ export function buildJqHints(category: string, subname?: string): JqHints | null
|
|
|
276
318
|
];
|
|
277
319
|
return {
|
|
278
320
|
examples,
|
|
279
|
-
|
|
321
|
+
rootPath: '.schemas',
|
|
322
|
+
tip: withResultTip(
|
|
280
323
|
subs.length > 1
|
|
281
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.`
|
|
282
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
|
+
),
|
|
283
341
|
};
|
|
284
342
|
}
|
package/src/schema.ts
CHANGED
|
@@ -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
|
|
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(),
|
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
|
-
|
|
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-DjNa-8Hv.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-CwKBkYmr.js";import{a as i}from"./mermaid.core-DjNa-8Hv.js";import"./index-5X7OVal6.js";import"./chunk-FMBD7UC4-DCWBhj6w.js";import"./chunk-ND2GUHAM-vLte473x.js";import"./chunk-55IACEB6-DZ5Ond8O.js";import"./chunk-2J33WTMH-BLQaRMqq.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-CwKBkYmr.js";import{a as i}from"./mermaid.core-DjNa-8Hv.js";import"./index-5X7OVal6.js";import"./chunk-FMBD7UC4-DCWBhj6w.js";import"./chunk-ND2GUHAM-vLte473x.js";import"./chunk-55IACEB6-DZ5Ond8O.js";import"./chunk-2J33WTMH-BLQaRMqq.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};
|