@treeseed/sdk 0.1.1 → 0.3.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 +97 -494
- package/dist/{src/cli-tools.d.ts → cli-tools.d.ts} +1 -1
- package/dist/cli-tools.js +5 -3
- package/dist/{src/content-store.d.ts → content-store.d.ts} +3 -2
- package/dist/content-store.js +52 -20
- package/dist/{src/d1-store.d.ts → d1-store.d.ts} +62 -1
- package/dist/d1-store.js +625 -65
- package/dist/field-aliases.d.ts +11 -0
- package/dist/field-aliases.js +41 -0
- package/dist/graph/build.d.ts +19 -0
- package/dist/graph/build.js +949 -0
- package/dist/graph/dsl.d.ts +2 -0
- package/dist/graph/dsl.js +243 -0
- package/dist/graph/query.d.ts +47 -0
- package/dist/graph/query.js +447 -0
- package/dist/graph/ranking.d.ts +3 -0
- package/dist/graph/ranking.js +483 -0
- package/dist/graph/schema.d.ts +142 -0
- package/dist/graph/schema.js +133 -0
- package/dist/graph.d.ts +52 -0
- package/dist/graph.js +133 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +90 -2
- package/dist/model-registry.d.ts +8 -0
- package/dist/model-registry.js +351 -25
- package/dist/operations/providers/default.d.ts +10 -0
- package/dist/operations/providers/default.js +514 -0
- package/dist/operations/runtime.d.ts +7 -0
- package/dist/operations/runtime.js +60 -0
- package/dist/operations/services/config-runtime.d.ts +269 -0
- package/dist/operations/services/config-runtime.js +1397 -0
- package/dist/operations/services/d1-migration.d.ts +6 -0
- package/dist/operations/services/d1-migration.js +89 -0
- package/dist/operations/services/deploy.d.ts +371 -0
- package/dist/operations/services/deploy.js +981 -0
- package/dist/operations/services/git-workflow.d.ts +49 -0
- package/dist/operations/services/git-workflow.js +218 -0
- package/dist/operations/services/github-automation.d.ts +156 -0
- package/dist/operations/services/github-automation.js +256 -0
- package/dist/operations/services/local-dev.d.ts +9 -0
- package/dist/operations/services/local-dev.js +106 -0
- package/dist/operations/services/mailpit-runtime.d.ts +4 -0
- package/dist/operations/services/mailpit-runtime.js +59 -0
- package/dist/operations/services/railway-deploy.d.ts +53 -0
- package/dist/operations/services/railway-deploy.js +123 -0
- package/dist/operations/services/runtime-paths.d.ts +19 -0
- package/dist/operations/services/runtime-paths.js +54 -0
- package/dist/operations/services/runtime-tools.d.ts +117 -0
- package/dist/operations/services/runtime-tools.js +358 -0
- package/dist/operations/services/save-deploy-preflight.d.ts +34 -0
- package/dist/operations/services/save-deploy-preflight.js +76 -0
- package/dist/operations/services/template-registry.d.ts +88 -0
- package/dist/operations/services/template-registry.js +407 -0
- package/dist/operations/services/watch-dev.d.ts +21 -0
- package/dist/operations/services/watch-dev.js +284 -0
- package/dist/operations/services/workspace-preflight.d.ts +40 -0
- package/dist/operations/services/workspace-preflight.js +165 -0
- package/dist/operations/services/workspace-save.d.ts +42 -0
- package/dist/operations/services/workspace-save.js +235 -0
- package/dist/operations/services/workspace-tools.d.ts +16 -0
- package/dist/operations/services/workspace-tools.js +270 -0
- package/dist/operations-registry.d.ts +5 -0
- package/dist/operations-registry.js +68 -0
- package/dist/operations-types.d.ts +71 -0
- package/dist/operations-types.js +17 -0
- package/dist/operations.d.ts +6 -0
- package/dist/operations.js +16 -0
- package/dist/platform/books-data.d.ts +1 -0
- package/dist/platform/books-data.js +1 -0
- package/dist/platform/contracts.d.ts +158 -0
- package/dist/platform/contracts.js +0 -0
- package/dist/platform/deploy/config.d.ts +4 -0
- package/dist/platform/deploy/config.js +222 -0
- package/dist/platform/deploy-config.d.ts +1 -0
- package/dist/platform/deploy-config.js +1 -0
- package/dist/platform/env.yaml +394 -0
- package/dist/platform/environment.d.ts +130 -0
- package/dist/platform/environment.js +331 -0
- package/dist/platform/plugin.d.ts +2 -0
- package/dist/platform/plugin.js +4 -0
- package/dist/platform/plugins/constants.d.ts +22 -0
- package/dist/platform/plugins/constants.js +29 -0
- package/dist/platform/plugins/plugin.d.ts +51 -0
- package/dist/platform/plugins/plugin.js +6 -0
- package/dist/platform/plugins/runtime.d.ts +35 -0
- package/dist/platform/plugins/runtime.js +142 -0
- package/dist/platform/plugins.d.ts +5 -0
- package/dist/platform/plugins.js +16 -0
- package/dist/platform/site-config-schema.js +1 -0
- package/dist/platform/tenant/config.d.ts +9 -0
- package/dist/platform/tenant/config.js +154 -0
- package/dist/platform/tenant/runtime-config.d.ts +4 -0
- package/dist/platform/tenant/runtime-config.js +20 -0
- package/dist/platform/tenant-config.d.ts +1 -0
- package/dist/platform/tenant-config.js +1 -0
- package/dist/platform/utils/books-data.d.ts +29 -0
- package/dist/platform/utils/books-data.js +82 -0
- package/dist/platform/utils/site-config-schema.js +321 -0
- package/dist/remote.d.ts +175 -0
- package/dist/remote.js +202 -0
- package/dist/runtime.js +50 -3
- package/dist/scripts/aggregate-book.js +121 -0
- package/dist/scripts/build-dist.js +57 -13
- package/dist/scripts/build-tenant-worker.js +36 -0
- package/dist/scripts/cleanup-markdown.js +373 -0
- package/dist/scripts/cli-test-fixtures.js +48 -0
- package/dist/scripts/config-treeseed.js +95 -0
- package/dist/scripts/ensure-mailpit.js +29 -0
- package/dist/scripts/local-dev.js +129 -0
- package/dist/scripts/logs-mailpit.js +2 -0
- package/dist/scripts/patch-starlight-content-path.js +172 -0
- package/dist/scripts/release-verify.js +34 -5
- package/dist/scripts/run-fixture-astro-command.js +18 -0
- package/dist/scripts/scaffold-site.js +65 -0
- package/dist/scripts/stop-mailpit.js +5 -0
- package/dist/scripts/sync-dev-vars.js +6 -0
- package/dist/scripts/sync-template.js +20 -0
- package/dist/scripts/template-catalog.test.js +100 -0
- package/dist/scripts/template-command.js +31 -0
- package/dist/scripts/tenant-astro-command.js +3 -0
- package/dist/scripts/tenant-build.js +16 -0
- package/dist/scripts/tenant-check.js +7 -0
- package/dist/scripts/tenant-d1-migrate-local.js +11 -0
- package/dist/scripts/tenant-deploy.js +180 -0
- package/dist/scripts/tenant-destroy.js +104 -0
- package/dist/scripts/tenant-dev.js +171 -0
- package/dist/scripts/tenant-lint.js +4 -0
- package/dist/scripts/tenant-test.js +4 -0
- package/dist/scripts/test-cloudflare-local.js +212 -0
- package/dist/scripts/test-scaffold.js +314 -0
- package/dist/scripts/test-smoke.js +71 -13
- package/dist/scripts/treeseed-assert-release-tag-version.js +21 -0
- package/dist/scripts/treeseed-build-dist.js +134 -0
- package/dist/scripts/treeseed-publish-package.js +19 -0
- package/dist/scripts/treeseed-release-verify.js +131 -0
- package/dist/scripts/treeseed-run-ts.js +45 -0
- package/dist/scripts/validate-templates.js +6 -0
- package/dist/scripts/verify-driver.js +29 -0
- package/dist/scripts/workflow-commands.test.js +39 -0
- package/dist/scripts/workspace-close.js +24 -0
- package/dist/scripts/workspace-command-e2e.js +718 -0
- package/dist/scripts/workspace-lint.js +9 -0
- package/dist/scripts/workspace-preflight.js +22 -0
- package/dist/scripts/workspace-publish-changed-packages.js +16 -0
- package/dist/scripts/workspace-release-verify.js +81 -0
- package/dist/scripts/workspace-release.js +42 -0
- package/dist/scripts/workspace-save.js +124 -0
- package/dist/scripts/workspace-start-warning.js +3 -0
- package/dist/scripts/workspace-start.js +71 -0
- package/dist/scripts/workspace-test-unit.js +4 -0
- package/dist/scripts/workspace-test.js +11 -0
- package/dist/sdk-fields.d.ts +11 -0
- package/dist/sdk-fields.js +169 -0
- package/dist/sdk-filters.d.ts +4 -0
- package/dist/sdk-filters.js +12 -15
- package/dist/sdk-types.d.ts +796 -0
- package/dist/sdk-types.js +7 -1
- package/dist/sdk-version.d.ts +2 -0
- package/dist/sdk-version.js +42 -0
- package/dist/sdk.d.ts +215 -0
- package/dist/sdk.js +235 -11
- package/dist/stores/cursor-store.js +9 -3
- package/dist/stores/lease-store.js +8 -2
- package/dist/{src/stores → stores}/message-store.d.ts +1 -1
- package/dist/stores/message-store.js +27 -3
- package/dist/stores/operational-store.d.ts +24 -0
- package/dist/stores/operational-store.js +279 -0
- package/dist/stores/run-store.js +8 -1
- package/dist/stores/subscription-store.js +7 -5
- package/dist/template-catalog.d.ts +13 -0
- package/dist/template-catalog.js +141 -0
- package/dist/treeseed/services/compose.yml +7 -0
- package/dist/treeseed/template-catalog/catalog.fixture.json +55 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +2 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +3 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +32 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +40 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +1 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +11 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +11 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +1 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +3 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +1 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +19 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +26 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +9 -0
- package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +90 -0
- package/dist/verification.d.ts +20 -0
- package/dist/verification.js +98 -0
- package/dist/workflow/operations.d.ts +396 -0
- package/dist/workflow/operations.js +841 -0
- package/dist/workflow-state.d.ts +56 -0
- package/dist/workflow-state.js +195 -0
- package/dist/workflow-support.d.ts +9 -0
- package/dist/workflow-support.js +176 -0
- package/dist/workflow.d.ts +111 -0
- package/dist/workflow.js +97 -0
- package/package.json +97 -5
- package/scripts/verify-driver.mjs +29 -0
- package/dist/scripts/.ts-run-1775616845195-odh4xzphk3l.js +0 -22
- package/dist/scripts/.ts-run-1775616848931-9386s6kwrl.js +0 -126
- package/dist/scripts/assert-release-tag-version.d.ts +0 -1
- package/dist/scripts/build-dist.d.ts +0 -1
- package/dist/scripts/package-tools.d.ts +0 -15
- package/dist/scripts/publish-package.d.ts +0 -1
- package/dist/scripts/release-verify.d.ts +0 -1
- package/dist/scripts/test-smoke.d.ts +0 -1
- package/dist/src/index.d.ts +0 -6
- package/dist/src/model-registry.d.ts +0 -4
- package/dist/src/sdk-filters.d.ts +0 -4
- package/dist/src/sdk-types.d.ts +0 -285
- package/dist/src/sdk.d.ts +0 -109
- package/dist/test/test-fixture.d.ts +0 -1
- package/dist/test/utils/envelopes.test.d.ts +0 -1
- package/dist/test/utils/sdk.test.d.ts +0 -1
- package/dist/vitest.config.d.ts +0 -2
- /package/dist/{src/frontmatter.d.ts → frontmatter.d.ts} +0 -0
- /package/dist/{src/git-runtime.d.ts → git-runtime.d.ts} +0 -0
- /package/dist/{src/runtime.d.ts → runtime.d.ts} +0 -0
- /package/dist/{src/stores → stores}/cursor-store.d.ts +0 -0
- /package/dist/{src/stores → stores}/envelopes.d.ts +0 -0
- /package/dist/{src/stores → stores}/helpers.d.ts +0 -0
- /package/dist/{src/stores → stores}/lease-store.d.ts +0 -0
- /package/dist/{src/stores → stores}/run-store.d.ts +0 -0
- /package/dist/{src/stores → stores}/subscription-store.d.ts +0 -0
- /package/dist/{src/types → types}/agents.d.ts +0 -0
- /package/dist/{src/types → types}/cloudflare.d.ts +0 -0
- /package/dist/{src/wrangler-d1.d.ts → wrangler-d1.d.ts} +0 -0
package/dist/d1-store.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import crypto from "node:crypto";
|
|
2
2
|
import { applyFilters, applySort } from "./sdk-filters.js";
|
|
3
|
+
import { normalizeFilterFields, normalizeMutationData, normalizeRecordToCanonicalShape, normalizeSortFields } from "./sdk-fields.js";
|
|
4
|
+
import { assertExpectedVersion } from "./sdk-version.js";
|
|
5
|
+
import { resolveModelDefinition } from "./model-registry.js";
|
|
3
6
|
import { CursorStore } from "./stores/cursor-store.js";
|
|
4
7
|
import { LeaseStore } from "./stores/lease-store.js";
|
|
5
8
|
import { MessageStore } from "./stores/message-store.js";
|
|
9
|
+
import { OperationalStore } from "./stores/operational-store.js";
|
|
6
10
|
import { RunStore } from "./stores/run-store.js";
|
|
7
11
|
import { SubscriptionStore } from "./stores/subscription-store.js";
|
|
8
12
|
function nowIso() {
|
|
@@ -11,6 +15,16 @@ function nowIso() {
|
|
|
11
15
|
function nextLeaseToken() {
|
|
12
16
|
return crypto.randomUUID();
|
|
13
17
|
}
|
|
18
|
+
function pickSortForRequest(request, defaultField) {
|
|
19
|
+
switch (request.strategy) {
|
|
20
|
+
case "oldest":
|
|
21
|
+
return [{ field: defaultField, direction: "asc" }];
|
|
22
|
+
case "highest_priority":
|
|
23
|
+
case "latest":
|
|
24
|
+
default:
|
|
25
|
+
return [{ field: defaultField, direction: "desc" }];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
14
28
|
function filterSinceField(model) {
|
|
15
29
|
switch (model) {
|
|
16
30
|
case "message":
|
|
@@ -32,6 +46,12 @@ class MemoryAgentDatabase {
|
|
|
32
46
|
runs = /* @__PURE__ */ new Map();
|
|
33
47
|
contentLeases = /* @__PURE__ */ new Map();
|
|
34
48
|
cursors = /* @__PURE__ */ new Map();
|
|
49
|
+
workDays = /* @__PURE__ */ new Map();
|
|
50
|
+
tasks = /* @__PURE__ */ new Map();
|
|
51
|
+
taskEvents = /* @__PURE__ */ new Map();
|
|
52
|
+
taskOutputs = /* @__PURE__ */ new Map();
|
|
53
|
+
graphRuns = /* @__PURE__ */ new Map();
|
|
54
|
+
reports = /* @__PURE__ */ new Map();
|
|
35
55
|
messageId = 0;
|
|
36
56
|
constructor(seed) {
|
|
37
57
|
for (const item of seed?.subscriptions ?? []) {
|
|
@@ -82,6 +102,18 @@ class MemoryAgentDatabase {
|
|
|
82
102
|
token: lease.token
|
|
83
103
|
}));
|
|
84
104
|
}
|
|
105
|
+
if (model === "work_day") {
|
|
106
|
+
return [...this.workDays.values()];
|
|
107
|
+
}
|
|
108
|
+
if (model === "task") {
|
|
109
|
+
return [...this.tasks.values()];
|
|
110
|
+
}
|
|
111
|
+
if (model === "graph_run") {
|
|
112
|
+
return [...this.graphRuns.values()];
|
|
113
|
+
}
|
|
114
|
+
if (model === "report") {
|
|
115
|
+
return [...this.reports.values()];
|
|
116
|
+
}
|
|
85
117
|
throw new Error(`Unsupported D1 model "${model}".`);
|
|
86
118
|
}
|
|
87
119
|
async get(request) {
|
|
@@ -110,13 +142,29 @@ class MemoryAgentDatabase {
|
|
|
110
142
|
token: lease.token
|
|
111
143
|
} : null;
|
|
112
144
|
}
|
|
145
|
+
if (request.model === "work_day") {
|
|
146
|
+
return this.workDays.get(key) ?? null;
|
|
147
|
+
}
|
|
148
|
+
if (request.model === "task") {
|
|
149
|
+
return this.tasks.get(key) ?? null;
|
|
150
|
+
}
|
|
151
|
+
if (request.model === "graph_run") {
|
|
152
|
+
return this.graphRuns.get(key) ?? null;
|
|
153
|
+
}
|
|
154
|
+
if (request.model === "report") {
|
|
155
|
+
return this.reports.get(key) ?? null;
|
|
156
|
+
}
|
|
113
157
|
return this.rowsForModel(request.model).find(
|
|
114
158
|
(row) => [row.id, row.email, row.runId].map((value) => String(value ?? "")).includes(key)
|
|
115
159
|
) ?? null;
|
|
116
160
|
}
|
|
117
161
|
async search(request) {
|
|
118
|
-
const
|
|
119
|
-
const
|
|
162
|
+
const definition = resolveModelDefinition(request.model);
|
|
163
|
+
const rows = this.rowsForModel(request.model).map(
|
|
164
|
+
(row) => normalizeRecordToCanonicalShape(definition, row)
|
|
165
|
+
);
|
|
166
|
+
const filtered = applyFilters(rows, normalizeFilterFields(definition, request.filters), definition);
|
|
167
|
+
const sorted = applySort(filtered, normalizeSortFields(definition, request.sort), definition);
|
|
120
168
|
return sorted.slice(0, request.limit ?? sorted.length);
|
|
121
169
|
}
|
|
122
170
|
async follow(request) {
|
|
@@ -138,14 +186,35 @@ class MemoryAgentDatabase {
|
|
|
138
186
|
}
|
|
139
187
|
async pick(request) {
|
|
140
188
|
if (request.model === "message") {
|
|
141
|
-
const
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
189
|
+
const candidates = [...this.messages.values()].filter(
|
|
190
|
+
(message) => (message.status === "pending" || message.status === "failed") && new Date(message.availableAt).valueOf() <= Date.now() && (!request.filters?.filter((filter) => filter.field === "type" && filter.op === "in").flatMap((filter) => Array.isArray(filter.value) ? filter.value.map(String) : []).length || request.filters.filter((filter) => filter.field === "type" && filter.op === "in").flatMap((filter) => Array.isArray(filter.value) ? filter.value.map(String) : []).includes(message.type))
|
|
191
|
+
).sort((left, right) => {
|
|
192
|
+
if (request.strategy === "oldest") {
|
|
193
|
+
return left.availableAt.localeCompare(right.availableAt) || right.priority - left.priority;
|
|
194
|
+
}
|
|
195
|
+
if (request.strategy === "latest") {
|
|
196
|
+
return right.availableAt.localeCompare(left.availableAt) || right.priority - left.priority;
|
|
197
|
+
}
|
|
198
|
+
return right.priority - left.priority || left.availableAt.localeCompare(right.availableAt);
|
|
145
199
|
});
|
|
200
|
+
const pending = candidates[0];
|
|
201
|
+
if (!pending) {
|
|
202
|
+
return { item: null, leaseToken: null };
|
|
203
|
+
}
|
|
204
|
+
const claimedAt = nowIso();
|
|
205
|
+
const next = {
|
|
206
|
+
...pending,
|
|
207
|
+
status: "claimed",
|
|
208
|
+
claimedBy: request.workerId,
|
|
209
|
+
claimedAt,
|
|
210
|
+
leaseExpiresAt: new Date(Date.now() + request.leaseSeconds * 1e3).toISOString(),
|
|
211
|
+
attempts: pending.attempts + 1,
|
|
212
|
+
updatedAt: claimedAt
|
|
213
|
+
};
|
|
214
|
+
this.messages.set(next.id, next);
|
|
146
215
|
return {
|
|
147
|
-
item,
|
|
148
|
-
leaseToken:
|
|
216
|
+
item: next,
|
|
217
|
+
leaseToken: nextLeaseToken()
|
|
149
218
|
};
|
|
150
219
|
}
|
|
151
220
|
if (request.model === "content_lease") {
|
|
@@ -163,7 +232,7 @@ class MemoryAgentDatabase {
|
|
|
163
232
|
const items = await this.search({
|
|
164
233
|
model: request.model,
|
|
165
234
|
filters: request.filters,
|
|
166
|
-
sort:
|
|
235
|
+
sort: pickSortForRequest(request, filterSinceField(request.model))
|
|
167
236
|
});
|
|
168
237
|
return {
|
|
169
238
|
item: items[0] ?? null,
|
|
@@ -171,38 +240,40 @@ class MemoryAgentDatabase {
|
|
|
171
240
|
};
|
|
172
241
|
}
|
|
173
242
|
async create(request) {
|
|
243
|
+
const definition = resolveModelDefinition(request.model);
|
|
244
|
+
const data = normalizeMutationData(definition, request.data);
|
|
174
245
|
switch (request.model) {
|
|
175
246
|
case "message":
|
|
176
247
|
return await this.createMessage({
|
|
177
|
-
type: String(
|
|
178
|
-
payload:
|
|
179
|
-
relatedModel: typeof
|
|
180
|
-
relatedId: typeof
|
|
181
|
-
priority: Number(
|
|
182
|
-
maxAttempts: Number(
|
|
248
|
+
type: String(data.type ?? "message.created"),
|
|
249
|
+
payload: data.payload ?? data,
|
|
250
|
+
relatedModel: typeof data.related_model === "string" ? data.related_model : null,
|
|
251
|
+
relatedId: typeof data.related_id === "string" ? data.related_id : null,
|
|
252
|
+
priority: Number(data.priority ?? 0),
|
|
253
|
+
maxAttempts: Number(data.maxAttempts ?? 3),
|
|
183
254
|
actor: request.actor
|
|
184
255
|
});
|
|
185
256
|
case "subscription": {
|
|
186
257
|
const record = {
|
|
187
258
|
id: this.subscriptions.size + 1,
|
|
188
|
-
email: String(
|
|
189
|
-
name:
|
|
190
|
-
status: String(
|
|
191
|
-
source: String(
|
|
192
|
-
consent_at: String(
|
|
193
|
-
created_at: String(
|
|
194
|
-
updated_at: String(
|
|
195
|
-
ip_hash: String(
|
|
259
|
+
email: String(data.email ?? ""),
|
|
260
|
+
name: data.name ? String(data.name) : null,
|
|
261
|
+
status: String(data.status ?? "active"),
|
|
262
|
+
source: String(data.source ?? "sdk"),
|
|
263
|
+
consent_at: String(data.consent_at ?? nowIso()),
|
|
264
|
+
created_at: String(data.created_at ?? nowIso()),
|
|
265
|
+
updated_at: String(data.updated_at ?? nowIso()),
|
|
266
|
+
ip_hash: String(data.ip_hash ?? "")
|
|
196
267
|
};
|
|
197
268
|
this.subscriptions.set(String(record.id), record);
|
|
198
269
|
return record;
|
|
199
270
|
}
|
|
200
271
|
case "agent_run":
|
|
201
|
-
return this.recordRun({ run:
|
|
272
|
+
return this.recordRun({ run: data });
|
|
202
273
|
case "agent_cursor": {
|
|
203
|
-
const agentSlug = String(
|
|
204
|
-
const cursorKey = String(
|
|
205
|
-
const cursorValue = String(
|
|
274
|
+
const agentSlug = String(data.agent_slug ?? "");
|
|
275
|
+
const cursorKey = String(data.cursor_key ?? "");
|
|
276
|
+
const cursorValue = String(data.cursor_value ?? "");
|
|
206
277
|
this.cursors.set(`${agentSlug}:${cursorKey}`, cursorValue);
|
|
207
278
|
return {
|
|
208
279
|
agentSlug,
|
|
@@ -213,68 +284,182 @@ class MemoryAgentDatabase {
|
|
|
213
284
|
}
|
|
214
285
|
case "content_lease": {
|
|
215
286
|
const token = await this.tryClaimContentLease({
|
|
216
|
-
model: String(
|
|
217
|
-
itemKey: String(
|
|
218
|
-
claimedBy: String(
|
|
219
|
-
leaseSeconds: Number(
|
|
287
|
+
model: String(data.model ?? ""),
|
|
288
|
+
itemKey: String(data.item_key ?? ""),
|
|
289
|
+
claimedBy: String(data.claimed_by ?? request.actor),
|
|
290
|
+
leaseSeconds: Number(data.leaseSeconds ?? 300)
|
|
220
291
|
});
|
|
221
|
-
const lease = this.contentLeases.get(`${
|
|
292
|
+
const lease = this.contentLeases.get(`${data.model}:${data.item_key}`);
|
|
222
293
|
return {
|
|
223
|
-
model: String(
|
|
224
|
-
itemKey: String(
|
|
225
|
-
claimedBy: String(
|
|
294
|
+
model: String(data.model ?? ""),
|
|
295
|
+
itemKey: String(data.item_key ?? ""),
|
|
296
|
+
claimedBy: String(data.claimed_by ?? request.actor),
|
|
226
297
|
claimedAt: String(lease?.claimedAt ?? nowIso()),
|
|
227
298
|
leaseExpiresAt: String(lease?.leaseExpiresAt ?? nowIso()),
|
|
228
299
|
token: String(token ?? lease?.token ?? "")
|
|
229
300
|
};
|
|
230
301
|
}
|
|
302
|
+
case "work_day":
|
|
303
|
+
return this.startWorkDay({
|
|
304
|
+
id: typeof data.id === "string" ? data.id : void 0,
|
|
305
|
+
projectId: String(data.projectId ?? data.project_id ?? ""),
|
|
306
|
+
capacityBudget: Number(data.capacityBudget ?? data.capacity_budget ?? 0),
|
|
307
|
+
graphVersion: typeof (data.graphVersion ?? data.graph_version) === "string" ? String(data.graphVersion ?? data.graph_version) : null,
|
|
308
|
+
summary: data.summary ?? null,
|
|
309
|
+
actor: request.actor
|
|
310
|
+
});
|
|
311
|
+
case "task":
|
|
312
|
+
return this.createTask({
|
|
313
|
+
id: typeof data.id === "string" ? data.id : void 0,
|
|
314
|
+
workDayId: String(data.workDayId ?? data.work_day_id ?? ""),
|
|
315
|
+
agentId: String(data.agentId ?? data.agent_id ?? ""),
|
|
316
|
+
type: String(data.type ?? ""),
|
|
317
|
+
state: typeof data.state === "string" ? data.state : "pending",
|
|
318
|
+
priority: Number(data.priority ?? 0),
|
|
319
|
+
idempotencyKey: String(data.idempotencyKey ?? data.idempotency_key ?? ""),
|
|
320
|
+
payload: data.payload ?? data,
|
|
321
|
+
payloadHash: typeof (data.payloadHash ?? data.payload_hash) === "string" ? String(data.payloadHash ?? data.payload_hash) : null,
|
|
322
|
+
maxAttempts: Number(data.maxAttempts ?? data.max_attempts ?? 3),
|
|
323
|
+
availableAt: typeof (data.availableAt ?? data.available_at) === "string" ? String(data.availableAt ?? data.available_at) : void 0,
|
|
324
|
+
graphVersion: typeof (data.graphVersion ?? data.graph_version) === "string" ? String(data.graphVersion ?? data.graph_version) : null,
|
|
325
|
+
parentTaskId: typeof (data.parentTaskId ?? data.parent_task_id) === "string" ? String(data.parentTaskId ?? data.parent_task_id) : null,
|
|
326
|
+
actor: request.actor
|
|
327
|
+
});
|
|
328
|
+
case "graph_run": {
|
|
329
|
+
const record = {
|
|
330
|
+
id: String(data.id ?? crypto.randomUUID()),
|
|
331
|
+
workDayId: String(data.workDayId ?? data.work_day_id ?? ""),
|
|
332
|
+
corpusHash: String(data.corpusHash ?? data.corpus_hash ?? ""),
|
|
333
|
+
graphVersion: String(data.graphVersion ?? data.graph_version ?? ""),
|
|
334
|
+
queryJson: typeof (data.queryJson ?? data.query_json) === "string" ? String(data.queryJson ?? data.query_json) : null,
|
|
335
|
+
seedIdsJson: typeof (data.seedIdsJson ?? data.seed_ids_json) === "string" ? String(data.seedIdsJson ?? data.seed_ids_json) : null,
|
|
336
|
+
selectedNodeIdsJson: typeof (data.selectedNodeIdsJson ?? data.selected_node_ids_json) === "string" ? String(data.selectedNodeIdsJson ?? data.selected_node_ids_json) : null,
|
|
337
|
+
statsJson: typeof (data.statsJson ?? data.stats_json) === "string" ? String(data.statsJson ?? data.stats_json) : null,
|
|
338
|
+
snapshotRef: typeof (data.snapshotRef ?? data.snapshot_ref) === "string" ? String(data.snapshotRef ?? data.snapshot_ref) : null,
|
|
339
|
+
createdAt: String(data.createdAt ?? data.created_at ?? nowIso())
|
|
340
|
+
};
|
|
341
|
+
this.graphRuns.set(record.id, record);
|
|
342
|
+
return record;
|
|
343
|
+
}
|
|
344
|
+
case "report":
|
|
345
|
+
return this.createReport({
|
|
346
|
+
id: typeof data.id === "string" ? data.id : void 0,
|
|
347
|
+
workDayId: String(data.workDayId ?? data.work_day_id ?? ""),
|
|
348
|
+
kind: String(data.kind ?? "workday_summary"),
|
|
349
|
+
body: data.body ?? data,
|
|
350
|
+
renderedRef: typeof (data.renderedRef ?? data.rendered_ref) === "string" ? String(data.renderedRef ?? data.rendered_ref) : null,
|
|
351
|
+
sentAt: typeof (data.sentAt ?? data.sent_at) === "string" ? String(data.sentAt ?? data.sent_at) : null,
|
|
352
|
+
actor: request.actor
|
|
353
|
+
});
|
|
231
354
|
default:
|
|
232
355
|
throw new Error(`Unsupported D1 create model "${request.model}".`);
|
|
233
356
|
}
|
|
234
357
|
}
|
|
235
358
|
async update(request) {
|
|
359
|
+
const definition = resolveModelDefinition(request.model);
|
|
360
|
+
const data = normalizeMutationData(definition, request.data);
|
|
236
361
|
switch (request.model) {
|
|
237
362
|
case "message": {
|
|
238
|
-
const current = this.messages.get(Number(request.id ?? request.key ??
|
|
363
|
+
const current = this.messages.get(Number(request.id ?? request.key ?? data.id ?? 0));
|
|
239
364
|
if (!current) {
|
|
240
365
|
return null;
|
|
241
366
|
}
|
|
367
|
+
assertExpectedVersion(request.expectedVersion, current, `message ${current.id}`);
|
|
242
368
|
const next = {
|
|
243
369
|
...current,
|
|
244
|
-
...
|
|
370
|
+
...data,
|
|
245
371
|
updatedAt: nowIso()
|
|
246
372
|
};
|
|
247
373
|
this.messages.set(next.id, next);
|
|
248
374
|
return next;
|
|
249
375
|
}
|
|
250
376
|
case "subscription": {
|
|
251
|
-
const key = String(request.id ?? request.key ??
|
|
377
|
+
const key = String(request.id ?? request.key ?? data.email ?? "");
|
|
252
378
|
const current = await this.get({ model: "subscription", key });
|
|
253
379
|
if (!current) {
|
|
254
380
|
return null;
|
|
255
381
|
}
|
|
382
|
+
assertExpectedVersion(request.expectedVersion, current, `subscription "${current.email}"`);
|
|
256
383
|
const next = {
|
|
257
384
|
...current,
|
|
258
|
-
...
|
|
385
|
+
...data,
|
|
259
386
|
updated_at: nowIso()
|
|
260
387
|
};
|
|
261
388
|
this.subscriptions.set(String(next.id ?? next.email), next);
|
|
262
389
|
return next;
|
|
263
390
|
}
|
|
264
391
|
case "agent_run":
|
|
265
|
-
|
|
392
|
+
assertExpectedVersion(
|
|
393
|
+
request.expectedVersion,
|
|
394
|
+
await this.get({ model: "agent_run", key: String(request.id ?? request.key ?? data.run_id ?? "") }),
|
|
395
|
+
`agent_run "${String(request.id ?? request.key ?? data.run_id ?? "")}"`
|
|
396
|
+
);
|
|
397
|
+
return this.recordRun({ run: { ...data, runId: request.id ?? request.key ?? data.run_id } });
|
|
266
398
|
case "agent_cursor":
|
|
399
|
+
assertExpectedVersion(
|
|
400
|
+
request.expectedVersion,
|
|
401
|
+
await this.get({
|
|
402
|
+
model: "agent_cursor",
|
|
403
|
+
key: `${String(data.agent_slug ?? request.id ?? request.key ?? "")}:${String(data.cursor_key ?? request.slug ?? "")}`
|
|
404
|
+
}),
|
|
405
|
+
`agent_cursor "${String(data.agent_slug ?? request.id ?? request.key ?? "")}:${String(data.cursor_key ?? request.slug ?? "")}"`
|
|
406
|
+
);
|
|
267
407
|
return this.create({
|
|
268
408
|
model: "agent_cursor",
|
|
269
|
-
data
|
|
409
|
+
data,
|
|
270
410
|
actor: request.actor
|
|
271
411
|
});
|
|
272
412
|
case "content_lease":
|
|
413
|
+
assertExpectedVersion(
|
|
414
|
+
request.expectedVersion,
|
|
415
|
+
await this.get({
|
|
416
|
+
model: "content_lease",
|
|
417
|
+
key: `${String(data.model ?? request.id ?? "")}:${String(data.item_key ?? request.slug ?? request.key ?? "")}`
|
|
418
|
+
}),
|
|
419
|
+
`content_lease "${String(data.model ?? request.id ?? "")}:${String(data.item_key ?? request.slug ?? request.key ?? "")}"`
|
|
420
|
+
);
|
|
273
421
|
return this.create({
|
|
274
422
|
model: "content_lease",
|
|
275
|
-
data
|
|
423
|
+
data,
|
|
276
424
|
actor: request.actor
|
|
277
425
|
});
|
|
426
|
+
case "work_day":
|
|
427
|
+
return this.closeWorkDay({
|
|
428
|
+
id: String(request.id ?? request.key ?? data.id ?? ""),
|
|
429
|
+
state: data.state ?? "completed",
|
|
430
|
+
summary: data.summary ?? null,
|
|
431
|
+
actor: request.actor
|
|
432
|
+
});
|
|
433
|
+
case "task": {
|
|
434
|
+
const taskId = String(request.id ?? request.key ?? data.id ?? "");
|
|
435
|
+
if (data.state === "completed") {
|
|
436
|
+
return this.completeTask({
|
|
437
|
+
id: taskId,
|
|
438
|
+
output: data.output ?? null,
|
|
439
|
+
outputRef: typeof data.outputRef === "string" ? data.outputRef : null,
|
|
440
|
+
summary: data.summary ?? null,
|
|
441
|
+
actor: request.actor
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
if (data.state === "failed") {
|
|
445
|
+
return this.failTask({
|
|
446
|
+
id: taskId,
|
|
447
|
+
errorCode: typeof data.errorCode === "string" ? data.errorCode : null,
|
|
448
|
+
errorMessage: String(data.errorMessage ?? "Task failed"),
|
|
449
|
+
retryable: Boolean(data.retryable),
|
|
450
|
+
nextVisibleAt: typeof data.nextVisibleAt === "string" ? data.nextVisibleAt : null,
|
|
451
|
+
actor: request.actor
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
return this.recordTaskProgress({
|
|
455
|
+
id: taskId,
|
|
456
|
+
workerId: typeof data.workerId === "string" ? data.workerId : null,
|
|
457
|
+
state: typeof data.state === "string" ? data.state : void 0,
|
|
458
|
+
appendEvent: data.appendEvent,
|
|
459
|
+
patch: data.patch ?? void 0,
|
|
460
|
+
actor: request.actor
|
|
461
|
+
});
|
|
462
|
+
}
|
|
278
463
|
default:
|
|
279
464
|
throw new Error(`Unsupported D1 update model "${request.model}".`);
|
|
280
465
|
}
|
|
@@ -374,6 +559,197 @@ class MemoryAgentDatabase {
|
|
|
374
559
|
inspectLeases() {
|
|
375
560
|
return [...this.contentLeases.values()];
|
|
376
561
|
}
|
|
562
|
+
async startWorkDay(request) {
|
|
563
|
+
const timestamp = nowIso();
|
|
564
|
+
const record = {
|
|
565
|
+
id: request.id ?? crypto.randomUUID(),
|
|
566
|
+
projectId: request.projectId,
|
|
567
|
+
state: "active",
|
|
568
|
+
capacityBudget: Number(request.capacityBudget ?? 0),
|
|
569
|
+
capacityUsed: 0,
|
|
570
|
+
graphVersion: request.graphVersion ?? null,
|
|
571
|
+
summaryJson: request.summary ? JSON.stringify(request.summary) : null,
|
|
572
|
+
startedAt: timestamp,
|
|
573
|
+
endedAt: null,
|
|
574
|
+
createdAt: timestamp,
|
|
575
|
+
updatedAt: timestamp
|
|
576
|
+
};
|
|
577
|
+
this.workDays.set(record.id, record);
|
|
578
|
+
return record;
|
|
579
|
+
}
|
|
580
|
+
async closeWorkDay(request) {
|
|
581
|
+
const existing = this.workDays.get(request.id);
|
|
582
|
+
if (!existing) return null;
|
|
583
|
+
const next = {
|
|
584
|
+
...existing,
|
|
585
|
+
state: request.state ?? "completed",
|
|
586
|
+
summaryJson: request.summary ? JSON.stringify(request.summary) : existing.summaryJson,
|
|
587
|
+
endedAt: nowIso(),
|
|
588
|
+
updatedAt: nowIso()
|
|
589
|
+
};
|
|
590
|
+
this.workDays.set(next.id, next);
|
|
591
|
+
return next;
|
|
592
|
+
}
|
|
593
|
+
async createTask(request) {
|
|
594
|
+
const timestamp = nowIso();
|
|
595
|
+
const record = {
|
|
596
|
+
id: request.id ?? crypto.randomUUID(),
|
|
597
|
+
workDayId: request.workDayId,
|
|
598
|
+
agentId: request.agentId,
|
|
599
|
+
type: request.type,
|
|
600
|
+
state: request.state ?? "pending",
|
|
601
|
+
priority: Number(request.priority ?? 0),
|
|
602
|
+
idempotencyKey: request.idempotencyKey,
|
|
603
|
+
payloadJson: JSON.stringify(request.payload),
|
|
604
|
+
payloadHash: request.payloadHash ?? null,
|
|
605
|
+
attemptCount: 0,
|
|
606
|
+
maxAttempts: Number(request.maxAttempts ?? 3),
|
|
607
|
+
claimedBy: null,
|
|
608
|
+
leaseExpiresAt: null,
|
|
609
|
+
availableAt: request.availableAt ?? timestamp,
|
|
610
|
+
lastErrorCode: null,
|
|
611
|
+
lastErrorMessage: null,
|
|
612
|
+
graphVersion: request.graphVersion ?? null,
|
|
613
|
+
parentTaskId: request.parentTaskId ?? null,
|
|
614
|
+
createdAt: timestamp,
|
|
615
|
+
startedAt: null,
|
|
616
|
+
completedAt: null,
|
|
617
|
+
updatedAt: timestamp
|
|
618
|
+
};
|
|
619
|
+
this.tasks.set(record.id, record);
|
|
620
|
+
return record;
|
|
621
|
+
}
|
|
622
|
+
async claimTask(request) {
|
|
623
|
+
const existing = this.tasks.get(request.id);
|
|
624
|
+
if (!existing) return null;
|
|
625
|
+
const next = {
|
|
626
|
+
...existing,
|
|
627
|
+
state: "claimed",
|
|
628
|
+
claimedBy: request.workerId,
|
|
629
|
+
leaseExpiresAt: new Date(Date.now() + request.leaseSeconds * 1e3).toISOString(),
|
|
630
|
+
attemptCount: existing.attemptCount + 1,
|
|
631
|
+
startedAt: existing.startedAt ?? nowIso(),
|
|
632
|
+
updatedAt: nowIso()
|
|
633
|
+
};
|
|
634
|
+
this.tasks.set(next.id, next);
|
|
635
|
+
return next;
|
|
636
|
+
}
|
|
637
|
+
async recordTaskProgress(request) {
|
|
638
|
+
const existing = this.tasks.get(request.id);
|
|
639
|
+
if (!existing) return null;
|
|
640
|
+
const nextPayload = {
|
|
641
|
+
...JSON.parse(existing.payloadJson),
|
|
642
|
+
...request.patch ?? {}
|
|
643
|
+
};
|
|
644
|
+
const next = {
|
|
645
|
+
...existing,
|
|
646
|
+
state: request.state ?? existing.state,
|
|
647
|
+
claimedBy: request.workerId ?? existing.claimedBy,
|
|
648
|
+
payloadJson: JSON.stringify(nextPayload),
|
|
649
|
+
updatedAt: nowIso()
|
|
650
|
+
};
|
|
651
|
+
this.tasks.set(next.id, next);
|
|
652
|
+
if (request.appendEvent?.kind) {
|
|
653
|
+
await this.appendTaskEvent({
|
|
654
|
+
taskId: request.id,
|
|
655
|
+
kind: request.appendEvent.kind,
|
|
656
|
+
data: request.appendEvent.data,
|
|
657
|
+
actor: request.actor
|
|
658
|
+
});
|
|
659
|
+
}
|
|
660
|
+
return next;
|
|
661
|
+
}
|
|
662
|
+
async completeTask(request) {
|
|
663
|
+
const existing = this.tasks.get(request.id);
|
|
664
|
+
if (!existing) return null;
|
|
665
|
+
const next = {
|
|
666
|
+
...existing,
|
|
667
|
+
state: "completed",
|
|
668
|
+
completedAt: nowIso(),
|
|
669
|
+
leaseExpiresAt: null,
|
|
670
|
+
updatedAt: nowIso()
|
|
671
|
+
};
|
|
672
|
+
this.tasks.set(next.id, next);
|
|
673
|
+
if (request.output) {
|
|
674
|
+
const outputs = this.taskOutputs.get(request.id) ?? [];
|
|
675
|
+
outputs.push({
|
|
676
|
+
id: crypto.randomUUID(),
|
|
677
|
+
taskId: request.id,
|
|
678
|
+
outputJson: JSON.stringify(request.output),
|
|
679
|
+
outputRef: request.outputRef ?? null,
|
|
680
|
+
createdAt: nowIso()
|
|
681
|
+
});
|
|
682
|
+
this.taskOutputs.set(request.id, outputs);
|
|
683
|
+
}
|
|
684
|
+
if (request.summary) {
|
|
685
|
+
await this.appendTaskEvent({
|
|
686
|
+
taskId: request.id,
|
|
687
|
+
kind: "completed",
|
|
688
|
+
data: request.summary,
|
|
689
|
+
actor: request.actor
|
|
690
|
+
});
|
|
691
|
+
}
|
|
692
|
+
return next;
|
|
693
|
+
}
|
|
694
|
+
async failTask(request) {
|
|
695
|
+
const existing = this.tasks.get(request.id);
|
|
696
|
+
if (!existing) return null;
|
|
697
|
+
const next = {
|
|
698
|
+
...existing,
|
|
699
|
+
state: request.retryable ? "pending" : "failed",
|
|
700
|
+
availableAt: request.nextVisibleAt ?? existing.availableAt,
|
|
701
|
+
lastErrorCode: request.errorCode ?? null,
|
|
702
|
+
lastErrorMessage: request.errorMessage,
|
|
703
|
+
leaseExpiresAt: null,
|
|
704
|
+
updatedAt: nowIso()
|
|
705
|
+
};
|
|
706
|
+
this.tasks.set(next.id, next);
|
|
707
|
+
return next;
|
|
708
|
+
}
|
|
709
|
+
async appendTaskEvent(request) {
|
|
710
|
+
const events = this.taskEvents.get(request.taskId) ?? [];
|
|
711
|
+
const next = {
|
|
712
|
+
id: crypto.randomUUID(),
|
|
713
|
+
taskId: request.taskId,
|
|
714
|
+
seq: events.length + 1,
|
|
715
|
+
kind: request.kind,
|
|
716
|
+
dataJson: JSON.stringify({ ...request.data ?? {}, actor: request.actor }),
|
|
717
|
+
createdAt: nowIso()
|
|
718
|
+
};
|
|
719
|
+
events.push(next);
|
|
720
|
+
this.taskEvents.set(request.taskId, events);
|
|
721
|
+
return next;
|
|
722
|
+
}
|
|
723
|
+
async searchTasks(request) {
|
|
724
|
+
return [...this.tasks.values()].filter((task) => !request.workDayId || task.workDayId === request.workDayId).filter((task) => !request.agentId || task.agentId === request.agentId).filter((task) => {
|
|
725
|
+
if (!request.state) return true;
|
|
726
|
+
const states = Array.isArray(request.state) ? request.state : [request.state];
|
|
727
|
+
return states.includes(task.state);
|
|
728
|
+
}).sort((left, right) => right.priority - left.priority || left.availableAt.localeCompare(right.availableAt)).slice(0, request.limit ?? 50);
|
|
729
|
+
}
|
|
730
|
+
async createReport(request) {
|
|
731
|
+
const record = {
|
|
732
|
+
id: request.id ?? crypto.randomUUID(),
|
|
733
|
+
workDayId: request.workDayId,
|
|
734
|
+
kind: request.kind,
|
|
735
|
+
bodyJson: JSON.stringify(request.body),
|
|
736
|
+
renderedRef: request.renderedRef ?? null,
|
|
737
|
+
sentAt: request.sentAt ?? null,
|
|
738
|
+
createdAt: nowIso()
|
|
739
|
+
};
|
|
740
|
+
this.reports.set(record.id, record);
|
|
741
|
+
return record;
|
|
742
|
+
}
|
|
743
|
+
async getManagerContext(taskId) {
|
|
744
|
+
const task = this.tasks.get(taskId) ?? null;
|
|
745
|
+
const workDay = task ? this.workDays.get(task.workDayId) ?? null : null;
|
|
746
|
+
return {
|
|
747
|
+
task,
|
|
748
|
+
workDay,
|
|
749
|
+
agent: null,
|
|
750
|
+
graph: workDay?.graphVersion ? { graphVersion: workDay.graphVersion } : null
|
|
751
|
+
};
|
|
752
|
+
}
|
|
377
753
|
}
|
|
378
754
|
class CloudflareD1AgentDatabase {
|
|
379
755
|
constructor(db) {
|
|
@@ -383,6 +759,7 @@ class CloudflareD1AgentDatabase {
|
|
|
383
759
|
this.runs = new RunStore(db);
|
|
384
760
|
this.cursors = new CursorStore(db);
|
|
385
761
|
this.leases = new LeaseStore(db);
|
|
762
|
+
this.operational = new OperationalStore(db);
|
|
386
763
|
}
|
|
387
764
|
db;
|
|
388
765
|
subscriptions;
|
|
@@ -390,6 +767,7 @@ class CloudflareD1AgentDatabase {
|
|
|
390
767
|
runs;
|
|
391
768
|
cursors;
|
|
392
769
|
leases;
|
|
770
|
+
operational;
|
|
393
771
|
async get(request) {
|
|
394
772
|
if (request.model === "subscription") {
|
|
395
773
|
return this.subscriptions.getByKey(String(request.id ?? request.slug ?? request.key ?? ""));
|
|
@@ -406,23 +784,52 @@ class CloudflareD1AgentDatabase {
|
|
|
406
784
|
if (request.model === "content_lease") {
|
|
407
785
|
return this.leases.getByKey(String(request.id ?? request.key ?? request.slug ?? ""));
|
|
408
786
|
}
|
|
787
|
+
if (request.model === "work_day") {
|
|
788
|
+
return this.operational.getWorkDay(String(request.id ?? request.key ?? request.slug ?? ""));
|
|
789
|
+
}
|
|
790
|
+
if (request.model === "task") {
|
|
791
|
+
return this.operational.getTask(String(request.id ?? request.key ?? request.slug ?? ""));
|
|
792
|
+
}
|
|
793
|
+
if (request.model === "report") {
|
|
794
|
+
return this.operational.getReport(String(request.id ?? request.key ?? request.slug ?? ""));
|
|
795
|
+
}
|
|
409
796
|
throw new Error(`Unsupported D1 get model "${request.model}".`);
|
|
410
797
|
}
|
|
411
798
|
async search(request) {
|
|
799
|
+
const definition = resolveModelDefinition(request.model);
|
|
800
|
+
const normalizedRequest = {
|
|
801
|
+
...request,
|
|
802
|
+
filters: normalizeFilterFields(definition, request.filters),
|
|
803
|
+
sort: normalizeSortFields(definition, request.sort)
|
|
804
|
+
};
|
|
412
805
|
if (request.model === "subscription") {
|
|
413
|
-
return this.subscriptions.search(
|
|
806
|
+
return this.subscriptions.search(normalizedRequest);
|
|
414
807
|
}
|
|
415
808
|
if (request.model === "message") {
|
|
416
|
-
return this.messages.search(
|
|
809
|
+
return this.messages.search(normalizedRequest);
|
|
417
810
|
}
|
|
418
811
|
if (request.model === "agent_run") {
|
|
419
|
-
return this.runs.search(
|
|
812
|
+
return this.runs.search(normalizedRequest);
|
|
420
813
|
}
|
|
421
814
|
if (request.model === "agent_cursor") {
|
|
422
|
-
return this.cursors.search(
|
|
815
|
+
return this.cursors.search(normalizedRequest);
|
|
423
816
|
}
|
|
424
817
|
if (request.model === "content_lease") {
|
|
425
|
-
return this.leases.search(
|
|
818
|
+
return this.leases.search(normalizedRequest);
|
|
819
|
+
}
|
|
820
|
+
if (request.model === "work_day") {
|
|
821
|
+
return this.operational.searchWorkDays(request.limit);
|
|
822
|
+
}
|
|
823
|
+
if (request.model === "task") {
|
|
824
|
+
return this.operational.searchTasks({
|
|
825
|
+
workDayId: request.filters?.find((entry) => entry.field === "workDayId" || entry.field === "work_day_id")?.value,
|
|
826
|
+
agentId: request.filters?.find((entry) => entry.field === "agentId" || entry.field === "agent_id")?.value,
|
|
827
|
+
state: request.filters?.find((entry) => entry.field === "state")?.value,
|
|
828
|
+
limit: request.limit
|
|
829
|
+
});
|
|
830
|
+
}
|
|
831
|
+
if (request.model === "report") {
|
|
832
|
+
return [];
|
|
426
833
|
}
|
|
427
834
|
throw new Error(`Unsupported D1 search model "${request.model}".`);
|
|
428
835
|
}
|
|
@@ -442,7 +849,7 @@ class CloudflareD1AgentDatabase {
|
|
|
442
849
|
workerId: request.workerId,
|
|
443
850
|
messageTypes: request.filters?.filter((filter) => filter.field === "type" && filter.op === "in").flatMap((filter) => Array.isArray(filter.value) ? filter.value.map(String) : []),
|
|
444
851
|
leaseSeconds: request.leaseSeconds
|
|
445
|
-
});
|
|
852
|
+
}, request.strategy);
|
|
446
853
|
return {
|
|
447
854
|
item: claimed,
|
|
448
855
|
leaseToken: claimed ? nextLeaseToken() : null
|
|
@@ -452,7 +859,7 @@ class CloudflareD1AgentDatabase {
|
|
|
452
859
|
const items = await this.leases.search({
|
|
453
860
|
model: "content_lease",
|
|
454
861
|
filters: request.filters,
|
|
455
|
-
sort:
|
|
862
|
+
sort: pickSortForRequest(request, "lease_expires_at"),
|
|
456
863
|
limit: 1
|
|
457
864
|
});
|
|
458
865
|
return {
|
|
@@ -460,58 +867,171 @@ class CloudflareD1AgentDatabase {
|
|
|
460
867
|
leaseToken: items[0]?.token ?? null
|
|
461
868
|
};
|
|
462
869
|
}
|
|
870
|
+
if (request.model === "task") {
|
|
871
|
+
const items = await this.operational.searchTasks({
|
|
872
|
+
state: "pending",
|
|
873
|
+
limit: 1
|
|
874
|
+
});
|
|
875
|
+
return { item: items[0] ?? null, leaseToken: null };
|
|
876
|
+
}
|
|
463
877
|
return {
|
|
464
|
-
item:
|
|
878
|
+
item: (await this.search({
|
|
879
|
+
model: request.model,
|
|
880
|
+
filters: request.filters,
|
|
881
|
+
sort: pickSortForRequest(request, filterSinceField(request.model)),
|
|
882
|
+
limit: 1
|
|
883
|
+
}))[0] ?? null,
|
|
465
884
|
leaseToken: null
|
|
466
885
|
};
|
|
467
886
|
}
|
|
468
887
|
async create(request) {
|
|
888
|
+
const definition = resolveModelDefinition(request.model);
|
|
889
|
+
const normalizedRequest = {
|
|
890
|
+
...request,
|
|
891
|
+
data: normalizeMutationData(definition, request.data)
|
|
892
|
+
};
|
|
469
893
|
if (request.model === "message") {
|
|
470
894
|
return await this.createMessage({
|
|
471
|
-
type: String(
|
|
472
|
-
payload:
|
|
473
|
-
relatedModel: typeof
|
|
474
|
-
relatedId: typeof
|
|
475
|
-
priority: Number(
|
|
476
|
-
maxAttempts: Number(
|
|
895
|
+
type: String(normalizedRequest.data.type ?? "message.created"),
|
|
896
|
+
payload: normalizedRequest.data.payload ?? normalizedRequest.data,
|
|
897
|
+
relatedModel: typeof normalizedRequest.data.related_model === "string" ? normalizedRequest.data.related_model : null,
|
|
898
|
+
relatedId: typeof normalizedRequest.data.related_id === "string" ? normalizedRequest.data.related_id : null,
|
|
899
|
+
priority: Number(normalizedRequest.data.priority ?? 0),
|
|
900
|
+
maxAttempts: Number(normalizedRequest.data.maxAttempts ?? 3),
|
|
477
901
|
actor: request.actor
|
|
478
902
|
});
|
|
479
903
|
}
|
|
480
904
|
if (request.model === "subscription") {
|
|
481
|
-
return await this.subscriptions.create(
|
|
905
|
+
return await this.subscriptions.create(normalizedRequest);
|
|
482
906
|
}
|
|
483
907
|
if (request.model === "agent_run") {
|
|
484
|
-
return await this.runs.record({ run:
|
|
908
|
+
return await this.runs.record({ run: normalizedRequest.data });
|
|
485
909
|
}
|
|
486
910
|
if (request.model === "agent_cursor") {
|
|
487
911
|
return await this.cursors.update({
|
|
488
|
-
...
|
|
912
|
+
...normalizedRequest,
|
|
489
913
|
model: "agent_cursor"
|
|
490
914
|
});
|
|
491
915
|
}
|
|
492
916
|
if (request.model === "content_lease") {
|
|
493
917
|
return await this.leases.update({
|
|
494
|
-
...
|
|
918
|
+
...normalizedRequest,
|
|
495
919
|
model: "content_lease"
|
|
496
920
|
});
|
|
497
921
|
}
|
|
922
|
+
if (request.model === "work_day") {
|
|
923
|
+
return await this.startWorkDay({
|
|
924
|
+
id: typeof normalizedRequest.data.id === "string" ? normalizedRequest.data.id : void 0,
|
|
925
|
+
projectId: String(normalizedRequest.data.projectId ?? normalizedRequest.data.project_id ?? ""),
|
|
926
|
+
capacityBudget: Number(normalizedRequest.data.capacityBudget ?? normalizedRequest.data.capacity_budget ?? 0),
|
|
927
|
+
graphVersion: typeof (normalizedRequest.data.graphVersion ?? normalizedRequest.data.graph_version) === "string" ? String(normalizedRequest.data.graphVersion ?? normalizedRequest.data.graph_version) : null,
|
|
928
|
+
summary: normalizedRequest.data.summary,
|
|
929
|
+
actor: request.actor
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
if (request.model === "task") {
|
|
933
|
+
return await this.createTask({
|
|
934
|
+
id: typeof normalizedRequest.data.id === "string" ? normalizedRequest.data.id : void 0,
|
|
935
|
+
workDayId: String(normalizedRequest.data.workDayId ?? normalizedRequest.data.work_day_id ?? ""),
|
|
936
|
+
agentId: String(normalizedRequest.data.agentId ?? normalizedRequest.data.agent_id ?? ""),
|
|
937
|
+
type: String(normalizedRequest.data.type ?? ""),
|
|
938
|
+
state: typeof normalizedRequest.data.state === "string" ? normalizedRequest.data.state : "pending",
|
|
939
|
+
priority: Number(normalizedRequest.data.priority ?? 0),
|
|
940
|
+
idempotencyKey: String(normalizedRequest.data.idempotencyKey ?? normalizedRequest.data.idempotency_key ?? ""),
|
|
941
|
+
payload: normalizedRequest.data.payload ?? normalizedRequest.data,
|
|
942
|
+
payloadHash: typeof (normalizedRequest.data.payloadHash ?? normalizedRequest.data.payload_hash) === "string" ? String(normalizedRequest.data.payloadHash ?? normalizedRequest.data.payload_hash) : null,
|
|
943
|
+
maxAttempts: Number(normalizedRequest.data.maxAttempts ?? normalizedRequest.data.max_attempts ?? 3),
|
|
944
|
+
availableAt: typeof (normalizedRequest.data.availableAt ?? normalizedRequest.data.available_at) === "string" ? String(normalizedRequest.data.availableAt ?? normalizedRequest.data.available_at) : void 0,
|
|
945
|
+
graphVersion: typeof (normalizedRequest.data.graphVersion ?? normalizedRequest.data.graph_version) === "string" ? String(normalizedRequest.data.graphVersion ?? normalizedRequest.data.graph_version) : null,
|
|
946
|
+
parentTaskId: typeof (normalizedRequest.data.parentTaskId ?? normalizedRequest.data.parent_task_id) === "string" ? String(normalizedRequest.data.parentTaskId ?? normalizedRequest.data.parent_task_id) : null,
|
|
947
|
+
actor: request.actor
|
|
948
|
+
});
|
|
949
|
+
}
|
|
950
|
+
if (request.model === "graph_run") {
|
|
951
|
+
return await this.operational.createGraphRun({
|
|
952
|
+
id: String(normalizedRequest.data.id ?? crypto.randomUUID()),
|
|
953
|
+
workDayId: String(normalizedRequest.data.workDayId ?? normalizedRequest.data.work_day_id ?? ""),
|
|
954
|
+
corpusHash: String(normalizedRequest.data.corpusHash ?? normalizedRequest.data.corpus_hash ?? ""),
|
|
955
|
+
graphVersion: String(normalizedRequest.data.graphVersion ?? normalizedRequest.data.graph_version ?? ""),
|
|
956
|
+
queryJson: typeof (normalizedRequest.data.queryJson ?? normalizedRequest.data.query_json) === "string" ? String(normalizedRequest.data.queryJson ?? normalizedRequest.data.query_json) : null,
|
|
957
|
+
seedIdsJson: typeof (normalizedRequest.data.seedIdsJson ?? normalizedRequest.data.seed_ids_json) === "string" ? String(normalizedRequest.data.seedIdsJson ?? normalizedRequest.data.seed_ids_json) : null,
|
|
958
|
+
selectedNodeIdsJson: typeof (normalizedRequest.data.selectedNodeIdsJson ?? normalizedRequest.data.selected_node_ids_json) === "string" ? String(normalizedRequest.data.selectedNodeIdsJson ?? normalizedRequest.data.selected_node_ids_json) : null,
|
|
959
|
+
statsJson: typeof (normalizedRequest.data.statsJson ?? normalizedRequest.data.stats_json) === "string" ? String(normalizedRequest.data.statsJson ?? normalizedRequest.data.stats_json) : null,
|
|
960
|
+
snapshotRef: typeof (normalizedRequest.data.snapshotRef ?? normalizedRequest.data.snapshot_ref) === "string" ? String(normalizedRequest.data.snapshotRef ?? normalizedRequest.data.snapshot_ref) : null,
|
|
961
|
+
createdAt: typeof (normalizedRequest.data.createdAt ?? normalizedRequest.data.created_at) === "string" ? String(normalizedRequest.data.createdAt ?? normalizedRequest.data.created_at) : void 0
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
if (request.model === "report") {
|
|
965
|
+
return await this.createReport({
|
|
966
|
+
id: typeof normalizedRequest.data.id === "string" ? normalizedRequest.data.id : void 0,
|
|
967
|
+
workDayId: String(normalizedRequest.data.workDayId ?? normalizedRequest.data.work_day_id ?? ""),
|
|
968
|
+
kind: String(normalizedRequest.data.kind ?? "workday_summary"),
|
|
969
|
+
body: normalizedRequest.data.body ?? normalizedRequest.data,
|
|
970
|
+
renderedRef: typeof (normalizedRequest.data.renderedRef ?? normalizedRequest.data.rendered_ref) === "string" ? String(normalizedRequest.data.renderedRef ?? normalizedRequest.data.rendered_ref) : null,
|
|
971
|
+
sentAt: typeof (normalizedRequest.data.sentAt ?? normalizedRequest.data.sent_at) === "string" ? String(normalizedRequest.data.sentAt ?? normalizedRequest.data.sent_at) : null,
|
|
972
|
+
actor: request.actor
|
|
973
|
+
});
|
|
974
|
+
}
|
|
498
975
|
throw new Error(`Unsupported D1 create model "${request.model}".`);
|
|
499
976
|
}
|
|
500
977
|
async update(request) {
|
|
978
|
+
const definition = resolveModelDefinition(request.model);
|
|
979
|
+
const normalizedRequest = {
|
|
980
|
+
...request,
|
|
981
|
+
data: normalizeMutationData(definition, request.data)
|
|
982
|
+
};
|
|
501
983
|
if (request.model === "message") {
|
|
502
|
-
return this.messages.update(
|
|
984
|
+
return this.messages.update(normalizedRequest);
|
|
503
985
|
}
|
|
504
986
|
if (request.model === "subscription") {
|
|
505
|
-
return this.subscriptions.update(
|
|
987
|
+
return this.subscriptions.update(normalizedRequest);
|
|
506
988
|
}
|
|
507
989
|
if (request.model === "agent_run") {
|
|
508
|
-
return this.runs.update(
|
|
990
|
+
return this.runs.update(normalizedRequest);
|
|
509
991
|
}
|
|
510
992
|
if (request.model === "agent_cursor") {
|
|
511
|
-
return this.cursors.update(
|
|
993
|
+
return this.cursors.update(normalizedRequest);
|
|
512
994
|
}
|
|
513
995
|
if (request.model === "content_lease") {
|
|
514
|
-
return this.leases.update(
|
|
996
|
+
return this.leases.update(normalizedRequest);
|
|
997
|
+
}
|
|
998
|
+
if (request.model === "work_day") {
|
|
999
|
+
return this.closeWorkDay({
|
|
1000
|
+
id: String(request.id ?? request.key ?? normalizedRequest.data.id ?? ""),
|
|
1001
|
+
state: normalizedRequest.data.state ?? "completed",
|
|
1002
|
+
summary: normalizedRequest.data.summary,
|
|
1003
|
+
actor: request.actor
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
if (request.model === "task") {
|
|
1007
|
+
const taskId = String(request.id ?? request.key ?? normalizedRequest.data.id ?? "");
|
|
1008
|
+
if (normalizedRequest.data.state === "completed") {
|
|
1009
|
+
return this.completeTask({
|
|
1010
|
+
id: taskId,
|
|
1011
|
+
output: normalizedRequest.data.output,
|
|
1012
|
+
outputRef: typeof normalizedRequest.data.outputRef === "string" ? normalizedRequest.data.outputRef : null,
|
|
1013
|
+
summary: normalizedRequest.data.summary,
|
|
1014
|
+
actor: request.actor
|
|
1015
|
+
});
|
|
1016
|
+
}
|
|
1017
|
+
if (normalizedRequest.data.state === "failed") {
|
|
1018
|
+
return this.failTask({
|
|
1019
|
+
id: taskId,
|
|
1020
|
+
errorCode: typeof normalizedRequest.data.errorCode === "string" ? normalizedRequest.data.errorCode : null,
|
|
1021
|
+
errorMessage: String(normalizedRequest.data.errorMessage ?? "Task failed"),
|
|
1022
|
+
retryable: Boolean(normalizedRequest.data.retryable),
|
|
1023
|
+
nextVisibleAt: typeof normalizedRequest.data.nextVisibleAt === "string" ? normalizedRequest.data.nextVisibleAt : null,
|
|
1024
|
+
actor: request.actor
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
return this.recordTaskProgress({
|
|
1028
|
+
id: taskId,
|
|
1029
|
+
workerId: typeof normalizedRequest.data.workerId === "string" ? normalizedRequest.data.workerId : null,
|
|
1030
|
+
state: typeof normalizedRequest.data.state === "string" ? normalizedRequest.data.state : void 0,
|
|
1031
|
+
appendEvent: normalizedRequest.data.appendEvent,
|
|
1032
|
+
patch: normalizedRequest.data.patch,
|
|
1033
|
+
actor: request.actor
|
|
1034
|
+
});
|
|
515
1035
|
}
|
|
516
1036
|
throw new Error(`Unsupported D1 update model "${request.model}".`);
|
|
517
1037
|
}
|
|
@@ -542,6 +1062,46 @@ class CloudflareD1AgentDatabase {
|
|
|
542
1062
|
releaseAllLeases() {
|
|
543
1063
|
return this.leases.releaseAll();
|
|
544
1064
|
}
|
|
1065
|
+
startWorkDay(request) {
|
|
1066
|
+
return this.operational.startWorkDay(request);
|
|
1067
|
+
}
|
|
1068
|
+
closeWorkDay(request) {
|
|
1069
|
+
return this.operational.closeWorkDay(request);
|
|
1070
|
+
}
|
|
1071
|
+
createTask(request) {
|
|
1072
|
+
return this.operational.createTask(request);
|
|
1073
|
+
}
|
|
1074
|
+
claimTask(request) {
|
|
1075
|
+
return this.operational.claimTask(request);
|
|
1076
|
+
}
|
|
1077
|
+
recordTaskProgress(request) {
|
|
1078
|
+
return this.operational.recordTaskProgress(request);
|
|
1079
|
+
}
|
|
1080
|
+
completeTask(request) {
|
|
1081
|
+
return this.operational.completeTask(request);
|
|
1082
|
+
}
|
|
1083
|
+
failTask(request) {
|
|
1084
|
+
return this.operational.failTask(request);
|
|
1085
|
+
}
|
|
1086
|
+
appendTaskEvent(request) {
|
|
1087
|
+
return this.operational.appendTaskEvent(request);
|
|
1088
|
+
}
|
|
1089
|
+
searchTasks(request) {
|
|
1090
|
+
return this.operational.searchTasks(request);
|
|
1091
|
+
}
|
|
1092
|
+
createReport(request) {
|
|
1093
|
+
return this.operational.createReport(request);
|
|
1094
|
+
}
|
|
1095
|
+
async getManagerContext(taskId) {
|
|
1096
|
+
const task = await this.operational.getTask(taskId);
|
|
1097
|
+
const workDay = task ? await this.operational.getWorkDay(task.workDayId) : null;
|
|
1098
|
+
return {
|
|
1099
|
+
task,
|
|
1100
|
+
workDay,
|
|
1101
|
+
agent: null,
|
|
1102
|
+
graph: workDay?.graphVersion ? { graphVersion: workDay.graphVersion } : null
|
|
1103
|
+
};
|
|
1104
|
+
}
|
|
545
1105
|
}
|
|
546
1106
|
export {
|
|
547
1107
|
CloudflareD1AgentDatabase,
|