@poncho-ai/harness 0.35.0 → 0.36.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 (49) hide show
  1. package/.turbo/turbo-build.log +12 -11
  2. package/CHANGELOG.md +25 -0
  3. package/dist/index.d.ts +485 -29
  4. package/dist/index.js +2839 -2114
  5. package/dist/isolate-TCWTUVG4.js +1532 -0
  6. package/package.json +23 -4
  7. package/scripts/migrate-to-engine.mjs +556 -0
  8. package/src/config.ts +106 -1
  9. package/src/harness.ts +226 -91
  10. package/src/index.ts +5 -0
  11. package/src/isolate/bindings.ts +206 -0
  12. package/src/isolate/bundler.ts +179 -0
  13. package/src/isolate/index.ts +10 -0
  14. package/src/isolate/polyfills.ts +796 -0
  15. package/src/isolate/run-code-tool.ts +220 -0
  16. package/src/isolate/runtime.ts +286 -0
  17. package/src/isolate/type-stubs.ts +196 -0
  18. package/src/memory.ts +129 -198
  19. package/src/reminder-store.ts +3 -237
  20. package/src/secrets-store.ts +2 -91
  21. package/src/state.ts +11 -1302
  22. package/src/storage/engine.ts +106 -0
  23. package/src/storage/index.ts +59 -0
  24. package/src/storage/memory-engine.ts +588 -0
  25. package/src/storage/postgres-engine.ts +139 -0
  26. package/src/storage/schema.ts +145 -0
  27. package/src/storage/sql-dialect.ts +963 -0
  28. package/src/storage/sqlite-engine.ts +99 -0
  29. package/src/storage/store-adapters.ts +100 -0
  30. package/src/todo-tools.ts +1 -136
  31. package/src/upload-store.ts +1 -0
  32. package/src/vfs/bash-manager.ts +120 -0
  33. package/src/vfs/bash-tool.ts +59 -0
  34. package/src/vfs/create-bash-fs.ts +32 -0
  35. package/src/vfs/edit-file-tool.ts +72 -0
  36. package/src/vfs/index.ts +5 -0
  37. package/src/vfs/poncho-fs-adapter.ts +267 -0
  38. package/src/vfs/protected-fs.ts +177 -0
  39. package/src/vfs/read-file-tool.ts +103 -0
  40. package/src/vfs/write-file-tool.ts +49 -0
  41. package/test/harness.test.ts +30 -36
  42. package/test/isolate-vfs.test.ts +453 -0
  43. package/test/isolate.test.ts +252 -0
  44. package/test/state.test.ts +4 -27
  45. package/test/storage-engine.test.ts +250 -0
  46. package/test/vfs.test.ts +242 -0
  47. package/.turbo/turbo-lint.log +0 -6
  48. package/.turbo/turbo-test.log +0 -11931
  49. package/src/kv-store.ts +0 -216
