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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Unfamiliar City
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Tuff Lil Unit
|
|
2
|
+
|
|
3
|
+

|
|
4
|
+
|
|
5
|
+
A lil durable pipeline toolkit for AI coding agents.
|
|
6
|
+
|
|
7
|
+
Tuff's an ultra-simple implementation of the 'step function' pattern from Temporal and Inngest, built for AI coding agents like Claude Code and friends. Micro-scale, on your local machine.
|
|
8
|
+
|
|
9
|
+
It's just a little TypeScript and SQLite. Your agent could build this from scratch every time, but Tuff saves it the trouble — so it can focus on what you want to get done.
|
|
10
|
+
|
|
11
|
+
## Tuff features
|
|
12
|
+
|
|
13
|
+
- **Slot-based concurrency** — new tasks start when a slot opens (vs. Claude Code's native Tasks = max 10 concurrent in batched waves, slowest holds flow).
|
|
14
|
+
- **Three execution modes, mix freely** — LLM API calls, Claude Code headless using your subscription (play at your own risk), or any async function.
|
|
15
|
+
- **Concurrency per stage** — slot limits per phase (fan out high for HTTP fetches, throttle back for LLM processing).
|
|
16
|
+
- **Token budget** — global and per-step limits (Claude Code subprocess kills mid-run).
|
|
17
|
+
- **Progress and state is queryable** — step results, token usage, and durations land in Tuff's local db. Talk to Claude about progress during execution.
|
|
18
|
+
- **Domain storage** — define your own data tables alongside Tuff's state tables.
|
|
19
|
+
|
|
20
|
+
## An example pipeline
|
|
21
|
+
|
|
22
|
+
| Phase | What it does | Model | Calls | Concurrency |
|
|
23
|
+
|-------|-------------|-------|-------|-------------|
|
|
24
|
+
| Collect | Fetch 200 source URLs | *none* | 200 | 50 |
|
|
25
|
+
| Extract | Pull structured data from each page | GPT-5-nano | 200 | 10 |
|
|
26
|
+
| Classify | Score and categorise each result | GPT-5-mini | 200 | 5 |
|
|
27
|
+
| Distil | Aggregate into final report | *none* | 1 | 1 |
|
|
28
|
+
|
|
29
|
+
~400 LLM calls, 200 HTTP fetches, 4 phases. One `tuff()` call.
|
|
30
|
+
|
|
31
|
+
## Getting started
|
|
32
|
+
|
|
33
|
+
Install the skill:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
/plugin marketplace add unfamiliar-city/marketplace
|
|
37
|
+
/plugin install tuff
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Then use it:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
Claude Code
|
|
44
|
+
Opus 4.6 · Claude API
|
|
45
|
+
~/Projects/myproject
|
|
46
|
+
|
|
47
|
+
> /tuff build me a pipeline to make a million bucks.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Code example
|
|
51
|
+
|
|
52
|
+
The entire runtime is one function call:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// Pipeline 'my-pipeline', state persisted to ./state/tuff.db
|
|
56
|
+
await tuff('my-pipeline', { stateDir: './state' }, async (ctx) => {
|
|
57
|
+
|
|
58
|
+
// Durable step — if this succeeded before, returns cached result instantly
|
|
59
|
+
const data = await ctx.step('fetch', async () => fetchAll());
|
|
60
|
+
|
|
61
|
+
// Fan out — one step per item, concurrent within slot limit
|
|
62
|
+
// Each has a unique ID, so on resume only uncompleted ones re-execute
|
|
63
|
+
const results = await Promise.all(
|
|
64
|
+
data.map((item) => ctx.step(item.id, async () => process(item)))
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
// Fan in — summarise all results
|
|
68
|
+
return ctx.step('summarise', async () => summarise(results));
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Status
|
|
73
|
+
|
|
74
|
+
> You either die a hero or you live long enough to see yourself reimplementing Kubernetes.
|
|
75
|
+
|
|
76
|
+
Alpha.
|
|
77
|
+
|
|
78
|
+
Not production-tested.
|
|
79
|
+
|
|
80
|
+
**Claude Code CLI provider** — a house of cards on top of undocumented Claude Code internals. Use if you're relaxed about robustness, approximate budget tracking is good enough, and you want to use your Claude subscription.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT
|
package/dist/budget.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { TokenUsage } from './types.js';
|
|
2
|
+
export declare class BudgetManager {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(globalBudget?: {
|
|
5
|
+
tokens: number;
|
|
6
|
+
timeMs?: number;
|
|
7
|
+
});
|
|
8
|
+
consume(usage: TokenUsage): void;
|
|
9
|
+
canAfford(estimatedTokens: number): boolean;
|
|
10
|
+
isExceeded(): boolean;
|
|
11
|
+
remaining(): number;
|
|
12
|
+
totalUsed(): number;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,qBAAa,aAAa;;gBAIZ,YAAY,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE;IAI9D,OAAO,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI;IAKhC,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO;IAK3C,UAAU,IAAI,OAAO;IAKrB,SAAS,IAAI,MAAM;IAKnB,SAAS,IAAI,MAAM;CAGpB"}
|
package/dist/budget.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export class BudgetManager {
|
|
2
|
+
#globalBudget;
|
|
3
|
+
#totalUsed = 0;
|
|
4
|
+
constructor(globalBudget) {
|
|
5
|
+
this.#globalBudget = globalBudget;
|
|
6
|
+
}
|
|
7
|
+
consume(usage) {
|
|
8
|
+
const tokens = usage.inputTokens + usage.outputTokens + (usage.cacheCreationTokens ?? 0);
|
|
9
|
+
this.#totalUsed += tokens;
|
|
10
|
+
}
|
|
11
|
+
canAfford(estimatedTokens) {
|
|
12
|
+
if (!this.#globalBudget)
|
|
13
|
+
return true;
|
|
14
|
+
return this.#totalUsed + estimatedTokens <= this.#globalBudget.tokens;
|
|
15
|
+
}
|
|
16
|
+
isExceeded() {
|
|
17
|
+
if (!this.#globalBudget)
|
|
18
|
+
return false;
|
|
19
|
+
return this.#totalUsed > this.#globalBudget.tokens;
|
|
20
|
+
}
|
|
21
|
+
remaining() {
|
|
22
|
+
if (!this.#globalBudget)
|
|
23
|
+
return Infinity;
|
|
24
|
+
return Math.max(0, this.#globalBudget.tokens - this.#totalUsed);
|
|
25
|
+
}
|
|
26
|
+
totalUsed() {
|
|
27
|
+
return this.#totalUsed;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=budget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"AAEA,MAAM,OAAO,aAAa;IACxB,aAAa,CAAuC;IACpD,UAAU,GAAW,CAAC,CAAC;IAEvB,YAAY,YAAkD;QAC5D,IAAI,CAAC,aAAa,GAAG,YAAY,CAAC;IACpC,CAAC;IAED,OAAO,CAAC,KAAiB;QACvB,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,GAAG,KAAK,CAAC,YAAY,GAAG,CAAC,KAAK,CAAC,mBAAmB,IAAI,CAAC,CAAC,CAAC;QACzF,IAAI,CAAC,UAAU,IAAI,MAAM,CAAC;IAC5B,CAAC;IAED,SAAS,CAAC,eAAuB;QAC/B,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO,IAAI,CAAC;QACrC,OAAO,IAAI,CAAC,UAAU,GAAG,eAAe,IAAI,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;IACxE,CAAC;IAED,UAAU;QACR,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO,KAAK,CAAC;QACtC,OAAO,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC;IACrD,CAAC;IAED,SAAS;QACP,IAAI,CAAC,IAAI,CAAC,aAAa;YAAE,OAAO,QAAQ,CAAC;QACzC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;IAClE,CAAC;IAED,SAAS;QACP,OAAO,IAAI,CAAC,UAAU,CAAC;IACzB,CAAC;CACF"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type Database from 'better-sqlite3';
|
|
2
|
+
import { BudgetManager } from './budget.js';
|
|
3
|
+
import { type Provider } from './providers/base.js';
|
|
4
|
+
import { StateManager } from './state.js';
|
|
5
|
+
import type { Progress, StepBudget } from './types.js';
|
|
6
|
+
/** Default token estimator: ~4 chars per token, conservative (overestimates = safer for budgets). */
|
|
7
|
+
export declare function estimateTokens(text: string): number;
|
|
8
|
+
export declare class AbortError extends Error {
|
|
9
|
+
constructor(message?: string);
|
|
10
|
+
}
|
|
11
|
+
export interface StageOptions {
|
|
12
|
+
concurrency?: number;
|
|
13
|
+
/** Invalidate cached results for all steps in this stage. Use when code changes affect output shape. */
|
|
14
|
+
force?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface StepOptions {
|
|
17
|
+
/** Invalidate cached result for this step. Use when code changes affect output shape. */
|
|
18
|
+
force?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface ContextConfig {
|
|
21
|
+
id: string;
|
|
22
|
+
concurrency: number;
|
|
23
|
+
onProgress?: (progress: Progress) => void;
|
|
24
|
+
signal: AbortSignal;
|
|
25
|
+
state: StateManager;
|
|
26
|
+
budgetManager: BudgetManager;
|
|
27
|
+
db: Database.Database;
|
|
28
|
+
providers?: {
|
|
29
|
+
anthropic?: Provider;
|
|
30
|
+
openai?: Provider;
|
|
31
|
+
claudeCode?: Provider;
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export declare class Context {
|
|
35
|
+
#private;
|
|
36
|
+
readonly db: Database.Database;
|
|
37
|
+
constructor(config: ContextConfig);
|
|
38
|
+
/** Set the current stage label, reset per-stage counters, optionally override concurrency. */
|
|
39
|
+
stage(label: string, options?: StageOptions): void;
|
|
40
|
+
/**
|
|
41
|
+
* Durable step: checks SQLite cache, enforces budget/abort, then executes with
|
|
42
|
+
* concurrency limiting and retry. Result is persisted on success; failure is
|
|
43
|
+
* recorded in step_failures for crash forensics and resume control.
|
|
44
|
+
*
|
|
45
|
+
* Note: step functions must return JSON-serializable values. Date, Buffer, and
|
|
46
|
+
* class instances silently corrupt on round-trip.
|
|
47
|
+
*/
|
|
48
|
+
step<T>(id: string, fn: () => Promise<T>, options?: StepOptions): Promise<T>;
|
|
49
|
+
/**
|
|
50
|
+
* Batch step+upsert: run each item through step() for memoization/retry/concurrency,
|
|
51
|
+
* then upsert results into a DB table. Returns count of rows written.
|
|
52
|
+
*/
|
|
53
|
+
upsert<TItem, TResult>(items: TItem[], options: {
|
|
54
|
+
table: string;
|
|
55
|
+
key: (item: TItem) => string;
|
|
56
|
+
run: (item: TItem) => Promise<TResult>;
|
|
57
|
+
skip?: (result: TResult) => boolean;
|
|
58
|
+
map?: (result: TResult) => Record<string, unknown>;
|
|
59
|
+
update?: string[];
|
|
60
|
+
}): Promise<number>;
|
|
61
|
+
readonly agent: {
|
|
62
|
+
/**
|
|
63
|
+
* Execute a step via the Claude Code CLI (experimental).
|
|
64
|
+
* Spawns a headless `claude -p` subprocess using your local CLI subscription.
|
|
65
|
+
* Budget is enforced by monitoring the live transcript mid-execution.
|
|
66
|
+
* API may change in future releases.
|
|
67
|
+
* @experimental
|
|
68
|
+
*/
|
|
69
|
+
claudeCode: (id: string, model: string, prompt: string, opts?: StepBudget) => Promise<unknown>;
|
|
70
|
+
};
|
|
71
|
+
readonly model: {
|
|
72
|
+
anthropic: <T>(id: string, model: string, prompt: string, opts?: StepBudget & Record<string, unknown>) => Promise<T>;
|
|
73
|
+
openai: <T>(id: string, model: string, prompt: string, opts?: StepBudget & Record<string, unknown>) => Promise<T>;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAuB,KAAK,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAKzE,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EAAE,QAAQ,EAAc,UAAU,EAAE,MAAM,YAAY,CAAC;AAGnE,qGAAqG;AACrG,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAWD,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,SAA0B;CAI9C;AAED,MAAM,WAAW,YAAY;IAC3B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wGAAwG;IACxG,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,yFAAyF;IACzF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAC;IAC1C,MAAM,EAAE,WAAW,CAAC;IACpB,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,EAAE,aAAa,CAAC;IAC7B,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;IACtB,SAAS,CAAC,EAAE;QACV,SAAS,CAAC,EAAE,QAAQ,CAAC;QACrB,MAAM,CAAC,EAAE,QAAQ,CAAC;QAClB,UAAU,CAAC,EAAE,QAAQ,CAAC;KACvB,CAAC;CACH;AAED,qBAAa,OAAO;;IAsBlB,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,CAAC;gBAEnB,MAAM,EAAE,aAAa;IAiBjC,8FAA8F;IAC9F,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI;IA2ClD;;;;;;;OAOG;IACG,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;IAmDlF;;;OAGG;IACG,MAAM,CAAC,KAAK,EAAE,OAAO,EACzB,KAAK,EAAE,KAAK,EAAE,EACd,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,MAAM,CAAC;QAC7B,GAAG,EAAE,CAAC,IAAI,EAAE,KAAK,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC;QACpC,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;KACnB,GACA,OAAO,CAAC,MAAM,CAAC;IAkBlB,QAAQ,CAAC,KAAK;QACZ;;;;;;WAMG;yBACc,MAAM,SAAS,MAAM,UAAU,MAAM,SAAS,UAAU,KAAG,OAAO,CAAC,OAAO,CAAC;MAe5F;IAGF,QAAQ,CAAC,KAAK;oBACA,CAAC,MACP,MAAM,SACH,MAAM,UACL,MAAM,SACP,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1C,OAAO,CAAC,CAAC,CAAC;iBAgBJ,CAAC,MACJ,MAAM,SACH,MAAM,UACL,MAAM,SACP,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1C,OAAO,CAAC,CAAC,CAAC;MAeb;CACH"}
|
package/dist/context.js
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import pLimit from 'p-limit';
|
|
2
|
+
import pRetry from 'p-retry';
|
|
3
|
+
import { BudgetExceededError } from './providers/base.js';
|
|
4
|
+
import { ClaudeCLIProvider } from './providers/claude-cli.js';
|
|
5
|
+
import { createAnthropicProvider } from './providers/anthropic.js';
|
|
6
|
+
import { createOpenAIProvider } from './providers/openai.js';
|
|
7
|
+
import { createRetryConfig } from './retry.js';
|
|
8
|
+
import { upsertRow } from './upsert.js';
|
|
9
|
+
/** Default token estimator: ~4 chars per token, conservative (overestimates = safer for budgets). */
|
|
10
|
+
export function estimateTokens(text) {
|
|
11
|
+
return Math.ceil(text.length / 4);
|
|
12
|
+
}
|
|
13
|
+
/** Strip StepBudget-only fields so they don't leak into provider execute() calls. */
|
|
14
|
+
function stripBudgetOpts(opts) {
|
|
15
|
+
if (!opts)
|
|
16
|
+
return {};
|
|
17
|
+
const { maxInputTokens: _, onExceed: __, tokenEstimator: ___, ...rest } = opts;
|
|
18
|
+
return rest;
|
|
19
|
+
}
|
|
20
|
+
export class AbortError extends Error {
|
|
21
|
+
constructor(message = 'Operation was aborted') {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = 'AbortError';
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
export class Context {
|
|
27
|
+
#limiter;
|
|
28
|
+
#defaultConcurrency;
|
|
29
|
+
#state;
|
|
30
|
+
#budget;
|
|
31
|
+
#signal;
|
|
32
|
+
#onProgress;
|
|
33
|
+
#stage = '';
|
|
34
|
+
#forceStage = false;
|
|
35
|
+
#registered = 0;
|
|
36
|
+
#completed = 0;
|
|
37
|
+
// Per-step usage side-channel: provider helpers write here, step() reads for persistence.
|
|
38
|
+
// Concurrency-safe because step IDs are unique.
|
|
39
|
+
#stepUsage = new Map();
|
|
40
|
+
// Lazy provider instances — constructed on first use, shared across all calls
|
|
41
|
+
#claudeCode;
|
|
42
|
+
#anthropic;
|
|
43
|
+
#openai;
|
|
44
|
+
db;
|
|
45
|
+
constructor(config) {
|
|
46
|
+
this.#defaultConcurrency = config.concurrency;
|
|
47
|
+
this.#limiter = pLimit(config.concurrency);
|
|
48
|
+
this.#state = config.state;
|
|
49
|
+
this.#budget = config.budgetManager;
|
|
50
|
+
this.#signal = config.signal;
|
|
51
|
+
this.#onProgress = config.onProgress;
|
|
52
|
+
this.db = config.db;
|
|
53
|
+
this.#anthropic = config.providers?.anthropic;
|
|
54
|
+
this.#openai = config.providers?.openai;
|
|
55
|
+
this.#claudeCode = config.providers?.claudeCode;
|
|
56
|
+
// Seed completed count from prior run for progress prediction on resume
|
|
57
|
+
this.#completed = config.state.getStepCount();
|
|
58
|
+
}
|
|
59
|
+
/** Set the current stage label, reset per-stage counters, optionally override concurrency. */
|
|
60
|
+
stage(label, options) {
|
|
61
|
+
this.#stage = label;
|
|
62
|
+
this.#forceStage = options?.force ?? false;
|
|
63
|
+
this.#registered = 0;
|
|
64
|
+
this.#completed = 0;
|
|
65
|
+
this.#limiter = pLimit(options?.concurrency ?? this.#defaultConcurrency);
|
|
66
|
+
this.#fireProgress();
|
|
67
|
+
}
|
|
68
|
+
#fireProgress() {
|
|
69
|
+
this.#onProgress?.({
|
|
70
|
+
stage: this.#stage,
|
|
71
|
+
completed: this.#completed,
|
|
72
|
+
total: this.#registered,
|
|
73
|
+
usage: { tokens: this.#budget.totalUsed() },
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
#checkInputBudget(prompt, opts) {
|
|
77
|
+
if (!opts?.maxInputTokens)
|
|
78
|
+
return;
|
|
79
|
+
const estimate = (opts.tokenEstimator ?? estimateTokens)(prompt);
|
|
80
|
+
if (estimate > opts.maxInputTokens) {
|
|
81
|
+
throw new BudgetExceededError(`Estimated input tokens (${estimate}) exceeds step limit (${opts.maxInputTokens})`);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
#checkPostCallUsage(id, usage, opts) {
|
|
85
|
+
if (!opts)
|
|
86
|
+
return;
|
|
87
|
+
const exceeded = (opts.maxInputTokens && usage.inputTokens > opts.maxInputTokens) ||
|
|
88
|
+
(opts.maxTokens && usage.outputTokens > opts.maxTokens);
|
|
89
|
+
if (!exceeded)
|
|
90
|
+
return;
|
|
91
|
+
const msg = `Step '${id}' exceeded budget: ${usage.inputTokens} input, ${usage.outputTokens} output`;
|
|
92
|
+
if (opts.onExceed === 'warn') {
|
|
93
|
+
console.warn(`[tuff] ${msg}`);
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
throw new BudgetExceededError(msg);
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Durable step: checks SQLite cache, enforces budget/abort, then executes with
|
|
100
|
+
* concurrency limiting and retry. Result is persisted on success; failure is
|
|
101
|
+
* recorded in step_failures for crash forensics and resume control.
|
|
102
|
+
*
|
|
103
|
+
* Note: step functions must return JSON-serializable values. Date, Buffer, and
|
|
104
|
+
* class instances silently corrupt on round-trip.
|
|
105
|
+
*/
|
|
106
|
+
async step(id, fn, options) {
|
|
107
|
+
const force = options?.force || this.#forceStage;
|
|
108
|
+
if (force) {
|
|
109
|
+
this.#state.deleteStep(id);
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
const cached = this.#state.getStep(id);
|
|
113
|
+
if (cached !== undefined)
|
|
114
|
+
return cached;
|
|
115
|
+
}
|
|
116
|
+
// Abort check before entering the limiter queue
|
|
117
|
+
if (this.#signal.aborted)
|
|
118
|
+
throw new AbortError();
|
|
119
|
+
if (this.#budget.isExceeded())
|
|
120
|
+
throw new BudgetExceededError('Budget exceeded');
|
|
121
|
+
// Register synchronously before the limiter queue — enables fan-out total tracking
|
|
122
|
+
// (Promise.all registers all steps before any executes)
|
|
123
|
+
this.#registered++;
|
|
124
|
+
return this.#limiter(async () => {
|
|
125
|
+
// Check again after waiting in the queue — signal may have fired while queued
|
|
126
|
+
if (this.#signal.aborted)
|
|
127
|
+
throw new AbortError();
|
|
128
|
+
const startTime = Date.now();
|
|
129
|
+
try {
|
|
130
|
+
// Check signal at the start of each retry attempt rather than passing it to
|
|
131
|
+
// pRetry directly — pRetry would race the signal against fn(), which breaks
|
|
132
|
+
// the case where fn() itself triggers the abort (e.g., budget kill).
|
|
133
|
+
const result = await pRetry(() => {
|
|
134
|
+
if (this.#signal.aborted)
|
|
135
|
+
throw new AbortError();
|
|
136
|
+
return fn();
|
|
137
|
+
}, createRetryConfig());
|
|
138
|
+
const durationMs = Date.now() - startTime;
|
|
139
|
+
const usage = this.#stepUsage.get(id);
|
|
140
|
+
this.#stepUsage.delete(id);
|
|
141
|
+
this.#state.setStep(id, result, usage, durationMs);
|
|
142
|
+
this.#completed++;
|
|
143
|
+
this.#fireProgress();
|
|
144
|
+
return result;
|
|
145
|
+
}
|
|
146
|
+
catch (error) {
|
|
147
|
+
// Only abort if the pipeline's own signal fired — not per-request AbortErrors
|
|
148
|
+
// (e.g., Vercel AI SDK throws AbortError on per-call timeouts)
|
|
149
|
+
if (this.#signal.aborted) {
|
|
150
|
+
throw new AbortError();
|
|
151
|
+
}
|
|
152
|
+
const durationMs = Date.now() - startTime;
|
|
153
|
+
this.#state.setStepFailure(id, String(error), durationMs);
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Batch step+upsert: run each item through step() for memoization/retry/concurrency,
|
|
160
|
+
* then upsert results into a DB table. Returns count of rows written.
|
|
161
|
+
*/
|
|
162
|
+
async upsert(items, options) {
|
|
163
|
+
let written = 0;
|
|
164
|
+
const results = await Promise.all(items.map(async (item) => {
|
|
165
|
+
const result = await this.step(options.key(item), () => options.run(item));
|
|
166
|
+
return { result, item };
|
|
167
|
+
}));
|
|
168
|
+
for (const { result } of results) {
|
|
169
|
+
if (options.skip?.(result))
|
|
170
|
+
continue;
|
|
171
|
+
const row = options.map ? options.map(result) : result;
|
|
172
|
+
upsertRow(this.db, options.table, row, options.update);
|
|
173
|
+
written++;
|
|
174
|
+
}
|
|
175
|
+
return written;
|
|
176
|
+
}
|
|
177
|
+
// Agent providers (subprocess-based coding agents — model chosen per-call)
|
|
178
|
+
agent = {
|
|
179
|
+
/**
|
|
180
|
+
* Execute a step via the Claude Code CLI (experimental).
|
|
181
|
+
* Spawns a headless `claude -p` subprocess using your local CLI subscription.
|
|
182
|
+
* Budget is enforced by monitoring the live transcript mid-execution.
|
|
183
|
+
* API may change in future releases.
|
|
184
|
+
* @experimental
|
|
185
|
+
*/
|
|
186
|
+
claudeCode: (id, model, prompt, opts) => {
|
|
187
|
+
this.#claudeCode ??= new ClaudeCLIProvider();
|
|
188
|
+
return this.step(id, async () => {
|
|
189
|
+
this.#checkInputBudget(prompt, opts);
|
|
190
|
+
const result = await this.#claudeCode.execute(prompt, {
|
|
191
|
+
model,
|
|
192
|
+
maxTokens: opts?.maxTokens,
|
|
193
|
+
signal: this.#signal,
|
|
194
|
+
});
|
|
195
|
+
this.#budget.consume(result.usage);
|
|
196
|
+
this.#stepUsage.set(id, result.usage);
|
|
197
|
+
this.#checkPostCallUsage(id, result.usage, opts);
|
|
198
|
+
return result.output;
|
|
199
|
+
});
|
|
200
|
+
},
|
|
201
|
+
};
|
|
202
|
+
// Model providers (direct HTTP API calls — model required per-call)
|
|
203
|
+
model = {
|
|
204
|
+
anthropic: (id, model, prompt, opts) => {
|
|
205
|
+
this.#anthropic ??= createAnthropicProvider();
|
|
206
|
+
return this.step(id, async () => {
|
|
207
|
+
this.#checkInputBudget(prompt, opts);
|
|
208
|
+
const result = await this.#anthropic.execute(prompt, {
|
|
209
|
+
model,
|
|
210
|
+
signal: this.#signal,
|
|
211
|
+
...stripBudgetOpts(opts),
|
|
212
|
+
});
|
|
213
|
+
this.#budget.consume(result.usage);
|
|
214
|
+
this.#stepUsage.set(id, result.usage);
|
|
215
|
+
this.#checkPostCallUsage(id, result.usage, opts);
|
|
216
|
+
return result.output;
|
|
217
|
+
});
|
|
218
|
+
},
|
|
219
|
+
openai: (id, model, prompt, opts) => {
|
|
220
|
+
this.#openai ??= createOpenAIProvider();
|
|
221
|
+
return this.step(id, async () => {
|
|
222
|
+
this.#checkInputBudget(prompt, opts);
|
|
223
|
+
const result = await this.#openai.execute(prompt, {
|
|
224
|
+
model,
|
|
225
|
+
signal: this.#signal,
|
|
226
|
+
...stripBudgetOpts(opts),
|
|
227
|
+
});
|
|
228
|
+
this.#budget.consume(result.usage);
|
|
229
|
+
this.#stepUsage.set(id, result.usage);
|
|
230
|
+
this.#checkPostCallUsage(id, result.usage, opts);
|
|
231
|
+
return result.output;
|
|
232
|
+
});
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../src/context.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { tuff } from './tuff.js';
|
|
2
|
+
export { AbortError, estimateTokens } from './context.js';
|
|
3
|
+
export { upsertRow, autoStringify } from './upsert.js';
|
|
4
|
+
export { syncSchema } from './schema-sync.js';
|
|
5
|
+
export { SCHEMA_SQL } from './schema.js';
|
|
6
|
+
export { BudgetExceededError } from './providers/base.js';
|
|
7
|
+
export { ClaudeCLIProvider } from './providers/claude-cli.js';
|
|
8
|
+
export { createOpenAIProvider } from './providers/openai.js';
|
|
9
|
+
export { createAnthropicProvider } from './providers/anthropic.js';
|
|
10
|
+
export type { Context, StepOptions, StageOptions } from './context.js';
|
|
11
|
+
export type { TuffRun, TuffStep, TuffStepFailure } from './schema.js';
|
|
12
|
+
export type { DurableConfig, Progress, StepBudget, TokenUsage, ProviderResult, } from './types.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACnE,YAAY,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACvE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACtE,YAAY,EACV,aAAa,EACb,QAAQ,EACR,UAAU,EACV,UAAU,EACV,cAAc,GACf,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { tuff } from './tuff.js';
|
|
2
|
+
export { AbortError, estimateTokens } from './context.js';
|
|
3
|
+
export { upsertRow, autoStringify } from './upsert.js';
|
|
4
|
+
export { syncSchema } from './schema-sync.js';
|
|
5
|
+
export { SCHEMA_SQL } from './schema.js';
|
|
6
|
+
export { BudgetExceededError } from './providers/base.js';
|
|
7
|
+
export { ClaudeCLIProvider } from './providers/claude-cli.js';
|
|
8
|
+
export { createOpenAIProvider } from './providers/openai.js';
|
|
9
|
+
export { createAnthropicProvider } from './providers/anthropic.js';
|
|
10
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC"}
|
package/dist/job.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Job, CustomJob, ProviderJob, CommandJob, ClaudeCodeJob, JobContext, JobResult } from './types.js';
|
|
2
|
+
import type { Provider } from './providers/base.js';
|
|
3
|
+
export declare function isCustomJob<T = unknown>(job: Job<T>): job is CustomJob<T>;
|
|
4
|
+
export declare function isProviderJob(job: Job): job is ProviderJob;
|
|
5
|
+
export declare function isCommandJob(job: Job): job is CommandJob;
|
|
6
|
+
export declare function isClaudeCodeJob(job: Job): job is ClaudeCodeJob;
|
|
7
|
+
export declare function executeJob(job: Job, context: JobContext, provider?: Provider): Promise<JobResult>;
|
|
8
|
+
//# sourceMappingURL=job.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"job.d.ts","sourceRoot":"","sources":["../src/job.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAChH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAEpD,wBAAgB,WAAW,CAAC,CAAC,GAAG,OAAO,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAEzE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,WAAW,CAE1D;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,UAAU,CAExD;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG,IAAI,aAAa,CAE9D;AAED,wBAAsB,UAAU,CAC9B,GAAG,EAAE,GAAG,EACR,OAAO,EAAE,UAAU,EACnB,QAAQ,CAAC,EAAE,QAAQ,GAClB,OAAO,CAAC,SAAS,CAAC,CAgCpB"}
|