@spendgraph/prompt 0.4.0 → 0.6.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 +202 -0
- package/README.md +24 -221
- package/dist/budget/budget.d.ts +10 -0
- package/dist/budget/budget.js +1 -31
- package/dist/budget/errors.js +1 -11
- package/dist/budget/index.js +1 -2
- package/dist/build/build.d.ts +11 -2
- package/dist/build/build.js +1 -57
- package/dist/build/index.js +1 -1
- package/dist/cache/cache.js +1 -128
- package/dist/cache/index.js +1 -1
- package/dist/client.d.ts +7 -1
- package/dist/client.js +1 -145
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -5
- package/dist/internals.d.ts +2 -2
- package/dist/internals.js +1 -6
- package/dist/prompt/bind.js +1 -15
- package/dist/prompt/factory.d.ts +1 -1
- package/dist/prompt/factory.js +1 -100
- package/dist/prompt/index.js +1 -2
- package/dist/pull/index.js +1 -1
- package/dist/pull/pull.js +1 -19
- package/dist/render/index.js +1 -3
- package/dist/render/messages.js +1 -14
- package/dist/render/system.js +4 -13
- package/dist/render/types.js +0 -1
- package/dist/render/variables.d.ts +7 -0
- package/dist/render/variables.js +1 -20
- package/dist/run/across-models.d.ts +11 -1
- package/dist/run/across-models.js +1 -5
- package/dist/run/concurrency.js +1 -12
- package/dist/run/id.js +1 -3
- package/dist/run/index.js +1 -5
- package/dist/run/once.js +1 -21
- package/dist/run/sample.js +1 -28
- package/dist/types/dataset.js +0 -1
- package/dist/types/index.js +0 -1
- package/dist/types/payload.js +0 -1
- package/dist/types/prompt.d.ts +1 -1
- package/dist/types/prompt.js +0 -1
- package/dist/types/result.js +0 -1
- package/dist/types/rollout.js +0 -1
- package/dist/types/run.js +0 -1
- package/dist/types/trace.js +0 -1
- package/dist/types/version.js +0 -1
- package/package.json +7 -7
package/dist/cache/cache.js
CHANGED
|
@@ -1,128 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
store = new Map();
|
|
3
|
-
ttlMs;
|
|
4
|
-
maxSize;
|
|
5
|
-
now;
|
|
6
|
-
refreshing = new Set();
|
|
7
|
-
failures = new Map();
|
|
8
|
-
retryAfterMs;
|
|
9
|
-
onRefreshError;
|
|
10
|
-
identify;
|
|
11
|
-
tick = 0;
|
|
12
|
-
invalidatedAt = new Map();
|
|
13
|
-
clearedAt = -1;
|
|
14
|
-
outstanding = 0;
|
|
15
|
-
constructor(opts = {}) {
|
|
16
|
-
this.ttlMs = (opts.ttlSeconds ?? 300) * 1000;
|
|
17
|
-
this.maxSize = Math.max(1, opts.maxSize ?? 100);
|
|
18
|
-
this.now = opts.now ?? (() => Date.now());
|
|
19
|
-
this.retryAfterMs = (opts.retryAfterSeconds ?? 60) * 1000;
|
|
20
|
-
this.onRefreshError = opts.onRefreshError;
|
|
21
|
-
this.identify = opts.identify;
|
|
22
|
-
}
|
|
23
|
-
get(key) {
|
|
24
|
-
const entry = this.store.get(key);
|
|
25
|
-
if (!entry)
|
|
26
|
-
return undefined;
|
|
27
|
-
this.store.delete(key);
|
|
28
|
-
this.store.set(key, entry);
|
|
29
|
-
const ageMs = this.now() - entry.at;
|
|
30
|
-
return { value: entry.value, stale: ageMs > this.ttlMs, ageMs };
|
|
31
|
-
}
|
|
32
|
-
set(key, value) {
|
|
33
|
-
this.store.delete(key);
|
|
34
|
-
this.store.set(key, { value, at: this.now() });
|
|
35
|
-
while (this.store.size > this.maxSize) {
|
|
36
|
-
const oldest = this.store.keys().next().value;
|
|
37
|
-
if (oldest === undefined)
|
|
38
|
-
break;
|
|
39
|
-
this.store.delete(oldest);
|
|
40
|
-
if (!this.refreshing.has(oldest))
|
|
41
|
-
this.failures.delete(oldest);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
refreshInBackground(key, refresh) {
|
|
45
|
-
if (this.refreshing.has(key))
|
|
46
|
-
return;
|
|
47
|
-
const failedAt = this.failures.get(key);
|
|
48
|
-
if (failedAt !== undefined && this.now() - failedAt < this.retryAfterMs)
|
|
49
|
-
return;
|
|
50
|
-
this.refreshing.add(key);
|
|
51
|
-
const startedAt = this.beginFetch();
|
|
52
|
-
void refresh()
|
|
53
|
-
.then((value) => this.settle(key, value, startedAt))
|
|
54
|
-
.catch((err) => {
|
|
55
|
-
this.abandon(key);
|
|
56
|
-
try {
|
|
57
|
-
this.onRefreshError?.(err, key);
|
|
58
|
-
}
|
|
59
|
-
catch {
|
|
60
|
-
}
|
|
61
|
-
})
|
|
62
|
-
.finally(() => {
|
|
63
|
-
this.refreshing.delete(key);
|
|
64
|
-
this.forgetLogIfIdle();
|
|
65
|
-
});
|
|
66
|
-
}
|
|
67
|
-
beginFetch() {
|
|
68
|
-
this.outstanding++;
|
|
69
|
-
return this.tick;
|
|
70
|
-
}
|
|
71
|
-
settle(key, value, startedAt) {
|
|
72
|
-
this.outstanding--;
|
|
73
|
-
const names = [key, ...(this.identify?.(value) ?? [])];
|
|
74
|
-
const overtaken = startedAt < this.clearedAt ||
|
|
75
|
-
names.some((n) => (this.invalidatedAt.get(n) ?? -1) > startedAt);
|
|
76
|
-
if (!overtaken) {
|
|
77
|
-
this.failures.delete(key);
|
|
78
|
-
this.set(key, value);
|
|
79
|
-
}
|
|
80
|
-
this.forgetLogIfIdle();
|
|
81
|
-
}
|
|
82
|
-
abandon(key) {
|
|
83
|
-
this.outstanding--;
|
|
84
|
-
this.failures.set(key, this.now());
|
|
85
|
-
this.boundFailures();
|
|
86
|
-
this.forgetLogIfIdle();
|
|
87
|
-
}
|
|
88
|
-
invalidate(name) {
|
|
89
|
-
this.invalidatedAt.set(name, ++this.tick);
|
|
90
|
-
}
|
|
91
|
-
forgetLogIfIdle() {
|
|
92
|
-
if (this.outstanding === 0 && this.refreshing.size === 0)
|
|
93
|
-
this.invalidatedAt.clear();
|
|
94
|
-
}
|
|
95
|
-
boundFailures() {
|
|
96
|
-
while (this.failures.size > this.maxSize) {
|
|
97
|
-
const oldest = this.failures.keys().next().value;
|
|
98
|
-
if (oldest === undefined)
|
|
99
|
-
break;
|
|
100
|
-
this.failures.delete(oldest);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
keysWhere(match) {
|
|
104
|
-
const out = [];
|
|
105
|
-
for (const [key, entry] of this.store)
|
|
106
|
-
if (match(entry.value))
|
|
107
|
-
out.push(key);
|
|
108
|
-
return out;
|
|
109
|
-
}
|
|
110
|
-
delete(key) {
|
|
111
|
-
this.store.delete(key);
|
|
112
|
-
this.failures.delete(key);
|
|
113
|
-
this.invalidate(key);
|
|
114
|
-
this.forgetLogIfIdle();
|
|
115
|
-
}
|
|
116
|
-
clear() {
|
|
117
|
-
this.clearedAt = ++this.tick;
|
|
118
|
-
this.store.clear();
|
|
119
|
-
this.failures.clear();
|
|
120
|
-
this.forgetLogIfIdle();
|
|
121
|
-
}
|
|
122
|
-
get size() {
|
|
123
|
-
return this.store.size;
|
|
124
|
-
}
|
|
125
|
-
get trackedKeys() {
|
|
126
|
-
return new Set([...this.invalidatedAt.keys(), ...this.failures.keys()]).size;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
1
|
+
class a{store=new Map;ttlMs;maxSize;now;refreshing=new Set;failures=new Map;retryAfterMs;onRefreshError;identify;tick=0;invalidatedAt=new Map;clearedAt=-1;outstanding=0;constructor(t={}){this.ttlMs=(t.ttlSeconds??300)*1e3,this.maxSize=Math.max(1,t.maxSize??100),this.now=t.now??(()=>Date.now()),this.retryAfterMs=(t.retryAfterSeconds??60)*1e3,this.onRefreshError=t.onRefreshError,this.identify=t.identify}get(t){const s=this.store.get(t);if(!s)return;this.store.delete(t),this.store.set(t,s);const e=this.now()-s.at;return{value:s.value,stale:e>this.ttlMs,ageMs:e}}set(t,s){for(this.store.delete(t),this.store.set(t,{value:s,at:this.now()});this.store.size>this.maxSize;){const e=this.store.keys().next().value;if(e===void 0)break;this.store.delete(e),this.refreshing.has(e)||this.failures.delete(e)}}refreshInBackground(t,s){if(this.refreshing.has(t))return;const e=this.failures.get(t);if(e!==void 0&&this.now()-e<this.retryAfterMs)return;this.refreshing.add(t);const i=this.beginFetch();s().then(r=>this.settle(t,r,i)).catch(r=>{this.abandon(t);try{this.onRefreshError?.(r,t)}catch{}}).finally(()=>{this.refreshing.delete(t),this.forgetLogIfIdle()})}beginFetch(){return this.outstanding++,this.tick}settle(t,s,e){this.outstanding--;const i=[t,...this.identify?.(s)??[]];e<this.clearedAt||i.some(n=>(this.invalidatedAt.get(n)??-1)>e)||(this.failures.delete(t),this.set(t,s)),this.forgetLogIfIdle()}abandon(t){this.outstanding--,this.failures.set(t,this.now()),this.boundFailures(),this.forgetLogIfIdle()}invalidate(t){this.invalidatedAt.set(t,++this.tick)}forgetLogIfIdle(){this.outstanding===0&&this.refreshing.size===0&&this.invalidatedAt.clear()}boundFailures(){for(;this.failures.size>this.maxSize;){const t=this.failures.keys().next().value;if(t===void 0)break;this.failures.delete(t)}}keysWhere(t){const s=[];for(const[e,i]of this.store)t(i.value)&&s.push(e);return s}delete(t){this.store.delete(t),this.failures.delete(t),this.invalidate(t),this.forgetLogIfIdle()}clear(){this.clearedAt=++this.tick,this.store.clear(),this.failures.clear(),this.forgetLogIfIdle()}get size(){return this.store.size}get trackedKeys(){return new Set([...this.invalidatedAt.keys(),...this.failures.keys()]).size}}export{a as PullCache};
|
package/dist/cache/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{PullCache as o}from"./cache.js";export{o as PullCache};
|
package/dist/client.d.ts
CHANGED
|
@@ -6,7 +6,13 @@ export interface PromptClientOptions extends Omit<ClientOptions, "apiKey" | "bas
|
|
|
6
6
|
/** spendgraph API key (sg_…). Without it, `pull` throws and `report` no-ops. */
|
|
7
7
|
apiKey: string | undefined;
|
|
8
8
|
baseUrl: string;
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* `identify` is not yours to set: the client fixes it to the prompt's id and
|
|
11
|
+
* slug, because an invalidation that arrives under one handle has to reach a
|
|
12
|
+
* fetch started under the other. Naming it in the type and discarding it in
|
|
13
|
+
* the constructor was worse than not offering it.
|
|
14
|
+
*/
|
|
15
|
+
cache?: Omit<CacheOptions<PromptPayload>, "identify">;
|
|
10
16
|
/** Max requests in flight for sample() and runAll(). Default 4. */
|
|
11
17
|
concurrency?: number;
|
|
12
18
|
/**
|
package/dist/client.js
CHANGED
|
@@ -1,145 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Budget } from "./budget/index.js";
|
|
3
|
-
import { buildCustomPrompt } from "./build/index.js";
|
|
4
|
-
import { PullCache } from "./cache/index.js";
|
|
5
|
-
import { makePrompt } from "./prompt/index.js";
|
|
6
|
-
import { pullWithCache } from "./pull/index.js";
|
|
7
|
-
import { newRolloutId } from "./run/id.js";
|
|
8
|
-
import { runAcrossModels, runOnce, sampleRuns } from "./run/index.js";
|
|
9
|
-
const DEFAULT_CONCURRENCY = 4;
|
|
10
|
-
export class PromptClient {
|
|
11
|
-
sdk;
|
|
12
|
-
cache;
|
|
13
|
-
hasKey;
|
|
14
|
-
onReportError;
|
|
15
|
-
concurrency;
|
|
16
|
-
budget;
|
|
17
|
-
warnedAboutTokens = false;
|
|
18
|
-
constructor(opts) {
|
|
19
|
-
const { cache, onReportError, onPullError, concurrency, maxCostMicros, ...clientOpts } = opts;
|
|
20
|
-
this.sdk = new Spendgraph(clientOpts);
|
|
21
|
-
this.cache = new PullCache({
|
|
22
|
-
...cache,
|
|
23
|
-
onRefreshError: cache?.onRefreshError ?? onPullError,
|
|
24
|
-
identify: (p) => [p.id, p.slug].filter((v) => Boolean(v)),
|
|
25
|
-
});
|
|
26
|
-
this.hasKey = Boolean(opts.apiKey);
|
|
27
|
-
this.onReportError = onReportError;
|
|
28
|
-
this.concurrency = Math.max(1, concurrency ?? DEFAULT_CONCURRENCY);
|
|
29
|
-
this.budget = new Budget("maxCostMicros" in opts ? maxCostMicros : undefined);
|
|
30
|
-
}
|
|
31
|
-
recorder() {
|
|
32
|
-
return {
|
|
33
|
-
enabled: true,
|
|
34
|
-
write: (promptId, entry) => {
|
|
35
|
-
this.warnOnEmptyTokens(entry);
|
|
36
|
-
return this.priced(promptId, entry);
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
async pull(handle) {
|
|
41
|
-
const payload = await pullWithCache(this.cache, handle, async () => {
|
|
42
|
-
const res = await this.sdk.prompts.get(handle);
|
|
43
|
-
return res.prompt;
|
|
44
|
-
});
|
|
45
|
-
return makePrompt({
|
|
46
|
-
id: payload.id,
|
|
47
|
-
name: payload.name,
|
|
48
|
-
slug: payload.slug ?? null,
|
|
49
|
-
blocks: payload.blocks,
|
|
50
|
-
question: payload.question,
|
|
51
|
-
fields: payload.fieldSpec ?? [],
|
|
52
|
-
versionId: payload.currentVersionId ?? null,
|
|
53
|
-
models: payload.models ?? [],
|
|
54
|
-
}, "server", this.recorder());
|
|
55
|
-
}
|
|
56
|
-
build(spec, opts = {}) {
|
|
57
|
-
return buildCustomPrompt(spec, { ...opts, sdk: this.sdk });
|
|
58
|
-
}
|
|
59
|
-
warnOnEmptyTokens(outcome) {
|
|
60
|
-
if (this.warnedAboutTokens)
|
|
61
|
-
return;
|
|
62
|
-
if (outcome.status === "failed")
|
|
63
|
-
return;
|
|
64
|
-
if ((outcome.inputTokens ?? 0) > 0 || (outcome.outputTokens ?? 0) > 0)
|
|
65
|
-
return;
|
|
66
|
-
this.warnedAboutTokens = true;
|
|
67
|
-
console.warn("[prompt] trace() recorded a rollout with no tokens. This package never sees " +
|
|
68
|
-
"the provider response, so return inputTokens and outputTokens from your callback " +
|
|
69
|
-
"or every cost on this prompt reads as zero.");
|
|
70
|
-
}
|
|
71
|
-
async run(promptId, values = {}, opts = {}) {
|
|
72
|
-
return runOnce(this.sdk.prompts, promptId, values, opts, this.budget);
|
|
73
|
-
}
|
|
74
|
-
async sample(promptId, values = {}, opts = {}) {
|
|
75
|
-
return sampleRuns(this.sdk.prompts, promptId, values, { concurrency: this.concurrency, ...opts }, this.budget);
|
|
76
|
-
}
|
|
77
|
-
async runAll(promptId, values = {}, opts = {}) {
|
|
78
|
-
const models = opts.models ?? (await this.pull(promptId)).models;
|
|
79
|
-
if (models.length === 0) {
|
|
80
|
-
throw new Error("No models given and the prompt has none saved.");
|
|
81
|
-
}
|
|
82
|
-
return runAcrossModels(this.sdk.prompts, promptId, values, models, { concurrency: this.concurrency, ...opts }, this.budget);
|
|
83
|
-
}
|
|
84
|
-
async cases(promptId) {
|
|
85
|
-
return this.sdk.prompts.cases(promptId);
|
|
86
|
-
}
|
|
87
|
-
async setCases(promptId, cases) {
|
|
88
|
-
return this.sdk.prompts.putCases(promptId, cases);
|
|
89
|
-
}
|
|
90
|
-
spent() {
|
|
91
|
-
return this.budget.spent();
|
|
92
|
-
}
|
|
93
|
-
remaining() {
|
|
94
|
-
return this.budget.remaining();
|
|
95
|
-
}
|
|
96
|
-
async versions(promptId, opts = {}) {
|
|
97
|
-
return this.sdk.prompts.versions(promptId, opts);
|
|
98
|
-
}
|
|
99
|
-
async promote(promptId, versionId) {
|
|
100
|
-
const res = await this.sdk.prompts.promote(promptId, versionId);
|
|
101
|
-
this.invalidate(promptId);
|
|
102
|
-
return res;
|
|
103
|
-
}
|
|
104
|
-
invalidate(promptId) {
|
|
105
|
-
if (!promptId) {
|
|
106
|
-
this.cache.clear();
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
for (const key of this.cache.keysWhere((p) => p.id === promptId || p.slug === promptId)) {
|
|
110
|
-
this.cache.delete(key);
|
|
111
|
-
}
|
|
112
|
-
this.cache.delete(promptId);
|
|
113
|
-
this.cache.invalidate(promptId);
|
|
114
|
-
}
|
|
115
|
-
async priced(promptId, input) {
|
|
116
|
-
const rolloutId = input.rolloutId ?? newRolloutId();
|
|
117
|
-
if (!this.hasKey)
|
|
118
|
-
return undefined;
|
|
119
|
-
try {
|
|
120
|
-
const res = (await this.sdk.prompts.report(promptId, { ...input, rolloutId }));
|
|
121
|
-
if (res.priced === false)
|
|
122
|
-
return undefined;
|
|
123
|
-
return res.rollout?.costMicros;
|
|
124
|
-
}
|
|
125
|
-
catch (err) {
|
|
126
|
-
this.onReportError?.(err);
|
|
127
|
-
return undefined;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
async report(promptId, input) {
|
|
131
|
-
const rolloutId = input.rolloutId ?? newRolloutId();
|
|
132
|
-
if (!this.hasKey)
|
|
133
|
-
return rolloutId;
|
|
134
|
-
try {
|
|
135
|
-
await this.sdk.prompts.report(promptId, { ...input, rolloutId });
|
|
136
|
-
}
|
|
137
|
-
catch (err) {
|
|
138
|
-
this.onReportError?.(err);
|
|
139
|
-
}
|
|
140
|
-
return rolloutId;
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
export function pullPrompt(handle, opts) {
|
|
144
|
-
return new PromptClient(opts).pull(handle);
|
|
145
|
-
}
|
|
1
|
+
import{Spendgraph as h}from"@spendgraph/sdk";import{Budget as d}from"./budget/index.js";import{buildCustomPrompt as l}from"./build/index.js";import{PullCache as m}from"./cache/index.js";import{makePrompt as f}from"./prompt/index.js";import{pullWithCache as y}from"./pull/index.js";import{newRolloutId as i}from"./run/id.js";import{runAcrossModels as k,runOnce as w,sampleRuns as g}from"./run/index.js";const b=4;function E(o,r){const e=o?.prompt;if(!e||typeof e!="object"||typeof e.id!="string")throw new Error(`Asked for prompt "${r}" and the response carried no prompt. Check the base URL points at a spendgraph app and that the key can read this project.`);return e}class R{sdk;cache;hasKey;onReportError;concurrency;budget;warnedAboutTokens=!1;constructor(r){const{cache:e,onReportError:t,onPullError:s,concurrency:a,maxCostMicros:c,...u}=r;this.sdk=new h(u),this.cache=new m({...e,onRefreshError:e?.onRefreshError??s,identify:n=>[n.id,n.slug].filter(p=>!!p)}),this.hasKey=!!r.apiKey,this.onReportError=t,this.concurrency=Math.max(1,a??b),this.budget=new d("maxCostMicros"in r?c:void 0)}recorder(){return{enabled:!0,write:(r,e)=>(this.warnOnEmptyTokens(e),this.priced(r,e))}}async pull(r){const e=await y(this.cache,r,async()=>{const t=await this.sdk.prompts.get(r);return E(t,r)});return f({id:e.id,name:e.name??e.id,slug:e.slug??null,blocks:e.blocks??[],question:e.question??"",fields:e.fieldSpec??[],versionId:e.currentVersionId??null,models:e.models??[]},"server",this.recorder())}build(r,e={}){return l(r,{onReportError:this.onReportError,...e,sdk:this.sdk})}warnOnEmptyTokens(r){this.warnedAboutTokens||r.status!=="failed"&&((r.inputTokens??0)>0||(r.outputTokens??0)>0||(this.warnedAboutTokens=!0,console.warn("[prompt] call() recorded a rollout with no tokens. This package never sees the provider response, so return inputTokens and outputTokens from your callback or every cost on this prompt reads as zero.")))}async run(r,e={},t={}){return w(this.sdk.prompts,r,e,t,this.budget)}async sample(r,e={},t={}){return g(this.sdk.prompts,r,e,{concurrency:this.concurrency,...t},this.budget)}async runAll(r,e={},t={}){const s=t.models??(await this.pull(r)).models;if(s.length===0)throw new Error("No models given and the prompt has none saved.");return k(this.sdk.prompts,r,e,s,{concurrency:this.concurrency,...t},this.budget)}async cases(r){return this.sdk.prompts.cases(r)}async setCases(r,e){return this.sdk.prompts.putCases(r,e)}spent(){return this.budget.spent()}remaining(){return this.budget.remaining()}async versions(r,e={}){return this.sdk.prompts.versions(r,e)}async promote(r,e){const t=await this.sdk.prompts.promote(r,e);return this.invalidate(r),t}invalidate(r){if(!r){this.cache.clear();return}for(const e of this.cache.keysWhere(t=>t.id===r||t.slug===r))this.cache.delete(e);this.cache.delete(r),this.cache.invalidate(r)}async priced(r,e){const t=e.rolloutId??i();if(this.hasKey)try{const s=await this.sdk.prompts.report(r,{...e,rolloutId:t});return s.priced===!1?void 0:s.rollout?.costMicros}catch(s){this.onReportError?.(s);return}}async report(r,e){const t=e.rolloutId??i();if(!this.hasKey)return t;try{await this.sdk.prompts.report(r,{...e,rolloutId:t})}catch(s){this.onReportError?.(s)}return t}}function O(o,r){return new R(r).pull(o)}export{R as PromptClient,O as pullPrompt};
|
package/dist/index.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ export type { BuildOptions } from "./build/index.js";
|
|
|
5
5
|
export { buildCustomPrompt } from "./build/index.js";
|
|
6
6
|
export type { PromptClientOptions } from "./client.js";
|
|
7
7
|
export { PromptClient, pullPrompt } from "./client.js";
|
|
8
|
-
export type { Answer, BatchOptions, Chain, InvokeOptions, Model } from "./prompt/index.js";
|
|
8
|
+
export type { Answer, BatchOptions, Chain, InvokeOptions, Model, ModelOptions, } from "./prompt/index.js";
|
|
9
9
|
export { MAX_RECORDED_MESSAGES } from "./prompt/index.js";
|
|
10
10
|
export type { Block, History, Message } from "./render/index.js";
|
|
11
|
-
export type { DatasetCase, DatasetSummary, Prompt, PromptSource, PromptSpec, PromptVersion, RenderOptions, ReportInput, RunOptions, RunResult, Split, TraceHandle, TraceOptions, TraceOutcome, } from "./types/index.js";
|
|
11
|
+
export type { DatasetCase, DatasetSummary, Prompt, PromptSource, PromptSpec, PromptVersion, Recordable, RenderOptions, ReportInput, RunOptions, RunResult, Split, TraceHandle, TraceOptions, TraceOutcome, TurnRecord, TurnSource, } from "./types/index.js";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { BudgetExceededError } from "./budget/index.js";
|
|
3
|
-
export { buildCustomPrompt } from "./build/index.js";
|
|
4
|
-
export { PromptClient, pullPrompt } from "./client.js";
|
|
5
|
-
export { MAX_RECORDED_MESSAGES } from "./prompt/index.js";
|
|
1
|
+
import{FieldValidationError as t}from"@spendgraph/sdk";import{BudgetExceededError as m}from"./budget/index.js";import{buildCustomPrompt as E}from"./build/index.js";import{PromptClient as l,pullPrompt as x}from"./client.js";import{MAX_RECORDED_MESSAGES as i}from"./prompt/index.js";export{m as BudgetExceededError,t as FieldValidationError,i as MAX_RECORDED_MESSAGES,l as PromptClient,E as buildCustomPrompt,x as pullPrompt};
|
package/dist/internals.d.ts
CHANGED
|
@@ -10,8 +10,8 @@ export { serializeFields, validateFields } from "@spendgraph/sdk";
|
|
|
10
10
|
export { Budget } from "./budget/index.js";
|
|
11
11
|
export type { CacheHit, CacheOptions } from "./cache/index.js";
|
|
12
12
|
export { PullCache } from "./cache/index.js";
|
|
13
|
-
export type {
|
|
13
|
+
export type { PromptShape, Recorder } from "./prompt/index.js";
|
|
14
14
|
export { bind, makePrompt, noRecorder } from "./prompt/index.js";
|
|
15
15
|
export { pullWithCache } from "./pull/index.js";
|
|
16
16
|
export { mapLimit, newRolloutId } from "./run/index.js";
|
|
17
|
-
export type { PromptPayload,
|
|
17
|
+
export type { PromptPayload, Rollout } from "./types/index.js";
|
package/dist/internals.js
CHANGED
|
@@ -1,6 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { Budget } from "./budget/index.js";
|
|
3
|
-
export { PullCache } from "./cache/index.js";
|
|
4
|
-
export { bind, makePrompt, noRecorder } from "./prompt/index.js";
|
|
5
|
-
export { pullWithCache } from "./pull/index.js";
|
|
6
|
-
export { mapLimit, newRolloutId } from "./run/index.js";
|
|
1
|
+
import{serializeFields as r,validateFields as t}from"@spendgraph/sdk";import{Budget as m}from"./budget/index.js";import{PullCache as p}from"./cache/index.js";import{bind as d,makePrompt as f,noRecorder as x}from"./prompt/index.js";import{pullWithCache as c}from"./pull/index.js";import{mapLimit as n,newRolloutId as s}from"./run/index.js";export{m as Budget,p as PullCache,d as bind,f as makePrompt,n as mapLimit,s as newRolloutId,x as noRecorder,c as pullWithCache,r as serializeFields,t as validateFields};
|
package/dist/prompt/bind.js
CHANGED
|
@@ -1,15 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
const DEFAULT_CONCURRENCY = 4;
|
|
3
|
-
export function bind(prompt, model) {
|
|
4
|
-
const once = (values, opts, streaming) => prompt.call(values, ({ messages, turn }) => {
|
|
5
|
-
const modelOpts = { tools: turn, onText: opts.onText };
|
|
6
|
-
return streaming && model.stream
|
|
7
|
-
? model.stream(messages, modelOpts)
|
|
8
|
-
: model.call(messages, modelOpts);
|
|
9
|
-
}, opts);
|
|
10
|
-
return {
|
|
11
|
-
invoke: (values = {}, opts = {}) => once(values, opts, false),
|
|
12
|
-
stream: (values = {}, opts = {}) => once(values, opts, true),
|
|
13
|
-
batch: (values, opts = {}) => mapLimit(values, opts.concurrency ?? DEFAULT_CONCURRENCY, (v) => once(v, opts, false)),
|
|
14
|
-
};
|
|
15
|
-
}
|
|
1
|
+
import{mapLimit as m}from"../run/concurrency.js";const s=4;function f(i,r){const c=(n,t,e)=>i.call(n,({messages:o,turn:l})=>{const a={tools:l,onText:t.onText};return e&&r.stream?r.stream(o,a):r.call(o,a)},t);return{invoke:(n={},t={})=>c(n,t,!1),stream:(n={},t={})=>c(n,t,!0),batch:(n,t={})=>m(n,t.concurrency??s,e=>c(e,t,!1))}}export{f as bind};
|
package/dist/prompt/factory.d.ts
CHANGED
|
@@ -17,7 +17,7 @@ export interface PromptShape {
|
|
|
17
17
|
*
|
|
18
18
|
* A server prompt writes a rollout; a custom one has no row to hang one on and
|
|
19
19
|
* writes usage instead. Injecting it is what lets both constructors share one
|
|
20
|
-
* `
|
|
20
|
+
* `call`, so the two can never drift on what "recorded" means.
|
|
21
21
|
*/
|
|
22
22
|
export interface Recorder {
|
|
23
23
|
enabled: boolean;
|
package/dist/prompt/factory.js
CHANGED
|
@@ -1,100 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { renderMessages } from "../render/index.js";
|
|
3
|
-
import { newRolloutId } from "../run/id.js";
|
|
4
|
-
import { bind } from "./bind.js";
|
|
5
|
-
export const noRecorder = {
|
|
6
|
-
enabled: false,
|
|
7
|
-
write: () => { },
|
|
8
|
-
};
|
|
9
|
-
export const MAX_RECORDED_MESSAGES = 50;
|
|
10
|
-
let warnedAboutLength = false;
|
|
11
|
-
function warnIfUnrecordable(messages) {
|
|
12
|
-
if (warnedAboutLength || messages.length <= MAX_RECORDED_MESSAGES)
|
|
13
|
-
return;
|
|
14
|
-
warnedAboutLength = true;
|
|
15
|
-
console.warn(`[prompt] ${messages.length} messages is over the ${MAX_RECORDED_MESSAGES} a rollout ` +
|
|
16
|
-
"can record. The call still runs; the rollout will be rejected. Trim the history you pass.");
|
|
17
|
-
}
|
|
18
|
-
function lastUserMessage(messages) {
|
|
19
|
-
for (let i = messages.length - 1; i >= 0; i--) {
|
|
20
|
-
if (messages[i].role === "user")
|
|
21
|
-
return messages[i].content;
|
|
22
|
-
}
|
|
23
|
-
return "";
|
|
24
|
-
}
|
|
25
|
-
export function makePrompt(shape, source, recorder = noRecorder) {
|
|
26
|
-
const serialize = (values = {}) => serializeFields(values, shape.fields);
|
|
27
|
-
const format = (values = {}, opts = {}) => renderMessages(shape.blocks, shape.question, serialize(values), opts.history);
|
|
28
|
-
const built = {
|
|
29
|
-
id: shape.id,
|
|
30
|
-
name: shape.name,
|
|
31
|
-
slug: shape.slug,
|
|
32
|
-
fields: shape.fields,
|
|
33
|
-
versionId: shape.versionId,
|
|
34
|
-
models: shape.models,
|
|
35
|
-
source,
|
|
36
|
-
serialize,
|
|
37
|
-
format,
|
|
38
|
-
async call(values, run, opts = {}) {
|
|
39
|
-
const messages = format(values, { history: opts.history });
|
|
40
|
-
warnIfUnrecordable(messages);
|
|
41
|
-
const turn = opts.tools?.trace(opts.query ?? lastUserMessage(messages));
|
|
42
|
-
const rolloutId = opts.rolloutId ?? newRolloutId();
|
|
43
|
-
const recording = recorder.enabled && (opts.report ?? true);
|
|
44
|
-
const startedAt = Date.now();
|
|
45
|
-
const sent = {
|
|
46
|
-
rolloutId,
|
|
47
|
-
versionId: shape.versionId,
|
|
48
|
-
fields: serialize(values),
|
|
49
|
-
rendered: messages,
|
|
50
|
-
};
|
|
51
|
-
let outcome;
|
|
52
|
-
try {
|
|
53
|
-
outcome = await run({ messages, turn });
|
|
54
|
-
}
|
|
55
|
-
catch (err) {
|
|
56
|
-
if (recording) {
|
|
57
|
-
const recorded = turn?.record();
|
|
58
|
-
recorder.write(shape.id, {
|
|
59
|
-
...sent,
|
|
60
|
-
model: "unknown",
|
|
61
|
-
output: "",
|
|
62
|
-
status: "failed",
|
|
63
|
-
error: err instanceof Error ? err.message : String(err),
|
|
64
|
-
latencyMs: Date.now() - startedAt,
|
|
65
|
-
offeredTools: recorded?.offeredTools,
|
|
66
|
-
steps: recorded?.steps,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
throw err;
|
|
70
|
-
}
|
|
71
|
-
const latencyMs = Date.now() - startedAt;
|
|
72
|
-
let pricing;
|
|
73
|
-
if (recording) {
|
|
74
|
-
const recorded = turn?.record();
|
|
75
|
-
const written = recorder.write(shape.id, {
|
|
76
|
-
...sent,
|
|
77
|
-
model: outcome.model,
|
|
78
|
-
output: outcome.output,
|
|
79
|
-
status: outcome.status ?? "completed",
|
|
80
|
-
error: outcome.error,
|
|
81
|
-
inputTokens: outcome.inputTokens,
|
|
82
|
-
outputTokens: outcome.outputTokens,
|
|
83
|
-
cacheReadTokens: outcome.cacheReadTokens,
|
|
84
|
-
cacheWriteTokens: outcome.cacheWriteTokens,
|
|
85
|
-
citationTokens: outcome.citationTokens,
|
|
86
|
-
reasoningTokens: outcome.reasoningTokens,
|
|
87
|
-
latencyMs,
|
|
88
|
-
caseId: outcome.caseId,
|
|
89
|
-
seed: outcome.seed,
|
|
90
|
-
offeredTools: outcome.offeredTools ?? recorded?.offeredTools,
|
|
91
|
-
steps: outcome.steps ?? recorded?.steps,
|
|
92
|
-
});
|
|
93
|
-
pricing = written instanceof Promise ? written : undefined;
|
|
94
|
-
}
|
|
95
|
-
return { ...outcome, rolloutId, ...(pricing ? { pricing } : {}) };
|
|
96
|
-
},
|
|
97
|
-
bind: (model) => bind(built, model),
|
|
98
|
-
};
|
|
99
|
-
return built;
|
|
100
|
-
}
|
|
1
|
+
import{serializeFields as S}from"@spendgraph/sdk";import{findVariables as v,renderMessages as I}from"../render/index.js";import{newRolloutId as E}from"../run/id.js";import{bind as q}from"./bind.js";const $={enabled:!1,write:()=>{}},A=50;let D=!1;function j(e){D||e.length<=A||(D=!0,console.warn(`[prompt] ${e.length} messages is over the ${A} a rollout can record. The call still runs; the rollout will be rejected. Trim the history you pass.`))}function x(e,r,l){const s=Object.keys(e).filter(i=>l.has(i)&&!r.has(i));return s.length===0||console.warn(`[prompt] ${s.map(i=>`{${i}}`).join(", ")} appears in this prompt and you passed a value for it, but no field declares it, so it was not substituted and the placeholder goes to the model as written. Add it to the prompt's fields.`),s}function z(e){for(let r=e.length-1;r>=0;r--)if(e[r].role==="user")return e[r].content;return""}function _(e,r,l=$){const s=new Set(e.fields.map(o=>o.name)),i=new Set(v(e.blocks,e.question));let w=!1;const u=(o={})=>(w||(w=x(o,s,i).length>0),S(o,e.fields)),M=(o={},f={})=>I(e.blocks,e.question,u(o),f.history),T={id:e.id,name:e.name,slug:e.slug,fields:e.fields,versionId:e.versionId,models:e.models,source:r,serialize:u,format:M,async call(o,f,d={}){const b=u(o),a=I(e.blocks,e.question,b,d.history);j(a);const m=d.tools?.trace(d.query??z(a)),k=d.rolloutId??E(),g=l.enabled&&(d.report??!0),h=Date.now(),y={rolloutId:k,versionId:e.versionId,fields:b,rendered:a};let t;try{t=await f({messages:a,turn:m})}catch(n){if(g){const c=m?.record();l.write(e.id,{...y,model:"unknown",output:"",status:"failed",error:n instanceof Error?n.message:String(n),latencyMs:Date.now()-h,offeredTools:c?.offeredTools,steps:c?.steps})}throw n}const R=Date.now()-h;let p;if(g){const n=m?.record(),c=l.write(e.id,{...y,model:t.model,output:t.output,status:t.status??"completed",error:t.error,inputTokens:t.inputTokens,outputTokens:t.outputTokens,cacheReadTokens:t.cacheReadTokens,cacheWriteTokens:t.cacheWriteTokens,citationTokens:t.citationTokens,reasoningTokens:t.reasoningTokens,latencyMs:R,caseId:t.caseId,seed:t.seed,offeredTools:t.offeredTools??n?.offeredTools,steps:t.steps??n?.steps});p=c instanceof Promise?c:void 0}return{...t,rolloutId:k,...p?{pricing:p}:{}}},bind:o=>q(T,o)};return T}export{A as MAX_RECORDED_MESSAGES,_ as makePrompt,$ as noRecorder};
|
package/dist/prompt/index.js
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { MAX_RECORDED_MESSAGES, makePrompt, noRecorder } from "./factory.js";
|
|
1
|
+
import{bind as e}from"./bind.js";import{MAX_RECORDED_MESSAGES as E,makePrompt as p,noRecorder as t}from"./factory.js";export{E as MAX_RECORDED_MESSAGES,e as bind,p as makePrompt,t as noRecorder};
|
package/dist/pull/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
import{pullWithCache as l}from"./pull.js";export{l as pullWithCache};
|
package/dist/pull/pull.js
CHANGED
|
@@ -1,19 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const hit = cache.get(key);
|
|
3
|
-
if (hit && !hit.stale)
|
|
4
|
-
return hit.value;
|
|
5
|
-
if (hit) {
|
|
6
|
-
cache.refreshInBackground(key, fetchOne);
|
|
7
|
-
return hit.value;
|
|
8
|
-
}
|
|
9
|
-
const startedAt = cache.beginFetch();
|
|
10
|
-
try {
|
|
11
|
-
const value = await fetchOne();
|
|
12
|
-
cache.settle(key, value, startedAt);
|
|
13
|
-
return value;
|
|
14
|
-
}
|
|
15
|
-
catch (err) {
|
|
16
|
-
cache.abandon(key);
|
|
17
|
-
throw err;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
1
|
+
async function o(t,n,e){const r=t.get(n);if(r&&!r.stale)return r.value;if(r)return t.refreshInBackground(n,e),r.value;const u=t.beginFetch();try{const a=await e();return t.settle(n,a,u),a}catch(a){throw t.abandon(n),a}}export{o as pullWithCache};
|
package/dist/render/index.js
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
2
|
-
export { compileSystemPrompt } from "./system.js";
|
|
3
|
-
export { applyVariables, findVariables } from "./variables.js";
|
|
1
|
+
import{renderMessages as o}from"./messages.js";import{compileSystemPrompt as a}from"./system.js";import{applyVariables as s,findVariables as t}from"./variables.js";export{s as applyVariables,a as compileSystemPrompt,t as findVariables,o as renderMessages};
|
package/dist/render/messages.js
CHANGED
|
@@ -1,14 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { applyVariables } from "./variables.js";
|
|
3
|
-
export function renderMessages(blocks, question, values, history = []) {
|
|
4
|
-
const system = compileSystemPrompt(blocks, values);
|
|
5
|
-
const user = applyVariables(question, values);
|
|
6
|
-
const turns = history.filter((m) => m.role !== "system");
|
|
7
|
-
return system
|
|
8
|
-
? [
|
|
9
|
-
{ role: "system", content: system },
|
|
10
|
-
...turns,
|
|
11
|
-
{ role: "user", content: user },
|
|
12
|
-
]
|
|
13
|
-
: [...turns, { role: "user", content: user }];
|
|
14
|
-
}
|
|
1
|
+
import{compileSystemPrompt as l}from"./system.js";import{applyVariables as p}from"./variables.js";function y(s,n,e,m=[]){const t=l(s,e),r=p(n,e),o=m.filter(c=>c.role!=="system");return t?[{role:"system",content:t},...o,{role:"user",content:r}]:[...o,{role:"user",content:r}]}export{y as renderMessages};
|
package/dist/render/system.js
CHANGED
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
const body = b.body?.trim();
|
|
6
|
-
if (!body)
|
|
7
|
-
continue;
|
|
8
|
-
const title = b.title?.trim();
|
|
9
|
-
const text = applyVariables(body, values);
|
|
10
|
-
out.push(title ? `## ${applyVariables(title, values)}\n${text}` : text);
|
|
11
|
-
}
|
|
12
|
-
return out.join("\n\n");
|
|
13
|
-
}
|
|
1
|
+
import{applyVariables as e}from"./variables.js";function s(m,t){const o=[];for(const n of m??[]){const i=n.body?.trim();if(!i)continue;const r=n.title?.trim(),c=e(i,t);o.push(r?`## ${e(r,t)}
|
|
2
|
+
${c}`:c)}return o.join(`
|
|
3
|
+
|
|
4
|
+
`)}export{s as compileSystemPrompt};
|
package/dist/render/types.js
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -3,6 +3,13 @@ import type { Block } from "./types.js";
|
|
|
3
3
|
* Substitutes `{name}` placeholders, leaving unknown ones verbatim — emptying
|
|
4
4
|
* one would send a prompt with a hole the caller cannot see.
|
|
5
5
|
*
|
|
6
|
+
* `Object.hasOwn` rather than `in`, which walks the prototype chain: every
|
|
7
|
+
* object has `constructor`, `toString` and `valueOf`, so `in` counted those as
|
|
8
|
+
* supplied and a prompt reading "explain what {constructor} does" went to the
|
|
9
|
+
* model as "explain what function Object() { [native code] } does". A template
|
|
10
|
+
* about code is all it takes, and noise that looks like content is worse than
|
|
11
|
+
* the visible hole this function exists to avoid.
|
|
12
|
+
*
|
|
6
13
|
* Mirrors `lib/prompt.ts` in the app. Duplicated because this package depends on
|
|
7
14
|
* nothing; `rendered` on every rollout makes a divergence visible.
|
|
8
15
|
*/
|
package/dist/render/variables.js
CHANGED
|
@@ -1,20 +1 @@
|
|
|
1
|
-
|
|
2
|
-
if (!text || !values)
|
|
3
|
-
return text;
|
|
4
|
-
return text.replace(/\{(\w+)\}/g, (whole, name) => name in values ? values[name] : whole);
|
|
5
|
-
}
|
|
6
|
-
export function findVariables(blocks, question) {
|
|
7
|
-
const seen = [];
|
|
8
|
-
const scan = (text) => {
|
|
9
|
-
for (const m of text.matchAll(/\{(\w+)\}/g)) {
|
|
10
|
-
if (!seen.includes(m[1]))
|
|
11
|
-
seen.push(m[1]);
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
for (const b of blocks ?? []) {
|
|
15
|
-
scan(b.title ?? "");
|
|
16
|
-
scan(b.body ?? "");
|
|
17
|
-
}
|
|
18
|
-
scan(question);
|
|
19
|
-
return seen;
|
|
20
|
-
}
|
|
1
|
+
function f(o,r){return!o||!r?o:o.replace(/\{(\w+)\}/g,(c,n)=>Object.hasOwn(r,n)?r[n]:c)}function i(o,r){const c=[],n=t=>{for(const e of t.matchAll(/\{(\w+)\}/g))c.includes(e[1])||c.push(e[1])};for(const t of o??[])n(t.title??""),n(t.body??"");return n(r),c}export{f as applyVariables,i as findVariables};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { Prompts } from "@spendgraph/sdk";
|
|
2
2
|
import type { Budget } from "../budget/index.js";
|
|
3
3
|
import type { RunOptions, RunResult } from "../types/index.js";
|
|
4
|
-
/**
|
|
4
|
+
/**
|
|
5
|
+
* One rollout per model — the playground's comparison, headless.
|
|
6
|
+
*
|
|
7
|
+
* Always one result per model, in the order given. A model that failed is
|
|
8
|
+
* present with `status: "failed"` rather than missing, for the same reason
|
|
9
|
+
* `sampleRuns` keeps a failed seed: this is a comparison, and throwing on the
|
|
10
|
+
* first bad model discards every model that answered — after paying for them,
|
|
11
|
+
* because the calls already in flight are not cancelled by the throw.
|
|
12
|
+
*
|
|
13
|
+
* A budget stop throws instead. Money running out says nothing about a model.
|
|
14
|
+
*/
|
|
5
15
|
export declare function runAcrossModels(prompts: Prompts, promptId: string, values: Record<string, unknown>, models: string[], opts?: RunOptions & {
|
|
6
16
|
concurrency?: number;
|
|
7
17
|
}, budget?: Budget): Promise<RunResult[]>;
|
|
@@ -1,5 +1 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { runOnce } from "./once.js";
|
|
3
|
-
export async function runAcrossModels(prompts, promptId, values, models, opts = {}, budget) {
|
|
4
|
-
return mapLimit(models, opts.concurrency ?? 4, (model) => runOnce(prompts, promptId, values, { ...opts, model, rolloutId: undefined }, budget));
|
|
5
|
-
}
|
|
1
|
+
import{BudgetExceededError as i}from"../budget/index.js";import{mapLimit as a}from"./concurrency.js";import{runOnce as d}from"./once.js";async function p(n,o,u,c,r={},s){return a(c,r.concurrency??4,async t=>{try{return await d(n,o,u,{...r,model:t,rolloutId:void 0},s)}catch(e){if(e instanceof i)throw e;return{id:null,model:t,status:"failed",output:"",error:e.message,costMicros:0,latencyMs:0,inputTokens:0,outputTokens:0,seed:r.seed??0}}})}export{p as runAcrossModels};
|
package/dist/run/concurrency.js
CHANGED
|
@@ -1,12 +1 @@
|
|
|
1
|
-
|
|
2
|
-
const out = new Array(items.length);
|
|
3
|
-
let next = 0;
|
|
4
|
-
const workers = Array.from({ length: Math.max(1, Math.min(limit, items.length)) }, async () => {
|
|
5
|
-
while (next < items.length) {
|
|
6
|
-
const i = next++;
|
|
7
|
-
out[i] = await fn(items[i], i);
|
|
8
|
-
}
|
|
9
|
-
});
|
|
10
|
-
await Promise.all(workers);
|
|
11
|
-
return out;
|
|
12
|
-
}
|
|
1
|
+
async function h(n,e,o){const a=new Array(n.length);let r=0;const l=Array.from({length:Math.max(1,Math.min(e,n.length))},async()=>{for(;r<n.length;){const t=r++;a[t]=await o(n[t],t)}});return await Promise.all(l),a}export{h as mapLimit};
|
package/dist/run/id.js
CHANGED