@dereekb/openrouter 14.6.0 → 14.8.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/README.md +144 -1
- package/firebase/index.esm.js +14 -5
- package/firebase/package.json +7 -7
- package/firebase/src/lib/openrouter.api.d.ts +21 -0
- package/firebase/src/lib/openrouter.model.d.ts +74 -2
- package/firebase-server/index.esm.js +417 -49
- package/firebase-server/package.json +12 -12
- package/firebase-server/src/lib/openrouter.call.inline.d.ts +58 -1
- package/firebase-server/src/lib/openrouter.runtask.handle.d.ts +26 -0
- package/firebase-server/src/lib/openrouter.runtask.service.d.ts +37 -1
- package/firebase-server/src/test/openrouter.fake.d.ts +45 -0
- package/index.esm.js +1402 -52
- package/package.json +7 -7
- package/src/lib/index.d.ts +2 -0
- package/src/lib/openrouter.call.d.ts +18 -1
- package/src/lib/openrouter.config.d.ts +18 -1
- package/src/lib/openrouter.decision.d.ts +352 -0
- package/src/lib/openrouter.decision.question.d.ts +392 -0
- package/src/lib/openrouter.prompt.d.ts +25 -0
- package/src/lib/openrouter.sdk.d.ts +10 -2
- package/src/lib/openrouter.type.d.ts +51 -0
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dereekb/openrouter/firebase-server",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.8.0",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"peerDependencies": {
|
|
7
|
-
"@dereekb/analytics": "14.
|
|
8
|
-
"@dereekb/date": "14.
|
|
9
|
-
"@dereekb/firebase": "14.
|
|
10
|
-
"@dereekb/firebase-server": "14.
|
|
11
|
-
"@dereekb/model": "14.
|
|
12
|
-
"@dereekb/nestjs": "14.
|
|
13
|
-
"@dereekb/openrouter": "14.
|
|
14
|
-
"@dereekb/rxjs": "14.
|
|
15
|
-
"@dereekb/util": "14.
|
|
7
|
+
"@dereekb/analytics": "14.8.0",
|
|
8
|
+
"@dereekb/date": "14.8.0",
|
|
9
|
+
"@dereekb/firebase": "14.8.0",
|
|
10
|
+
"@dereekb/firebase-server": "14.8.0",
|
|
11
|
+
"@dereekb/model": "14.8.0",
|
|
12
|
+
"@dereekb/nestjs": "14.8.0",
|
|
13
|
+
"@dereekb/openrouter": "14.8.0",
|
|
14
|
+
"@dereekb/rxjs": "14.8.0",
|
|
15
|
+
"@dereekb/util": "14.8.0",
|
|
16
16
|
"@nestjs/common": "^12.0.1",
|
|
17
17
|
"@nestjs/config": "^12.0.0",
|
|
18
|
-
"@openrouter/sdk": "^1.
|
|
18
|
+
"@openrouter/sdk": "^1.3.8",
|
|
19
19
|
"arktype": "^2.2.0",
|
|
20
20
|
"date-fns": "^4.1.0",
|
|
21
21
|
"express": "^5.2.1",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
"make-error": "^1.3.6"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@dereekb/nestjs": "14.
|
|
26
|
+
"@dereekb/nestjs": "14.8.0",
|
|
27
27
|
"@nestjs/testing": "^12.0.1"
|
|
28
28
|
},
|
|
29
29
|
"exports": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
|
-
import { type OpenRouterAttachedFileReference, type OpenRouterCallResult, type OpenRouterCore, type OpenRouterInput, type OpenRouterModelConfig, type OpenRouterPromptKey, type OpenRouterPromptVersionNumber, type Tool } from '@dereekb/openrouter';
|
|
2
|
+
import { type OpenRouterAttachedFileReference, type OpenRouterCallResult, type OpenRouterCore, type OpenRouterDecisionQuestions, type OpenRouterDecisionResult, type OpenRouterDecisionState, type OpenRouterInput, type OpenRouterModelConfig, type OpenRouterPromptKey, type OpenRouterPromptVersionNumber, type Tool } from '@dereekb/openrouter';
|
|
3
3
|
import { type OpenRouterPromptService } from './openrouter.prompt.service';
|
|
4
4
|
/**
|
|
5
5
|
* Params for {@link callModelForPrompt}.
|
|
@@ -55,3 +55,60 @@ export interface CallModelForPromptParams {
|
|
|
55
55
|
* @returns The normalized call result.
|
|
56
56
|
*/
|
|
57
57
|
export declare function callModelForPrompt(params: CallModelForPromptParams): Promise<OpenRouterCallResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Params for {@link decideForPrompt}.
|
|
60
|
+
*/
|
|
61
|
+
export interface DecideForPromptParams {
|
|
62
|
+
/**
|
|
63
|
+
* The OpenRouter client.
|
|
64
|
+
*/
|
|
65
|
+
readonly client: OpenRouterCore;
|
|
66
|
+
/**
|
|
67
|
+
* The prompt service used to resolve the version.
|
|
68
|
+
*/
|
|
69
|
+
readonly promptService: OpenRouterPromptService;
|
|
70
|
+
/**
|
|
71
|
+
* The decision prompt to ask.
|
|
72
|
+
*/
|
|
73
|
+
readonly promptKey: OpenRouterPromptKey;
|
|
74
|
+
/**
|
|
75
|
+
* Version to pin. Omit to use the prompt's active version.
|
|
76
|
+
*/
|
|
77
|
+
readonly version?: Maybe<OpenRouterPromptVersionNumber>;
|
|
78
|
+
/**
|
|
79
|
+
* The content to judge.
|
|
80
|
+
*/
|
|
81
|
+
readonly state: OpenRouterDecisionState;
|
|
82
|
+
/**
|
|
83
|
+
* Questions declared for THIS call, merged over the version's stored questions by id.
|
|
84
|
+
*/
|
|
85
|
+
readonly questions?: Maybe<OpenRouterDecisionQuestions>;
|
|
86
|
+
/**
|
|
87
|
+
* Per-call config overrides.
|
|
88
|
+
*/
|
|
89
|
+
readonly configOverrides?: Maybe<OpenRouterModelConfig>;
|
|
90
|
+
/**
|
|
91
|
+
* Observability grouping id.
|
|
92
|
+
*/
|
|
93
|
+
readonly sessionId?: Maybe<string>;
|
|
94
|
+
/**
|
|
95
|
+
* Trace metadata for cost/usage reconciliation.
|
|
96
|
+
*/
|
|
97
|
+
readonly trace?: Maybe<Record<string, unknown>>;
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Asks a decision prompt INLINE and returns its answers, with no run task document.
|
|
101
|
+
*
|
|
102
|
+
* The default way to ask a decision. A System One call typically answers in around a hundred
|
|
103
|
+
* milliseconds, has no tools to loop and nothing to defer, so the queue's lease, sweep interval and
|
|
104
|
+
* retry ladder buy nothing on the happy path — paying for a document to run a call that finishes before
|
|
105
|
+
* the write does is pure overhead.
|
|
106
|
+
*
|
|
107
|
+
* Reach for `enqueueRunTask({ state, questions, immediate: true })` instead when a FAILURE needs to
|
|
108
|
+
* survive this process: that keeps the same run-it-now latency and leaves a retryable failure queued for
|
|
109
|
+
* the sweep, at the cost of one document per run.
|
|
110
|
+
*
|
|
111
|
+
* @param params - The client, prompt service, prompt, state, and questions.
|
|
112
|
+
* @returns The decision result.
|
|
113
|
+
*/
|
|
114
|
+
export declare function decideForPrompt(params: DecideForPromptParams): Promise<OpenRouterDecisionResult>;
|
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
import { type Maybe } from '@dereekb/util';
|
|
2
|
+
import { type OpenRouterDecisionAnswers, type OpenRouterDecisionQuestions } from '@dereekb/openrouter';
|
|
2
3
|
import { type OpenRouterRunTask } from '@dereekb/openrouter/firebase';
|
|
4
|
+
/**
|
|
5
|
+
* Whether a run task is a DECISION run.
|
|
6
|
+
*
|
|
7
|
+
* Reads the state field, which is the discriminator — see `OpenRouterRunTask.st`.
|
|
8
|
+
*
|
|
9
|
+
* @param task - The run task.
|
|
10
|
+
* @returns True when the task asks a decision rather than a completion.
|
|
11
|
+
*
|
|
12
|
+
* @__NO_SIDE_EFFECTS__
|
|
13
|
+
*/
|
|
14
|
+
export declare function isOpenRouterDecisionRunTask(task: Maybe<OpenRouterRunTask>): boolean;
|
|
15
|
+
/**
|
|
16
|
+
* Reads the answers off a completed decision run.
|
|
17
|
+
*
|
|
18
|
+
* The type parameter is the caller's own question map, which is what lets a consumer read
|
|
19
|
+
* `answers.urgency.noul` rather than walking an untyped record. It is an ASSERTION, not a check: the
|
|
20
|
+
* answers were membership-checked against the declared questions when they were written, so the only
|
|
21
|
+
* way this lies is a caller naming a different question map than the run used.
|
|
22
|
+
*
|
|
23
|
+
* @param task - The run task.
|
|
24
|
+
* @returns The answers, or undefined when the run is not a completed decision.
|
|
25
|
+
*
|
|
26
|
+
* @__NO_SIDE_EFFECTS__
|
|
27
|
+
*/
|
|
28
|
+
export declare function openRouterRunTaskDecisionAnswers<Q extends OpenRouterDecisionQuestions = OpenRouterDecisionQuestions>(task: Maybe<OpenRouterRunTask>): Maybe<OpenRouterDecisionAnswers<Q>>;
|
|
3
29
|
/**
|
|
4
30
|
* How a caller should proceed given a run task's current state.
|
|
5
31
|
*
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { type FirebaseStorageContext } from '@dereekb/firebase';
|
|
2
2
|
import { type FirebaseServerEnvService } from '@dereekb/firebase-server';
|
|
3
3
|
import { type Maybe, type Milliseconds } from '@dereekb/util';
|
|
4
|
-
import { type OpenRouterAttachedFileReference, type OpenRouterCallResult, type OpenRouterCore, type OpenRouterDeferredToolResolution, type OpenRouterFileReference, type OpenRouterInput, type OpenRouterModelConfig, type OpenRouterPromptKey, type OpenRouterPromptVersionNumber, type OpenRouterRunTaskKey, type Tool } from '@dereekb/openrouter';
|
|
4
|
+
import { type OpenRouterAttachedFileReference, type OpenRouterCallResult, type OpenRouterCore, type OpenRouterDecisionQuestions, type OpenRouterDecisionResult, type OpenRouterDeferredToolResolution, type OpenRouterFileReference, type OpenRouterInput, type OpenRouterModelConfig, type OpenRouterPromptKey, type OpenRouterPromptVersionNumber, type OpenRouterRunTaskKey, type OpenRouterStorableDecisionState, type Tool } from '@dereekb/openrouter';
|
|
5
5
|
import { type OpenRouterRunTask, type OpenRouterRunTaskDocument, type OpenRouterRunTaskFirestoreCollections, type OpenRouterRunTaskPendingToolCall, OpenRouterRunTaskState, type OpenRouterRunTaskUnsentToolResult } from '@dereekb/openrouter/firebase';
|
|
6
6
|
import { type OpenRouterFileAttachmentMode } from './openrouter.file.attachment';
|
|
7
7
|
import { type OpenRouterPromptService } from './openrouter.prompt.service';
|
|
@@ -69,6 +69,30 @@ export interface OpenRouterEnqueueRunTaskParams {
|
|
|
69
69
|
* that is already in flight or already finished.
|
|
70
70
|
*/
|
|
71
71
|
readonly restart?: Maybe<boolean>;
|
|
72
|
+
/**
|
|
73
|
+
* The content to judge, making this a DECISION run.
|
|
74
|
+
*
|
|
75
|
+
* Presence of this is what sends the run to `POST /systemone` instead of `/responses`, and it is the
|
|
76
|
+
* only discriminator: which surface a request needs is a property of the request, and a second field
|
|
77
|
+
* declaring it is a second thing that can disagree.
|
|
78
|
+
*/
|
|
79
|
+
readonly state?: Maybe<OpenRouterStorableDecisionState>;
|
|
80
|
+
/**
|
|
81
|
+
* Questions declared for THIS run, merged over the prompt version's own stored questions.
|
|
82
|
+
*/
|
|
83
|
+
readonly questions?: Maybe<OpenRouterDecisionQuestions>;
|
|
84
|
+
/**
|
|
85
|
+
* Whether to run the task immediately rather than leaving it for the next sweep.
|
|
86
|
+
*
|
|
87
|
+
* The document is written either way, so a consumer's `readRunTask(key)` contract does not change
|
|
88
|
+
* shape depending on whether the inline attempt happened to succeed — which is the whole reason this
|
|
89
|
+
* is a flag on the queue rather than a separate inline call. What it buys is the queue's durability
|
|
90
|
+
* without the queue's latency: the common case answers within this call, and a run that fails
|
|
91
|
+
* RETRYABLY (OpenRouter down, a 429, a dropped connection) is left QUEUED for the sweep to pick up. A
|
|
92
|
+
* deterministic failure still reaches FAILED on the first attempt, because three sweep ticks would
|
|
93
|
+
* only reach the same answer more slowly.
|
|
94
|
+
*/
|
|
95
|
+
readonly immediate?: Maybe<boolean>;
|
|
72
96
|
}
|
|
73
97
|
/**
|
|
74
98
|
* Result of enqueueing a run task.
|
|
@@ -81,6 +105,14 @@ export interface OpenRouterEnqueueRunTaskResult {
|
|
|
81
105
|
*/
|
|
82
106
|
readonly created: boolean;
|
|
83
107
|
readonly task: OpenRouterRunTask;
|
|
108
|
+
/**
|
|
109
|
+
* What the immediate attempt did, when one was asked for and actually ran.
|
|
110
|
+
*
|
|
111
|
+
* Absent when `immediate` was not set, and also when it was but the task was not claimable — an
|
|
112
|
+
* already-running or already-finished run reached through an idempotent re-enqueue. A caller reads the
|
|
113
|
+
* document rather than assuming this is present.
|
|
114
|
+
*/
|
|
115
|
+
readonly execution?: Maybe<OpenRouterRunTaskExecutionResult>;
|
|
84
116
|
}
|
|
85
117
|
/**
|
|
86
118
|
* Params for claiming run tasks.
|
|
@@ -169,6 +201,10 @@ export interface OpenRouterRunTaskExecutionResult {
|
|
|
169
201
|
readonly key: OpenRouterRunTaskKey;
|
|
170
202
|
readonly state: OpenRouterRunTaskState;
|
|
171
203
|
readonly result?: Maybe<OpenRouterCallResult>;
|
|
204
|
+
/**
|
|
205
|
+
* What a DECISION run produced. Present instead of `result`, never alongside it.
|
|
206
|
+
*/
|
|
207
|
+
readonly decision?: Maybe<OpenRouterDecisionResult>;
|
|
172
208
|
readonly error?: Maybe<unknown>;
|
|
173
209
|
}
|
|
174
210
|
/**
|
|
@@ -19,6 +19,20 @@ export interface FakeOpenRouterToolCall {
|
|
|
19
19
|
readonly name: string;
|
|
20
20
|
readonly arguments?: Maybe<Record<string, unknown>>;
|
|
21
21
|
}
|
|
22
|
+
/**
|
|
23
|
+
* What the fake System One model should answer with, when the request went to `/systemone`.
|
|
24
|
+
*/
|
|
25
|
+
export interface FakeOpenRouterDecisionReply {
|
|
26
|
+
/**
|
|
27
|
+
* The answers, keyed by question id, in the WIRE shape (`{ type, noul }`, `{ type, choice }`, …).
|
|
28
|
+
*
|
|
29
|
+
* Deliberately untyped: a fixture has to be able to produce replies the declaration types forbid,
|
|
30
|
+
* which is the only way the membership check gets exercised at all.
|
|
31
|
+
*/
|
|
32
|
+
readonly answers?: Maybe<Record<string, unknown>>;
|
|
33
|
+
readonly inputTokens?: Maybe<number>;
|
|
34
|
+
readonly outputTokens?: Maybe<number>;
|
|
35
|
+
}
|
|
22
36
|
/**
|
|
23
37
|
* What the fake model should answer with on one turn.
|
|
24
38
|
*/
|
|
@@ -49,6 +63,14 @@ export interface FakeOpenRouterReply {
|
|
|
49
63
|
* Thrown instead of answered, for the transport-failure path.
|
|
50
64
|
*/
|
|
51
65
|
readonly throws?: Maybe<Error>;
|
|
66
|
+
/**
|
|
67
|
+
* An HTTP status to answer with instead of a success, for the retryable-vs-permanent classification.
|
|
68
|
+
*/
|
|
69
|
+
readonly status?: Maybe<number>;
|
|
70
|
+
/**
|
|
71
|
+
* What to answer a DECISION request with. Ignored on a request that went to `/responses`.
|
|
72
|
+
*/
|
|
73
|
+
readonly decision?: Maybe<FakeOpenRouterDecisionReply>;
|
|
52
74
|
}
|
|
53
75
|
/**
|
|
54
76
|
* Decides the reply for one request. Receives the request body exactly as it went on the wire.
|
|
@@ -63,8 +85,31 @@ export interface FakeOpenRouterClient {
|
|
|
63
85
|
* Every request body sent, in order, serialized exactly as OpenRouter would have received it.
|
|
64
86
|
*/
|
|
65
87
|
readonly requests: Record<string, unknown>[];
|
|
88
|
+
/**
|
|
89
|
+
* Every request URL sent, in order, positionally matching {@link FakeOpenRouterClient.requests}.
|
|
90
|
+
*
|
|
91
|
+
* Recorded because the body alone cannot tell a completion from a decision, and because a fake that
|
|
92
|
+
* never looks at the URL stays green no matter which route the SDK resolves — which is how this
|
|
93
|
+
* vendor's decisions endpoint was once shipped 404ing on every live call with a fully green suite.
|
|
94
|
+
*/
|
|
95
|
+
readonly urls: string[];
|
|
66
96
|
readonly callCount: number;
|
|
67
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* The path a System One (decisions) request goes to.
|
|
100
|
+
*/
|
|
101
|
+
export declare const FAKE_OPENROUTER_SYSTEM_ONE_PATH = "/systemone";
|
|
102
|
+
/**
|
|
103
|
+
* Builds a `DecisionsResponse` JSON body in the WIRE shape the SDK's inbound schema parses.
|
|
104
|
+
*
|
|
105
|
+
* Note the snake_case token counts: the SDK decodes those to camelCase, so a fake emitting the decoded
|
|
106
|
+
* names would hide the rename the usage mapper reads through.
|
|
107
|
+
*
|
|
108
|
+
* @param reply - What the fake System One model should answer with.
|
|
109
|
+
* @param index - The call ordinal, used to make a distinct generation id.
|
|
110
|
+
* @returns The response body.
|
|
111
|
+
*/
|
|
112
|
+
export declare function fakeOpenRouterDecisionResponseBody(reply: Maybe<FakeOpenRouterDecisionReply>, index: number): Record<string, unknown>;
|
|
68
113
|
/**
|
|
69
114
|
* Builds an `OpenResponsesResult` JSON body in the wire (snake_case) shape the SDK's inbound schema
|
|
70
115
|
* parses.
|