@agentic-kit/pi 0.17.1 → 0.18.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/README.md +5 -7
- package/confirm-gate.d.ts +1 -2
- package/esm/confirm-gate.d.ts +1 -2
- package/esm/host.d.ts +5 -110
- package/esm/host.js +5 -18
- package/esm/index.d.ts +17 -9
- package/esm/index.js +20 -38
- package/esm/pi-tool.d.ts +16 -0
- package/esm/pi-tool.js +32 -0
- package/host.d.ts +5 -110
- package/host.js +10 -22
- package/index.d.ts +17 -9
- package/index.js +47 -62
- package/package.json +6 -10
- package/pi-tool.d.ts +16 -0
- package/pi-tool.js +36 -0
- package/app-workspace.d.ts +0 -16
- package/app-workspace.js +0 -145
- package/context.d.ts +0 -62
- package/context.js +0 -282
- package/db-probe.d.ts +0 -30
- package/db-probe.js +0 -50
- package/esm/app-workspace.d.ts +0 -16
- package/esm/app-workspace.js +0 -134
- package/esm/context.d.ts +0 -62
- package/esm/context.js +0 -270
- package/esm/db-probe.d.ts +0 -30
- package/esm/db-probe.js +0 -47
- package/esm/policy/add-policies-to-table.d.ts +0 -26
- package/esm/policy/add-policies-to-table.js +0 -66
- package/esm/policy/provision-helpers.d.ts +0 -38
- package/esm/policy/provision-helpers.js +0 -50
- package/esm/provision-database/credential.d.ts +0 -14
- package/esm/provision-database/credential.js +0 -19
- package/esm/provision-database/env-file.d.ts +0 -37
- package/esm/provision-database/env-file.js +0 -85
- package/esm/provision-database/manifest.d.ts +0 -10
- package/esm/provision-database/manifest.js +0 -48
- package/esm/provision-database/pg-fixups.d.ts +0 -16
- package/esm/provision-database/pg-fixups.js +0 -132
- package/esm/provision-database/preset-match.d.ts +0 -13
- package/esm/provision-database/preset-match.js +0 -66
- package/esm/provision-database/presets.d.ts +0 -4
- package/esm/provision-database/presets.js +0 -13
- package/esm/provision-database/request-database.d.ts +0 -61
- package/esm/provision-database/request-database.js +0 -130
- package/esm/provision-database/resolve.d.ts +0 -27
- package/esm/provision-database/resolve.js +0 -49
- package/esm/records/meta.d.ts +0 -41
- package/esm/records/meta.js +0 -167
- package/esm/run-codegen/barrels.d.ts +0 -3
- package/esm/run-codegen/barrels.js +0 -48
- package/esm/run-codegen/endpoints.d.ts +0 -8
- package/esm/run-codegen/endpoints.js +0 -46
- package/esm/schema-resolve.d.ts +0 -23
- package/esm/schema-resolve.js +0 -69
- package/esm/tool-schema.d.ts +0 -3
- package/esm/tool-schema.js +0 -10
- package/esm/tools/add-policies.d.ts +0 -8
- package/esm/tools/add-policies.js +0 -96
- package/esm/tools/add-records.d.ts +0 -14
- package/esm/tools/add-records.js +0 -124
- package/esm/tools/add-relation-schema.d.ts +0 -30
- package/esm/tools/add-relation-schema.js +0 -58
- package/esm/tools/add-relation.d.ts +0 -10
- package/esm/tools/add-relation.js +0 -91
- package/esm/tools/create-api-key.d.ts +0 -18
- package/esm/tools/create-api-key.js +0 -216
- package/esm/tools/describe-schema.d.ts +0 -18
- package/esm/tools/describe-schema.js +0 -132
- package/esm/tools/manage-entity-types.d.ts +0 -41
- package/esm/tools/manage-entity-types.js +0 -203
- package/esm/tools/mutations.d.ts +0 -14
- package/esm/tools/mutations.js +0 -235
- package/esm/tools/provision-blueprint.d.ts +0 -22
- package/esm/tools/provision-blueprint.js +0 -111
- package/esm/tools/provision-database.d.ts +0 -14
- package/esm/tools/provision-database.js +0 -262
- package/esm/tools/run-codegen.d.ts +0 -11
- package/esm/tools/run-codegen.js +0 -139
- package/esm/tools/templates.d.ts +0 -49
- package/esm/tools/templates.js +0 -337
- package/policy/add-policies-to-table.d.ts +0 -26
- package/policy/add-policies-to-table.js +0 -71
- package/policy/provision-helpers.d.ts +0 -38
- package/policy/provision-helpers.js +0 -58
- package/provision-database/credential.d.ts +0 -14
- package/provision-database/credential.js +0 -22
- package/provision-database/env-file.d.ts +0 -37
- package/provision-database/env-file.js +0 -91
- package/provision-database/manifest.d.ts +0 -10
- package/provision-database/manifest.js +0 -56
- package/provision-database/pg-fixups.d.ts +0 -16
- package/provision-database/pg-fixups.js +0 -170
- package/provision-database/preset-match.d.ts +0 -13
- package/provision-database/preset-match.js +0 -70
- package/provision-database/presets.d.ts +0 -4
- package/provision-database/presets.js +0 -17
- package/provision-database/request-database.d.ts +0 -61
- package/provision-database/request-database.js +0 -134
- package/provision-database/resolve.d.ts +0 -27
- package/provision-database/resolve.js +0 -53
- package/records/meta.d.ts +0 -41
- package/records/meta.js +0 -172
- package/run-codegen/barrels.d.ts +0 -3
- package/run-codegen/barrels.js +0 -54
- package/run-codegen/endpoints.d.ts +0 -8
- package/run-codegen/endpoints.js +0 -51
- package/schema-resolve.d.ts +0 -23
- package/schema-resolve.js +0 -75
- package/tool-schema.d.ts +0 -3
- package/tool-schema.js +0 -13
- package/tools/add-policies.d.ts +0 -8
- package/tools/add-policies.js +0 -99
- package/tools/add-records.d.ts +0 -14
- package/tools/add-records.js +0 -127
- package/tools/add-relation-schema.d.ts +0 -30
- package/tools/add-relation-schema.js +0 -62
- package/tools/add-relation.d.ts +0 -10
- package/tools/add-relation.js +0 -94
- package/tools/create-api-key.d.ts +0 -18
- package/tools/create-api-key.js +0 -222
- package/tools/describe-schema.d.ts +0 -18
- package/tools/describe-schema.js +0 -135
- package/tools/manage-entity-types.d.ts +0 -41
- package/tools/manage-entity-types.js +0 -208
- package/tools/mutations.d.ts +0 -14
- package/tools/mutations.js +0 -238
- package/tools/provision-blueprint.d.ts +0 -22
- package/tools/provision-blueprint.js +0 -114
- package/tools/provision-database.d.ts +0 -14
- package/tools/provision-database.js +0 -268
- package/tools/run-codegen.d.ts +0 -11
- package/tools/run-codegen.js +0 -143
- package/tools/templates.d.ts +0 -49
- package/tools/templates.js +0 -341
package/esm/tools/templates.js
DELETED
|
@@ -1,337 +0,0 @@
|
|
|
1
|
-
import { filterInternalPolicies } from '@agentic-kit/harness';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { resolveProjectContext } from '../context';
|
|
4
|
-
import { toolSchema } from '../tool-schema';
|
|
5
|
-
// A stored blueprint field's `type` is an expanded object (`{ name: 'text' }`),
|
|
6
|
-
// not the bare string the agent passes to provision_blueprint. Flatten it to the
|
|
7
|
-
// type name so the renderer gets a string, never an object (which React can't
|
|
8
|
-
// render as a child).
|
|
9
|
-
function fieldTypeName(raw) {
|
|
10
|
-
if (typeof raw === 'string')
|
|
11
|
-
return raw;
|
|
12
|
-
if (raw && typeof raw === 'object' && typeof raw.name === 'string') {
|
|
13
|
-
return raw.name;
|
|
14
|
-
}
|
|
15
|
-
return '';
|
|
16
|
-
}
|
|
17
|
-
// A template's definition is a stored blueprint (see BlueprintDefinitionSchema):
|
|
18
|
-
// { tables: [{ table_name, fields, policies }], relations: [{ source_table, … }] }.
|
|
19
|
-
// Parse it into the same table shape provision_blueprint surfaces so the renderer
|
|
20
|
-
// can reuse TableCard. Defensive throughout — it's untyped JSON from the catalog.
|
|
21
|
-
function parseTemplateTables(definition) {
|
|
22
|
-
if (!definition || typeof definition !== 'object')
|
|
23
|
-
return [];
|
|
24
|
-
const def = definition;
|
|
25
|
-
const tables = Array.isArray(def.tables) ? def.tables : [];
|
|
26
|
-
const relations = Array.isArray(def.relations) ? def.relations : [];
|
|
27
|
-
return tables.map((raw) => {
|
|
28
|
-
const table = raw;
|
|
29
|
-
const fields = Array.isArray(table.fields) ? table.fields : [];
|
|
30
|
-
const policies = Array.isArray(table.policies) ? table.policies : [];
|
|
31
|
-
return {
|
|
32
|
-
name: table.table_name ?? '',
|
|
33
|
-
fields: fields.map((rawField) => {
|
|
34
|
-
const field = rawField;
|
|
35
|
-
return {
|
|
36
|
-
name: field.name ?? '',
|
|
37
|
-
type: fieldTypeName(field.type),
|
|
38
|
-
isRequired: field.is_required ?? false,
|
|
39
|
-
defaultValue: typeof field.default === 'string' ? field.default : null,
|
|
40
|
-
};
|
|
41
|
-
}),
|
|
42
|
-
policies: filterInternalPolicies(policies.map((policy) => policy.$type ?? '').filter(Boolean)),
|
|
43
|
-
relationCount: relations.filter((relation) => relation.source_table === table.table_name).length,
|
|
44
|
-
};
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
function formatTemplatesText(templates) {
|
|
48
|
-
if (templates.length === 0)
|
|
49
|
-
return 'No blueprint templates available.';
|
|
50
|
-
const lines = [`Available blueprint templates (${templates.length}):`];
|
|
51
|
-
for (const template of templates) {
|
|
52
|
-
const cats = template.categories.length ? ` [${template.categories.join(', ')}]` : '';
|
|
53
|
-
lines.push(` ${template.displayName} — ${template.tables.length} tables${cats}`);
|
|
54
|
-
for (const table of template.tables) {
|
|
55
|
-
lines.push(` - ${table.name} (${table.fields.length} field${table.fields.length === 1 ? '' : 's'})`);
|
|
56
|
-
}
|
|
57
|
-
}
|
|
58
|
-
return lines.join('\n');
|
|
59
|
-
}
|
|
60
|
-
// The latest project blueprint (or a named one) — the definition source for
|
|
61
|
-
// create_template, and for the confirm preview of the tables it will template.
|
|
62
|
-
// A blueprintName is a best-effort hint: if it matches nothing (the agent often
|
|
63
|
-
// guesses casing/wording), fall back to the most recent blueprint so the confirm
|
|
64
|
-
// still previews real tables and execute templates the same one it previewed.
|
|
65
|
-
async function fetchLatestBlueprint(context, blueprintName) {
|
|
66
|
-
const found = await context.modules.blueprint
|
|
67
|
-
.findMany({
|
|
68
|
-
select: { displayName: true, definition: true },
|
|
69
|
-
where: {
|
|
70
|
-
databaseId: { equalTo: context.databaseId },
|
|
71
|
-
...(blueprintName ? { displayName: { equalTo: blueprintName } } : {}),
|
|
72
|
-
},
|
|
73
|
-
orderBy: ['CREATED_AT_DESC'],
|
|
74
|
-
first: 1,
|
|
75
|
-
})
|
|
76
|
-
.unwrap();
|
|
77
|
-
return found.blueprints?.nodes?.[0];
|
|
78
|
-
}
|
|
79
|
-
async function findProjectBlueprint(context, blueprintName) {
|
|
80
|
-
let node = await fetchLatestBlueprint(context, blueprintName);
|
|
81
|
-
if (!node && blueprintName)
|
|
82
|
-
node = await fetchLatestBlueprint(context, undefined);
|
|
83
|
-
return node?.definition ? { displayName: node.displayName ?? '', definition: node.definition } : null;
|
|
84
|
-
}
|
|
85
|
-
// The create_template confirm preview — the source blueprint's name and its
|
|
86
|
-
// tables, parsed into the shape the renderer's TableCard reuses. Best-effort: any
|
|
87
|
-
// failure yields no tables rather than blocking the confirm.
|
|
88
|
-
export async function createTemplatePreviewTables(context, blueprintName) {
|
|
89
|
-
try {
|
|
90
|
-
const blueprint = await findProjectBlueprint(context, blueprintName);
|
|
91
|
-
if (!blueprint)
|
|
92
|
-
return { blueprintName: '', tables: [] };
|
|
93
|
-
return {
|
|
94
|
-
blueprintName: blueprint.displayName,
|
|
95
|
-
tables: parseTemplateTables(blueprint.definition),
|
|
96
|
-
};
|
|
97
|
-
}
|
|
98
|
-
catch (err) {
|
|
99
|
-
console.warn('[db-tools] create_template preview lookup failed:', err);
|
|
100
|
-
return { blueprintName: '', tables: [] };
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
async function resolveTemplateId(client, displayName) {
|
|
104
|
-
const result = await client.blueprintTemplate
|
|
105
|
-
.findMany({
|
|
106
|
-
select: { id: true, displayName: true },
|
|
107
|
-
where: { displayName: { equalTo: displayName } },
|
|
108
|
-
first: 1,
|
|
109
|
-
})
|
|
110
|
-
.unwrap();
|
|
111
|
-
const template = result.blueprintTemplates?.nodes?.[0];
|
|
112
|
-
if (!template?.id)
|
|
113
|
-
throw new Error(`Template "${displayName}" not found`);
|
|
114
|
-
return template.id;
|
|
115
|
-
}
|
|
116
|
-
function done(success, message) {
|
|
117
|
-
return { content: [{ type: 'text', text: message }], details: { success, message } };
|
|
118
|
-
}
|
|
119
|
-
// ── list_templates ────────────────────────────────────────────────────────
|
|
120
|
-
const ListTemplatesZod = z.object({});
|
|
121
|
-
const ListTemplatesSchema = toolSchema(ListTemplatesZod);
|
|
122
|
-
export const listTemplatesTool = {
|
|
123
|
-
name: 'list_templates',
|
|
124
|
-
label: 'List templates',
|
|
125
|
-
description: 'List the blueprint templates available to provision into the project database (display name, description, categories, table count). Read-only — these are a global catalog, not the project schema.',
|
|
126
|
-
promptSnippet: 'list_templates: list the available blueprint templates to apply. Read-only — call before apply_template.',
|
|
127
|
-
parameters: ListTemplatesSchema,
|
|
128
|
-
async execute(_id, _params, _signal, _onUpdate, ctx) {
|
|
129
|
-
const resolved = await resolveProjectContext(ctx.cwd);
|
|
130
|
-
if (!resolved.context) {
|
|
131
|
-
return { content: [{ type: 'text', text: resolved.reason }], details: { templates: [] } };
|
|
132
|
-
}
|
|
133
|
-
const result = await resolved.context.modules.blueprintTemplate
|
|
134
|
-
.findMany({
|
|
135
|
-
select: {
|
|
136
|
-
displayName: true,
|
|
137
|
-
description: true,
|
|
138
|
-
categories: true,
|
|
139
|
-
definition: true,
|
|
140
|
-
},
|
|
141
|
-
orderBy: ['NAME_ASC'],
|
|
142
|
-
})
|
|
143
|
-
.execute();
|
|
144
|
-
if (!result.ok) {
|
|
145
|
-
const message = result.errors.map((e) => e.message).join('; ');
|
|
146
|
-
return {
|
|
147
|
-
content: [{ type: 'text', text: `Failed to read templates: ${message}` }],
|
|
148
|
-
details: { templates: [] },
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
const templates = (result.data.blueprintTemplates?.nodes ?? []).map((template) => ({
|
|
152
|
-
displayName: template.displayName ?? '',
|
|
153
|
-
description: template.description ?? null,
|
|
154
|
-
categories: Array.isArray(template.categories) ? template.categories : [],
|
|
155
|
-
tables: parseTemplateTables(template.definition),
|
|
156
|
-
}));
|
|
157
|
-
return {
|
|
158
|
-
content: [{ type: 'text', text: formatTemplatesText(templates) }],
|
|
159
|
-
details: { templates },
|
|
160
|
-
};
|
|
161
|
-
},
|
|
162
|
-
};
|
|
163
|
-
// ── create_template ───────────────────────────────────────────────────────
|
|
164
|
-
const CreateTemplateZod = z.object({
|
|
165
|
-
displayName: z.string().describe('Display name for the new blueprint template'),
|
|
166
|
-
blueprintName: z
|
|
167
|
-
.string()
|
|
168
|
-
.describe('Display name of an existing project blueprint to save as the template. Defaults to the most recently provisioned blueprint.')
|
|
169
|
-
.optional(),
|
|
170
|
-
description: z.string().describe('Description shown in the template catalog').optional(),
|
|
171
|
-
categories: z
|
|
172
|
-
.array(z.string())
|
|
173
|
-
.describe('Categories for catalog grouping and discovery')
|
|
174
|
-
.optional(),
|
|
175
|
-
});
|
|
176
|
-
const CreateTemplateSchema = toolSchema(CreateTemplateZod);
|
|
177
|
-
export const createTemplateTool = {
|
|
178
|
-
name: 'create_template',
|
|
179
|
-
label: 'Create template',
|
|
180
|
-
description: 'Save an existing project blueprint into the global template catalog as a reusable blueprint template. Defaults to the most recently provisioned blueprint; pass blueprintName to pick a specific one by display name. Gated.',
|
|
181
|
-
promptSnippet: 'create_template: save a project blueprint to the reusable template catalog. Gated.',
|
|
182
|
-
parameters: CreateTemplateSchema,
|
|
183
|
-
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
184
|
-
const resolved = await resolveProjectContext(ctx.cwd);
|
|
185
|
-
if (!resolved.context)
|
|
186
|
-
return done(false, resolved.reason);
|
|
187
|
-
const { modules, ownerId } = resolved.context;
|
|
188
|
-
if (!ownerId)
|
|
189
|
-
return done(false, 'Not authenticated (missing OWNER_ID in .env).');
|
|
190
|
-
try {
|
|
191
|
-
const blueprint = await findProjectBlueprint(resolved.context, params.blueprintName);
|
|
192
|
-
if (!blueprint) {
|
|
193
|
-
const which = params.blueprintName ? `"${params.blueprintName}"` : 'any blueprint';
|
|
194
|
-
return done(false, `No project blueprint found (${which}). Provision a blueprint first.`);
|
|
195
|
-
}
|
|
196
|
-
const base = params.displayName.toLowerCase().replace(/\s+/g, '_');
|
|
197
|
-
await modules.blueprintTemplate
|
|
198
|
-
.create({
|
|
199
|
-
data: {
|
|
200
|
-
ownerId,
|
|
201
|
-
name: `${base}_${Date.now()}`,
|
|
202
|
-
displayName: params.displayName,
|
|
203
|
-
description: params.description,
|
|
204
|
-
categories: params.categories,
|
|
205
|
-
definition: blueprint.definition,
|
|
206
|
-
},
|
|
207
|
-
select: { id: true, displayName: true },
|
|
208
|
-
})
|
|
209
|
-
.unwrap();
|
|
210
|
-
const message = `Created template "${params.displayName}"`;
|
|
211
|
-
return {
|
|
212
|
-
content: [{ type: 'text', text: message }],
|
|
213
|
-
details: {
|
|
214
|
-
success: true,
|
|
215
|
-
message,
|
|
216
|
-
displayName: params.displayName,
|
|
217
|
-
blueprintName: blueprint.displayName,
|
|
218
|
-
tables: parseTemplateTables(blueprint.definition),
|
|
219
|
-
},
|
|
220
|
-
};
|
|
221
|
-
}
|
|
222
|
-
catch (err) {
|
|
223
|
-
return done(false, err instanceof Error ? err.message : 'Failed to create template');
|
|
224
|
-
}
|
|
225
|
-
},
|
|
226
|
-
};
|
|
227
|
-
// ── apply_template ────────────────────────────────────────────────────────
|
|
228
|
-
const ApplyTemplateZod = z.object({
|
|
229
|
-
templateName: z.string().describe('The display name of the blueprint template to apply'),
|
|
230
|
-
nameOverride: z
|
|
231
|
-
.string()
|
|
232
|
-
.describe('Optional name override for the created blueprint (snake_case). Defaults to template name.')
|
|
233
|
-
.optional(),
|
|
234
|
-
});
|
|
235
|
-
const ApplyTemplateSchema = toolSchema(ApplyTemplateZod);
|
|
236
|
-
export const applyTemplateTool = {
|
|
237
|
-
name: 'apply_template',
|
|
238
|
-
label: 'Apply template',
|
|
239
|
-
description: 'Apply an existing blueprint template to the project database, creating its tables. Use the template display name (from list_templates).',
|
|
240
|
-
promptSnippet: 'apply_template: provision a saved blueprint template by display name. Gated.',
|
|
241
|
-
parameters: ApplyTemplateSchema,
|
|
242
|
-
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
243
|
-
const resolved = await resolveProjectContext(ctx.cwd);
|
|
244
|
-
if (!resolved.context)
|
|
245
|
-
return done(false, resolved.reason);
|
|
246
|
-
const { modules, databaseId, schemaId, ownerId } = resolved.context;
|
|
247
|
-
if (!ownerId)
|
|
248
|
-
return done(false, 'Not authenticated (missing OWNER_ID in .env).');
|
|
249
|
-
try {
|
|
250
|
-
const templateId = await resolveTemplateId(modules, params.templateName);
|
|
251
|
-
const base = params.nameOverride ?? params.templateName.toLowerCase().replace(/\s+/g, '_');
|
|
252
|
-
const nameOverride = `${base}_${Date.now()}`;
|
|
253
|
-
const copyResult = await modules.mutation
|
|
254
|
-
.copyTemplateToBlueprint({ input: { templateId, databaseId, ownerId, nameOverride } }, { select: { result: true } })
|
|
255
|
-
.unwrap();
|
|
256
|
-
const blueprintId = copyResult.copyTemplateToBlueprint?.result;
|
|
257
|
-
if (!blueprintId)
|
|
258
|
-
throw new Error('Failed to copy template');
|
|
259
|
-
const constructResult = await modules.mutation
|
|
260
|
-
.constructBlueprint({ input: { blueprintId, schemaId } }, { select: { result: true } })
|
|
261
|
-
.unwrap();
|
|
262
|
-
const refMap = constructResult.constructBlueprint?.result;
|
|
263
|
-
if (!refMap)
|
|
264
|
-
return done(false, `Construction failed for template "${params.templateName}"`);
|
|
265
|
-
const createdCount = Object.keys(refMap).length;
|
|
266
|
-
return done(true, `Applied template "${params.templateName}" — created ${createdCount} table${createdCount === 1 ? '' : 's'}`);
|
|
267
|
-
}
|
|
268
|
-
catch (err) {
|
|
269
|
-
return done(false, err instanceof Error ? err.message : 'Failed to apply template');
|
|
270
|
-
}
|
|
271
|
-
},
|
|
272
|
-
};
|
|
273
|
-
// ── update_template ───────────────────────────────────────────────────────
|
|
274
|
-
const UpdateTemplateZod = z.object({
|
|
275
|
-
templateName: z.string().describe('The display name of the blueprint template to update'),
|
|
276
|
-
patch: z.object({
|
|
277
|
-
displayName: z.string().describe('New display name').optional(),
|
|
278
|
-
description: z.string().describe('New description').optional(),
|
|
279
|
-
categories: z.array(z.string()).describe('New categories').optional(),
|
|
280
|
-
tags: z.array(z.string()).describe('New tags').optional(),
|
|
281
|
-
visibility: z.enum(['private', 'public']).describe('New visibility').optional(),
|
|
282
|
-
}),
|
|
283
|
-
});
|
|
284
|
-
const UpdateTemplateSchema = toolSchema(UpdateTemplateZod);
|
|
285
|
-
export const updateTemplateTool = {
|
|
286
|
-
name: 'update_template',
|
|
287
|
-
label: 'Update template',
|
|
288
|
-
description: 'Update a blueprint template’s metadata (display name, description, categories, tags, visibility).',
|
|
289
|
-
promptSnippet: 'update_template: edit a saved template’s metadata by display name. Gated.',
|
|
290
|
-
parameters: UpdateTemplateSchema,
|
|
291
|
-
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
292
|
-
const resolved = await resolveProjectContext(ctx.cwd);
|
|
293
|
-
if (!resolved.context)
|
|
294
|
-
return done(false, resolved.reason);
|
|
295
|
-
try {
|
|
296
|
-
const templateId = await resolveTemplateId(resolved.context.modules, params.templateName);
|
|
297
|
-
await resolved.context.modules.blueprintTemplate
|
|
298
|
-
.update({
|
|
299
|
-
where: { id: templateId },
|
|
300
|
-
data: params.patch,
|
|
301
|
-
select: { id: true, displayName: true },
|
|
302
|
-
})
|
|
303
|
-
.unwrap();
|
|
304
|
-
return done(true, `Updated template "${params.templateName}"`);
|
|
305
|
-
}
|
|
306
|
-
catch (err) {
|
|
307
|
-
return done(false, err instanceof Error ? err.message : 'Failed to update template');
|
|
308
|
-
}
|
|
309
|
-
},
|
|
310
|
-
};
|
|
311
|
-
// ── delete_template ───────────────────────────────────────────────────────
|
|
312
|
-
const DeleteTemplateZod = z.object({
|
|
313
|
-
templateName: z.string().describe('The display name of the blueprint template to delete'),
|
|
314
|
-
});
|
|
315
|
-
const DeleteTemplateSchema = toolSchema(DeleteTemplateZod);
|
|
316
|
-
export const deleteTemplateTool = {
|
|
317
|
-
name: 'delete_template',
|
|
318
|
-
label: 'Delete template',
|
|
319
|
-
description: 'Permanently delete a blueprint template by its display name.',
|
|
320
|
-
promptSnippet: 'delete_template: remove a saved template by display name. Destructive — gated.',
|
|
321
|
-
parameters: DeleteTemplateSchema,
|
|
322
|
-
async execute(_id, params, _signal, _onUpdate, ctx) {
|
|
323
|
-
const resolved = await resolveProjectContext(ctx.cwd);
|
|
324
|
-
if (!resolved.context)
|
|
325
|
-
return done(false, resolved.reason);
|
|
326
|
-
try {
|
|
327
|
-
const templateId = await resolveTemplateId(resolved.context.modules, params.templateName);
|
|
328
|
-
await resolved.context.modules.blueprintTemplate
|
|
329
|
-
.delete({ where: { id: templateId }, select: { id: true } })
|
|
330
|
-
.unwrap();
|
|
331
|
-
return done(true, `Deleted template "${params.templateName}"`);
|
|
332
|
-
}
|
|
333
|
-
catch (err) {
|
|
334
|
-
return done(false, err instanceof Error ? err.message : 'Failed to delete template');
|
|
335
|
-
}
|
|
336
|
-
},
|
|
337
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { type PolicyProvisioningCategory } from '@agentic-kit/harness';
|
|
2
|
-
import type { ModulesClient } from '../context';
|
|
3
|
-
import { type CrudOperation, type CrudPolicyConfigs } from './provision-helpers';
|
|
4
|
-
export interface AddPoliciesToTablePolicyEntry {
|
|
5
|
-
policyType: string;
|
|
6
|
-
dataNodeType?: string;
|
|
7
|
-
nodeData?: Record<string, unknown>;
|
|
8
|
-
sharedPolicyData: Record<string, unknown>;
|
|
9
|
-
operations: CrudPolicyConfigs;
|
|
10
|
-
enabledOperations?: CrudOperation[];
|
|
11
|
-
}
|
|
12
|
-
export interface AddPoliciesToTableInput {
|
|
13
|
-
client: ModulesClient;
|
|
14
|
-
databaseId: string;
|
|
15
|
-
schemaId: string;
|
|
16
|
-
tableId: string;
|
|
17
|
-
policies: AddPoliciesToTablePolicyEntry[];
|
|
18
|
-
}
|
|
19
|
-
export declare class UnsupportedPolicyCategoryError extends Error {
|
|
20
|
-
readonly policyType: string;
|
|
21
|
-
readonly category: PolicyProvisioningCategory;
|
|
22
|
-
constructor(policyType: string, category: PolicyProvisioningCategory);
|
|
23
|
-
}
|
|
24
|
-
export declare function addPoliciesToExistingTable(input: AddPoliciesToTableInput): Promise<{
|
|
25
|
-
success: true;
|
|
26
|
-
}>;
|
|
@@ -1,71 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.UnsupportedPolicyCategoryError = void 0;
|
|
4
|
-
exports.addPoliciesToExistingTable = addPoliciesToExistingTable;
|
|
5
|
-
const harness_1 = require("@agentic-kit/harness");
|
|
6
|
-
const provision_helpers_1 = require("./provision-helpers");
|
|
7
|
-
const SUPPORTED_CATEGORIES = new Set([
|
|
8
|
-
'has-module',
|
|
9
|
-
'no-fields',
|
|
10
|
-
'needs-table',
|
|
11
|
-
]);
|
|
12
|
-
class UnsupportedPolicyCategoryError extends Error {
|
|
13
|
-
policyType;
|
|
14
|
-
category;
|
|
15
|
-
constructor(policyType, category) {
|
|
16
|
-
super(`Policy type "${policyType}" has category "${category}" which requires column creation or composite handling — use the policies UI instead.`);
|
|
17
|
-
this.policyType = policyType;
|
|
18
|
-
this.category = category;
|
|
19
|
-
this.name = 'UnsupportedPolicyCategoryError';
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
exports.UnsupportedPolicyCategoryError = UnsupportedPolicyCategoryError;
|
|
23
|
-
async function addPoliciesToExistingTable(input) {
|
|
24
|
-
const { client } = input;
|
|
25
|
-
for (const entry of input.policies) {
|
|
26
|
-
const category = (0, harness_1.getPolicyCategory)(entry.policyType);
|
|
27
|
-
if (!SUPPORTED_CATEGORIES.has(category)) {
|
|
28
|
-
throw new UnsupportedPolicyCategoryError(entry.policyType, category);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
const policiesArray = [];
|
|
32
|
-
const nodesByType = new Map();
|
|
33
|
-
for (const entry of input.policies) {
|
|
34
|
-
const groups = (0, provision_helpers_1.groupOperationsByConfig)(entry.enabledOperations ?? provision_helpers_1.CRUD_OPERATIONS, entry.operations);
|
|
35
|
-
for (const group of groups) {
|
|
36
|
-
const ops = group.privileges.join('_');
|
|
37
|
-
const rand = Math.random().toString(36).slice(2, 8);
|
|
38
|
-
policiesArray.push((0, provision_helpers_1.buildPolicyEntry)(entry.policyType, {
|
|
39
|
-
privileges: group.privileges,
|
|
40
|
-
policy_role: group.roleName,
|
|
41
|
-
permissive: group.isPermissive,
|
|
42
|
-
data: entry.sharedPolicyData,
|
|
43
|
-
policy_name: `${ops}_${rand}`,
|
|
44
|
-
}));
|
|
45
|
-
}
|
|
46
|
-
if (entry.dataNodeType && !nodesByType.has(entry.dataNodeType)) {
|
|
47
|
-
const nodeData = entry.nodeData ?? {};
|
|
48
|
-
nodesByType.set(entry.dataNodeType, {
|
|
49
|
-
$type: entry.dataNodeType,
|
|
50
|
-
...(Object.keys(nodeData).length > 0 ? { data: nodeData } : {}),
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
const provisionInput = {
|
|
55
|
-
databaseId: input.databaseId,
|
|
56
|
-
schemaId: input.schemaId,
|
|
57
|
-
tableId: input.tableId,
|
|
58
|
-
grants: (0, provision_helpers_1.buildGrants)(),
|
|
59
|
-
policies: policiesArray,
|
|
60
|
-
};
|
|
61
|
-
if (nodesByType.size > 0) {
|
|
62
|
-
provisionInput.nodes = [...nodesByType.values()];
|
|
63
|
-
}
|
|
64
|
-
await client.secureTableProvision
|
|
65
|
-
.create({
|
|
66
|
-
data: provisionInput,
|
|
67
|
-
select: { id: true, tableId: true, tableName: true },
|
|
68
|
-
})
|
|
69
|
-
.unwrap();
|
|
70
|
-
return { success: true };
|
|
71
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
export type CrudOperation = 'create' | 'read' | 'update' | 'delete';
|
|
2
|
-
export interface OperationPolicyConfig {
|
|
3
|
-
roleName: string;
|
|
4
|
-
isPermissive: boolean;
|
|
5
|
-
policyData: Record<string, unknown>;
|
|
6
|
-
isCustomized: boolean;
|
|
7
|
-
}
|
|
8
|
-
export interface CrudPolicyConfigs {
|
|
9
|
-
create: OperationPolicyConfig;
|
|
10
|
-
read: OperationPolicyConfig;
|
|
11
|
-
update: OperationPolicyConfig;
|
|
12
|
-
delete: OperationPolicyConfig;
|
|
13
|
-
}
|
|
14
|
-
export declare const CRUD_OPERATIONS: CrudOperation[];
|
|
15
|
-
export type GrantPrivilege = [string, string | string[]];
|
|
16
|
-
export interface GrantEntry {
|
|
17
|
-
roles: string[];
|
|
18
|
-
privileges: GrantPrivilege[];
|
|
19
|
-
}
|
|
20
|
-
export interface PolicyEntry {
|
|
21
|
-
$type: string;
|
|
22
|
-
data?: Record<string, unknown>;
|
|
23
|
-
privileges?: string[];
|
|
24
|
-
policy_role?: string;
|
|
25
|
-
permissive?: boolean;
|
|
26
|
-
policy_name?: string;
|
|
27
|
-
}
|
|
28
|
-
export declare const ALL_CRUD_PRIVILEGES: GrantPrivilege[];
|
|
29
|
-
export declare function crudOpToPrivilege(op: CrudOperation): string;
|
|
30
|
-
export declare function crudOpsToPrivileges(ops: readonly CrudOperation[]): string[];
|
|
31
|
-
export declare function buildGrants(roles?: string[], privileges?: GrantPrivilege[]): GrantEntry[];
|
|
32
|
-
export declare function buildPolicyEntry(type: string, opts?: Partial<Omit<PolicyEntry, '$type'>>): PolicyEntry;
|
|
33
|
-
export interface OperationGroup {
|
|
34
|
-
roleName: string;
|
|
35
|
-
isPermissive: boolean;
|
|
36
|
-
privileges: string[];
|
|
37
|
-
}
|
|
38
|
-
export declare function groupOperationsByConfig(enabledOperations: readonly CrudOperation[], operations: CrudPolicyConfigs): OperationGroup[];
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ALL_CRUD_PRIVILEGES = exports.CRUD_OPERATIONS = void 0;
|
|
4
|
-
exports.crudOpToPrivilege = crudOpToPrivilege;
|
|
5
|
-
exports.crudOpsToPrivileges = crudOpsToPrivileges;
|
|
6
|
-
exports.buildGrants = buildGrants;
|
|
7
|
-
exports.buildPolicyEntry = buildPolicyEntry;
|
|
8
|
-
exports.groupOperationsByConfig = groupOperationsByConfig;
|
|
9
|
-
exports.CRUD_OPERATIONS = ['create', 'read', 'update', 'delete'];
|
|
10
|
-
exports.ALL_CRUD_PRIVILEGES = [
|
|
11
|
-
['select', '*'],
|
|
12
|
-
['insert', '*'],
|
|
13
|
-
['update', '*'],
|
|
14
|
-
['delete', '*'],
|
|
15
|
-
];
|
|
16
|
-
const CRUD_OP_TO_LOWER_PRIVILEGE = {
|
|
17
|
-
create: 'insert',
|
|
18
|
-
read: 'select',
|
|
19
|
-
update: 'update',
|
|
20
|
-
delete: 'delete',
|
|
21
|
-
};
|
|
22
|
-
function crudOpToPrivilege(op) {
|
|
23
|
-
return CRUD_OP_TO_LOWER_PRIVILEGE[op];
|
|
24
|
-
}
|
|
25
|
-
function crudOpsToPrivileges(ops) {
|
|
26
|
-
return ops.map(crudOpToPrivilege);
|
|
27
|
-
}
|
|
28
|
-
function buildGrants(roles = ['authenticated'], privileges = exports.ALL_CRUD_PRIVILEGES) {
|
|
29
|
-
return [{ roles, privileges }];
|
|
30
|
-
}
|
|
31
|
-
function buildPolicyEntry(type, opts = {}) {
|
|
32
|
-
const entry = { $type: type };
|
|
33
|
-
if (opts.data && Object.keys(opts.data).length > 0)
|
|
34
|
-
entry.data = opts.data;
|
|
35
|
-
if (opts.privileges && opts.privileges.length > 0)
|
|
36
|
-
entry.privileges = opts.privileges;
|
|
37
|
-
if (opts.policy_role)
|
|
38
|
-
entry.policy_role = opts.policy_role;
|
|
39
|
-
if (opts.permissive !== undefined)
|
|
40
|
-
entry.permissive = opts.permissive;
|
|
41
|
-
if (opts.policy_name)
|
|
42
|
-
entry.policy_name = opts.policy_name;
|
|
43
|
-
return entry;
|
|
44
|
-
}
|
|
45
|
-
function groupOperationsByConfig(enabledOperations, operations) {
|
|
46
|
-
const groupMap = new Map();
|
|
47
|
-
for (const op of enabledOperations) {
|
|
48
|
-
const config = operations[op];
|
|
49
|
-
const key = `${config.roleName}:${config.isPermissive}`;
|
|
50
|
-
let group = groupMap.get(key);
|
|
51
|
-
if (!group) {
|
|
52
|
-
group = { roleName: config.roleName, isPermissive: config.isPermissive, privileges: [] };
|
|
53
|
-
groupMap.set(key, group);
|
|
54
|
-
}
|
|
55
|
-
group.privileges.push(...crudOpsToPrivileges([op]));
|
|
56
|
-
}
|
|
57
|
-
return [...groupMap.values()];
|
|
58
|
-
}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
export type AccountCredential = {
|
|
2
|
-
userId: string;
|
|
3
|
-
accessToken: string;
|
|
4
|
-
apiKey?: string;
|
|
5
|
-
};
|
|
6
|
-
export type ProvisionCredential = {
|
|
7
|
-
mode: 'account';
|
|
8
|
-
ownerId: string;
|
|
9
|
-
bearer: string;
|
|
10
|
-
} | {
|
|
11
|
-
mode: 'error';
|
|
12
|
-
reason: string;
|
|
13
|
-
};
|
|
14
|
-
export declare function selectProvisionCredential(account: AccountCredential | null | undefined, signInHint?: string): ProvisionCredential;
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
// Pure: decide which credential authenticates a project's provisioning. Under the
|
|
3
|
-
// account gate a signed-in session is guaranteed, so every new project provisions
|
|
4
|
-
// UNDER the account (account-owned + enumerable): the database's owner_id is the
|
|
5
|
-
// account's own userId, and the account's API key (falling back to its session
|
|
6
|
-
// token) is the bearer that authenticates the provision mutation and lands in the
|
|
7
|
-
// project .env as ACCESS_TOKEN (refreshed on every provision run, including the
|
|
8
|
-
// skip path). A signed-in session with no usable bearer (keychain locked) is an
|
|
9
|
-
// explicit error, never a silent throwaway owner.
|
|
10
|
-
// Side-effect-free so the branch is unit-testable without runtime/network.
|
|
11
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.selectProvisionCredential = selectProvisionCredential;
|
|
13
|
-
function selectProvisionCredential(account, signInHint) {
|
|
14
|
-
const bearer = account?.apiKey ?? account?.accessToken;
|
|
15
|
-
if (account?.userId && bearer) {
|
|
16
|
-
return { mode: 'account', ownerId: account.userId, bearer };
|
|
17
|
-
}
|
|
18
|
-
return {
|
|
19
|
-
mode: 'error',
|
|
20
|
-
reason: `No usable account credential. ${signInHint ?? 'Sign in (or unlock your session) before provisioning a database.'}`,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
export type EnvVars = Record<string, string>;
|
|
2
|
-
/**
|
|
3
|
-
* Upsert `vars` into the existing `.env` `content`. Existing keys are replaced
|
|
4
|
-
* in place (preserving surrounding lines/comments); new keys are appended.
|
|
5
|
-
* Returns the new file body, trailing-newline-terminated.
|
|
6
|
-
*/
|
|
7
|
-
export declare function mergeEnv(content: string, vars: EnvVars): string;
|
|
8
|
-
/** The credential keys provision_database owns in a project's .env. */
|
|
9
|
-
export declare const PROVISION_ENV_KEYS: readonly ["DATABASE_ID", "DATABASE_NAME", "OWNER_ID", "ACCESS_TOKEN", "PGDATABASE", "API_ENDPOINT", "MODULES_ENDPOINT"];
|
|
10
|
-
/**
|
|
11
|
-
* Keys archived as comments on reprovision — the binding identity: which
|
|
12
|
-
* database, under whom, on which backend. ACCESS_TOKEN is the account login
|
|
13
|
-
* token, identical across bindings, so it is overwritten in place rather than
|
|
14
|
-
* archived.
|
|
15
|
-
*/
|
|
16
|
-
export declare const ARCHIVED_BINDING_KEYS: readonly ["DATABASE_ID", "DATABASE_NAME", "OWNER_ID", "PGDATABASE", "API_ENDPOINT", "MODULES_ENDPOINT"];
|
|
17
|
-
/**
|
|
18
|
-
* Build the provisioning credential block written to a project's .env. The
|
|
19
|
-
* endpoint pins record which backend owns this binding — outside-app consumers
|
|
20
|
-
* (verify-feature.sh, skill scripts, dev-server shells) resolve them instead of
|
|
21
|
-
* falling back to localhost defaults when the app targets a hosted backend.
|
|
22
|
-
*/
|
|
23
|
-
export declare function provisionEnvVars(args: {
|
|
24
|
-
databaseId: string;
|
|
25
|
-
databaseName: string;
|
|
26
|
-
ownerId: string;
|
|
27
|
-
accessToken: string;
|
|
28
|
-
apiEndpoint: string;
|
|
29
|
-
modulesEndpoint: string;
|
|
30
|
-
}): EnvVars;
|
|
31
|
-
/**
|
|
32
|
-
* Comment out the given keys in place (`# archived <date>: KEY=value`) so a
|
|
33
|
-
* reprovision keeps the previous binding readable in the file instead of
|
|
34
|
-
* silently overwriting it. Every other line — including existing comments and
|
|
35
|
-
* already-archived entries — passes through untouched.
|
|
36
|
-
*/
|
|
37
|
-
export declare function archiveBindingKeys(content: string, keys: readonly string[], archivedOn: string): string;
|