dominds 1.2.5 → 1.2.7
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/agent-priming.js +2051 -0
- package/dist/apps/app-lock-file.js +228 -0
- package/dist/apps/assigned-port.js +124 -0
- package/dist/apps/enabled-apps.js +472 -7
- package/dist/apps/manifest.js +37 -0
- package/dist/apps/override-paths.js +19 -6
- package/dist/apps/problems.js +43 -0
- package/dist/apps/resolution-file.js +370 -0
- package/dist/apps/runtime.js +5 -17
- package/dist/apps/teammates.js +102 -1
- package/dist/cli/disable.js +10 -6
- package/dist/cli/enable.js +21 -19
- package/dist/cli/install.js +40 -18
- package/dist/cli/uninstall.js +6 -6
- package/dist/cli/update.js +38 -13
- package/dist/dialog.js +5 -0
- package/dist/docs/app-constitution.md +85 -18
- package/dist/docs/app-constitution.zh.md +86 -21
- package/dist/docs/dialog-system.md +1 -1
- package/dist/docs/dialog-system.zh.md +1 -1
- package/dist/docs/dominds-agent-priming.md +218 -0
- package/dist/docs/dominds-agent-priming.zh.md +196 -0
- package/dist/docs/drive-logic-context-refactor-plan.zh.md +338 -0
- package/dist/docs/keep-going.md +176 -0
- package/dist/docs/keep-going.zh.md +162 -0
- package/dist/docs/showing-by-doing.md +208 -0
- package/dist/docs/showing-by-doing.zh.md +177 -0
- package/dist/docs/team-mgmt-toolset.md +482 -0
- package/dist/docs/team-mgmt-toolset.zh.md +426 -0
- package/dist/llm/defaults.yaml +1 -1
- package/dist/llm/driver.js +4093 -0
- package/dist/llm/kernel-driver/drive.js +5 -2
- package/dist/llm/kernel-driver/flow.js +3 -0
- package/dist/minds/promptdocs.js +263 -0
- package/dist/problems.js +67 -16
- package/dist/server/api-routes.js +333 -0
- package/dist/server/prompts-routes.js +545 -0
- package/dist/server/server-core.js +4 -0
- package/dist/server/websocket-handler.js +17 -0
- package/dist/shared/team-mgmt-manual.js +120 -0
- package/dist/shared/types/prompts.js +2 -0
- package/dist/shared/types/tellask.js +8 -0
- package/dist/showing-by-doing.js +1091 -0
- package/dist/snippets/README.en.md +3 -0
- package/dist/snippets/README.md +4 -0
- package/dist/static/assets/{_basePickBy-CF9r08iy.js → _basePickBy-BMCtwrV7.js} +3 -3
- package/dist/static/assets/{_basePickBy-CF9r08iy.js.map → _basePickBy-BMCtwrV7.js.map} +1 -1
- package/dist/static/assets/{_baseUniq-CxKv0cd4.js → _baseUniq-BuyCgJiA.js} +2 -2
- package/dist/static/assets/{_baseUniq-CxKv0cd4.js.map → _baseUniq-BuyCgJiA.js.map} +1 -1
- package/dist/static/assets/{arc-C9JyvnlB.js → arc-BDuN8lwA.js} +2 -2
- package/dist/static/assets/{arc-C9JyvnlB.js.map → arc-BDuN8lwA.js.map} +1 -1
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-CpcUgjHf.js → architectureDiagram-VXUJARFQ-C-ekqGAD.js} +7 -7
- package/dist/static/assets/{architectureDiagram-VXUJARFQ-CpcUgjHf.js.map → architectureDiagram-VXUJARFQ-C-ekqGAD.js.map} +1 -1
- package/dist/static/assets/{blockDiagram-VD42YOAC-BA9vtmm7.js → blockDiagram-VD42YOAC-CgQiNuuQ.js} +7 -7
- package/dist/static/assets/{blockDiagram-VD42YOAC-BA9vtmm7.js.map → blockDiagram-VD42YOAC-CgQiNuuQ.js.map} +1 -1
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D49MGNdF.js → c4Diagram-YG6GDRKO-DONC39q-.js} +3 -3
- package/dist/static/assets/{c4Diagram-YG6GDRKO-D49MGNdF.js.map → c4Diagram-YG6GDRKO-DONC39q-.js.map} +1 -1
- package/dist/static/assets/{channel-B4KzL0Kg.js → channel-CJTFwXIG.js} +2 -2
- package/dist/static/assets/{channel-B4KzL0Kg.js.map → channel-CJTFwXIG.js.map} +1 -1
- package/dist/static/assets/{chunk-4BX2VUAB-0F-1ayl0.js → chunk-4BX2VUAB-NaIy4uLJ.js} +2 -2
- package/dist/static/assets/{chunk-4BX2VUAB-0F-1ayl0.js.map → chunk-4BX2VUAB-NaIy4uLJ.js.map} +1 -1
- package/dist/static/assets/{chunk-55IACEB6-Dnl2HDTZ.js → chunk-55IACEB6-JUKI_Ayx.js} +2 -2
- package/dist/static/assets/{chunk-55IACEB6-Dnl2HDTZ.js.map → chunk-55IACEB6-JUKI_Ayx.js.map} +1 -1
- package/dist/static/assets/{chunk-B4BG7PRW-Bhx5RbkQ.js → chunk-B4BG7PRW-dIswFJDn.js} +5 -5
- package/dist/static/assets/{chunk-B4BG7PRW-Bhx5RbkQ.js.map → chunk-B4BG7PRW-dIswFJDn.js.map} +1 -1
- package/dist/static/assets/{chunk-DI55MBZ5-EYd1wL3E.js → chunk-DI55MBZ5-DU2b_N30.js} +4 -4
- package/dist/static/assets/{chunk-DI55MBZ5-EYd1wL3E.js.map → chunk-DI55MBZ5-DU2b_N30.js.map} +1 -1
- package/dist/static/assets/{chunk-FMBD7UC4-DAjkhhUU.js → chunk-FMBD7UC4-BgExcScw.js} +2 -2
- package/dist/static/assets/{chunk-FMBD7UC4-DAjkhhUU.js.map → chunk-FMBD7UC4-BgExcScw.js.map} +1 -1
- package/dist/static/assets/{chunk-QN33PNHL-CK6TY7IE.js → chunk-QN33PNHL-bitxyqh7.js} +2 -2
- package/dist/static/assets/{chunk-QN33PNHL-CK6TY7IE.js.map → chunk-QN33PNHL-bitxyqh7.js.map} +1 -1
- package/dist/static/assets/{chunk-QZHKN3VN-CketngiE.js → chunk-QZHKN3VN-Cor8u7DT.js} +2 -2
- package/dist/static/assets/{chunk-QZHKN3VN-CketngiE.js.map → chunk-QZHKN3VN-Cor8u7DT.js.map} +1 -1
- package/dist/static/assets/{chunk-TZMSLE5B-Bcuvqo45.js → chunk-TZMSLE5B-Aceoxav_.js} +2 -2
- package/dist/static/assets/{chunk-TZMSLE5B-Bcuvqo45.js.map → chunk-TZMSLE5B-Aceoxav_.js.map} +1 -1
- package/dist/static/assets/{classDiagram-2ON5EDUG-CaP4T3r4.js → classDiagram-2ON5EDUG-D1Q6a8Hg.js} +6 -6
- package/dist/static/assets/{classDiagram-2ON5EDUG-CaP4T3r4.js.map → classDiagram-2ON5EDUG-D1Q6a8Hg.js.map} +1 -1
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-CaP4T3r4.js → classDiagram-v2-WZHVMYZB-D1Q6a8Hg.js} +6 -6
- package/dist/static/assets/{classDiagram-v2-WZHVMYZB-CaP4T3r4.js.map → classDiagram-v2-WZHVMYZB-D1Q6a8Hg.js.map} +1 -1
- package/dist/static/assets/{clone-C-JULvnG.js → clone-MlWbv1V0.js} +2 -2
- package/dist/static/assets/{clone-C-JULvnG.js.map → clone-MlWbv1V0.js.map} +1 -1
- package/dist/static/assets/{cose-bilkent-S5V4N54A-vXCmi_eC.js → cose-bilkent-S5V4N54A-DWPCXSrn.js} +2 -2
- package/dist/static/assets/{cose-bilkent-S5V4N54A-vXCmi_eC.js.map → cose-bilkent-S5V4N54A-DWPCXSrn.js.map} +1 -1
- package/dist/static/assets/{dagre-6UL2VRFP-bhGzX6kO.js → dagre-6UL2VRFP-C8ptQ9V3.js} +7 -7
- package/dist/static/assets/{dagre-6UL2VRFP-bhGzX6kO.js.map → dagre-6UL2VRFP-C8ptQ9V3.js.map} +1 -1
- package/dist/static/assets/{diagram-PSM6KHXK-BUKfmfGk.js → diagram-PSM6KHXK-Bgf1FqkE.js} +8 -8
- package/dist/static/assets/{diagram-PSM6KHXK-BUKfmfGk.js.map → diagram-PSM6KHXK-Bgf1FqkE.js.map} +1 -1
- package/dist/static/assets/{diagram-QEK2KX5R-DYlq3uFq.js → diagram-QEK2KX5R-BZ5xzofU.js} +7 -7
- package/dist/static/assets/{diagram-QEK2KX5R-DYlq3uFq.js.map → diagram-QEK2KX5R-BZ5xzofU.js.map} +1 -1
- package/dist/static/assets/{diagram-S2PKOQOG-CjxkLHWG.js → diagram-S2PKOQOG-Dwp47T9I.js} +7 -7
- package/dist/static/assets/{diagram-S2PKOQOG-CjxkLHWG.js.map → diagram-S2PKOQOG-Dwp47T9I.js.map} +1 -1
- package/dist/static/assets/{erDiagram-Q2GNP2WA-S3hR85On.js → erDiagram-Q2GNP2WA-Cx4weIHl.js} +5 -5
- package/dist/static/assets/{erDiagram-Q2GNP2WA-S3hR85On.js.map → erDiagram-Q2GNP2WA-Cx4weIHl.js.map} +1 -1
- package/dist/static/assets/{flowDiagram-NV44I4VS-aBmNMuQ0.js → flowDiagram-NV44I4VS-vNUuIeRk.js} +6 -6
- package/dist/static/assets/{flowDiagram-NV44I4VS-aBmNMuQ0.js.map → flowDiagram-NV44I4VS-vNUuIeRk.js.map} +1 -1
- package/dist/static/assets/{ganttDiagram-JELNMOA3-DJxXaiW1.js → ganttDiagram-JELNMOA3-BEfozJAr.js} +3 -3
- package/dist/static/assets/{ganttDiagram-JELNMOA3-DJxXaiW1.js.map → ganttDiagram-JELNMOA3-BEfozJAr.js.map} +1 -1
- package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-DEOBCM0G.js → gitGraphDiagram-V2S2FVAM-eHxwc3d9.js} +8 -8
- package/dist/static/assets/{gitGraphDiagram-V2S2FVAM-DEOBCM0G.js.map → gitGraphDiagram-V2S2FVAM-eHxwc3d9.js.map} +1 -1
- package/dist/static/assets/{graph-DwrKSIE7.js → graph-C6a6uAok.js} +3 -3
- package/dist/static/assets/{graph-DwrKSIE7.js.map → graph-C6a6uAok.js.map} +1 -1
- package/dist/static/assets/{index-HWTRvE2k.js → index-D3TQbAKh.js} +383 -59
- package/dist/static/assets/index-D3TQbAKh.js.map +1 -0
- package/dist/static/assets/{infoDiagram-HS3SLOUP-BH9kVuYd.js → infoDiagram-HS3SLOUP-CX0NiId3.js} +6 -6
- package/dist/static/assets/{infoDiagram-HS3SLOUP-BH9kVuYd.js.map → infoDiagram-HS3SLOUP-CX0NiId3.js.map} +1 -1
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Dap7AcjR.js → journeyDiagram-XKPGCS4Q-C1IepPZ-.js} +5 -5
- package/dist/static/assets/{journeyDiagram-XKPGCS4Q-Dap7AcjR.js.map → journeyDiagram-XKPGCS4Q-C1IepPZ-.js.map} +1 -1
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-4NOl8MEj.js → kanban-definition-3W4ZIXB7-uMNX4Z1W.js} +3 -3
- package/dist/static/assets/{kanban-definition-3W4ZIXB7-4NOl8MEj.js.map → kanban-definition-3W4ZIXB7-uMNX4Z1W.js.map} +1 -1
- package/dist/static/assets/{layout-D6uIxu1E.js → layout-CpE3kk5z.js} +5 -5
- package/dist/static/assets/{layout-D6uIxu1E.js.map → layout-CpE3kk5z.js.map} +1 -1
- package/dist/static/assets/{linear-CvBOGQA2.js → linear-DV8laXr9.js} +2 -2
- package/dist/static/assets/{linear-CvBOGQA2.js.map → linear-DV8laXr9.js.map} +1 -1
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-ugsrLNY5.js → mindmap-definition-VGOIOE7T-CKjgVM9S.js} +4 -4
- package/dist/static/assets/{mindmap-definition-VGOIOE7T-ugsrLNY5.js.map → mindmap-definition-VGOIOE7T-CKjgVM9S.js.map} +1 -1
- package/dist/static/assets/{pieDiagram-ADFJNKIX-CdVZjM8g.js → pieDiagram-ADFJNKIX-BBonlNyT.js} +8 -8
- package/dist/static/assets/{pieDiagram-ADFJNKIX-CdVZjM8g.js.map → pieDiagram-ADFJNKIX-BBonlNyT.js.map} +1 -1
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-A6m5lZKd.js → quadrantDiagram-AYHSOK5B-BTI8HbBu.js} +3 -3
- package/dist/static/assets/{quadrantDiagram-AYHSOK5B-A6m5lZKd.js.map → quadrantDiagram-AYHSOK5B-BTI8HbBu.js.map} +1 -1
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-Cac3zSJH.js → requirementDiagram-UZGBJVZJ-ZtSr9Q5R.js} +4 -4
- package/dist/static/assets/{requirementDiagram-UZGBJVZJ-Cac3zSJH.js.map → requirementDiagram-UZGBJVZJ-ZtSr9Q5R.js.map} +1 -1
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DXDdUUl1.js → sankeyDiagram-TZEHDZUN-DibLVGzg.js} +2 -2
- package/dist/static/assets/{sankeyDiagram-TZEHDZUN-DXDdUUl1.js.map → sankeyDiagram-TZEHDZUN-DibLVGzg.js.map} +1 -1
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-Domsjl5Y.js → sequenceDiagram-WL72ISMW-qXatfzVt.js} +4 -4
- package/dist/static/assets/{sequenceDiagram-WL72ISMW-Domsjl5Y.js.map → sequenceDiagram-WL72ISMW-qXatfzVt.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-Bu0lRQK1.js → stateDiagram-FKZM4ZOC-7fgxCQHo.js} +9 -9
- package/dist/static/assets/{stateDiagram-FKZM4ZOC-Bu0lRQK1.js.map → stateDiagram-FKZM4ZOC-7fgxCQHo.js.map} +1 -1
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-D0K-n3ic.js → stateDiagram-v2-4FDKWEC3-DcWlOAnF.js} +5 -5
- package/dist/static/assets/{stateDiagram-v2-4FDKWEC3-D0K-n3ic.js.map → stateDiagram-v2-4FDKWEC3-DcWlOAnF.js.map} +1 -1
- package/dist/static/assets/{timeline-definition-IT6M3QCI-BGvpddwR.js → timeline-definition-IT6M3QCI-iX2MRdpY.js} +3 -3
- package/dist/static/assets/{timeline-definition-IT6M3QCI-BGvpddwR.js.map → timeline-definition-IT6M3QCI-iX2MRdpY.js.map} +1 -1
- package/dist/static/assets/{treemap-GDKQZRPO-BoOzOm2j.js → treemap-GDKQZRPO-AVRnyXu1.js} +5 -5
- package/dist/static/assets/{treemap-GDKQZRPO-BoOzOm2j.js.map → treemap-GDKQZRPO-AVRnyXu1.js.map} +1 -1
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_h3_ICR.js → xychartDiagram-PRI3JC2R-DVYEo5aJ.js} +3 -3
- package/dist/static/assets/{xychartDiagram-PRI3JC2R-C_h3_ICR.js.map → xychartDiagram-PRI3JC2R-DVYEo5aJ.js.map} +1 -1
- package/dist/static/index.html +1 -1
- package/dist/team.js +52 -48
- package/dist/tellask.js +439 -0
- package/dist/tools/context-health.js +177 -0
- package/dist/tools/diag.js +583 -0
- package/dist/tools/fs.js +194 -68
- package/dist/tools/prompts/memory/en/principles.md +13 -5
- package/dist/tools/prompts/memory/en/tools.md +11 -36
- package/dist/tools/prompts/memory/zh/principles.md +18 -8
- package/dist/tools/prompts/memory/zh/tools.md +11 -36
- package/dist/tools/team-mgmt.js +3487 -0
- package/dist/utils/task-doc.js +236 -0
- package/package.json +1 -1
- package/dist/static/assets/index-HWTRvE2k.js.map +0 -1
package/dist/static/index.html
CHANGED
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
padding: 20px;
|
|
53
53
|
}
|
|
54
54
|
</style>
|
|
55
|
-
<script type="module" crossorigin src="/assets/index-
|
|
55
|
+
<script type="module" crossorigin src="/assets/index-D3TQbAKh.js"></script>
|
|
56
56
|
<link rel="stylesheet" crossorigin href="/assets/index-BiNcBn_U.css">
|
|
57
57
|
</head>
|
|
58
58
|
<body>
|
package/dist/team.js
CHANGED
|
@@ -699,38 +699,14 @@ exports.Team = Team;
|
|
|
699
699
|
finalizeProblems();
|
|
700
700
|
return team;
|
|
701
701
|
}
|
|
702
|
-
|
|
702
|
+
let appTeammates = [];
|
|
703
703
|
try {
|
|
704
|
-
|
|
705
|
-
if (appTeammates.length > 0) {
|
|
706
|
-
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
707
|
-
addIssue('apps/teammates/invalid_base', 'Failed to merge app teammates into .minds/team.yaml: base YAML is not an object.', `Expected .minds/team.yaml to parse into an object before applying app teammate merges.`);
|
|
708
|
-
}
|
|
709
|
-
else {
|
|
710
|
-
const rec = parsed;
|
|
711
|
-
const membersRaw = rec['members'];
|
|
712
|
-
const members = typeof membersRaw === 'object' && membersRaw !== null && !Array.isArray(membersRaw)
|
|
713
|
-
? membersRaw
|
|
714
|
-
: {};
|
|
715
|
-
if (rec['members'] === undefined) {
|
|
716
|
-
rec['members'] = members;
|
|
717
|
-
}
|
|
718
|
-
for (const snip of appTeammates) {
|
|
719
|
-
for (const [id, member] of Object.entries(snip.members)) {
|
|
720
|
-
if (Object.prototype.hasOwnProperty.call(members, id)) {
|
|
721
|
-
addIssue(`apps/teammates/duplicate_member/${sanitizeProblemIdSegment(id)}`, 'App teammate id collision while loading .minds/team.yaml.', `Enabled app '${snip.appId}' contributes member id '${id}', but it already exists in team.yaml (or another app). Disable/uninstall the conflicting app or rename the member id.`);
|
|
722
|
-
continue;
|
|
723
|
-
}
|
|
724
|
-
members[id] = member;
|
|
725
|
-
}
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
}
|
|
704
|
+
appTeammates = await (0, teammates_1.loadEnabledAppTeammates)({ rtwsRootAbs: process.cwd() });
|
|
729
705
|
}
|
|
730
706
|
catch (err) {
|
|
731
707
|
addIssue('apps/teammates/load', 'Failed to load enabled app teammates.', err instanceof Error ? err.message : String(err));
|
|
732
708
|
}
|
|
733
|
-
const parsedTeam = parseTeamYamlObject(parsed, md, { fuxi, pangu });
|
|
709
|
+
const parsedTeam = parseTeamYamlObject(parsed, md, { fuxi, pangu }, { appTeammates });
|
|
734
710
|
for (const issue of parsedTeam.issues) {
|
|
735
711
|
addIssue(issue.id, issue.message, issue.errorText);
|
|
736
712
|
}
|
|
@@ -1306,11 +1282,15 @@ exports.Team = Team;
|
|
|
1306
1282
|
if (overrides.hidden !== undefined)
|
|
1307
1283
|
member.setHidden(overrides.hidden);
|
|
1308
1284
|
}
|
|
1309
|
-
function parseTeamYamlObject(obj, md, shadow) {
|
|
1285
|
+
function parseTeamYamlObject(obj, md, shadow, deps) {
|
|
1310
1286
|
const issues = [];
|
|
1311
1287
|
const pushIssue = (id, message, errorText) => {
|
|
1312
1288
|
issues.push({ id, message, errorText });
|
|
1313
1289
|
};
|
|
1290
|
+
const appMembersByAppId = new Map();
|
|
1291
|
+
for (const snip of deps.appTeammates) {
|
|
1292
|
+
appMembersByAppId.set(snip.appId, snip.members);
|
|
1293
|
+
}
|
|
1314
1294
|
const teamObj = (() => {
|
|
1315
1295
|
if (isRecordValue(obj))
|
|
1316
1296
|
return obj;
|
|
@@ -1394,9 +1374,9 @@ exports.Team = Team;
|
|
|
1394
1374
|
pushIssue(`members/${idSeg}`, `Invalid .minds/team.yaml: ${memberAt} must be an object.`, `Invalid ${memberAt}: expected an object (got ${describeValueType(raw)})`);
|
|
1395
1375
|
continue;
|
|
1396
1376
|
}
|
|
1397
|
-
// Cross-app teammate reference (
|
|
1398
|
-
//
|
|
1399
|
-
{
|
|
1377
|
+
// Cross-app teammate reference (v0): members.<id>.from + (use|import).
|
|
1378
|
+
// Fail-open: surface Problems, but keep Team usable.
|
|
1379
|
+
const effectiveRaw = (() => {
|
|
1400
1380
|
const memberObj = raw;
|
|
1401
1381
|
const hasFrom = hasOwnKey(memberObj, 'from');
|
|
1402
1382
|
const hasUse = hasOwnKey(memberObj, 'use');
|
|
@@ -1405,34 +1385,58 @@ exports.Team = Team;
|
|
|
1405
1385
|
const useRaw = hasUse ? memberObj['use'] : undefined;
|
|
1406
1386
|
const importRaw = hasImport ? memberObj['import'] : undefined;
|
|
1407
1387
|
// Problem id should stay short and stable: it is a UI address, not a stack trace.
|
|
1408
|
-
//
|
|
1409
|
-
// This validator currently runs on the effective rtws `.minds/team.yaml` object.
|
|
1388
|
+
// This validator runs on the effective rtws `.minds/team.yaml` object.
|
|
1410
1389
|
const definingScopeSeg = 'rtws';
|
|
1411
1390
|
const memberPrefix = `members/${definingScopeSeg}/${idSeg}`;
|
|
1412
1391
|
if (hasUse && hasImport) {
|
|
1413
1392
|
pushIssue(`${memberPrefix}/use_and_import_conflict`, `Invalid .minds/team.yaml: ${memberAt} cannot specify both 'use' and 'import'.`, `Both ${memberAt}.use and ${memberAt}.import are present; remove one.`);
|
|
1393
|
+
return memberObj;
|
|
1414
1394
|
}
|
|
1415
1395
|
if ((hasUse || hasImport) && !hasFrom) {
|
|
1416
1396
|
pushIssue(`${memberPrefix}/from/missing`, `Invalid .minds/team.yaml: ${memberAt} uses cross-app member reference but is missing 'from'.`, `Either remove ${memberAt}.use/${memberAt}.import, or add ${memberAt}.from: <dep-app-id>.`);
|
|
1397
|
+
return memberObj;
|
|
1417
1398
|
}
|
|
1418
|
-
if (hasFrom)
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
}
|
|
1399
|
+
if (!hasFrom)
|
|
1400
|
+
return memberObj;
|
|
1401
|
+
if (typeof fromRaw !== 'string' || fromRaw.trim() === '') {
|
|
1402
|
+
pushIssue(`${memberPrefix}/from/invalid`, `Invalid .minds/team.yaml: ${memberAt}.from must be a non-empty string.`, `Invalid ${memberAt}.from: expected non-empty string (got ${describeValueType(fromRaw)})`);
|
|
1403
|
+
return memberObj;
|
|
1422
1404
|
}
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1405
|
+
// `from`-only is accepted (v0 no-op): treat it as a local member definition.
|
|
1406
|
+
if (!hasUse && !hasImport)
|
|
1407
|
+
return memberObj;
|
|
1408
|
+
const refKind = hasUse ? 'use' : 'import';
|
|
1409
|
+
const refRaw = hasUse ? useRaw : importRaw;
|
|
1410
|
+
if (typeof refRaw !== 'string' || refRaw.trim() === '') {
|
|
1411
|
+
pushIssue(`${memberPrefix}/${refKind}/invalid`, `Invalid .minds/team.yaml: ${memberAt}.${refKind} must be a non-empty string.`, `Invalid ${memberAt}.${refKind}: expected non-empty string (got ${describeValueType(refRaw)})`);
|
|
1412
|
+
return memberObj;
|
|
1427
1413
|
}
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1414
|
+
const fromAppId = fromRaw.trim();
|
|
1415
|
+
const refMemberId = refRaw.trim();
|
|
1416
|
+
const appMembers = appMembersByAppId.get(fromAppId);
|
|
1417
|
+
if (!appMembers) {
|
|
1418
|
+
pushIssue(`${memberPrefix}/from/unresolved_app`, `Invalid .minds/team.yaml: ${memberAt}.from refers to an app that is not enabled.`, `App '${fromAppId}' is not enabled (or does not export teammates YAML).`);
|
|
1419
|
+
return memberObj;
|
|
1432
1420
|
}
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1421
|
+
const sourceRaw = appMembers[refMemberId];
|
|
1422
|
+
if (sourceRaw === undefined) {
|
|
1423
|
+
pushIssue(`${memberPrefix}/${refKind}/unresolved_member`, `Invalid .minds/team.yaml: ${memberAt}.${refKind} refers to a missing member in app '${fromAppId}'.`, `App '${fromAppId}' does not export member id '${refMemberId}'.`);
|
|
1424
|
+
return memberObj;
|
|
1425
|
+
}
|
|
1426
|
+
if (!isRecordValue(sourceRaw)) {
|
|
1427
|
+
pushIssue(`${memberPrefix}/${refKind}/invalid_member`, `Invalid app teammates YAML: member '${refMemberId}' must be an object (app '${fromAppId}').`, `Expected app member '${fromAppId}.${refMemberId}' to be an object (got ${describeValueType(sourceRaw)}).`);
|
|
1428
|
+
return memberObj;
|
|
1429
|
+
}
|
|
1430
|
+
const merged = { ...sourceRaw };
|
|
1431
|
+
for (const [k, v] of Object.entries(memberObj)) {
|
|
1432
|
+
if (k === 'from' || k === 'use' || k === 'import')
|
|
1433
|
+
continue;
|
|
1434
|
+
merged[k] = v;
|
|
1435
|
+
}
|
|
1436
|
+
return merged;
|
|
1437
|
+
})();
|
|
1438
|
+
validateCommonModelParamMisplacements(pushIssue, `members/${idSeg}`, memberAt, effectiveRaw);
|
|
1439
|
+
const parsedMember = parseMemberOverrides(effectiveRaw, memberAt);
|
|
1436
1440
|
if (parsedMember.kind === 'error') {
|
|
1437
1441
|
pushIssue(`members/${idSeg}`, `Invalid .minds/team.yaml: ${memberAt} has invalid fields.`, parsedMember.errorTexts.join('\n'));
|
|
1438
1442
|
if (id === 'fuxi' || id === 'pangu') {
|
package/dist/tellask.js
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* # Tellask Grammar ("诉请")
|
|
4
|
+
*
|
|
5
|
+
* A primitive, line-based streaming call format designed to be robust under arbitrary
|
|
6
|
+
* upstream chunk boundaries (no backtick/markdown state machine required).
|
|
7
|
+
*
|
|
8
|
+
* ## Rules
|
|
9
|
+
*
|
|
10
|
+
* - Tellask call blocks consist of **lines**.
|
|
11
|
+
* - Any line starting with literal `!?` is a tellask line (prefix is not included in payload).
|
|
12
|
+
* - Any line(s) **without** `!?` prefix are treated as markdown, and also act as separators:
|
|
13
|
+
* they terminate the current tellask call block (if any).
|
|
14
|
+
*
|
|
15
|
+
* Within a tellask call block:
|
|
16
|
+
* - The first tellask line is the start of the call headline.
|
|
17
|
+
* - The first line MUST start with `!?@<valid-mention-id>` to be considered valid.
|
|
18
|
+
* Otherwise the block still parses, but is reported as malformed.
|
|
19
|
+
* - While still in headline phase, subsequent tellask lines starting with `!?@` extend
|
|
20
|
+
* the headline (multiline headline).
|
|
21
|
+
* - Any other tellask lines (starting with `!?` but NOT `!?@`) start/continue the call body.
|
|
22
|
+
*
|
|
23
|
+
* All downstream chunks preserve upstream chunk boundaries unless correctness requires
|
|
24
|
+
* a split (e.g. line-start prefix disambiguation across chunks).
|
|
25
|
+
*/
|
|
26
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
27
|
+
exports.TellaskStreamParser = void 0;
|
|
28
|
+
const id_1 = require("./utils/id");
|
|
29
|
+
class TellaskStreamParser {
|
|
30
|
+
constructor(downstream) {
|
|
31
|
+
this.callCounter = 0;
|
|
32
|
+
this.collectedCalls = [];
|
|
33
|
+
this.markdownStarted = false;
|
|
34
|
+
this.markdownChunkBuffer = '';
|
|
35
|
+
this.activeCall = null;
|
|
36
|
+
this.headlineBuffer = '';
|
|
37
|
+
this.bodyBuffer = '';
|
|
38
|
+
this.isAtLineStart = true;
|
|
39
|
+
this.lineStartProbe = '';
|
|
40
|
+
this.currentLineKind = 'unknown';
|
|
41
|
+
this.pendingCallLineRole = false;
|
|
42
|
+
this.currentCallLineRole = null;
|
|
43
|
+
// Total raw upstream characters consumed so far.
|
|
44
|
+
this.upstreamPos = 0;
|
|
45
|
+
this.downstream = downstream;
|
|
46
|
+
}
|
|
47
|
+
async takeUpstreamChunk(chunk) {
|
|
48
|
+
let pos = 0;
|
|
49
|
+
while (pos < chunk.length) {
|
|
50
|
+
const char = chunk[pos] ?? '';
|
|
51
|
+
if (this.isAtLineStart && this.currentLineKind === 'unknown') {
|
|
52
|
+
const consumed = await this.processLineStartProbe(char);
|
|
53
|
+
if (consumed) {
|
|
54
|
+
pos += 1;
|
|
55
|
+
this.upstreamPos += 1;
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
// Not consumed means we decided the line kind and need to re-process this char
|
|
59
|
+
// with the decided line kind.
|
|
60
|
+
}
|
|
61
|
+
if (this.currentLineKind === 'markdown') {
|
|
62
|
+
await this.processMarkdownChar(char);
|
|
63
|
+
pos += 1;
|
|
64
|
+
this.upstreamPos += 1;
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
if (this.currentLineKind === 'call') {
|
|
68
|
+
await this.processCallChar(char);
|
|
69
|
+
pos += 1;
|
|
70
|
+
this.upstreamPos += 1;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
// Fallback: should be unreachable, but keep safe to avoid infinite loops.
|
|
74
|
+
await this.processMarkdownChar(char);
|
|
75
|
+
pos += 1;
|
|
76
|
+
this.upstreamPos += 1;
|
|
77
|
+
}
|
|
78
|
+
await this.flushAtUpstreamChunkEnd();
|
|
79
|
+
}
|
|
80
|
+
async finalize() {
|
|
81
|
+
// Resolve any pending single-char probe at start-of-line.
|
|
82
|
+
if (this.isAtLineStart && this.currentLineKind === 'unknown' && this.lineStartProbe === '!') {
|
|
83
|
+
// This is a markdown separator line starting with '!' but not enough chars to be `!?`.
|
|
84
|
+
await this.endActiveCallBlockIfAny();
|
|
85
|
+
this.markdownChunkBuffer += '!';
|
|
86
|
+
this.lineStartProbe = '';
|
|
87
|
+
}
|
|
88
|
+
// End-of-input can terminate a call without a trailing newline.
|
|
89
|
+
if (this.activeCall) {
|
|
90
|
+
await this.resolvePendingFirstLineMentionAtEofIfNeeded();
|
|
91
|
+
await this.endActiveCallBlockIfAny();
|
|
92
|
+
}
|
|
93
|
+
if (this.markdownChunkBuffer.length > 0) {
|
|
94
|
+
if (!this.markdownStarted) {
|
|
95
|
+
await this.downstream.markdownStart();
|
|
96
|
+
this.markdownStarted = true;
|
|
97
|
+
}
|
|
98
|
+
await this.downstream.markdownChunk(this.markdownChunkBuffer);
|
|
99
|
+
this.markdownChunkBuffer = '';
|
|
100
|
+
}
|
|
101
|
+
if (this.markdownStarted) {
|
|
102
|
+
await this.downstream.markdownFinish();
|
|
103
|
+
this.markdownStarted = false;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
getCollectedCalls() {
|
|
107
|
+
return [...this.collectedCalls];
|
|
108
|
+
}
|
|
109
|
+
async processLineStartProbe(char) {
|
|
110
|
+
// Returns true if the character was consumed as part of probing decision.
|
|
111
|
+
if (this.lineStartProbe === '') {
|
|
112
|
+
if (char === '\n') {
|
|
113
|
+
// Empty line is markdown separator.
|
|
114
|
+
await this.endActiveCallBlockIfAny();
|
|
115
|
+
this.currentLineKind = 'markdown';
|
|
116
|
+
await this.processMarkdownChar(char);
|
|
117
|
+
this.resetLineStateAfterNewline();
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
this.lineStartProbe = '!';
|
|
121
|
+
if (char !== '!') {
|
|
122
|
+
// First char isn't '!' => markdown line.
|
|
123
|
+
this.lineStartProbe = '';
|
|
124
|
+
await this.endActiveCallBlockIfAny();
|
|
125
|
+
this.currentLineKind = 'markdown';
|
|
126
|
+
// Re-process this char as markdown.
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
// We saw '!' at column 0; need one more char to decide.
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
// lineStartProbe === '!' means we already consumed a '!' at strict column 0.
|
|
133
|
+
if (char === '\n') {
|
|
134
|
+
// Line length is 1 => markdown line containing '!\n'.
|
|
135
|
+
this.lineStartProbe = '';
|
|
136
|
+
await this.endActiveCallBlockIfAny();
|
|
137
|
+
this.currentLineKind = 'markdown';
|
|
138
|
+
this.markdownChunkBuffer += '!\n';
|
|
139
|
+
this.resetLineStateAfterNewline();
|
|
140
|
+
return true;
|
|
141
|
+
}
|
|
142
|
+
if (char === '?') {
|
|
143
|
+
// Confirmed call line prefix `!?` at column 0.
|
|
144
|
+
this.lineStartProbe = '';
|
|
145
|
+
await this.ensureCallLineModeStart();
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
// Not `!?` => markdown line starting with '!' then current char.
|
|
149
|
+
this.lineStartProbe = '';
|
|
150
|
+
await this.endActiveCallBlockIfAny();
|
|
151
|
+
this.currentLineKind = 'markdown';
|
|
152
|
+
this.markdownChunkBuffer += '!' + char;
|
|
153
|
+
this.isAtLineStart = false;
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
async ensureCallLineModeStart() {
|
|
157
|
+
// Transition from markdown to call line: finalize markdown fragment if active.
|
|
158
|
+
if (this.markdownChunkBuffer.length > 0) {
|
|
159
|
+
if (!this.markdownStarted) {
|
|
160
|
+
await this.downstream.markdownStart();
|
|
161
|
+
this.markdownStarted = true;
|
|
162
|
+
}
|
|
163
|
+
await this.downstream.markdownChunk(this.markdownChunkBuffer);
|
|
164
|
+
this.markdownChunkBuffer = '';
|
|
165
|
+
}
|
|
166
|
+
if (this.markdownStarted) {
|
|
167
|
+
await this.downstream.markdownFinish();
|
|
168
|
+
this.markdownStarted = false;
|
|
169
|
+
}
|
|
170
|
+
this.currentLineKind = 'call';
|
|
171
|
+
this.isAtLineStart = false;
|
|
172
|
+
this.pendingCallLineRole = true;
|
|
173
|
+
this.currentCallLineRole = null;
|
|
174
|
+
if (!this.activeCall) {
|
|
175
|
+
this.activeCall = {
|
|
176
|
+
kind: 'active',
|
|
177
|
+
validation: null,
|
|
178
|
+
firstLineMentionParse: { kind: 'pending_first_char' },
|
|
179
|
+
tellaskHead: '',
|
|
180
|
+
body: '',
|
|
181
|
+
callLineIndex: 0,
|
|
182
|
+
phase: 'headline',
|
|
183
|
+
tellaskHeadFinished: false,
|
|
184
|
+
bodyStarted: false,
|
|
185
|
+
callStartEmitted: false,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
this.activeCall.callLineIndex += 1;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async processMarkdownChar(char) {
|
|
193
|
+
// Markdown content includes all characters verbatim.
|
|
194
|
+
this.markdownChunkBuffer += char;
|
|
195
|
+
if (char === '\n') {
|
|
196
|
+
this.resetLineStateAfterNewline();
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
this.isAtLineStart = false;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
async processCallChar(char) {
|
|
203
|
+
const call = this.activeCall;
|
|
204
|
+
if (!call) {
|
|
205
|
+
// Should never happen: call line implies active call. Fall back to markdown.
|
|
206
|
+
await this.processMarkdownChar(char);
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
if (this.pendingCallLineRole) {
|
|
210
|
+
const role = this.decideCallLineRole(call, char);
|
|
211
|
+
this.pendingCallLineRole = false;
|
|
212
|
+
this.currentCallLineRole = role;
|
|
213
|
+
if (role === 'body') {
|
|
214
|
+
if (call.phase === 'headline') {
|
|
215
|
+
await this.finishHeadlineIfNeeded();
|
|
216
|
+
await this.startBodyIfNeeded();
|
|
217
|
+
call.phase = 'body';
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
// First line mention validation is based on the first tellask line only.
|
|
222
|
+
if (call.callLineIndex === 0 && call.phase === 'headline') {
|
|
223
|
+
await this.processFirstLineMentionParse(char);
|
|
224
|
+
}
|
|
225
|
+
if (this.currentCallLineRole === 'headline') {
|
|
226
|
+
this.headlineBuffer += char;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
this.bodyBuffer += char;
|
|
230
|
+
}
|
|
231
|
+
if (char === '\n') {
|
|
232
|
+
this.resetLineStateAfterNewline();
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
this.isAtLineStart = false;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
decideCallLineRole(call, firstCharAfterPrefix) {
|
|
239
|
+
if (call.phase === 'body')
|
|
240
|
+
return 'body';
|
|
241
|
+
if (call.callLineIndex === 0)
|
|
242
|
+
return 'headline';
|
|
243
|
+
return firstCharAfterPrefix === '@' ? 'headline' : 'body';
|
|
244
|
+
}
|
|
245
|
+
async processFirstLineMentionParse(char) {
|
|
246
|
+
const call = this.activeCall;
|
|
247
|
+
if (!call)
|
|
248
|
+
return;
|
|
249
|
+
const parse = call.firstLineMentionParse;
|
|
250
|
+
if (parse.kind === 'resolved')
|
|
251
|
+
return;
|
|
252
|
+
if (parse.kind === 'pending_first_char') {
|
|
253
|
+
if (char === '\n') {
|
|
254
|
+
await this.resolveFirstLineMention({ kind: 'malformed', reason: 'missing_mention_prefix' });
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
if (char !== '@') {
|
|
258
|
+
await this.resolveFirstLineMention({ kind: 'malformed', reason: 'missing_mention_prefix' });
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
261
|
+
call.firstLineMentionParse = { kind: 'pending_mention_chars', raw: '' };
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
if (parse.kind === 'pending_mention_chars') {
|
|
265
|
+
if (this.isValidMentionChar(char)) {
|
|
266
|
+
call.firstLineMentionParse = { kind: 'pending_mention_chars', raw: parse.raw + char };
|
|
267
|
+
return;
|
|
268
|
+
}
|
|
269
|
+
const trimmed = this.trimTrailingDots(parse.raw);
|
|
270
|
+
if (trimmed.length > 0) {
|
|
271
|
+
await this.resolveFirstLineMention({ kind: 'valid', firstMention: trimmed });
|
|
272
|
+
}
|
|
273
|
+
else {
|
|
274
|
+
await this.resolveFirstLineMention({ kind: 'malformed', reason: 'invalid_mention_id' });
|
|
275
|
+
}
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
async resolveFirstLineMention(validation) {
|
|
280
|
+
const call = this.activeCall;
|
|
281
|
+
if (!call)
|
|
282
|
+
return;
|
|
283
|
+
call.validation = validation;
|
|
284
|
+
call.firstLineMentionParse = { kind: 'resolved', validation };
|
|
285
|
+
if (!call.callStartEmitted) {
|
|
286
|
+
call.callStartEmitted = true;
|
|
287
|
+
await this.downstream.callStart(validation);
|
|
288
|
+
}
|
|
289
|
+
await this.flushHeadlineBuffer();
|
|
290
|
+
}
|
|
291
|
+
async resolvePendingFirstLineMentionAtEofIfNeeded() {
|
|
292
|
+
const call = this.activeCall;
|
|
293
|
+
if (!call)
|
|
294
|
+
return;
|
|
295
|
+
if (call.callLineIndex !== 0)
|
|
296
|
+
return;
|
|
297
|
+
const parse = call.firstLineMentionParse;
|
|
298
|
+
if (parse.kind === 'resolved')
|
|
299
|
+
return;
|
|
300
|
+
if (parse.kind === 'pending_first_char') {
|
|
301
|
+
await this.resolveFirstLineMention({ kind: 'malformed', reason: 'missing_mention_prefix' });
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
if (parse.kind === 'pending_mention_chars') {
|
|
305
|
+
const trimmed = this.trimTrailingDots(parse.raw);
|
|
306
|
+
if (trimmed.length > 0) {
|
|
307
|
+
await this.resolveFirstLineMention({ kind: 'valid', firstMention: trimmed });
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
await this.resolveFirstLineMention({ kind: 'malformed', reason: 'invalid_mention_id' });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
async finishHeadlineIfNeeded() {
|
|
315
|
+
const call = this.activeCall;
|
|
316
|
+
if (!call)
|
|
317
|
+
return;
|
|
318
|
+
if (call.tellaskHeadFinished)
|
|
319
|
+
return;
|
|
320
|
+
if (!call.callStartEmitted) {
|
|
321
|
+
// If the first line did not contain a mention terminator, we resolve at boundary.
|
|
322
|
+
await this.resolvePendingFirstLineMentionAtEofIfNeeded();
|
|
323
|
+
}
|
|
324
|
+
await this.flushHeadlineBuffer();
|
|
325
|
+
await this.downstream.callHeadLineFinish();
|
|
326
|
+
call.tellaskHeadFinished = true;
|
|
327
|
+
}
|
|
328
|
+
async startBodyIfNeeded() {
|
|
329
|
+
const call = this.activeCall;
|
|
330
|
+
if (!call)
|
|
331
|
+
return;
|
|
332
|
+
if (call.bodyStarted)
|
|
333
|
+
return;
|
|
334
|
+
await this.downstream.tellaskBodyStart();
|
|
335
|
+
call.bodyStarted = true;
|
|
336
|
+
}
|
|
337
|
+
async endActiveCallBlockIfAny() {
|
|
338
|
+
const call = this.activeCall;
|
|
339
|
+
if (!call)
|
|
340
|
+
return;
|
|
341
|
+
const upstreamEndOffset = this.upstreamPos;
|
|
342
|
+
// If the first line never encountered an invalid mention delimiter, ensure we still resolve.
|
|
343
|
+
await this.resolvePendingFirstLineMentionAtEofIfNeeded();
|
|
344
|
+
await this.finishHeadlineIfNeeded();
|
|
345
|
+
if (call.bodyStarted) {
|
|
346
|
+
await this.flushBodyBuffer();
|
|
347
|
+
await this.downstream.tellaskBodyFinish();
|
|
348
|
+
}
|
|
349
|
+
const validation = call.validation ?? { kind: 'malformed', reason: 'missing_mention_prefix' };
|
|
350
|
+
const callId = (0, id_1.generateContentHash)(`tellask\n${validation.kind === 'valid' ? validation.firstMention : ''}\n${call.tellaskHead}\n${call.body}`, this.callCounter++);
|
|
351
|
+
const collected = {
|
|
352
|
+
validation,
|
|
353
|
+
tellaskHead: call.tellaskHead,
|
|
354
|
+
body: call.body,
|
|
355
|
+
callId,
|
|
356
|
+
};
|
|
357
|
+
this.collectedCalls.push(collected);
|
|
358
|
+
await this.downstream.callFinish(collected, upstreamEndOffset);
|
|
359
|
+
this.activeCall = null;
|
|
360
|
+
this.headlineBuffer = '';
|
|
361
|
+
this.bodyBuffer = '';
|
|
362
|
+
this.pendingCallLineRole = false;
|
|
363
|
+
this.currentCallLineRole = null;
|
|
364
|
+
}
|
|
365
|
+
resetLineStateAfterNewline() {
|
|
366
|
+
this.isAtLineStart = true;
|
|
367
|
+
this.lineStartProbe = '';
|
|
368
|
+
this.currentLineKind = 'unknown';
|
|
369
|
+
this.pendingCallLineRole = false;
|
|
370
|
+
this.currentCallLineRole = null;
|
|
371
|
+
}
|
|
372
|
+
async flushHeadlineBuffer() {
|
|
373
|
+
const call = this.activeCall;
|
|
374
|
+
if (!call)
|
|
375
|
+
return;
|
|
376
|
+
if (!call.callStartEmitted)
|
|
377
|
+
return;
|
|
378
|
+
if (this.headlineBuffer.length === 0)
|
|
379
|
+
return;
|
|
380
|
+
call.tellaskHead += this.headlineBuffer;
|
|
381
|
+
await this.downstream.callHeadLineChunk(this.headlineBuffer);
|
|
382
|
+
this.headlineBuffer = '';
|
|
383
|
+
}
|
|
384
|
+
async flushBodyBuffer() {
|
|
385
|
+
const call = this.activeCall;
|
|
386
|
+
if (!call)
|
|
387
|
+
return;
|
|
388
|
+
if (this.bodyBuffer.length === 0)
|
|
389
|
+
return;
|
|
390
|
+
call.body += this.bodyBuffer;
|
|
391
|
+
await this.downstream.tellaskBodyChunk(this.bodyBuffer);
|
|
392
|
+
this.bodyBuffer = '';
|
|
393
|
+
}
|
|
394
|
+
async flushAtUpstreamChunkEnd() {
|
|
395
|
+
if (this.markdownChunkBuffer.length > 0) {
|
|
396
|
+
if (!this.markdownStarted) {
|
|
397
|
+
await this.downstream.markdownStart();
|
|
398
|
+
this.markdownStarted = true;
|
|
399
|
+
}
|
|
400
|
+
await this.downstream.markdownChunk(this.markdownChunkBuffer);
|
|
401
|
+
this.markdownChunkBuffer = '';
|
|
402
|
+
}
|
|
403
|
+
const call = this.activeCall;
|
|
404
|
+
if (call) {
|
|
405
|
+
if (call.callLineIndex === 0) {
|
|
406
|
+
const parse = call.firstLineMentionParse;
|
|
407
|
+
if (parse.kind === 'pending_mention_chars' && parse.raw.length > 0) {
|
|
408
|
+
// Do nothing: we cannot resolve until a delimiter/newline/EOF.
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
await this.flushHeadlineBuffer();
|
|
412
|
+
if (call.bodyStarted) {
|
|
413
|
+
await this.flushBodyBuffer();
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
isValidMentionChar(char) {
|
|
418
|
+
const charCode = char.charCodeAt(0);
|
|
419
|
+
return (
|
|
420
|
+
// ASCII alphanumeric: a-z, A-Z, 0-9
|
|
421
|
+
(charCode >= 48 && charCode <= 57) ||
|
|
422
|
+
(charCode >= 65 && charCode <= 90) ||
|
|
423
|
+
(charCode >= 97 && charCode <= 122) ||
|
|
424
|
+
// Special allowed characters
|
|
425
|
+
char === '_' ||
|
|
426
|
+
char === '-' ||
|
|
427
|
+
char === '.' ||
|
|
428
|
+
// Unicode letters and digits
|
|
429
|
+
/\p{L}/u.test(char) ||
|
|
430
|
+
/\p{N}/u.test(char));
|
|
431
|
+
}
|
|
432
|
+
trimTrailingDots(value) {
|
|
433
|
+
let out = value;
|
|
434
|
+
while (out.endsWith('.'))
|
|
435
|
+
out = out.slice(0, -1);
|
|
436
|
+
return out;
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
exports.TellaskStreamParser = TellaskStreamParser;
|