dominds 0.1.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/LICENSE +157 -0
- package/README.md +250 -0
- package/README.zh.md +161 -0
- package/dist/access-control.js +253 -0
- package/dist/cli/create.js +263 -0
- package/dist/cli/read.js +84 -0
- package/dist/cli/tui.js +199 -0
- package/dist/cli/webui.js +169 -0
- package/dist/cli.js +227 -0
- package/dist/dialog-factory.js +53 -0
- package/dist/dialog-global-registry.js +68 -0
- package/dist/dialog-instance-registry.js +78 -0
- package/dist/dialog-run-state.js +198 -0
- package/dist/dialog.js +1024 -0
- package/dist/evt-registry.js +103 -0
- package/dist/index.js +8 -0
- package/dist/llm/client.js +69 -0
- package/dist/llm/defaults.yaml +386 -0
- package/dist/llm/driver.js +3214 -0
- package/dist/llm/gen/anthropic.js +611 -0
- package/dist/llm/gen/codex.js +375 -0
- package/dist/llm/gen/mock.js +326 -0
- package/dist/llm/gen/openai.js +470 -0
- package/dist/llm/gen/registry.js +26 -0
- package/dist/llm/gen.js +2 -0
- package/dist/llm/tools-projection.js +37 -0
- package/dist/log.js +228 -0
- package/dist/mcp/config.js +230 -0
- package/dist/mcp/sdk-client.js +129 -0
- package/dist/mcp/server-runtime.js +57 -0
- package/dist/mcp/stdio-client.js +280 -0
- package/dist/mcp/supervisor.js +979 -0
- package/dist/mcp/tool-names.js +109 -0
- package/dist/minds/builtin/cmdr/persona.md +3 -0
- package/dist/minds/builtin/dijiang/knowledge.md +287 -0
- package/dist/minds/builtin/dijiang/persona.md +7 -0
- package/dist/minds/builtin/fuxi/persona.en.md +59 -0
- package/dist/minds/builtin/fuxi/persona.zh.md +49 -0
- package/dist/minds/builtin/pangu/persona.en.md +78 -0
- package/dist/minds/builtin/pangu/persona.zh.md +71 -0
- package/dist/minds/load.js +617 -0
- package/dist/minds/minds-i18n.js +131 -0
- package/dist/minds/system-prompt.js +281 -0
- package/dist/persistence.js +3128 -0
- package/dist/problems.js +109 -0
- package/dist/server/api-routes.js +1031 -0
- package/dist/server/auth.js +180 -0
- package/dist/server/mime-types.js +32 -0
- package/dist/server/prompts-routes.js +543 -0
- package/dist/server/server-core.js +235 -0
- package/dist/server/setup-routes.js +697 -0
- package/dist/server/static-server.js +132 -0
- package/dist/server/websocket-handler.js +1011 -0
- package/dist/server.js +164 -0
- package/dist/shared/async-fifo-mutex.js +36 -0
- package/dist/shared/diligence.js +20 -0
- package/dist/shared/dotenv.js +144 -0
- package/dist/shared/evt.js +195 -0
- package/dist/shared/i18n/driver-messages.js +267 -0
- package/dist/shared/i18n/text.js +9 -0
- package/dist/shared/i18n/tool-result-messages.js +51 -0
- package/dist/shared/rtws-cli.js +73 -0
- package/dist/shared/runtime-language.js +47 -0
- package/dist/shared/team-mgmt-manual.js +116 -0
- package/dist/shared/types/context-health.js +2 -0
- package/dist/shared/types/dialog.js +11 -0
- package/dist/shared/types/i18n.js +2 -0
- package/dist/shared/types/index.js +26 -0
- package/dist/shared/types/language.js +40 -0
- package/dist/shared/types/problems.js +2 -0
- package/dist/shared/types/prompts.js +2 -0
- package/dist/shared/types/q4h.js +7 -0
- package/dist/shared/types/run-state.js +8 -0
- package/dist/shared/types/setup.js +2 -0
- package/dist/shared/types/storage.js +10 -0
- package/dist/shared/types/tellask.js +8 -0
- package/dist/shared/types/tools-registry.js +2 -0
- package/dist/shared/types/wire.js +12 -0
- package/dist/shared/utils/fmt.js +9 -0
- package/dist/shared/utils/html.js +20 -0
- package/dist/shared/utils/id.js +18 -0
- package/dist/shared/utils/inter-dialog-format.js +101 -0
- package/dist/shared/utils/time.js +13 -0
- package/dist/static/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/dist/static/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/dist/static/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/dist/static/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/dist/static/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/dist/static/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/dist/static/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/dist/static/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/dist/static/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/dist/static/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/dist/static/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/dist/static/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/dist/static/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/dist/static/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/dist/static/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/dist/static/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/dist/static/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/dist/static/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/dist/static/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/dist/static/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/dist/static/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/dist/static/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/dist/static/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/dist/static/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/dist/static/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/dist/static/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/dist/static/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/dist/static/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/dist/static/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/dist/static/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/dist/static/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/dist/static/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/dist/static/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/dist/static/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/dist/static/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/dist/static/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/dist/static/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/dist/static/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/dist/static/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/dist/static/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/dist/static/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/dist/static/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/dist/static/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/dist/static/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/dist/static/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/dist/static/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/dist/static/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/dist/static/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/dist/static/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/dist/static/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/dist/static/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/dist/static/assets/_baseUniq-Crfl3d5Y.js +661 -0
- package/dist/static/assets/_baseUniq-Crfl3d5Y.js.map +1 -0
- package/dist/static/assets/arc-CbA_x9GD.js +132 -0
- package/dist/static/assets/arc-CbA_x9GD.js.map +1 -0
- package/dist/static/assets/architectureDiagram-VXUJARFQ-lcFS8ZQJ.js +8685 -0
- package/dist/static/assets/architectureDiagram-VXUJARFQ-lcFS8ZQJ.js.map +1 -0
- package/dist/static/assets/blockDiagram-VD42YOAC-B3Q36qRc.js +3608 -0
- package/dist/static/assets/blockDiagram-VD42YOAC-B3Q36qRc.js.map +1 -0
- package/dist/static/assets/c4Diagram-YG6GDRKO-Mt-aq3VH.js +2482 -0
- package/dist/static/assets/c4Diagram-YG6GDRKO-Mt-aq3VH.js.map +1 -0
- package/dist/static/assets/channel-BVr1Yke-.js +8 -0
- package/dist/static/assets/channel-BVr1Yke-.js.map +1 -0
- package/dist/static/assets/chunk-4BX2VUAB-qCIn5Iic.js +17 -0
- package/dist/static/assets/chunk-4BX2VUAB-qCIn5Iic.js.map +1 -0
- package/dist/static/assets/chunk-55IACEB6-q172NeCV.js +14 -0
- package/dist/static/assets/chunk-55IACEB6-q172NeCV.js.map +1 -0
- package/dist/static/assets/chunk-B4BG7PRW-CMJmtYzq.js +1827 -0
- package/dist/static/assets/chunk-B4BG7PRW-CMJmtYzq.js.map +1 -0
- package/dist/static/assets/chunk-DI55MBZ5-DiuwwZPL.js +1916 -0
- package/dist/static/assets/chunk-DI55MBZ5-DiuwwZPL.js.map +1 -0
- package/dist/static/assets/chunk-FMBD7UC4-06sqZTTn.js +20 -0
- package/dist/static/assets/chunk-FMBD7UC4-06sqZTTn.js.map +1 -0
- package/dist/static/assets/chunk-QN33PNHL-CnpBNkpP.js +25 -0
- package/dist/static/assets/chunk-QN33PNHL-CnpBNkpP.js.map +1 -0
- package/dist/static/assets/chunk-QZHKN3VN-CNgjMR-e.js +18 -0
- package/dist/static/assets/chunk-QZHKN3VN-CNgjMR-e.js.map +1 -0
- package/dist/static/assets/chunk-TZMSLE5B-BxtzW6--.js +109 -0
- package/dist/static/assets/chunk-TZMSLE5B-BxtzW6--.js.map +1 -0
- package/dist/static/assets/classDiagram-2ON5EDUG-29huvmn-.js +23 -0
- package/dist/static/assets/classDiagram-2ON5EDUG-29huvmn-.js.map +1 -0
- package/dist/static/assets/classDiagram-v2-WZHVMYZB-29huvmn-.js +23 -0
- package/dist/static/assets/classDiagram-v2-WZHVMYZB-29huvmn-.js.map +1 -0
- package/dist/static/assets/clone-D2OgLSSn.js +9 -0
- package/dist/static/assets/clone-D2OgLSSn.js.map +1 -0
- package/dist/static/assets/cose-bilkent-S5V4N54A-BNegDCxl.js +4943 -0
- package/dist/static/assets/cose-bilkent-S5V4N54A-BNegDCxl.js.map +1 -0
- package/dist/static/assets/cytoscape.esm-Bm8DJGmZ.js +30240 -0
- package/dist/static/assets/cytoscape.esm-Bm8DJGmZ.js.map +1 -0
- package/dist/static/assets/dagre-6UL2VRFP-f1XrTRSn.js +695 -0
- package/dist/static/assets/dagre-6UL2VRFP-f1XrTRSn.js.map +1 -0
- package/dist/static/assets/defaultLocale-DVr69WTU.js +207 -0
- package/dist/static/assets/defaultLocale-DVr69WTU.js.map +1 -0
- package/dist/static/assets/diagram-PSM6KHXK-8w1WbeDi.js +849 -0
- package/dist/static/assets/diagram-PSM6KHXK-8w1WbeDi.js.map +1 -0
- package/dist/static/assets/diagram-QEK2KX5R-CF4wtMmR.js +303 -0
- package/dist/static/assets/diagram-QEK2KX5R-CF4wtMmR.js.map +1 -0
- package/dist/static/assets/diagram-S2PKOQOG-8p3Avgn2.js +213 -0
- package/dist/static/assets/diagram-S2PKOQOG-8p3Avgn2.js.map +1 -0
- package/dist/static/assets/erDiagram-Q2GNP2WA-BMKLxlM9.js +1159 -0
- package/dist/static/assets/erDiagram-Q2GNP2WA-BMKLxlM9.js.map +1 -0
- package/dist/static/assets/favicon-Cmg5RbCj.svg +8 -0
- package/dist/static/assets/flowDiagram-NV44I4VS-CgEuPNK2.js +2332 -0
- package/dist/static/assets/flowDiagram-NV44I4VS-CgEuPNK2.js.map +1 -0
- package/dist/static/assets/ganttDiagram-JELNMOA3-bJkDCf-9.js +3681 -0
- package/dist/static/assets/ganttDiagram-JELNMOA3-bJkDCf-9.js.map +1 -0
- package/dist/static/assets/gitGraphDiagram-NY62KEGX-4QE9kesp.js +1206 -0
- package/dist/static/assets/gitGraphDiagram-NY62KEGX-4QE9kesp.js.map +1 -0
- package/dist/static/assets/graph-CS0Pmm7c.js +597 -0
- package/dist/static/assets/graph-CS0Pmm7c.js.map +1 -0
- package/dist/static/assets/index-BS6HnGzC.js +112303 -0
- package/dist/static/assets/index-BS6HnGzC.js.map +1 -0
- package/dist/static/assets/index-DaIsSzC_.css +483 -0
- package/dist/static/assets/infoDiagram-WHAUD3N6-ypBcKfUs.js +34 -0
- package/dist/static/assets/infoDiagram-WHAUD3N6-ypBcKfUs.js.map +1 -0
- package/dist/static/assets/init-ZxktEp_H.js +17 -0
- package/dist/static/assets/init-ZxktEp_H.js.map +1 -0
- package/dist/static/assets/journeyDiagram-XKPGCS4Q-QnrxDowJ.js +1255 -0
- package/dist/static/assets/journeyDiagram-XKPGCS4Q-QnrxDowJ.js.map +1 -0
- package/dist/static/assets/kanban-definition-3W4ZIXB7-CfvEc4z5.js +1048 -0
- package/dist/static/assets/kanban-definition-3W4ZIXB7-CfvEc4z5.js.map +1 -0
- package/dist/static/assets/layout-8TGxpm23.js +2218 -0
- package/dist/static/assets/layout-8TGxpm23.js.map +1 -0
- package/dist/static/assets/linear-BATBPQQv.js +341 -0
- package/dist/static/assets/linear-BATBPQQv.js.map +1 -0
- package/dist/static/assets/min-B3oVH3AC.js +42 -0
- package/dist/static/assets/min-B3oVH3AC.js.map +1 -0
- package/dist/static/assets/mindmap-definition-VGOIOE7T-L7VLwwF8.js +1127 -0
- package/dist/static/assets/mindmap-definition-VGOIOE7T-L7VLwwF8.js.map +1 -0
- package/dist/static/assets/ordinal-CxptdPJm.js +77 -0
- package/dist/static/assets/ordinal-CxptdPJm.js.map +1 -0
- package/dist/static/assets/pieDiagram-ADFJNKIX-CFW3zIhM.js +241 -0
- package/dist/static/assets/pieDiagram-ADFJNKIX-CFW3zIhM.js.map +1 -0
- package/dist/static/assets/quadrantDiagram-AYHSOK5B-B7ssen3E.js +1338 -0
- package/dist/static/assets/quadrantDiagram-AYHSOK5B-B7ssen3E.js.map +1 -0
- package/dist/static/assets/requirementDiagram-UZGBJVZJ-D0v5BArv.js +1162 -0
- package/dist/static/assets/requirementDiagram-UZGBJVZJ-D0v5BArv.js.map +1 -0
- package/dist/static/assets/sankeyDiagram-TZEHDZUN-B7slncJe.js +1195 -0
- package/dist/static/assets/sankeyDiagram-TZEHDZUN-B7slncJe.js.map +1 -0
- package/dist/static/assets/sequenceDiagram-WL72ISMW-oXU2lRh_.js +3875 -0
- package/dist/static/assets/sequenceDiagram-WL72ISMW-oXU2lRh_.js.map +1 -0
- package/dist/static/assets/stateDiagram-FKZM4ZOC-CFYsEd0x.js +452 -0
- package/dist/static/assets/stateDiagram-FKZM4ZOC-CFYsEd0x.js.map +1 -0
- package/dist/static/assets/stateDiagram-v2-4FDKWEC3-C0UWaNA7.js +22 -0
- package/dist/static/assets/stateDiagram-v2-4FDKWEC3-C0UWaNA7.js.map +1 -0
- package/dist/static/assets/timeline-definition-IT6M3QCI-C3KODUrh.js +1223 -0
- package/dist/static/assets/timeline-definition-IT6M3QCI-C3KODUrh.js.map +1 -0
- package/dist/static/assets/treemap-KMMF4GRG-DAGDLhj2.js +18753 -0
- package/dist/static/assets/treemap-KMMF4GRG-DAGDLhj2.js.map +1 -0
- package/dist/static/assets/xychartDiagram-PRI3JC2R-C0J9iwTO.js +1888 -0
- package/dist/static/assets/xychartDiagram-PRI3JC2R-C0J9iwTO.js.map +1 -0
- package/dist/static/index.html +71 -0
- package/dist/static/testing/dom-observation-utils.js +425 -0
- package/dist/static/testing/e2e-test-helper.js +3119 -0
- package/dist/team.js +1160 -0
- package/dist/tellask.js +431 -0
- package/dist/tool.js +150 -0
- package/dist/tools/apply-patch.js +542 -0
- package/dist/tools/builtins.js +196 -0
- package/dist/tools/context-health.js +177 -0
- package/dist/tools/ctrl.js +478 -0
- package/dist/tools/diag.js +583 -0
- package/dist/tools/env.js +184 -0
- package/dist/tools/fs.js +818 -0
- package/dist/tools/mcp.js +138 -0
- package/dist/tools/mem.js +349 -0
- package/dist/tools/os.js +751 -0
- package/dist/tools/prompts/team_mgmt.en.md +70 -0
- package/dist/tools/prompts/team_mgmt.zh.md +70 -0
- package/dist/tools/prompts/ws_mod.en.md +86 -0
- package/dist/tools/prompts/ws_mod.zh.md +87 -0
- package/dist/tools/registry-snapshot.js +31 -0
- package/dist/tools/registry.js +121 -0
- package/dist/tools/ripgrep.js +678 -0
- package/dist/tools/team-mgmt.js +3300 -0
- package/dist/tools/txt.js +3178 -0
- package/dist/utils/id.js +72 -0
- package/dist/utils/task-doc.js +236 -0
- package/dist/utils/task-package.js +522 -0
- package/dist/utils/taskdoc-search.js +280 -0
- package/dist/utils/taskdoc.js +400 -0
- package/package.json +69 -0
package/dist/server.js
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.startServer = startServer;
|
|
37
|
+
/**
|
|
38
|
+
* Module: server
|
|
39
|
+
*
|
|
40
|
+
* HTTP/WebSocket server for both development and production modes:
|
|
41
|
+
* - Serves static files with MIME detection and SPA fallback (production)
|
|
42
|
+
* - Provides `/api/*` endpoints and `/ws` WebSocket communication
|
|
43
|
+
* - CLI bootstrap with optional cwd/port/host/mode parameters
|
|
44
|
+
* - Development mode: `tsx --watch src/server.ts -p 5556 --mode dev`
|
|
45
|
+
* - Production mode: `node dist/server.js` (default port 5666)
|
|
46
|
+
*/
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const dialog_run_state_1 = require("./dialog-run-state");
|
|
49
|
+
const driver_1 = require("./llm/driver");
|
|
50
|
+
const log_1 = require("./log");
|
|
51
|
+
const supervisor_1 = require("./mcp/supervisor");
|
|
52
|
+
const auth_1 = require("./server/auth");
|
|
53
|
+
const server_core_1 = require("./server/server-core");
|
|
54
|
+
const websocket_handler_1 = require("./server/websocket-handler");
|
|
55
|
+
const runtime_language_1 = require("./shared/runtime-language");
|
|
56
|
+
require("./tools/builtins");
|
|
57
|
+
const log = (0, log_1.createLogger)('server');
|
|
58
|
+
// Setup unhandled rejection handler to capture crashes
|
|
59
|
+
process.on('unhandledRejection', (reason, promise) => {
|
|
60
|
+
log.error('Unhandled Rejection at:', promise);
|
|
61
|
+
log.error('Reason:', reason instanceof Error ? reason : new Error(String(reason)));
|
|
62
|
+
log.error('Stack trace:', (reason instanceof Error && reason.stack) || 'No stack trace available');
|
|
63
|
+
// Optionally, we could exit the process here with code 1
|
|
64
|
+
// But in development, we might want to keep running
|
|
65
|
+
});
|
|
66
|
+
// Setup uncaught exception handler
|
|
67
|
+
process.on('uncaughtException', (error) => {
|
|
68
|
+
log.error('Uncaught Exception:', error);
|
|
69
|
+
log.error('Stack trace:', error.stack);
|
|
70
|
+
// Optionally, exit with code 1
|
|
71
|
+
// process.exit(1);
|
|
72
|
+
});
|
|
73
|
+
function parseArgs(argv) {
|
|
74
|
+
const out = {};
|
|
75
|
+
for (let i = 0; i < argv.length; i++) {
|
|
76
|
+
const a = argv[i];
|
|
77
|
+
if (a === '-C' || a === '--chdir') {
|
|
78
|
+
out['C'] = argv[i + 1];
|
|
79
|
+
i++;
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (a === '-p' || a === '--port') {
|
|
83
|
+
out['p'] = argv[i + 1];
|
|
84
|
+
i++;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (a === '-H' || a === '--host') {
|
|
88
|
+
out['H'] = argv[i + 1];
|
|
89
|
+
i++;
|
|
90
|
+
continue;
|
|
91
|
+
}
|
|
92
|
+
if (a === '--mode') {
|
|
93
|
+
out['mode'] = argv[i + 1];
|
|
94
|
+
i++;
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return out;
|
|
99
|
+
}
|
|
100
|
+
async function startServer(opts = {}) {
|
|
101
|
+
const { language: resolvedLanguage, source } = (0, runtime_language_1.resolveWorkLanguage)({ env: process.env });
|
|
102
|
+
(0, runtime_language_1.setWorkLanguage)(resolvedLanguage);
|
|
103
|
+
// Get port and host from options
|
|
104
|
+
const port = opts.port || (opts.mode === 'dev' ? 5556 : 5666);
|
|
105
|
+
const host = opts.host || '127.0.0.1';
|
|
106
|
+
const mode = opts.mode || 'prod';
|
|
107
|
+
log.info(`Starting server in ${mode} mode on ${host}:${port} (working language: ${(0, runtime_language_1.getWorkLanguage)()} from ${source})`);
|
|
108
|
+
// WebSocket clients set
|
|
109
|
+
const clients = new Set();
|
|
110
|
+
// Create server configuration
|
|
111
|
+
const config = {
|
|
112
|
+
mode: mode === 'dev' ? 'development' : 'production',
|
|
113
|
+
staticRoot: 'dist/static',
|
|
114
|
+
host,
|
|
115
|
+
port,
|
|
116
|
+
clients,
|
|
117
|
+
auth: (0, auth_1.computeAuthConfig)({
|
|
118
|
+
mode: mode === 'dev' ? 'development' : 'production',
|
|
119
|
+
env: process.env,
|
|
120
|
+
}),
|
|
121
|
+
};
|
|
122
|
+
const auth = config.auth ?? { kind: 'disabled' };
|
|
123
|
+
// Create HTTP server
|
|
124
|
+
const httpServer = (0, server_core_1.createHttpServer)(config);
|
|
125
|
+
// Setup WebSocket server
|
|
126
|
+
(0, websocket_handler_1.setupWebSocketServer)(httpServer.getHttpServer(), clients, config.auth ?? { kind: 'disabled' }, (0, runtime_language_1.getWorkLanguage)());
|
|
127
|
+
// MCP is best-effort: startup must not be blocked by MCP config/server issues.
|
|
128
|
+
(0, supervisor_1.startMcpSupervisor)();
|
|
129
|
+
// Crash recovery: any dialogs left in "proceeding" state are surfaced as interrupted/resumable.
|
|
130
|
+
await (0, dialog_run_state_1.reconcileRunStatesAfterRestart)();
|
|
131
|
+
// Start backend driver loop (non-blocking)
|
|
132
|
+
void (0, driver_1.runBackendDriver)();
|
|
133
|
+
// Start listening
|
|
134
|
+
await httpServer.start();
|
|
135
|
+
return { httpServer, auth, host, port, mode };
|
|
136
|
+
}
|
|
137
|
+
// Main function for CLI execution
|
|
138
|
+
async function main() {
|
|
139
|
+
const cliArgs = parseArgs(process.argv.slice(2));
|
|
140
|
+
// Handle working directory change from -C flag
|
|
141
|
+
const wsDir = cliArgs['C'];
|
|
142
|
+
if (wsDir) {
|
|
143
|
+
// Resolve to absolute path before changing directory
|
|
144
|
+
const absoluteWsDir = path.isAbsolute(wsDir) ? wsDir : path.resolve(process.cwd(), wsDir);
|
|
145
|
+
try {
|
|
146
|
+
process.chdir(wsDir);
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
log.warn(`Failed to change working directory to ${wsDir}:`, err);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
// Get port, host, and mode from CLI args
|
|
153
|
+
const port = cliArgs['p'] ? Number(cliArgs['p']) : undefined;
|
|
154
|
+
const host = cliArgs['H'] || undefined;
|
|
155
|
+
const mode = cliArgs['mode'] || undefined;
|
|
156
|
+
await startServer({ port, host, mode });
|
|
157
|
+
}
|
|
158
|
+
// Start server if this file is run directly
|
|
159
|
+
if (require.main === module) {
|
|
160
|
+
main().catch((error) => {
|
|
161
|
+
log.error('Web UI startup failed', error);
|
|
162
|
+
process.exit(1);
|
|
163
|
+
});
|
|
164
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AsyncFifoMutex = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Async FIFO mutex (fair queue).
|
|
6
|
+
*
|
|
7
|
+
* Used for per-dialog and per-dialog-tree critical sections, keyed by dialog ID.
|
|
8
|
+
*/
|
|
9
|
+
class AsyncFifoMutex {
|
|
10
|
+
constructor() {
|
|
11
|
+
this.locked = false;
|
|
12
|
+
this.waiters = [];
|
|
13
|
+
}
|
|
14
|
+
async acquire() {
|
|
15
|
+
if (!this.locked) {
|
|
16
|
+
this.locked = true;
|
|
17
|
+
return () => this.release();
|
|
18
|
+
}
|
|
19
|
+
await new Promise((resolve) => {
|
|
20
|
+
this.waiters.push(resolve);
|
|
21
|
+
});
|
|
22
|
+
return () => this.release();
|
|
23
|
+
}
|
|
24
|
+
isLocked() {
|
|
25
|
+
return this.locked;
|
|
26
|
+
}
|
|
27
|
+
release() {
|
|
28
|
+
const next = this.waiters.shift();
|
|
29
|
+
if (next) {
|
|
30
|
+
next();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
this.locked = false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
exports.AsyncFifoMutex = AsyncFifoMutex;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DILIGENCE_FALLBACK_TEXT = exports.DEFAULT_DILIGENCE_PUSH_MAX = void 0;
|
|
4
|
+
exports.DEFAULT_DILIGENCE_PUSH_MAX = 3;
|
|
5
|
+
exports.DILIGENCE_FALLBACK_TEXT = {
|
|
6
|
+
zh: [
|
|
7
|
+
'除非确实需要人类用户介入,请继续你的工作。',
|
|
8
|
+
'',
|
|
9
|
+
'作为智能体团队成员,你该诉请(`!?@<teammate-callsign>`)队友完成的事儿千万别自己干,你自己的事儿能自己动手推进的就绝不要麻烦人类。',
|
|
10
|
+
'',
|
|
11
|
+
'不该或者不能自主继续工作时,你应该使用 `!?@human` 诉请人类确认相关问题或者指出工作方向。',
|
|
12
|
+
].join('\n'),
|
|
13
|
+
en: [
|
|
14
|
+
'Unless you truly need the human user to intervene, keep working.',
|
|
15
|
+
'',
|
|
16
|
+
'As an agent team member: if it’s something you should ask a teammate (`!?@<teammate-callsign>`) to do, do not do it yourself; and for things you can advance on your own, do not bother the human.',
|
|
17
|
+
'',
|
|
18
|
+
'When you should not or cannot continue autonomously, use `!?@human` to ask the human to confirm the relevant questions or provide direction.',
|
|
19
|
+
].join('\n'),
|
|
20
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.loadRtwsDotenv = loadRtwsDotenv;
|
|
37
|
+
const fs = __importStar(require("fs"));
|
|
38
|
+
const path = __importStar(require("path"));
|
|
39
|
+
function isEnvKeyValid(key) {
|
|
40
|
+
return /^[A-Za-z_][A-Za-z0-9_]*$/.test(key);
|
|
41
|
+
}
|
|
42
|
+
function unescapeDoubleQuoted(value) {
|
|
43
|
+
let out = '';
|
|
44
|
+
for (let i = 0; i < value.length; i++) {
|
|
45
|
+
const ch = value[i];
|
|
46
|
+
if (ch !== '\\') {
|
|
47
|
+
out += ch;
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const next = value[i + 1];
|
|
51
|
+
if (next === undefined) {
|
|
52
|
+
out += '\\';
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
i++;
|
|
56
|
+
if (next === 'n')
|
|
57
|
+
out += '\n';
|
|
58
|
+
else if (next === 'r')
|
|
59
|
+
out += '\r';
|
|
60
|
+
else if (next === 't')
|
|
61
|
+
out += '\t';
|
|
62
|
+
else if (next === '\\')
|
|
63
|
+
out += '\\';
|
|
64
|
+
else if (next === '"')
|
|
65
|
+
out += '"';
|
|
66
|
+
else
|
|
67
|
+
out += next;
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
function stripInlineCommentFromUnquotedValue(raw) {
|
|
72
|
+
// Strip `# ...` only when it is preceded by whitespace.
|
|
73
|
+
for (let i = 0; i < raw.length; i++) {
|
|
74
|
+
const ch = raw[i];
|
|
75
|
+
if (ch !== '#')
|
|
76
|
+
continue;
|
|
77
|
+
if (i === 0)
|
|
78
|
+
return '';
|
|
79
|
+
const prev = raw[i - 1];
|
|
80
|
+
if (prev === ' ' || prev === '\t')
|
|
81
|
+
return raw.slice(0, i).trimEnd();
|
|
82
|
+
}
|
|
83
|
+
return raw.trimEnd();
|
|
84
|
+
}
|
|
85
|
+
function parseLine(line) {
|
|
86
|
+
const trimmed = line.trim();
|
|
87
|
+
if (trimmed.length === 0)
|
|
88
|
+
return { kind: 'skip' };
|
|
89
|
+
if (trimmed.startsWith('#'))
|
|
90
|
+
return { kind: 'skip' };
|
|
91
|
+
const withoutExport = trimmed.startsWith('export ')
|
|
92
|
+
? trimmed.slice('export '.length).trim()
|
|
93
|
+
: trimmed;
|
|
94
|
+
const equalsIndex = withoutExport.indexOf('=');
|
|
95
|
+
if (equalsIndex < 0)
|
|
96
|
+
return { kind: 'error', reason: 'missing_equals' };
|
|
97
|
+
const rawKey = withoutExport.slice(0, equalsIndex).trim();
|
|
98
|
+
if (rawKey.length === 0)
|
|
99
|
+
return { kind: 'error', reason: 'empty_key' };
|
|
100
|
+
if (!isEnvKeyValid(rawKey))
|
|
101
|
+
return { kind: 'error', reason: 'invalid_key' };
|
|
102
|
+
let rawValue = withoutExport.slice(equalsIndex + 1).trim();
|
|
103
|
+
if (rawValue.length >= 2 && rawValue.startsWith('"') && rawValue.endsWith('"')) {
|
|
104
|
+
rawValue = unescapeDoubleQuoted(rawValue.slice(1, -1));
|
|
105
|
+
}
|
|
106
|
+
else if (rawValue.length >= 2 && rawValue.startsWith("'") && rawValue.endsWith("'")) {
|
|
107
|
+
rawValue = rawValue.slice(1, -1);
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
rawValue = stripInlineCommentFromUnquotedValue(rawValue);
|
|
111
|
+
}
|
|
112
|
+
return { kind: 'entry', key: rawKey, value: rawValue };
|
|
113
|
+
}
|
|
114
|
+
function loadRtwsDotenv(params) {
|
|
115
|
+
const cwd = params && typeof params.cwd === 'string' ? params.cwd : process.cwd();
|
|
116
|
+
const files = ['.env', '.env.local'];
|
|
117
|
+
const loadedFiles = [];
|
|
118
|
+
const errors = [];
|
|
119
|
+
for (const file of files) {
|
|
120
|
+
const absPath = path.join(cwd, file);
|
|
121
|
+
if (!fs.existsSync(absPath))
|
|
122
|
+
continue;
|
|
123
|
+
loadedFiles.push(file);
|
|
124
|
+
const content = fs.readFileSync(absPath, 'utf8');
|
|
125
|
+
const lines = content.split(/\r?\n/);
|
|
126
|
+
for (let i = 0; i < lines.length; i++) {
|
|
127
|
+
const raw = lines[i];
|
|
128
|
+
const parsed = parseLine(raw);
|
|
129
|
+
if (parsed.kind === 'skip')
|
|
130
|
+
continue;
|
|
131
|
+
if (parsed.kind === 'error') {
|
|
132
|
+
errors.push({ file, lineNumber: i + 1, raw, reason: parsed.reason });
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
if (parsed.kind === 'entry') {
|
|
136
|
+
process.env[parsed.key] = parsed.value;
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const _exhaustive = parsed;
|
|
140
|
+
throw new Error(`Unexpected dotenv parse result: ${String(_exhaustive)}`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return { cwd, loadedFiles, errors };
|
|
144
|
+
}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Event processing constructs equivalent to Edh's:
|
|
4
|
+
* - PubChan: write-only broadcast channel
|
|
5
|
+
* - SubChan: read-only subscriber channel
|
|
6
|
+
* - EventSink: event source with sequence and most-recent value, streaming support
|
|
7
|
+
*
|
|
8
|
+
* Notes:
|
|
9
|
+
* - PubChan behaves like a broadcast channel: if there is no SubChan reading, writes are effectively dropped
|
|
10
|
+
* - SubChan buffers unboundedly relative to its own consumption speed
|
|
11
|
+
* - EndOfStream sentinel signals termination of streams
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.EventSink = exports.SubChan = exports.PubChan = exports.EndOfStream = void 0;
|
|
15
|
+
exports.createPubChan = createPubChan;
|
|
16
|
+
exports.createSubChan = createSubChan;
|
|
17
|
+
exports.createEventSink = createEventSink;
|
|
18
|
+
exports.EndOfStream = Symbol('EndOfStream');
|
|
19
|
+
/**
|
|
20
|
+
* A small "deferred" helper to build a promise that can be resolved externally.
|
|
21
|
+
*/
|
|
22
|
+
function deferred() {
|
|
23
|
+
let resolve;
|
|
24
|
+
const promise = new Promise((res) => {
|
|
25
|
+
resolve = res;
|
|
26
|
+
});
|
|
27
|
+
return { promise, resolve };
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* PubChan: publisher's write-only channel.
|
|
31
|
+
* Internally maintains a linked list of deferred promises to form a stream.
|
|
32
|
+
*/
|
|
33
|
+
class PubChan {
|
|
34
|
+
constructor() {
|
|
35
|
+
// The head of the chain: a deferred whose promise yields [ev, nextPromise]
|
|
36
|
+
this.nxt = deferred();
|
|
37
|
+
this.writes = 0;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Write an event into the channel.
|
|
41
|
+
* Subsequent readers will observe it in order.
|
|
42
|
+
*/
|
|
43
|
+
write(ev) {
|
|
44
|
+
const next = deferred();
|
|
45
|
+
// Resolve current node with [event, nextPromise], then advance head
|
|
46
|
+
this.nxt.resolve([ev, next.promise]);
|
|
47
|
+
this.nxt = next;
|
|
48
|
+
this.writes += 1;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Expose current next promise for SubChan to adopt.
|
|
52
|
+
* Consumers should typically not use this directly.
|
|
53
|
+
*/
|
|
54
|
+
get nextPromise() {
|
|
55
|
+
return this.nxt.promise;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.PubChan = PubChan;
|
|
59
|
+
/**
|
|
60
|
+
* SubChan: subscriber's read-only channel.
|
|
61
|
+
* Holds its own pointer into the shared stream chain, thus buffering
|
|
62
|
+
* independently of other subscribers.
|
|
63
|
+
*/
|
|
64
|
+
class SubChan {
|
|
65
|
+
constructor(pub) {
|
|
66
|
+
this.reads = 0;
|
|
67
|
+
this.nxtP = pub.nextPromise;
|
|
68
|
+
const cancelDefer = deferred();
|
|
69
|
+
this.cancelled = cancelDefer.promise;
|
|
70
|
+
this.cancel = () => cancelDefer.resolve();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Read the next available value (could be EndOfStream).
|
|
74
|
+
* Caller may check ev === EndOfStream to detect eos.
|
|
75
|
+
*/
|
|
76
|
+
async read() {
|
|
77
|
+
// If cancelled, return EndOfStream immediately
|
|
78
|
+
const raceResult = await Promise.race([this.cancelled, this.nxtP]);
|
|
79
|
+
if (raceResult === undefined) {
|
|
80
|
+
return exports.EndOfStream;
|
|
81
|
+
}
|
|
82
|
+
const [ev, nextP] = raceResult;
|
|
83
|
+
this.nxtP = nextP;
|
|
84
|
+
this.reads += 1;
|
|
85
|
+
return ev;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Async iterator over values until EndOfStream or cancellation.
|
|
89
|
+
*/
|
|
90
|
+
stream() {
|
|
91
|
+
let nxtP = this.nxtP;
|
|
92
|
+
return (async function* (self) {
|
|
93
|
+
// eslint-disable-next-line no-constant-condition
|
|
94
|
+
while (true) {
|
|
95
|
+
const result = await Promise.race([self.cancelled, nxtP]);
|
|
96
|
+
// If cancelled (undefined), return immediately
|
|
97
|
+
if (result === undefined) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const [ev, nextP] = result;
|
|
101
|
+
nxtP = self.nxtP = nextP;
|
|
102
|
+
if (ev === exports.EndOfStream)
|
|
103
|
+
return;
|
|
104
|
+
yield ev;
|
|
105
|
+
}
|
|
106
|
+
})(this);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
exports.SubChan = SubChan;
|
|
110
|
+
/**
|
|
111
|
+
* EventSink: holds sequence, most recent value, and a PubChan.
|
|
112
|
+
* Provides stream(), one_more(), and run_producer() helpers.
|
|
113
|
+
*/
|
|
114
|
+
class EventSink {
|
|
115
|
+
constructor() {
|
|
116
|
+
this.seqn = 0;
|
|
117
|
+
this.mrv = null;
|
|
118
|
+
this.chan = new PubChan();
|
|
119
|
+
}
|
|
120
|
+
get eos() {
|
|
121
|
+
return this.mrv === exports.EndOfStream;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Publish an event. Increments sequence (wraps int64 max to 1).
|
|
125
|
+
* Ignores repeated EndOfStream publications after the first one.
|
|
126
|
+
*/
|
|
127
|
+
publish(ev) {
|
|
128
|
+
if (ev === exports.EndOfStream && this.mrv === exports.EndOfStream) {
|
|
129
|
+
// Already published EndOfStream, ignore repeated attempts
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (this.seqn >= 9223372036854775807) {
|
|
133
|
+
this.seqn = 1;
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
this.seqn += 1;
|
|
137
|
+
}
|
|
138
|
+
this.mrv = ev;
|
|
139
|
+
this.chan.write(ev);
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Await exactly one more item from the stream unless already at eos.
|
|
143
|
+
* If already eos after at least one event, returns EndOfStream immediately.
|
|
144
|
+
*/
|
|
145
|
+
async one_more() {
|
|
146
|
+
if (this.seqn > 0 && this.mrv === exports.EndOfStream) {
|
|
147
|
+
return exports.EndOfStream;
|
|
148
|
+
}
|
|
149
|
+
// Peek the next from channel's head
|
|
150
|
+
const [ev] = await this.chan.nextPromise;
|
|
151
|
+
return ev;
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Async iterator: yields the most recent value first (if any and not eos),
|
|
155
|
+
* then continues with subsequent events until EndOfStream.
|
|
156
|
+
*/
|
|
157
|
+
stream() {
|
|
158
|
+
// Capture stream state at call time: capture the current most recent value and
|
|
159
|
+
// promise chain position immediately when this method is invoked. This prevents
|
|
160
|
+
// race conditions where events could be missed if we captured state when the
|
|
161
|
+
// returned generator starts iterating (which might be much later).
|
|
162
|
+
const yield1st = this.mrv;
|
|
163
|
+
const shouldYield1st = this.seqn > 0;
|
|
164
|
+
let nxtP = this.chan.nextPromise;
|
|
165
|
+
return (async function* () {
|
|
166
|
+
if (shouldYield1st) {
|
|
167
|
+
if (yield1st === exports.EndOfStream)
|
|
168
|
+
return;
|
|
169
|
+
// yield the most recent first
|
|
170
|
+
yield yield1st;
|
|
171
|
+
}
|
|
172
|
+
// eslint-disable-next-line no-constant-condition
|
|
173
|
+
while (true) {
|
|
174
|
+
const [ev, nextP] = await Promise.resolve(nxtP);
|
|
175
|
+
if (ev === exports.EndOfStream)
|
|
176
|
+
return;
|
|
177
|
+
yield ev;
|
|
178
|
+
nxtP = nextP;
|
|
179
|
+
}
|
|
180
|
+
})();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
exports.EventSink = EventSink;
|
|
184
|
+
/**
|
|
185
|
+
* Helpers to create channels/sinks
|
|
186
|
+
*/
|
|
187
|
+
function createPubChan() {
|
|
188
|
+
return new PubChan();
|
|
189
|
+
}
|
|
190
|
+
function createSubChan(pub) {
|
|
191
|
+
return new SubChan(pub);
|
|
192
|
+
}
|
|
193
|
+
function createEventSink() {
|
|
194
|
+
return new EventSink();
|
|
195
|
+
}
|