@treeseed/sdk 0.1.1

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 (63) hide show
  1. package/README.md +565 -0
  2. package/dist/cli-tools.js +44 -0
  3. package/dist/content-store.js +237 -0
  4. package/dist/d1-store.js +549 -0
  5. package/dist/frontmatter.js +33 -0
  6. package/dist/git-runtime.js +67 -0
  7. package/dist/index.js +12 -0
  8. package/dist/model-registry.js +164 -0
  9. package/dist/runtime.js +36 -0
  10. package/dist/scripts/.ts-run-1775616845195-odh4xzphk3l.js +22 -0
  11. package/dist/scripts/.ts-run-1775616848931-9386s6kwrl.js +126 -0
  12. package/dist/scripts/assert-release-tag-version.d.ts +1 -0
  13. package/dist/scripts/assert-release-tag-version.js +23 -0
  14. package/dist/scripts/build-dist.d.ts +1 -0
  15. package/dist/scripts/build-dist.js +114 -0
  16. package/dist/scripts/package-tools.d.ts +15 -0
  17. package/dist/scripts/package-tools.js +76 -0
  18. package/dist/scripts/publish-package.d.ts +1 -0
  19. package/dist/scripts/publish-package.js +20 -0
  20. package/dist/scripts/release-verify.d.ts +1 -0
  21. package/dist/scripts/release-verify.js +49 -0
  22. package/dist/scripts/run-ts.js +45 -0
  23. package/dist/scripts/test-smoke.d.ts +1 -0
  24. package/dist/scripts/test-smoke.js +77 -0
  25. package/dist/sdk-filters.js +77 -0
  26. package/dist/sdk-types.js +24 -0
  27. package/dist/sdk.js +232 -0
  28. package/dist/src/cli-tools.d.ts +3 -0
  29. package/dist/src/content-store.d.ts +24 -0
  30. package/dist/src/d1-store.d.ts +108 -0
  31. package/dist/src/frontmatter.d.ts +6 -0
  32. package/dist/src/git-runtime.d.ts +16 -0
  33. package/dist/src/index.d.ts +6 -0
  34. package/dist/src/model-registry.d.ts +4 -0
  35. package/dist/src/runtime.d.ts +1 -0
  36. package/dist/src/sdk-filters.d.ts +4 -0
  37. package/dist/src/sdk-types.d.ts +285 -0
  38. package/dist/src/sdk.d.ts +109 -0
  39. package/dist/src/stores/cursor-store.d.ts +10 -0
  40. package/dist/src/stores/envelopes.d.ts +116 -0
  41. package/dist/src/stores/helpers.d.ts +12 -0
  42. package/dist/src/stores/lease-store.d.ts +18 -0
  43. package/dist/src/stores/message-store.d.ts +12 -0
  44. package/dist/src/stores/run-store.d.ts +10 -0
  45. package/dist/src/stores/subscription-store.d.ts +9 -0
  46. package/dist/src/types/agents.d.ts +100 -0
  47. package/dist/src/types/cloudflare.d.ts +32 -0
  48. package/dist/src/wrangler-d1.d.ts +25 -0
  49. package/dist/stores/cursor-store.js +158 -0
  50. package/dist/stores/envelopes.js +219 -0
  51. package/dist/stores/helpers.js +42 -0
  52. package/dist/stores/lease-store.js +183 -0
  53. package/dist/stores/message-store.js +249 -0
  54. package/dist/stores/run-store.js +166 -0
  55. package/dist/stores/subscription-store.js +171 -0
  56. package/dist/test/test-fixture.d.ts +1 -0
  57. package/dist/test/utils/envelopes.test.d.ts +1 -0
  58. package/dist/test/utils/sdk.test.d.ts +1 -0
  59. package/dist/types/agents.js +40 -0
  60. package/dist/types/cloudflare.js +0 -0
  61. package/dist/vitest.config.d.ts +2 -0
  62. package/dist/wrangler-d1.js +84 -0
  63. package/package.json +130 -0
