@agentic-kit/pi 0.17.0 → 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.
Files changed (136) hide show
  1. package/README.md +5 -7
  2. package/confirm-gate.d.ts +1 -2
  3. package/esm/confirm-gate.d.ts +1 -2
  4. package/esm/host.d.ts +5 -110
  5. package/esm/host.js +5 -18
  6. package/esm/index.d.ts +17 -9
  7. package/esm/index.js +20 -38
  8. package/esm/pi-tool.d.ts +16 -0
  9. package/esm/pi-tool.js +32 -0
  10. package/host.d.ts +5 -110
  11. package/host.js +10 -22
  12. package/index.d.ts +17 -9
  13. package/index.js +47 -62
  14. package/package.json +6 -10
  15. package/pi-tool.d.ts +16 -0
  16. package/pi-tool.js +36 -0
  17. package/app-workspace.d.ts +0 -16
  18. package/app-workspace.js +0 -145
  19. package/context.d.ts +0 -62
  20. package/context.js +0 -282
  21. package/db-probe.d.ts +0 -30
  22. package/db-probe.js +0 -50
  23. package/esm/app-workspace.d.ts +0 -16
  24. package/esm/app-workspace.js +0 -134
  25. package/esm/context.d.ts +0 -62
  26. package/esm/context.js +0 -270
  27. package/esm/db-probe.d.ts +0 -30
  28. package/esm/db-probe.js +0 -47
  29. package/esm/policy/add-policies-to-table.d.ts +0 -26
  30. package/esm/policy/add-policies-to-table.js +0 -66
  31. package/esm/policy/provision-helpers.d.ts +0 -38
  32. package/esm/policy/provision-helpers.js +0 -50
  33. package/esm/provision-database/credential.d.ts +0 -14
  34. package/esm/provision-database/credential.js +0 -19
  35. package/esm/provision-database/env-file.d.ts +0 -37
  36. package/esm/provision-database/env-file.js +0 -85
  37. package/esm/provision-database/manifest.d.ts +0 -10
  38. package/esm/provision-database/manifest.js +0 -48
  39. package/esm/provision-database/pg-fixups.d.ts +0 -16
  40. package/esm/provision-database/pg-fixups.js +0 -132
  41. package/esm/provision-database/preset-match.d.ts +0 -13
  42. package/esm/provision-database/preset-match.js +0 -66
  43. package/esm/provision-database/presets.d.ts +0 -4
  44. package/esm/provision-database/presets.js +0 -13
  45. package/esm/provision-database/request-database.d.ts +0 -61
  46. package/esm/provision-database/request-database.js +0 -130
  47. package/esm/provision-database/resolve.d.ts +0 -27
  48. package/esm/provision-database/resolve.js +0 -49
  49. package/esm/records/meta.d.ts +0 -41
  50. package/esm/records/meta.js +0 -167
  51. package/esm/run-codegen/barrels.d.ts +0 -3
  52. package/esm/run-codegen/barrels.js +0 -48
  53. package/esm/run-codegen/endpoints.d.ts +0 -8
  54. package/esm/run-codegen/endpoints.js +0 -46
  55. package/esm/schema-resolve.d.ts +0 -23
  56. package/esm/schema-resolve.js +0 -69
  57. package/esm/tool-schema.d.ts +0 -3
  58. package/esm/tool-schema.js +0 -10
  59. package/esm/tools/add-policies.d.ts +0 -8
  60. package/esm/tools/add-policies.js +0 -96
  61. package/esm/tools/add-records.d.ts +0 -14
  62. package/esm/tools/add-records.js +0 -124
  63. package/esm/tools/add-relation-schema.d.ts +0 -30
  64. package/esm/tools/add-relation-schema.js +0 -58
  65. package/esm/tools/add-relation.d.ts +0 -10
  66. package/esm/tools/add-relation.js +0 -91
  67. package/esm/tools/create-api-key.d.ts +0 -18
  68. package/esm/tools/create-api-key.js +0 -216
  69. package/esm/tools/describe-schema.d.ts +0 -18
  70. package/esm/tools/describe-schema.js +0 -132
  71. package/esm/tools/manage-entity-types.d.ts +0 -41
  72. package/esm/tools/manage-entity-types.js +0 -203
  73. package/esm/tools/mutations.d.ts +0 -14
  74. package/esm/tools/mutations.js +0 -235
  75. package/esm/tools/provision-blueprint.d.ts +0 -22
  76. package/esm/tools/provision-blueprint.js +0 -111
  77. package/esm/tools/provision-database.d.ts +0 -14
  78. package/esm/tools/provision-database.js +0 -262
  79. package/esm/tools/run-codegen.d.ts +0 -11
  80. package/esm/tools/run-codegen.js +0 -139
  81. package/esm/tools/templates.d.ts +0 -49
  82. package/esm/tools/templates.js +0 -337
  83. package/policy/add-policies-to-table.d.ts +0 -26
  84. package/policy/add-policies-to-table.js +0 -71
  85. package/policy/provision-helpers.d.ts +0 -38
  86. package/policy/provision-helpers.js +0 -58
  87. package/provision-database/credential.d.ts +0 -14
  88. package/provision-database/credential.js +0 -22
  89. package/provision-database/env-file.d.ts +0 -37
  90. package/provision-database/env-file.js +0 -91
  91. package/provision-database/manifest.d.ts +0 -10
  92. package/provision-database/manifest.js +0 -56
  93. package/provision-database/pg-fixups.d.ts +0 -16
  94. package/provision-database/pg-fixups.js +0 -170
  95. package/provision-database/preset-match.d.ts +0 -13
  96. package/provision-database/preset-match.js +0 -70
  97. package/provision-database/presets.d.ts +0 -4
  98. package/provision-database/presets.js +0 -17
  99. package/provision-database/request-database.d.ts +0 -61
  100. package/provision-database/request-database.js +0 -134
  101. package/provision-database/resolve.d.ts +0 -27
  102. package/provision-database/resolve.js +0 -53
  103. package/records/meta.d.ts +0 -41
  104. package/records/meta.js +0 -172
  105. package/run-codegen/barrels.d.ts +0 -3
  106. package/run-codegen/barrels.js +0 -54
  107. package/run-codegen/endpoints.d.ts +0 -8
  108. package/run-codegen/endpoints.js +0 -51
  109. package/schema-resolve.d.ts +0 -23
  110. package/schema-resolve.js +0 -75
  111. package/tool-schema.d.ts +0 -3
  112. package/tool-schema.js +0 -13
  113. package/tools/add-policies.d.ts +0 -8
  114. package/tools/add-policies.js +0 -99
  115. package/tools/add-records.d.ts +0 -14
  116. package/tools/add-records.js +0 -127
  117. package/tools/add-relation-schema.d.ts +0 -30
  118. package/tools/add-relation-schema.js +0 -62
  119. package/tools/add-relation.d.ts +0 -10
  120. package/tools/add-relation.js +0 -94
  121. package/tools/create-api-key.d.ts +0 -18
  122. package/tools/create-api-key.js +0 -222
  123. package/tools/describe-schema.d.ts +0 -18
  124. package/tools/describe-schema.js +0 -135
  125. package/tools/manage-entity-types.d.ts +0 -41
  126. package/tools/manage-entity-types.js +0 -208
  127. package/tools/mutations.d.ts +0 -14
  128. package/tools/mutations.js +0 -238
  129. package/tools/provision-blueprint.d.ts +0 -22
  130. package/tools/provision-blueprint.js +0 -114
  131. package/tools/provision-database.d.ts +0 -14
  132. package/tools/provision-database.js +0 -268
  133. package/tools/run-codegen.d.ts +0 -11
  134. package/tools/run-codegen.js +0 -143
  135. package/tools/templates.d.ts +0 -49
  136. package/tools/templates.js +0 -341
