@absolutejs/artifacts 0.0.4 → 0.1.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 +21 -0
- package/dist/drizzle.js +245 -0
- package/dist/manifest.js +175 -23
- package/dist/manifest.json +123 -7
- package/dist/src/drizzle.d.ts +1586 -0
- package/dist/src/manifest.d.ts +74 -2
- package/package.json +18 -6
package/README.md
CHANGED
|
@@ -87,6 +87,27 @@ const history = await artifacts.listRevisions("owner-123", page.id);
|
|
|
87
87
|
const restored = await artifacts.restore("owner-123", page.id, 1);
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
## Production persistence
|
|
91
|
+
|
|
92
|
+
Use the package-owned Drizzle schema on PostgreSQL, including Neon. The store
|
|
93
|
+
atomically writes the current artifact, immutable revision, and lifecycle
|
|
94
|
+
outbox events. It also persists per-revision indexing state and fences every
|
|
95
|
+
artifact read and mutation by owner.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import {
|
|
99
|
+
artifactDrizzleSchema,
|
|
100
|
+
createDrizzleArtifactStore,
|
|
101
|
+
} from "@absolutejs/artifacts/drizzle";
|
|
102
|
+
|
|
103
|
+
const store = createDrizzleArtifactStore({ db });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Export `artifactDrizzleSchema` from your application's Drizzle schema so its
|
|
107
|
+
normal migration workflow owns the four tables. Insert and select TypeBoxes
|
|
108
|
+
generated directly from those tables are exported from the same entry point;
|
|
109
|
+
hosts should reuse them instead of redefining database row schemas.
|
|
110
|
+
|
|
90
111
|
## File-backed artifact kinds
|
|
91
112
|
|
|
92
113
|
Use the bundled definitions directly or compose them with application-specific
|
package/dist/drizzle.js
ADDED
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/drizzle.ts
|
|
3
|
+
import { and, asc, desc, eq, isNotNull, isNull } from "drizzle-orm";
|
|
4
|
+
import {
|
|
5
|
+
customType,
|
|
6
|
+
index,
|
|
7
|
+
integer,
|
|
8
|
+
pgTable,
|
|
9
|
+
primaryKey,
|
|
10
|
+
text,
|
|
11
|
+
timestamp
|
|
12
|
+
} from "drizzle-orm/pg-core";
|
|
13
|
+
import { createInsertSchema, createSelectSchema } from "drizzle-typebox";
|
|
14
|
+
var recordJsonb = customType({
|
|
15
|
+
dataType: () => "jsonb",
|
|
16
|
+
fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
|
|
17
|
+
toDriver: (value) => JSON.stringify(value)
|
|
18
|
+
});
|
|
19
|
+
var revisionJsonb = customType({
|
|
20
|
+
dataType: () => "jsonb",
|
|
21
|
+
fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
|
|
22
|
+
toDriver: (value) => JSON.stringify(value)
|
|
23
|
+
});
|
|
24
|
+
var eventJsonb = customType({
|
|
25
|
+
dataType: () => "jsonb",
|
|
26
|
+
fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
|
|
27
|
+
toDriver: (value) => JSON.stringify(value)
|
|
28
|
+
});
|
|
29
|
+
var indexingJsonb = customType({
|
|
30
|
+
dataType: () => "jsonb",
|
|
31
|
+
fromDriver: (value) => typeof value === "string" ? JSON.parse(value) : value,
|
|
32
|
+
toDriver: (value) => JSON.stringify(value)
|
|
33
|
+
});
|
|
34
|
+
var artifactRecords = pgTable("artifact_records", {
|
|
35
|
+
document: recordJsonb().notNull(),
|
|
36
|
+
id: text().primaryKey(),
|
|
37
|
+
kind: text().notNull(),
|
|
38
|
+
ownerId: text("owner_id").notNull(),
|
|
39
|
+
revision: integer().notNull(),
|
|
40
|
+
status: text().notNull(),
|
|
41
|
+
updatedAt: timestamp("updated_at", {
|
|
42
|
+
mode: "string",
|
|
43
|
+
withTimezone: true
|
|
44
|
+
}).notNull()
|
|
45
|
+
}, (table) => [
|
|
46
|
+
index("artifact_records_owner_updated_idx").on(table.ownerId, table.updatedAt.desc()),
|
|
47
|
+
index("artifact_records_owner_kind_idx").on(table.ownerId, table.kind)
|
|
48
|
+
]);
|
|
49
|
+
var artifactRevisions = pgTable("artifact_revisions", {
|
|
50
|
+
artifactId: text("artifact_id").notNull().references(() => artifactRecords.id),
|
|
51
|
+
document: revisionJsonb().notNull(),
|
|
52
|
+
ownerId: text("owner_id").notNull(),
|
|
53
|
+
revision: integer().notNull()
|
|
54
|
+
}, (table) => [
|
|
55
|
+
primaryKey({
|
|
56
|
+
columns: [table.artifactId, table.revision],
|
|
57
|
+
name: "artifact_revisions_pkey"
|
|
58
|
+
}),
|
|
59
|
+
index("artifact_revisions_owner_idx").on(table.ownerId, table.artifactId, table.revision.desc())
|
|
60
|
+
]);
|
|
61
|
+
var artifactEvents = pgTable("artifact_events", {
|
|
62
|
+
artifactId: text("artifact_id").notNull().references(() => artifactRecords.id),
|
|
63
|
+
createdAt: timestamp("created_at", {
|
|
64
|
+
mode: "string",
|
|
65
|
+
withTimezone: true
|
|
66
|
+
}).notNull(),
|
|
67
|
+
document: eventJsonb().notNull(),
|
|
68
|
+
id: text().primaryKey(),
|
|
69
|
+
ownerId: text("owner_id").notNull(),
|
|
70
|
+
processedAt: timestamp("processed_at", {
|
|
71
|
+
mode: "string",
|
|
72
|
+
withTimezone: true
|
|
73
|
+
}),
|
|
74
|
+
type: text().notNull()
|
|
75
|
+
}, (table) => [
|
|
76
|
+
index("artifact_events_outbox_idx").on(table.processedAt, table.createdAt),
|
|
77
|
+
index("artifact_events_artifact_idx").on(table.ownerId, table.artifactId, table.createdAt)
|
|
78
|
+
]);
|
|
79
|
+
var artifactIndexingStates = pgTable("artifact_indexing_states", {
|
|
80
|
+
artifactId: text("artifact_id").primaryKey().references(() => artifactRecords.id),
|
|
81
|
+
document: indexingJsonb().notNull(),
|
|
82
|
+
ownerId: text("owner_id").notNull(),
|
|
83
|
+
revision: integer().notNull(),
|
|
84
|
+
status: text().notNull(),
|
|
85
|
+
updatedAt: timestamp("updated_at", {
|
|
86
|
+
mode: "string",
|
|
87
|
+
withTimezone: true
|
|
88
|
+
}).notNull()
|
|
89
|
+
});
|
|
90
|
+
var artifactDrizzleSchema = {
|
|
91
|
+
artifactEvents,
|
|
92
|
+
artifactIndexingStates,
|
|
93
|
+
artifactRecords,
|
|
94
|
+
artifactRevisions
|
|
95
|
+
};
|
|
96
|
+
var ArtifactRecordInsertSchema = createInsertSchema(artifactRecords);
|
|
97
|
+
var ArtifactRecordSelectSchema = createSelectSchema(artifactRecords);
|
|
98
|
+
var ArtifactRevisionInsertSchema = createInsertSchema(artifactRevisions);
|
|
99
|
+
var ArtifactRevisionSelectSchema = createSelectSchema(artifactRevisions);
|
|
100
|
+
var ArtifactEventInsertSchema = createInsertSchema(artifactEvents);
|
|
101
|
+
var ArtifactEventSelectSchema = createSelectSchema(artifactEvents);
|
|
102
|
+
var ArtifactIndexingStateInsertSchema = createInsertSchema(artifactIndexingStates);
|
|
103
|
+
var ArtifactIndexingStateSelectSchema = createSelectSchema(artifactIndexingStates);
|
|
104
|
+
var eventRows = (events) => events.map((event) => ({
|
|
105
|
+
artifactId: event.artifactId,
|
|
106
|
+
createdAt: event.createdAt,
|
|
107
|
+
document: event,
|
|
108
|
+
id: event.id,
|
|
109
|
+
ownerId: event.ownerId,
|
|
110
|
+
processedAt: event.processedAt,
|
|
111
|
+
type: event.type
|
|
112
|
+
}));
|
|
113
|
+
var assertEventsBelongToArtifact = (record, events) => {
|
|
114
|
+
if (events.some((event) => event.artifactId !== record.id || event.ownerId !== record.ownerId))
|
|
115
|
+
throw new Error("Artifact events must belong to the persisted artifact");
|
|
116
|
+
};
|
|
117
|
+
var recordRow = (record) => ({
|
|
118
|
+
document: record,
|
|
119
|
+
id: record.id,
|
|
120
|
+
kind: record.kind,
|
|
121
|
+
ownerId: record.ownerId,
|
|
122
|
+
revision: record.revision,
|
|
123
|
+
status: record.status,
|
|
124
|
+
updatedAt: record.updatedAt
|
|
125
|
+
});
|
|
126
|
+
var recordUpdate = (record) => ({
|
|
127
|
+
document: record,
|
|
128
|
+
kind: record.kind,
|
|
129
|
+
ownerId: record.ownerId,
|
|
130
|
+
revision: record.revision,
|
|
131
|
+
status: record.status,
|
|
132
|
+
updatedAt: record.updatedAt
|
|
133
|
+
});
|
|
134
|
+
var revisionRow = (record) => ({
|
|
135
|
+
artifactId: record.id,
|
|
136
|
+
document: record,
|
|
137
|
+
ownerId: record.ownerId,
|
|
138
|
+
revision: record.revision
|
|
139
|
+
});
|
|
140
|
+
var createDrizzleArtifactStore = (options) => ({
|
|
141
|
+
create: (record, events = []) => options.db.transaction(async (transaction) => {
|
|
142
|
+
assertEventsBelongToArtifact(record, events);
|
|
143
|
+
await transaction.insert(artifactRecords).values(recordRow(record));
|
|
144
|
+
await transaction.insert(artifactRevisions).values(revisionRow(record));
|
|
145
|
+
if (events.length > 0)
|
|
146
|
+
await transaction.insert(artifactEvents).values(eventRows(events));
|
|
147
|
+
}),
|
|
148
|
+
get: async (ownerId, artifactId) => {
|
|
149
|
+
const [row] = await options.db.select({ document: artifactRecords.document }).from(artifactRecords).where(and(eq(artifactRecords.id, artifactId), eq(artifactRecords.ownerId, ownerId))).limit(1);
|
|
150
|
+
return row?.document ?? null;
|
|
151
|
+
},
|
|
152
|
+
getIndexingState: async (ownerId, artifactId) => {
|
|
153
|
+
const [row] = await options.db.select({ document: artifactIndexingStates.document }).from(artifactIndexingStates).where(and(eq(artifactIndexingStates.artifactId, artifactId), eq(artifactIndexingStates.ownerId, ownerId))).limit(1);
|
|
154
|
+
return row?.document ?? null;
|
|
155
|
+
},
|
|
156
|
+
getRevision: async (ownerId, artifactId, revision) => {
|
|
157
|
+
const [row] = await options.db.select({ document: artifactRevisions.document }).from(artifactRevisions).where(and(eq(artifactRevisions.artifactId, artifactId), eq(artifactRevisions.ownerId, ownerId), eq(artifactRevisions.revision, revision))).limit(1);
|
|
158
|
+
return row?.document ?? null;
|
|
159
|
+
},
|
|
160
|
+
list: async (ownerId, query = {}) => {
|
|
161
|
+
const conditions = [eq(artifactRecords.ownerId, ownerId)];
|
|
162
|
+
if (query.kind)
|
|
163
|
+
conditions.push(eq(artifactRecords.kind, query.kind));
|
|
164
|
+
if (query.status)
|
|
165
|
+
conditions.push(eq(artifactRecords.status, query.status));
|
|
166
|
+
const statement = options.db.select({ document: artifactRecords.document }).from(artifactRecords).where(and(...conditions)).orderBy(desc(artifactRecords.updatedAt));
|
|
167
|
+
const rows = query.limit === undefined ? await statement : await statement.limit(query.limit);
|
|
168
|
+
return rows.map(({ document }) => document);
|
|
169
|
+
},
|
|
170
|
+
listEvents: async (query = {}) => {
|
|
171
|
+
const conditions = [];
|
|
172
|
+
if (query.processed !== undefined)
|
|
173
|
+
conditions.push(query.processed ? isNotNull(artifactEvents.processedAt) : isNull(artifactEvents.processedAt));
|
|
174
|
+
if (query.type)
|
|
175
|
+
conditions.push(eq(artifactEvents.type, query.type));
|
|
176
|
+
const statement = options.db.select({
|
|
177
|
+
document: artifactEvents.document,
|
|
178
|
+
processedAt: artifactEvents.processedAt
|
|
179
|
+
}).from(artifactEvents).where(conditions.length > 0 ? and(...conditions) : undefined).orderBy(asc(artifactEvents.createdAt));
|
|
180
|
+
const rows = query.limit === undefined ? await statement : await statement.limit(query.limit);
|
|
181
|
+
return rows.map(({ document, processedAt }) => ({
|
|
182
|
+
...document,
|
|
183
|
+
...processedAt ? { processedAt: new Date(processedAt).toISOString() } : {}
|
|
184
|
+
}));
|
|
185
|
+
},
|
|
186
|
+
listReferencedAssetIds: async () => {
|
|
187
|
+
const rows = await options.db.select({ document: artifactRevisions.document }).from(artifactRevisions);
|
|
188
|
+
return [
|
|
189
|
+
...new Set(rows.flatMap(({ document }) => document.assets.map(({ id }) => id)))
|
|
190
|
+
];
|
|
191
|
+
},
|
|
192
|
+
listRevisions: async (ownerId, artifactId) => (await options.db.select({ document: artifactRevisions.document }).from(artifactRevisions).where(and(eq(artifactRevisions.artifactId, artifactId), eq(artifactRevisions.ownerId, ownerId))).orderBy(desc(artifactRevisions.revision))).map(({ document }) => document),
|
|
193
|
+
markEventProcessed: async (eventId, processedAt) => (await options.db.update(artifactEvents).set({ processedAt }).where(eq(artifactEvents.id, eventId)).returning({ id: artifactEvents.id })).length === 1,
|
|
194
|
+
putIndexingState: (ownerId, state, events = []) => options.db.transaction(async (transaction) => {
|
|
195
|
+
assertEventsBelongToArtifact({ id: state.artifactId, ownerId }, events);
|
|
196
|
+
const [artifact] = await transaction.select({ id: artifactRecords.id }).from(artifactRecords).where(and(eq(artifactRecords.id, state.artifactId), eq(artifactRecords.ownerId, ownerId))).limit(1);
|
|
197
|
+
if (!artifact)
|
|
198
|
+
throw new Error("Artifact not found");
|
|
199
|
+
await transaction.insert(artifactIndexingStates).values({
|
|
200
|
+
artifactId: state.artifactId,
|
|
201
|
+
document: state,
|
|
202
|
+
ownerId,
|
|
203
|
+
revision: state.revision,
|
|
204
|
+
status: state.status,
|
|
205
|
+
updatedAt: state.updatedAt
|
|
206
|
+
}).onConflictDoUpdate({
|
|
207
|
+
set: {
|
|
208
|
+
document: state,
|
|
209
|
+
ownerId,
|
|
210
|
+
revision: state.revision,
|
|
211
|
+
status: state.status,
|
|
212
|
+
updatedAt: state.updatedAt
|
|
213
|
+
},
|
|
214
|
+
target: artifactIndexingStates.artifactId
|
|
215
|
+
});
|
|
216
|
+
if (events.length > 0)
|
|
217
|
+
await transaction.insert(artifactEvents).values(eventRows(events));
|
|
218
|
+
}),
|
|
219
|
+
save: (record, expectedRevision, events = []) => options.db.transaction(async (transaction) => {
|
|
220
|
+
assertEventsBelongToArtifact(record, events);
|
|
221
|
+
const updated = await transaction.update(artifactRecords).set(recordUpdate(record)).where(and(eq(artifactRecords.id, record.id), eq(artifactRecords.ownerId, record.ownerId), eq(artifactRecords.revision, expectedRevision))).returning({ id: artifactRecords.id });
|
|
222
|
+
if (updated.length !== 1)
|
|
223
|
+
return false;
|
|
224
|
+
await transaction.insert(artifactRevisions).values(revisionRow(record));
|
|
225
|
+
if (events.length > 0)
|
|
226
|
+
await transaction.insert(artifactEvents).values(eventRows(events));
|
|
227
|
+
return true;
|
|
228
|
+
})
|
|
229
|
+
});
|
|
230
|
+
export {
|
|
231
|
+
createDrizzleArtifactStore,
|
|
232
|
+
artifactRevisions,
|
|
233
|
+
artifactRecords,
|
|
234
|
+
artifactIndexingStates,
|
|
235
|
+
artifactEvents,
|
|
236
|
+
artifactDrizzleSchema,
|
|
237
|
+
ArtifactRevisionSelectSchema,
|
|
238
|
+
ArtifactRevisionInsertSchema,
|
|
239
|
+
ArtifactRecordSelectSchema,
|
|
240
|
+
ArtifactRecordInsertSchema,
|
|
241
|
+
ArtifactIndexingStateSelectSchema,
|
|
242
|
+
ArtifactIndexingStateInsertSchema,
|
|
243
|
+
ArtifactEventSelectSchema,
|
|
244
|
+
ArtifactEventInsertSchema
|
|
245
|
+
};
|
package/dist/manifest.js
CHANGED
|
@@ -14,14 +14,23 @@ var __export = (target, all) => {
|
|
|
14
14
|
set: __exportSetter.bind(all, name)
|
|
15
15
|
});
|
|
16
16
|
};
|
|
17
|
-
var
|
|
18
|
-
const defined =
|
|
17
|
+
var defineImplementation = () => (implementation) => {
|
|
18
|
+
const defined = implementation;
|
|
19
19
|
return defined;
|
|
20
20
|
};
|
|
21
|
-
var
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
var defineManifest = () => (manifest) => manifest;
|
|
22
|
+
var literal = (value) => value;
|
|
23
|
+
var RUNTIME_KIND = literal("runtime");
|
|
24
|
+
var WORKSPACE_KIND = literal("workspace");
|
|
25
|
+
var toolFactory = () => {
|
|
26
|
+
function runtime(definition) {
|
|
27
|
+
return { kind: RUNTIME_KIND, ...definition };
|
|
28
|
+
}
|
|
29
|
+
function workspace(definition) {
|
|
30
|
+
return { kind: WORKSPACE_KIND, ...definition };
|
|
31
|
+
}
|
|
32
|
+
return { runtime, workspace };
|
|
33
|
+
};
|
|
25
34
|
function IsAsyncIterator(value) {
|
|
26
35
|
return IsObject(value) && globalThis.Symbol.asyncIterator in value;
|
|
27
36
|
}
|
|
@@ -759,7 +768,7 @@ function String2(options) {
|
|
|
759
768
|
function* FromUnion(syntax) {
|
|
760
769
|
const trim = syntax.trim().replace(/"|'/g, "");
|
|
761
770
|
return trim === "boolean" ? yield Boolean() : trim === "number" ? yield Number2() : trim === "bigint" ? yield BigInt2() : trim === "string" ? yield String2() : yield (() => {
|
|
762
|
-
const literals = trim.split("|").map((
|
|
771
|
+
const literals = trim.split("|").map((literal2) => Literal(literal2.trim()));
|
|
763
772
|
return literals.length === 0 ? Never() : literals.length === 1 ? literals[0] : UnionEvaluated(literals);
|
|
764
773
|
})();
|
|
765
774
|
}
|
|
@@ -3467,10 +3476,10 @@ function ScoreUnion(schema, references, value) {
|
|
|
3467
3476
|
const keys = Object.getOwnPropertyNames(value);
|
|
3468
3477
|
const entries = Object.entries(object.properties);
|
|
3469
3478
|
return entries.reduce((acc, [key, schema2]) => {
|
|
3470
|
-
const
|
|
3479
|
+
const literal2 = schema2[Kind] === "Literal" && schema2.const === value[key] ? 100 : 0;
|
|
3471
3480
|
const checks = Check(schema2, references, value[key]) ? 10 : 0;
|
|
3472
3481
|
const exists = keys.includes(key) ? 1 : 0;
|
|
3473
|
-
return acc + (
|
|
3482
|
+
return acc + (literal2 + checks + exists);
|
|
3474
3483
|
}, 0);
|
|
3475
3484
|
} else if (schema[Kind] === "Union") {
|
|
3476
3485
|
const schemas = schema.anyOf.map((schema2) => Deref(schema2, references));
|
|
@@ -5807,7 +5816,13 @@ var wiringSnippet = Type.Object({
|
|
|
5807
5816
|
Type.Literal("server-plugin")
|
|
5808
5817
|
]))
|
|
5809
5818
|
});
|
|
5810
|
-
var clientFrameworks = [
|
|
5819
|
+
var clientFrameworks = [
|
|
5820
|
+
"angular",
|
|
5821
|
+
"client",
|
|
5822
|
+
"react",
|
|
5823
|
+
"svelte",
|
|
5824
|
+
"vue"
|
|
5825
|
+
];
|
|
5811
5826
|
var wiringRecipe = Type.Object({
|
|
5812
5827
|
client: Type.Optional(Type.Partial(Type.Object(Object.fromEntries(clientFrameworks.map((framework) => [framework, wiringSnippet]))))),
|
|
5813
5828
|
description: Type.Optional(Type.String()),
|
|
@@ -5872,8 +5887,47 @@ var toolAnnotations = Type.Object({
|
|
|
5872
5887
|
readOnlyHint: Type.Optional(Type.Boolean()),
|
|
5873
5888
|
title: Type.Optional(Type.String())
|
|
5874
5889
|
});
|
|
5890
|
+
var toolAuthorization = Type.Object({
|
|
5891
|
+
approval: Type.Union([
|
|
5892
|
+
Type.Literal("always"),
|
|
5893
|
+
Type.Literal("never"),
|
|
5894
|
+
Type.Literal("policy")
|
|
5895
|
+
]),
|
|
5896
|
+
audience: Type.Union([
|
|
5897
|
+
Type.Literal("admin"),
|
|
5898
|
+
Type.Literal("authenticated"),
|
|
5899
|
+
Type.Literal("owner"),
|
|
5900
|
+
Type.Literal("public")
|
|
5901
|
+
]),
|
|
5902
|
+
compensatingTool: Type.Optional(Type.String({ pattern: TOOL_NAME_PATTERN.source })),
|
|
5903
|
+
destinationFields: Type.Optional(Type.Array(Type.String({ minLength: 1 }), { minItems: 1 })),
|
|
5904
|
+
destinations: Type.Optional(Type.Array(Type.String({ minLength: 1 }), { minItems: 1 })),
|
|
5905
|
+
effects: Type.Array(Type.String({ minLength: 1 }), { minItems: 1 }),
|
|
5906
|
+
idempotency: Type.Optional(Type.Union([
|
|
5907
|
+
Type.Object({
|
|
5908
|
+
field: Type.String({ minLength: 1 }),
|
|
5909
|
+
mode: Type.Literal("field")
|
|
5910
|
+
}),
|
|
5911
|
+
Type.Object({ mode: Type.Literal("host") }),
|
|
5912
|
+
Type.Object({ mode: Type.Literal("resource") })
|
|
5913
|
+
])),
|
|
5914
|
+
requiredScopes: Type.Optional(Type.Array(Type.String({ minLength: 1 }), { minItems: 1 })),
|
|
5915
|
+
resource: Type.Optional(Type.Object({
|
|
5916
|
+
idField: Type.Optional(Type.String({ minLength: 1 })),
|
|
5917
|
+
ownerIdField: Type.Optional(Type.String({ minLength: 1 })),
|
|
5918
|
+
tenantIdField: Type.Optional(Type.String({ minLength: 1 })),
|
|
5919
|
+
type: Type.String({ minLength: 1 })
|
|
5920
|
+
})),
|
|
5921
|
+
reversible: Type.Optional(Type.Boolean()),
|
|
5922
|
+
spend: Type.Optional(Type.Object({
|
|
5923
|
+
amountMinorField: Type.String({ minLength: 1 }),
|
|
5924
|
+
currencyField: Type.String({ minLength: 1 }),
|
|
5925
|
+
maximumAmountMinor: Type.Optional(Type.Integer({ minimum: 0 }))
|
|
5926
|
+
}))
|
|
5927
|
+
});
|
|
5875
5928
|
var serializedTool = Type.Object({
|
|
5876
5929
|
annotations: Type.Optional(toolAnnotations),
|
|
5930
|
+
authorization: Type.Optional(toolAuthorization),
|
|
5877
5931
|
capabilities: Type.Optional(Type.Array(Type.Union([
|
|
5878
5932
|
Type.Literal("exec"),
|
|
5879
5933
|
Type.Literal("glob"),
|
|
@@ -5885,7 +5939,15 @@ var serializedTool = Type.Object({
|
|
|
5885
5939
|
kind: Type.Union([Type.Literal("runtime"), Type.Literal("workspace")])
|
|
5886
5940
|
});
|
|
5887
5941
|
var manifestSchema = Type.Object({
|
|
5888
|
-
contract: Type.Literal(1),
|
|
5942
|
+
contract: Type.Union([Type.Literal(1), Type.Literal(2)]),
|
|
5943
|
+
discovery: Type.Optional(Type.Object({
|
|
5944
|
+
audiences: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
5945
|
+
certificationUrl: Type.Optional(Type.String()),
|
|
5946
|
+
intents: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
5947
|
+
keywords: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
5948
|
+
protocols: Type.Optional(Type.Array(Type.String({ minLength: 1 }))),
|
|
5949
|
+
url: Type.Optional(Type.String())
|
|
5950
|
+
})),
|
|
5889
5951
|
identity: Type.Object({
|
|
5890
5952
|
accent: Type.Optional(Type.String({ pattern: "^#[0-9a-fA-F]{3,8}$" })),
|
|
5891
5953
|
category: Type.String({ minLength: 1 }),
|
|
@@ -5895,7 +5957,9 @@ var manifestSchema = Type.Object({
|
|
|
5895
5957
|
svg: Type.Optional(Type.String()),
|
|
5896
5958
|
url: Type.Optional(Type.String())
|
|
5897
5959
|
})),
|
|
5898
|
-
name: Type.String({
|
|
5960
|
+
name: Type.String({
|
|
5961
|
+
pattern: "^(@[a-z0-9-~][a-z0-9-._~]*/)?[a-z0-9-~][a-z0-9-._~]*$"
|
|
5962
|
+
}),
|
|
5899
5963
|
tagline: Type.String({ minLength: 1 })
|
|
5900
5964
|
}),
|
|
5901
5965
|
implements: Type.Optional(Type.Array(adapterImplementation)),
|
|
@@ -5917,7 +5981,7 @@ var manifestSchema = Type.Object({
|
|
|
5917
5981
|
import { Type as Type2 } from "@sinclair/typebox";
|
|
5918
5982
|
var tool = toolFactory();
|
|
5919
5983
|
var manifest = defineManifest()({
|
|
5920
|
-
contract:
|
|
5984
|
+
contract: 2,
|
|
5921
5985
|
identity: {
|
|
5922
5986
|
accent: "#8b5cf6",
|
|
5923
5987
|
category: "ai",
|
|
@@ -5926,19 +5990,80 @@ var manifest = defineManifest()({
|
|
|
5926
5990
|
name: "@absolutejs/artifacts",
|
|
5927
5991
|
tagline: "Give everything your AI makes a real lifecycle."
|
|
5928
5992
|
},
|
|
5993
|
+
implements: [
|
|
5994
|
+
defineImplementation()({
|
|
5995
|
+
contract: "artifacts/store",
|
|
5996
|
+
factory: "createMemoryArtifactStore",
|
|
5997
|
+
from: "@absolutejs/artifacts",
|
|
5998
|
+
title: "In memory (development only \u2014 history resets on restart)",
|
|
5999
|
+
wiring: {
|
|
6000
|
+
code: "createMemoryArtifactStore()",
|
|
6001
|
+
imports: [
|
|
6002
|
+
{
|
|
6003
|
+
from: "@absolutejs/artifacts",
|
|
6004
|
+
names: ["createMemoryArtifactStore"]
|
|
6005
|
+
}
|
|
6006
|
+
]
|
|
6007
|
+
}
|
|
6008
|
+
}),
|
|
6009
|
+
defineImplementation()({
|
|
6010
|
+
contract: "artifacts/store",
|
|
6011
|
+
factory: "createDrizzleArtifactStore",
|
|
6012
|
+
from: "@absolutejs/artifacts/drizzle",
|
|
6013
|
+
requires: {
|
|
6014
|
+
peers: [
|
|
6015
|
+
{
|
|
6016
|
+
name: "drizzle-orm",
|
|
6017
|
+
range: ">=1.0.0-rc.4 <2",
|
|
6018
|
+
reason: "Typed artifact revisions, indexing state, and transactional outbox persistence"
|
|
6019
|
+
}
|
|
6020
|
+
],
|
|
6021
|
+
services: [
|
|
6022
|
+
{
|
|
6023
|
+
description: "Artifact lifecycle and revision database",
|
|
6024
|
+
id: "postgres"
|
|
6025
|
+
}
|
|
6026
|
+
]
|
|
6027
|
+
},
|
|
6028
|
+
title: "Drizzle Postgres (production, including Neon)",
|
|
6029
|
+
wiring: {
|
|
6030
|
+
code: "createDrizzleArtifactStore({ db })",
|
|
6031
|
+
imports: [
|
|
6032
|
+
{
|
|
6033
|
+
from: "@absolutejs/artifacts/drizzle",
|
|
6034
|
+
names: ["createDrizzleArtifactStore"]
|
|
6035
|
+
}
|
|
6036
|
+
]
|
|
6037
|
+
}
|
|
6038
|
+
})
|
|
6039
|
+
],
|
|
5929
6040
|
settings: Type2.Object({}),
|
|
5930
6041
|
slots: {
|
|
5931
|
-
|
|
6042
|
+
store: {
|
|
5932
6043
|
configPath: "$self",
|
|
5933
|
-
contract: "artifacts/
|
|
5934
|
-
description: "
|
|
5935
|
-
known: [
|
|
6044
|
+
contract: "artifacts/store",
|
|
6045
|
+
description: "Where current artifacts, immutable revisions, indexing state, and transactional outbox events live",
|
|
6046
|
+
known: [
|
|
6047
|
+
"@absolutejs/artifacts#createMemoryArtifactStore",
|
|
6048
|
+
"@absolutejs/artifacts#drizzle"
|
|
6049
|
+
],
|
|
5936
6050
|
required: true
|
|
5937
6051
|
}
|
|
5938
6052
|
},
|
|
5939
6053
|
tools: {
|
|
5940
6054
|
artifact_get: tool.runtime({
|
|
5941
6055
|
annotations: { readOnlyHint: true },
|
|
6056
|
+
authorization: {
|
|
6057
|
+
approval: "never",
|
|
6058
|
+
audience: "owner",
|
|
6059
|
+
effects: ["read"],
|
|
6060
|
+
requiredScopes: ["artifacts:read"],
|
|
6061
|
+
resource: {
|
|
6062
|
+
idField: "artifactId",
|
|
6063
|
+
ownerIdField: "ownerId",
|
|
6064
|
+
type: "artifact"
|
|
6065
|
+
}
|
|
6066
|
+
},
|
|
5942
6067
|
description: "Open one artifact owned by a user.",
|
|
5943
6068
|
handler: async ({ artifactId, ownerId }, service) => JSON.stringify(await service.get(ownerId, artifactId)),
|
|
5944
6069
|
input: Type2.Object({
|
|
@@ -5948,6 +6073,13 @@ var manifest = defineManifest()({
|
|
|
5948
6073
|
}),
|
|
5949
6074
|
artifact_list: tool.runtime({
|
|
5950
6075
|
annotations: { readOnlyHint: true },
|
|
6076
|
+
authorization: {
|
|
6077
|
+
approval: "never",
|
|
6078
|
+
audience: "owner",
|
|
6079
|
+
effects: ["read"],
|
|
6080
|
+
requiredScopes: ["artifacts:read"],
|
|
6081
|
+
resource: { ownerIdField: "ownerId", type: "artifact" }
|
|
6082
|
+
},
|
|
5951
6083
|
description: "List artifacts owned by a user.",
|
|
5952
6084
|
handler: async ({ kind, ownerId }, service) => JSON.stringify(await service.list(ownerId, { kind })),
|
|
5953
6085
|
input: Type2.Object({
|
|
@@ -5957,6 +6089,17 @@ var manifest = defineManifest()({
|
|
|
5957
6089
|
}),
|
|
5958
6090
|
artifact_history: tool.runtime({
|
|
5959
6091
|
annotations: { readOnlyHint: true },
|
|
6092
|
+
authorization: {
|
|
6093
|
+
approval: "never",
|
|
6094
|
+
audience: "owner",
|
|
6095
|
+
effects: ["read"],
|
|
6096
|
+
requiredScopes: ["artifacts:read"],
|
|
6097
|
+
resource: {
|
|
6098
|
+
idField: "artifactId",
|
|
6099
|
+
ownerIdField: "ownerId",
|
|
6100
|
+
type: "artifact-revision"
|
|
6101
|
+
}
|
|
6102
|
+
},
|
|
5960
6103
|
description: "List immutable revisions of one artifact owned by a user.",
|
|
5961
6104
|
handler: async ({ artifactId, ownerId }, service) => JSON.stringify(await service.listRevisions(ownerId, artifactId)),
|
|
5962
6105
|
input: Type2.Object({
|
|
@@ -5965,6 +6108,19 @@ var manifest = defineManifest()({
|
|
|
5965
6108
|
})
|
|
5966
6109
|
}),
|
|
5967
6110
|
artifact_restore: tool.runtime({
|
|
6111
|
+
authorization: {
|
|
6112
|
+
approval: "policy",
|
|
6113
|
+
audience: "owner",
|
|
6114
|
+
effects: ["write"],
|
|
6115
|
+
idempotency: { mode: "host" },
|
|
6116
|
+
requiredScopes: ["artifacts:write"],
|
|
6117
|
+
resource: {
|
|
6118
|
+
idField: "artifactId",
|
|
6119
|
+
ownerIdField: "ownerId",
|
|
6120
|
+
type: "artifact-revision"
|
|
6121
|
+
},
|
|
6122
|
+
reversible: false
|
|
6123
|
+
},
|
|
5968
6124
|
description: "Restore an old artifact revision as a new private draft.",
|
|
5969
6125
|
handler: async ({ artifactId, ownerId, revision }, service) => JSON.stringify(await service.restore(ownerId, artifactId, revision)),
|
|
5970
6126
|
input: Type2.Object({
|
|
@@ -5988,7 +6144,7 @@ var manifest = defineManifest()({
|
|
|
5988
6144
|
"\t}",
|
|
5989
6145
|
"});",
|
|
5990
6146
|
"",
|
|
5991
|
-
"const artifactStore =
|
|
6147
|
+
"const artifactStore = ${slot.store};",
|
|
5992
6148
|
"const artifactService = createArtifactService({",
|
|
5993
6149
|
"\tregistry: artifactRegistry,",
|
|
5994
6150
|
"\tstore: artifactStore",
|
|
@@ -5998,11 +6154,7 @@ var manifest = defineManifest()({
|
|
|
5998
6154
|
imports: [
|
|
5999
6155
|
{
|
|
6000
6156
|
from: "@absolutejs/artifacts",
|
|
6001
|
-
names: [
|
|
6002
|
-
"createArtifactService",
|
|
6003
|
-
"createMemoryArtifactStore",
|
|
6004
|
-
"defineArtifactRegistry"
|
|
6005
|
-
]
|
|
6157
|
+
names: ["createArtifactService", "defineArtifactRegistry"]
|
|
6006
6158
|
},
|
|
6007
6159
|
{ from: "@sinclair/typebox", names: ["Type"] }
|
|
6008
6160
|
],
|