@@ -0,0 +1,100 @@
1
+ export declare const AGENT_TRIGGER_KINDS: readonly ["schedule", "message", "follow", "startup"];
2
+ export declare const AGENT_PERMISSION_OPERATIONS: readonly ["get", "read", "search", "follow", "pick", "create", "update"];
3
+ export declare const AGENT_MESSAGE_STATUSES: readonly ["pending", "claimed", "completed", "failed", "dead_letter"];
4
+ export declare const AGENT_RUN_STATUSES: readonly ["running", "completed", "failed", "waiting"];
5
+ export declare const AGENT_HANDLER_KINDS: readonly ["planner", "architect", "engineer", "notifier", "researcher", "reviewer", "releaser"];
6
+ export declare const AGENT_CLI_ALLOW_TOOLS: readonly ["shell(git)", "shell(npm)", "web"];
7
+ export type AgentTriggerKind = (typeof AGENT_TRIGGER_KINDS)[number];
8
+ export type AgentPermissionOperation = (typeof AGENT_PERMISSION_OPERATIONS)[number];
9
+ export type AgentMessageStatus = (typeof AGENT_MESSAGE_STATUSES)[number];
10
+ export type AgentRunStatus = (typeof AGENT_RUN_STATUSES)[number];
11
+ export type AgentHandlerKind = string;
12
+ export type AgentCliAllowTool = (typeof AGENT_CLI_ALLOW_TOOLS)[number];
13
+ export interface AgentTriggerConfig {
14
+ type: AgentTriggerKind;
15
+ cron?: string;
16
+ messageTypes?: string[];
17
+ models?: string[];
18
+ sinceField?: string;
19
+ runOnStart?: boolean;
20
+ }
21
+ export interface AgentPermissionConfig {
22
+ model: string;
23
+ operations: AgentPermissionOperation[];
24
+ }
25
+ export interface AgentOutputContract {
26
+ messageTypes: string[];
27
+ modelMutations: string[];
28
+ }
29
+ export interface AgentExecutionConfig {
30
+ maxConcurrency: number;
31
+ timeoutSeconds: number;
32
+ cooldownSeconds: number;
33
+ leaseSeconds: number;
34
+ retryLimit: number;
35
+ branchPrefix: string;
36
+ }
37
+ export interface AgentTriggerPolicy {
38
+ maxRunsPerCycle?: number;
39
+ messageBatchSize?: number;
40
+ }
41
+ export interface AgentCliOptions {
42
+ model?: string;
43
+ allowTools?: AgentCliAllowTool[];
44
+ additionalArgs?: string[];
45
+ }
46
+ export interface AgentRuntimeSpec {
47
+ slug: string;
48
+ handler: AgentHandlerKind;
49
+ enabled: boolean;
50
+ systemPrompt: string;
51
+ persona: string;
52
+ cli: AgentCliOptions;
53
+ triggers: AgentTriggerConfig[];
54
+ triggerPolicy?: AgentTriggerPolicy;
55
+ permissions: AgentPermissionConfig[];
56
+ execution: AgentExecutionConfig;
57
+ outputs: AgentOutputContract;
58
+ }
59
+ export interface AgentMessageRecord {
60
+ [key: string]: unknown;
61
+ id: number;
62
+ type: string;
63
+ status: AgentMessageStatus;
64
+ payloadJson: string;
65
+ relatedModel: string | null;
66
+ relatedId: string | null;
67
+ priority: number;
68
+ availableAt: string;
69
+ claimedBy: string | null;
70
+ claimedAt: string | null;
71
+ leaseExpiresAt: string | null;
72
+ attempts: number;
73
+ maxAttempts: number;
74
+ createdAt: string;
75
+ updatedAt: string;
76
+ }
77
+ export interface AgentRunRecord {
78
+ [key: string]: unknown;
79
+ runId: string;
80
+ agentSlug: string;
81
+ triggerSource: string;
82
+ status: AgentRunStatus;
83
+ selectedItemKey: string | null;
84
+ selectedMessageId: number | null;
85
+ branchName: string | null;
86
+ prUrl: string | null;
87
+ summary: string | null;
88
+ error: string | null;
89
+ startedAt: string;
90
+ finishedAt: string | null;
91
+ }
92
+ export interface ContentLeaseRecord {
93
+ [key: string]: unknown;
94
+ model: string;
95
+ itemKey: string;
96
+ claimedBy: string;
97
+ claimedAt: string;
98
+ leaseExpiresAt: string;
99
+ token: string;
100
+ }
@@ -0,0 +1,32 @@
1
+ export interface KvNamespacePutOptions {
2
+ expirationTtl?: number;
3
+ }
4
+ export interface KvNamespaceLike {
5
+ get(key: string): Promise<string | null>;
6
+ put(key: string, value: string, options?: KvNamespacePutOptions): Promise<void>;
7
+ }
8
+ export interface D1PreparedStatementLike {
9
+ bind(...values: unknown[]): D1PreparedStatementLike;
10
+ run(): Promise<unknown>;
11
+ first<T = Record<string, unknown>>(): Promise<T | null>;
12
+ all<T = Record<string, unknown>>(): Promise<{
13
+ results: T[];
14
+ }>;
15
+ raw<T = unknown[]>(): Promise<T[]>;
16
+ }
17
+ export interface D1DatabaseLike {
18
+ prepare(query: string): D1PreparedStatementLike;
19
+ batch?(statements: D1PreparedStatementLike[]): Promise<unknown[]>;
20
+ exec?(query: string): Promise<unknown>;
21
+ }
22
+ export interface CloudflareRuntimeAssets {
23
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
24
+ }
25
+ export interface CloudflareRuntime {
26
+ env: {
27
+ FORM_GUARD_KV: KvNamespaceLike;
28
+ SITE_DATA_DB: D1DatabaseLike;
29
+ SESSION: KvNamespaceLike;
30
+ ASSETS?: CloudflareRuntimeAssets;
31
+ };
32
+ }
@@ -0,0 +1,25 @@
1
+ import type { D1DatabaseLike, D1PreparedStatementLike } from './types/cloudflare.ts';
2
+ declare class WranglerD1PreparedStatement implements D1PreparedStatementLike {
3
+ private readonly databaseName;
4
+ private readonly cwd;
5
+ private readonly persistTo?;
6
+ private readonly query;
7
+ private bindings;
8
+ constructor(databaseName: string, cwd: string, persistTo?: string | undefined, query?: string);
9
+ bind(...values: unknown[]): this;
10
+ private execute;
11
+ run(): Promise<any[]>;
12
+ all<T = Record<string, unknown>>(): Promise<{
13
+ results: T[];
14
+ }>;
15
+ first<T = Record<string, unknown>>(): Promise<NonNullable<T> | null>;
16
+ raw<T = unknown[]>(): Promise<T[]>;
17
+ }
18
+ export declare class WranglerD1Database implements D1DatabaseLike {
19
+ private readonly databaseName;
20
+ private readonly cwd;
21
+ private readonly persistTo?;
22
+ constructor(databaseName: string, cwd: string, persistTo?: string | undefined);
23
+ prepare(query: string): WranglerD1PreparedStatement;
24
+ }
25
+ export {};
@@ -0,0 +1,158 @@
1
+ import { SqliteStoreBase, nowIso, toSqlValue } from "./helpers.js";
2
+ import { createCursorEnvelope, cursorEntityFromEnvelope, TRESEED_ENVELOPE_SCHEMA_VERSION } from "./envelopes.js";
3
+ function cursorFromRow(row) {
4
+ return {
5
+ agentSlug: String(row.agentSlug ?? row.agent_slug ?? ""),
6
+ cursorKey: String(row.cursorKey ?? row.cursor_key ?? ""),
7
+ cursorValue: String(row.cursorValue ?? row.cursor_value ?? ""),
8
+ updatedAt: row.updatedAt !== void 0 && row.updatedAt !== null ? String(row.updatedAt) : row.updated_at !== void 0 && row.updated_at !== null ? String(row.updated_at) : null
9
+ };
10
+ }
11
+ function buildFilterSql(filters = []) {
12
+ return filters?.length ? `WHERE ${filters.map((filter) => {
13
+ switch (filter.op) {
14
+ case "eq":
15
+ return `${filter.field} = ${toSqlValue(filter.value)}`;
16
+ case "in":
17
+ return `${filter.field} IN (${(Array.isArray(filter.value) ? filter.value : [filter.value]).map(toSqlValue).join(", ")})`;
18
+ case "updated_since":
19
+ return `${filter.field} >= ${toSqlValue(filter.value)}`;
20
+ default:
21
+ return `${filter.field} LIKE ${toSqlValue(`%${String(filter.value ?? "")}%`)}`;
22
+ }
23
+ }).join(" AND ")}` : "";
24
+ }
25
+ class CursorStore extends SqliteStoreBase {
26
+ async usesEnvelopeTable() {
27
+ return this.tableExists("cursor_state");
28
+ }
29
+ async getByKey(key) {
30
+ const [agentSlug, cursorKey] = key.split(":", 2);
31
+ if (!agentSlug || !cursorKey) {
32
+ return null;
33
+ }
34
+ if (await this.usesEnvelopeTable()) {
35
+ const row2 = await this.selectFirst(
36
+ `SELECT * FROM cursor_state WHERE agent_slug = ${toSqlValue(agentSlug)} AND cursor_key = ${toSqlValue(cursorKey)} LIMIT 1`
37
+ );
38
+ return row2 ? cursorEntityFromEnvelope(row2) : null;
39
+ }
40
+ const row = await this.selectFirst(
41
+ `SELECT * FROM agent_cursors WHERE agent_slug = ${toSqlValue(agentSlug)} AND cursor_key = ${toSqlValue(cursorKey)} LIMIT 1`
42
+ );
43
+ return row ? cursorFromRow(row) : null;
44
+ }
45
+ async get(request) {
46
+ if (await this.usesEnvelopeTable()) {
47
+ const row2 = await this.selectFirst(
48
+ `SELECT payload_json FROM cursor_state WHERE agent_slug = ${toSqlValue(request.agentSlug)} AND cursor_key = ${toSqlValue(request.cursorKey)} LIMIT 1`
49
+ );
50
+ if (typeof row2?.payload_json !== "string") {
51
+ return null;
52
+ }
53
+ try {
54
+ return String(JSON.parse(row2.payload_json).cursorValue ?? "");
55
+ } catch {
56
+ return null;
57
+ }
58
+ }
59
+ const row = await this.selectFirst(
60
+ `SELECT cursor_value FROM agent_cursors WHERE agent_slug = ${toSqlValue(request.agentSlug)} AND cursor_key = ${toSqlValue(request.cursorKey)} LIMIT 1`
61
+ );
62
+ return row?.cursor_value !== void 0 && row?.cursor_value !== null ? String(row.cursor_value) : null;
63
+ }
64
+ async search(request) {
65
+ if (await this.usesEnvelopeTable()) {
66
+ const sql2 = [
67
+ "SELECT * FROM cursor_state",
68
+ buildEnvelopeFilterSql(request.filters),
69
+ request.sort?.length ? `ORDER BY ${request.sort.map((entry) => `${cursorSortColumn(entry.field)} ${entry.direction === "asc" ? "ASC" : "DESC"}`).join(", ")}` : "",
70
+ request.limit ? `LIMIT ${request.limit}` : ""
71
+ ].filter(Boolean).join(" ");
72
+ const rows2 = await this.selectAll(sql2);
73
+ return rows2.map(cursorEntityFromEnvelope);
74
+ }
75
+ const sql = [
76
+ "SELECT * FROM agent_cursors",
77
+ buildFilterSql(request.filters),
78
+ request.sort?.length ? `ORDER BY ${request.sort.map((entry) => `${entry.field} ${entry.direction === "asc" ? "ASC" : "DESC"}`).join(", ")}` : "",
79
+ request.limit ? `LIMIT ${request.limit}` : ""
80
+ ].filter(Boolean).join(" ");
81
+ const rows = await this.selectAll(sql);
82
+ return rows.map(cursorFromRow);
83
+ }
84
+ async upsert(request) {
85
+ if (await this.usesEnvelopeTable()) {
86
+ const envelope = createCursorEnvelope({
87
+ agentSlug: request.agentSlug,
88
+ cursorKey: request.cursorKey,
89
+ cursorValue: request.cursorValue
90
+ });
91
+ await this.execute(
92
+ `INSERT OR REPLACE INTO cursor_state (agent_slug, cursor_key, status, schema_version, updated_at, payload_json, meta_json) VALUES (${toSqlValue(request.agentSlug)}, ${toSqlValue(request.cursorKey)}, ${toSqlValue(envelope.status)}, ${TRESEED_ENVELOPE_SCHEMA_VERSION}, ${toSqlValue(nowIso())}, ${toSqlValue(JSON.stringify(envelope.payload))}, ${toSqlValue(JSON.stringify(envelope.meta))})`
93
+ );
94
+ return;
95
+ }
96
+ await this.execute(
97
+ `INSERT OR REPLACE INTO agent_cursors (agent_slug, cursor_key, cursor_value, updated_at) VALUES (${toSqlValue(request.agentSlug)}, ${toSqlValue(request.cursorKey)}, ${toSqlValue(request.cursorValue)}, ${toSqlValue(nowIso())})`
98
+ );
99
+ }
100
+ async update(request) {
101
+ const agentSlug = String(request.data.agentSlug ?? request.id ?? request.key ?? "");
102
+ const cursorKey = String(request.data.cursorKey ?? request.slug ?? "");
103
+ const cursorValue = String(request.data.cursorValue ?? "");
104
+ await this.upsert({
105
+ agentSlug,
106
+ cursorKey,
107
+ cursorValue
108
+ });
109
+ return this.getByKey(`${agentSlug}:${cursorKey}`);
110
+ }
111
+ }
112
+ function buildEnvelopeFilterSql(filters = []) {
113
+ return filters?.length ? `WHERE ${filters.map((filter) => {
114
+ const field = cursorFilterColumn(filter.field);
115
+ switch (filter.op) {
116
+ case "eq":
117
+ return `${field} = ${toSqlValue(filter.value)}`;
118
+ case "in":
119
+ return `${field} IN (${(Array.isArray(filter.value) ? filter.value : [filter.value]).map(toSqlValue).join(", ")})`;
120
+ case "updated_since":
121
+ return `updated_at >= ${toSqlValue(filter.value)}`;
122
+ default:
123
+ return `${field} LIKE ${toSqlValue(`%${String(filter.value ?? "")}%`)}`;
124
+ }
125
+ }).join(" AND ")}` : "";
126
+ }
127
+ function cursorFilterColumn(field) {
128
+ switch (field) {
129
+ case "agentSlug":
130
+ case "agent_slug":
131
+ return "agent_slug";
132
+ case "cursorKey":
133
+ case "cursor_key":
134
+ return "cursor_key";
135
+ case "updatedAt":
136
+ case "updated_at":
137
+ return "updated_at";
138
+ default:
139
+ return `json_extract(payload_json, '$.${field}')`;
140
+ }
141
+ }
142
+ function cursorSortColumn(field) {
143
+ switch (field) {
144
+ case "agentSlug":
145
+ case "agent_slug":
146
+ return "agent_slug";
147
+ case "cursorKey":
148
+ case "cursor_key":
149
+ return "cursor_key";
150
+ case "updatedAt":
151
+ case "updated_at":
152
+ default:
153
+ return "updated_at";
154
+ }
155
+ }
156
+ export {
157
+ CursorStore
158
+ };
@@ -0,0 +1,219 @@
1
+ const TRESEED_ENVELOPE_SCHEMA_VERSION = 1;
2
+ function parseJsonObject(value, fallback) {
3
+ if (typeof value !== "string" || value.trim().length === 0) return fallback;
4
+ try {
5
+ return { ...fallback, ...JSON.parse(value) };
6
+ } catch {
7
+ return fallback;
8
+ }
9
+ }
10
+ function createSubscriptionEnvelope(input) {
11
+ return {
12
+ recordType: "subscription",
13
+ schemaVersion: TRESEED_ENVELOPE_SCHEMA_VERSION,
14
+ status: input.status ?? "active",
15
+ payload: {
16
+ email: input.email,
17
+ name: input.name ?? null,
18
+ source: input.source ?? "sdk",
19
+ consentAt: input.consentAt ?? null,
20
+ ipHash: input.ipHash ?? ""
21
+ },
22
+ meta: input.meta ?? {}
23
+ };
24
+ }
25
+ function subscriptionEntityFromEnvelope(row) {
26
+ const payload = parseJsonObject(row.payload_json, {
27
+ email: String(row.record_key ?? row.lookup_key ?? ""),
28
+ name: null,
29
+ source: "sdk",
30
+ consentAt: null,
31
+ ipHash: ""
32
+ });
33
+ return {
34
+ id: row.id !== void 0 ? Number(row.id) : void 0,
35
+ recordType: "subscription",
36
+ schemaVersion: Number(row.schema_version ?? TRESEED_ENVELOPE_SCHEMA_VERSION),
37
+ email: payload.email,
38
+ name: payload.name,
39
+ status: String(row.status ?? "active"),
40
+ source: payload.source,
41
+ consent_at: payload.consentAt ?? void 0,
42
+ created_at: row.created_at ? String(row.created_at) : void 0,
43
+ updated_at: row.updated_at ? String(row.updated_at) : void 0,
44
+ ip_hash: payload.ipHash,
45
+ metaJson: typeof row.meta_json === "string" ? row.meta_json : "{}"
46
+ };
47
+ }
48
+ function createContactSubmissionEnvelope(input) {
49
+ return {
50
+ recordType: "contact_submission",
51
+ schemaVersion: TRESEED_ENVELOPE_SCHEMA_VERSION,
52
+ status: "received",
53
+ payload: {
54
+ name: input.name,
55
+ email: input.email,
56
+ organization: input.organization ?? null,
57
+ contactType: input.contactType,
58
+ subject: input.subject,
59
+ message: input.message,
60
+ userAgent: input.userAgent,
61
+ ipHash: input.ipHash
62
+ },
63
+ meta: input.meta ?? {}
64
+ };
65
+ }
66
+ function createMessageEnvelope(input) {
67
+ return {
68
+ recordType: "message",
69
+ schemaVersion: TRESEED_ENVELOPE_SCHEMA_VERSION,
70
+ status: "pending",
71
+ payload: { body: input.payload },
72
+ meta: input.meta ?? {}
73
+ };
74
+ }
75
+ function messageEntityFromEnvelope(row) {
76
+ const payload = parseJsonObject(row.payload_json, { body: {} });
77
+ return {
78
+ id: Number(row.id ?? 0),
79
+ recordType: "message",
80
+ schemaVersion: Number(row.schema_version ?? TRESEED_ENVELOPE_SCHEMA_VERSION),
81
+ type: String(row.message_type ?? ""),
82
+ status: String(row.status ?? "pending"),
83
+ payloadJson: JSON.stringify(payload.body ?? {}),
84
+ metaJson: typeof row.meta_json === "string" ? row.meta_json : "{}",
85
+ relatedModel: row.related_model ? String(row.related_model) : null,
86
+ relatedId: row.related_id ? String(row.related_id) : null,
87
+ priority: Number(row.priority ?? 0),
88
+ availableAt: String(row.available_at ?? ""),
89
+ claimedBy: row.claimed_by ? String(row.claimed_by) : null,
90
+ claimedAt: row.claimed_at ? String(row.claimed_at) : null,
91
+ leaseExpiresAt: row.lease_expires_at ? String(row.lease_expires_at) : null,
92
+ attempts: Number(row.attempts ?? 0),
93
+ maxAttempts: Number(row.max_attempts ?? 3),
94
+ createdAt: String(row.created_at ?? ""),
95
+ updatedAt: String(row.updated_at ?? "")
96
+ };
97
+ }
98
+ function createRunEnvelope(input) {
99
+ return {
100
+ recordType: "agent_run",
101
+ schemaVersion: TRESEED_ENVELOPE_SCHEMA_VERSION,
102
+ status: input.status,
103
+ payload: {
104
+ triggerSource: input.triggerSource,
105
+ handlerKind: input.handlerKind ?? null,
106
+ triggerKind: input.triggerKind ?? null,
107
+ selectedItemKey: input.selectedItemKey ?? null,
108
+ selectedMessageId: input.selectedMessageId ?? null,
109
+ claimedMessageId: input.claimedMessageId ?? null,
110
+ branchName: input.branchName ?? null,
111
+ prUrl: input.prUrl ?? null,
112
+ summary: input.summary ?? null,
113
+ error: input.error ?? null,
114
+ errorCategory: input.errorCategory ?? null,
115
+ commitSha: input.commitSha ?? null,
116
+ changedPaths: input.changedPaths ?? [],
117
+ finishedAt: input.finishedAt ?? null
118
+ },
119
+ meta: {
120
+ runId: input.runId,
121
+ agentSlug: input.agentSlug
122
+ }
123
+ };
124
+ }
125
+ function runEntityFromEnvelope(row) {
126
+ const payload = parseJsonObject(row.payload_json, {
127
+ triggerSource: "",
128
+ selectedItemKey: null,
129
+ selectedMessageId: null,
130
+ branchName: null,
131
+ prUrl: null,
132
+ summary: null,
133
+ error: null,
134
+ changedPaths: [],
135
+ finishedAt: null
136
+ });
137
+ const meta = parseJsonObject(row.meta_json, {
138
+ runId: String(row.record_key ?? ""),
139
+ agentSlug: String(row.lookup_key ?? "")
140
+ });
141
+ return {
142
+ recordType: "agent_run",
143
+ schemaVersion: Number(row.schema_version ?? TRESEED_ENVELOPE_SCHEMA_VERSION),
144
+ runId: meta.runId,
145
+ agentSlug: meta.agentSlug,
146
+ status: String(row.status ?? ""),
147
+ triggerSource: payload.triggerSource,
148
+ handlerKind: payload.handlerKind ?? null,
149
+ triggerKind: payload.triggerKind ?? null,
150
+ selectedItemKey: payload.selectedItemKey ?? null,
151
+ selectedMessageId: payload.selectedMessageId ?? null,
152
+ claimedMessageId: payload.claimedMessageId ?? null,
153
+ branchName: payload.branchName ?? null,
154
+ prUrl: payload.prUrl ?? null,
155
+ summary: payload.summary ?? null,
156
+ error: payload.error ?? null,
157
+ errorCategory: payload.errorCategory ?? null,
158
+ commitSha: payload.commitSha ?? (row.secondary_key ? String(row.secondary_key) : null),
159
+ changedPaths: payload.changedPaths ?? [],
160
+ startedAt: String(row.created_at ?? ""),
161
+ finishedAt: payload.finishedAt ?? null
162
+ };
163
+ }
164
+ function createCursorEnvelope(input) {
165
+ return {
166
+ recordType: "agent_cursor",
167
+ schemaVersion: TRESEED_ENVELOPE_SCHEMA_VERSION,
168
+ status: "active",
169
+ payload: { cursorValue: input.cursorValue },
170
+ meta: input.meta ?? {}
171
+ };
172
+ }
173
+ function cursorEntityFromEnvelope(row) {
174
+ const payload = parseJsonObject(row.payload_json, { cursorValue: "" });
175
+ return {
176
+ recordType: "agent_cursor",
177
+ schemaVersion: Number(row.schema_version ?? TRESEED_ENVELOPE_SCHEMA_VERSION),
178
+ agentSlug: String(row.agent_slug ?? ""),
179
+ cursorKey: String(row.cursor_key ?? ""),
180
+ cursorValue: payload.cursorValue,
181
+ updatedAt: row.updated_at ? String(row.updated_at) : null
182
+ };
183
+ }
184
+ function createLeaseEnvelope(input) {
185
+ return {
186
+ recordType: "content_lease",
187
+ schemaVersion: TRESEED_ENVELOPE_SCHEMA_VERSION,
188
+ status: "claimed",
189
+ payload: { token: input.token },
190
+ meta: input.meta ?? {}
191
+ };
192
+ }
193
+ function leaseEntityFromEnvelope(row) {
194
+ const payload = parseJsonObject(row.payload_json, { token: "" });
195
+ return {
196
+ recordType: "content_lease",
197
+ schemaVersion: Number(row.schema_version ?? TRESEED_ENVELOPE_SCHEMA_VERSION),
198
+ model: String(row.model ?? ""),
199
+ itemKey: String(row.item_key ?? ""),
200
+ claimedBy: row.claimed_by ? String(row.claimed_by) : "",
201
+ claimedAt: row.claimed_at ? String(row.claimed_at) : "",
202
+ leaseExpiresAt: row.lease_expires_at ? String(row.lease_expires_at) : "",
203
+ token: payload.token
204
+ };
205
+ }
206
+ export {
207
+ TRESEED_ENVELOPE_SCHEMA_VERSION,
208
+ createContactSubmissionEnvelope,
209
+ createCursorEnvelope,
210
+ createLeaseEnvelope,
211
+ createMessageEnvelope,
212
+ createRunEnvelope,
213
+ createSubscriptionEnvelope,
214
+ cursorEntityFromEnvelope,
215
+ leaseEntityFromEnvelope,
216
+ messageEntityFromEnvelope,
217
+ runEntityFromEnvelope,
218
+ subscriptionEntityFromEnvelope
219
+ };
@@ -0,0 +1,42 @@
1
+ function nowIso() {
2
+ return (/* @__PURE__ */ new Date()).toISOString();
3
+ }
4
+ function toSqlValue(value) {
5
+ if (value === null || value === void 0) {
6
+ return "NULL";
7
+ }
8
+ if (typeof value === "number") {
9
+ return String(value);
10
+ }
11
+ if (typeof value === "boolean") {
12
+ return value ? "1" : "0";
13
+ }
14
+ return `'${String(value).replace(/'/g, "''")}'`;
15
+ }
16
+ class SqliteStoreBase {
17
+ constructor(db) {
18
+ this.db = db;
19
+ }
20
+ db;
21
+ async selectAll(query) {
22
+ const result = await this.db.prepare(query).all();
23
+ return result.results ?? [];
24
+ }
25
+ async selectFirst(query) {
26
+ return this.db.prepare(query).first();
27
+ }
28
+ async execute(query) {
29
+ await this.db.prepare(query).run();
30
+ }
31
+ async tableExists(tableName) {
32
+ const row = await this.selectFirst(
33
+ `SELECT name FROM sqlite_master WHERE type = 'table' AND name = ${toSqlValue(tableName)} LIMIT 1`
34
+ );
35
+ return Boolean(row?.name);
36
+ }
37
+ }
38
+ export {
39
+ SqliteStoreBase,
40
+ nowIso,
41
+ toSqlValue
42
+ };