@restforgejs/mcp-server 1.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/LICENSE.md +21 -0
- package/README.md +149 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/env-parser.d.ts +30 -0
- package/dist/lib/env-parser.js +150 -0
- package/dist/lib/env-parser.js.map +1 -0
- package/dist/lib/exec.d.ts +29 -0
- package/dist/lib/exec.js +38 -0
- package/dist/lib/exec.js.map +1 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +220 -0
- package/dist/server.js.map +1 -0
- package/dist/tools/codegen/create-dashboard.d.ts +2 -0
- package/dist/tools/codegen/create-dashboard.js +256 -0
- package/dist/tools/codegen/create-dashboard.js.map +1 -0
- package/dist/tools/codegen/create-endpoint.d.ts +2 -0
- package/dist/tools/codegen/create-endpoint.js +263 -0
- package/dist/tools/codegen/create-endpoint.js.map +1 -0
- package/dist/tools/codegen/dbschema-generate-ddl.d.ts +2 -0
- package/dist/tools/codegen/dbschema-generate-ddl.js +187 -0
- package/dist/tools/codegen/dbschema-generate-ddl.js.map +1 -0
- package/dist/tools/codegen/dbschema-init.d.ts +2 -0
- package/dist/tools/codegen/dbschema-init.js +158 -0
- package/dist/tools/codegen/dbschema-init.js.map +1 -0
- package/dist/tools/codegen/dbschema-introspect.d.ts +2 -0
- package/dist/tools/codegen/dbschema-introspect.js +241 -0
- package/dist/tools/codegen/dbschema-introspect.js.map +1 -0
- package/dist/tools/codegen/dbschema-migrate.d.ts +2 -0
- package/dist/tools/codegen/dbschema-migrate.js +219 -0
- package/dist/tools/codegen/dbschema-migrate.js.map +1 -0
- package/dist/tools/codegen/dbschema-models.d.ts +2 -0
- package/dist/tools/codegen/dbschema-models.js +146 -0
- package/dist/tools/codegen/dbschema-models.js.map +1 -0
- package/dist/tools/codegen/dbschema-validate.d.ts +2 -0
- package/dist/tools/codegen/dbschema-validate.js +153 -0
- package/dist/tools/codegen/dbschema-validate.js.map +1 -0
- package/dist/tools/codegen/describe-table.d.ts +2 -0
- package/dist/tools/codegen/describe-table.js +259 -0
- package/dist/tools/codegen/describe-table.js.map +1 -0
- package/dist/tools/codegen/diff-payload.d.ts +2 -0
- package/dist/tools/codegen/diff-payload.js +165 -0
- package/dist/tools/codegen/diff-payload.js.map +1 -0
- package/dist/tools/codegen/generate-payload.d.ts +2 -0
- package/dist/tools/codegen/generate-payload.js +145 -0
- package/dist/tools/codegen/generate-payload.js.map +1 -0
- package/dist/tools/codegen/get-dashboard-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-dashboard-catalog.js +213 -0
- package/dist/tools/codegen/get-dashboard-catalog.js.map +1 -0
- package/dist/tools/codegen/get-dbschema-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-dbschema-catalog.js +244 -0
- package/dist/tools/codegen/get-dbschema-catalog.js.map +1 -0
- package/dist/tools/codegen/get-field-validation-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-field-validation-catalog.js +186 -0
- package/dist/tools/codegen/get-field-validation-catalog.js.map +1 -0
- package/dist/tools/codegen/get-query-declarative-catalog.d.ts +2 -0
- package/dist/tools/codegen/get-query-declarative-catalog.js +200 -0
- package/dist/tools/codegen/get-query-declarative-catalog.js.map +1 -0
- package/dist/tools/codegen/index.d.ts +2 -0
- package/dist/tools/codegen/index.js +43 -0
- package/dist/tools/codegen/index.js.map +1 -0
- package/dist/tools/codegen/list-tables.d.ts +2 -0
- package/dist/tools/codegen/list-tables.js +220 -0
- package/dist/tools/codegen/list-tables.js.map +1 -0
- package/dist/tools/codegen/sync-payload.d.ts +2 -0
- package/dist/tools/codegen/sync-payload.js +177 -0
- package/dist/tools/codegen/sync-payload.js.map +1 -0
- package/dist/tools/codegen/validate-dashboard-payload.d.ts +2 -0
- package/dist/tools/codegen/validate-dashboard-payload.js +239 -0
- package/dist/tools/codegen/validate-dashboard-payload.js.map +1 -0
- package/dist/tools/codegen/validate-payload.d.ts +2 -0
- package/dist/tools/codegen/validate-payload.js +166 -0
- package/dist/tools/codegen/validate-payload.js.map +1 -0
- package/dist/tools/codegen/validate-sql.d.ts +2 -0
- package/dist/tools/codegen/validate-sql.js +270 -0
- package/dist/tools/codegen/validate-sql.js.map +1 -0
- package/dist/tools/health/index.d.ts +2 -0
- package/dist/tools/health/index.js +5 -0
- package/dist/tools/health/index.js.map +1 -0
- package/dist/tools/health/ping.d.ts +2 -0
- package/dist/tools/health/ping.js +68 -0
- package/dist/tools/health/ping.js.map +1 -0
- package/dist/tools/runtime/check-launcher-exists.d.ts +2 -0
- package/dist/tools/runtime/check-launcher-exists.js +111 -0
- package/dist/tools/runtime/check-launcher-exists.js.map +1 -0
- package/dist/tools/runtime/check-status.d.ts +2 -0
- package/dist/tools/runtime/check-status.js +417 -0
- package/dist/tools/runtime/check-status.js.map +1 -0
- package/dist/tools/runtime/detect-config.d.ts +2 -0
- package/dist/tools/runtime/detect-config.js +130 -0
- package/dist/tools/runtime/detect-config.js.map +1 -0
- package/dist/tools/runtime/detect-project.d.ts +2 -0
- package/dist/tools/runtime/detect-project.js +132 -0
- package/dist/tools/runtime/detect-project.js.map +1 -0
- package/dist/tools/runtime/generate-launcher.d.ts +2 -0
- package/dist/tools/runtime/generate-launcher.js +438 -0
- package/dist/tools/runtime/generate-launcher.js.map +1 -0
- package/dist/tools/runtime/index.d.ts +2 -0
- package/dist/tools/runtime/index.js +15 -0
- package/dist/tools/runtime/index.js.map +1 -0
- package/dist/tools/runtime/validate-preflight.d.ts +2 -0
- package/dist/tools/runtime/validate-preflight.js +209 -0
- package/dist/tools/runtime/validate-preflight.js.map +1 -0
- package/dist/tools/setup/create-folder.d.ts +2 -0
- package/dist/tools/setup/create-folder.js +138 -0
- package/dist/tools/setup/create-folder.js.map +1 -0
- package/dist/tools/setup/get-config-schema.d.ts +2 -0
- package/dist/tools/setup/get-config-schema.js +158 -0
- package/dist/tools/setup/get-config-schema.js.map +1 -0
- package/dist/tools/setup/get-init-template.d.ts +2 -0
- package/dist/tools/setup/get-init-template.js +130 -0
- package/dist/tools/setup/get-init-template.js.map +1 -0
- package/dist/tools/setup/index.d.ts +2 -0
- package/dist/tools/setup/index.js +21 -0
- package/dist/tools/setup/index.js.map +1 -0
- package/dist/tools/setup/init-config.d.ts +2 -0
- package/dist/tools/setup/init-config.js +120 -0
- package/dist/tools/setup/init-config.js.map +1 -0
- package/dist/tools/setup/install-package.d.ts +2 -0
- package/dist/tools/setup/install-package.js +133 -0
- package/dist/tools/setup/install-package.js.map +1 -0
- package/dist/tools/setup/read-env.d.ts +2 -0
- package/dist/tools/setup/read-env.js +138 -0
- package/dist/tools/setup/read-env.js.map +1 -0
- package/dist/tools/setup/update-env.d.ts +2 -0
- package/dist/tools/setup/update-env.js +176 -0
- package/dist/tools/setup/update-env.js.map +1 -0
- package/dist/tools/setup/validate-config.d.ts +2 -0
- package/dist/tools/setup/validate-config.js +138 -0
- package/dist/tools/setup/validate-config.js.map +1 -0
- package/dist/tools/setup/write-env.d.ts +2 -0
- package/dist/tools/setup/write-env.js +168 -0
- package/dist/tools/setup/write-env.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { execProcess } from '../../lib/exec.js';
|
|
5
|
+
export function registerCodegenDbschemaValidate(server) {
|
|
6
|
+
server.registerTool('codegen_dbschema_validate', {
|
|
7
|
+
title: 'Validate dbschema-kit Files',
|
|
8
|
+
description: `Validate dbschema-kit schema definition files (single-model + cross-model) by wrapping restforge schema validate. Single-model checks: defineModel structure, field types, length, nullable, primary key, default value compatibility. Cross-model checks: foreign key target table existence, referenced column existence, primary key requirement for belongsTo relations.
|
|
9
|
+
|
|
10
|
+
USE WHEN:
|
|
11
|
+
- The user asks to validate schema files or check defineModel correctness
|
|
12
|
+
- Pertanyaan dalam bentuk: "validasi schema saya", "check apakah schema valid", "verify dbschema files", "cek schema definition"
|
|
13
|
+
- After authoring or editing schema files (via Write/Edit tools) — to confirm correctness before downstream actions
|
|
14
|
+
- Before invoking 'codegen_dbschema_generate_ddl' or 'codegen_dbschema_migrate' — to catch errors early
|
|
15
|
+
- The user reports an unclear error message from another dbschema action and wants a focused validation check
|
|
16
|
+
- The user asks about FK target validity ("does my FK reference work", "is the relation correct")
|
|
17
|
+
- The user wants a sanity check after introspecting from a live database (after 'codegen_dbschema_introspect')
|
|
18
|
+
|
|
19
|
+
DO NOT USE FOR:
|
|
20
|
+
- Validating CRUD payload files -> use 'codegen_validate_payload'
|
|
21
|
+
- Validating dashboard payload -> use 'codegen_validate_dashboard_payload'
|
|
22
|
+
- Validating SQL syntax -> use 'codegen_validate_sql'
|
|
23
|
+
- Looking up valid syntax -> use 'codegen_get_dbschema_catalog'
|
|
24
|
+
- Generating or applying DDL -> use 'codegen_dbschema_generate_ddl' / 'codegen_dbschema_migrate'
|
|
25
|
+
|
|
26
|
+
This tool runs: npx restforge schema validate [<path>] in the given cwd.
|
|
27
|
+
The CLI loads each file in the path (file or folder), runs single-model checks first, then cross-model checks, and reports per-file status.
|
|
28
|
+
|
|
29
|
+
Preconditions:
|
|
30
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
31
|
+
- The schema path (default './schema') must exist. If the CLI fails because the folder is missing, the failure response surfaces the underlying cause.
|
|
32
|
+
|
|
33
|
+
PRESENTATION GUIDANCE:
|
|
34
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
35
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "validate the schema files", "look up the schema catalog", "generate the DDL").
|
|
36
|
+
- Speak in plain language. Summarise the result; do not paste the raw CLI output unless the user explicitly asks.
|
|
37
|
+
- Validation covers two layers: single-model (struct, types, constraints) and cross-model (FK target tables and columns). A model can be single-valid but fail cross-model if its FK target does not exist.
|
|
38
|
+
- The path defaults to './schema'. If the user organizes files differently (e.g. 'db/models'), confirm the path before invoking.
|
|
39
|
+
- When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
|
|
40
|
+
inputSchema: {
|
|
41
|
+
cwd: z
|
|
42
|
+
.string()
|
|
43
|
+
.min(1)
|
|
44
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform)'),
|
|
45
|
+
path: z
|
|
46
|
+
.string()
|
|
47
|
+
.min(1)
|
|
48
|
+
.optional()
|
|
49
|
+
.describe('Path to schema file or folder relative to cwd. When omitted, the CLI uses its default (./schema).'),
|
|
50
|
+
},
|
|
51
|
+
annotations: {
|
|
52
|
+
title: 'Validate dbschema-kit Files',
|
|
53
|
+
readOnlyHint: true,
|
|
54
|
+
idempotentHint: true,
|
|
55
|
+
},
|
|
56
|
+
}, async ({ cwd, path }) => {
|
|
57
|
+
const projectCwd = resolve(cwd);
|
|
58
|
+
// Precondition check: @restforgejs/platform must be present in node_modules. per §3.4
|
|
59
|
+
try {
|
|
60
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return {
|
|
64
|
+
content: [
|
|
65
|
+
{
|
|
66
|
+
type: 'text',
|
|
67
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
68
|
+
|
|
69
|
+
Project path: ${projectCwd}
|
|
70
|
+
Expected location: node_modules/@restforgejs/platform
|
|
71
|
+
Requested schema path: ${path ?? 'default (./schema)'}
|
|
72
|
+
|
|
73
|
+
For the assistant:
|
|
74
|
+
- The user needs to install the RESTForge package before schema files can be validated.
|
|
75
|
+
- Suggest installing the package first, then retry validating the schema.
|
|
76
|
+
- When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
isError: false, // per §3.4
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
// Forward only the arguments the user supplied. CLI default './schema' applies otherwise. per §3.5
|
|
83
|
+
const cliArgs = ['restforge', 'schema', 'validate'];
|
|
84
|
+
if (path !== undefined)
|
|
85
|
+
cliArgs.push(path);
|
|
86
|
+
const result = await execProcess('npx', cliArgs, {
|
|
87
|
+
cwd: projectCwd,
|
|
88
|
+
timeout: 30_000,
|
|
89
|
+
env: { NODE_ENV: 'production' },
|
|
90
|
+
stripFinalNewline: true,
|
|
91
|
+
});
|
|
92
|
+
// Branch C: CLI failure — real error per §3.4 (validation failures land here). per §3.5
|
|
93
|
+
if (!result.success) {
|
|
94
|
+
return {
|
|
95
|
+
content: [
|
|
96
|
+
{
|
|
97
|
+
type: 'text',
|
|
98
|
+
text: `Schema validation failed.
|
|
99
|
+
|
|
100
|
+
Project path: ${projectCwd}
|
|
101
|
+
Schema path: ${path ?? 'default (./schema)'}
|
|
102
|
+
Command: ${result.command}
|
|
103
|
+
Exit code: ${result.exitCode}
|
|
104
|
+
|
|
105
|
+
--- CLI output ---
|
|
106
|
+
stdout:
|
|
107
|
+
${result.stdout}
|
|
108
|
+
|
|
109
|
+
stderr:
|
|
110
|
+
${result.stderr}
|
|
111
|
+
--- end CLI output ---
|
|
112
|
+
|
|
113
|
+
For the assistant:
|
|
114
|
+
- Tell the user that the schema validation surfaced one or more issues (or could not run at all).
|
|
115
|
+
- Summarise the most likely cause from the CLI output in plain language. Common causes:
|
|
116
|
+
* Single-model error — a field has an invalid type, constraint, or shorthand. Suggest reviewing the offending file and consulting the schema catalog for valid syntax.
|
|
117
|
+
* Cross-model error — a foreign key references a table or column that does not exist in any sibling schema file. Suggest checking the FK target name and that the referenced model is included in the same path.
|
|
118
|
+
* Schema folder not found — the CLI cannot locate the path. Suggest verifying the folder name (default is './schema').
|
|
119
|
+
* Unknown command 'schema validate' — the installed RESTForge version may be older than this CLI subcommand; suggest upgrading the package.
|
|
120
|
+
- Read the per-file error report in the CLI output to identify the failing file and field. Help the user fix it by referencing the catalog (do not invent rules from training data).
|
|
121
|
+
- Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.
|
|
122
|
+
- Offer to retry once the issue is resolved.`,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
isError: true, // per §3.4
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Branch B: success — labeled facts + fenced raw output per §3.5.
|
|
129
|
+
return {
|
|
130
|
+
content: [
|
|
131
|
+
{
|
|
132
|
+
type: 'text',
|
|
133
|
+
text: `Schema validation passed.
|
|
134
|
+
|
|
135
|
+
Project path: ${projectCwd}
|
|
136
|
+
Schema path: ${path ?? 'default (./schema)'}
|
|
137
|
+
|
|
138
|
+
--- CLI output ---
|
|
139
|
+
${result.stdout}
|
|
140
|
+
--- end CLI output ---
|
|
141
|
+
|
|
142
|
+
For the assistant:
|
|
143
|
+
- Confirm to the user that all schema files are valid. If the CLI output lists per-file status lines, count them and mention the file count in plain language.
|
|
144
|
+
- The validation covers both single-model (type, length, nullable, primary key, default value) and cross-model (FK target table existence, referenced column existence). All layers passed.
|
|
145
|
+
- Suggest the next step depending on user intent: list models for an overview, generate DDL for review, or apply via migrate.
|
|
146
|
+
- Do not paste the raw CLI output unless the user explicitly asks.
|
|
147
|
+
- Match the user's language.`,
|
|
148
|
+
},
|
|
149
|
+
],
|
|
150
|
+
};
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=dbschema-validate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dbschema-validate.js","sourceRoot":"","sources":["../../../src/tools/codegen/dbschema-validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,UAAU,+BAA+B,CAAC,MAAiB;IAC/D,MAAM,CAAC,YAAY,CACjB,2BAA2B,EAC3B;QACE,KAAK,EAAE,6BAA6B;QACpC,WAAW,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;uGA+BoF;QACjG,WAAW,EAAE;YACX,GAAG,EAAE,CAAC;iBACH,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,CAAC,uFAAuF,CAAC;YACpG,IAAI,EAAE,CAAC;iBACJ,MAAM,EAAE;iBACR,GAAG,CAAC,CAAC,CAAC;iBACN,QAAQ,EAAE;iBACV,QAAQ,CAAC,mGAAmG,CAAC;SACjH;QACD,WAAW,EAAE;YACX,KAAK,EAAE,6BAA6B;YACpC,YAAY,EAAE,IAAI;YAClB,cAAc,EAAE,IAAI;SACrB;KACF,EACD,KAAK,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE;QACtB,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAEhC,sFAAsF;QACtF,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,cAAc,EAAE,UAAU,CAAC,CAAC,CAAC;QAC7E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;gBAEJ,UAAU;;yBAED,IAAI,IAAI,oBAAoB;;;;;gKAK2G;qBACnJ;iBACF;gBACD,OAAO,EAAE,KAAK,EAAE,WAAW;aAC5B,CAAC;QACJ,CAAC;QAED,mGAAmG;QACnG,MAAM,OAAO,GAAG,CAAC,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACpD,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE3C,MAAM,MAAM,GAAG,MAAM,WAAW,CAC9B,KAAK,EACL,OAAO,EACP;YACE,GAAG,EAAE,UAAU;YACf,OAAO,EAAE,MAAM;YACf,GAAG,EAAE,EAAE,QAAQ,EAAE,YAAY,EAAE;YAC/B,iBAAiB,EAAE,IAAI;SACxB,CACF,CAAC;QAEF,wFAAwF;QACxF,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,OAAO;gBACL,OAAO,EAAE;oBACP;wBACE,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE;;gBAEJ,UAAU;eACX,IAAI,IAAI,oBAAoB;WAChC,MAAM,CAAC,OAAO;aACZ,MAAM,CAAC,QAAQ;;;;EAI1B,MAAM,CAAC,MAAM;;;EAGb,MAAM,CAAC,MAAM;;;;;;;;;;;;6CAY8B;qBAChC;iBACF;gBACD,OAAO,EAAE,IAAI,EAAE,WAAW;aAC3B,CAAC;QACJ,CAAC;QAED,kEAAkE;QAClE,OAAO;YACL,OAAO,EAAE;gBACP;oBACE,IAAI,EAAE,MAAM;oBACZ,IAAI,EAAE;;gBAEF,UAAU;eACX,IAAI,IAAI,oBAAoB;;;EAGzC,MAAM,CAAC,MAAM;;;;;;;;6BAQc;iBAClB;aACF;SACF,CAAC;IACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { execProcess } from '../../lib/exec.js';
|
|
5
|
+
export function registerCodegenDescribeTable(server) {
|
|
6
|
+
server.registerTool('codegen_describe_table', {
|
|
7
|
+
title: 'Describe Database Table',
|
|
8
|
+
description: `Describe a single database table — columns (with dialect-specific types), primary key, foreign keys, and indexes — by wrapping restforge schema describe. Live introspection — the CLI connects to the database and queries the catalog.
|
|
9
|
+
|
|
10
|
+
USE WHEN:
|
|
11
|
+
- The user asks about the columns, primary key, foreign keys, or indexes of a specific table
|
|
12
|
+
- Pertanyaan dalam bentuk seperti "kolom apa saja di tabel X", "describe tabel sales_order", "show schema for users table", "tabel X punya FK ke mana", "ada index apa di tabel Y"
|
|
13
|
+
- Before authoring a SQL JOIN — to discover the foreign key path between two tables and write the JOIN clause correctly
|
|
14
|
+
- Before authoring a dashboard widget query — to confirm column names and types before composing the SELECT
|
|
15
|
+
- The user wants to verify whether a specific column exists in a table
|
|
16
|
+
- The user asks "what type is column X in table Y" — column type is dialect-specific so live introspection is more reliable than guessing
|
|
17
|
+
- Before invoking 'codegen_create_dashboard' (with widget SQL) — to ground SQL identifiers in the live schema
|
|
18
|
+
- After 'codegen_list_tables' returned a candidate name and the user wants the per-column details
|
|
19
|
+
|
|
20
|
+
DO NOT USE FOR:
|
|
21
|
+
- Listing all tables in the database -> use 'codegen_list_tables'
|
|
22
|
+
- Querying the actual row data inside a table -> out of scope; this tool returns metadata (columns, PK, FK, indexes) only, not row content
|
|
23
|
+
- Validating a payload spec file against the database schema (file-level diff) -> use 'codegen_validate_payload' or 'codegen_diff_payload'
|
|
24
|
+
- Modifying the schema (ALTER TABLE) -> out of scope
|
|
25
|
+
- Inspecting the SQL definition behind a database view -> out of scope; only column-level info is returned for views
|
|
26
|
+
- Cross-database introspection (multiple databases at once) -> out of scope; a single config = a single connection
|
|
27
|
+
|
|
28
|
+
Cross-reference: this tool is the sibling of 'codegen_list_tables'. Use list-tables first to discover candidate names, then describe-table for the per-column details.
|
|
29
|
+
|
|
30
|
+
This tool runs: npx restforge schema describe --config=<config> --table=<table> [--include-foreign-keys=<bool>] [--include-indexes=<bool>] in the given cwd.
|
|
31
|
+
The CLI connects to the database described in the config file, queries the catalog, and emits a JSON envelope with the table metadata.
|
|
32
|
+
|
|
33
|
+
Preconditions:
|
|
34
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
35
|
+
- The config file (default 'db-connection.env') must exist in the project and contain valid database credentials. This tool does not pre-check that — if the CLI fails, the failure response will surface the underlying cause.
|
|
36
|
+
- The named table must exist in the database; otherwise the CLI fails with a "Table 'X' not found" error.
|
|
37
|
+
|
|
38
|
+
PRESENTATION GUIDANCE:
|
|
39
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
40
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "describe the table", "list the database tables", "install the package").
|
|
41
|
+
- Speak in plain language. Summarise the result; do not paste the raw JSON unless the user explicitly asks.
|
|
42
|
+
- This is a live introspection: the tool actively queries the database catalog. The result reflects the schema state at query time.
|
|
43
|
+
- Column types are dialect-specific (Postgres: 'character varying(N)', MySQL: 'varchar(N)', Oracle: 'VARCHAR2(N)'). Use the type as-is when the user asks about column constraints; do not normalise.
|
|
44
|
+
- Foreign key 'references' field is the JOIN target — when the user asks "how do I join A and B", look at FK paths in both directions to compose the JOIN clause.
|
|
45
|
+
- When a precondition is not met (e.g. the package is not installed), frame it as a question or next-step suggestion rather than an error.`,
|
|
46
|
+
inputSchema: {
|
|
47
|
+
cwd: z
|
|
48
|
+
.string()
|
|
49
|
+
.min(1)
|
|
50
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform and the config file)'),
|
|
51
|
+
config: z
|
|
52
|
+
.string()
|
|
53
|
+
.min(1)
|
|
54
|
+
.default('db-connection.env')
|
|
55
|
+
.describe('Config file name relative to the project, used by the CLI to connect to the database'),
|
|
56
|
+
table: z
|
|
57
|
+
.string()
|
|
58
|
+
.min(1)
|
|
59
|
+
.describe('Table name to describe. Format: <schema>.<table> or just <table> (the CLI resolves the schema). Example: supplier, public.supplier, core.users.'),
|
|
60
|
+
includeForeignKeys: z
|
|
61
|
+
.boolean()
|
|
62
|
+
.optional()
|
|
63
|
+
.describe('Default true (CLI default). When false, omit the foreignKeys field from output.'),
|
|
64
|
+
includeIndexes: z
|
|
65
|
+
.boolean()
|
|
66
|
+
.optional()
|
|
67
|
+
.describe('Default true (CLI default). When false, omit the indexes field from output.'),
|
|
68
|
+
},
|
|
69
|
+
annotations: {
|
|
70
|
+
title: 'Describe Database Table',
|
|
71
|
+
readOnlyHint: true,
|
|
72
|
+
idempotentHint: true,
|
|
73
|
+
},
|
|
74
|
+
}, async ({ cwd, config, table, includeForeignKeys, includeIndexes }) => {
|
|
75
|
+
const projectCwd = resolve(cwd);
|
|
76
|
+
// Precondition check: @restforgejs/platform must be present in node_modules.
|
|
77
|
+
// Treated as a non-error precondition per the authoring guide §3.4.
|
|
78
|
+
try {
|
|
79
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
return {
|
|
83
|
+
content: [
|
|
84
|
+
{
|
|
85
|
+
type: 'text',
|
|
86
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
87
|
+
|
|
88
|
+
Project path: ${projectCwd}
|
|
89
|
+
Expected location: node_modules/@restforgejs/platform
|
|
90
|
+
Requested table: ${table}
|
|
91
|
+
Requested config: ${config}
|
|
92
|
+
Requested includeForeignKeys: ${includeForeignKeys ?? 'default (true)'}
|
|
93
|
+
Requested includeIndexes: ${includeIndexes ?? 'default (true)'}
|
|
94
|
+
|
|
95
|
+
For the assistant:
|
|
96
|
+
- The user needs to install the RESTForge package before the table description can be retrieved.
|
|
97
|
+
- Suggest installing the package first, then retry describing the table.
|
|
98
|
+
- When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
isError: false, // per §3.4
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
// Forward only the arguments the user supplied. CLI defaults remain in
|
|
105
|
+
// effect when the user does not specify them. per §3.5
|
|
106
|
+
const cliArgs = [
|
|
107
|
+
'restforge',
|
|
108
|
+
'schema',
|
|
109
|
+
'describe',
|
|
110
|
+
`--config=${config}`,
|
|
111
|
+
`--table=${table}`,
|
|
112
|
+
];
|
|
113
|
+
if (includeForeignKeys !== undefined)
|
|
114
|
+
cliArgs.push(`--include-foreign-keys=${includeForeignKeys}`);
|
|
115
|
+
if (includeIndexes !== undefined)
|
|
116
|
+
cliArgs.push(`--include-indexes=${includeIndexes}`);
|
|
117
|
+
const result = await execProcess('npx', cliArgs, {
|
|
118
|
+
cwd: projectCwd,
|
|
119
|
+
timeout: 30_000,
|
|
120
|
+
env: { NODE_ENV: 'production' },
|
|
121
|
+
stripFinalNewline: true,
|
|
122
|
+
});
|
|
123
|
+
// Branch C: CLI failure — real error per §3.4; structured per §3.5.
|
|
124
|
+
if (!result.success) {
|
|
125
|
+
return {
|
|
126
|
+
content: [
|
|
127
|
+
{
|
|
128
|
+
type: 'text',
|
|
129
|
+
text: `Failed to describe the database table.
|
|
130
|
+
|
|
131
|
+
Project path: ${projectCwd}
|
|
132
|
+
Config: ${config}
|
|
133
|
+
Table: ${table}
|
|
134
|
+
includeForeignKeys: ${includeForeignKeys ?? 'default (true)'}
|
|
135
|
+
includeIndexes: ${includeIndexes ?? 'default (true)'}
|
|
136
|
+
Command: ${result.command}
|
|
137
|
+
Exit code: ${result.exitCode}
|
|
138
|
+
|
|
139
|
+
--- CLI output ---
|
|
140
|
+
stdout:
|
|
141
|
+
${result.stdout}
|
|
142
|
+
|
|
143
|
+
stderr:
|
|
144
|
+
${result.stderr}
|
|
145
|
+
--- end CLI output ---
|
|
146
|
+
|
|
147
|
+
For the assistant:
|
|
148
|
+
- Tell the user that describing the table did not complete successfully.
|
|
149
|
+
- Summarise the most likely cause from the CLI output in plain language. Common causes:
|
|
150
|
+
* Table not found — the most common error. Suggest that the table name might be misspelled or that the user is looking in a different schema; offer to list the available tables first to find candidate names.
|
|
151
|
+
* Config file not found — suggest verifying the path and that the file exists in the project.
|
|
152
|
+
* Database connection failed — suggest verifying the credentials, that the host is reachable, and that the port is open.
|
|
153
|
+
* Unknown command 'schema describe' — the installed RESTForge version may be older than this CLI subcommand; suggest upgrading the package.
|
|
154
|
+
- Do not paste the raw stdout/stderr unless the user explicitly asks. Do not mention internal tool names.
|
|
155
|
+
- Offer to retry once the underlying issue is resolved.`,
|
|
156
|
+
},
|
|
157
|
+
],
|
|
158
|
+
isError: true, // per §3.4
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
// Branch D: JSON parse failure — real error per §3.4 (CLI succeeded but produced invalid output).
|
|
162
|
+
let parsed;
|
|
163
|
+
try {
|
|
164
|
+
parsed = JSON.parse(result.stdout);
|
|
165
|
+
}
|
|
166
|
+
catch (err) {
|
|
167
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
168
|
+
return {
|
|
169
|
+
content: [
|
|
170
|
+
{
|
|
171
|
+
type: 'text',
|
|
172
|
+
text: `Failed to parse the table description as JSON.
|
|
173
|
+
|
|
174
|
+
Project path: ${projectCwd}
|
|
175
|
+
Config: ${config}
|
|
176
|
+
Table: ${table}
|
|
177
|
+
Reason: ${msg}
|
|
178
|
+
|
|
179
|
+
--- Raw stdout ---
|
|
180
|
+
${result.stdout}
|
|
181
|
+
--- end Raw stdout ---
|
|
182
|
+
|
|
183
|
+
For the assistant:
|
|
184
|
+
- The CLI returned output that is not valid JSON.
|
|
185
|
+
- Summarise this to the user in plain language; do not paste the raw stdout unless they explicitly ask.
|
|
186
|
+
- Suggest checking that the installed RESTForge package version is compatible. Do not mention internal tool names.`,
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
isError: true, // per §3.4
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
// Defensive labeled facts: if the JSON shape changes upstream, fall back to 'unknown' / 'n/a'
|
|
193
|
+
// rather than crashing. Mirror the catalog tools pattern.
|
|
194
|
+
const root = (parsed ?? {});
|
|
195
|
+
const tableObj = (root.table ?? {});
|
|
196
|
+
const tableSchema = typeof tableObj.schema === 'string' ? tableObj.schema : 'unknown';
|
|
197
|
+
const tableName = typeof tableObj.name === 'string' ? tableObj.name : 'unknown';
|
|
198
|
+
const tableType = typeof tableObj.type === 'string' ? tableObj.type : 'unknown';
|
|
199
|
+
const databaseType = typeof root.database === 'string' ? root.database : 'unknown';
|
|
200
|
+
const columns = Array.isArray(root.columns) ? root.columns : [];
|
|
201
|
+
const columnsCount = columns.length;
|
|
202
|
+
const pk = root.primaryKey;
|
|
203
|
+
let primaryKeyLabel;
|
|
204
|
+
if (pk && typeof pk === 'object' && Array.isArray(pk.columns)) {
|
|
205
|
+
const pkCols = pk.columns;
|
|
206
|
+
primaryKeyLabel = `[${pkCols.map((c) => JSON.stringify(c)).join(', ')}]`;
|
|
207
|
+
}
|
|
208
|
+
else if (pk === null) {
|
|
209
|
+
primaryKeyLabel = 'none';
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
primaryKeyLabel = 'unknown';
|
|
213
|
+
}
|
|
214
|
+
const foreignKeysCount = includeForeignKeys === false
|
|
215
|
+
? 'n/a (excluded)'
|
|
216
|
+
: Array.isArray(root.foreignKeys)
|
|
217
|
+
? root.foreignKeys.length
|
|
218
|
+
: 'unknown';
|
|
219
|
+
const indexesCount = includeIndexes === false
|
|
220
|
+
? 'n/a (excluded)'
|
|
221
|
+
: Array.isArray(root.indexes)
|
|
222
|
+
? root.indexes.length
|
|
223
|
+
: 'unknown';
|
|
224
|
+
const prettyJson = JSON.stringify(parsed, null, 2);
|
|
225
|
+
// Branch B: success — one-line summary + labeled facts + fenced JSON output per §3.5.
|
|
226
|
+
return {
|
|
227
|
+
content: [
|
|
228
|
+
{
|
|
229
|
+
type: 'text',
|
|
230
|
+
text: `Table description retrieved successfully.
|
|
231
|
+
|
|
232
|
+
Project path: ${projectCwd}
|
|
233
|
+
Config: ${config}
|
|
234
|
+
Database: ${databaseType}
|
|
235
|
+
Table: ${tableSchema}.${tableName} (${tableType})
|
|
236
|
+
columnsCount: ${columnsCount}
|
|
237
|
+
primaryKey: ${primaryKeyLabel}
|
|
238
|
+
foreignKeysCount: ${foreignKeysCount}
|
|
239
|
+
indexesCount: ${indexesCount}
|
|
240
|
+
|
|
241
|
+
--- Table Description (JSON) ---
|
|
242
|
+
${prettyJson}
|
|
243
|
+
--- end Table Description (JSON) ---
|
|
244
|
+
|
|
245
|
+
For the assistant:
|
|
246
|
+
- Confirm to the user that the table description was retrieved. Mention the table name and column count in plain language.
|
|
247
|
+
- When the user asked to compose a SQL query (e.g. for a dashboard widget), use this metadata as ground truth for: (1) column names and types — match SQL identifiers exactly; (2) primary key — for JOIN target identity; (3) foreign keys — for cross-table JOIN paths; (4) indexes — informational, helps anticipate query performance.
|
|
248
|
+
- Column types are dialect-specific (e.g. 'character varying(50)' in Postgres, 'varchar(50)' in MySQL, 'VARCHAR2(50)' in Oracle). Use the type as-is when the user asks about column constraints; do not normalise.
|
|
249
|
+
- Foreign keys describe the schema-level relationship (which column references which target). Use the 'references' field to write JOIN clauses correctly.
|
|
250
|
+
- This is a read-only operation: it queries the database catalog without modifying anything.
|
|
251
|
+
- Do not paste the full JSON unless the user asks. Summarise — for a wide table (more than 10 columns), list only the columns relevant to the user's task.
|
|
252
|
+
- For listing all tables in the database, suggest the table-list action. Do not mention internal tool names.
|
|
253
|
+
- Match the user's language.`,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
};
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=describe-table.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"describe-table.js","sourceRoot":"","sources":["../../../src/tools/codegen/describe-table.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { access } from 'node:fs/promises';
|
|
3
|
+
import { resolve, join } from 'node:path';
|
|
4
|
+
import { execProcess } from '../../lib/exec.js';
|
|
5
|
+
export function registerCodegenDiffPayload(server) {
|
|
6
|
+
server.registerTool('codegen_diff_payload', {
|
|
7
|
+
title: 'Diff Payload',
|
|
8
|
+
description: `Show the column-level differences between existing payload spec files and the current database schema, by running restforge payload --diff.
|
|
9
|
+
|
|
10
|
+
USE WHEN:
|
|
11
|
+
- The user asks to see the detailed differences between a payload file and the current database schema (column-level)
|
|
12
|
+
- The user asks things like "tunjukkan diff payload", "apa yang berubah di table X", "kolom apa saja yang baru", "show schema diff", "what columns changed"
|
|
13
|
+
- After 'codegen_validate_payload' reported DRIFT and the user wants to know what specifically changed
|
|
14
|
+
- Pre-flight inspection before deciding whether to run sync
|
|
15
|
+
- Often called after 'codegen_validate_payload' once a DRIFT status is reported, to drill into the column-level differences for the affected file.
|
|
16
|
+
|
|
17
|
+
DO NOT USE FOR:
|
|
18
|
+
- Quick overall status (OK / DRIFT / ERROR per file) -> use 'codegen_validate_payload'
|
|
19
|
+
- Generating a payload from scratch for a table that has no payload yet -> use 'codegen_generate_payload'
|
|
20
|
+
- Applying the changes to payload files -> use 'codegen_sync_payload'
|
|
21
|
+
|
|
22
|
+
This tool runs: npx restforge payload --diff --config=<config> [--table=<table>] [--output=<output>] in the given cwd.
|
|
23
|
+
The CLI reads existing payload JSON files from the output directory, connects to the database described
|
|
24
|
+
in the config file, and prints a per-column diff (added, removed, or type-changed columns) without
|
|
25
|
+
modifying any file. The CLI typically uses '[+]' for added columns, '[-]' for removed columns,
|
|
26
|
+
and '[~]' for type-changed columns.
|
|
27
|
+
|
|
28
|
+
Preconditions:
|
|
29
|
+
- The project must have @restforgejs/platform installed in node_modules.
|
|
30
|
+
- The config file (default 'db-connection.env') must exist in the project and contain valid
|
|
31
|
+
database credentials. This tool does not pre-check that — if the CLI fails, the failure response
|
|
32
|
+
will surface the underlying cause.
|
|
33
|
+
|
|
34
|
+
PRESENTATION GUIDANCE:
|
|
35
|
+
- Match the user's language. If the user writes in Indonesian, respond in Indonesian.
|
|
36
|
+
- Never mention internal tool names in the reply to the user. Describe actions by what they do (e.g. "see the column-level differences", "do a quick overall validation", "sync the payload files").
|
|
37
|
+
- Speak in plain language. Summarise the result; do not paste raw CLI output unless the user explicitly asks.
|
|
38
|
+
- When a precondition is not met, frame it as a question or next-step suggestion rather than an error.`,
|
|
39
|
+
inputSchema: {
|
|
40
|
+
cwd: z
|
|
41
|
+
.string()
|
|
42
|
+
.min(1)
|
|
43
|
+
.describe('Absolute path of the project folder (must contain node_modules/@restforgejs/platform and the config file)'),
|
|
44
|
+
config: z
|
|
45
|
+
.string()
|
|
46
|
+
.min(1)
|
|
47
|
+
.default('db-connection.env')
|
|
48
|
+
.describe('Config file name (relative to project) used by the CLI to connect to the database'),
|
|
49
|
+
table: z
|
|
50
|
+
.string()
|
|
51
|
+
.min(1)
|
|
52
|
+
.optional()
|
|
53
|
+
.describe('Specific table name to inspect (e.g. supplier or core.supplier). When omitted, all payload files in the output directory are diffed.'),
|
|
54
|
+
output: z
|
|
55
|
+
.string()
|
|
56
|
+
.min(1)
|
|
57
|
+
.optional()
|
|
58
|
+
.describe('Payload directory relative to project (e.g. payload). When omitted, the CLI uses its default (payload/).'),
|
|
59
|
+
},
|
|
60
|
+
annotations: {
|
|
61
|
+
title: 'Diff Payload',
|
|
62
|
+
readOnlyHint: true,
|
|
63
|
+
idempotentHint: true,
|
|
64
|
+
},
|
|
65
|
+
}, async ({ cwd, config, table, output }) => {
|
|
66
|
+
const projectCwd = resolve(cwd);
|
|
67
|
+
// Precondition check: @restforgejs/platform must be present in node_modules.
|
|
68
|
+
// Treated as a non-error precondition per the authoring guide §3.4.
|
|
69
|
+
try {
|
|
70
|
+
await access(join(projectCwd, 'node_modules', '@restforgejs', 'platform'));
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return {
|
|
74
|
+
content: [
|
|
75
|
+
{
|
|
76
|
+
type: 'text',
|
|
77
|
+
text: `Precondition not met: the RESTForge package is not installed in this project.
|
|
78
|
+
|
|
79
|
+
Project path: ${projectCwd}
|
|
80
|
+
Expected location: node_modules/@restforgejs/platform
|
|
81
|
+
Requested table: ${table ?? 'all'}
|
|
82
|
+
Requested config: ${config}
|
|
83
|
+
Requested output: ${output ?? 'default (payload/)'}
|
|
84
|
+
|
|
85
|
+
For the assistant:
|
|
86
|
+
- The user needs to install the RESTForge package before column-level differences can be computed against the database schema.
|
|
87
|
+
- Use the appropriate package-installation tool to do this, then retry computing the differences.
|
|
88
|
+
- When explaining to the user, say something like "the RESTForge package isn't installed yet — should I install it first?". Do not mention internal tool names.`,
|
|
89
|
+
},
|
|
90
|
+
],
|
|
91
|
+
isError: false, // per §3.4
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// Forward only the arguments the user supplied. Defaults inside restforge
|
|
95
|
+
// (e.g. payload/ as the default output dir, all files when --table is omitted)
|
|
96
|
+
// should remain in effect when the user does not specify them. per §3.5
|
|
97
|
+
const args = ['restforge', 'payload', 'diff', `--config=${config}`];
|
|
98
|
+
if (table)
|
|
99
|
+
args.push(`--table=${table}`);
|
|
100
|
+
if (output)
|
|
101
|
+
args.push(`--output=${output}`);
|
|
102
|
+
const result = await execProcess('npx', args, { cwd: projectCwd, timeout: 30_000 });
|
|
103
|
+
// CLI failure: real error per §3.4; structured per §3.5.
|
|
104
|
+
if (!result.success) {
|
|
105
|
+
return {
|
|
106
|
+
content: [
|
|
107
|
+
{
|
|
108
|
+
type: 'text',
|
|
109
|
+
text: `Failed to diff payload.
|
|
110
|
+
|
|
111
|
+
Project path: ${projectCwd}
|
|
112
|
+
Config: ${config}
|
|
113
|
+
Table: ${table ?? 'all'}
|
|
114
|
+
Output: ${output ?? 'default (payload/)'}
|
|
115
|
+
Command: ${result.command}
|
|
116
|
+
Exit code: ${result.exitCode}
|
|
117
|
+
|
|
118
|
+
--- CLI output ---
|
|
119
|
+
stdout:
|
|
120
|
+
${result.stdout}
|
|
121
|
+
|
|
122
|
+
stderr:
|
|
123
|
+
${result.stderr}
|
|
124
|
+
--- end CLI output ---
|
|
125
|
+
|
|
126
|
+
For the assistant:
|
|
127
|
+
- Tell the user that computing the column-level differences did not complete successfully.
|
|
128
|
+
- Summarise the likely cause from the CLI output in plain language (common causes: the config file is missing or has incomplete credentials, the database is unreachable, the requested table does not exist, or the payload directory is empty). Do not paste the raw stdout/stderr unless the user explicitly asks.
|
|
129
|
+
- Offer to retry once the underlying issue is resolved. Do not mention internal tool names.`,
|
|
130
|
+
},
|
|
131
|
+
],
|
|
132
|
+
isError: true, // per §3.4
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
// Success: one-line summary + labeled facts + fenced raw output per §3.5.
|
|
136
|
+
// The CLI prints column-level diff with [+], [-], [~] markers; the model
|
|
137
|
+
// should translate those markers into plain language when talking to the user.
|
|
138
|
+
return {
|
|
139
|
+
content: [
|
|
140
|
+
{
|
|
141
|
+
type: 'text',
|
|
142
|
+
text: `Payload diff completed.
|
|
143
|
+
|
|
144
|
+
Project path: ${projectCwd}
|
|
145
|
+
Config: ${config}
|
|
146
|
+
Table: ${table ?? 'all'}
|
|
147
|
+
Output: ${output ?? 'default (payload/)'}
|
|
148
|
+
Command: ${result.command}
|
|
149
|
+
|
|
150
|
+
--- CLI output ---
|
|
151
|
+
${result.stdout}
|
|
152
|
+
--- end CLI output ---
|
|
153
|
+
|
|
154
|
+
For the assistant:
|
|
155
|
+
- Translate the diff markers into plain language for the user: '[+]' means a new column in the database that is not yet in the payload file, '[-]' means a column that exists in the payload file but has been removed from the database, and '[~]' means a column whose data type has changed.
|
|
156
|
+
- Group the differences per file or per table when multiple are reported, and name the affected columns explicitly so the user can decide what to do.
|
|
157
|
+
- If there are no differences, confirm in plain language that the payload files match the database.
|
|
158
|
+
- If the user wants to apply these changes, mention that the next step is to update the payload files automatically (with the previous version archived). Describe this step in plain language; do not name the internal tool.
|
|
159
|
+
- Keep the reply concise. Do not paste the raw CLI output unless the user explicitly asks. Do not mention internal tool names.`,
|
|
160
|
+
},
|
|
161
|
+
],
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
//# sourceMappingURL=diff-payload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-payload.js","sourceRoot":"","sources":["../../../src/tools/codegen/diff-payload.ts"],"names":[],"mappings":"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"}
|