@@ -1,203 +0,0 @@
1
- import { z } from 'zod';
2
- import { resolveProjectContext } from '../context';
3
- import { toolSchema } from '../tool-schema';
4
- const ManageEntityTypesZod = z.object({
5
- action: z
6
- .enum(['list', 'create', 'delete'])
7
- .describe('list: show the entity types provisioned in this database. create: provision a new entity type (creates its entity table + membership wiring). delete: remove the provision registration. Registrations are immutable once provisioned — there is no update; to change one, delete it and create a new one.'),
8
- name: z.string().describe('Entity type name. Required for create.').optional(),
9
- entity_type_id: z
10
- .string()
11
- .describe('Entity type provision id. Required for delete — get it from action "list".')
12
- .optional(),
13
- description: z
14
- .string()
15
- .describe('Human-readable description of the entity type. Create only.')
16
- .optional(),
17
- prefix: z
18
- .string()
19
- .describe('Table-name prefix for the provisioned tables (e.g. "org" → org table, org_memberships). Create only; defaults to the snake_case of name.')
20
- .optional(),
21
- parent_entity: z
22
- .string()
23
- .describe('Parent entity table name, for hierarchical types (e.g. a "team" under an "org"). Create only; the backend defaults it to the root entity (org).')
24
- .optional(),
25
- is_visible: z
26
- .boolean()
27
- .describe('Whether the type shows up in end-user entity listings. Create only.')
28
- .optional(),
29
- has_invites: z
30
- .boolean()
31
- .describe('Provision an invites module ({prefix}_invites + claimed invites). Create only.')
32
- .optional(),
33
- has_profiles: z
34
- .boolean()
35
- .describe('Provision a profiles table for members of this type. Create only.')
36
- .optional(),
37
- has_limits: z
38
- .boolean()
39
- .describe('Provision usage-limits tracking for this type. Create only.')
40
- .optional(),
41
- has_levels: z
42
- .boolean()
43
- .describe('Provision levels/achievements support for this type. Create only.')
44
- .optional(),
45
- has_storage: z
46
- .boolean()
47
- .describe('Provision a storage module (files + buckets tables) for this type. Create only.')
48
- .optional(),
49
- });
50
- const ManageEntityTypesSchema = toolSchema(ManageEntityTypesZod);
51
- const SUMMARY_SELECT = {
52
- id: true,
53
- name: true,
54
- description: true,
55
- prefix: true,
56
- parentEntity: true,
57
- isVisible: true,
58
- outEntityTableName: true,
59
- outInstalledModules: true,
60
- };
61
- function toSummary(row) {
62
- return {
63
- id: row.id,
64
- name: row.name,
65
- description: row.description,
66
- prefix: row.prefix,
67
- parentEntity: row.parentEntity,
68
- isVisible: row.isVisible,
69
- entityTableName: row.outEntityTableName,
70
- installedModules: row.outInstalledModules,
71
- };
72
- }
73
- function formatSummary(s) {
74
- const parts = [
75
- `- ${s.name ?? '?'} (id: ${s.id})`,
76
- ` table: ${s.entityTableName ?? '?'}, prefix: ${s.prefix ?? '?'}`,
77
- ];
78
- if (s.parentEntity)
79
- parts.push(` parent: ${s.parentEntity}`);
80
- if (s.description)
81
- parts.push(` description: ${s.description}`);
82
- if (s.installedModules?.length)
83
- parts.push(` modules: ${s.installedModules.join(', ')}`);
84
- return parts.join('\n');
85
- }
86
- export function defaultPrefix(name) {
87
- return name
88
- .trim()
89
- .toLowerCase()
90
- .replace(/[^a-z0-9]+/g, '_')
91
- .replace(/^_+|_+$/g, '');
92
- }
93
- export function validateManageEntityTypes(params) {
94
- switch (params.action) {
95
- case 'create':
96
- if (!params.name?.trim())
97
- return 'create requires "name".';
98
- if (params.entity_type_id)
99
- return 'create does not take "entity_type_id" — it mints a new one.';
100
- return null;
101
- case 'delete':
102
- if (!params.entity_type_id)
103
- return 'delete requires "entity_type_id" (use action "list" to find it).';
104
- return null;
105
- default:
106
- return null;
107
- }
108
- }
109
- export const manageEntityTypesTool = {
110
- name: 'manage_entity_types',
111
- label: 'Manage entity types',
112
- description: 'List, create, or delete entity types in the project database. An entity type (e.g. organization, team, project) provisions its own entity table plus membership wiring, and is the unit that API keys can be scoped to. Registrations are immutable once provisioned — to change one, delete it and create a new one. Deleting removes the registration; the already-provisioned entity table stays in the API schema.',
113
- promptSnippet: 'manage_entity_types: list/create/delete entity types (orgs, teams, …) in the project database. list is free; create/delete are gated.',
114
- parameters: ManageEntityTypesSchema,
115
- async execute(_id, params, _signal, _onUpdate, ctx) {
116
- const resolved = await resolveProjectContext(ctx.cwd);
117
- if (!resolved.context) {
118
- return {
119
- content: [{ type: 'text', text: resolved.reason }],
120
- details: { success: false, message: resolved.reason },
121
- };
122
- }
123
- const invalid = validateManageEntityTypes(params);
124
- if (invalid) {
125
- return {
126
- content: [{ type: 'text', text: invalid }],
127
- details: { success: false, message: invalid },
128
- };
129
- }
130
- const { modules, databaseId } = resolved.context;
131
- try {
132
- switch (params.action) {
133
- case 'list': {
134
- const result = await modules.entityTypeProvision
135
- .findMany({
136
- where: { databaseId: { equalTo: databaseId } },
137
- select: SUMMARY_SELECT,
138
- })
139
- .unwrap();
140
- const entityTypes = result.entityTypeProvisions.nodes.map((row) => toSummary(row));
141
- const message = entityTypes.length === 0
142
- ? 'No entity types are provisioned in this database yet.'
143
- : `${entityTypes.length} entity type${entityTypes.length === 1 ? '' : 's'}:\n${entityTypes.map(formatSummary).join('\n')}`;
144
- return {
145
- content: [{ type: 'text', text: message }],
146
- details: { success: true, message, entityTypes },
147
- };
148
- }
149
- case 'create': {
150
- const name = params.name.trim();
151
- const result = await modules.entityTypeProvision
152
- .create({
153
- data: {
154
- databaseId,
155
- name,
156
- prefix: params.prefix?.trim() || defaultPrefix(name),
157
- ...(params.description !== undefined && { description: params.description }),
158
- ...(params.parent_entity !== undefined && { parentEntity: params.parent_entity }),
159
- ...(params.is_visible !== undefined && { isVisible: params.is_visible }),
160
- ...(params.has_invites !== undefined && { hasInvites: params.has_invites }),
161
- ...(params.has_profiles !== undefined && { hasProfiles: params.has_profiles }),
162
- ...(params.has_limits !== undefined && { hasLimits: params.has_limits }),
163
- ...(params.has_levels !== undefined && { hasLevels: params.has_levels }),
164
- ...(params.has_storage && {
165
- storage: [{}],
166
- }),
167
- },
168
- select: SUMMARY_SELECT,
169
- })
170
- .unwrap();
171
- const row = result.createEntityTypeProvision?.entityTypeProvision;
172
- if (!row)
173
- throw new Error('createEntityTypeProvision returned no row.');
174
- const summary = toSummary(row);
175
- const message = `Created entity type "${summary.name}" (id: ${summary.id}) — entity table "${summary.entityTableName}"${summary.installedModules?.length ? `, modules: ${summary.installedModules.join(', ')}` : ''}. Run run_codegen to pull it into the typed SDK.`;
176
- return {
177
- content: [{ type: 'text', text: message }],
178
- details: { success: true, message, entityTypes: [summary] },
179
- };
180
- }
181
- case 'delete': {
182
- const result = await modules.entityTypeProvision
183
- .delete({
184
- where: { id: params.entity_type_id },
185
- select: { id: true, name: true, outEntityTableName: true },
186
- })
187
- .unwrap();
188
- const row = result.deleteEntityTypeProvision?.entityTypeProvision;
189
- const name = row?.name ?? params.entity_type_id;
190
- const message = `Deleted entity type registration "${name}". Note: the provisioned entity table${row?.outEntityTableName ? ` "${row.outEntityTableName}"` : ''} remains in the API schema with its data.`;
191
- return {
192
- content: [{ type: 'text', text: message }],
193
- details: { success: true, message },
194
- };
195
- }
196
- }
197
- }
198
- catch (err) {
199
- const message = err instanceof Error ? err.message : 'Failed to manage entity types';
200
- return { content: [{ type: 'text', text: message }], details: { success: false, message } };
201
- }
202
- },
203
- };
@@ -1,14 +0,0 @@
1
- import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
2
- export type MutationDetails = {
3
- success: boolean;
4
- message: string;
5
- };
6
- declare const DeleteTableSchema: import("typebox/type").TSchema;
7
- export declare const deleteTableTool: ToolDefinition<typeof DeleteTableSchema, MutationDetails>;
8
- declare const CreateFieldSchema: import("typebox/type").TSchema;
9
- export declare const createFieldTool: ToolDefinition<typeof CreateFieldSchema, MutationDetails>;
10
- declare const UpdateFieldSchema: import("typebox/type").TSchema;
11
- export declare const updateFieldTool: ToolDefinition<typeof UpdateFieldSchema, MutationDetails>;
12
- declare const DeleteFieldSchema: import("typebox/type").TSchema;
13
- export declare const deleteFieldTool: ToolDefinition<typeof DeleteFieldSchema, MutationDetails>;
14
- export {};
@@ -1,235 +0,0 @@
1
- import { toFieldDefault, toFieldType } from '@agentic-kit/harness';
2
- import { z } from 'zod';
3
- import { resolveProjectContext } from '../context';
4
- import { findUniqueConstraintId, resolveField, resolveSchema, resolveTable } from '../schema-resolve';
5
- import { toolSchema } from '../tool-schema';
6
- function ok(message) {
7
- return {
8
- content: [{ type: 'text', text: message }],
9
- details: { success: true, message },
10
- };
11
- }
12
- function fail(message) {
13
- return {
14
- content: [{ type: 'text', text: message }],
15
- details: { success: false, message },
16
- };
17
- }
18
- // ── delete_table ──────────────────────────────────────────────────────────
19
- const DeleteTableZod = z.object({
20
- table_name: z.string().describe('Name of the table to delete (snake_case)'),
21
- });
22
- const DeleteTableSchema = toolSchema(DeleteTableZod);
23
- export const deleteTableTool = {
24
- name: 'delete_table',
25
- label: 'Delete table',
26
- description: 'Permanently delete a table and its data from the project database.',
27
- promptSnippet: 'delete_table: drop an existing table by name. Destructive — gated.',
28
- parameters: DeleteTableSchema,
29
- async execute(_id, params, _signal, _onUpdate, ctx) {
30
- const resolved = await resolveProjectContext(ctx.cwd);
31
- if (!resolved.context)
32
- return fail(resolved.reason);
33
- try {
34
- const schema = await resolveSchema(resolved.context);
35
- const table = resolveTable(schema, params.table_name);
36
- await resolved.context.api.table
37
- .delete({ where: { id: table.id }, select: { id: true } })
38
- .unwrap();
39
- return ok(`Deleted table ${params.table_name}`);
40
- }
41
- catch (err) {
42
- return fail(err instanceof Error ? err.message : 'Failed to delete table');
43
- }
44
- },
45
- };
46
- // ── create_field ──────────────────────────────────────────────────────────
47
- const CreateFieldZod = z.object({
48
- table_name: z.string().describe('Name of the table to add the field to'),
49
- field_name: z.string().describe('Field name in snake_case'),
50
- type: z
51
- .string()
52
- .describe('PostgreSQL type: text, integer, smallint, numeric, boolean, date, timestamp, timestamptz, time, json, jsonb, inet, email, url, image, upload'),
53
- is_required: z.boolean().describe('Whether the field is NOT NULL. Defaults to false.').optional(),
54
- default_value: z
55
- .union([z.string(), z.null()])
56
- .describe('SQL default expression, e.g. "now()", "\'draft\'"')
57
- .optional(),
58
- is_unique: z
59
- .boolean()
60
- .describe('Whether the field has a unique constraint. Defaults to false.')
61
- .optional(),
62
- });
63
- const CreateFieldSchema = toolSchema(CreateFieldZod);
64
- export const createFieldTool = {
65
- name: 'create_field',
66
- label: 'Create field',
67
- description: 'Add a new field (column) to an existing table in the project database.',
68
- promptSnippet: 'create_field: add a column to an existing table. Gated.',
69
- parameters: CreateFieldSchema,
70
- async execute(_id, params, _signal, _onUpdate, ctx) {
71
- const resolved = await resolveProjectContext(ctx.cwd);
72
- if (!resolved.context)
73
- return fail(resolved.reason);
74
- const { api, databaseId } = resolved.context;
75
- try {
76
- const schema = await resolveSchema(resolved.context);
77
- const table = resolveTable(schema, params.table_name);
78
- const result = await api.field
79
- .create({
80
- data: {
81
- name: params.field_name,
82
- type: toFieldType(params.type),
83
- tableId: table.id,
84
- databaseId,
85
- isRequired: params.is_required ?? false,
86
- defaultValue: toFieldDefault(params.default_value),
87
- },
88
- select: { id: true, name: true, type: true },
89
- })
90
- .unwrap();
91
- const createdId = result.createField?.field?.id;
92
- if (params.is_unique && createdId) {
93
- try {
94
- await api.uniqueConstraint
95
- .create({
96
- data: {
97
- tableId: table.id,
98
- databaseId,
99
- fieldIds: [createdId],
100
- name: `${table.name}_${params.field_name}_key`,
101
- type: 'u',
102
- },
103
- select: { id: true },
104
- })
105
- .unwrap();
106
- }
107
- catch (err) {
108
- console.warn('Failed to create unique constraint:', err);
109
- }
110
- }
111
- return ok(`Added field ${params.table_name}.${params.field_name}`);
112
- }
113
- catch (err) {
114
- return fail(err instanceof Error ? err.message : 'Failed to create field');
115
- }
116
- },
117
- };
118
- // ── update_field ──────────────────────────────────────────────────────────
119
- const UpdateFieldZod = z.object({
120
- table_name: z.string().describe('Name of the table containing the field'),
121
- field_name: z.string().describe('Current field name'),
122
- new_name: z.string().describe('New field name in snake_case (if renaming)').optional(),
123
- new_type: z.string().describe('New PostgreSQL type (if changing type)').optional(),
124
- is_required: z.boolean().describe('Set NOT NULL constraint').optional(),
125
- default_value: z
126
- .union([z.string(), z.null()])
127
- .describe('New SQL default expression, or null to remove')
128
- .optional(),
129
- is_unique: z.boolean().describe('Set or remove unique constraint').optional(),
130
- });
131
- const UpdateFieldSchema = toolSchema(UpdateFieldZod);
132
- export const updateFieldTool = {
133
- name: 'update_field',
134
- label: 'Update field',
135
- description: 'Modify an existing field: rename, change type, toggle required/unique, or set default.',
136
- promptSnippet: 'update_field: rename/retype/toggle an existing column. Gated.',
137
- parameters: UpdateFieldSchema,
138
- async execute(_id, params, _signal, _onUpdate, ctx) {
139
- const resolved = await resolveProjectContext(ctx.cwd);
140
- if (!resolved.context)
141
- return fail(resolved.reason);
142
- const { api, databaseId } = resolved.context;
143
- try {
144
- const schema = await resolveSchema(resolved.context);
145
- const table = resolveTable(schema, params.table_name);
146
- const field = resolveField(table, params.field_name);
147
- const patch = {};
148
- if (params.new_name)
149
- patch.name = params.new_name;
150
- if (params.new_type)
151
- patch.type = toFieldType(params.new_type);
152
- if (params.is_required !== undefined)
153
- patch.isRequired = params.is_required;
154
- if (params.default_value !== undefined) {
155
- patch.defaultValue =
156
- params.default_value === null ? null : (toFieldDefault(params.default_value) ?? null);
157
- }
158
- if (Object.keys(patch).length > 0) {
159
- await api.field
160
- .update({
161
- where: { id: field.id },
162
- data: patch,
163
- select: { id: true, name: true, type: true },
164
- })
165
- .unwrap();
166
- }
167
- if (params.is_unique !== undefined) {
168
- const existingUniqueId = findUniqueConstraintId(table, field.id);
169
- if (params.is_unique && !existingUniqueId) {
170
- try {
171
- await api.uniqueConstraint
172
- .create({
173
- data: {
174
- tableId: table.id,
175
- databaseId,
176
- fieldIds: [field.id],
177
- name: `${table.name}_${params.new_name ?? field.name}_key`,
178
- type: 'u',
179
- },
180
- select: { id: true },
181
- })
182
- .unwrap();
183
- }
184
- catch (err) {
185
- console.warn('Failed to create unique constraint:', err);
186
- }
187
- }
188
- else if (!params.is_unique && existingUniqueId) {
189
- try {
190
- await api.uniqueConstraint
191
- .delete({ where: { id: existingUniqueId }, select: { id: true } })
192
- .unwrap();
193
- }
194
- catch (err) {
195
- console.warn('Failed to delete unique constraint:', err);
196
- }
197
- }
198
- }
199
- return ok(`Updated field ${params.table_name}.${params.field_name}`);
200
- }
201
- catch (err) {
202
- return fail(err instanceof Error ? err.message : 'Failed to update field');
203
- }
204
- },
205
- };
206
- // ── delete_field ──────────────────────────────────────────────────────────
207
- const DeleteFieldZod = z.object({
208
- table_name: z.string().describe('Name of the table containing the field'),
209
- field_name: z.string().describe('Name of the field to delete'),
210
- });
211
- const DeleteFieldSchema = toolSchema(DeleteFieldZod);
212
- export const deleteFieldTool = {
213
- name: 'delete_field',
214
- label: 'Delete field',
215
- description: 'Permanently delete a field (column) from an existing table.',
216
- promptSnippet: 'delete_field: drop a column from a table by name. Destructive — gated.',
217
- parameters: DeleteFieldSchema,
218
- async execute(_id, params, _signal, _onUpdate, ctx) {
219
- const resolved = await resolveProjectContext(ctx.cwd);
220
- if (!resolved.context)
221
- return fail(resolved.reason);
222
- try {
223
- const schema = await resolveSchema(resolved.context);
224
- const table = resolveTable(schema, params.table_name);
225
- const field = resolveField(table, params.field_name);
226
- await resolved.context.api.field
227
- .delete({ where: { id: field.id }, select: { id: true } })
228
- .unwrap();
229
- return ok(`Deleted field ${params.table_name}.${params.field_name}`);
230
- }
231
- catch (err) {
232
- return fail(err instanceof Error ? err.message : 'Failed to delete field');
233
- }
234
- },
235
- };
@@ -1,22 +0,0 @@
1
- import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
2
- declare const BlueprintSchema: import("typebox/type").TSchema;
3
- type ProvisionedField = {
4
- name: string;
5
- type: string;
6
- isRequired: boolean;
7
- defaultValue: string | null;
8
- };
9
- type ProvisionedTable = {
10
- name: string;
11
- fields: ProvisionedField[];
12
- policies: string[];
13
- relationCount: number;
14
- };
15
- export type ProvisionBlueprintDetails = {
16
- created: number;
17
- total: number;
18
- tables: ProvisionedTable[];
19
- error: string | null;
20
- };
21
- export declare const provisionBlueprintTool: ToolDefinition<typeof BlueprintSchema, ProvisionBlueprintDetails>;
22
- export {};
@@ -1,111 +0,0 @@
1
- import { BlueprintZod, expandBlueprintDefaults, filterInternalPolicies, } from '@agentic-kit/harness';
2
- import { resolveProjectContext } from '../context';
3
- import { toolSchema } from '../tool-schema';
4
- const BlueprintSchema = toolSchema(BlueprintZod);
5
- function formatText(name, details) {
6
- if (details.error)
7
- return `Failed to provision "${name}": ${details.error}`;
8
- const lines = [`Created ${details.created} table${details.created === 1 ? '' : 's'} from "${name}":`];
9
- for (const table of details.tables) {
10
- const parts = [`${table.fields.length} field${table.fields.length === 1 ? '' : 's'}`];
11
- if (table.relationCount > 0) {
12
- parts.push(`${table.relationCount} relation${table.relationCount === 1 ? '' : 's'}`);
13
- }
14
- if (table.policies.length > 0) {
15
- parts.push(`policies: ${table.policies.map((policy) => policy.replace(/^Authz/, '')).join(', ')}`);
16
- }
17
- lines.push(` - ${table.name} (${parts.join(', ')})`);
18
- }
19
- return lines.join('\n');
20
- }
21
- export const provisionBlueprintTool = {
22
- name: 'provision_blueprint',
23
- label: 'Provision blueprint',
24
- description: 'Create one or more related tables (with fields, RLS policies, and relations) in the project database from a blueprint definition. Always put related tables in a SINGLE call so relations are created together.',
25
- promptSnippet: 'provision_blueprint: create new tables from scratch in a single call (fields + policies + relations). Call describe_schema first.',
26
- parameters: BlueprintSchema,
27
- async execute(_toolCallId, params, _signal, _onUpdate, ctx) {
28
- const empty = { created: 0, total: 0, tables: [], error: null };
29
- const resolved = await resolveProjectContext(ctx.cwd);
30
- if (!resolved.context) {
31
- return { content: [{ type: 'text', text: resolved.reason }], details: empty };
32
- }
33
- const { modules, databaseId, schemaId, ownerId } = resolved.context;
34
- if (!ownerId) {
35
- return {
36
- content: [{ type: 'text', text: 'Not authenticated (missing OWNER_ID in .env).' }],
37
- details: empty,
38
- };
39
- }
40
- const definition = expandBlueprintDefaults(params.definition);
41
- const uniqueName = `${params.name}_${Date.now()}`;
42
- try {
43
- const createResult = await modules.blueprint
44
- .create({
45
- data: {
46
- ownerId,
47
- databaseId,
48
- name: uniqueName,
49
- displayName: params.name,
50
- description: params.description,
51
- definition,
52
- },
53
- select: { id: true, name: true },
54
- })
55
- .unwrap();
56
- const blueprintId = createResult.createBlueprint?.blueprint?.id;
57
- if (!blueprintId)
58
- throw new Error('Failed to create blueprint');
59
- const constructResult = await modules.mutation
60
- .constructBlueprint({ input: { blueprintId, schemaId } }, { select: { result: true } })
61
- .unwrap();
62
- const result = constructResult.constructBlueprint?.result;
63
- if (!result) {
64
- const constructions = await modules.blueprintConstruction
65
- .findMany({
66
- where: { blueprintId: { equalTo: blueprintId } },
67
- orderBy: ['ID_DESC'],
68
- first: 1,
69
- select: { status: true, errorDetails: true },
70
- })
71
- .unwrap();
72
- const error = constructions?.blueprintConstructions?.nodes?.[0]?.errorDetails ?? 'Unknown error';
73
- const details = {
74
- created: 0,
75
- total: params.definition.tables.length,
76
- tables: [],
77
- error: typeof error === 'string' ? error : JSON.stringify(error),
78
- };
79
- return { content: [{ type: 'text', text: formatText(params.name, details) }], details };
80
- }
81
- const relations = params.definition.relations ?? [];
82
- const details = {
83
- created: params.definition.tables.length,
84
- total: params.definition.tables.length,
85
- tables: params.definition.tables.map((t) => ({
86
- name: t.table_name,
87
- fields: (t.fields ?? []).map((f) => ({
88
- name: f.name,
89
- type: f.type,
90
- isRequired: f.is_required ?? false,
91
- defaultValue: f.default ?? null,
92
- })),
93
- policies: filterInternalPolicies(t.policies.map((p) => p.$type)),
94
- relationCount: relations.filter((r) => r.source_table === t.table_name).length,
95
- })),
96
- error: null,
97
- };
98
- return { content: [{ type: 'text', text: formatText(params.name, details) }], details };
99
- }
100
- catch (err) {
101
- const message = err instanceof Error ? err.message : 'Failed to provision blueprint';
102
- const details = {
103
- created: 0,
104
- total: params.definition.tables.length,
105
- tables: [],
106
- error: message,
107
- };
108
- return { content: [{ type: 'text', text: formatText(params.name, details) }], details };
109
- }
110
- },
111
- };
@@ -1,14 +0,0 @@
1
- import type { ToolDefinition } from '@earendil-works/pi-coding-agent';
2
- declare const ProvisionDatabaseSchema: import("typebox/type").TSchema;
3
- export type ProvisionDatabaseDetails = {
4
- success: boolean;
5
- message: string;
6
- databaseId?: string;
7
- databaseName?: string;
8
- ownerId?: string;
9
- fixupNote?: string;
10
- /** True when an existing live binding was kept — nothing changed. */
11
- skipped?: boolean;
12
- };
13
- export declare const provisionDatabaseTool: ToolDefinition<typeof ProvisionDatabaseSchema, ProvisionDatabaseDetails>;
14
- export {};