cwtools-shared 0.1.0 → 0.2.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/dist/generated/mcpTools.d.ts +132 -3
- package/dist/generated/mcpTools.js +141 -2
- package/dist/host/indexing.d.ts +5 -0
- package/dist/project/knowledge.js +28 -91
- package/dist/project/profile.d.ts +16 -2
- package/dist/project/profile.js +14 -3
- package/dist/tools/names.d.ts +2 -2
- package/dist/tools/names.js +3 -0
- package/dist/tools/toolHandlers.js +67 -1
- package/package.json +1 -1
|
@@ -317,7 +317,7 @@ export declare const GENERATED_MCP_TOOLS: readonly [{
|
|
|
317
317
|
readonly properties: {
|
|
318
318
|
readonly section: {
|
|
319
319
|
readonly type: "string";
|
|
320
|
-
readonly enum: readonly ["summary", "routing", "directories", "localisation", "identifiers", "validation", "promptCards", "all"];
|
|
320
|
+
readonly enum: readonly ["summary", "routing", "directories", "localisation", "identifiers", "validation", "compatibility", "promptCards", "all"];
|
|
321
321
|
readonly description: "Targeted profile section to return. Default summary. Use all only when you need the whole profile.";
|
|
322
322
|
};
|
|
323
323
|
readonly mode: {
|
|
@@ -450,7 +450,11 @@ export declare const GENERATED_MCP_TOOLS: readonly [{
|
|
|
450
450
|
};
|
|
451
451
|
readonly includeReferences: {
|
|
452
452
|
readonly type: "boolean";
|
|
453
|
-
readonly description: "
|
|
453
|
+
readonly description: "Include lightweight cross-file reference contexts. Default false.";
|
|
454
|
+
};
|
|
455
|
+
readonly includeAssetChain: {
|
|
456
|
+
readonly type: "boolean";
|
|
457
|
+
readonly description: "Check bounded GUI/GFX/model targets, path case, and DDS frame layout.";
|
|
454
458
|
};
|
|
455
459
|
readonly limit: {
|
|
456
460
|
readonly type: "number";
|
|
@@ -471,7 +475,7 @@ export declare const GENERATED_MCP_TOOLS: readonly [{
|
|
|
471
475
|
}, {
|
|
472
476
|
readonly tool: {
|
|
473
477
|
readonly name: "explore_pdx_project";
|
|
474
|
-
readonly description: "Primary semantic exploration
|
|
478
|
+
readonly description: "Primary semantic exploration for large Paradox projects: live CWTools type/reference graph with bounded nodes, edges, file facts, provenance and freshness. Use FIRST for connectivity and impact; follow with exact query_rules/query_scope/query_types/get_pdx_block before writing.";
|
|
475
479
|
readonly inputSchema: {
|
|
476
480
|
readonly type: "object";
|
|
477
481
|
readonly properties: {
|
|
@@ -513,6 +517,14 @@ export declare const GENERATED_MCP_TOOLS: readonly [{
|
|
|
513
517
|
readonly type: "boolean";
|
|
514
518
|
readonly description: "Include documentation, variables, event targets, and block metadata. Default true.";
|
|
515
519
|
};
|
|
520
|
+
readonly relationshipKinds: {
|
|
521
|
+
readonly type: "array";
|
|
522
|
+
readonly items: {
|
|
523
|
+
readonly type: "string";
|
|
524
|
+
readonly enum: readonly ["inline_invocation", "inline_expansion"];
|
|
525
|
+
};
|
|
526
|
+
readonly description: "Extra graph kinds: inline_invocation or inline_expansion.";
|
|
527
|
+
};
|
|
516
528
|
};
|
|
517
529
|
readonly required: readonly [];
|
|
518
530
|
};
|
|
@@ -525,6 +537,103 @@ export declare const GENERATED_MCP_TOOLS: readonly [{
|
|
|
525
537
|
readonly riskLevel: 0;
|
|
526
538
|
readonly concurrencyClass: "lsp-limited";
|
|
527
539
|
};
|
|
540
|
+
}, {
|
|
541
|
+
readonly tool: {
|
|
542
|
+
readonly name: "query_inline_instantiation";
|
|
543
|
+
readonly description: "Preview one inline_script template instantiation: parameters, arguments, expanded symbol, and problems (missing/unused/unresolved). Precise template path or file+line only; no whole-project expansion. Use before editing a template or caller.";
|
|
544
|
+
readonly inputSchema: {
|
|
545
|
+
readonly type: "object";
|
|
546
|
+
readonly properties: {
|
|
547
|
+
readonly template: {
|
|
548
|
+
readonly type: "string";
|
|
549
|
+
readonly description: "Template path, e.g. common/inline_scripts/example.txt.";
|
|
550
|
+
};
|
|
551
|
+
readonly file: {
|
|
552
|
+
readonly type: "string";
|
|
553
|
+
readonly description: "Caller file; narrows to one invocation.";
|
|
554
|
+
};
|
|
555
|
+
readonly line: {
|
|
556
|
+
readonly type: "number";
|
|
557
|
+
readonly description: "Caller line; combined with file selects one invocation.";
|
|
558
|
+
};
|
|
559
|
+
readonly limit: {
|
|
560
|
+
readonly type: "number";
|
|
561
|
+
readonly description: "Maximum invocations to return. Default 50, max 200.";
|
|
562
|
+
};
|
|
563
|
+
};
|
|
564
|
+
readonly required: readonly [];
|
|
565
|
+
};
|
|
566
|
+
};
|
|
567
|
+
readonly registry: {
|
|
568
|
+
readonly name: "query_inline_instantiation";
|
|
569
|
+
readonly isWrite: false;
|
|
570
|
+
readonly isReadOnly: true;
|
|
571
|
+
readonly effect: "workspace_read";
|
|
572
|
+
readonly riskLevel: 0;
|
|
573
|
+
readonly concurrencyClass: "lsp-limited";
|
|
574
|
+
};
|
|
575
|
+
}, {
|
|
576
|
+
readonly tool: {
|
|
577
|
+
readonly name: "analyze_pdx_flow";
|
|
578
|
+
readonly description: "Static cost model and gameplay relations for a file or definition: traversals (every_*/while), pulse handlers, nested fan-out, and typed edges (tech prerequisites, special project events, megastructure upgrades). Relative weights only.";
|
|
579
|
+
readonly inputSchema: {
|
|
580
|
+
readonly type: "object";
|
|
581
|
+
readonly properties: {
|
|
582
|
+
readonly file: {
|
|
583
|
+
readonly type: "string";
|
|
584
|
+
readonly description: "Optional file path to analyze; when omitted a definitionId must be given.";
|
|
585
|
+
};
|
|
586
|
+
readonly definitionId: {
|
|
587
|
+
readonly type: "string";
|
|
588
|
+
readonly description: "Optional exact definition ID; combined with file to scope the analysis.";
|
|
589
|
+
};
|
|
590
|
+
readonly entityType: {
|
|
591
|
+
readonly type: "string";
|
|
592
|
+
readonly description: "Optional exact CWTools entity type; use with definitionId to disambiguate duplicate IDs.";
|
|
593
|
+
};
|
|
594
|
+
readonly limit: {
|
|
595
|
+
readonly type: "number";
|
|
596
|
+
readonly description: "Maximum costs and relations returned per collection. Default 100, max 500.";
|
|
597
|
+
};
|
|
598
|
+
};
|
|
599
|
+
readonly required: readonly [];
|
|
600
|
+
};
|
|
601
|
+
};
|
|
602
|
+
readonly registry: {
|
|
603
|
+
readonly name: "analyze_pdx_flow";
|
|
604
|
+
readonly isWrite: false;
|
|
605
|
+
readonly isReadOnly: true;
|
|
606
|
+
readonly effect: "workspace_read";
|
|
607
|
+
readonly riskLevel: 0;
|
|
608
|
+
readonly concurrencyClass: "lsp-limited";
|
|
609
|
+
};
|
|
610
|
+
}, {
|
|
611
|
+
readonly tool: {
|
|
612
|
+
readonly name: "compare_definition_with_vanilla";
|
|
613
|
+
readonly description: "Field-level diff of one definition against its vanilla counterpart: added, removed and modified fields with stable source locations. Accepts exact entityType + symbolId only; returns the resolved winner and never fabricates a conclusion when the winner is ambiguous. Use before editing any file that overrides vanilla.";
|
|
614
|
+
readonly inputSchema: {
|
|
615
|
+
readonly type: "object";
|
|
616
|
+
readonly properties: {
|
|
617
|
+
readonly entityType: {
|
|
618
|
+
readonly type: "string";
|
|
619
|
+
readonly description: "Exact CWTools type name (e.g. event, technology, ship_size).";
|
|
620
|
+
};
|
|
621
|
+
readonly symbolId: {
|
|
622
|
+
readonly type: "string";
|
|
623
|
+
readonly description: "Exact definition ID shared by workspace and vanilla candidates.";
|
|
624
|
+
};
|
|
625
|
+
};
|
|
626
|
+
readonly required: readonly ["entityType", "symbolId"];
|
|
627
|
+
};
|
|
628
|
+
};
|
|
629
|
+
readonly registry: {
|
|
630
|
+
readonly name: "compare_definition_with_vanilla";
|
|
631
|
+
readonly isWrite: false;
|
|
632
|
+
readonly isReadOnly: true;
|
|
633
|
+
readonly effect: "workspace_read";
|
|
634
|
+
readonly riskLevel: 0;
|
|
635
|
+
readonly concurrencyClass: "lsp-limited";
|
|
636
|
+
};
|
|
528
637
|
}, {
|
|
529
638
|
readonly tool: {
|
|
530
639
|
readonly name: "query_localisation_index";
|
|
@@ -552,6 +661,26 @@ export declare const GENERATED_MCP_TOOLS: readonly [{
|
|
|
552
661
|
readonly type: "boolean";
|
|
553
662
|
readonly description: "Only applies to prefix/contains searches. Default false.";
|
|
554
663
|
};
|
|
664
|
+
readonly includeDuplicates: {
|
|
665
|
+
readonly type: "boolean";
|
|
666
|
+
readonly description: "Include per-key duplicate groups with all occurrences (file/line), so duplicate keys are auditable instead of trusting the last write. Default false.";
|
|
667
|
+
};
|
|
668
|
+
readonly compareLanguages: {
|
|
669
|
+
readonly type: "boolean";
|
|
670
|
+
readonly description: "Include true missing/extra key-set differences per language, independent of result truncation. Default false.";
|
|
671
|
+
};
|
|
672
|
+
readonly referenceLanguage: {
|
|
673
|
+
readonly type: "string";
|
|
674
|
+
readonly description: "Reference language for missing/extra differences. Defaults to l_english when indexed.";
|
|
675
|
+
};
|
|
676
|
+
readonly referenceStatus: {
|
|
677
|
+
readonly type: "boolean";
|
|
678
|
+
readonly description: "Include bounded LSP reference status and origin; dynamic keys remain uncertain.";
|
|
679
|
+
};
|
|
680
|
+
readonly auditMode: {
|
|
681
|
+
readonly type: "boolean";
|
|
682
|
+
readonly description: "Include authoritative CWTools localisation diagnostics: completely missing script-referenced keys, inline/dynamic-key provenance, and localisation command/scope issues.";
|
|
683
|
+
};
|
|
555
684
|
readonly limit: {
|
|
556
685
|
readonly type: "number";
|
|
557
686
|
readonly description: "Maximum entries to return. Default 20, max 100.";
|
|
@@ -368,6 +368,7 @@ exports.GENERATED_MCP_TOOLS = [
|
|
|
368
368
|
"localisation",
|
|
369
369
|
"identifiers",
|
|
370
370
|
"validation",
|
|
371
|
+
"compatibility",
|
|
371
372
|
"promptCards",
|
|
372
373
|
"all"
|
|
373
374
|
],
|
|
@@ -527,7 +528,11 @@ exports.GENERATED_MCP_TOOLS = [
|
|
|
527
528
|
},
|
|
528
529
|
"includeReferences": {
|
|
529
530
|
"type": "boolean",
|
|
530
|
-
"description": "
|
|
531
|
+
"description": "Include lightweight cross-file reference contexts. Default false."
|
|
532
|
+
},
|
|
533
|
+
"includeAssetChain": {
|
|
534
|
+
"type": "boolean",
|
|
535
|
+
"description": "Check bounded GUI/GFX/model targets, path case, and DDS frame layout."
|
|
531
536
|
},
|
|
532
537
|
"limit": {
|
|
533
538
|
"type": "number",
|
|
@@ -549,7 +554,7 @@ exports.GENERATED_MCP_TOOLS = [
|
|
|
549
554
|
{
|
|
550
555
|
"tool": {
|
|
551
556
|
"name": "explore_pdx_project",
|
|
552
|
-
"description": "Primary semantic exploration
|
|
557
|
+
"description": "Primary semantic exploration for large Paradox projects: live CWTools type/reference graph with bounded nodes, edges, file facts, provenance and freshness. Use FIRST for connectivity and impact; follow with exact query_rules/query_scope/query_types/get_pdx_block before writing.",
|
|
553
558
|
"inputSchema": {
|
|
554
559
|
"type": "object",
|
|
555
560
|
"properties": {
|
|
@@ -590,6 +595,17 @@ exports.GENERATED_MCP_TOOLS = [
|
|
|
590
595
|
"includeMetadata": {
|
|
591
596
|
"type": "boolean",
|
|
592
597
|
"description": "Include documentation, variables, event targets, and block metadata. Default true."
|
|
598
|
+
},
|
|
599
|
+
"relationshipKinds": {
|
|
600
|
+
"type": "array",
|
|
601
|
+
"items": {
|
|
602
|
+
"type": "string",
|
|
603
|
+
"enum": [
|
|
604
|
+
"inline_invocation",
|
|
605
|
+
"inline_expansion"
|
|
606
|
+
]
|
|
607
|
+
},
|
|
608
|
+
"description": "Extra graph kinds: inline_invocation or inline_expansion."
|
|
593
609
|
}
|
|
594
610
|
},
|
|
595
611
|
"required": []
|
|
@@ -604,6 +620,109 @@ exports.GENERATED_MCP_TOOLS = [
|
|
|
604
620
|
"concurrencyClass": "lsp-limited"
|
|
605
621
|
}
|
|
606
622
|
},
|
|
623
|
+
{
|
|
624
|
+
"tool": {
|
|
625
|
+
"name": "query_inline_instantiation",
|
|
626
|
+
"description": "Preview one inline_script template instantiation: parameters, arguments, expanded symbol, and problems (missing/unused/unresolved). Precise template path or file+line only; no whole-project expansion. Use before editing a template or caller.",
|
|
627
|
+
"inputSchema": {
|
|
628
|
+
"type": "object",
|
|
629
|
+
"properties": {
|
|
630
|
+
"template": {
|
|
631
|
+
"type": "string",
|
|
632
|
+
"description": "Template path, e.g. common/inline_scripts/example.txt."
|
|
633
|
+
},
|
|
634
|
+
"file": {
|
|
635
|
+
"type": "string",
|
|
636
|
+
"description": "Caller file; narrows to one invocation."
|
|
637
|
+
},
|
|
638
|
+
"line": {
|
|
639
|
+
"type": "number",
|
|
640
|
+
"description": "Caller line; combined with file selects one invocation."
|
|
641
|
+
},
|
|
642
|
+
"limit": {
|
|
643
|
+
"type": "number",
|
|
644
|
+
"description": "Maximum invocations to return. Default 50, max 200."
|
|
645
|
+
}
|
|
646
|
+
},
|
|
647
|
+
"required": []
|
|
648
|
+
}
|
|
649
|
+
},
|
|
650
|
+
"registry": {
|
|
651
|
+
"name": "query_inline_instantiation",
|
|
652
|
+
"isWrite": false,
|
|
653
|
+
"isReadOnly": true,
|
|
654
|
+
"effect": "workspace_read",
|
|
655
|
+
"riskLevel": 0,
|
|
656
|
+
"concurrencyClass": "lsp-limited"
|
|
657
|
+
}
|
|
658
|
+
},
|
|
659
|
+
{
|
|
660
|
+
"tool": {
|
|
661
|
+
"name": "analyze_pdx_flow",
|
|
662
|
+
"description": "Static cost model and gameplay relations for a file or definition: traversals (every_*/while), pulse handlers, nested fan-out, and typed edges (tech prerequisites, special project events, megastructure upgrades). Relative weights only.",
|
|
663
|
+
"inputSchema": {
|
|
664
|
+
"type": "object",
|
|
665
|
+
"properties": {
|
|
666
|
+
"file": {
|
|
667
|
+
"type": "string",
|
|
668
|
+
"description": "Optional file path to analyze; when omitted a definitionId must be given."
|
|
669
|
+
},
|
|
670
|
+
"definitionId": {
|
|
671
|
+
"type": "string",
|
|
672
|
+
"description": "Optional exact definition ID; combined with file to scope the analysis."
|
|
673
|
+
},
|
|
674
|
+
"entityType": {
|
|
675
|
+
"type": "string",
|
|
676
|
+
"description": "Optional exact CWTools entity type; use with definitionId to disambiguate duplicate IDs."
|
|
677
|
+
},
|
|
678
|
+
"limit": {
|
|
679
|
+
"type": "number",
|
|
680
|
+
"description": "Maximum costs and relations returned per collection. Default 100, max 500."
|
|
681
|
+
}
|
|
682
|
+
},
|
|
683
|
+
"required": []
|
|
684
|
+
}
|
|
685
|
+
},
|
|
686
|
+
"registry": {
|
|
687
|
+
"name": "analyze_pdx_flow",
|
|
688
|
+
"isWrite": false,
|
|
689
|
+
"isReadOnly": true,
|
|
690
|
+
"effect": "workspace_read",
|
|
691
|
+
"riskLevel": 0,
|
|
692
|
+
"concurrencyClass": "lsp-limited"
|
|
693
|
+
}
|
|
694
|
+
},
|
|
695
|
+
{
|
|
696
|
+
"tool": {
|
|
697
|
+
"name": "compare_definition_with_vanilla",
|
|
698
|
+
"description": "Field-level diff of one definition against its vanilla counterpart: added, removed and modified fields with stable source locations. Accepts exact entityType + symbolId only; returns the resolved winner and never fabricates a conclusion when the winner is ambiguous. Use before editing any file that overrides vanilla.",
|
|
699
|
+
"inputSchema": {
|
|
700
|
+
"type": "object",
|
|
701
|
+
"properties": {
|
|
702
|
+
"entityType": {
|
|
703
|
+
"type": "string",
|
|
704
|
+
"description": "Exact CWTools type name (e.g. event, technology, ship_size)."
|
|
705
|
+
},
|
|
706
|
+
"symbolId": {
|
|
707
|
+
"type": "string",
|
|
708
|
+
"description": "Exact definition ID shared by workspace and vanilla candidates."
|
|
709
|
+
}
|
|
710
|
+
},
|
|
711
|
+
"required": [
|
|
712
|
+
"entityType",
|
|
713
|
+
"symbolId"
|
|
714
|
+
]
|
|
715
|
+
}
|
|
716
|
+
},
|
|
717
|
+
"registry": {
|
|
718
|
+
"name": "compare_definition_with_vanilla",
|
|
719
|
+
"isWrite": false,
|
|
720
|
+
"isReadOnly": true,
|
|
721
|
+
"effect": "workspace_read",
|
|
722
|
+
"riskLevel": 0,
|
|
723
|
+
"concurrencyClass": "lsp-limited"
|
|
724
|
+
}
|
|
725
|
+
},
|
|
607
726
|
{
|
|
608
727
|
"tool": {
|
|
609
728
|
"name": "query_localisation_index",
|
|
@@ -631,6 +750,26 @@ exports.GENERATED_MCP_TOOLS = [
|
|
|
631
750
|
"type": "boolean",
|
|
632
751
|
"description": "Only applies to prefix/contains searches. Default false."
|
|
633
752
|
},
|
|
753
|
+
"includeDuplicates": {
|
|
754
|
+
"type": "boolean",
|
|
755
|
+
"description": "Include per-key duplicate groups with all occurrences (file/line), so duplicate keys are auditable instead of trusting the last write. Default false."
|
|
756
|
+
},
|
|
757
|
+
"compareLanguages": {
|
|
758
|
+
"type": "boolean",
|
|
759
|
+
"description": "Include true missing/extra key-set differences per language, independent of result truncation. Default false."
|
|
760
|
+
},
|
|
761
|
+
"referenceLanguage": {
|
|
762
|
+
"type": "string",
|
|
763
|
+
"description": "Reference language for missing/extra differences. Defaults to l_english when indexed."
|
|
764
|
+
},
|
|
765
|
+
"referenceStatus": {
|
|
766
|
+
"type": "boolean",
|
|
767
|
+
"description": "Include bounded LSP reference status and origin; dynamic keys remain uncertain."
|
|
768
|
+
},
|
|
769
|
+
"auditMode": {
|
|
770
|
+
"type": "boolean",
|
|
771
|
+
"description": "Include authoritative CWTools localisation diagnostics: completely missing script-referenced keys, inline/dynamic-key provenance, and localisation command/scope issues."
|
|
772
|
+
},
|
|
634
773
|
"limit": {
|
|
635
774
|
"type": "number",
|
|
636
775
|
"description": "Maximum entries to return. Default 20, max 100."
|
package/dist/host/indexing.d.ts
CHANGED
|
@@ -28,6 +28,11 @@ export interface LocalisationIndexQuery {
|
|
|
28
28
|
prefix?: boolean;
|
|
29
29
|
contains?: boolean;
|
|
30
30
|
caseSensitive?: boolean;
|
|
31
|
+
includeDuplicates?: boolean;
|
|
32
|
+
compareLanguages?: boolean;
|
|
33
|
+
referenceLanguage?: string;
|
|
34
|
+
referenceStatus?: boolean;
|
|
35
|
+
auditMode?: boolean;
|
|
31
36
|
limit?: number;
|
|
32
37
|
}
|
|
33
38
|
export interface LocalisationIndexEntry {
|
|
@@ -36,6 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
36
36
|
exports.queryProjectKnowledgeWithHost = queryProjectKnowledgeWithHost;
|
|
37
37
|
const path = __importStar(require("path"));
|
|
38
38
|
const KNOWLEDGE_DIR = path.join('.cwtools', 'project', 'knowledge');
|
|
39
|
+
const CURRENT_KNOWLEDGE_SCHEMA_VERSION = 7;
|
|
39
40
|
function asRecord(value) {
|
|
40
41
|
return value && typeof value === 'object' && !Array.isArray(value)
|
|
41
42
|
? value
|
|
@@ -44,19 +45,6 @@ function asRecord(value) {
|
|
|
44
45
|
function stringArray(value) {
|
|
45
46
|
return Array.isArray(value) ? value.filter((item) => typeof item === 'string') : [];
|
|
46
47
|
}
|
|
47
|
-
function tokensFor(args) {
|
|
48
|
-
return [args.intent ?? '', ...(args.identifiers ?? []), ...(args.entityTypes ?? [])]
|
|
49
|
-
.join(' ')
|
|
50
|
-
.toLowerCase()
|
|
51
|
-
.match(/[@a-z0-9_.:-]{2,}/g)
|
|
52
|
-
?.slice(0, 30) ?? [];
|
|
53
|
-
}
|
|
54
|
-
function score(value, tokens) {
|
|
55
|
-
if (tokens.length === 0)
|
|
56
|
-
return 1;
|
|
57
|
-
const text = JSON.stringify(value).toLowerCase();
|
|
58
|
-
return tokens.reduce((total, token) => total + (text.includes(token) ? 3 : 0), 0);
|
|
59
|
-
}
|
|
60
48
|
async function readJson(host, filePath) {
|
|
61
49
|
const read = await host.filesystem.readTextFile(filePath);
|
|
62
50
|
if (!read.exists)
|
|
@@ -69,19 +57,9 @@ async function readJson(host, filePath) {
|
|
|
69
57
|
}
|
|
70
58
|
}
|
|
71
59
|
async function queryProjectKnowledgeWithHost(host, args = {}) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (!manifest) {
|
|
76
|
-
const legacyRoot = path.join(host.workspaceRoot, '.cwtools-ai', 'project', 'knowledge');
|
|
77
|
-
const legacyManifestPath = path.join(legacyRoot, 'manifest.json');
|
|
78
|
-
const legacyManifest = await readJson(host, legacyManifestPath);
|
|
79
|
-
if (legacyManifest) {
|
|
80
|
-
root = legacyRoot;
|
|
81
|
-
manifestPath = legacyManifestPath;
|
|
82
|
-
manifest = legacyManifest;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
60
|
+
const root = path.join(host.workspaceRoot, KNOWLEDGE_DIR);
|
|
61
|
+
const manifestPath = path.join(root, 'manifest.json');
|
|
62
|
+
const manifest = await readJson(host, manifestPath);
|
|
85
63
|
if (!manifest) {
|
|
86
64
|
return {
|
|
87
65
|
ok: false,
|
|
@@ -98,8 +76,30 @@ async function queryProjectKnowledgeWithHost(host, args = {}) {
|
|
|
98
76
|
},
|
|
99
77
|
};
|
|
100
78
|
}
|
|
101
|
-
|
|
102
|
-
|
|
79
|
+
const database = asRecord(manifest.database);
|
|
80
|
+
const foundSchemaVersion = Number(database.schemaVersion ?? manifest.schemaVersion) || 0;
|
|
81
|
+
if (Number(manifest.schemaVersion) !== CURRENT_KNOWLEDGE_SCHEMA_VERSION
|
|
82
|
+
|| foundSchemaVersion !== CURRENT_KNOWLEDGE_SCHEMA_VERSION) {
|
|
83
|
+
return {
|
|
84
|
+
ok: false,
|
|
85
|
+
status: 'stale',
|
|
86
|
+
source: 'cwtools-project-knowledge-sqlite',
|
|
87
|
+
error: {
|
|
88
|
+
code: 'knowledge_schema_obsolete',
|
|
89
|
+
message: `Project knowledge schema V${foundSchemaVersion} is obsolete. Rebuild it with the current V${CURRENT_KNOWLEDGE_SCHEMA_VERSION} extension.`,
|
|
90
|
+
},
|
|
91
|
+
data: {
|
|
92
|
+
status: 'stale',
|
|
93
|
+
manifestPath,
|
|
94
|
+
rebuildRequired: true,
|
|
95
|
+
foundSchemaVersion,
|
|
96
|
+
currentSchemaVersion: CURRENT_KNOWLEDGE_SCHEMA_VERSION,
|
|
97
|
+
staleReasons: ['schema_version_obsolete'],
|
|
98
|
+
_hint: 'Run /init or reopen the project and wait for the automatic full rebuild. Old database schemas are not queried.',
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
{
|
|
103
103
|
const relativeDatabasePath = typeof database.path === 'string' && database.path.trim()
|
|
104
104
|
? database.path
|
|
105
105
|
: 'knowledge.sqlite';
|
|
@@ -143,67 +143,4 @@ async function queryProjectKnowledgeWithHost(host, args = {}) {
|
|
|
143
143
|
},
|
|
144
144
|
};
|
|
145
145
|
}
|
|
146
|
-
const manifestDomains = stringArray(manifest.domains);
|
|
147
|
-
const domains = (args.domains?.length ? args.domains : manifestDomains)
|
|
148
|
-
.map(value => value.trim().toLowerCase())
|
|
149
|
-
.filter(Boolean)
|
|
150
|
-
.slice(0, 12);
|
|
151
|
-
const tokens = tokensFor(args);
|
|
152
|
-
const limit = Math.max(1, Math.min(Number(args.limit ?? 80) || 80, 300));
|
|
153
|
-
const evidence = [];
|
|
154
|
-
const capabilities = [];
|
|
155
|
-
for (const domain of domains) {
|
|
156
|
-
const capability = await readJson(host, path.join(root, 'capabilities', `${domain}.json`));
|
|
157
|
-
if (!capability)
|
|
158
|
-
continue;
|
|
159
|
-
capabilities.push({ domain, summary: capability.summary, evidencePolicy: capability.evidencePolicy });
|
|
160
|
-
const candidates = [];
|
|
161
|
-
if (Array.isArray(capability.definitions))
|
|
162
|
-
candidates.push(...capability.definitions.map(asRecord));
|
|
163
|
-
if (args.includeProjectPatterns !== false && Array.isArray(capability.projectExamples))
|
|
164
|
-
candidates.push(...capability.projectExamples.map(asRecord));
|
|
165
|
-
if (args.includeVanillaArchetypes !== false && Array.isArray(capability.vanillaArchetypes))
|
|
166
|
-
candidates.push(...capability.vanillaArchetypes.map(asRecord));
|
|
167
|
-
if (args.includeTopology !== false) {
|
|
168
|
-
const topology = asRecord(capability.topology);
|
|
169
|
-
if (Array.isArray(topology.edges))
|
|
170
|
-
candidates.push(...topology.edges.map(asRecord));
|
|
171
|
-
}
|
|
172
|
-
evidence.push(...candidates
|
|
173
|
-
.map(item => ({ ...item, domain, score: score(item, tokens) }))
|
|
174
|
-
.filter(item => tokens.length === 0 || Number(item.score) > 0)
|
|
175
|
-
.sort((a, b) => Number(b.score) - Number(a.score))
|
|
176
|
-
.slice(0, Math.max(5, Math.ceil(limit / Math.max(1, domains.length)))));
|
|
177
|
-
}
|
|
178
|
-
const unresolvedFile = args.includeUnresolved === false
|
|
179
|
-
? undefined
|
|
180
|
-
: await readJson(host, path.join(root, 'unresolved.json'));
|
|
181
|
-
const unresolved = Array.isArray(unresolvedFile?.entries)
|
|
182
|
-
? unresolvedFile.entries.map(asRecord).slice(0, 100)
|
|
183
|
-
: [];
|
|
184
|
-
const manifestStatus = String(manifest.status ?? 'stale');
|
|
185
|
-
const staleReasons = stringArray(manifest.staleReasons);
|
|
186
|
-
const ready = manifestStatus === 'ready' && staleReasons.length === 0;
|
|
187
|
-
return {
|
|
188
|
-
ok: true,
|
|
189
|
-
status: ready ? 'ready' : 'stale',
|
|
190
|
-
source: 'cwtools-project-knowledge',
|
|
191
|
-
data: {
|
|
192
|
-
status: ready ? 'ready' : 'stale',
|
|
193
|
-
manifestPath,
|
|
194
|
-
generatedAt: manifest.generatedAt,
|
|
195
|
-
game: manifest.game,
|
|
196
|
-
graphVersion: manifest.graphVersion,
|
|
197
|
-
staleReasons,
|
|
198
|
-
domains,
|
|
199
|
-
capabilities,
|
|
200
|
-
evidence: evidence.slice(0, limit),
|
|
201
|
-
unresolved,
|
|
202
|
-
requiredNextChecks: [
|
|
203
|
-
'Use query_cwt_schema/query_rules/query_scope for legality before writing.',
|
|
204
|
-
'Use query_override_modes for target directories with vanilla definitions.',
|
|
205
|
-
'Read exact source blocks before approving a complex blueprint.',
|
|
206
|
-
],
|
|
207
|
-
},
|
|
208
|
-
};
|
|
209
146
|
}
|
|
@@ -2,21 +2,31 @@ import type { HostServices } from '../host/hostServices';
|
|
|
2
2
|
import type { SharedToolResult } from '../tools/schema';
|
|
3
3
|
export type AgentMode = 'build' | 'plan' | 'explore' | 'general' | 'utility' | 'review' | 'gui_expert' | 'script_reviewer' | 'loc_translator' | 'loc_writer' | 'orchestrator' | 'script';
|
|
4
4
|
export interface QueryProjectProfileArgs {
|
|
5
|
-
section?: 'summary' | 'routing' | 'directories' | 'localisation' | 'identifiers' | 'validation' | 'promptCards' | 'all';
|
|
5
|
+
section?: 'summary' | 'routing' | 'directories' | 'localisation' | 'identifiers' | 'validation' | 'compatibility' | 'promptCards' | 'all';
|
|
6
6
|
mode?: AgentMode | 'asset';
|
|
7
7
|
}
|
|
8
8
|
export interface ProjectProfile {
|
|
9
|
-
schemaVersion:
|
|
9
|
+
schemaVersion: 2;
|
|
10
10
|
generatedAt: string;
|
|
11
11
|
workspaceRoot: string;
|
|
12
12
|
workspaceKind: string;
|
|
13
13
|
projectName: string;
|
|
14
|
+
/** True when a schemaVersion 1 profile was read and normalized. */
|
|
15
|
+
legacyProfile?: boolean;
|
|
14
16
|
game: {
|
|
15
17
|
id: string;
|
|
16
18
|
displayName: string;
|
|
17
19
|
confidence: 'high' | 'medium' | 'low';
|
|
18
20
|
evidence: string[];
|
|
19
21
|
};
|
|
22
|
+
modInfo?: {
|
|
23
|
+
name?: string;
|
|
24
|
+
version?: string;
|
|
25
|
+
tags?: string[];
|
|
26
|
+
supportedVersion?: string;
|
|
27
|
+
remoteFileId?: string;
|
|
28
|
+
dependencies?: string[];
|
|
29
|
+
};
|
|
20
30
|
keyDirectories: Array<{
|
|
21
31
|
key: string;
|
|
22
32
|
path: string;
|
|
@@ -26,12 +36,16 @@ export interface ProjectProfile {
|
|
|
26
36
|
localisation: {
|
|
27
37
|
roots: string[];
|
|
28
38
|
languages: string[];
|
|
39
|
+
defaultLanguage?: string;
|
|
29
40
|
encoding: string;
|
|
41
|
+
encodingByLanguage?: Record<string, string>;
|
|
30
42
|
sampleFiles: string[];
|
|
31
43
|
};
|
|
32
44
|
identifiers: Record<string, unknown>;
|
|
33
45
|
routing: Record<string, unknown>;
|
|
34
46
|
validation: Record<string, unknown>;
|
|
47
|
+
freshness?: Record<string, unknown>;
|
|
48
|
+
warnings?: string[];
|
|
35
49
|
promptCards: Partial<Record<AgentMode | 'asset', string>>;
|
|
36
50
|
efficiencyHints: string[];
|
|
37
51
|
[key: string]: unknown;
|
package/dist/project/profile.js
CHANGED
|
@@ -60,7 +60,7 @@ function getProjectProfilePath(workspaceRoot) {
|
|
|
60
60
|
function isProjectProfile(value) {
|
|
61
61
|
return !!value
|
|
62
62
|
&& typeof value === 'object'
|
|
63
|
-
&& value.schemaVersion === 1
|
|
63
|
+
&& (value.schemaVersion === 1 || value.schemaVersion === 2)
|
|
64
64
|
&& typeof value.projectName === 'string';
|
|
65
65
|
}
|
|
66
66
|
function buildProfileSummary(profile) {
|
|
@@ -69,10 +69,11 @@ function buildProfileSummary(profile) {
|
|
|
69
69
|
? profile.identifiers.namespaces.slice(0, 8).join(', ') || 'none'
|
|
70
70
|
: 'none';
|
|
71
71
|
const languages = profile.localisation.languages.join(', ') || 'unknown';
|
|
72
|
+
const supportedVersion = typeof profile.modInfo?.supportedVersion === 'string' ? ` (${profile.modInfo.supportedVersion})` : '';
|
|
72
73
|
return [
|
|
73
74
|
`Project: ${profile.projectName}`,
|
|
74
75
|
`Kind: ${profile.workspaceKind}`,
|
|
75
|
-
`Game: ${profile.game.displayName}`,
|
|
76
|
+
`Game: ${profile.game.displayName}${supportedVersion}`,
|
|
76
77
|
`Key dirs: ${dirs}`,
|
|
77
78
|
`Namespaces: ${namespaces}`,
|
|
78
79
|
`Localisation: ${languages} (${profile.localisation.encoding})`,
|
|
@@ -96,6 +97,13 @@ function selectProfileSection(profile, section) {
|
|
|
96
97
|
case 'localisation': return profile.localisation;
|
|
97
98
|
case 'identifiers': return profile.identifiers;
|
|
98
99
|
case 'validation': return profile.validation;
|
|
100
|
+
case 'compatibility': return {
|
|
101
|
+
supportedVersion: profile.modInfo?.supportedVersion,
|
|
102
|
+
remoteFileId: profile.modInfo?.remoteFileId,
|
|
103
|
+
dependencies: profile.modInfo?.dependencies ?? [],
|
|
104
|
+
vanillaCache: profile.validation?.vanillaCache,
|
|
105
|
+
game: profile.game,
|
|
106
|
+
};
|
|
99
107
|
case 'promptCards': return profile.promptCards;
|
|
100
108
|
case 'all': return profile;
|
|
101
109
|
case 'summary':
|
|
@@ -104,7 +112,10 @@ function selectProfileSection(profile, section) {
|
|
|
104
112
|
workspaceKind: profile.workspaceKind,
|
|
105
113
|
projectName: profile.projectName,
|
|
106
114
|
game: profile.game,
|
|
115
|
+
supportedVersion: profile.modInfo?.supportedVersion,
|
|
107
116
|
generatedAt: profile.generatedAt,
|
|
117
|
+
freshness: profile.freshness,
|
|
118
|
+
warnings: profile.warnings ?? [],
|
|
108
119
|
efficiencyHints: profile.efficiencyHints,
|
|
109
120
|
};
|
|
110
121
|
}
|
|
@@ -137,7 +148,7 @@ async function queryProjectProfileWithHost(host, args = {}) {
|
|
|
137
148
|
source: 'cwtools-shared',
|
|
138
149
|
error: {
|
|
139
150
|
code: 'invalid_profile',
|
|
140
|
-
message: 'Project profile exists but is not schemaVersion 1.',
|
|
151
|
+
message: 'Project profile exists but is not a valid schemaVersion 1 or 2 profile.',
|
|
141
152
|
},
|
|
142
153
|
};
|
|
143
154
|
}
|
package/dist/tools/names.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export declare const MCP_TOOL_NAMES: readonly ["query_types", "query_rules", "query_cwt_schema", "search_rule_capabilities", "explain_scope", "parse_pdx_fragment", "query_scope", "get_diagnostics", "analyze_diagnostic_error", "query_project_profile", "query_project_knowledge", "query_workspace_index", "explore_pdx_project", "query_localisation_index", "get_pdx_block", "get_completion_at", "document_symbols", "workspace_symbols", "query_definition", "query_definition_by_name", "query_references", "query_scripted_effects", "query_scripted_triggers", "query_enums", "query_static_modifiers", "query_variables", "get_entity_info", "query_shader_symbol", "query_shader_compile_unit", "query_shader_platform_variants", "query_shader_callers", "explain_shader_reachability", "validate_shader", "compare_shader_with_vanilla"];
|
|
1
|
+
export declare const MCP_TOOL_NAMES: readonly ["query_types", "query_rules", "query_cwt_schema", "search_rule_capabilities", "explain_scope", "parse_pdx_fragment", "query_scope", "get_diagnostics", "analyze_diagnostic_error", "query_project_profile", "query_project_knowledge", "query_workspace_index", "explore_pdx_project", "query_inline_instantiation", "analyze_pdx_flow", "compare_definition_with_vanilla", "query_localisation_index", "get_pdx_block", "get_completion_at", "document_symbols", "workspace_symbols", "query_definition", "query_definition_by_name", "query_references", "query_scripted_effects", "query_scripted_triggers", "query_enums", "query_static_modifiers", "query_variables", "get_entity_info", "query_shader_symbol", "query_shader_compile_unit", "query_shader_platform_variants", "query_shader_callers", "explain_shader_reachability", "validate_shader", "compare_shader_with_vanilla"];
|
|
2
2
|
export type McpToolName = typeof MCP_TOOL_NAMES[number];
|
|
3
3
|
export declare const MCP_WRITE_TOOL_NAMES: readonly [];
|
|
4
|
-
export declare const MCP_READONLY_TOOL_NAMES: readonly ["query_types", "query_rules", "query_cwt_schema", "search_rule_capabilities", "explain_scope", "parse_pdx_fragment", "query_scope", "get_diagnostics", "analyze_diagnostic_error", "query_project_profile", "query_project_knowledge", "query_workspace_index", "explore_pdx_project", "query_localisation_index", "get_pdx_block", "get_completion_at", "document_symbols", "workspace_symbols", "query_definition", "query_definition_by_name", "query_references", "query_scripted_effects", "query_scripted_triggers", "query_enums", "query_static_modifiers", "query_variables", "get_entity_info", "query_shader_symbol", "query_shader_compile_unit", "query_shader_platform_variants", "query_shader_callers", "explain_shader_reachability", "validate_shader", "compare_shader_with_vanilla"];
|
|
4
|
+
export declare const MCP_READONLY_TOOL_NAMES: readonly ["query_types", "query_rules", "query_cwt_schema", "search_rule_capabilities", "explain_scope", "parse_pdx_fragment", "query_scope", "get_diagnostics", "analyze_diagnostic_error", "query_project_profile", "query_project_knowledge", "query_workspace_index", "explore_pdx_project", "query_inline_instantiation", "analyze_pdx_flow", "compare_definition_with_vanilla", "query_localisation_index", "get_pdx_block", "get_completion_at", "document_symbols", "workspace_symbols", "query_definition", "query_definition_by_name", "query_references", "query_scripted_effects", "query_scripted_triggers", "query_enums", "query_static_modifiers", "query_variables", "get_entity_info", "query_shader_symbol", "query_shader_compile_unit", "query_shader_platform_variants", "query_shader_callers", "explain_shader_reachability", "validate_shader", "compare_shader_with_vanilla"];
|
|
5
5
|
export declare function isMcpToolName(value: string): value is McpToolName;
|
|
6
6
|
export declare function isMcpWriteToolName(value: string): value is typeof MCP_WRITE_TOOL_NAMES[number];
|
package/dist/tools/names.js
CHANGED
|
@@ -17,6 +17,9 @@ exports.MCP_TOOL_NAMES = [
|
|
|
17
17
|
'query_project_knowledge',
|
|
18
18
|
'query_workspace_index',
|
|
19
19
|
'explore_pdx_project',
|
|
20
|
+
'query_inline_instantiation',
|
|
21
|
+
'analyze_pdx_flow',
|
|
22
|
+
'compare_definition_with_vanilla',
|
|
20
23
|
'query_localisation_index',
|
|
21
24
|
'get_pdx_block',
|
|
22
25
|
'get_completion_at',
|
|
@@ -108,17 +108,83 @@ const defaultSharedToolDispatcher = async (host, name, rawArgs) => {
|
|
|
108
108
|
args.maxEdges ?? 80,
|
|
109
109
|
args.includeMetadata !== false,
|
|
110
110
|
], 'Start the CWTools LSP process and wait for the game model to load before exploring the semantic graph.');
|
|
111
|
+
case 'analyze_pdx_flow': {
|
|
112
|
+
const file = typeof args.file === 'string' ? args.file.trim() : '';
|
|
113
|
+
const definitionId = typeof args.definitionId === 'string' ? args.definitionId.trim() : '';
|
|
114
|
+
if (!file && !definitionId) {
|
|
115
|
+
return {
|
|
116
|
+
ok: false,
|
|
117
|
+
status: 'error',
|
|
118
|
+
source: 'cwtools-shared',
|
|
119
|
+
error: {
|
|
120
|
+
code: 'invalid_arguments',
|
|
121
|
+
message: 'analyze_pdx_flow requires a file or a definitionId.',
|
|
122
|
+
},
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
return executeLspTool(host, 'cwtools.ai.analyzePdxFlow', [{
|
|
126
|
+
...(file ? { file } : {}),
|
|
127
|
+
...(definitionId ? { definitionId } : {}),
|
|
128
|
+
...(typeof args.entityType === 'string' && args.entityType.trim() ? { entityType: args.entityType.trim() } : {}),
|
|
129
|
+
limit: Math.max(1, Math.min(Number(args.limit ?? 100) || 100, 500)),
|
|
130
|
+
}], 'Start the CWTools LSP process and wait for the game model to load before analyzing flow cost and gameplay relations.');
|
|
131
|
+
}
|
|
132
|
+
case 'compare_definition_with_vanilla': {
|
|
133
|
+
if (typeof args.entityType !== 'string' || typeof args.symbolId !== 'string' || !args.entityType.trim() || !args.symbolId.trim()) {
|
|
134
|
+
return {
|
|
135
|
+
ok: false,
|
|
136
|
+
status: 'error',
|
|
137
|
+
source: 'cwtools-shared',
|
|
138
|
+
error: {
|
|
139
|
+
code: 'invalid_arguments',
|
|
140
|
+
message: 'compare_definition_with_vanilla requires entityType and symbolId.',
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
return executeLspTool(host, 'cwtools.ai.compareDefinitionWithVanilla', [args.entityType.trim(), args.symbolId.trim()], 'Start the CWTools LSP process and wait for the game model to load before comparing the definition with vanilla.');
|
|
145
|
+
}
|
|
146
|
+
case 'query_inline_instantiation': {
|
|
147
|
+
const template = typeof args.template === 'string' ? args.template.trim() : '';
|
|
148
|
+
const file = typeof args.file === 'string' ? args.file.trim() : '';
|
|
149
|
+
if (!template && !file) {
|
|
150
|
+
return {
|
|
151
|
+
ok: false,
|
|
152
|
+
status: 'error',
|
|
153
|
+
source: 'cwtools-shared',
|
|
154
|
+
error: {
|
|
155
|
+
code: 'invalid_arguments',
|
|
156
|
+
message: 'query_inline_instantiation requires a template path or a caller file (optionally with line).',
|
|
157
|
+
},
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
return executeLspTool(host, 'cwtools.ai.exploreInlineGraph', [{
|
|
161
|
+
...(template ? { template } : {}),
|
|
162
|
+
...(file ? { file } : {}),
|
|
163
|
+
...(Number.isInteger(args.line) ? { line: Number(args.line) } : {}),
|
|
164
|
+
limit: Math.max(1, Math.min(Number(args.limit ?? 50) || 50, 200)),
|
|
165
|
+
}], 'Start the CWTools LSP process and wait for the game model to load before resolving the inline template instantiation.');
|
|
166
|
+
}
|
|
111
167
|
case 'query_localisation_index': {
|
|
112
168
|
if (!host.indexing) {
|
|
113
169
|
return (0, schema_1.toolUnavailable)(name, 'Localisation index is not available in this host.', [
|
|
114
170
|
'Wire an LSP index command or a thin Node index before using this tool for localisation evidence.',
|
|
115
171
|
]);
|
|
116
172
|
}
|
|
173
|
+
const data = await host.indexing.queryLocalisation(args);
|
|
174
|
+
const semanticAudit = args.auditMode === true
|
|
175
|
+
? await executeLspTool(host, 'cwtools.ai.queryLocalisationAudit', [{
|
|
176
|
+
...(typeof args.key === 'string' ? { key: args.key } : {}),
|
|
177
|
+
prefix: args.prefix === true,
|
|
178
|
+
contains: args.contains === true,
|
|
179
|
+
caseSensitive: args.caseSensitive === true,
|
|
180
|
+
limit: Math.max(1, Math.min(Number(args.limit ?? 100) || 100, 500)),
|
|
181
|
+
}], 'Start the CWTools LSP process and wait for localisation validation before requesting auditMode.')
|
|
182
|
+
: undefined;
|
|
117
183
|
return {
|
|
118
184
|
ok: true,
|
|
119
185
|
status: 'ready',
|
|
120
186
|
source: 'cwtools-index',
|
|
121
|
-
data:
|
|
187
|
+
data: semanticAudit ? { ...data, semanticAudit } : data,
|
|
122
188
|
};
|
|
123
189
|
}
|
|
124
190
|
case 'get_diagnostics':
|