@loom-framework/core 0.1.0-alpha.8 → 0.1.0-alpha.81
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/adapter-base.d.ts +29 -0
- package/dist/adapter-base.d.ts.map +1 -0
- package/dist/adapter-base.js +62 -0
- package/dist/adapter-base.js.map +1 -0
- package/dist/adapter-factory.d.ts +8 -0
- package/dist/adapter-factory.d.ts.map +1 -0
- package/dist/adapter-factory.js +25 -0
- package/dist/adapter-factory.js.map +1 -0
- package/dist/adapter-filesystem.d.ts +6 -11
- package/dist/adapter-filesystem.d.ts.map +1 -1
- package/dist/adapter-filesystem.js +56 -41
- package/dist/adapter-filesystem.js.map +1 -1
- package/dist/adapter-sqlite.d.ts +6 -23
- package/dist/adapter-sqlite.d.ts.map +1 -1
- package/dist/adapter-sqlite.js +65 -50
- package/dist/adapter-sqlite.js.map +1 -1
- package/dist/backend/ai/button-resolver.d.ts +18 -0
- package/dist/backend/ai/button-resolver.d.ts.map +1 -0
- package/dist/backend/ai/button-resolver.js +58 -0
- package/dist/backend/ai/button-resolver.js.map +1 -0
- package/dist/backend/ai/engine.d.ts +52 -0
- package/dist/backend/ai/engine.d.ts.map +1 -0
- package/dist/backend/ai/engine.js +186 -0
- package/dist/backend/ai/engine.js.map +1 -0
- package/dist/backend/ai/index.d.ts +11 -0
- package/dist/backend/ai/index.d.ts.map +1 -0
- package/dist/backend/ai/index.js +8 -0
- package/dist/backend/ai/index.js.map +1 -0
- package/dist/backend/ai/output-parser.d.ts +29 -0
- package/dist/backend/ai/output-parser.d.ts.map +1 -0
- package/dist/backend/ai/output-parser.js +247 -0
- package/dist/backend/ai/output-parser.js.map +1 -0
- package/dist/backend/ai/session-manager.d.ts +103 -0
- package/dist/backend/ai/session-manager.d.ts.map +1 -0
- package/dist/backend/ai/session-manager.js +298 -0
- package/dist/backend/ai/session-manager.js.map +1 -0
- package/dist/backend/index.d.ts +61 -0
- package/dist/backend/index.d.ts.map +1 -0
- package/dist/backend/index.js +161 -0
- package/dist/backend/index.js.map +1 -0
- package/dist/backend/observe/index.d.ts +6 -0
- package/dist/backend/observe/index.d.ts.map +1 -0
- package/dist/backend/observe/index.js +5 -0
- package/dist/backend/observe/index.js.map +1 -0
- package/dist/backend/observe/logger.d.ts +28 -0
- package/dist/backend/observe/logger.d.ts.map +1 -0
- package/dist/backend/observe/logger.js +80 -0
- package/dist/backend/observe/logger.js.map +1 -0
- package/dist/backend/observe/types.d.ts +26 -0
- package/dist/backend/observe/types.d.ts.map +1 -0
- package/dist/backend/observe/types.js +7 -0
- package/dist/backend/observe/types.js.map +1 -0
- package/dist/backend/routes/chat.d.ts +31 -0
- package/dist/backend/routes/chat.d.ts.map +1 -0
- package/dist/backend/routes/chat.js +426 -0
- package/dist/backend/routes/chat.js.map +1 -0
- package/dist/backend/routes/data.d.ts +13 -0
- package/dist/backend/routes/data.d.ts.map +1 -0
- package/dist/backend/routes/data.js +134 -0
- package/dist/backend/routes/data.js.map +1 -0
- package/dist/backend/routes/health.d.ts +7 -0
- package/dist/backend/routes/health.d.ts.map +1 -0
- package/dist/backend/routes/health.js +15 -0
- package/dist/backend/routes/health.js.map +1 -0
- package/dist/backend/routes/index.d.ts +11 -0
- package/dist/backend/routes/index.d.ts.map +1 -0
- package/dist/backend/routes/index.js +9 -0
- package/dist/backend/routes/index.js.map +1 -0
- package/dist/backend/routes/skills.d.ts +16 -0
- package/dist/backend/routes/skills.d.ts.map +1 -0
- package/dist/backend/routes/skills.js +590 -0
- package/dist/backend/routes/skills.js.map +1 -0
- package/dist/backend/routes/upload.d.ts +24 -0
- package/dist/backend/routes/upload.d.ts.map +1 -0
- package/dist/backend/routes/upload.js +67 -0
- package/dist/backend/routes/upload.js.map +1 -0
- package/dist/bin.d.ts +8 -0
- package/dist/bin.d.ts.map +1 -0
- package/dist/bin.js +12 -0
- package/dist/bin.js.map +1 -0
- package/dist/capability-generator.d.ts +21 -6
- package/dist/capability-generator.d.ts.map +1 -1
- package/dist/capability-generator.js +88 -261
- package/dist/capability-generator.js.map +1 -1
- package/dist/cli/commands/build.d.ts +11 -0
- package/dist/cli/commands/build.d.ts.map +1 -0
- package/dist/cli/commands/build.js +170 -0
- package/dist/cli/commands/build.js.map +1 -0
- package/dist/cli/commands/data.d.ts +12 -0
- package/dist/cli/commands/data.d.ts.map +1 -0
- package/dist/cli/commands/data.js +158 -0
- package/dist/cli/commands/data.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +9 -0
- package/dist/cli/commands/dev.d.ts.map +1 -0
- package/dist/cli/commands/dev.js +114 -0
- package/dist/cli/commands/dev.js.map +1 -0
- package/dist/cli/commands/generate-capabilities.d.ts +8 -0
- package/dist/cli/commands/generate-capabilities.d.ts.map +1 -0
- package/dist/cli/commands/generate-capabilities.js +40 -0
- package/dist/cli/commands/generate-capabilities.js.map +1 -0
- package/dist/cli/commands/generate-cli-command.d.ts +8 -0
- package/dist/cli/commands/generate-cli-command.d.ts.map +1 -0
- package/dist/cli/commands/generate-cli-command.js +64 -0
- package/dist/cli/commands/generate-cli-command.js.map +1 -0
- package/dist/cli/commands/generate-dashboard.d.ts +9 -0
- package/dist/cli/commands/generate-dashboard.d.ts.map +1 -0
- package/dist/cli/commands/generate-dashboard.js +452 -0
- package/dist/cli/commands/generate-dashboard.js.map +1 -0
- package/dist/cli/commands/generate-page.d.ts +9 -0
- package/dist/cli/commands/generate-page.d.ts.map +1 -0
- package/dist/cli/commands/generate-page.js +518 -0
- package/dist/cli/commands/generate-page.js.map +1 -0
- package/dist/cli/commands/generate-skill.d.ts +8 -0
- package/dist/cli/commands/generate-skill.d.ts.map +1 -0
- package/dist/cli/commands/generate-skill.js +75 -0
- package/dist/cli/commands/generate-skill.js.map +1 -0
- package/dist/cli/commands/generate.d.ts +6 -0
- package/dist/cli/commands/generate.d.ts.map +1 -0
- package/dist/cli/commands/generate.js +19 -0
- package/dist/cli/commands/generate.js.map +1 -0
- package/dist/cli/commands/init.d.ts +8 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +539 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/observe.d.ts +9 -0
- package/dist/cli/commands/observe.d.ts.map +1 -0
- package/dist/cli/commands/observe.js +142 -0
- package/dist/cli/commands/observe.js.map +1 -0
- package/dist/cli/commands/skill.d.ts +9 -0
- package/dist/cli/commands/skill.d.ts.map +1 -0
- package/dist/cli/commands/skill.js +186 -0
- package/dist/cli/commands/skill.js.map +1 -0
- package/dist/cli/helpers/app-tsx-wiring.d.ts +17 -0
- package/dist/cli/helpers/app-tsx-wiring.d.ts.map +1 -0
- package/dist/cli/helpers/app-tsx-wiring.js +132 -0
- package/dist/cli/helpers/app-tsx-wiring.js.map +1 -0
- package/dist/cli/helpers/duration.d.ts +5 -0
- package/dist/cli/helpers/duration.d.ts.map +1 -0
- package/dist/cli/helpers/duration.js +19 -0
- package/dist/cli/helpers/duration.js.map +1 -0
- package/dist/cli/helpers/field-template.d.ts +10 -0
- package/dist/cli/helpers/field-template.d.ts.map +1 -0
- package/dist/cli/helpers/field-template.js +100 -0
- package/dist/cli/helpers/field-template.js.map +1 -0
- package/dist/cli/helpers/naming.d.ts +12 -0
- package/dist/cli/helpers/naming.d.ts.map +1 -0
- package/dist/cli/helpers/naming.js +25 -0
- package/dist/cli/helpers/naming.js.map +1 -0
- package/dist/cli/index.d.ts +9 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +33 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/utils.d.ts +10 -0
- package/dist/cli/utils.d.ts.map +1 -0
- package/dist/cli/utils.js +31 -0
- package/dist/cli/utils.js.map +1 -0
- package/dist/config.d.ts +118 -42
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +59 -10
- package/dist/config.js.map +1 -1
- package/dist/index.d.ts +7 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/server-bin.d.ts +12 -0
- package/dist/server-bin.d.ts.map +1 -0
- package/dist/server-bin.js +75 -0
- package/dist/server-bin.js.map +1 -0
- package/dist/types.d.ts +71 -20
- package/dist/types.d.ts.map +1 -1
- package/package.json +25 -10
- package/templates/app-skill/SKILL.md +27 -0
- package/templates/app-skill/references/data-semantics.md +44 -0
- package/templates/app-skill/references/models.md +31 -0
- package/templates/loom-skill/SKILL.md +153 -0
- package/templates/loom-skill/references/README.md +128 -0
- package/templates/loom-skill/references/dashboard.md +161 -0
- package/templates/loom-skill/references/data-model.md +78 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Field-to-template utilities - extracted for testability
|
|
3
|
+
*/
|
|
4
|
+
/** Map FieldType to Ant Design table column render hint */
|
|
5
|
+
export function fieldToColumnType(type) {
|
|
6
|
+
switch (type) {
|
|
7
|
+
case 'number':
|
|
8
|
+
case 'number[]':
|
|
9
|
+
return "'right'";
|
|
10
|
+
case 'boolean':
|
|
11
|
+
return "'bool'";
|
|
12
|
+
case 'date':
|
|
13
|
+
return "'date'";
|
|
14
|
+
default:
|
|
15
|
+
return "'text'";
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** Fallback labels for common field names without description */
|
|
19
|
+
const FALLBACK_LABELS = {
|
|
20
|
+
createdAt: '创建时间',
|
|
21
|
+
updatedAt: '更新时间',
|
|
22
|
+
};
|
|
23
|
+
export function getFieldLabel(field) {
|
|
24
|
+
return field.description || FALLBACK_LABELS[field.name] || field.name;
|
|
25
|
+
}
|
|
26
|
+
/** Guess if a field is a long-text field (should use TextArea instead of Input) */
|
|
27
|
+
function isLongTextField(field) {
|
|
28
|
+
const name = field.name.toLowerCase();
|
|
29
|
+
return (field.type === 'string' &&
|
|
30
|
+
!field.enum &&
|
|
31
|
+
(name.includes('content') ||
|
|
32
|
+
name.includes('description') ||
|
|
33
|
+
name.includes('body') ||
|
|
34
|
+
name.includes('text') ||
|
|
35
|
+
name.includes('note') ||
|
|
36
|
+
name.includes('remark') ||
|
|
37
|
+
name.includes('bio') ||
|
|
38
|
+
name.includes('summary')));
|
|
39
|
+
}
|
|
40
|
+
/** Get appropriate required rule message based on field type */
|
|
41
|
+
function getRequiredRule(field, label) {
|
|
42
|
+
if (field.enum || field.type === 'string[]') {
|
|
43
|
+
return ` rules={[{ required: true, message: '请选择${label}' }]}`;
|
|
44
|
+
}
|
|
45
|
+
if (field.type === 'date') {
|
|
46
|
+
return ` rules={[{ required: true, message: '请选择${label}' }]}`;
|
|
47
|
+
}
|
|
48
|
+
if (field.type === 'number') {
|
|
49
|
+
return ` rules={[{ required: true, message: '请输入${label}' }]}`;
|
|
50
|
+
}
|
|
51
|
+
return ` rules={[{ required: true, message: '请输入${label}' }]}`;
|
|
52
|
+
}
|
|
53
|
+
/** Generate Ant Design form item for a field */
|
|
54
|
+
export function fieldToFormItem(field, modelName) {
|
|
55
|
+
const name = field.name;
|
|
56
|
+
const label = getFieldLabel(field);
|
|
57
|
+
const requiredRule = field.required ? getRequiredRule(field, label) : '';
|
|
58
|
+
if (field.enum) {
|
|
59
|
+
const options = field.enum.map((v) => ` <Select.Option value="${v}">${v}</Select.Option>`).join('\n');
|
|
60
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
61
|
+
<Select placeholder="请选择${label}">
|
|
62
|
+
${options}
|
|
63
|
+
</Select>
|
|
64
|
+
</Form.Item>`;
|
|
65
|
+
}
|
|
66
|
+
switch (field.type) {
|
|
67
|
+
case 'boolean':
|
|
68
|
+
return ` <Form.Item name="${name}" label="${label}" valuePropName="checked">
|
|
69
|
+
<Switch />
|
|
70
|
+
</Form.Item>`;
|
|
71
|
+
case 'number':
|
|
72
|
+
case 'number[]':
|
|
73
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
74
|
+
<InputNumber style={{ width: '100%' }} />
|
|
75
|
+
</Form.Item>`;
|
|
76
|
+
case 'string[]':
|
|
77
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
78
|
+
<Select mode="tags" placeholder="请输入${label}" />
|
|
79
|
+
</Form.Item>`;
|
|
80
|
+
case 'json':
|
|
81
|
+
return ` <Form.Item name="${name}" label="${label}">
|
|
82
|
+
<Input.TextArea rows={4} placeholder="请输入JSON" />
|
|
83
|
+
</Form.Item>`;
|
|
84
|
+
case 'date':
|
|
85
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
86
|
+
<DatePicker style={{ width: '100%' }} />
|
|
87
|
+
</Form.Item>`;
|
|
88
|
+
default:
|
|
89
|
+
// Long text fields use TextArea
|
|
90
|
+
if (isLongTextField(field)) {
|
|
91
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
92
|
+
<Input.TextArea rows={3} placeholder="请输入${label}" />
|
|
93
|
+
</Form.Item>`;
|
|
94
|
+
}
|
|
95
|
+
return ` <Form.Item name="${name}" label="${label}"${requiredRule}>
|
|
96
|
+
<Input placeholder="请输入${label}" />
|
|
97
|
+
</Form.Item>`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=field-template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"field-template.js","sourceRoot":"","sources":["../../../src/cli/helpers/field-template.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Naming utilities - extracted for testability
|
|
3
|
+
*
|
|
4
|
+
* Converts model names to valid JS identifiers for generated code.
|
|
5
|
+
* Only transforms what's strictly necessary:
|
|
6
|
+
* - Replace hyphens (invalid in JS identifiers) → capitalize next letter
|
|
7
|
+
* - Capitalize first letter (React requirement)
|
|
8
|
+
* Everything else (camelCase, snake_case, PascalCase) is preserved as-is.
|
|
9
|
+
*/
|
|
10
|
+
export declare function toPascalCase(name: string): string;
|
|
11
|
+
export declare function toCamelCase(name: string): string;
|
|
12
|
+
//# sourceMappingURL=naming.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.d.ts","sourceRoot":"","sources":["../../../src/cli/helpers/naming.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMjD;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGhD"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Naming utilities - extracted for testability
|
|
3
|
+
*
|
|
4
|
+
* Converts model names to valid JS identifiers for generated code.
|
|
5
|
+
* Only transforms what's strictly necessary:
|
|
6
|
+
* - Replace hyphens (invalid in JS identifiers) → capitalize next letter
|
|
7
|
+
* - Capitalize first letter (React requirement)
|
|
8
|
+
* Everything else (camelCase, snake_case, PascalCase) is preserved as-is.
|
|
9
|
+
*/
|
|
10
|
+
function capitalizeFirst(s) {
|
|
11
|
+
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
12
|
+
}
|
|
13
|
+
export function toPascalCase(name) {
|
|
14
|
+
if (!name)
|
|
15
|
+
return name;
|
|
16
|
+
// Split on hyphens and underscores, PascalCase-join the parts,
|
|
17
|
+
// then capitalize first letter.
|
|
18
|
+
const parts = name.split(/[-_]/).map(capitalizeFirst).join('');
|
|
19
|
+
return capitalizeFirst(parts);
|
|
20
|
+
}
|
|
21
|
+
export function toCamelCase(name) {
|
|
22
|
+
const pascal = toPascalCase(name);
|
|
23
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"naming.js","sourceRoot":"","sources":["../../../src/cli/helpers/naming.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,SAAS,eAAe,CAAC,CAAS;IAChC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC,IAAI;QAAE,OAAO,IAAI,CAAC;IACvB,+DAA+D;IAC/D,gCAAgC;IAChC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC/D,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAClC,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom CLI - Main Program
|
|
3
|
+
*
|
|
4
|
+
* Registers all subcommands and runs the CLI.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
export declare function createProgram(): Command;
|
|
8
|
+
export declare function run(): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAUpC,wBAAgB,aAAa,IAAI,OAAO,CAiBvC;AAED,wBAAsB,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAGzC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom CLI - Main Program
|
|
3
|
+
*
|
|
4
|
+
* Registers all subcommands and runs the CLI.
|
|
5
|
+
*/
|
|
6
|
+
import { Command } from 'commander';
|
|
7
|
+
import { registerGenerateCommand } from './commands/generate.js';
|
|
8
|
+
import { registerDevCommand } from './commands/dev.js';
|
|
9
|
+
import { registerBuildCommand } from './commands/build.js';
|
|
10
|
+
import { registerDataCommand } from './commands/data.js';
|
|
11
|
+
import { registerSkillCommand } from './commands/skill.js';
|
|
12
|
+
import { registerObserveCommand } from './commands/observe.js';
|
|
13
|
+
import { registerInitCommand } from './commands/init.js';
|
|
14
|
+
export function createProgram() {
|
|
15
|
+
const program = new Command();
|
|
16
|
+
program
|
|
17
|
+
.name('loom')
|
|
18
|
+
.description('Loom - Weave AI capabilities into your application')
|
|
19
|
+
.version('0.1.0');
|
|
20
|
+
registerInitCommand(program);
|
|
21
|
+
registerGenerateCommand(program);
|
|
22
|
+
registerDevCommand(program);
|
|
23
|
+
registerBuildCommand(program);
|
|
24
|
+
registerDataCommand(program);
|
|
25
|
+
registerSkillCommand(program);
|
|
26
|
+
registerObserveCommand(program);
|
|
27
|
+
return program;
|
|
28
|
+
}
|
|
29
|
+
export async function run() {
|
|
30
|
+
const program = createProgram();
|
|
31
|
+
await program.parseAsync(process.argv);
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD,MAAM,UAAU,aAAa;IAC3B,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,MAAM,CAAC;SACZ,WAAW,CAAC,oDAAoD,CAAC;SACjE,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,uBAAuB,CAAC,OAAO,CAAC,CAAC;IACjC,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC7B,oBAAoB,CAAC,OAAO,CAAC,CAAC;IAC9B,sBAAsB,CAAC,OAAO,CAAC,CAAC;IAEhC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,OAAO,GAAG,aAAa,EAAE,CAAC;IAChC,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Resolve the project root directory.
|
|
6
|
+
* Walks up from CWD looking for loom.config.ts or loom.config.js.
|
|
7
|
+
* Falls back to CWD if no config found.
|
|
8
|
+
*/
|
|
9
|
+
export declare function resolveProjectRoot(): Promise<string>;
|
|
10
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;;;GAIG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CAoB1D"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared CLI utilities
|
|
3
|
+
*/
|
|
4
|
+
import { promises as fs } from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
/**
|
|
7
|
+
* Resolve the project root directory.
|
|
8
|
+
* Walks up from CWD looking for loom.config.ts or loom.config.js.
|
|
9
|
+
* Falls back to CWD if no config found.
|
|
10
|
+
*/
|
|
11
|
+
export async function resolveProjectRoot() {
|
|
12
|
+
let current = process.cwd();
|
|
13
|
+
for (let i = 0; i < 20; i++) {
|
|
14
|
+
for (const candidate of ['loom.config.ts', 'loom.config.js']) {
|
|
15
|
+
try {
|
|
16
|
+
await fs.access(path.join(current, candidate));
|
|
17
|
+
return current;
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
const parent = path.dirname(current);
|
|
24
|
+
if (parent === current)
|
|
25
|
+
break; // reached root
|
|
26
|
+
current = parent;
|
|
27
|
+
}
|
|
28
|
+
// Fallback to CWD
|
|
29
|
+
return process.cwd();
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/cli/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,IAAI,OAAO,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAE5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,KAAK,MAAM,SAAS,IAAI,CAAC,gBAAgB,EAAE,gBAAgB,CAAC,EAAE,CAAC;YAC7D,IAAI,CAAC;gBACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAC;gBAC/C,OAAO,OAAO,CAAC;YACjB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QACrC,IAAI,MAAM,KAAK,OAAO;YAAE,MAAM,CAAC,eAAe;QAC9C,OAAO,GAAG,MAAM,CAAC;IACnB,CAAC;IAED,kBAAkB;IAClB,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC;AACvB,CAAC"}
|
package/dist/config.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* loadConfig() - Load and validate loom.config.ts
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
|
-
import type { LoomConfig, ModelSchema } from './types.js';
|
|
8
|
+
import type { LoomConfig, ModelSchema, DashboardConfig } from './types.js';
|
|
9
9
|
declare const LoomConfigSchema: z.ZodObject<{
|
|
10
10
|
project: z.ZodObject<{
|
|
11
11
|
name: z.ZodString;
|
|
@@ -222,19 +222,16 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
222
222
|
pluginRoot: z.ZodOptional<z.ZodString>;
|
|
223
223
|
timeout: z.ZodOptional<z.ZodNumber>;
|
|
224
224
|
skipPermissions: z.ZodOptional<z.ZodBoolean>;
|
|
225
|
-
defaultModel: z.ZodOptional<z.ZodString>;
|
|
226
225
|
}, "strip", z.ZodTypeAny, {
|
|
227
226
|
path?: string | undefined;
|
|
228
227
|
pluginRoot?: string | undefined;
|
|
229
228
|
timeout?: number | undefined;
|
|
230
229
|
skipPermissions?: boolean | undefined;
|
|
231
|
-
defaultModel?: string | undefined;
|
|
232
230
|
}, {
|
|
233
231
|
path?: string | undefined;
|
|
234
232
|
pluginRoot?: string | undefined;
|
|
235
233
|
timeout?: number | undefined;
|
|
236
234
|
skipPermissions?: boolean | undefined;
|
|
237
|
-
defaultModel?: string | undefined;
|
|
238
235
|
}>>;
|
|
239
236
|
}, "strip", z.ZodTypeAny, {
|
|
240
237
|
engine?: string | undefined;
|
|
@@ -243,7 +240,6 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
243
240
|
pluginRoot?: string | undefined;
|
|
244
241
|
timeout?: number | undefined;
|
|
245
242
|
skipPermissions?: boolean | undefined;
|
|
246
|
-
defaultModel?: string | undefined;
|
|
247
243
|
} | undefined;
|
|
248
244
|
}, {
|
|
249
245
|
engine?: string | undefined;
|
|
@@ -252,7 +248,6 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
252
248
|
pluginRoot?: string | undefined;
|
|
253
249
|
timeout?: number | undefined;
|
|
254
250
|
skipPermissions?: boolean | undefined;
|
|
255
|
-
defaultModel?: string | undefined;
|
|
256
251
|
} | undefined;
|
|
257
252
|
}>>;
|
|
258
253
|
server: z.ZodOptional<z.ZodObject<{
|
|
@@ -271,45 +266,23 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
271
266
|
cors?: boolean | undefined;
|
|
272
267
|
staticDir?: string | undefined;
|
|
273
268
|
}>>;
|
|
274
|
-
aiButtons: z.ZodOptional<z.ZodArray<z.
|
|
269
|
+
aiButtons: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
275
270
|
id: z.ZodString;
|
|
276
271
|
label: z.ZodString;
|
|
277
272
|
icon: z.ZodOptional<z.ZodString>;
|
|
278
|
-
prompt: z.
|
|
279
|
-
promptTemplate: z.ZodOptional<z.ZodString>;
|
|
280
|
-
contextVars: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
273
|
+
prompt: z.ZodString;
|
|
281
274
|
placement: z.ZodOptional<z.ZodString>;
|
|
282
275
|
}, "strip", z.ZodTypeAny, {
|
|
283
276
|
id: string;
|
|
284
277
|
label: string;
|
|
278
|
+
prompt: string;
|
|
285
279
|
icon?: string | undefined;
|
|
286
|
-
prompt?: string | undefined;
|
|
287
|
-
promptTemplate?: string | undefined;
|
|
288
|
-
contextVars?: string[] | undefined;
|
|
289
280
|
placement?: string | undefined;
|
|
290
281
|
}, {
|
|
291
282
|
id: string;
|
|
292
283
|
label: string;
|
|
284
|
+
prompt: string;
|
|
293
285
|
icon?: string | undefined;
|
|
294
|
-
prompt?: string | undefined;
|
|
295
|
-
promptTemplate?: string | undefined;
|
|
296
|
-
contextVars?: string[] | undefined;
|
|
297
|
-
placement?: string | undefined;
|
|
298
|
-
}>, {
|
|
299
|
-
id: string;
|
|
300
|
-
label: string;
|
|
301
|
-
icon?: string | undefined;
|
|
302
|
-
prompt?: string | undefined;
|
|
303
|
-
promptTemplate?: string | undefined;
|
|
304
|
-
contextVars?: string[] | undefined;
|
|
305
|
-
placement?: string | undefined;
|
|
306
|
-
}, {
|
|
307
|
-
id: string;
|
|
308
|
-
label: string;
|
|
309
|
-
icon?: string | undefined;
|
|
310
|
-
prompt?: string | undefined;
|
|
311
|
-
promptTemplate?: string | undefined;
|
|
312
|
-
contextVars?: string[] | undefined;
|
|
313
286
|
placement?: string | undefined;
|
|
314
287
|
}>, "many">>;
|
|
315
288
|
}, "strip", z.ZodTypeAny, {
|
|
@@ -356,7 +329,6 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
356
329
|
pluginRoot?: string | undefined;
|
|
357
330
|
timeout?: number | undefined;
|
|
358
331
|
skipPermissions?: boolean | undefined;
|
|
359
|
-
defaultModel?: string | undefined;
|
|
360
332
|
} | undefined;
|
|
361
333
|
} | undefined;
|
|
362
334
|
server?: {
|
|
@@ -368,10 +340,8 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
368
340
|
aiButtons?: {
|
|
369
341
|
id: string;
|
|
370
342
|
label: string;
|
|
343
|
+
prompt: string;
|
|
371
344
|
icon?: string | undefined;
|
|
372
|
-
prompt?: string | undefined;
|
|
373
|
-
promptTemplate?: string | undefined;
|
|
374
|
-
contextVars?: string[] | undefined;
|
|
375
345
|
placement?: string | undefined;
|
|
376
346
|
}[] | undefined;
|
|
377
347
|
}, {
|
|
@@ -418,7 +388,6 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
418
388
|
pluginRoot?: string | undefined;
|
|
419
389
|
timeout?: number | undefined;
|
|
420
390
|
skipPermissions?: boolean | undefined;
|
|
421
|
-
defaultModel?: string | undefined;
|
|
422
391
|
} | undefined;
|
|
423
392
|
} | undefined;
|
|
424
393
|
server?: {
|
|
@@ -430,10 +399,8 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
430
399
|
aiButtons?: {
|
|
431
400
|
id: string;
|
|
432
401
|
label: string;
|
|
402
|
+
prompt: string;
|
|
433
403
|
icon?: string | undefined;
|
|
434
|
-
prompt?: string | undefined;
|
|
435
|
-
promptTemplate?: string | undefined;
|
|
436
|
-
contextVars?: string[] | undefined;
|
|
437
404
|
placement?: string | undefined;
|
|
438
405
|
}[] | undefined;
|
|
439
406
|
}>;
|
|
@@ -450,7 +417,8 @@ declare const LoomConfigSchema: z.ZodObject<{
|
|
|
450
417
|
* defaultAdapter: 'filesystem',
|
|
451
418
|
* models: [
|
|
452
419
|
* {
|
|
453
|
-
*
|
|
420
|
+
* // Model names accept any casing: kebab-case, camelCase, PascalCase, snake_case
|
|
421
|
+
* name: 'wrongQuestions',
|
|
454
422
|
* fields: [
|
|
455
423
|
* { name: 'id', type: 'string', required: true },
|
|
456
424
|
* { name: 'name', type: 'string', required: true },
|
|
@@ -479,5 +447,113 @@ export declare function getModelSchema(config: LoomConfig, modelName: string): M
|
|
|
479
447
|
* Validate that all model names are unique
|
|
480
448
|
*/
|
|
481
449
|
export declare function validateModelUniqueness(config: LoomConfig): string[];
|
|
482
|
-
|
|
450
|
+
declare const DashboardConfigSchema: z.ZodObject<{
|
|
451
|
+
name: z.ZodString;
|
|
452
|
+
description: z.ZodOptional<z.ZodString>;
|
|
453
|
+
models: z.ZodArray<z.ZodString, "many">;
|
|
454
|
+
layout: z.ZodArray<z.ZodObject<{
|
|
455
|
+
row: z.ZodArray<z.ZodObject<{
|
|
456
|
+
type: z.ZodEnum<["stat", "pie", "ring", "bar", "line", "area", "scatter", "radar", "funnel", "treemap", "gauge", "liquid", "heatmap", "stacked_bar", "grouped_bar"]>;
|
|
457
|
+
title: z.ZodString;
|
|
458
|
+
model: z.ZodString;
|
|
459
|
+
span: z.ZodOptional<z.ZodNumber>;
|
|
460
|
+
groupBy: z.ZodOptional<z.ZodString>;
|
|
461
|
+
crossGroupBy: z.ZodOptional<z.ZodString>;
|
|
462
|
+
aggregate: z.ZodOptional<z.ZodEnum<["count", "sum", "avg", "min", "max", "ratio"]>>;
|
|
463
|
+
field: z.ZodOptional<z.ZodString>;
|
|
464
|
+
filter: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
465
|
+
interval: z.ZodOptional<z.ZodEnum<["day", "week", "month"]>>;
|
|
466
|
+
}, "strip", z.ZodTypeAny, {
|
|
467
|
+
type: "stat" | "pie" | "ring" | "bar" | "line" | "area" | "scatter" | "radar" | "funnel" | "treemap" | "gauge" | "liquid" | "heatmap" | "stacked_bar" | "grouped_bar";
|
|
468
|
+
title: string;
|
|
469
|
+
model: string;
|
|
470
|
+
filter?: Record<string, unknown> | undefined;
|
|
471
|
+
field?: string | undefined;
|
|
472
|
+
span?: number | undefined;
|
|
473
|
+
groupBy?: string | undefined;
|
|
474
|
+
crossGroupBy?: string | undefined;
|
|
475
|
+
aggregate?: "count" | "sum" | "avg" | "min" | "max" | "ratio" | undefined;
|
|
476
|
+
interval?: "day" | "week" | "month" | undefined;
|
|
477
|
+
}, {
|
|
478
|
+
type: "stat" | "pie" | "ring" | "bar" | "line" | "area" | "scatter" | "radar" | "funnel" | "treemap" | "gauge" | "liquid" | "heatmap" | "stacked_bar" | "grouped_bar";
|
|
479
|
+
title: string;
|
|
480
|
+
model: string;
|
|
481
|
+
filter?: Record<string, unknown> | undefined;
|
|
482
|
+
field?: string | undefined;
|
|
483
|
+
span?: number | undefined;
|
|
484
|
+
groupBy?: string | undefined;
|
|
485
|
+
crossGroupBy?: string | undefined;
|
|
486
|
+
aggregate?: "count" | "sum" | "avg" | "min" | "max" | "ratio" | undefined;
|
|
487
|
+
interval?: "day" | "week" | "month" | undefined;
|
|
488
|
+
}>, "many">;
|
|
489
|
+
}, "strip", z.ZodTypeAny, {
|
|
490
|
+
row: {
|
|
491
|
+
type: "stat" | "pie" | "ring" | "bar" | "line" | "area" | "scatter" | "radar" | "funnel" | "treemap" | "gauge" | "liquid" | "heatmap" | "stacked_bar" | "grouped_bar";
|
|
492
|
+
title: string;
|
|
493
|
+
model: string;
|
|
494
|
+
filter?: Record<string, unknown> | undefined;
|
|
495
|
+
field?: string | undefined;
|
|
496
|
+
span?: number | undefined;
|
|
497
|
+
groupBy?: string | undefined;
|
|
498
|
+
crossGroupBy?: string | undefined;
|
|
499
|
+
aggregate?: "count" | "sum" | "avg" | "min" | "max" | "ratio" | undefined;
|
|
500
|
+
interval?: "day" | "week" | "month" | undefined;
|
|
501
|
+
}[];
|
|
502
|
+
}, {
|
|
503
|
+
row: {
|
|
504
|
+
type: "stat" | "pie" | "ring" | "bar" | "line" | "area" | "scatter" | "radar" | "funnel" | "treemap" | "gauge" | "liquid" | "heatmap" | "stacked_bar" | "grouped_bar";
|
|
505
|
+
title: string;
|
|
506
|
+
model: string;
|
|
507
|
+
filter?: Record<string, unknown> | undefined;
|
|
508
|
+
field?: string | undefined;
|
|
509
|
+
span?: number | undefined;
|
|
510
|
+
groupBy?: string | undefined;
|
|
511
|
+
crossGroupBy?: string | undefined;
|
|
512
|
+
aggregate?: "count" | "sum" | "avg" | "min" | "max" | "ratio" | undefined;
|
|
513
|
+
interval?: "day" | "week" | "month" | undefined;
|
|
514
|
+
}[];
|
|
515
|
+
}>, "many">;
|
|
516
|
+
}, "strip", z.ZodTypeAny, {
|
|
517
|
+
name: string;
|
|
518
|
+
models: string[];
|
|
519
|
+
layout: {
|
|
520
|
+
row: {
|
|
521
|
+
type: "stat" | "pie" | "ring" | "bar" | "line" | "area" | "scatter" | "radar" | "funnel" | "treemap" | "gauge" | "liquid" | "heatmap" | "stacked_bar" | "grouped_bar";
|
|
522
|
+
title: string;
|
|
523
|
+
model: string;
|
|
524
|
+
filter?: Record<string, unknown> | undefined;
|
|
525
|
+
field?: string | undefined;
|
|
526
|
+
span?: number | undefined;
|
|
527
|
+
groupBy?: string | undefined;
|
|
528
|
+
crossGroupBy?: string | undefined;
|
|
529
|
+
aggregate?: "count" | "sum" | "avg" | "min" | "max" | "ratio" | undefined;
|
|
530
|
+
interval?: "day" | "week" | "month" | undefined;
|
|
531
|
+
}[];
|
|
532
|
+
}[];
|
|
533
|
+
description?: string | undefined;
|
|
534
|
+
}, {
|
|
535
|
+
name: string;
|
|
536
|
+
models: string[];
|
|
537
|
+
layout: {
|
|
538
|
+
row: {
|
|
539
|
+
type: "stat" | "pie" | "ring" | "bar" | "line" | "area" | "scatter" | "radar" | "funnel" | "treemap" | "gauge" | "liquid" | "heatmap" | "stacked_bar" | "grouped_bar";
|
|
540
|
+
title: string;
|
|
541
|
+
model: string;
|
|
542
|
+
filter?: Record<string, unknown> | undefined;
|
|
543
|
+
field?: string | undefined;
|
|
544
|
+
span?: number | undefined;
|
|
545
|
+
groupBy?: string | undefined;
|
|
546
|
+
crossGroupBy?: string | undefined;
|
|
547
|
+
aggregate?: "count" | "sum" | "avg" | "min" | "max" | "ratio" | undefined;
|
|
548
|
+
interval?: "day" | "week" | "month" | undefined;
|
|
549
|
+
}[];
|
|
550
|
+
}[];
|
|
551
|
+
description?: string | undefined;
|
|
552
|
+
}>;
|
|
553
|
+
/**
|
|
554
|
+
* Load dashboard.config.json from a project directory.
|
|
555
|
+
* Returns the validated DashboardConfig, or null if no config file exists.
|
|
556
|
+
*/
|
|
557
|
+
export declare function loadDashboardConfig(projectRoot: string): Promise<DashboardConfig | null>;
|
|
558
|
+
export { LoomConfigSchema, DashboardConfigSchema };
|
|
483
559
|
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAmC,eAAe,EAAE,MAAM,YAAY,CAAC;AA8C5G,QAAA,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4BpB,CAAC;AAIH;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,GAAG,UAAU,CAU3D;AAID;;;GAGG;AACH,wBAAsB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAqBzE;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAE7F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,EAAE,CAUpE;AAqBD,QAAA,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAKY,CAAC;AAExC;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CA0B9F;AAGD,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,CAAC"}
|
package/dist/config.js
CHANGED
|
@@ -12,7 +12,7 @@ const FieldTypeSchema = z.enum([
|
|
|
12
12
|
'string[]', 'number[]', 'json',
|
|
13
13
|
]);
|
|
14
14
|
const FieldDefinitionSchema = z.object({
|
|
15
|
-
name: z.string(),
|
|
15
|
+
name: z.string().regex(/^[a-zA-Z_][a-zA-Z0-9_]*$/, 'Field name must start with a letter or underscore, and contain only alphanumeric characters and underscores'),
|
|
16
16
|
type: FieldTypeSchema,
|
|
17
17
|
required: z.boolean().optional(),
|
|
18
18
|
description: z.string().optional(),
|
|
@@ -20,7 +20,7 @@ const FieldDefinitionSchema = z.object({
|
|
|
20
20
|
enum: z.array(z.string()).optional(),
|
|
21
21
|
});
|
|
22
22
|
const ModelSchemaSchema = z.object({
|
|
23
|
-
name: z.string().regex(/^[a-
|
|
23
|
+
name: z.string().regex(/^[a-zA-Z][a-zA-Z0-9_]*$/, 'Model name must start with a letter and contain only letters, digits, or underscores (no hyphens)'),
|
|
24
24
|
fields: z.array(FieldDefinitionSchema).min(1),
|
|
25
25
|
indexes: z.array(z.object({
|
|
26
26
|
fields: z.array(z.string()),
|
|
@@ -42,11 +42,9 @@ const AIButtonConfigSchema = z.object({
|
|
|
42
42
|
id: z.string(),
|
|
43
43
|
label: z.string(),
|
|
44
44
|
icon: z.string().optional(),
|
|
45
|
-
prompt: z.string()
|
|
46
|
-
promptTemplate: z.string().optional(),
|
|
47
|
-
contextVars: z.array(z.string()).optional(),
|
|
45
|
+
prompt: z.string(),
|
|
48
46
|
placement: z.string().optional(),
|
|
49
|
-
})
|
|
47
|
+
});
|
|
50
48
|
const LoomConfigSchema = z.object({
|
|
51
49
|
project: z.object({
|
|
52
50
|
name: z.string(),
|
|
@@ -66,7 +64,6 @@ const LoomConfigSchema = z.object({
|
|
|
66
64
|
pluginRoot: z.string().optional(),
|
|
67
65
|
timeout: z.number().optional(),
|
|
68
66
|
skipPermissions: z.boolean().optional(),
|
|
69
|
-
defaultModel: z.string().optional(),
|
|
70
67
|
}).optional(),
|
|
71
68
|
}).optional(),
|
|
72
69
|
server: z.object({
|
|
@@ -91,7 +88,8 @@ const LoomConfigSchema = z.object({
|
|
|
91
88
|
* defaultAdapter: 'filesystem',
|
|
92
89
|
* models: [
|
|
93
90
|
* {
|
|
94
|
-
*
|
|
91
|
+
* // Model names accept any casing: kebab-case, camelCase, PascalCase, snake_case
|
|
92
|
+
* name: 'wrongQuestions',
|
|
95
93
|
* fields: [
|
|
96
94
|
* { name: 'id', type: 'string', required: true },
|
|
97
95
|
* { name: 'name', type: 'string', required: true },
|
|
@@ -174,6 +172,57 @@ export function validateModelUniqueness(config) {
|
|
|
174
172
|
}
|
|
175
173
|
return errors;
|
|
176
174
|
}
|
|
177
|
-
//
|
|
178
|
-
|
|
175
|
+
// ── Dashboard Config Schema ──
|
|
176
|
+
const DashboardWidgetSchema = z.object({
|
|
177
|
+
type: z.enum(['stat', 'pie', 'ring', 'bar', 'line', 'area', 'scatter', 'radar', 'funnel', 'treemap', 'gauge', 'liquid', 'heatmap', 'stacked_bar', 'grouped_bar']),
|
|
178
|
+
title: z.string(),
|
|
179
|
+
model: z.string(),
|
|
180
|
+
span: z.number().int().min(1).max(24).optional(),
|
|
181
|
+
groupBy: z.string().optional(),
|
|
182
|
+
crossGroupBy: z.string().optional(),
|
|
183
|
+
aggregate: z.enum(['count', 'sum', 'avg', 'min', 'max', 'ratio']).optional(),
|
|
184
|
+
field: z.string().optional(),
|
|
185
|
+
filter: z.record(z.unknown()).optional(),
|
|
186
|
+
interval: z.enum(['day', 'week', 'month']).optional(),
|
|
187
|
+
});
|
|
188
|
+
const DashboardLayoutRowSchema = z.object({
|
|
189
|
+
row: z.array(DashboardWidgetSchema).min(1),
|
|
190
|
+
});
|
|
191
|
+
const DashboardConfigSchema = z.object({
|
|
192
|
+
name: z.string().regex(/^[a-zA-Z][a-zA-Z0-9_]*$/, 'Dashboard name must start with a letter and contain only letters, digits, or underscores'),
|
|
193
|
+
description: z.string().optional(),
|
|
194
|
+
models: z.array(z.string()).min(1),
|
|
195
|
+
layout: z.array(DashboardLayoutRowSchema).min(1),
|
|
196
|
+
});
|
|
197
|
+
/**
|
|
198
|
+
* Load dashboard.config.json from a project directory.
|
|
199
|
+
* Returns the validated DashboardConfig, or null if no config file exists.
|
|
200
|
+
*/
|
|
201
|
+
export async function loadDashboardConfig(projectRoot) {
|
|
202
|
+
const fs = await import('fs/promises');
|
|
203
|
+
const path = await import('path');
|
|
204
|
+
const configPath = path.resolve(projectRoot, 'dashboard.config.json');
|
|
205
|
+
try {
|
|
206
|
+
const raw = await fs.readFile(configPath, 'utf-8');
|
|
207
|
+
const json = JSON.parse(raw);
|
|
208
|
+
const result = DashboardConfigSchema.safeParse(json);
|
|
209
|
+
if (!result.success) {
|
|
210
|
+
const errors = result.error.issues.map((i) => ` ${i.path.join('.')}: ${i.message}`).join('\n');
|
|
211
|
+
throw new Error(`Invalid dashboard.config.json:\n${errors}`);
|
|
212
|
+
}
|
|
213
|
+
return result.data;
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
if (err instanceof SyntaxError) {
|
|
217
|
+
throw new Error(`dashboard.config.json is not valid JSON: ${err.message}`);
|
|
218
|
+
}
|
|
219
|
+
// File not found → return null (dashboard is optional)
|
|
220
|
+
if (err.code === 'ENOENT') {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
throw err;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
// Re-export zod schemas for external validation
|
|
227
|
+
export { LoomConfigSchema, DashboardConfigSchema };
|
|
179
228
|
//# sourceMappingURL=config.js.map
|