@ryanfw/prompt-orchestration-pipeline 1.2.6 → 1.2.7
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/package.json +1 -1
- package/src/config/__tests__/models.test.ts +21 -11
- package/src/config/models.ts +123 -74
- package/src/core/__tests__/lifecycle-policy.test.ts +78 -0
- package/src/core/__tests__/pipeline-runner.test.ts +361 -0
- package/src/core/__tests__/task-runner.test.ts +3 -3
- package/src/core/pipeline-runner.ts +28 -5
- package/src/core/task-runner.ts +2 -5
- package/src/providers/__tests__/base.test.ts +2 -2
- package/src/providers/__tests__/openai.test.ts +1 -1
- package/src/ui/dist/assets/{index-CeAgP91B.js → index-SKy2shWc.js} +100 -58
- package/src/ui/dist/assets/{index-CeAgP91B.js.map → index-SKy2shWc.js.map} +1 -1
- package/src/ui/dist/index.html +1 -1
- package/src/ui/embedded-assets.js +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ryanfw/prompt-orchestration-pipeline",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.7",
|
|
4
4
|
"description": "A Prompt-orchestration pipeline (POP) is a framework for building, running, and experimenting with complex chains of LLM tasks.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/ui/server/index.ts",
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
} from "../models";
|
|
16
16
|
import type { ModelConfigEntry } from "../models";
|
|
17
17
|
|
|
18
|
-
const MODEL_COUNT =
|
|
18
|
+
const MODEL_COUNT = 48;
|
|
19
19
|
const PROVIDER_COUNT = 8;
|
|
20
20
|
|
|
21
21
|
describe("ModelAlias", () => {
|
|
@@ -110,8 +110,8 @@ describe("DEFAULT_MODEL_BY_PROVIDER", () => {
|
|
|
110
110
|
});
|
|
111
111
|
|
|
112
112
|
describe("aliasToFunctionName", () => {
|
|
113
|
-
it('converts "openai:gpt-5.
|
|
114
|
-
expect(aliasToFunctionName("openai:gpt-5.
|
|
113
|
+
it('converts "openai:gpt-5.4" to "gpt54"', () => {
|
|
114
|
+
expect(aliasToFunctionName("openai:gpt-5.4")).toBe("gpt54");
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
it('converts "gemini:flash-2.5-lite" to "flash25Lite"', () => {
|
|
@@ -137,8 +137,8 @@ describe("aliasToFunctionName", () => {
|
|
|
137
137
|
});
|
|
138
138
|
|
|
139
139
|
describe("getProviderFromAlias", () => {
|
|
140
|
-
it('returns "openai" for "openai:gpt-5.
|
|
141
|
-
expect(getProviderFromAlias("openai:gpt-5.
|
|
140
|
+
it('returns "openai" for "openai:gpt-5.4"', () => {
|
|
141
|
+
expect(getProviderFromAlias("openai:gpt-5.4")).toBe("openai");
|
|
142
142
|
});
|
|
143
143
|
|
|
144
144
|
it("throws for non-string input", () => {
|
|
@@ -152,8 +152,8 @@ describe("getProviderFromAlias", () => {
|
|
|
152
152
|
});
|
|
153
153
|
|
|
154
154
|
describe("getModelFromAlias", () => {
|
|
155
|
-
it('returns "gpt-5.
|
|
156
|
-
expect(getModelFromAlias("openai:gpt-5.
|
|
155
|
+
it('returns "gpt-5.4" for "openai:gpt-5.4"', () => {
|
|
156
|
+
expect(getModelFromAlias("openai:gpt-5.4")).toBe("gpt-5.4");
|
|
157
157
|
});
|
|
158
158
|
|
|
159
159
|
it("handles multiple colons by rejoining segments after first", () => {
|
|
@@ -171,8 +171,8 @@ describe("getModelFromAlias", () => {
|
|
|
171
171
|
});
|
|
172
172
|
|
|
173
173
|
describe("getModelConfig", () => {
|
|
174
|
-
it('returns config for "openai:gpt-5.
|
|
175
|
-
const config = getModelConfig("openai:gpt-5.
|
|
174
|
+
it('returns config for "openai:gpt-5.4" with provider "openai"', () => {
|
|
175
|
+
const config = getModelConfig("openai:gpt-5.4");
|
|
176
176
|
expect(config).not.toBeNull();
|
|
177
177
|
expect(config!.provider).toBe("openai");
|
|
178
178
|
});
|
|
@@ -184,10 +184,20 @@ describe("getModelConfig", () => {
|
|
|
184
184
|
|
|
185
185
|
it("returns null for removed aliases", () => {
|
|
186
186
|
expect(getModelConfig("openai:gpt-4")).toBeNull();
|
|
187
|
+
expect(getModelConfig("openai:gpt-4o")).toBeNull();
|
|
188
|
+
expect(getModelConfig("openai:gpt-4o-mini")).toBeNull();
|
|
189
|
+
expect(getModelConfig("openai:gpt-5.2")).toBeNull();
|
|
190
|
+
expect(getModelConfig("openai:gpt-5.2-pro")).toBeNull();
|
|
191
|
+
expect(getModelConfig("openai:o3-mini")).toBeNull();
|
|
192
|
+
expect(getModelConfig("anthropic:haiku-4-6")).toBeNull();
|
|
193
|
+
expect(getModelConfig("deepseek:deepseek-chat")).toBeNull();
|
|
194
|
+
expect(getModelConfig("deepseek:deepseek-reasoner")).toBeNull();
|
|
187
195
|
expect(getModelConfig("deepseek:r1")).toBeNull();
|
|
196
|
+
expect(getModelConfig("moonshot:kimi-k1.5")).toBeNull();
|
|
188
197
|
expect(getModelConfig("moonshot:kimi-moonshot-v1-128k")).toBeNull();
|
|
189
198
|
expect(getModelConfig("gemini:flash-3")).toBeNull();
|
|
190
199
|
expect(getModelConfig("gemini:pro-3")).toBeNull();
|
|
200
|
+
expect(getModelConfig("zai:glm-5-code")).toBeNull();
|
|
191
201
|
expect(getModelConfig("zai:glm-4-plus")).toBeNull();
|
|
192
202
|
});
|
|
193
203
|
});
|
|
@@ -201,8 +211,8 @@ describe("FUNCTION_NAME_BY_ALIAS", () => {
|
|
|
201
211
|
expect(Object.isFrozen(FUNCTION_NAME_BY_ALIAS)).toBe(true);
|
|
202
212
|
});
|
|
203
213
|
|
|
204
|
-
it("has correct value for openai:gpt-5.
|
|
205
|
-
expect(FUNCTION_NAME_BY_ALIAS["openai:gpt-5.
|
|
214
|
+
it("has correct value for openai:gpt-5.4", () => {
|
|
215
|
+
expect(FUNCTION_NAME_BY_ALIAS["openai:gpt-5.4"]).toBe("gpt54");
|
|
206
216
|
});
|
|
207
217
|
|
|
208
218
|
it("has correct value for gemini:flash-2.5-lite", () => {
|
package/src/config/models.ts
CHANGED
|
@@ -41,12 +41,12 @@ export const ModelAlias = Object.freeze({
|
|
|
41
41
|
OPENAI_GPT_4_1: "openai:gpt-4-1",
|
|
42
42
|
OPENAI_GPT_4_1_MINI: "openai:gpt-4-1-mini",
|
|
43
43
|
OPENAI_GPT_4_1_NANO: "openai:gpt-4-1-nano",
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
44
|
+
OPENAI_GPT_5_4: "openai:gpt-5.4",
|
|
45
|
+
OPENAI_GPT_5_4_MINI: "openai:gpt-5.4-mini",
|
|
46
|
+
OPENAI_GPT_5_4_NANO: "openai:gpt-5.4-nano",
|
|
47
|
+
OPENAI_GPT_5_5: "openai:gpt-5.5",
|
|
48
|
+
OPENAI_GPT_5_5_PRO: "openai:gpt-5.5-pro",
|
|
48
49
|
OPENAI_O3: "openai:o3",
|
|
49
|
-
OPENAI_O3_MINI: "openai:o3-mini",
|
|
50
50
|
OPENAI_O4_MINI: "openai:o4-mini",
|
|
51
51
|
// Anthropic
|
|
52
52
|
ANTHROPIC_OPUS_4_5: "anthropic:opus-4-5",
|
|
@@ -54,33 +54,40 @@ export const ModelAlias = Object.freeze({
|
|
|
54
54
|
ANTHROPIC_HAIKU_4_5: "anthropic:haiku-4-5",
|
|
55
55
|
ANTHROPIC_OPUS_4_6: "anthropic:opus-4-6",
|
|
56
56
|
ANTHROPIC_SONNET_4_6: "anthropic:sonnet-4-6",
|
|
57
|
-
|
|
57
|
+
ANTHROPIC_OPUS_4_7: "anthropic:opus-4-7",
|
|
58
58
|
// Gemini
|
|
59
59
|
GEMINI_FLASH_2_5: "gemini:flash-2.5",
|
|
60
60
|
GEMINI_FLASH_2_5_LITE: "gemini:flash-2.5-lite",
|
|
61
61
|
GEMINI_PRO_2_5: "gemini:pro-2.5",
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
62
|
+
GEMINI_PRO_3_1_PREVIEW: "gemini:pro-3.1-preview",
|
|
63
|
+
GEMINI_FLASH_3_PREVIEW: "gemini:flash-3-preview",
|
|
64
|
+
GEMINI_FLASH_3_1_LITE_PREVIEW: "gemini:flash-3.1-lite-preview",
|
|
65
|
+
// DeepSeek
|
|
66
|
+
DEEPSEEK_V4_FLASH: "deepseek:v4-flash",
|
|
67
|
+
DEEPSEEK_V4_PRO: "deepseek:v4-pro",
|
|
65
68
|
// Moonshot / Kimi
|
|
66
69
|
MOONSHOT_KIMI_K2_5: "moonshot:kimi-k2.5",
|
|
67
|
-
|
|
70
|
+
MOONSHOT_KIMI_K2_6: "moonshot:kimi-k2.6",
|
|
68
71
|
// Claude Code — subscription-based, zero token cost
|
|
69
72
|
CLAUDE_CODE_SONNET: "claude-code:sonnet",
|
|
70
73
|
CLAUDE_CODE_OPUS: "claude-code:opus",
|
|
71
74
|
CLAUDE_CODE_HAIKU: "claude-code:haiku",
|
|
72
75
|
// Z.ai
|
|
76
|
+
ZAI_GLM_5_1: "zai:glm-5-1",
|
|
73
77
|
ZAI_GLM_5: "zai:glm-5",
|
|
74
|
-
|
|
78
|
+
ZAI_GLM_5_TURBO: "zai:glm-5-turbo",
|
|
75
79
|
ZAI_GLM_4_7: "zai:glm-4-7",
|
|
76
80
|
ZAI_GLM_4_7_FLASH_X: "zai:glm-4-7-flash-x",
|
|
77
81
|
ZAI_GLM_4_6: "zai:glm-4-6",
|
|
78
82
|
ZAI_GLM_4_5: "zai:glm-4-5",
|
|
83
|
+
ZAI_GLM_4_5_X: "zai:glm-4-5-x",
|
|
79
84
|
ZAI_GLM_4_5_AIR: "zai:glm-4-5-air",
|
|
80
85
|
ZAI_GLM_4_5_AIR_X: "zai:glm-4-5-air-x",
|
|
81
|
-
// Alibaba (Qwen via DashScope)
|
|
86
|
+
// Alibaba (Qwen via DashScope, international/Singapore deployment)
|
|
82
87
|
ALIBABA_QWEN3_MAX: "alibaba:qwen3-max",
|
|
88
|
+
ALIBABA_QWEN3_6_PLUS: "alibaba:qwen3.6-plus",
|
|
83
89
|
ALIBABA_QWEN3_5_PLUS: "alibaba:qwen3.5-plus",
|
|
90
|
+
ALIBABA_QWEN3_5_FLASH: "alibaba:qwen3.5-flash",
|
|
84
91
|
ALIBABA_QWEN_PLUS: "alibaba:qwen-plus",
|
|
85
92
|
ALIBABA_QWEN_FLASH: "alibaba:qwen-flash",
|
|
86
93
|
ALIBABA_QWQ_PLUS: "alibaba:qwq-plus",
|
|
@@ -112,41 +119,41 @@ const MODEL_CONFIG_RAW: Record<ModelAliasKey, ModelConfigEntry> = {
|
|
|
112
119
|
tokenCostInPerMillion: 0.1,
|
|
113
120
|
tokenCostOutPerMillion: 0.4,
|
|
114
121
|
},
|
|
115
|
-
"openai:gpt-
|
|
122
|
+
"openai:gpt-5.4": {
|
|
116
123
|
provider: "openai",
|
|
117
|
-
model: "gpt-
|
|
124
|
+
model: "gpt-5.4",
|
|
118
125
|
tokenCostInPerMillion: 2.5,
|
|
119
|
-
tokenCostOutPerMillion:
|
|
126
|
+
tokenCostOutPerMillion: 15,
|
|
120
127
|
},
|
|
121
|
-
"openai:gpt-
|
|
128
|
+
"openai:gpt-5.4-mini": {
|
|
122
129
|
provider: "openai",
|
|
123
|
-
model: "gpt-
|
|
124
|
-
tokenCostInPerMillion: 0.
|
|
125
|
-
tokenCostOutPerMillion:
|
|
130
|
+
model: "gpt-5.4-mini",
|
|
131
|
+
tokenCostInPerMillion: 0.75,
|
|
132
|
+
tokenCostOutPerMillion: 4.5,
|
|
126
133
|
},
|
|
127
|
-
"openai:gpt-5.
|
|
134
|
+
"openai:gpt-5.4-nano": {
|
|
128
135
|
provider: "openai",
|
|
129
|
-
model: "gpt-5.
|
|
130
|
-
tokenCostInPerMillion: 2,
|
|
131
|
-
tokenCostOutPerMillion:
|
|
136
|
+
model: "gpt-5.4-nano",
|
|
137
|
+
tokenCostInPerMillion: 0.2,
|
|
138
|
+
tokenCostOutPerMillion: 1.25,
|
|
132
139
|
},
|
|
133
|
-
"openai:gpt-5.
|
|
140
|
+
"openai:gpt-5.5": {
|
|
134
141
|
provider: "openai",
|
|
135
|
-
model: "gpt-5.
|
|
136
|
-
tokenCostInPerMillion:
|
|
137
|
-
tokenCostOutPerMillion:
|
|
142
|
+
model: "gpt-5.5",
|
|
143
|
+
tokenCostInPerMillion: 5,
|
|
144
|
+
tokenCostOutPerMillion: 30,
|
|
138
145
|
},
|
|
139
|
-
"openai:
|
|
146
|
+
"openai:gpt-5.5-pro": {
|
|
140
147
|
provider: "openai",
|
|
141
|
-
model: "
|
|
142
|
-
tokenCostInPerMillion:
|
|
143
|
-
tokenCostOutPerMillion:
|
|
148
|
+
model: "gpt-5.5-pro",
|
|
149
|
+
tokenCostInPerMillion: 30,
|
|
150
|
+
tokenCostOutPerMillion: 180,
|
|
144
151
|
},
|
|
145
|
-
"openai:o3
|
|
152
|
+
"openai:o3": {
|
|
146
153
|
provider: "openai",
|
|
147
|
-
model: "o3
|
|
148
|
-
tokenCostInPerMillion:
|
|
149
|
-
tokenCostOutPerMillion:
|
|
154
|
+
model: "o3",
|
|
155
|
+
tokenCostInPerMillion: 2,
|
|
156
|
+
tokenCostOutPerMillion: 8,
|
|
150
157
|
},
|
|
151
158
|
"openai:o4-mini": {
|
|
152
159
|
provider: "openai",
|
|
@@ -185,13 +192,13 @@ const MODEL_CONFIG_RAW: Record<ModelAliasKey, ModelConfigEntry> = {
|
|
|
185
192
|
tokenCostInPerMillion: 3,
|
|
186
193
|
tokenCostOutPerMillion: 15,
|
|
187
194
|
},
|
|
188
|
-
"anthropic:
|
|
195
|
+
"anthropic:opus-4-7": {
|
|
189
196
|
provider: "anthropic",
|
|
190
|
-
model: "claude-
|
|
191
|
-
tokenCostInPerMillion:
|
|
192
|
-
tokenCostOutPerMillion:
|
|
197
|
+
model: "claude-opus-4-7",
|
|
198
|
+
tokenCostInPerMillion: 5,
|
|
199
|
+
tokenCostOutPerMillion: 25,
|
|
193
200
|
},
|
|
194
|
-
// Gemini
|
|
201
|
+
// Gemini — base (≤200k context) pricing for tiered models
|
|
195
202
|
"gemini:flash-2.5": {
|
|
196
203
|
provider: "gemini",
|
|
197
204
|
model: "gemini-2.5-flash",
|
|
@@ -210,31 +217,49 @@ const MODEL_CONFIG_RAW: Record<ModelAliasKey, ModelConfigEntry> = {
|
|
|
210
217
|
tokenCostInPerMillion: 1.25,
|
|
211
218
|
tokenCostOutPerMillion: 10,
|
|
212
219
|
},
|
|
220
|
+
"gemini:pro-3.1-preview": {
|
|
221
|
+
provider: "gemini",
|
|
222
|
+
model: "gemini-3.1-pro-preview",
|
|
223
|
+
tokenCostInPerMillion: 2,
|
|
224
|
+
tokenCostOutPerMillion: 12,
|
|
225
|
+
},
|
|
226
|
+
"gemini:flash-3-preview": {
|
|
227
|
+
provider: "gemini",
|
|
228
|
+
model: "gemini-3-flash-preview",
|
|
229
|
+
tokenCostInPerMillion: 0.5,
|
|
230
|
+
tokenCostOutPerMillion: 3,
|
|
231
|
+
},
|
|
232
|
+
"gemini:flash-3.1-lite-preview": {
|
|
233
|
+
provider: "gemini",
|
|
234
|
+
model: "gemini-3.1-flash-lite-preview",
|
|
235
|
+
tokenCostInPerMillion: 0.25,
|
|
236
|
+
tokenCostOutPerMillion: 1.5,
|
|
237
|
+
},
|
|
213
238
|
// DeepSeek — cache miss prices
|
|
214
|
-
"deepseek:
|
|
239
|
+
"deepseek:v4-flash": {
|
|
215
240
|
provider: "deepseek",
|
|
216
|
-
model: "deepseek-
|
|
217
|
-
tokenCostInPerMillion: 0.
|
|
218
|
-
tokenCostOutPerMillion: 0.
|
|
241
|
+
model: "deepseek-v4-flash",
|
|
242
|
+
tokenCostInPerMillion: 0.14,
|
|
243
|
+
tokenCostOutPerMillion: 0.28,
|
|
219
244
|
},
|
|
220
|
-
"deepseek:
|
|
245
|
+
"deepseek:v4-pro": {
|
|
221
246
|
provider: "deepseek",
|
|
222
|
-
model: "deepseek-
|
|
223
|
-
tokenCostInPerMillion:
|
|
224
|
-
tokenCostOutPerMillion:
|
|
247
|
+
model: "deepseek-v4-pro",
|
|
248
|
+
tokenCostInPerMillion: 1.74,
|
|
249
|
+
tokenCostOutPerMillion: 3.48,
|
|
225
250
|
},
|
|
226
|
-
// Moonshot / Kimi
|
|
251
|
+
// Moonshot / Kimi — cache miss prices
|
|
227
252
|
"moonshot:kimi-k2.5": {
|
|
228
253
|
provider: "moonshot",
|
|
229
254
|
model: "kimi-k2.5",
|
|
230
|
-
tokenCostInPerMillion: 0.
|
|
255
|
+
tokenCostInPerMillion: 0.6,
|
|
231
256
|
tokenCostOutPerMillion: 2.5,
|
|
232
257
|
},
|
|
233
|
-
"moonshot:kimi-
|
|
258
|
+
"moonshot:kimi-k2.6": {
|
|
234
259
|
provider: "moonshot",
|
|
235
|
-
model: "kimi-
|
|
236
|
-
tokenCostInPerMillion: 0.
|
|
237
|
-
tokenCostOutPerMillion:
|
|
260
|
+
model: "kimi-k2.6",
|
|
261
|
+
tokenCostInPerMillion: 0.95,
|
|
262
|
+
tokenCostOutPerMillion: 4,
|
|
238
263
|
},
|
|
239
264
|
// Claude Code — subscription-based, zero token cost
|
|
240
265
|
"claude-code:sonnet": {
|
|
@@ -256,17 +281,23 @@ const MODEL_CONFIG_RAW: Record<ModelAliasKey, ModelConfigEntry> = {
|
|
|
256
281
|
tokenCostOutPerMillion: 0,
|
|
257
282
|
},
|
|
258
283
|
// Z.ai
|
|
284
|
+
"zai:glm-5-1": {
|
|
285
|
+
provider: "zai",
|
|
286
|
+
model: "glm-5.1",
|
|
287
|
+
tokenCostInPerMillion: 1.4,
|
|
288
|
+
tokenCostOutPerMillion: 4.4,
|
|
289
|
+
},
|
|
259
290
|
"zai:glm-5": {
|
|
260
291
|
provider: "zai",
|
|
261
292
|
model: "glm-5",
|
|
262
293
|
tokenCostInPerMillion: 1,
|
|
263
294
|
tokenCostOutPerMillion: 3.2,
|
|
264
295
|
},
|
|
265
|
-
"zai:glm-5-
|
|
296
|
+
"zai:glm-5-turbo": {
|
|
266
297
|
provider: "zai",
|
|
267
|
-
model: "glm-5-
|
|
298
|
+
model: "glm-5-turbo",
|
|
268
299
|
tokenCostInPerMillion: 1.2,
|
|
269
|
-
tokenCostOutPerMillion:
|
|
300
|
+
tokenCostOutPerMillion: 4,
|
|
270
301
|
},
|
|
271
302
|
"zai:glm-4-7": {
|
|
272
303
|
provider: "zai",
|
|
@@ -292,6 +323,12 @@ const MODEL_CONFIG_RAW: Record<ModelAliasKey, ModelConfigEntry> = {
|
|
|
292
323
|
tokenCostInPerMillion: 0.6,
|
|
293
324
|
tokenCostOutPerMillion: 2.2,
|
|
294
325
|
},
|
|
326
|
+
"zai:glm-4-5-x": {
|
|
327
|
+
provider: "zai",
|
|
328
|
+
model: "glm-4.5-x",
|
|
329
|
+
tokenCostInPerMillion: 2.2,
|
|
330
|
+
tokenCostOutPerMillion: 8.9,
|
|
331
|
+
},
|
|
295
332
|
"zai:glm-4-5-air": {
|
|
296
333
|
provider: "zai",
|
|
297
334
|
model: "glm-4.5-air",
|
|
@@ -304,30 +341,42 @@ const MODEL_CONFIG_RAW: Record<ModelAliasKey, ModelConfigEntry> = {
|
|
|
304
341
|
tokenCostInPerMillion: 1.1,
|
|
305
342
|
tokenCostOutPerMillion: 4.5,
|
|
306
343
|
},
|
|
307
|
-
// Alibaba (Qwen via DashScope)
|
|
344
|
+
// Alibaba (Qwen via DashScope, international/Singapore deployment, base tier)
|
|
308
345
|
"alibaba:qwen3-max": {
|
|
309
346
|
provider: "alibaba",
|
|
310
347
|
model: "qwen3-max",
|
|
311
|
-
tokenCostInPerMillion:
|
|
312
|
-
tokenCostOutPerMillion:
|
|
348
|
+
tokenCostInPerMillion: 1.2,
|
|
349
|
+
tokenCostOutPerMillion: 6,
|
|
350
|
+
},
|
|
351
|
+
"alibaba:qwen3.6-plus": {
|
|
352
|
+
provider: "alibaba",
|
|
353
|
+
model: "qwen3.6-plus",
|
|
354
|
+
tokenCostInPerMillion: 0.276,
|
|
355
|
+
tokenCostOutPerMillion: 1.651,
|
|
313
356
|
},
|
|
314
357
|
"alibaba:qwen3.5-plus": {
|
|
315
358
|
provider: "alibaba",
|
|
316
359
|
model: "qwen3.5-plus",
|
|
317
|
-
tokenCostInPerMillion: 0.
|
|
318
|
-
tokenCostOutPerMillion:
|
|
360
|
+
tokenCostInPerMillion: 0.4,
|
|
361
|
+
tokenCostOutPerMillion: 2.4,
|
|
362
|
+
},
|
|
363
|
+
"alibaba:qwen3.5-flash": {
|
|
364
|
+
provider: "alibaba",
|
|
365
|
+
model: "qwen3.5-flash",
|
|
366
|
+
tokenCostInPerMillion: 0.1,
|
|
367
|
+
tokenCostOutPerMillion: 0.4,
|
|
319
368
|
},
|
|
320
369
|
"alibaba:qwen-plus": {
|
|
321
370
|
provider: "alibaba",
|
|
322
371
|
model: "qwen-plus",
|
|
323
|
-
tokenCostInPerMillion: 0.
|
|
324
|
-
tokenCostOutPerMillion:
|
|
372
|
+
tokenCostInPerMillion: 0.4,
|
|
373
|
+
tokenCostOutPerMillion: 1.2,
|
|
325
374
|
},
|
|
326
375
|
"alibaba:qwen-flash": {
|
|
327
376
|
provider: "alibaba",
|
|
328
377
|
model: "qwen-flash",
|
|
329
|
-
tokenCostInPerMillion: 0.
|
|
330
|
-
tokenCostOutPerMillion: 0.
|
|
378
|
+
tokenCostInPerMillion: 0.05,
|
|
379
|
+
tokenCostOutPerMillion: 0.4,
|
|
331
380
|
},
|
|
332
381
|
"alibaba:qwq-plus": {
|
|
333
382
|
provider: "alibaba",
|
|
@@ -338,14 +387,14 @@ const MODEL_CONFIG_RAW: Record<ModelAliasKey, ModelConfigEntry> = {
|
|
|
338
387
|
"alibaba:qwen3-coder-plus": {
|
|
339
388
|
provider: "alibaba",
|
|
340
389
|
model: "qwen3-coder-plus",
|
|
341
|
-
tokenCostInPerMillion:
|
|
342
|
-
tokenCostOutPerMillion:
|
|
390
|
+
tokenCostInPerMillion: 1,
|
|
391
|
+
tokenCostOutPerMillion: 5,
|
|
343
392
|
},
|
|
344
393
|
"alibaba:qwen3-coder-flash": {
|
|
345
394
|
provider: "alibaba",
|
|
346
395
|
model: "qwen3-coder-flash",
|
|
347
|
-
tokenCostInPerMillion: 0.
|
|
348
|
-
tokenCostOutPerMillion:
|
|
396
|
+
tokenCostInPerMillion: 0.3,
|
|
397
|
+
tokenCostOutPerMillion: 1.5,
|
|
349
398
|
},
|
|
350
399
|
};
|
|
351
400
|
|
|
@@ -397,13 +446,13 @@ export function getModelConfig(alias: string): ModelConfigEntry | null {
|
|
|
397
446
|
|
|
398
447
|
export const DEFAULT_MODEL_BY_PROVIDER: Readonly<Record<ProviderName, ModelAliasKey>> =
|
|
399
448
|
Object.freeze({
|
|
400
|
-
openai: "openai:gpt-5.
|
|
449
|
+
openai: "openai:gpt-5.4",
|
|
401
450
|
anthropic: "anthropic:sonnet-4-6",
|
|
402
451
|
gemini: "gemini:flash-2.5",
|
|
403
|
-
deepseek: "deepseek:
|
|
404
|
-
moonshot: "moonshot:kimi-k2.
|
|
452
|
+
deepseek: "deepseek:v4-flash",
|
|
453
|
+
moonshot: "moonshot:kimi-k2.6",
|
|
405
454
|
"claude-code": "claude-code:sonnet",
|
|
406
|
-
zai: "zai:glm-5",
|
|
455
|
+
zai: "zai:glm-5-1",
|
|
407
456
|
alibaba: "alibaba:qwen3-max",
|
|
408
457
|
} as const);
|
|
409
458
|
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { describe, test, expect } from "bun:test";
|
|
2
|
+
import { decideTransition } from "../lifecycle-policy";
|
|
3
|
+
|
|
4
|
+
describe("decideTransition", () => {
|
|
5
|
+
test("start with pending task and ready dependencies returns ok", () => {
|
|
6
|
+
const result = decideTransition({
|
|
7
|
+
op: "start",
|
|
8
|
+
taskState: "pending",
|
|
9
|
+
dependenciesReady: true,
|
|
10
|
+
});
|
|
11
|
+
expect(result).toEqual({ ok: true });
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
test("start with pending task and unready dependencies is blocked by dependencies", () => {
|
|
15
|
+
const result = decideTransition({
|
|
16
|
+
op: "start",
|
|
17
|
+
taskState: "pending",
|
|
18
|
+
dependenciesReady: false,
|
|
19
|
+
});
|
|
20
|
+
expect(result).toEqual({
|
|
21
|
+
ok: false,
|
|
22
|
+
code: "unsupported_lifecycle",
|
|
23
|
+
reason: "dependencies",
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test("restart from done state returns ok regardless of dependencies", () => {
|
|
28
|
+
const result = decideTransition({
|
|
29
|
+
op: "restart",
|
|
30
|
+
taskState: "done",
|
|
31
|
+
dependenciesReady: false,
|
|
32
|
+
});
|
|
33
|
+
expect(result).toEqual({ ok: true });
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("restart from running state is blocked by policy", () => {
|
|
37
|
+
const result = decideTransition({
|
|
38
|
+
op: "restart",
|
|
39
|
+
taskState: "running",
|
|
40
|
+
dependenciesReady: true,
|
|
41
|
+
});
|
|
42
|
+
expect(result).toEqual({
|
|
43
|
+
ok: false,
|
|
44
|
+
code: "unsupported_lifecycle",
|
|
45
|
+
reason: "policy",
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("throws for invalid op", () => {
|
|
50
|
+
expect(() =>
|
|
51
|
+
decideTransition({
|
|
52
|
+
op: "stop" as unknown as "start",
|
|
53
|
+
taskState: "pending",
|
|
54
|
+
dependenciesReady: true,
|
|
55
|
+
})
|
|
56
|
+
).toThrow(/Invalid op/);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
test("throws for non-string taskState", () => {
|
|
60
|
+
expect(() =>
|
|
61
|
+
decideTransition({
|
|
62
|
+
op: "start",
|
|
63
|
+
taskState: 42 as unknown as string,
|
|
64
|
+
dependenciesReady: true,
|
|
65
|
+
})
|
|
66
|
+
).toThrow(/Invalid taskState/);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("throws for non-boolean dependenciesReady", () => {
|
|
70
|
+
expect(() =>
|
|
71
|
+
decideTransition({
|
|
72
|
+
op: "start",
|
|
73
|
+
taskState: "pending",
|
|
74
|
+
dependenciesReady: "yes" as unknown as boolean,
|
|
75
|
+
})
|
|
76
|
+
).toThrow(/Invalid dependenciesReady/);
|
|
77
|
+
});
|
|
78
|
+
});
|