yaml-flow 3.1.1 → 5.0.0
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/README.md +81 -20
- package/board-live-cards-cli.js +37 -0
- package/browser/board-livegraph-runtime.js +1453 -0
- package/browser/board-livegraph-runtime.js.map +1 -0
- package/browser/card-compute.js +153 -433
- package/browser/live-cards.js +868 -115
- package/browser/live-cards.schema.json +90 -83
- package/dist/board-livegraph-runtime/index.cjs +1448 -0
- package/dist/board-livegraph-runtime/index.cjs.map +1 -0
- package/dist/board-livegraph-runtime/index.d.cts +101 -0
- package/dist/board-livegraph-runtime/index.d.ts +101 -0
- package/dist/board-livegraph-runtime/index.js +1441 -0
- package/dist/board-livegraph-runtime/index.js.map +1 -0
- package/dist/card-compute/index.cjs +266 -431
- package/dist/card-compute/index.cjs.map +1 -1
- package/dist/card-compute/index.d.cts +77 -49
- package/dist/card-compute/index.d.ts +77 -49
- package/dist/card-compute/index.js +263 -432
- package/dist/card-compute/index.js.map +1 -1
- package/dist/cli/board-live-cards-cli.cjs +2750 -0
- package/dist/cli/board-live-cards-cli.cjs.map +1 -0
- package/dist/cli/board-live-cards-cli.d.cts +205 -0
- package/dist/cli/board-live-cards-cli.d.ts +205 -0
- package/dist/cli/board-live-cards-cli.js +2702 -0
- package/dist/cli/board-live-cards-cli.js.map +1 -0
- package/dist/{constants-B2zqu10b.d.ts → constants-DuzE5n03.d.ts} +2 -2
- package/dist/{constants-DJZU1pwJ.d.cts → constants-ozjf1Ejw.d.cts} +2 -2
- package/dist/continuous-event-graph/index.cjs +258 -464
- package/dist/continuous-event-graph/index.cjs.map +1 -1
- package/dist/continuous-event-graph/index.d.cts +18 -358
- package/dist/continuous-event-graph/index.d.ts +18 -358
- package/dist/continuous-event-graph/index.js +255 -464
- package/dist/continuous-event-graph/index.js.map +1 -1
- package/dist/event-graph/index.cjs +4 -4
- package/dist/event-graph/index.cjs.map +1 -1
- package/dist/event-graph/index.d.cts +5 -5
- package/dist/event-graph/index.d.ts +5 -5
- package/dist/event-graph/index.js +4 -4
- package/dist/event-graph/index.js.map +1 -1
- package/dist/index.cjs +1684 -555
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +26 -7
- package/dist/index.d.ts +26 -7
- package/dist/index.js +1678 -555
- package/dist/index.js.map +1 -1
- package/dist/inference/index.cjs +138 -19
- package/dist/inference/index.cjs.map +1 -1
- package/dist/inference/index.d.cts +2 -2
- package/dist/inference/index.d.ts +2 -2
- package/dist/inference/index.js +138 -19
- package/dist/inference/index.js.map +1 -1
- package/dist/journal-DRfJiheM.d.cts +28 -0
- package/dist/journal-NLYuqege.d.ts +28 -0
- package/dist/live-cards-bridge-Or7fdEJV.d.ts +316 -0
- package/dist/live-cards-bridge-vGJ6tMzN.d.cts +316 -0
- package/dist/schedule-CMcZe5Ny.d.ts +21 -0
- package/dist/schedule-CiucyCan.d.cts +21 -0
- package/dist/step-machine/index.cjs +18 -1
- package/dist/step-machine/index.cjs.map +1 -1
- package/dist/step-machine/index.d.cts +2 -2
- package/dist/step-machine/index.d.ts +2 -2
- package/dist/step-machine/index.js +18 -1
- package/dist/step-machine/index.js.map +1 -1
- package/dist/stores/file.d.cts +1 -1
- package/dist/stores/file.d.ts +1 -1
- package/dist/stores/index.d.cts +1 -1
- package/dist/stores/index.d.ts +1 -1
- package/dist/stores/localStorage.d.cts +1 -1
- package/dist/stores/localStorage.d.ts +1 -1
- package/dist/stores/memory.d.cts +1 -1
- package/dist/stores/memory.d.ts +1 -1
- package/dist/{types-BwvgvlOO.d.cts → types-BzLD8bjb.d.cts} +1 -1
- package/dist/{types-ClRA8hzC.d.ts → types-C2eJ7DAV.d.ts} +1 -1
- package/dist/{types-DEj7OakX.d.cts → types-CMFSIjpc.d.cts} +39 -4
- package/dist/{types-DEj7OakX.d.ts → types-CMFSIjpc.d.ts} +39 -4
- package/dist/{types-FZ_eyErS.d.cts → types-ycun84cq.d.cts} +1 -0
- package/dist/{types-FZ_eyErS.d.ts → types-ycun84cq.d.ts} +1 -0
- package/dist/{validate-DEZ2Ymdb.d.ts → validate-DJQTQ6bP.d.ts} +1 -1
- package/dist/{validate-DqKTZg_o.d.cts → validate-ke92Cleg.d.cts} +1 -1
- package/examples/browser/boards/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-form.json +16 -0
- package/examples/browser/boards/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/browser/boards/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/browser/boards/portfolio-tracker/fetch-prices.js +43 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.bat +7 -0
- package/examples/browser/boards/portfolio-tracker/portfolio-tracker.js +217 -0
- package/examples/browser/livecards-browser/index.html +41 -0
- package/examples/browser/{index.html → step-machine-browser/index.html} +53 -53
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
- package/examples/cli/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
- package/examples/cli/step-machine-demo/jsonata-init-board-cli.js +36 -0
- package/examples/cli/step-machine-demo/jsonata-init-board.flow.yaml +30 -0
- package/examples/cli/step-machine-demo/one-step-cli-only.flow.yaml +19 -0
- package/examples/cli/step-machine-demo/step-cli-echo-y.js +15 -0
- package/examples/cli/step-machine-demo/step2-double-cli.js +39 -0
- package/examples/cli/step-machine-demo/two-step-math-handlers.js +32 -0
- package/examples/cli/step-machine-demo/two-step-math.flow.yaml +31 -0
- package/examples/cli/step-machine-demo/two-step-mixed-handlers.js +24 -0
- package/examples/cli/step-machine-demo/two-step-mixed.flow.yaml +35 -0
- package/examples/example-board/board.yaml +23 -0
- package/examples/example-board/bootstrap_payload.json +1 -0
- package/examples/example-board/cards/card-chain-region-alert.json +39 -0
- package/examples/example-board/cards/card-chain-region-totals.json +26 -0
- package/examples/example-board/cards/card-chain-top-region.json +24 -0
- package/examples/example-board/cards/card-ex-actions.json +32 -0
- package/examples/example-board/cards/card-ex-chart.json +30 -0
- package/examples/example-board/cards/card-ex-filter.json +36 -0
- package/examples/example-board/cards/card-ex-filtered-by-preference.json +59 -0
- package/examples/example-board/cards/card-ex-form.json +91 -0
- package/examples/example-board/cards/card-ex-list.json +22 -0
- package/examples/example-board/cards/card-ex-markdown.json +17 -0
- package/examples/example-board/cards/card-ex-metric.json +19 -0
- package/examples/example-board/cards/card-ex-narrative.json +36 -0
- package/examples/example-board/cards/card-ex-source-http.json +28 -0
- package/examples/example-board/cards/card-ex-source.json +21 -0
- package/examples/example-board/cards/card-ex-status.json +35 -0
- package/examples/example-board/cards/card-ex-table.json +30 -0
- package/examples/example-board/cards/card-ex-todo.json +29 -0
- package/examples/example-board/demo-chat-handler.js +69 -0
- package/examples/example-board/demo-server.js +87 -0
- package/examples/example-board/demo-shell-browser.html +806 -0
- package/examples/example-board/demo-shell-with-server.html +280 -0
- package/examples/example-board/demo-shell.html +62 -0
- package/examples/example-board/demo-task-executor.js +255 -0
- package/examples/example-board/mock.db +15 -0
- package/examples/example-board/reusable-board-runtime-client.js +265 -0
- package/examples/example-board/reusable-runtime-artifacts-adapter.js +233 -0
- package/examples/example-board/reusable-server-runtime.js +1284 -0
- package/examples/index.html +799 -0
- package/examples/{batch → npm-libs/batch}/batch-step-machine.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/live-cards-board.ts +18 -18
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/live-portfolio-dashboard.ts +24 -24
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/portfolio-tracker.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/reactive-monitoring.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/reactive-pipeline.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/soc-incident-board.ts +1 -1
- package/examples/{continuous-event-graph → npm-libs/continuous-event-graph}/stock-dashboard.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/ci-cd-pipeline.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/executor-diamond.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/executor-pipeline.ts +1 -1
- package/examples/{event-graph → npm-libs/event-graph}/research-pipeline.ts +1 -1
- package/examples/{graph-of-graphs → npm-libs/graph-of-graphs}/multi-stage-etl.ts +1 -1
- package/examples/{graph-of-graphs → npm-libs/graph-of-graphs}/url-processing-pipeline.ts +1 -1
- package/examples/{inference → npm-libs/inference}/azure-deployment.ts +1 -1
- package/examples/{inference → npm-libs/inference}/copilot-cli.ts +1 -1
- package/examples/{inference → npm-libs/inference}/data-pipeline.ts +1 -1
- package/examples/{inference → npm-libs/inference}/pluggable-adapters.ts +1 -1
- package/examples/{node → npm-libs/node}/ai-conversation.ts +1 -1
- package/examples/{node → npm-libs/node}/simple-greeting.ts +2 -2
- package/examples/step-machine-cli/portfolio-tracker/cards/holdings-table.json +22 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-form.json +43 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/portfolio-value.json +15 -0
- package/examples/step-machine-cli/portfolio-tracker/cards/price-fetch.json +15 -0
- package/examples/step-machine-cli/portfolio-tracker/fetch-prices.js +48 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/_board-cli.js +58 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/add-cards-cli.js +27 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/init-board-cli.js +25 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/reset-board-dir-cli.js +29 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/retrigger-cli.js +27 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/status-cli.js +25 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/update-holdings-cli.js +37 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/wait-completed-cli.js +53 -0
- package/examples/step-machine-cli/portfolio-tracker/handlers/write-prices-cli.js +35 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker-task-executor.cjs +96 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.flow.yaml +227 -0
- package/examples/step-machine-cli/portfolio-tracker/portfolio-tracker.input.json +38 -0
- package/examples/step-machine-cli/portfolio-tracker/run-portfolio-tracker.bat +29 -0
- package/package.json +27 -2
- package/schema/board-status.schema.json +118 -0
- package/schema/card-runtime.schema.json +25 -0
- package/schema/flow.schema.json +5 -0
- package/schema/live-cards.schema.json +90 -83
- package/step-machine-cli.js +674 -0
- package/browser/ingest-board.js +0 -296
- package/examples/ingest.js +0 -733
- /package/examples/{flows → npm-libs/flows}/ai-conversation.yaml +0 -0
- /package/examples/{flows → npm-libs/flows}/order-processing.yaml +0 -0
- /package/examples/{flows → npm-libs/flows}/simple-greeting.yaml +0 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "card-ex-source-http",
|
|
3
|
+
"meta": {
|
|
4
|
+
"title": "Product Prices",
|
|
5
|
+
"tags": ["data", "linked"],
|
|
6
|
+
"desc": "Fetches pricing for products derived from upstream order data"
|
|
7
|
+
},
|
|
8
|
+
"requires": ["orders"],
|
|
9
|
+
"provides": [{ "bindTo": "prices", "src": "fetched_sources.raw" }],
|
|
10
|
+
"sources": [{
|
|
11
|
+
"bindTo": "raw",
|
|
12
|
+
"outputFile": "card-ex-source-http-raw.json",
|
|
13
|
+
"mock": "prices"
|
|
14
|
+
}],
|
|
15
|
+
"compute": [
|
|
16
|
+
{
|
|
17
|
+
"bindTo": "PRODUCT_LIST",
|
|
18
|
+
"expr": "$join($distinct(requires.orders.product), ',')"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"view": {
|
|
22
|
+
"elements": [
|
|
23
|
+
{ "kind": "table", "data": { "bind": "fetched_sources.raw", "columns": ["product", "price", "currency"], "sortable": true } }
|
|
24
|
+
],
|
|
25
|
+
"layout": { "board": { "col": 6, "order": 2 }, "canvas": { "x": 450, "y": 50, "w": 350, "h": 220 } }
|
|
26
|
+
},
|
|
27
|
+
"card_data": {}
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "card-ex-source",
|
|
3
|
+
"meta": {
|
|
4
|
+
"title": "Order Data",
|
|
5
|
+
"tags": ["data"],
|
|
6
|
+
"desc": "Root data source — fetches order records via a script"
|
|
7
|
+
},
|
|
8
|
+
"provides": [{ "bindTo": "orders", "src": "fetched_sources.raw" }],
|
|
9
|
+
"sources": [{
|
|
10
|
+
"bindTo": "raw",
|
|
11
|
+
"outputFile": "card-ex-source-raw.json",
|
|
12
|
+
"mock": "orders"
|
|
13
|
+
}],
|
|
14
|
+
"view": {
|
|
15
|
+
"elements": [
|
|
16
|
+
{ "kind": "table", "data": { "bind": "fetched_sources.raw", "columns": ["id", "product", "quantity", "amount", "region"], "maxRows": 10 } }
|
|
17
|
+
],
|
|
18
|
+
"layout": { "board": { "col": 6, "order": 1 }, "canvas": { "x": 50, "y": 50, "w": 350, "h": 220 } }
|
|
19
|
+
},
|
|
20
|
+
"card_data": {}
|
|
21
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "card-ex-status",
|
|
3
|
+
"meta": {
|
|
4
|
+
"title": "Revenue Health",
|
|
5
|
+
"tags": [],
|
|
6
|
+
"desc": "Status badge with threshold logic — JSONata ternary for green/amber/red"
|
|
7
|
+
},
|
|
8
|
+
"requires": ["orders"],
|
|
9
|
+
"compute": [
|
|
10
|
+
{ "bindTo": "totalRevenue", "expr": "$sum(requires.orders.amount)" },
|
|
11
|
+
{ "bindTo": "orderCount", "expr": "$count(requires.orders)" },
|
|
12
|
+
{
|
|
13
|
+
"bindTo": "health",
|
|
14
|
+
"expr": "computed_values.totalRevenue > 100000 ? { 'label': 'Healthy', 'value': computed_values.totalRevenue, 'orders': computed_values.orderCount } : computed_values.totalRevenue > 50000 ? { 'label': 'Moderate', 'value': computed_values.totalRevenue, 'orders': computed_values.orderCount } : { 'label': 'Low', 'value': computed_values.totalRevenue, 'orders': computed_values.orderCount }"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"view": {
|
|
18
|
+
"elements": [
|
|
19
|
+
{
|
|
20
|
+
"kind": "badge",
|
|
21
|
+
"data": {
|
|
22
|
+
"bind": "computed_values.health.label",
|
|
23
|
+
"colorMap": { "Healthy": "success", "Moderate": "warning", "Low": "danger" }
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"kind": "metric",
|
|
28
|
+
"label": "Revenue",
|
|
29
|
+
"data": { "bind": "computed_values.health.value" }
|
|
30
|
+
}
|
|
31
|
+
],
|
|
32
|
+
"layout": { "board": { "col": 3, "order": 8 }, "canvas": { "x": 450, "y": 530, "w": 200, "h": 170 } }
|
|
33
|
+
},
|
|
34
|
+
"card_data": {}
|
|
35
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "card-ex-table",
|
|
3
|
+
"meta": {
|
|
4
|
+
"title": "Order Details",
|
|
5
|
+
"tags": [],
|
|
6
|
+
"desc": "Filtered and sorted table — combines source data with user filter selections"
|
|
7
|
+
},
|
|
8
|
+
"requires": ["orders", "selections"],
|
|
9
|
+
"compute": [
|
|
10
|
+
{
|
|
11
|
+
"bindTo": "filtered",
|
|
12
|
+
"expr": "[$filter(requires.orders, function($v){ ($exists(requires.selections.region) ? $v.region = requires.selections.region : true) and ($exists(requires.selections.product) ? $v.product = requires.selections.product : true) })^(>amount)#$i[$i<20]]"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"view": {
|
|
16
|
+
"elements": [
|
|
17
|
+
{
|
|
18
|
+
"kind": "table",
|
|
19
|
+
"data": {
|
|
20
|
+
"bind": "computed_values.filtered",
|
|
21
|
+
"columns": ["id", "product", "quantity", "amount", "region"],
|
|
22
|
+
"sortable": true,
|
|
23
|
+
"maxRows": 20
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
],
|
|
27
|
+
"layout": { "board": { "col": 8, "order": 7 }, "canvas": { "x": 50, "y": 800, "w": 500, "h": 250 } }
|
|
28
|
+
},
|
|
29
|
+
"card_data": {}
|
|
30
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "card-ex-todo",
|
|
3
|
+
"meta": {
|
|
4
|
+
"title": "Action Items",
|
|
5
|
+
"tags": [],
|
|
6
|
+
"desc": "Interactive todo list — persistent user input via writeTo"
|
|
7
|
+
},
|
|
8
|
+
"view": {
|
|
9
|
+
"elements": [
|
|
10
|
+
{
|
|
11
|
+
"kind": "todo",
|
|
12
|
+
"label": "Tasks",
|
|
13
|
+
"data": {
|
|
14
|
+
"bind": "card_data.items",
|
|
15
|
+
"writeTo": "card_data.items",
|
|
16
|
+
"placeholder": "No tasks yet — add one above"
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
],
|
|
20
|
+
"layout": { "board": { "col": 4, "order": 11 }, "canvas": { "x": 700, "y": 320, "w": 260, "h": 180 } }
|
|
21
|
+
},
|
|
22
|
+
"card_data": {
|
|
23
|
+
"items": [
|
|
24
|
+
{ "text": "Set up task-executor for your data sources", "done": false },
|
|
25
|
+
{ "text": "Configure board.yaml connections", "done": false },
|
|
26
|
+
{ "text": "Run board-live-cards-cli init", "done": false }
|
|
27
|
+
]
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// demo-chat-handler.js — Echo chat handler for demo/example boards.
|
|
3
|
+
//
|
|
4
|
+
// Invoked by reusable-server-runtime after a user chat message is persisted,
|
|
5
|
+
// when a .chat-handler file is present in the board runtime directory.
|
|
6
|
+
//
|
|
7
|
+
// Invocation contract:
|
|
8
|
+
// node demo-chat-handler.js --boardId <id> --cardId <id> --extra <json>
|
|
9
|
+
//
|
|
10
|
+
// --extra JSON shape: { chatDir: "<abs path>", boardDir: "<abs path>", lastChatFile: "<filename>" }
|
|
11
|
+
//
|
|
12
|
+
// This demo handler:
|
|
13
|
+
// 1. Reads the content of the last chat file (the user message just written).
|
|
14
|
+
// 2. Computes the next serial by incrementing the leading number from lastChatFile.
|
|
15
|
+
// 3. Writes <nextSerial>-assistant.txt to chatDir with: "Echoing <original content>"
|
|
16
|
+
|
|
17
|
+
import * as fs from 'node:fs';
|
|
18
|
+
import * as path from 'node:path';
|
|
19
|
+
|
|
20
|
+
const args = process.argv.slice(2);
|
|
21
|
+
|
|
22
|
+
function getArg(name) {
|
|
23
|
+
const idx = args.indexOf(name);
|
|
24
|
+
return idx !== -1 && args[idx + 1] !== undefined ? args[idx + 1] : null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const boardId = getArg('--boardId') || '';
|
|
28
|
+
const cardId = getArg('--cardId') || '';
|
|
29
|
+
const extraStr = getArg('--extraEncJson') || '';
|
|
30
|
+
|
|
31
|
+
let extra = {};
|
|
32
|
+
try {
|
|
33
|
+
extra = JSON.parse(Buffer.from(extraStr, 'base64').toString('utf-8'));
|
|
34
|
+
} catch {
|
|
35
|
+
console.error('[demo-chat-handler] could not parse --extra JSON');
|
|
36
|
+
process.exit(0);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const { chatDir, lastChatFile } = extra;
|
|
40
|
+
|
|
41
|
+
if (!chatDir || !lastChatFile) {
|
|
42
|
+
console.error('[demo-chat-handler] --extra must contain chatDir and lastChatFile');
|
|
43
|
+
process.exit(0);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Read the user message from the last chat file.
|
|
47
|
+
const lastChatPath = path.join(chatDir, lastChatFile);
|
|
48
|
+
let content = '';
|
|
49
|
+
try {
|
|
50
|
+
content = fs.readFileSync(lastChatPath, 'utf-8').trim();
|
|
51
|
+
} catch (err) {
|
|
52
|
+
console.error(`[demo-chat-handler] could not read ${lastChatPath}: ${err.message}`);
|
|
53
|
+
process.exit(0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Derive next serial by incrementing the leading digits in lastChatFile.
|
|
57
|
+
// e.g. "007_user.txt" → 7 → next = 8 → "008-assistant.txt"
|
|
58
|
+
const serialMatch = String(lastChatFile).match(/^(\d+)/);
|
|
59
|
+
const nextSerial = serialMatch ? parseInt(serialMatch[1], 10) + 1 : 1;
|
|
60
|
+
const nextName = `${String(nextSerial).padStart(3, '0')}-assistant.txt`;
|
|
61
|
+
const nextPath = path.join(chatDir, nextName);
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
fs.writeFileSync(nextPath, `Echoing ${content}\n`, 'utf-8');
|
|
65
|
+
console.log(`[demo-chat-handler] boardId="${boardId}" cardId="${cardId}" wrote echo → ${nextPath}`);
|
|
66
|
+
} catch (err) {
|
|
67
|
+
console.error(`[demo-chat-handler] write failed: ${err.message}`);
|
|
68
|
+
process.exit(0);
|
|
69
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import http from 'node:http';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
createMultiBoardServerRuntime,
|
|
9
|
+
createRuntimeRequestDispatcher,
|
|
10
|
+
isRuntimeRoute,
|
|
11
|
+
} from './reusable-server-runtime.js';
|
|
12
|
+
|
|
13
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
14
|
+
const __dirname = path.dirname(__filename);
|
|
15
|
+
|
|
16
|
+
const PORT = Number(process.env.DEMO_SERVER_PORT || 7799);
|
|
17
|
+
const CORS_HEADERS = {
|
|
18
|
+
'Access-Control-Allow-Origin': '*',
|
|
19
|
+
'Access-Control-Allow-Headers': 'content-type,x-file-name',
|
|
20
|
+
'Access-Control-Allow-Methods': 'GET,POST,PATCH,OPTIONS',
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
const runtime = createMultiBoardServerRuntime({
|
|
24
|
+
apiBasePath: '/api/boards',
|
|
25
|
+
defaultTaskExecutorPath: process.env.DEMO_TASK_EXECUTOR_PATH || path.join(__dirname, 'demo-task-executor.js'),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const dispatch = createRuntimeRequestDispatcher(runtime);
|
|
29
|
+
|
|
30
|
+
// Board-id segment regex: /api/boards/:boardId/...
|
|
31
|
+
const BOARD_SEG_RE = /^\/api\/boards\/([^/]+)\/(.+)$/;
|
|
32
|
+
|
|
33
|
+
function jsonReply(res, status, payload) {
|
|
34
|
+
const body = JSON.stringify(payload);
|
|
35
|
+
res.writeHead(status, { ...CORS_HEADERS, 'Content-Type': 'application/json; charset=utf-8' });
|
|
36
|
+
res.end(body);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async function handleDemoSetup(req, res, boardId) {
|
|
40
|
+
const url = new URL(req.url, 'http://localhost');
|
|
41
|
+
const reset = String(url.searchParams.get('reset') || '').toLowerCase() === 'true';
|
|
42
|
+
try {
|
|
43
|
+
const result = runtime.performDemoSetup(boardId, reset);
|
|
44
|
+
jsonReply(res, 200, result);
|
|
45
|
+
} catch (err) {
|
|
46
|
+
jsonReply(res, err.statusCode || 500, { error: String((err && err.message) || err) });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const server = http.createServer((req, res) => {
|
|
51
|
+
const method = req.method || 'GET';
|
|
52
|
+
const pathname = new URL(req.url || '/', 'http://localhost').pathname;
|
|
53
|
+
|
|
54
|
+
if (method === 'OPTIONS') {
|
|
55
|
+
res.writeHead(204, CORS_HEADERS);
|
|
56
|
+
res.end();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Route: demo-setup is handled here in demo-server (host concern)
|
|
61
|
+
const boardSegMatch = pathname.match(BOARD_SEG_RE);
|
|
62
|
+
if (boardSegMatch && boardSegMatch[2] === 'demo-setup') {
|
|
63
|
+
void handleDemoSetup(req, res, boardSegMatch[1]);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// All other /api/boards routes are handled by the reusable runtime
|
|
68
|
+
void dispatch(req, res);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
server.listen(PORT, '127.0.0.1', () => {
|
|
72
|
+
console.log(`[demo-server] listening on http://127.0.0.1:${PORT}`);
|
|
73
|
+
console.log(`[demo-server] setup dir: ${runtime.setupDir}`);
|
|
74
|
+
console.log(`[demo-server] boards config: ${runtime.setupDir}/boards-config.json`);
|
|
75
|
+
console.log('[demo-server] endpoints:');
|
|
76
|
+
console.log(` GET ${runtime.apiBasePath} <- list boards`);
|
|
77
|
+
console.log(` POST ${runtime.apiBasePath} {id, label?} <- register board`);
|
|
78
|
+
console.log(` GET ${runtime.apiBasePath}/:boardId/demo-setup`);
|
|
79
|
+
console.log(` GET ${runtime.apiBasePath}/:boardId/bootstrap`);
|
|
80
|
+
console.log(` GET ${runtime.apiBasePath}/:boardId/sse`);
|
|
81
|
+
console.log(` GET ${runtime.apiBasePath}/:boardId/board-status`);
|
|
82
|
+
console.log(` PATCH ${runtime.apiBasePath}/:boardId/cards/:id`);
|
|
83
|
+
console.log(` POST ${runtime.apiBasePath}/:boardId/cards/:id/actions`);
|
|
84
|
+
console.log(` POST ${runtime.apiBasePath}/:boardId/cards/:id/files`);
|
|
85
|
+
console.log(` GET ${runtime.apiBasePath}/:boardId/cards/:id/files/:idx`);
|
|
86
|
+
console.log(` GET ${runtime.apiBasePath}/:boardId/cards/:id/chats`);
|
|
87
|
+
});
|