@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.
- package/.turbo/turbo-build.log +12 -11
- package/CHANGELOG.md +25 -0
- package/dist/index.d.ts +485 -29
- package/dist/index.js +2839 -2114
- package/dist/isolate-TCWTUVG4.js +1532 -0
- package/package.json +23 -4
- package/scripts/migrate-to-engine.mjs +556 -0
- package/src/config.ts +106 -1
- package/src/harness.ts +226 -91
- package/src/index.ts +5 -0
- package/src/isolate/bindings.ts +206 -0
- package/src/isolate/bundler.ts +179 -0
- package/src/isolate/index.ts +10 -0
- package/src/isolate/polyfills.ts +796 -0
- package/src/isolate/run-code-tool.ts +220 -0
- package/src/isolate/runtime.ts +286 -0
- package/src/isolate/type-stubs.ts +196 -0
- package/src/memory.ts +129 -198
- package/src/reminder-store.ts +3 -237
- package/src/secrets-store.ts +2 -91
- package/src/state.ts +11 -1302
- package/src/storage/engine.ts +106 -0
- package/src/storage/index.ts +59 -0
- package/src/storage/memory-engine.ts +588 -0
- package/src/storage/postgres-engine.ts +139 -0
- package/src/storage/schema.ts +145 -0
- package/src/storage/sql-dialect.ts +963 -0
- package/src/storage/sqlite-engine.ts +99 -0
- package/src/storage/store-adapters.ts +100 -0
- package/src/todo-tools.ts +1 -136
- package/src/upload-store.ts +1 -0
- package/src/vfs/bash-manager.ts +120 -0
- package/src/vfs/bash-tool.ts +59 -0
- package/src/vfs/create-bash-fs.ts +32 -0
- package/src/vfs/edit-file-tool.ts +72 -0
- package/src/vfs/index.ts +5 -0
- package/src/vfs/poncho-fs-adapter.ts +267 -0
- package/src/vfs/protected-fs.ts +177 -0
- package/src/vfs/read-file-tool.ts +103 -0
- package/src/vfs/write-file-tool.ts +49 -0
- package/test/harness.test.ts +30 -36
- package/test/isolate-vfs.test.ts +453 -0
- package/test/isolate.test.ts +252 -0
- package/test/state.test.ts +4 -27
- package/test/storage-engine.test.ts +250 -0
- package/test/vfs.test.ts +242 -0
- package/.turbo/turbo-lint.log +0 -6
- package/.turbo/turbo-test.log +0 -11931
- 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
|
-
};
|