package/src/kv-store.ts DELETED
@@ -1,216 +0,0 @@
1
- import type { StateConfig } from "./state.js";
2
-
3
- /**
4
- * Minimal raw key-value interface shared by MemoryStore, TodoStore, and any
5
- * future stores that sit on top of the same user-configured backend.
6
- */
7
- export interface RawKVStore {
8
- get(key: string): Promise<string | undefined>;
9
- set(key: string, value: string): Promise<void>;
10
- setWithTtl(key: string, value: string, ttlSeconds: number): Promise<void>;
11
- }
12
-
13
- // ---------------------------------------------------------------------------
14
- // Upstash
15
- // ---------------------------------------------------------------------------
16
-
17
- class UpstashKVStore implements RawKVStore {
18
- private readonly baseUrl: string;
19
- private readonly token: string;
20
-
21
- constructor(baseUrl: string, token: string) {
22
- this.baseUrl = baseUrl.replace(/\/+$/, "");
23
- this.token = token;
24
- }
25
-
26
- private headers(): HeadersInit {
27
- return { Authorization: `Bearer ${this.token}`, "Content-Type": "application/json" };
28
- }
29
-
30
- async get(key: string): Promise<string | undefined> {
31
- const response = await fetch(`${this.baseUrl}/get/${encodeURIComponent(key)}`, {
32
- method: "POST",
33
- headers: this.headers(),
34
- });
35
- if (!response.ok) return undefined;
36
- const payload = (await response.json()) as { result?: string | null };
37
- return payload.result ?? undefined;
38
- }
39
-
40
- async set(key: string, value: string): Promise<void> {
41
- const response = await fetch(this.baseUrl, {
42
- method: "POST",
43
- headers: this.headers(),
44
- body: JSON.stringify(["SET", key, value]),
45
- });
46
- if (!response.ok) {
47
- const text = await response.text().catch(() => "");
48
- console.error(`[kv][upstash] SET failed (${response.status}): ${text.slice(0, 200)}`);
49
- }
50
- }
51
-
52
- async setWithTtl(key: string, value: string, ttl: number): Promise<void> {
53
- const response = await fetch(this.baseUrl, {
54
- method: "POST",
55
- headers: this.headers(),
56
- body: JSON.stringify(["SETEX", key, Math.max(1, ttl), value]),
57
- });
58
- if (!response.ok) {
59
- const text = await response.text().catch(() => "");
60
- console.error(`[kv][upstash] SETEX failed (${response.status}): ${text.slice(0, 200)}`);
61
- }
62
- }
63
- }
64
-
65
- // ---------------------------------------------------------------------------
66
- // Redis
67
- // ---------------------------------------------------------------------------
68
-
69
- class RedisKVStore implements RawKVStore {
70
- private readonly clientPromise: Promise<
71
- | {
72
- get: (key: string) => Promise<string | null>;
73
- set: (key: string, value: string, options?: { EX?: number }) => Promise<unknown>;
74
- }
75
- | undefined
76
- >;
77
-
78
- constructor(url: string) {
79
- this.clientPromise = (async () => {
80
- try {
81
- const redisModule = (await import("redis")) as unknown as {
82
- createClient: (args: { url: string }) => {
83
- connect: () => Promise<unknown>;
84
- get: (key: string) => Promise<string | null>;
85
- set: (key: string, value: string, options?: { EX?: number }) => Promise<unknown>;
86
- };
87
- };
88
- const client = redisModule.createClient({ url });
89
- await client.connect();
90
- return client;
91
- } catch {
92
- return undefined;
93
- }
94
- })();
95
- }
96
-
97
- async get(key: string): Promise<string | undefined> {
98
- const client = await this.clientPromise;
99
- if (!client) throw new Error("Redis unavailable");
100
- const value = await client.get(key);
101
- return value ?? undefined;
102
- }
103
-
104
- async set(key: string, value: string): Promise<void> {
105
- const client = await this.clientPromise;
106
- if (!client) throw new Error("Redis unavailable");
107
- await client.set(key, value);
108
- }
109
-
110
- async setWithTtl(key: string, value: string, ttl: number): Promise<void> {
111
- const client = await this.clientPromise;
112
- if (!client) throw new Error("Redis unavailable");
113
- await client.set(key, value, { EX: Math.max(1, ttl) });
114
- }
115
- }
116
-
117
- // ---------------------------------------------------------------------------
118
- // DynamoDB
119
- // ---------------------------------------------------------------------------
120
-
121
- class DynamoDbKVStore implements RawKVStore {
122
- private readonly table: string;
123
- private readonly clientPromise: Promise<
124
- | {
125
- send: (command: unknown) => Promise<unknown>;
126
- GetItemCommand: new (input: unknown) => unknown;
127
- PutItemCommand: new (input: unknown) => unknown;
128
- }
129
- | undefined
130
- >;
131
-
132
- constructor(table: string, region?: string) {
133
- this.table = table;
134
- this.clientPromise = (async () => {
135
- try {
136
- const module = (await import("@aws-sdk/client-dynamodb")) as {
137
- DynamoDBClient: new (input: { region?: string }) => {
138
- send: (command: unknown) => Promise<unknown>;
139
- };
140
- GetItemCommand: new (input: unknown) => unknown;
141
- PutItemCommand: new (input: unknown) => unknown;
142
- };
143
- const client = new module.DynamoDBClient({ region });
144
- return {
145
- send: client.send.bind(client),
146
- GetItemCommand: module.GetItemCommand,
147
- PutItemCommand: module.PutItemCommand,
148
- };
149
- } catch {
150
- return undefined;
151
- }
152
- })();
153
- }
154
-
155
- async get(key: string): Promise<string | undefined> {
156
- const client = await this.clientPromise;
157
- if (!client) throw new Error("DynamoDB unavailable");
158
- const result = (await client.send(
159
- new client.GetItemCommand({ TableName: this.table, Key: { runId: { S: key } } }),
160
- )) as { Item?: { value?: { S?: string } } };
161
- return result.Item?.value?.S;
162
- }
163
-
164
- async set(key: string, value: string): Promise<void> {
165
- const client = await this.clientPromise;
166
- if (!client) throw new Error("DynamoDB unavailable");
167
- await client.send(
168
- new client.PutItemCommand({
169
- TableName: this.table,
170
- Item: { runId: { S: key }, value: { S: value } },
171
- }),
172
- );
173
- }
174
-
175
- async setWithTtl(key: string, value: string, ttl: number): Promise<void> {
176
- const client = await this.clientPromise;
177
- if (!client) throw new Error("DynamoDB unavailable");
178
- const ttlEpoch = Math.floor(Date.now() / 1000) + Math.max(1, ttl);
179
- await client.send(
180
- new client.PutItemCommand({
181
- TableName: this.table,
182
- Item: { runId: { S: key }, value: { S: value }, ttl: { N: String(ttlEpoch) } },
183
- }),
184
- );
185
- }
186
- }
187
-
188
- // ---------------------------------------------------------------------------
189
- // Factory — resolves the user's storage config into a RawKVStore, or
190
- // undefined when the provider is "local" or "memory" (handled by callers).
191
- // ---------------------------------------------------------------------------
192
-
193
- export const createRawKVStore = (config?: StateConfig): RawKVStore | undefined => {
194
- const provider = config?.provider ?? "local";
195
-
196
- if (provider === "upstash") {
197
- const urlEnv = config?.urlEnv ?? (process.env.UPSTASH_REDIS_REST_URL ? "UPSTASH_REDIS_REST_URL" : "KV_REST_API_URL");
198
- const tokenEnv = config?.tokenEnv ?? (process.env.UPSTASH_REDIS_REST_TOKEN ? "UPSTASH_REDIS_REST_TOKEN" : "KV_REST_API_TOKEN");
199
- const url = process.env[urlEnv] ?? "";
200
- const token = process.env[tokenEnv] ?? "";
201
- if (url && token) return new UpstashKVStore(url, token);
202
- }
203
-
204
- if (provider === "redis") {
205
- const urlEnv = config?.urlEnv ?? "REDIS_URL";
206
- const url = process.env[urlEnv] ?? "";
207
- if (url) return new RedisKVStore(url);
208
- }
209
-
210
- if (provider === "dynamodb") {
211
- const table = config?.table ?? process.env.PONCHO_DYNAMODB_TABLE ?? "";
212
- if (table) return new DynamoDbKVStore(table, config?.region);
213
- }
214
-
215
- return undefined;
216
- };