@saltcorn/copilot 0.8.2 → 0.8.3
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/actions/generate-page.js +6 -2
- package/actions/generate-tables.js +56 -6
- package/actions/generate-workflow.js +54 -3
- package/agent-skills/pagegen.js +155 -57
- package/agent-skills/registry-editor.js +15 -2
- package/app-constructor/common.js +7 -1
- package/app-constructor/errors.js +749 -61
- package/app-constructor/feedback-action.js +62 -60
- package/app-constructor/feedback.js +1294 -67
- package/app-constructor/fixed-prompts.js +829 -0
- package/app-constructor/phases.js +1485 -0
- package/app-constructor/prompt-generator.js +587 -0
- package/app-constructor/requirements.js +113 -54
- package/app-constructor/research.js +350 -0
- package/app-constructor/run_task.js +195 -64
- package/app-constructor/schema.js +163 -324
- package/app-constructor/tasks.js +90 -886
- package/app-constructor/tools.js +13 -1
- package/app-constructor/view.js +307 -54
- package/builder-gen.js +11 -8
- package/builder-schema.js +6 -0
- package/package.json +1 -1
- package/app-constructor/prompts.js +0 -120
|
@@ -1,364 +1,203 @@
|
|
|
1
|
-
const Field = require("@saltcorn/data/models/field");
|
|
2
1
|
const Table = require("@saltcorn/data/models/table");
|
|
3
|
-
const Form = require("@saltcorn/data/models/form");
|
|
4
2
|
const MetaData = require("@saltcorn/data/models/metadata");
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const { findType } = require("@saltcorn/data/models/discovery");
|
|
8
|
-
const { save_menu_items } = require("@saltcorn/data/models/config");
|
|
9
|
-
const db = require("@saltcorn/data/db");
|
|
10
|
-
const WorkflowRun = require("@saltcorn/data/models/workflow_run");
|
|
11
|
-
const {
|
|
12
|
-
localeDateTime,
|
|
13
|
-
renderForm,
|
|
14
|
-
mkTable,
|
|
15
|
-
post_delete_btn,
|
|
16
|
-
} = require("@saltcorn/markup");
|
|
17
|
-
const {
|
|
18
|
-
div,
|
|
19
|
-
script,
|
|
20
|
-
domReady,
|
|
21
|
-
pre,
|
|
22
|
-
code,
|
|
23
|
-
input,
|
|
24
|
-
h4,
|
|
25
|
-
style,
|
|
26
|
-
h5,
|
|
27
|
-
button,
|
|
28
|
-
text_attr,
|
|
29
|
-
i,
|
|
30
|
-
p,
|
|
31
|
-
span,
|
|
32
|
-
small,
|
|
33
|
-
form,
|
|
34
|
-
textarea,
|
|
35
|
-
} = require("@saltcorn/markup/tags");
|
|
36
|
-
const { getState } = require("@saltcorn/data/db/state");
|
|
37
|
-
const renderLayout = require("@saltcorn/markup/layout");
|
|
38
|
-
const { viewname, tool_choice } = require("./common");
|
|
39
|
-
const { requirements_tool } = require("./tools");
|
|
40
|
-
const { saltcorn_description, existing_tables_list } = require("./prompts");
|
|
3
|
+
const { div, pre, p, small, span } = require("@saltcorn/markup/tags");
|
|
4
|
+
const { viewname } = require("./common");
|
|
41
5
|
const GenerateTables = require("../actions/generate-tables");
|
|
42
6
|
const { buildMermaidMarkup } = GenerateTables;
|
|
43
|
-
const GenerateTablesSkill = require("../agent-skills/database-design");
|
|
44
7
|
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const reusedMd = await MetaData.findOne({
|
|
55
|
-
type: "CopilotConstructMgr",
|
|
56
|
-
name: "reused_schema",
|
|
57
|
-
});
|
|
58
|
-
const reusedNames = reusedMd?.body?.table_names || [];
|
|
59
|
-
const reusedInstances = reusedNames
|
|
60
|
-
.map((n) => Table.findOne({ name: n }))
|
|
61
|
-
.filter(Boolean);
|
|
62
|
-
const allTables = [...newTableInstances, ...reusedInstances];
|
|
63
|
-
const mmdia = buildMermaidMarkup(allTables);
|
|
64
|
-
const implemented = !!schema.body.implemented;
|
|
65
|
-
|
|
66
|
-
const newNames = newTableDefs.map((t) => t.table_name).filter(Boolean);
|
|
67
|
-
|
|
68
|
-
const colorMap = Object.fromEntries([
|
|
69
|
-
...newNames.map((n) => [n, "#198754"]),
|
|
70
|
-
...reusedNames.map((n) => [n, "#6c757d"]),
|
|
71
|
-
]);
|
|
72
|
-
const colorScript = script(
|
|
73
|
-
domReady(`
|
|
74
|
-
const colors = ${JSON.stringify(colorMap)};
|
|
75
|
-
const pre = document.querySelector('.schema-mermaid');
|
|
76
|
-
if (!pre) return;
|
|
77
|
-
|
|
78
|
-
const doRender = () => {
|
|
79
|
-
mermaid.run({ nodes: [pre], suppressErrors: true, postRenderCallback: () => {
|
|
80
|
-
for (const g of pre.querySelectorAll('g[id^="entity-"]')) {
|
|
81
|
-
const name = g.id.replace(/^entity-/, '').replace(/-\\d+$/, '');
|
|
82
|
-
const color = colors[name];
|
|
83
|
-
if (color) {
|
|
84
|
-
const p = g.querySelector('path');
|
|
85
|
-
if (p) p.setAttribute('fill', color);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
for (const el of pre.querySelectorAll('g.label.name .nodeLabel')) {
|
|
89
|
-
el.style.color = 'white';
|
|
90
|
-
el.style.fontWeight = 'bold';
|
|
91
|
-
}
|
|
92
|
-
}});
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
// Defer render until tab is visible, then colorize nodes.
|
|
96
|
-
const pane = pre.closest('.tab-pane');
|
|
97
|
-
if (pane && !pane.classList.contains('active')) {
|
|
98
|
-
const link = document.querySelector('[href="#' + pane.id + '"]');
|
|
99
|
-
if (link) link.addEventListener('shown.bs.tab', doRender, { once: true });
|
|
100
|
-
else {
|
|
101
|
-
const o = new MutationObserver(() => {
|
|
102
|
-
if (pane.classList.contains('active')) { o.disconnect(); doRender(); }
|
|
103
|
-
});
|
|
104
|
-
o.observe(pane, { attributes: true, attributeFilter: ['class'] });
|
|
105
|
-
}
|
|
106
|
-
} else doRender();
|
|
107
|
-
`)
|
|
108
|
-
);
|
|
109
|
-
|
|
110
|
-
const legend = div(
|
|
111
|
-
{ class: "mt-3 d-flex flex-wrap gap-3 align-items-start" },
|
|
112
|
-
newNames.length
|
|
113
|
-
? div(
|
|
114
|
-
{ class: "d-flex flex-wrap align-items-center gap-1" },
|
|
115
|
-
span(
|
|
116
|
-
{ class: "me-1 text-muted small" },
|
|
117
|
-
implemented ? "Was created:" : "Will be created:"
|
|
118
|
-
),
|
|
119
|
-
...newNames.map((n) => span({ class: "badge bg-success" }, n))
|
|
120
|
-
)
|
|
121
|
-
: "",
|
|
122
|
-
reusedNames.length
|
|
123
|
-
? div(
|
|
124
|
-
{ class: "d-flex flex-wrap align-items-center gap-1" },
|
|
125
|
-
span(
|
|
126
|
-
{ class: "me-1 text-muted small" },
|
|
127
|
-
implemented ? "Already existed:" : "Already exists:"
|
|
128
|
-
),
|
|
129
|
-
...reusedNames.map((n) => span({ class: "badge bg-secondary" }, n))
|
|
130
|
-
)
|
|
131
|
-
: ""
|
|
132
|
-
);
|
|
8
|
+
const PHASE_COLORS = [
|
|
9
|
+
{ fill: "#93c5fd", stroke: "#1e40af" },
|
|
10
|
+
{ fill: "#86efac", stroke: "#166534" },
|
|
11
|
+
{ fill: "#fcd34d", stroke: "#92400e" },
|
|
12
|
+
{ fill: "#d8b4fe", stroke: "#6b21a8" },
|
|
13
|
+
{ fill: "#f9a8d4", stroke: "#9d174d" },
|
|
14
|
+
{ fill: "#fdba74", stroke: "#9a3412" },
|
|
15
|
+
];
|
|
16
|
+
const NO_PHASE_COLOR = { fill: "#cbd5e1", stroke: "#334155" };
|
|
133
17
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
legend,
|
|
139
|
-
!implemented &&
|
|
140
|
-
div(
|
|
141
|
-
{ class: "mb-4 d-block mt-3" },
|
|
142
|
-
button(
|
|
143
|
-
{
|
|
144
|
-
class: "btn btn-primary me-2",
|
|
145
|
-
onclick: `view_post("${viewname}", "implement_schema")`,
|
|
146
|
-
},
|
|
147
|
-
"Implement schema"
|
|
148
|
-
),
|
|
149
|
-
button(
|
|
150
|
-
{
|
|
151
|
-
class: "btn btn-outline-danger",
|
|
152
|
-
onclick: `view_post("${viewname}", "del_schema")`,
|
|
153
|
-
},
|
|
154
|
-
"Delete schema"
|
|
155
|
-
)
|
|
156
|
-
)
|
|
157
|
-
);
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
const generating = await MetaData.findOne({
|
|
161
|
-
type: "CopilotConstructMgr",
|
|
162
|
-
name: "generating_schema",
|
|
163
|
-
});
|
|
164
|
-
if (generating) {
|
|
18
|
+
const showSchema = async (req) => {
|
|
19
|
+
const allTables = await Table.find({});
|
|
20
|
+
const userTables = allTables.filter((t) => !t.name.startsWith("_sc_"));
|
|
21
|
+
if (!userTables.length) {
|
|
165
22
|
return div(
|
|
166
23
|
{ class: "mt-2" },
|
|
167
24
|
p(
|
|
168
|
-
|
|
169
|
-
"
|
|
170
|
-
),
|
|
171
|
-
script(
|
|
172
|
-
domReady(`
|
|
173
|
-
const poll = () => {
|
|
174
|
-
view_post(${JSON.stringify(viewname)}, 'schema_status', {}, (resp) => {
|
|
175
|
-
if (resp && !resp.generating) location.reload();
|
|
176
|
-
else setTimeout(poll, 3000);
|
|
177
|
-
});
|
|
178
|
-
};
|
|
179
|
-
setTimeout(poll, 3000);
|
|
180
|
-
`)
|
|
25
|
+
{ class: "text-muted" },
|
|
26
|
+
"No tables in the database yet. Data model tasks in each phase will create them."
|
|
181
27
|
)
|
|
182
28
|
);
|
|
183
29
|
}
|
|
184
30
|
|
|
185
|
-
|
|
186
|
-
{ class: "mt-2", id: "schema-gen-area" },
|
|
187
|
-
p("Schema not found"),
|
|
188
|
-
button(
|
|
189
|
-
{ class: "btn btn-primary", onclick: `copilotGenSchema()` },
|
|
190
|
-
"Generate schema"
|
|
191
|
-
),
|
|
192
|
-
script(
|
|
193
|
-
domReady(`
|
|
194
|
-
window.copilotGenSchema = () => {
|
|
195
|
-
document.getElementById('schema-gen-area').innerHTML =
|
|
196
|
-
'<p><i class="fas fa-spinner fa-spin me-2"></i>Generating schema, please wait...</p>';
|
|
197
|
-
view_post(${JSON.stringify(viewname)}, 'gen_schema', {}, () => {});
|
|
198
|
-
const poll = () => {
|
|
199
|
-
view_post(${JSON.stringify(viewname)}, 'schema_status', {}, (resp) => {
|
|
200
|
-
if (resp && !resp.generating) location.reload();
|
|
201
|
-
else setTimeout(poll, 3000);
|
|
202
|
-
});
|
|
203
|
-
};
|
|
204
|
-
setTimeout(poll, 3000);
|
|
205
|
-
};
|
|
206
|
-
`)
|
|
207
|
-
)
|
|
208
|
-
);
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const doGenSchema = async (spec, rs, userId) => {
|
|
212
|
-
const generatingMd = await MetaData.create({
|
|
31
|
+
const phaseRecords = await MetaData.find({
|
|
213
32
|
type: "CopilotConstructMgr",
|
|
214
|
-
name: "
|
|
215
|
-
body: {},
|
|
216
|
-
user_id: userId,
|
|
33
|
+
name: "table_phase",
|
|
217
34
|
});
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
- If an existing table is already complete and used as-is: add its name to reused_table_names. Do NOT define its fields again in the tables array.
|
|
242
|
-
- New tables not yet in the database: include them in the tables array with all their fields as usual.
|
|
35
|
+
const tablePhaseMap = {};
|
|
36
|
+
for (const r of phaseRecords) tablePhaseMap[r.body.table_name] = r.body;
|
|
37
|
+
|
|
38
|
+
// Collect phases seen, sorted by index
|
|
39
|
+
const phasesSeen = new Map();
|
|
40
|
+
for (const r of phaseRecords)
|
|
41
|
+
if (!phasesSeen.has(r.body.phase_idx))
|
|
42
|
+
phasesSeen.set(r.body.phase_idx, r.body.phase_name);
|
|
43
|
+
const orderedPhases = [...phasesSeen.entries()].sort(([a], [b]) => a - b);
|
|
44
|
+
|
|
45
|
+
// Group table names by phase for the legend
|
|
46
|
+
const phaseTableNames = new Map();
|
|
47
|
+
const unassignedNames = [];
|
|
48
|
+
for (const t of userTables) {
|
|
49
|
+
const entry = tablePhaseMap[t.name];
|
|
50
|
+
if (entry) {
|
|
51
|
+
if (!phaseTableNames.has(entry.phase_idx))
|
|
52
|
+
phaseTableNames.set(entry.phase_idx, []);
|
|
53
|
+
phaseTableNames.get(entry.phase_idx).push(t.name);
|
|
54
|
+
} else {
|
|
55
|
+
unassignedNames.push(t.name);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
243
58
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
59
|
+
// Pre-compute fill color per table name for the client script
|
|
60
|
+
const colorMap = {};
|
|
61
|
+
for (const t of userTables) {
|
|
62
|
+
const entry = tablePhaseMap[t.name];
|
|
63
|
+
colorMap[t.name] = entry
|
|
64
|
+
? PHASE_COLORS[entry.phase_idx % PHASE_COLORS.length]
|
|
65
|
+
: NO_PHASE_COLOR;
|
|
66
|
+
}
|
|
247
67
|
|
|
248
|
-
|
|
68
|
+
const mmdia = buildMermaidMarkup(userTables);
|
|
249
69
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
} tool to generate the complete database schema for this software application
|
|
253
|
-
`,
|
|
70
|
+
const tableBadge = (color, name) =>
|
|
71
|
+
span(
|
|
254
72
|
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
}
|
|
73
|
+
class: "badge rounded-pill",
|
|
74
|
+
style: `background:${color.fill};color:${color.stroke};border:1.5px solid ${color.stroke}`,
|
|
75
|
+
},
|
|
76
|
+
name
|
|
260
77
|
);
|
|
261
78
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
type: "CopilotConstructMgr",
|
|
289
|
-
name: "spec",
|
|
290
|
-
});
|
|
291
|
-
if (!spec) throw new Error("Specification not found");
|
|
292
|
-
const rs = await MetaData.find({
|
|
293
|
-
type: "CopilotConstructMgr",
|
|
294
|
-
name: "requirement",
|
|
295
|
-
});
|
|
296
|
-
if (!rs.length) throw new Error("No requirements found");
|
|
79
|
+
const legendGroups = [
|
|
80
|
+
...(unassignedNames.length
|
|
81
|
+
? [
|
|
82
|
+
div(
|
|
83
|
+
{ class: "d-flex flex-wrap align-items-center gap-1" },
|
|
84
|
+
span({ class: "me-1 text-muted small" }, "Pre-existing:"),
|
|
85
|
+
...unassignedNames.map((n) => tableBadge(NO_PHASE_COLOR, n))
|
|
86
|
+
),
|
|
87
|
+
]
|
|
88
|
+
: []),
|
|
89
|
+
...orderedPhases
|
|
90
|
+
.map(([idx, name]) => {
|
|
91
|
+
const color = PHASE_COLORS[idx % PHASE_COLORS.length];
|
|
92
|
+
const names = phaseTableNames.get(idx) || [];
|
|
93
|
+
if (!names.length) return null;
|
|
94
|
+
return div(
|
|
95
|
+
{ class: "d-flex flex-wrap align-items-center gap-1" },
|
|
96
|
+
span(
|
|
97
|
+
{ class: "me-1 text-muted small" },
|
|
98
|
+
`Phase ${idx + 1}${name ? `: ${name}` : ""}:`
|
|
99
|
+
),
|
|
100
|
+
...names.map((n) => tableBadge(color, n))
|
|
101
|
+
);
|
|
102
|
+
})
|
|
103
|
+
.filter(Boolean),
|
|
104
|
+
];
|
|
297
105
|
|
|
298
|
-
|
|
299
|
-
|
|
106
|
+
return div(
|
|
107
|
+
{ class: "mt-2" },
|
|
108
|
+
small(
|
|
109
|
+
{ class: "text-muted d-block mb-2" },
|
|
110
|
+
`${userTables.length} table${
|
|
111
|
+
userTables.length !== 1 ? "s" : ""
|
|
112
|
+
} — reflects current database state`
|
|
113
|
+
),
|
|
114
|
+
pre(
|
|
115
|
+
{
|
|
116
|
+
class: "schema-mermaid",
|
|
117
|
+
"data-color-map": JSON.stringify(colorMap),
|
|
118
|
+
},
|
|
119
|
+
mmdia
|
|
120
|
+
),
|
|
121
|
+
legendGroups.length
|
|
122
|
+
? div({ class: "d-flex flex-column gap-2 mt-2" }, ...legendGroups)
|
|
123
|
+
: ""
|
|
300
124
|
);
|
|
301
|
-
return { json: { success: true } };
|
|
302
125
|
};
|
|
303
126
|
|
|
304
|
-
const
|
|
127
|
+
const schema_list_html = async (
|
|
305
128
|
table_id,
|
|
306
129
|
viewname,
|
|
307
130
|
config,
|
|
308
131
|
body,
|
|
309
132
|
{ req, res }
|
|
310
133
|
) => {
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
name: "generating_schema",
|
|
314
|
-
});
|
|
315
|
-
return { json: { generating: !!generating } };
|
|
134
|
+
const html = await showSchema(req);
|
|
135
|
+
return { json: { html } };
|
|
316
136
|
};
|
|
317
137
|
|
|
318
|
-
const
|
|
319
|
-
|
|
320
|
-
const rs = await MetaData.find({ type: "CopilotConstructMgr", name });
|
|
321
|
-
for (const r of rs) await r.delete();
|
|
322
|
-
}
|
|
323
|
-
return { json: { reload_page: true } };
|
|
138
|
+
const schema_routes = {
|
|
139
|
+
schema_list_html,
|
|
324
140
|
};
|
|
325
141
|
|
|
326
|
-
const
|
|
327
|
-
|
|
328
|
-
viewname
|
|
329
|
-
config,
|
|
330
|
-
body,
|
|
331
|
-
{ req, res }
|
|
332
|
-
) => {
|
|
333
|
-
const md = await MetaData.findOne({
|
|
334
|
-
type: "CopilotConstructMgr",
|
|
335
|
-
name: "schema",
|
|
336
|
-
});
|
|
142
|
+
const schemaStaticScript = `<script>
|
|
143
|
+
(function(){
|
|
144
|
+
const _schemVn = ${JSON.stringify(viewname)};
|
|
337
145
|
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
);
|
|
346
|
-
|
|
146
|
+
// Ensure mermaid won't auto-process on its own — we drive rendering manually
|
|
147
|
+
if (typeof mermaid !== 'undefined') {
|
|
148
|
+
try { mermaid.initialize({ startOnLoad: false, securityLevel: 'loose' }); } catch (_) {}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
function applyColors(el, colorMap) {
|
|
152
|
+
for (const g of el.querySelectorAll('g[id^="entity-"]')) {
|
|
153
|
+
const name = g.id.replace(/^entity-/, '').replace(/-\\d+$/, '');
|
|
154
|
+
const colors = colorMap[name];
|
|
155
|
+
if (!colors) continue;
|
|
156
|
+
const path = g.querySelector('path');
|
|
157
|
+
if (path) {
|
|
158
|
+
path.style.fill = colors.fill;
|
|
159
|
+
path.style.stroke = colors.stroke;
|
|
160
|
+
}
|
|
347
161
|
}
|
|
348
|
-
|
|
349
|
-
});
|
|
350
|
-
await apply_copilot_tables({ tables: newTables, user: req.user });
|
|
351
|
-
md.body.implemented = true;
|
|
352
|
-
await md.update({ body: md.body });
|
|
162
|
+
}
|
|
353
163
|
|
|
354
|
-
|
|
355
|
-
|
|
164
|
+
window.copilotRenderSchemaMermaid = () => {
|
|
165
|
+
const pre = document.querySelector('#schema-list-area .schema-mermaid');
|
|
166
|
+
if (!pre || typeof mermaid === 'undefined') return;
|
|
167
|
+
const colorMap = pre.dataset.colorMap ? JSON.parse(pre.dataset.colorMap) : {};
|
|
168
|
+
const mermaidText = pre.textContent.trim();
|
|
169
|
+
if (!mermaidText) return;
|
|
170
|
+
|
|
171
|
+
const tmp = document.createElement('div');
|
|
172
|
+
tmp.style.cssText = 'position:absolute;left:-9999px;top:0;visibility:hidden';
|
|
173
|
+
tmp.textContent = mermaidText;
|
|
174
|
+
document.body.appendChild(tmp);
|
|
175
|
+
|
|
176
|
+
mermaid.run({ nodes: [tmp], suppressErrors: true })
|
|
177
|
+
.then(() => {
|
|
178
|
+
const target = document.querySelector('#schema-list-area .schema-mermaid');
|
|
179
|
+
if (target) { target.innerHTML = tmp.innerHTML; applyColors(target, colorMap); }
|
|
180
|
+
tmp.remove();
|
|
181
|
+
})
|
|
182
|
+
.catch(e => {
|
|
183
|
+
console.warn('mermaid schema render error', e);
|
|
184
|
+
tmp.remove();
|
|
185
|
+
});
|
|
186
|
+
};
|
|
356
187
|
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
188
|
+
window.copilotRefreshSchema = function() {
|
|
189
|
+
view_post(_schemVn, 'schema_list_html', {}, (r) => {
|
|
190
|
+
const el = document.getElementById('schema-list-area');
|
|
191
|
+
if (r && r.html && el) {
|
|
192
|
+
el.innerHTML = r.html;
|
|
193
|
+
copilotRenderSchemaMermaid();
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
};
|
|
197
|
+
|
|
198
|
+
if (document.readyState !== 'loading') copilotRenderSchemaMermaid();
|
|
199
|
+
else document.addEventListener('DOMContentLoaded', copilotRenderSchemaMermaid);
|
|
200
|
+
})()
|
|
201
|
+
</script>`;
|
|
363
202
|
|
|
364
|
-
module.exports = { showSchema, schema_routes };
|
|
203
|
+
module.exports = { showSchema, schema_routes, schemaStaticScript };
|