podwatch 1.1.0 → 1.1.1
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/dist/hooks/budget.d.ts +6 -11
- package/dist/hooks/budget.d.ts.map +1 -1
- package/dist/hooks/budget.js +6 -103
- package/dist/hooks/budget.js.map +1 -1
- package/package.json +1 -1
package/dist/hooks/budget.d.ts
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Budget hard stop hooks —
|
|
2
|
+
* Budget hard stop hooks — before_prompt_build + before_tool_call.
|
|
3
3
|
*
|
|
4
4
|
* When the server signals a hard stop (budget exceeded + hard stop enabled),
|
|
5
5
|
* these hooks:
|
|
6
|
-
* 1.
|
|
7
|
-
* 2.
|
|
6
|
+
* 1. Prepend context telling the LLM to inform the user about the budget limit
|
|
7
|
+
* 2. Block all tool calls (via before_tool_call in security.ts)
|
|
8
|
+
*
|
|
9
|
+
* No model downgrade — we can't know what providers the user has configured,
|
|
10
|
+
* so forcing a "cheaper" model would break setups with a single provider.
|
|
8
11
|
*/
|
|
9
12
|
import type { PodwatchConfig } from "../index.js";
|
|
10
13
|
import type { PluginApi } from "../types.js";
|
|
11
|
-
/**
|
|
12
|
-
* Find the cheapest available model from the gateway config.
|
|
13
|
-
* Returns { model, provider } or null if only one model is configured.
|
|
14
|
-
*/
|
|
15
|
-
export declare function findCheapestModel(config: Record<string, unknown>): {
|
|
16
|
-
model: string;
|
|
17
|
-
provider: string;
|
|
18
|
-
} | null;
|
|
19
14
|
export declare function registerBudgetHooks(api: PluginApi, config: PodwatchConfig): void;
|
|
20
15
|
//# sourceMappingURL=budget.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/hooks/budget.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"budget.d.ts","sourceRoot":"","sources":["../../src/hooks/budget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAO7C,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,SAAS,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAuBhF"}
|
package/dist/hooks/budget.js
CHANGED
|
@@ -1,119 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* Budget hard stop hooks —
|
|
3
|
+
* Budget hard stop hooks — before_prompt_build + before_tool_call.
|
|
4
4
|
*
|
|
5
5
|
* When the server signals a hard stop (budget exceeded + hard stop enabled),
|
|
6
6
|
* these hooks:
|
|
7
|
-
* 1.
|
|
8
|
-
* 2.
|
|
7
|
+
* 1. Prepend context telling the LLM to inform the user about the budget limit
|
|
8
|
+
* 2. Block all tool calls (via before_tool_call in security.ts)
|
|
9
|
+
*
|
|
10
|
+
* No model downgrade — we can't know what providers the user has configured,
|
|
11
|
+
* so forcing a "cheaper" model would break setups with a single provider.
|
|
9
12
|
*/
|
|
10
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
-
exports.findCheapestModel = findCheapestModel;
|
|
12
14
|
exports.registerBudgetHooks = registerBudgetHooks;
|
|
13
15
|
const transmitter_js_1 = require("../transmitter.js");
|
|
14
16
|
// ---------------------------------------------------------------------------
|
|
15
|
-
// Model cost heuristic — cheaper models first
|
|
16
|
-
// ---------------------------------------------------------------------------
|
|
17
|
-
/** Known cheap model patterns (ordered cheapest first). */
|
|
18
|
-
const CHEAP_MODEL_PATTERNS = [
|
|
19
|
-
"haiku",
|
|
20
|
-
"flash",
|
|
21
|
-
"mini",
|
|
22
|
-
"nano",
|
|
23
|
-
"lite",
|
|
24
|
-
"sonnet",
|
|
25
|
-
];
|
|
26
|
-
/**
|
|
27
|
-
* Score a model name by cost (lower = cheaper).
|
|
28
|
-
* Known cheap patterns get low scores, unknown models get a high default.
|
|
29
|
-
*/
|
|
30
|
-
function modelCostScore(modelName) {
|
|
31
|
-
const lower = modelName.toLowerCase();
|
|
32
|
-
for (let i = 0; i < CHEAP_MODEL_PATTERNS.length; i++) {
|
|
33
|
-
if (lower.includes(CHEAP_MODEL_PATTERNS[i]))
|
|
34
|
-
return i;
|
|
35
|
-
}
|
|
36
|
-
return 100; // unknown = expensive
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Find the cheapest available model from the gateway config.
|
|
40
|
-
* Returns { model, provider } or null if only one model is configured.
|
|
41
|
-
*/
|
|
42
|
-
function findCheapestModel(config) {
|
|
43
|
-
const candidates = [];
|
|
44
|
-
// Check models.providers for available models
|
|
45
|
-
const providers = config?.models?.providers;
|
|
46
|
-
if (providers && typeof providers === "object") {
|
|
47
|
-
for (const [providerName, providerCfg] of Object.entries(providers)) {
|
|
48
|
-
const cfg = providerCfg;
|
|
49
|
-
const models = cfg.models;
|
|
50
|
-
if (Array.isArray(models)) {
|
|
51
|
-
for (const m of models) {
|
|
52
|
-
if (typeof m === "string") {
|
|
53
|
-
candidates.push({
|
|
54
|
-
model: `${providerName}/${m}`,
|
|
55
|
-
provider: providerName,
|
|
56
|
-
score: modelCostScore(m),
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Also check agents.defaults.models for configured model aliases
|
|
64
|
-
const agentModels = config?.agents?.defaults?.models;
|
|
65
|
-
if (agentModels && typeof agentModels === "object") {
|
|
66
|
-
for (const modelId of Object.keys(agentModels)) {
|
|
67
|
-
if (typeof modelId === "string") {
|
|
68
|
-
const parts = modelId.split("/");
|
|
69
|
-
const modelName = parts[parts.length - 1] ?? modelId;
|
|
70
|
-
const provider = parts.length > 1 ? parts[0] : "";
|
|
71
|
-
candidates.push({
|
|
72
|
-
model: modelId,
|
|
73
|
-
provider,
|
|
74
|
-
score: modelCostScore(modelName),
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
// Deduplicate by model name
|
|
80
|
-
const seen = new Set();
|
|
81
|
-
const unique = candidates.filter((c) => {
|
|
82
|
-
if (seen.has(c.model))
|
|
83
|
-
return false;
|
|
84
|
-
seen.add(c.model);
|
|
85
|
-
return true;
|
|
86
|
-
});
|
|
87
|
-
if (unique.length <= 1)
|
|
88
|
-
return null;
|
|
89
|
-
// Sort by score (cheapest first) and pick the cheapest
|
|
90
|
-
unique.sort((a, b) => a.score - b.score);
|
|
91
|
-
// Get the current primary model to avoid returning the same one
|
|
92
|
-
const primaryModel = config?.agents?.defaults?.model?.primary;
|
|
93
|
-
const cheapest = unique.find((c) => c.model !== primaryModel) ?? unique[0];
|
|
94
|
-
return { model: cheapest.model, provider: cheapest.provider };
|
|
95
|
-
}
|
|
96
|
-
// ---------------------------------------------------------------------------
|
|
97
17
|
// Hook registration
|
|
98
18
|
// ---------------------------------------------------------------------------
|
|
99
19
|
function registerBudgetHooks(api, config) {
|
|
100
|
-
// -----------------------------------------------------------------------
|
|
101
|
-
// before_model_resolve — downgrade to cheaper model on hard stop
|
|
102
|
-
// -----------------------------------------------------------------------
|
|
103
|
-
api.registerHook("before_model_resolve", async () => {
|
|
104
|
-
if (!config.enableBudgetEnforcement)
|
|
105
|
-
return;
|
|
106
|
-
const budget = transmitter_js_1.transmitter.getCachedBudget();
|
|
107
|
-
if (!budget?.hardStopActive)
|
|
108
|
-
return;
|
|
109
|
-
const cheaper = findCheapestModel(api.config);
|
|
110
|
-
if (!cheaper)
|
|
111
|
-
return; // only one model configured, skip
|
|
112
|
-
return {
|
|
113
|
-
modelOverride: cheaper.model,
|
|
114
|
-
providerOverride: cheaper.provider,
|
|
115
|
-
};
|
|
116
|
-
}, { name: "podwatch-budget-model-resolve" });
|
|
117
20
|
// -----------------------------------------------------------------------
|
|
118
21
|
// before_prompt_build — inject budget warning into prompt
|
|
119
22
|
// -----------------------------------------------------------------------
|
package/dist/hooks/budget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/hooks/budget.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../../src/hooks/budget.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAUH,kDAuBC;AA7BD,sDAAgD;AAEhD,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E;AAE9E,SAAgB,mBAAmB,CAAC,GAAc,EAAE,MAAsB;IACxE,0EAA0E;IAC1E,0DAA0D;IAC1D,0EAA0E;IAC1E,GAAG,CAAC,YAAY,CACd,qBAAqB,EACrB,KAAK,IAAiD,EAAE;QACtD,IAAI,CAAC,MAAM,CAAC,uBAAuB;YAAE,OAAO;QAE5C,MAAM,MAAM,GAAG,4BAAW,CAAC,eAAe,EAAE,CAAC;QAC7C,IAAI,CAAC,MAAM,EAAE,cAAc;YAAE,OAAO;QAEpC,OAAO;YACL,cAAc,EACZ,iEAAiE;gBACjE,4EAA4E;gBAC5E,+FAA+F;SAClG,CAAC;IACJ,CAAC,EACD,EAAE,IAAI,EAAE,8BAA8B,EAAE,CACzC,CAAC;IAEF,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,8CAA8C,CAAC,CAAC;AAClE,CAAC"}
|