tuff-lil-unit 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +84 -0
- package/dist/budget.d.ts +14 -0
- package/dist/budget.d.ts.map +1 -0
- package/dist/budget.js +30 -0
- package/dist/budget.js.map +1 -0
- package/dist/context.d.ts +76 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +236 -0
- package/dist/context.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/job.d.ts +8 -0
- package/dist/job.d.ts.map +1 -0
- package/dist/job.js +195 -0
- package/dist/job.js.map +1 -0
- package/dist/providers/anthropic.d.ts +3 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +6 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/base.d.ts +21 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +89 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/claude-cli.d.ts +16 -0
- package/dist/providers/claude-cli.d.ts.map +1 -0
- package/dist/providers/claude-cli.js +194 -0
- package/dist/providers/claude-cli.js.map +1 -0
- package/dist/providers/openai.d.ts +3 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +6 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/rate-limit.d.ts +8 -0
- package/dist/rate-limit.d.ts.map +1 -0
- package/dist/rate-limit.js +52 -0
- package/dist/rate-limit.js.map +1 -0
- package/dist/retry.d.ts +12 -0
- package/dist/retry.d.ts.map +1 -0
- package/dist/retry.js +59 -0
- package/dist/retry.js.map +1 -0
- package/dist/schema-sync.d.ts +7 -0
- package/dist/schema-sync.d.ts.map +1 -0
- package/dist/schema-sync.js +32 -0
- package/dist/schema-sync.js.map +1 -0
- package/dist/schema.d.ts +24 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +27 -0
- package/dist/schema.js.map +1 -0
- package/dist/state.d.ts +28 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +86 -0
- package/dist/state.js.map +1 -0
- package/dist/tuff.d.ts +8 -0
- package/dist/tuff.d.ts.map +1 -0
- package/dist/tuff.js +73 -0
- package/dist/tuff.js.map +1 -0
- package/dist/types.d.ts +49 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/upsert.d.ts +9 -0
- package/dist/upsert.d.ts.map +1 -0
- package/dist/upsert.js +42 -0
- package/dist/upsert.js.map +1 -0
- package/dist/workflow.d.ts +12 -0
- package/dist/workflow.d.ts.map +1 -0
- package/dist/workflow.js +507 -0
- package/dist/workflow.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
export class RateLimiter {
|
|
2
|
+
#rpm;
|
|
3
|
+
#tpm;
|
|
4
|
+
#requestTokens;
|
|
5
|
+
#tokenBucketTokens;
|
|
6
|
+
#lastRefill;
|
|
7
|
+
constructor(config) {
|
|
8
|
+
this.#rpm = config.rpm;
|
|
9
|
+
this.#tpm = config.tpm;
|
|
10
|
+
this.#requestTokens = config.rpm;
|
|
11
|
+
this.#tokenBucketTokens = config.tpm;
|
|
12
|
+
this.#lastRefill = Date.now();
|
|
13
|
+
}
|
|
14
|
+
tryAcquire(estimatedTokens = 0) {
|
|
15
|
+
this.#refill();
|
|
16
|
+
if (this.#rpm === 0 && this.#tpm === 0)
|
|
17
|
+
return true;
|
|
18
|
+
const needsRequest = this.#rpm > 0;
|
|
19
|
+
const needsTokens = this.#tpm > 0 && estimatedTokens > 0;
|
|
20
|
+
const hasRequestCapacity = !needsRequest || this.#requestTokens >= 1;
|
|
21
|
+
const hasTokenCapacity = !needsTokens || this.#tokenBucketTokens >= estimatedTokens;
|
|
22
|
+
if (hasRequestCapacity && hasTokenCapacity) {
|
|
23
|
+
if (needsRequest)
|
|
24
|
+
this.#requestTokens -= 1;
|
|
25
|
+
if (needsTokens)
|
|
26
|
+
this.#tokenBucketTokens -= estimatedTokens;
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
release(actualTokens) {
|
|
32
|
+
// Token bucket already consumed estimated tokens in tryAcquire
|
|
33
|
+
// This method could be used to adjust if actual differs from estimated
|
|
34
|
+
// For now, no-op as we pre-consume estimated tokens
|
|
35
|
+
}
|
|
36
|
+
#refill() {
|
|
37
|
+
const now = Date.now();
|
|
38
|
+
const elapsedMs = now - this.#lastRefill;
|
|
39
|
+
if (elapsedMs <= 0)
|
|
40
|
+
return;
|
|
41
|
+
if (this.#rpm > 0) {
|
|
42
|
+
const requestRefill = (this.#rpm / 60000) * elapsedMs;
|
|
43
|
+
this.#requestTokens = Math.min(this.#requestTokens + requestRefill, this.#rpm);
|
|
44
|
+
}
|
|
45
|
+
if (this.#tpm > 0) {
|
|
46
|
+
const tokenRefill = (this.#tpm / 60000) * elapsedMs;
|
|
47
|
+
this.#tokenBucketTokens = Math.min(this.#tokenBucketTokens + tokenRefill, this.#tpm);
|
|
48
|
+
}
|
|
49
|
+
this.#lastRefill = now;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=rate-limit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,WAAW;IACtB,IAAI,CAAS;IACb,IAAI,CAAS;IACb,cAAc,CAAS;IACvB,kBAAkB,CAAS;IAC3B,WAAW,CAAS;IAEpB,YAAY,MAAiB;QAC3B,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC;QACjC,IAAI,CAAC,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAC;QACrC,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAChC,CAAC;IAED,UAAU,CAAC,kBAA0B,CAAC;QACpC,IAAI,CAAC,OAAO,EAAE,CAAC;QAEf,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC;QAEpD,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QACnC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,eAAe,GAAG,CAAC,CAAC;QAEzD,MAAM,kBAAkB,GAAG,CAAC,YAAY,IAAI,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;QACrE,MAAM,gBAAgB,GAAG,CAAC,WAAW,IAAI,IAAI,CAAC,kBAAkB,IAAI,eAAe,CAAC;QAEpF,IAAI,kBAAkB,IAAI,gBAAgB,EAAE,CAAC;YAC3C,IAAI,YAAY;gBAAE,IAAI,CAAC,cAAc,IAAI,CAAC,CAAC;YAC3C,IAAI,WAAW;gBAAE,IAAI,CAAC,kBAAkB,IAAI,eAAe,CAAC;YAC5D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,KAAK,CAAC;IACf,CAAC;IAED,OAAO,CAAC,YAAoB;QAC1B,+DAA+D;QAC/D,uEAAuE;QACvE,oDAAoD;IACtD,CAAC;IAED,OAAO;QACL,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,SAAS,GAAG,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC;QAEzC,IAAI,SAAS,IAAI,CAAC;YAAE,OAAO;QAE3B,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,aAAa,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC;YACtD,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,GAAG,aAAa,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACjF,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAClB,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,GAAG,SAAS,CAAC;YACpD,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,GAAG,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACvF,CAAC;QAED,IAAI,CAAC,WAAW,GAAG,GAAG,CAAC;IACzB,CAAC;CACF"}
|
package/dist/retry.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Options as PRetryOptions } from 'p-retry';
|
|
2
|
+
export interface ErrorClassification {
|
|
3
|
+
type: 'rate_limit' | 'transient' | 'token_limit' | 'budget_exceeded' | 'permanent';
|
|
4
|
+
retriable: boolean;
|
|
5
|
+
retryAfterMs?: number;
|
|
6
|
+
}
|
|
7
|
+
export declare function classifyError(error: unknown): ErrorClassification;
|
|
8
|
+
/** Returns p-retry options using classifyError to decide retriability and respect Retry-After. */
|
|
9
|
+
export declare function createRetryConfig(opts?: {
|
|
10
|
+
maxRetries?: number;
|
|
11
|
+
}): PRetryOptions;
|
|
12
|
+
//# sourceMappingURL=retry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.d.ts","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,IAAI,aAAa,EAAgB,MAAM,SAAS,CAAC;AAEtE,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,YAAY,GAAG,WAAW,GAAG,aAAa,GAAG,iBAAiB,GAAG,WAAW,CAAC;IACnF,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,mBAAmB,CAkDjE;AAED,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,IAAI,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,aAAa,CAmB/E"}
|
package/dist/retry.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export function classifyError(error) {
|
|
2
|
+
if (!error) {
|
|
3
|
+
return { type: 'permanent', retriable: false };
|
|
4
|
+
}
|
|
5
|
+
// Check for enhanced error types with retryAfterMs
|
|
6
|
+
if (error instanceof Error && 'retryAfterMs' in error) {
|
|
7
|
+
const retryAfterMs = error.retryAfterMs;
|
|
8
|
+
return {
|
|
9
|
+
type: 'rate_limit',
|
|
10
|
+
retriable: true,
|
|
11
|
+
retryAfterMs,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
const errorObj = error;
|
|
15
|
+
const message = String(errorObj.message || error).toLowerCase();
|
|
16
|
+
if (errorObj.status === 429 || message.includes('rate limit')) {
|
|
17
|
+
return { type: 'rate_limit', retriable: true };
|
|
18
|
+
}
|
|
19
|
+
if (message.includes('token limit') ||
|
|
20
|
+
message.includes('context limit') ||
|
|
21
|
+
message.includes('maximum context') ||
|
|
22
|
+
message.includes('too many tokens')) {
|
|
23
|
+
return { type: 'token_limit', retriable: false };
|
|
24
|
+
}
|
|
25
|
+
if (message.includes('budget exceeded')) {
|
|
26
|
+
return { type: 'budget_exceeded', retriable: false };
|
|
27
|
+
}
|
|
28
|
+
// AbortError from per-request timeouts (AbortController pattern) — retriable
|
|
29
|
+
// Note: pipeline-level aborts are handled separately in context.ts (signal check)
|
|
30
|
+
if (errorObj.name === 'AbortError' || message.includes('timed out')) {
|
|
31
|
+
return { type: 'transient', retriable: true };
|
|
32
|
+
}
|
|
33
|
+
if (typeof errorObj.status === 'number' &&
|
|
34
|
+
errorObj.status >= 500 &&
|
|
35
|
+
errorObj.status < 600) {
|
|
36
|
+
return { type: 'transient', retriable: true };
|
|
37
|
+
}
|
|
38
|
+
return { type: 'permanent', retriable: false };
|
|
39
|
+
}
|
|
40
|
+
/** Returns p-retry options using classifyError to decide retriability and respect Retry-After. */
|
|
41
|
+
export function createRetryConfig(opts) {
|
|
42
|
+
return {
|
|
43
|
+
retries: opts?.maxRetries ?? 3,
|
|
44
|
+
factor: 2,
|
|
45
|
+
minTimeout: 1000,
|
|
46
|
+
maxTimeout: 60_000,
|
|
47
|
+
shouldRetry: (context) => {
|
|
48
|
+
const classification = classifyError(context.error);
|
|
49
|
+
return classification.retriable;
|
|
50
|
+
},
|
|
51
|
+
onFailedAttempt: async (context) => {
|
|
52
|
+
const classification = classifyError(context.error);
|
|
53
|
+
if (classification.retriable && classification.retryAfterMs && context.retriesLeft > 0) {
|
|
54
|
+
await new Promise((resolve) => setTimeout(resolve, classification.retryAfterMs));
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../src/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
/**
|
|
3
|
+
* Sync schema to DB — creates new tables via IF NOT EXISTS, adds new columns
|
|
4
|
+
* via PRAGMA table_info diffing + ALTER TABLE ADD COLUMN.
|
|
5
|
+
*/
|
|
6
|
+
export declare function syncSchema(db: Database.Database, statements: string[]): void;
|
|
7
|
+
//# sourceMappingURL=schema-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-sync.d.ts","sourceRoot":"","sources":["../src/schema-sync.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAM3C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,GAAG,IAAI,CA8B5E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync schema to DB — creates new tables via IF NOT EXISTS, adds new columns
|
|
3
|
+
* via PRAGMA table_info diffing + ALTER TABLE ADD COLUMN.
|
|
4
|
+
*/
|
|
5
|
+
export function syncSchema(db, statements) {
|
|
6
|
+
for (const sql of statements) {
|
|
7
|
+
db.exec(sql);
|
|
8
|
+
// After CREATE TABLE IF NOT EXISTS, diff columns for additive migrations
|
|
9
|
+
const match = sql.match(/CREATE\s+TABLE\s+IF\s+NOT\s+EXISTS\s+(\w+)/i);
|
|
10
|
+
if (!match)
|
|
11
|
+
continue;
|
|
12
|
+
const tableName = match[1];
|
|
13
|
+
const existingCols = new Set(db.prepare(`PRAGMA table_info('${tableName}')`).all()
|
|
14
|
+
.map((c) => c.name));
|
|
15
|
+
// Parse column definitions — strip table constraints before splitting on commas
|
|
16
|
+
const bodyMatch = sql.match(/\(([^]*)\)/);
|
|
17
|
+
if (!bodyMatch)
|
|
18
|
+
continue;
|
|
19
|
+
// Remove PRIMARY KEY(...) and similar table constraints before comma-splitting
|
|
20
|
+
const body = bodyMatch[1].replace(/,?\s*PRIMARY\s+KEY\s*\([^)]*\)/gi, '');
|
|
21
|
+
for (const line of body.split(',')) {
|
|
22
|
+
const trimmed = line.trim();
|
|
23
|
+
if (!trimmed)
|
|
24
|
+
continue;
|
|
25
|
+
const colName = trimmed.split(/\s+/)[0];
|
|
26
|
+
if (!existingCols.has(colName)) {
|
|
27
|
+
db.exec(`ALTER TABLE ${tableName} ADD COLUMN ${trimmed}`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=schema-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-sync.js","sourceRoot":"","sources":["../src/schema-sync.ts"],"names":[],"mappings":"AAMA;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,EAAqB,EAAE,UAAoB;IACpE,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEb,yEAAyE;QACzE,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,6CAA6C,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAE,CAAC;QAE5B,MAAM,YAAY,GAAG,IAAI,GAAG,CACzB,EAAE,CAAC,OAAO,CAAC,sBAAsB,SAAS,IAAI,CAAC,CAAC,GAAG,EAAmB;aACpE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CACtB,CAAC;QAEF,gFAAgF;QAChF,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;QAC1C,IAAI,CAAC,SAAS;YAAE,SAAS;QAEzB,+EAA+E;QAC/E,MAAM,IAAI,GAAG,SAAS,CAAC,CAAC,CAAE,CAAC,OAAO,CAAC,kCAAkC,EAAE,EAAE,CAAC,CAAC;QAE3E,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;YACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,SAAS;YACvB,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,CAAC;YACzC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC/B,EAAE,CAAC,IAAI,CAAC,eAAe,SAAS,eAAe,OAAO,EAAE,CAAC,CAAC;YAC5D,CAAC;QACH,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const SCHEMA_SQL: string[];
|
|
2
|
+
export interface TuffRun {
|
|
3
|
+
id: string;
|
|
4
|
+
config: string | null;
|
|
5
|
+
created_at: string;
|
|
6
|
+
updated_at: string;
|
|
7
|
+
}
|
|
8
|
+
export interface TuffStep {
|
|
9
|
+
run_id: string;
|
|
10
|
+
step_id: string;
|
|
11
|
+
output: string;
|
|
12
|
+
usage_input: number;
|
|
13
|
+
usage_output: number;
|
|
14
|
+
duration_ms: number | null;
|
|
15
|
+
created_at: string;
|
|
16
|
+
}
|
|
17
|
+
export interface TuffStepFailure {
|
|
18
|
+
run_id: string;
|
|
19
|
+
step_id: string;
|
|
20
|
+
error: string;
|
|
21
|
+
duration_ms: number | null;
|
|
22
|
+
created_at: string;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=schema.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,UAAU,UAyBtB,CAAC;AAEF,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB"}
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const SCHEMA_SQL = [
|
|
2
|
+
`CREATE TABLE IF NOT EXISTS tuff_runs (
|
|
3
|
+
id TEXT PRIMARY KEY,
|
|
4
|
+
config TEXT,
|
|
5
|
+
created_at TEXT NOT NULL,
|
|
6
|
+
updated_at TEXT NOT NULL
|
|
7
|
+
)`,
|
|
8
|
+
`CREATE TABLE IF NOT EXISTS tuff_steps (
|
|
9
|
+
run_id TEXT NOT NULL,
|
|
10
|
+
step_id TEXT NOT NULL,
|
|
11
|
+
output TEXT NOT NULL,
|
|
12
|
+
usage_input INTEGER NOT NULL DEFAULT 0,
|
|
13
|
+
usage_output INTEGER NOT NULL DEFAULT 0,
|
|
14
|
+
duration_ms INTEGER,
|
|
15
|
+
created_at TEXT NOT NULL,
|
|
16
|
+
PRIMARY KEY (run_id, step_id)
|
|
17
|
+
)`,
|
|
18
|
+
`CREATE TABLE IF NOT EXISTS tuff_step_failures (
|
|
19
|
+
run_id TEXT NOT NULL,
|
|
20
|
+
step_id TEXT NOT NULL,
|
|
21
|
+
error TEXT NOT NULL,
|
|
22
|
+
duration_ms INTEGER,
|
|
23
|
+
created_at TEXT NOT NULL,
|
|
24
|
+
PRIMARY KEY (run_id, step_id)
|
|
25
|
+
)`,
|
|
26
|
+
];
|
|
27
|
+
//# sourceMappingURL=schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.js","sourceRoot":"","sources":["../src/schema.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB;;;;;IAKE;IACF;;;;;;;;;IASE;IACF;;;;;;;IAOE;CACH,CAAC"}
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import type { TuffRun, TuffStepFailure } from './schema.js';
|
|
3
|
+
import type { TokenUsage } from './types.js';
|
|
4
|
+
export declare class StateManager {
|
|
5
|
+
#private;
|
|
6
|
+
constructor(db: Database.Database, runId: string);
|
|
7
|
+
initRun(id: string, config: unknown): void;
|
|
8
|
+
getRun(id: string): TuffRun | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the deserialized output for a step, or undefined if not found.
|
|
11
|
+
* Step functions must return JSON-serializable values — Date, Buffer, and
|
|
12
|
+
* class instances silently corrupt on round-trip.
|
|
13
|
+
*/
|
|
14
|
+
getStep(stepId: string): unknown;
|
|
15
|
+
setStep(stepId: string, output: unknown, usage?: {
|
|
16
|
+
inputTokens: number;
|
|
17
|
+
outputTokens: number;
|
|
18
|
+
}, durationMs?: number): void;
|
|
19
|
+
setStepFailure(stepId: string, error: string, durationMs?: number): void;
|
|
20
|
+
getStepFailure(stepId: string): TuffStepFailure | undefined;
|
|
21
|
+
/** Purge cached output + failure for a step — used by force invalidation. */
|
|
22
|
+
deleteStep(stepId: string): void;
|
|
23
|
+
/** Total steps completed in the previous run — seeds progress prediction on resume. */
|
|
24
|
+
getStepCount(): number;
|
|
25
|
+
/** Sums token usage across all completed steps — used to restore BudgetManager on resume. */
|
|
26
|
+
getUsageSummary(): TokenUsage;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,qBAAa,YAAY;;gBAIX,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM;IAKhD,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI;IAO1C,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,GAAG,SAAS;IAIvC;;;;OAIG;IACH,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO;IAShC,OAAO,CACL,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,OAAO,EACf,KAAK,CAAC,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,EACrD,UAAU,CAAC,EAAE,MAAM,GAClB,IAAI;IAoCP,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAYxE,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS;IAM3D,6EAA6E;IAC7E,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAWhC,uFAAuF;IACvF,YAAY,IAAI,MAAM;IAOtB,6FAA6F;IAC7F,eAAe,IAAI,UAAU;CAU9B"}
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export class StateManager {
|
|
2
|
+
#db;
|
|
3
|
+
#runId;
|
|
4
|
+
constructor(db, runId) {
|
|
5
|
+
this.#db = db;
|
|
6
|
+
this.#runId = runId;
|
|
7
|
+
}
|
|
8
|
+
initRun(id, config) {
|
|
9
|
+
const now = new Date().toISOString();
|
|
10
|
+
this.#db.prepare('INSERT INTO tuff_runs (id, config, created_at, updated_at) VALUES (?, ?, ?, ?)').run(id, JSON.stringify(config), now, now);
|
|
11
|
+
}
|
|
12
|
+
getRun(id) {
|
|
13
|
+
return this.#db.prepare('SELECT * FROM tuff_runs WHERE id = ?').get(id);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Returns the deserialized output for a step, or undefined if not found.
|
|
17
|
+
* Step functions must return JSON-serializable values — Date, Buffer, and
|
|
18
|
+
* class instances silently corrupt on round-trip.
|
|
19
|
+
*/
|
|
20
|
+
getStep(stepId) {
|
|
21
|
+
const row = this.#db.prepare('SELECT output FROM tuff_steps WHERE run_id = ? AND step_id = ?').get(this.#runId, stepId);
|
|
22
|
+
if (!row)
|
|
23
|
+
return undefined;
|
|
24
|
+
return JSON.parse(row.output);
|
|
25
|
+
}
|
|
26
|
+
setStep(stepId, output, usage, durationMs) {
|
|
27
|
+
// Provider outputs are already JSON-safe: generateText returns strings,
|
|
28
|
+
// generateObject validates through zod. This guard only catches raw step
|
|
29
|
+
// callbacks returning functions/symbols (→ JSON.stringify returns undefined).
|
|
30
|
+
// Date/Map/Set produce valid-but-lossy JSON — user's responsibility per JSDoc.
|
|
31
|
+
const serialized = JSON.stringify(output);
|
|
32
|
+
if (serialized === undefined) {
|
|
33
|
+
throw new Error(`Step '${stepId}' returned a non-JSON-serializable value (function or symbol)`);
|
|
34
|
+
}
|
|
35
|
+
const now = new Date().toISOString();
|
|
36
|
+
// Atomically write success + clear any prior failure record
|
|
37
|
+
this.#db.transaction(() => {
|
|
38
|
+
this.#db.prepare(`
|
|
39
|
+
INSERT INTO tuff_steps (run_id, step_id, output, usage_input, usage_output, duration_ms, created_at)
|
|
40
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
41
|
+
ON CONFLICT (run_id, step_id) DO UPDATE SET
|
|
42
|
+
output = excluded.output,
|
|
43
|
+
usage_input = excluded.usage_input,
|
|
44
|
+
usage_output = excluded.usage_output,
|
|
45
|
+
duration_ms = excluded.duration_ms,
|
|
46
|
+
created_at = excluded.created_at
|
|
47
|
+
`).run(this.#runId, stepId, serialized, usage?.inputTokens ?? 0, usage?.outputTokens ?? 0, durationMs ?? null, now);
|
|
48
|
+
this.#db.prepare('DELETE FROM tuff_step_failures WHERE run_id = ? AND step_id = ?').run(this.#runId, stepId);
|
|
49
|
+
})();
|
|
50
|
+
}
|
|
51
|
+
setStepFailure(stepId, error, durationMs) {
|
|
52
|
+
const now = new Date().toISOString();
|
|
53
|
+
this.#db.prepare(`
|
|
54
|
+
INSERT INTO tuff_step_failures (run_id, step_id, error, duration_ms, created_at)
|
|
55
|
+
VALUES (?, ?, ?, ?, ?)
|
|
56
|
+
ON CONFLICT (run_id, step_id) DO UPDATE SET
|
|
57
|
+
error = excluded.error,
|
|
58
|
+
duration_ms = excluded.duration_ms,
|
|
59
|
+
created_at = excluded.created_at
|
|
60
|
+
`).run(this.#runId, stepId, error, durationMs ?? null, now);
|
|
61
|
+
}
|
|
62
|
+
getStepFailure(stepId) {
|
|
63
|
+
return this.#db.prepare('SELECT * FROM tuff_step_failures WHERE run_id = ? AND step_id = ?').get(this.#runId, stepId);
|
|
64
|
+
}
|
|
65
|
+
/** Purge cached output + failure for a step — used by force invalidation. */
|
|
66
|
+
deleteStep(stepId) {
|
|
67
|
+
this.#db.transaction(() => {
|
|
68
|
+
this.#db.prepare('DELETE FROM tuff_steps WHERE run_id = ? AND step_id = ?').run(this.#runId, stepId);
|
|
69
|
+
this.#db.prepare('DELETE FROM tuff_step_failures WHERE run_id = ? AND step_id = ?').run(this.#runId, stepId);
|
|
70
|
+
})();
|
|
71
|
+
}
|
|
72
|
+
/** Total steps completed in the previous run — seeds progress prediction on resume. */
|
|
73
|
+
getStepCount() {
|
|
74
|
+
const row = this.#db.prepare('SELECT COUNT(*) AS count FROM tuff_steps WHERE run_id = ?').get(this.#runId);
|
|
75
|
+
return row.count;
|
|
76
|
+
}
|
|
77
|
+
/** Sums token usage across all completed steps — used to restore BudgetManager on resume. */
|
|
78
|
+
getUsageSummary() {
|
|
79
|
+
const row = this.#db.prepare('SELECT COALESCE(SUM(usage_input), 0) AS input_total, COALESCE(SUM(usage_output), 0) AS output_total FROM tuff_steps WHERE run_id = ?').get(this.#runId);
|
|
80
|
+
return {
|
|
81
|
+
inputTokens: row.input_total,
|
|
82
|
+
outputTokens: row.output_total,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"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"}
|
package/dist/tuff.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Context } from './context.js';
|
|
2
|
+
import type { DurableConfig } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Run a durable pipeline with step memoization. Call again with the same id to
|
|
5
|
+
* resume — cached steps return instantly, execution continues from first uncached step.
|
|
6
|
+
*/
|
|
7
|
+
export declare function tuff<T>(id: string, config: DurableConfig, fn: (ctx: Context) => Promise<T>): Promise<T>;
|
|
8
|
+
//# sourceMappingURL=tuff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tuff.d.ts","sourceRoot":"","sources":["../src/tuff.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD;;;GAGG;AACH,wBAAsB,IAAI,CAAC,CAAC,EAC1B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,CAAC,CAAC,GAC/B,OAAO,CAAC,CAAC,CAAC,CAgEZ"}
|
package/dist/tuff.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import { mkdirSync } from 'node:fs';
|
|
3
|
+
import { BudgetManager } from './budget.js';
|
|
4
|
+
import { Context } from './context.js';
|
|
5
|
+
import { SCHEMA_SQL } from './schema.js';
|
|
6
|
+
import { syncSchema } from './schema-sync.js';
|
|
7
|
+
import { StateManager } from './state.js';
|
|
8
|
+
/**
|
|
9
|
+
* Run a durable pipeline with step memoization. Call again with the same id to
|
|
10
|
+
* resume — cached steps return instantly, execution continues from first uncached step.
|
|
11
|
+
*/
|
|
12
|
+
export async function tuff(id, config, fn) {
|
|
13
|
+
if (!id)
|
|
14
|
+
throw new Error('tuff: id must be a non-empty string');
|
|
15
|
+
if (!config.stateDir)
|
|
16
|
+
throw new Error('tuff: stateDir is required');
|
|
17
|
+
if (config.concurrency !== undefined && (config.concurrency < 1 || !Number.isInteger(config.concurrency))) {
|
|
18
|
+
throw new Error('tuff: concurrency must be a positive integer');
|
|
19
|
+
}
|
|
20
|
+
if (config.budget?.tokens !== undefined && config.budget.tokens < 1) {
|
|
21
|
+
throw new Error('tuff: budget.tokens must be positive');
|
|
22
|
+
}
|
|
23
|
+
const controller = new AbortController();
|
|
24
|
+
const onSignal = () => controller.abort();
|
|
25
|
+
if (config.handleProcessSignals) {
|
|
26
|
+
process.on('SIGTERM', onSignal);
|
|
27
|
+
process.on('SIGINT', onSignal);
|
|
28
|
+
}
|
|
29
|
+
mkdirSync(config.stateDir, { recursive: true });
|
|
30
|
+
const db = new Database(`${config.stateDir}/tuff.db`);
|
|
31
|
+
db.pragma('journal_mode = WAL');
|
|
32
|
+
db.pragma('busy_timeout = 5000');
|
|
33
|
+
syncSchema(db, [...SCHEMA_SQL, ...(config.setup ?? [])]);
|
|
34
|
+
const state = new StateManager(db, id);
|
|
35
|
+
// Resume detection: if run exists, continue; otherwise initialize
|
|
36
|
+
const existingRun = state.getRun(id);
|
|
37
|
+
if (!existingRun) {
|
|
38
|
+
const { setup: _setup, ...serializableConfig } = config;
|
|
39
|
+
state.initRun(id, serializableConfig);
|
|
40
|
+
}
|
|
41
|
+
// Restore budget from prior run so remaining budget is accurate on resume
|
|
42
|
+
const budgetManager = new BudgetManager(config.budget);
|
|
43
|
+
const priorUsage = state.getUsageSummary();
|
|
44
|
+
if (priorUsage.inputTokens > 0 || priorUsage.outputTokens > 0) {
|
|
45
|
+
budgetManager.consume(priorUsage);
|
|
46
|
+
}
|
|
47
|
+
const ctx = new Context({
|
|
48
|
+
id,
|
|
49
|
+
concurrency: config.concurrency ?? 5,
|
|
50
|
+
onProgress: config.onProgress,
|
|
51
|
+
signal: controller.signal,
|
|
52
|
+
state,
|
|
53
|
+
budgetManager,
|
|
54
|
+
db,
|
|
55
|
+
});
|
|
56
|
+
try {
|
|
57
|
+
return await fn(ctx);
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
// Log before aborting — queued steps will throw AbortError, masking this root cause
|
|
61
|
+
console.error('[tuff] Pipeline error:', error);
|
|
62
|
+
controller.abort();
|
|
63
|
+
throw error;
|
|
64
|
+
}
|
|
65
|
+
finally {
|
|
66
|
+
if (config.handleProcessSignals) {
|
|
67
|
+
process.off('SIGTERM', onSignal);
|
|
68
|
+
process.off('SIGINT', onSignal);
|
|
69
|
+
}
|
|
70
|
+
db.close();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=tuff.js.map
|
package/dist/tuff.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tuff.js","sourceRoot":"","sources":["../src/tuff.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export interface TokenUsage {
|
|
2
|
+
inputTokens: number;
|
|
3
|
+
outputTokens: number;
|
|
4
|
+
cacheCreationTokens?: number;
|
|
5
|
+
cacheReadTokens?: number;
|
|
6
|
+
}
|
|
7
|
+
export interface ProviderResult {
|
|
8
|
+
output: unknown;
|
|
9
|
+
usage: TokenUsage;
|
|
10
|
+
durationMs: number;
|
|
11
|
+
}
|
|
12
|
+
export interface Progress {
|
|
13
|
+
stage: string;
|
|
14
|
+
completed: number;
|
|
15
|
+
total: number;
|
|
16
|
+
usage: {
|
|
17
|
+
tokens: number;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** Per-step budget limits — controls token spend on individual steps. */
|
|
21
|
+
export interface StepBudget {
|
|
22
|
+
/** Cap output tokens (API-enforced for LLM providers, total-token kill-threshold for Claude CLI). */
|
|
23
|
+
maxTokens?: number;
|
|
24
|
+
/** Pre-call input token check — refuses execution if estimated input exceeds limit. */
|
|
25
|
+
maxInputTokens?: number;
|
|
26
|
+
/** Behavior when post-call actual usage exceeds limits. Default: 'throw'. */
|
|
27
|
+
onExceed?: 'throw' | 'warn';
|
|
28
|
+
/** Override the default chars/4 estimator for pre-call input checks. */
|
|
29
|
+
tokenEstimator?: (text: string) => number;
|
|
30
|
+
}
|
|
31
|
+
export interface DurableConfig {
|
|
32
|
+
stateDir: string;
|
|
33
|
+
/** Max steps to run in parallel. Defaults to 5 — conservative for rate-limited LLM APIs. */
|
|
34
|
+
concurrency?: number;
|
|
35
|
+
budget?: {
|
|
36
|
+
tokens: number;
|
|
37
|
+
};
|
|
38
|
+
onProgress?: (progress: Progress) => void;
|
|
39
|
+
/** Register SIGTERM/SIGINT handlers for graceful abort. Default: false. */
|
|
40
|
+
handleProcessSignals?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Additional SQL CREATE TABLE statements to execute at startup.
|
|
43
|
+
* @example
|
|
44
|
+
* const setup = ['CREATE TABLE IF NOT EXISTS pages (url TEXT PRIMARY KEY, title TEXT)'];
|
|
45
|
+
* tuff('id', { stateDir, setup }, async (ctx) => { ... });
|
|
46
|
+
*/
|
|
47
|
+
setup?: string[];
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAGD,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAGD,MAAM,WAAW,QAAQ;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3B;AAED,yEAAyE;AACzE,MAAM,WAAW,UAAU;IACzB,qGAAqG;IACrG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uFAAuF;IACvF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,QAAQ,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAC5B,wEAAwE;IACxE,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;CAC3C;AAGD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5B,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1C,2EAA2E;IAC3E,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;CAClB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/upsert.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
/** JSON.stringify arrays and plain objects; coerce booleans to 0/1; primitives pass through. */
|
|
3
|
+
export declare function autoStringify(row: Record<string, unknown>): Record<string, unknown>;
|
|
4
|
+
/**
|
|
5
|
+
* Upsert a row: auto-stringify objects/arrays, build conflict update from non-PK columns.
|
|
6
|
+
* Row keys must match SQL column names (snake_case).
|
|
7
|
+
*/
|
|
8
|
+
export declare function upsertRow(db: Database.Database, table: string, row: Record<string, unknown>, updateColumns?: string[]): void;
|
|
9
|
+
//# sourceMappingURL=upsert.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsert.d.ts","sourceRoot":"","sources":["../src/upsert.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAO3C,gGAAgG;AAChG,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAYnF;AAED;;;GAGG;AACH,wBAAgB,SAAS,CACvB,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC5B,aAAa,CAAC,EAAE,MAAM,EAAE,GACvB,IAAI,CAyBN"}
|
package/dist/upsert.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/** JSON.stringify arrays and plain objects; coerce booleans to 0/1; primitives pass through. */
|
|
2
|
+
export function autoStringify(row) {
|
|
3
|
+
const out = {};
|
|
4
|
+
for (const [k, v] of Object.entries(row)) {
|
|
5
|
+
if (typeof v === 'boolean') {
|
|
6
|
+
out[k] = v ? 1 : 0;
|
|
7
|
+
}
|
|
8
|
+
else if (Array.isArray(v) || (v !== null && typeof v === 'object' && v.constructor === Object)) {
|
|
9
|
+
out[k] = JSON.stringify(v);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
out[k] = v;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Upsert a row: auto-stringify objects/arrays, build conflict update from non-PK columns.
|
|
19
|
+
* Row keys must match SQL column names (snake_case).
|
|
20
|
+
*/
|
|
21
|
+
export function upsertRow(db, table, row, updateColumns) {
|
|
22
|
+
const stringified = autoStringify(row);
|
|
23
|
+
const columns = db.prepare(`PRAGMA table_info('${table}')`).all();
|
|
24
|
+
const pkNames = new Set(columns.filter((c) => c.pk > 0).map((c) => c.name));
|
|
25
|
+
if (pkNames.size === 0) {
|
|
26
|
+
throw new Error(`No primary key found on table "${table}"`);
|
|
27
|
+
}
|
|
28
|
+
const colNames = Object.keys(stringified);
|
|
29
|
+
const values = Object.values(stringified);
|
|
30
|
+
const placeholders = colNames.map(() => '?').join(', ');
|
|
31
|
+
// Build SET clause: either explicit updateColumns or all non-PK columns present in row
|
|
32
|
+
const updateCols = updateColumns
|
|
33
|
+
? updateColumns.filter((c) => c in stringified)
|
|
34
|
+
: colNames.filter((c) => !pkNames.has(c));
|
|
35
|
+
const setClause = updateCols.map((c) => `${c} = excluded.${c}`).join(', ');
|
|
36
|
+
const pkList = [...pkNames].join(', ');
|
|
37
|
+
const sql = setClause
|
|
38
|
+
? `INSERT INTO ${table} (${colNames.join(', ')}) VALUES (${placeholders}) ON CONFLICT (${pkList}) DO UPDATE SET ${setClause}`
|
|
39
|
+
: `INSERT INTO ${table} (${colNames.join(', ')}) VALUES (${placeholders}) ON CONFLICT (${pkList}) DO NOTHING`;
|
|
40
|
+
db.prepare(sql).run(...values);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=upsert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upsert.js","sourceRoot":"","sources":["../src/upsert.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Job, WorkflowConfig, WorkflowResult } from './types.js';
|
|
2
|
+
export declare class Workflow {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(config: WorkflowConfig);
|
|
5
|
+
static resume(config: WorkflowConfig, options?: {
|
|
6
|
+
retryFailed?: boolean;
|
|
7
|
+
ignoreVersionMismatch?: boolean;
|
|
8
|
+
}): Workflow;
|
|
9
|
+
addJob(job: Job): void;
|
|
10
|
+
run(): Promise<WorkflowResult>;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=workflow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workflow.d.ts","sourceRoot":"","sources":["../src/workflow.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAyB,cAAc,EAAE,cAAc,EAAiB,MAAM,YAAY,CAAC;AAS5G,qBAAa,QAAQ;;gBAcP,MAAM,EAAE,cAAc;IAqBlC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,OAAO,CAAC;QAAC,qBAAqB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,QAAQ;IA0HrH,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IAwIhB,GAAG,IAAI,OAAO,CAAC,cAAc,CAAC;CA6RrC"}
|