@agentguard-run/spend 0.3.0 → 0.4.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/CHANGELOG.md +11 -0
- package/README.es-419.md +28 -0
- package/README.md +28 -0
- package/README.pt-BR.md +28 -0
- package/dist/advisor/anomaly.d.ts +26 -0
- package/dist/advisor/anomaly.d.ts.map +1 -0
- package/dist/advisor/anomaly.js +119 -0
- package/dist/advisor/anomaly.js.map +1 -0
- package/dist/advisor/conversation.d.ts +75 -0
- package/dist/advisor/conversation.d.ts.map +1 -0
- package/dist/advisor/conversation.js +264 -0
- package/dist/advisor/conversation.js.map +1 -0
- package/dist/advisor/forecast.d.ts +19 -0
- package/dist/advisor/forecast.d.ts.map +1 -0
- package/dist/advisor/forecast.js +57 -0
- package/dist/advisor/forecast.js.map +1 -0
- package/dist/advisor/llm-client.d.ts +41 -0
- package/dist/advisor/llm-client.d.ts.map +1 -0
- package/dist/advisor/llm-client.js +248 -0
- package/dist/advisor/llm-client.js.map +1 -0
- package/dist/advisor/output.d.ts +41 -0
- package/dist/advisor/output.d.ts.map +1 -0
- package/dist/advisor/output.js +202 -0
- package/dist/advisor/output.js.map +1 -0
- package/dist/advisor/posture.d.ts +26 -0
- package/dist/advisor/posture.d.ts.map +1 -0
- package/dist/advisor/posture.js +99 -0
- package/dist/advisor/posture.js.map +1 -0
- package/dist/advisor/system-prompt.d.ts +20 -0
- package/dist/advisor/system-prompt.d.ts.map +1 -0
- package/dist/advisor/system-prompt.js +190 -0
- package/dist/advisor/system-prompt.js.map +1 -0
- package/dist/cli/advisor.d.ts +5 -0
- package/dist/cli/advisor.d.ts.map +1 -0
- package/dist/cli/advisor.js +270 -0
- package/dist/cli/advisor.js.map +1 -0
- package/dist/cli/main.d.ts.map +1 -1
- package/dist/cli/main.js +6 -0
- package/dist/cli/main.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -2
- package/dist/index.js.map +1 -1
- package/dist/telemetry.js +1 -1
- package/package.json +9 -2
- package/src/advisor/anomaly.ts +98 -0
- package/src/advisor/conversation.ts +289 -0
- package/src/advisor/forecast.ts +64 -0
- package/src/advisor/llm-client.ts +247 -0
- package/src/advisor/output.ts +201 -0
- package/src/advisor/posture.ts +111 -0
- package/src/advisor/system-prompt.ts +195 -0
- package/src/cli/advisor.ts +262 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentGuard(TM) Spend: local Advisor forecast skeleton.
|
|
3
|
+
*
|
|
4
|
+
* Reads local decision logs only. No network calls are made.
|
|
5
|
+
*
|
|
6
|
+
* Patent notice: Protected by U.S. patent-pending technology
|
|
7
|
+
* (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626;
|
|
8
|
+
* 64/071,781; 64/071,789).
|
|
9
|
+
*/
|
|
10
|
+
import type { AdvisorSpendPoint } from './anomaly';
|
|
11
|
+
export interface AdvisorForecast {
|
|
12
|
+
daysObserved: number;
|
|
13
|
+
monthEndCents: number;
|
|
14
|
+
capCents: number | null;
|
|
15
|
+
overCap: boolean;
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function forecastMonthEnd(points: AdvisorSpendPoint[], capCents?: number | null, now?: Date): AdvisorForecast;
|
|
19
|
+
//# sourceMappingURL=forecast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forecast.d.ts","sourceRoot":"","sources":["../../src/advisor/forecast.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,iBAAiB,EAAE,EAAE,QAAQ,GAAE,MAAM,GAAG,IAAW,EAAE,GAAG,OAAa,GAAG,eAAe,CAoB/H"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AgentGuard(TM) Spend: local Advisor forecast skeleton.
|
|
4
|
+
*
|
|
5
|
+
* Reads local decision logs only. No network calls are made.
|
|
6
|
+
*
|
|
7
|
+
* Patent notice: Protected by U.S. patent-pending technology
|
|
8
|
+
* (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626;
|
|
9
|
+
* 64/071,781; 64/071,789).
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.forecastMonthEnd = forecastMonthEnd;
|
|
13
|
+
function forecastMonthEnd(points, capCents = null, now = new Date()) {
|
|
14
|
+
const daily = lastThirtyDaily(points, now);
|
|
15
|
+
if (daily.length === 0) {
|
|
16
|
+
return { daysObserved: 0, monthEndCents: 0, capCents, overCap: false, message: 'No local spend history found.' };
|
|
17
|
+
}
|
|
18
|
+
const slope = linearSlope(daily.map((row, index) => ({ x: index + 1, y: row.cents })));
|
|
19
|
+
const monthDays = new Date(now.getFullYear(), now.getMonth() + 1, 0).getDate();
|
|
20
|
+
const elapsed = now.getDate();
|
|
21
|
+
const observedTotal = daily.reduce((sum, row) => sum + row.cents, 0);
|
|
22
|
+
const avg = observedTotal / Math.max(1, daily.length);
|
|
23
|
+
const projectedRemaining = Math.max(0, monthDays - elapsed) * Math.max(0, avg + slope);
|
|
24
|
+
const monthEndCents = Math.round(observedTotal + projectedRemaining);
|
|
25
|
+
const overCap = capCents !== null && monthEndCents > capCents;
|
|
26
|
+
return {
|
|
27
|
+
daysObserved: daily.length,
|
|
28
|
+
monthEndCents,
|
|
29
|
+
capCents,
|
|
30
|
+
overCap,
|
|
31
|
+
message: overCap ? 'Projected spend is above cap. Consider a lower fallback model or a tighter per_day cap.' : 'Projected spend is within the current cap.',
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function lastThirtyDaily(points, now) {
|
|
35
|
+
const cutoff = now.getTime() - 30 * 24 * 60 * 60 * 1000;
|
|
36
|
+
const buckets = new Map();
|
|
37
|
+
for (const point of points) {
|
|
38
|
+
const t = Date.parse(point.ts);
|
|
39
|
+
if (!Number.isFinite(t) || t < cutoff)
|
|
40
|
+
continue;
|
|
41
|
+
const day = new Date(t).toISOString().slice(0, 10);
|
|
42
|
+
buckets.set(day, (buckets.get(day) ?? 0) + point.cents);
|
|
43
|
+
}
|
|
44
|
+
return [...buckets.entries()].map(([day, cents]) => ({ day, cents })).sort((a, b) => a.day.localeCompare(b.day));
|
|
45
|
+
}
|
|
46
|
+
function linearSlope(points) {
|
|
47
|
+
if (points.length < 2)
|
|
48
|
+
return 0;
|
|
49
|
+
const n = points.length;
|
|
50
|
+
const sx = points.reduce((sum, point) => sum + point.x, 0);
|
|
51
|
+
const sy = points.reduce((sum, point) => sum + point.y, 0);
|
|
52
|
+
const sxx = points.reduce((sum, point) => sum + point.x * point.x, 0);
|
|
53
|
+
const sxy = points.reduce((sum, point) => sum + point.x * point.y, 0);
|
|
54
|
+
const denom = n * sxx - sx * sx;
|
|
55
|
+
return denom === 0 ? 0 : (n * sxy - sx * sy) / denom;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=forecast.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"forecast.js","sourceRoot":"","sources":["../../src/advisor/forecast.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentGuard(TM) Spend: local Advisor LLM client.
|
|
3
|
+
*
|
|
4
|
+
* All provider calls go from the customer terminal to the configured provider.
|
|
5
|
+
* No AgentGuard service is contacted for prompts or completions.
|
|
6
|
+
*
|
|
7
|
+
* Patent notice: Protected by U.S. patent-pending technology
|
|
8
|
+
* (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626;
|
|
9
|
+
* 64/071,781; 64/071,789).
|
|
10
|
+
*/
|
|
11
|
+
export type AdvisorProvider = 'openrouter' | 'openai' | 'anthropic' | 'compatible' | 'mock';
|
|
12
|
+
export interface AdvisorChatMessage {
|
|
13
|
+
role: 'system' | 'user' | 'assistant';
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
export interface AdvisorClientOptions {
|
|
17
|
+
provider?: AdvisorProvider;
|
|
18
|
+
apiKey?: string;
|
|
19
|
+
baseUrl?: string;
|
|
20
|
+
model?: string;
|
|
21
|
+
timeoutMs?: number;
|
|
22
|
+
fetchImpl?: FetchLike;
|
|
23
|
+
}
|
|
24
|
+
export interface AdvisorClient {
|
|
25
|
+
provider: AdvisorProvider;
|
|
26
|
+
model: string;
|
|
27
|
+
baseUrl: string;
|
|
28
|
+
streamChat(messages: AdvisorChatMessage[], signal?: AbortSignalLike): AsyncIterable<string>;
|
|
29
|
+
}
|
|
30
|
+
type FetchLike = (url: string, init: Record<string, unknown>) => Promise<any>;
|
|
31
|
+
type AbortSignalLike = {
|
|
32
|
+
aborted?: boolean;
|
|
33
|
+
addEventListener?: (type: 'abort', listener: () => void, options?: {
|
|
34
|
+
once?: boolean;
|
|
35
|
+
}) => void;
|
|
36
|
+
};
|
|
37
|
+
export declare function resolveAdvisorApiKey(provider?: AdvisorProvider, explicit?: string): string | null;
|
|
38
|
+
export declare function createAdvisorClient(options?: AdvisorClientOptions): AdvisorClient;
|
|
39
|
+
export declare function parseSseResponse(response: any, pickText: (json: any) => string): AsyncIterable<string>;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=llm-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-client.d.ts","sourceRoot":"","sources":["../../src/advisor/llm-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,QAAQ,GAAG,WAAW,GAAG,YAAY,GAAG,MAAM,CAAC;AAE5F,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,QAAQ,GAAG,MAAM,GAAG,WAAW,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,eAAe,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,eAAe,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,QAAQ,EAAE,kBAAkB,EAAE,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;CAC7F;AAED,KAAK,SAAS,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,GAAG,CAAC,CAAC;AAE9E,KAAK,eAAe,GAAG;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,EAAE,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,IAAI,CAAC;CAChG,CAAC;AAYF,wBAAgB,oBAAoB,CAAC,QAAQ,GAAE,eAA8B,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAY/G;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,oBAAyB,GAAG,aAAa,CAwBrF;AAiED,wBAAuB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC,CAmB7G"}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AgentGuard(TM) Spend: local Advisor LLM client.
|
|
4
|
+
*
|
|
5
|
+
* All provider calls go from the customer terminal to the configured provider.
|
|
6
|
+
* No AgentGuard service is contacted for prompts or completions.
|
|
7
|
+
*
|
|
8
|
+
* Patent notice: Protected by U.S. patent-pending technology
|
|
9
|
+
* (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626;
|
|
10
|
+
* 64/071,781; 64/071,789).
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.resolveAdvisorApiKey = resolveAdvisorApiKey;
|
|
47
|
+
exports.createAdvisorClient = createAdvisorClient;
|
|
48
|
+
exports.parseSseResponse = parseSseResponse;
|
|
49
|
+
const fs = __importStar(require("fs"));
|
|
50
|
+
const os = __importStar(require("os"));
|
|
51
|
+
const path = __importStar(require("path"));
|
|
52
|
+
const DEFAULT_OPENROUTER_BASE_URL = 'https://openrouter.ai/api/v1';
|
|
53
|
+
const DEFAULT_OPENAI_BASE_URL = 'https://api.openai.com/v1';
|
|
54
|
+
const DEFAULT_ANTHROPIC_BASE_URL = 'https://api.anthropic.com/v1';
|
|
55
|
+
const DEFAULT_MODEL = 'openai/gpt-4o-mini';
|
|
56
|
+
function resolveAdvisorApiKey(provider = 'openrouter', explicit) {
|
|
57
|
+
if (explicit?.trim())
|
|
58
|
+
return explicit.trim();
|
|
59
|
+
if (provider === 'openai' && process.env.OPENAI_API_KEY)
|
|
60
|
+
return process.env.OPENAI_API_KEY;
|
|
61
|
+
if (provider === 'anthropic' && process.env.ANTHROPIC_API_KEY)
|
|
62
|
+
return process.env.ANTHROPIC_API_KEY;
|
|
63
|
+
if ((provider === 'openrouter' || provider === 'compatible') && process.env.OPENROUTER_API_KEY)
|
|
64
|
+
return process.env.OPENROUTER_API_KEY;
|
|
65
|
+
if (process.env.AGENTGUARD_ADVISOR_API_KEY)
|
|
66
|
+
return process.env.AGENTGUARD_ADVISOR_API_KEY;
|
|
67
|
+
try {
|
|
68
|
+
const key = fs.readFileSync(path.join(agentguardHome(), 'openrouter-key'), 'utf8').trim();
|
|
69
|
+
return key.length > 0 ? key : null;
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
function createAdvisorClient(options = {}) {
|
|
76
|
+
const provider = options.provider ?? providerFromBaseUrl(options.baseUrl) ?? 'openrouter';
|
|
77
|
+
const model = options.model ?? (provider === 'anthropic' ? 'claude-sonnet-4-6' : DEFAULT_MODEL);
|
|
78
|
+
const baseUrl = normalizeBaseUrl(options.baseUrl ?? defaultBaseUrl(provider));
|
|
79
|
+
const fetchImpl = options.fetchImpl ?? globalFetch;
|
|
80
|
+
const apiKey = resolveAdvisorApiKey(provider, options.apiKey);
|
|
81
|
+
return {
|
|
82
|
+
provider,
|
|
83
|
+
model,
|
|
84
|
+
baseUrl,
|
|
85
|
+
async *streamChat(messages, signal) {
|
|
86
|
+
if (provider === 'mock') {
|
|
87
|
+
yield 'Mock advisor response.';
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (!apiKey)
|
|
91
|
+
throw new Error('No Advisor API key configured');
|
|
92
|
+
if (provider === 'anthropic') {
|
|
93
|
+
yield* streamAnthropic({ fetchImpl, baseUrl, model, apiKey, messages, signal, timeoutMs: options.timeoutMs });
|
|
94
|
+
}
|
|
95
|
+
else {
|
|
96
|
+
yield* streamOpenAICompatible({ fetchImpl, baseUrl, model, apiKey, messages, signal, timeoutMs: options.timeoutMs });
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
async function* streamOpenAICompatible(args) {
|
|
102
|
+
const controller = createAbortController();
|
|
103
|
+
const timer = setTimeout(() => controller.abort(), args.timeoutMs ?? 120_000);
|
|
104
|
+
const signal = mergeSignal(args.signal, controller.signal);
|
|
105
|
+
try {
|
|
106
|
+
const response = await args.fetchImpl(`${args.baseUrl}/chat/completions`, {
|
|
107
|
+
method: 'POST',
|
|
108
|
+
headers: {
|
|
109
|
+
authorization: `Bearer ${args.apiKey}`,
|
|
110
|
+
'content-type': 'application/json',
|
|
111
|
+
accept: 'text/event-stream',
|
|
112
|
+
},
|
|
113
|
+
body: JSON.stringify({ model: args.model, messages: args.messages, stream: true }),
|
|
114
|
+
signal,
|
|
115
|
+
});
|
|
116
|
+
if (!response.ok)
|
|
117
|
+
throw new Error(`Advisor provider HTTP ${response.status}`);
|
|
118
|
+
yield* parseSseResponse(response, (json) => json?.choices?.[0]?.delta?.content ?? json?.choices?.[0]?.message?.content ?? '');
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
clearTimeout(timer);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
async function* streamAnthropic(args) {
|
|
125
|
+
const controller = createAbortController();
|
|
126
|
+
const timer = setTimeout(() => controller.abort(), args.timeoutMs ?? 120_000);
|
|
127
|
+
const signal = mergeSignal(args.signal, controller.signal);
|
|
128
|
+
try {
|
|
129
|
+
const system = args.messages.find((m) => m.role === 'system')?.content ?? '';
|
|
130
|
+
const messages = args.messages.filter((m) => m.role !== 'system').map((m) => ({ role: m.role === 'assistant' ? 'assistant' : 'user', content: m.content }));
|
|
131
|
+
const response = await args.fetchImpl(`${args.baseUrl}/messages`, {
|
|
132
|
+
method: 'POST',
|
|
133
|
+
headers: {
|
|
134
|
+
'x-api-key': args.apiKey,
|
|
135
|
+
'anthropic-version': '2023-06-01',
|
|
136
|
+
'content-type': 'application/json',
|
|
137
|
+
accept: 'text/event-stream',
|
|
138
|
+
},
|
|
139
|
+
body: JSON.stringify({ model: args.model, system, messages, max_tokens: 1200, stream: true }),
|
|
140
|
+
signal,
|
|
141
|
+
});
|
|
142
|
+
if (!response.ok)
|
|
143
|
+
throw new Error(`Advisor provider HTTP ${response.status}`);
|
|
144
|
+
yield* parseSseResponse(response, (json) => json?.delta?.text ?? json?.content_block?.text ?? '');
|
|
145
|
+
}
|
|
146
|
+
finally {
|
|
147
|
+
clearTimeout(timer);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async function* parseSseResponse(response, pickText) {
|
|
151
|
+
let buffer = '';
|
|
152
|
+
for await (const chunk of responseBodyIterable(response)) {
|
|
153
|
+
buffer += chunk;
|
|
154
|
+
const parts = buffer.split('\n\n');
|
|
155
|
+
buffer = parts.pop() ?? '';
|
|
156
|
+
for (const part of parts) {
|
|
157
|
+
const dataLines = part.split('\n').filter((line) => line.startsWith('data:')).map((line) => line.slice(5).trim());
|
|
158
|
+
for (const data of dataLines) {
|
|
159
|
+
if (!data || data === '[DONE]')
|
|
160
|
+
continue;
|
|
161
|
+
try {
|
|
162
|
+
const token = pickText(JSON.parse(data));
|
|
163
|
+
if (token)
|
|
164
|
+
yield token;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
continue;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
async function* responseBodyIterable(response) {
|
|
174
|
+
const body = response.body;
|
|
175
|
+
if (!body)
|
|
176
|
+
return;
|
|
177
|
+
if (typeof body[Symbol.asyncIterator] === 'function') {
|
|
178
|
+
for await (const chunk of body)
|
|
179
|
+
yield chunkToString(chunk);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (typeof body.getReader === 'function') {
|
|
183
|
+
const reader = body.getReader();
|
|
184
|
+
const decoder = new TextDecoder();
|
|
185
|
+
while (true) {
|
|
186
|
+
const { done, value } = await reader.read();
|
|
187
|
+
if (done)
|
|
188
|
+
break;
|
|
189
|
+
yield decoder.decode(value, { stream: true });
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function chunkToString(chunk) {
|
|
194
|
+
if (typeof chunk === 'string')
|
|
195
|
+
return chunk;
|
|
196
|
+
if (chunk instanceof Uint8Array)
|
|
197
|
+
return Buffer.from(chunk).toString('utf8');
|
|
198
|
+
return String(chunk ?? '');
|
|
199
|
+
}
|
|
200
|
+
function defaultBaseUrl(provider) {
|
|
201
|
+
if (provider === 'openai')
|
|
202
|
+
return DEFAULT_OPENAI_BASE_URL;
|
|
203
|
+
if (provider === 'anthropic')
|
|
204
|
+
return DEFAULT_ANTHROPIC_BASE_URL;
|
|
205
|
+
return DEFAULT_OPENROUTER_BASE_URL;
|
|
206
|
+
}
|
|
207
|
+
function normalizeBaseUrl(value) {
|
|
208
|
+
return value.replace(/\/+$/, '');
|
|
209
|
+
}
|
|
210
|
+
function providerFromBaseUrl(baseUrl) {
|
|
211
|
+
if (!baseUrl)
|
|
212
|
+
return null;
|
|
213
|
+
if (baseUrl.includes('anthropic.com'))
|
|
214
|
+
return 'anthropic';
|
|
215
|
+
if (baseUrl.includes('openai.com'))
|
|
216
|
+
return 'openai';
|
|
217
|
+
if (baseUrl.includes('openrouter.ai'))
|
|
218
|
+
return 'openrouter';
|
|
219
|
+
return 'compatible';
|
|
220
|
+
}
|
|
221
|
+
function agentguardHome() {
|
|
222
|
+
return process.env.AGENTGUARD_HOME || path.join(os.homedir(), '.agentguard');
|
|
223
|
+
}
|
|
224
|
+
function globalFetch(url, init) {
|
|
225
|
+
const fetchImpl = globalThis.fetch;
|
|
226
|
+
if (typeof fetchImpl !== 'function')
|
|
227
|
+
throw new Error('Global fetch is not available. Use Node 20 or newer.');
|
|
228
|
+
return fetchImpl(url, init);
|
|
229
|
+
}
|
|
230
|
+
function createAbortController() {
|
|
231
|
+
const Controller = globalThis.AbortController;
|
|
232
|
+
if (Controller)
|
|
233
|
+
return new Controller();
|
|
234
|
+
const signal = { aborted: false, addEventListener: () => undefined };
|
|
235
|
+
return { signal, abort: () => { signal.aborted = true; } };
|
|
236
|
+
}
|
|
237
|
+
function mergeSignal(a, b) {
|
|
238
|
+
if (!a)
|
|
239
|
+
return b;
|
|
240
|
+
if (a.aborted)
|
|
241
|
+
return a;
|
|
242
|
+
const controller = createAbortController();
|
|
243
|
+
const abort = () => controller.abort();
|
|
244
|
+
a.addEventListener?.('abort', abort, { once: true });
|
|
245
|
+
b.addEventListener?.('abort', abort, { once: true });
|
|
246
|
+
return controller.signal;
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=llm-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm-client.js","sourceRoot":"","sources":["../../src/advisor/llm-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentGuard(TM) Spend: Advisor output writers.
|
|
3
|
+
*
|
|
4
|
+
* Files are written locally under ~/.agentguard by default. Conversation logs
|
|
5
|
+
* stay in ~/.agentguard/advisor-sessions and are never uploaded by this SDK.
|
|
6
|
+
*
|
|
7
|
+
* Patent notice: Protected by U.S. patent-pending technology
|
|
8
|
+
* (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626;
|
|
9
|
+
* 64/071,781; 64/071,789).
|
|
10
|
+
*/
|
|
11
|
+
import type { SpendPolicy } from '../types';
|
|
12
|
+
import { type AdvisorBusinessProfile, type ProjectedSavings } from './conversation';
|
|
13
|
+
export interface AdvisorOutputOptions {
|
|
14
|
+
home?: string;
|
|
15
|
+
now?: Date;
|
|
16
|
+
language?: 'ts' | 'py';
|
|
17
|
+
overwrite?: boolean;
|
|
18
|
+
}
|
|
19
|
+
export interface AdvisorOutputs {
|
|
20
|
+
policy: SpendPolicy;
|
|
21
|
+
policyPath: string;
|
|
22
|
+
quickstartPath: string;
|
|
23
|
+
sessionDir: string;
|
|
24
|
+
savings: ProjectedSavings;
|
|
25
|
+
policyYaml: string;
|
|
26
|
+
quickstartCode: string;
|
|
27
|
+
savingsTable: string;
|
|
28
|
+
}
|
|
29
|
+
export interface AdvisorSessionLogger {
|
|
30
|
+
path: string;
|
|
31
|
+
append: (event: string, payload?: Record<string, unknown>) => void;
|
|
32
|
+
}
|
|
33
|
+
export declare function agentguardHome(): string;
|
|
34
|
+
export declare function advisorSessionDir(home?: string): string;
|
|
35
|
+
export declare function createAdvisorSessionLogger(home?: string, now?: Date): AdvisorSessionLogger;
|
|
36
|
+
export declare function writeAdvisorOutputs(profile: AdvisorBusinessProfile, options?: AdvisorOutputOptions): AdvisorOutputs;
|
|
37
|
+
export declare function renderPolicyYaml(policy: SpendPolicy, profile: AdvisorBusinessProfile, now?: Date): string;
|
|
38
|
+
export declare function renderQuickstartTs(policy: SpendPolicy, profile: AdvisorBusinessProfile): string;
|
|
39
|
+
export declare function renderQuickstartPy(policy: SpendPolicy, profile: AdvisorBusinessProfile): string;
|
|
40
|
+
export declare function renderSavingsTable(savings: ProjectedSavings): string;
|
|
41
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../../src/advisor/output.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAKH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAIL,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACtB,MAAM,gBAAgB,CAAC;AAGxB,MAAM,WAAW,oBAAoB;IACnC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,QAAQ,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,WAAW,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CACpE;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,SAAmB,GAAG,MAAM,CAEjE;AAED,wBAAgB,0BAA0B,CAAC,IAAI,SAAmB,EAAE,GAAG,OAAa,GAAG,oBAAoB,CAa1G;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,sBAAsB,EAAE,OAAO,GAAE,oBAAyB,GAAG,cAAc,CAuBvH;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,EAAE,GAAG,OAAa,GAAG,MAAM,CAyC/G;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAE/F;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAO/F;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,gBAAgB,GAAG,MAAM,CAQpE"}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AgentGuard(TM) Spend: Advisor output writers.
|
|
4
|
+
*
|
|
5
|
+
* Files are written locally under ~/.agentguard by default. Conversation logs
|
|
6
|
+
* stay in ~/.agentguard/advisor-sessions and are never uploaded by this SDK.
|
|
7
|
+
*
|
|
8
|
+
* Patent notice: Protected by U.S. patent-pending technology
|
|
9
|
+
* (App. Nos. 63/983,615; 63/983,621; 63/983,843; 63/984,626;
|
|
10
|
+
* 64/071,781; 64/071,789).
|
|
11
|
+
*/
|
|
12
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
15
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
16
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
17
|
+
}
|
|
18
|
+
Object.defineProperty(o, k2, desc);
|
|
19
|
+
}) : (function(o, m, k, k2) {
|
|
20
|
+
if (k2 === undefined) k2 = k;
|
|
21
|
+
o[k2] = m[k];
|
|
22
|
+
}));
|
|
23
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
24
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
25
|
+
}) : function(o, v) {
|
|
26
|
+
o["default"] = v;
|
|
27
|
+
});
|
|
28
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
29
|
+
var ownKeys = function(o) {
|
|
30
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
31
|
+
var ar = [];
|
|
32
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
33
|
+
return ar;
|
|
34
|
+
};
|
|
35
|
+
return ownKeys(o);
|
|
36
|
+
};
|
|
37
|
+
return function (mod) {
|
|
38
|
+
if (mod && mod.__esModule) return mod;
|
|
39
|
+
var result = {};
|
|
40
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
41
|
+
__setModuleDefault(result, mod);
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
})();
|
|
45
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
46
|
+
exports.agentguardHome = agentguardHome;
|
|
47
|
+
exports.advisorSessionDir = advisorSessionDir;
|
|
48
|
+
exports.createAdvisorSessionLogger = createAdvisorSessionLogger;
|
|
49
|
+
exports.writeAdvisorOutputs = writeAdvisorOutputs;
|
|
50
|
+
exports.renderPolicyYaml = renderPolicyYaml;
|
|
51
|
+
exports.renderQuickstartTs = renderQuickstartTs;
|
|
52
|
+
exports.renderQuickstartPy = renderQuickstartPy;
|
|
53
|
+
exports.renderSavingsTable = renderSavingsTable;
|
|
54
|
+
const fs = __importStar(require("fs"));
|
|
55
|
+
const os = __importStar(require("os"));
|
|
56
|
+
const path = __importStar(require("path"));
|
|
57
|
+
const conversation_1 = require("./conversation");
|
|
58
|
+
const posture_1 = require("./posture");
|
|
59
|
+
function agentguardHome() {
|
|
60
|
+
return process.env.AGENTGUARD_HOME || path.join(os.homedir(), '.agentguard');
|
|
61
|
+
}
|
|
62
|
+
function advisorSessionDir(home = agentguardHome()) {
|
|
63
|
+
return path.join(home, 'advisor-sessions');
|
|
64
|
+
}
|
|
65
|
+
function createAdvisorSessionLogger(home = agentguardHome(), now = new Date()) {
|
|
66
|
+
const dir = advisorSessionDir(home);
|
|
67
|
+
fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
|
|
68
|
+
const stamp = now.toISOString().replace(/[:.]/g, '-');
|
|
69
|
+
const file = path.join(dir, `${stamp}.jsonl`);
|
|
70
|
+
fs.closeSync(fs.openSync(file, 'a', 0o600));
|
|
71
|
+
return {
|
|
72
|
+
path: file,
|
|
73
|
+
append(event, payload = {}) {
|
|
74
|
+
const line = JSON.stringify({ ts: new Date().toISOString(), event, ...payload }) + '\n';
|
|
75
|
+
fs.appendFileSync(file, line, { encoding: 'utf8', mode: 0o600 });
|
|
76
|
+
},
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
function writeAdvisorOutputs(profile, options = {}) {
|
|
80
|
+
const home = options.home ?? agentguardHome();
|
|
81
|
+
const language = options.language ?? profile.language;
|
|
82
|
+
const sessionDir = advisorSessionDir(home);
|
|
83
|
+
fs.mkdirSync(home, { recursive: true, mode: 0o700 });
|
|
84
|
+
fs.mkdirSync(sessionDir, { recursive: true, mode: 0o700 });
|
|
85
|
+
const policy = (0, conversation_1.buildPolicyFromProfile)(profile);
|
|
86
|
+
const policyPath = path.join(home, 'policy.yaml');
|
|
87
|
+
const quickstartPath = path.join(home, language === 'py' ? 'quickstart.py' : 'quickstart.ts');
|
|
88
|
+
const savings = (0, conversation_1.projectedSavings)(profile);
|
|
89
|
+
const policyYaml = renderPolicyYaml(policy, profile, options.now ?? new Date());
|
|
90
|
+
const quickstartCode = language === 'py' ? renderQuickstartPy(policy, profile) : renderQuickstartTs(policy, profile);
|
|
91
|
+
const savingsTable = renderSavingsTable(savings);
|
|
92
|
+
if (!options.overwrite) {
|
|
93
|
+
assertWritableTarget(policyPath);
|
|
94
|
+
assertWritableTarget(quickstartPath);
|
|
95
|
+
}
|
|
96
|
+
atomicWrite(policyPath, policyYaml, 0o600);
|
|
97
|
+
atomicWrite(quickstartPath, quickstartCode, 0o600);
|
|
98
|
+
return { policy, policyPath, quickstartPath, sessionDir, savings, policyYaml, quickstartCode, savingsTable };
|
|
99
|
+
}
|
|
100
|
+
function renderPolicyYaml(policy, profile, now = new Date()) {
|
|
101
|
+
const caps = policy.caps.map((cap) => {
|
|
102
|
+
const lines = [
|
|
103
|
+
` # WHY: ${whyForWindow(cap.window)}`,
|
|
104
|
+
` - amountCents: ${cap.amountCents}`,
|
|
105
|
+
` window: ${cap.window}`,
|
|
106
|
+
` action: ${cap.action}`,
|
|
107
|
+
];
|
|
108
|
+
if (cap.downgradeTo)
|
|
109
|
+
lines.push(` downgradeTo: ${cap.downgradeTo}`);
|
|
110
|
+
if (cap.reason)
|
|
111
|
+
lines.push(` reason: ${quoteYaml(cap.reason)}`);
|
|
112
|
+
return lines.join('\n');
|
|
113
|
+
}).join('\n');
|
|
114
|
+
const tasks = profile.tasks.map((task) => ` - ${quoteYaml(task)}`).join('\n');
|
|
115
|
+
const posture = (0, posture_1.postureProfile)(profile.posture);
|
|
116
|
+
const canary = posture.canaryPercent === undefined ? '' : ` canaryPercent: ${posture.canaryPercent}\n`;
|
|
117
|
+
return `# AgentGuard Spend policy generated by agentguard advisor
|
|
118
|
+
# Generated at: ${now.toISOString()}
|
|
119
|
+
# Scope key: ${profile.scopeLabel}
|
|
120
|
+
id: ${policy.id}
|
|
121
|
+
name: ${quoteYaml(policy.name)}
|
|
122
|
+
version: ${policy.version}
|
|
123
|
+
effectiveFrom: ${quoteYaml(policy.effectiveFrom)}
|
|
124
|
+
mode: ${policy.mode}
|
|
125
|
+
requiredCapability: ${policy.requiredCapability ?? 'read_only'}
|
|
126
|
+
scope:
|
|
127
|
+
tenantId: ${quoteYaml(policy.scope.tenantId)}
|
|
128
|
+
models:
|
|
129
|
+
primary: ${profile.primaryModel}
|
|
130
|
+
fallback: ${profile.fallbackModel}
|
|
131
|
+
governancePosture:
|
|
132
|
+
posture: ${profile.posture}
|
|
133
|
+
auditRetentionDays: ${posture.auditRetentionDays}
|
|
134
|
+
approvalGates: ${posture.approvalGates}
|
|
135
|
+
downgradeStyle: ${posture.downgradeStyle}
|
|
136
|
+
${canary}tasks:
|
|
137
|
+
${tasks}
|
|
138
|
+
caps:
|
|
139
|
+
${caps}
|
|
140
|
+
systemInstructions: |
|
|
141
|
+
${indent(systemInstructions(profile), 2)}
|
|
142
|
+
`;
|
|
143
|
+
}
|
|
144
|
+
function renderQuickstartTs(policy, profile) {
|
|
145
|
+
return `import OpenAI from 'openai';\nimport { withSpendGuard, type SpendPolicy } from '@agentguard-run/spend';\n\nconst policy: SpendPolicy = ${JSON.stringify(policy, null, 2)};\n\nconst openrouter = new OpenAI({\n baseURL: 'https://openrouter.ai/api/v1',\n apiKey: process.env.OPENROUTER_API_KEY,\n});\n\nexport const guardedClient = withSpendGuard(openrouter, {\n policy,\n scope: { tenantId: '${escapeTs(profile.tenantId)}', agentId: '${escapeTs(profile.vertical)}' },\n capabilityClaim: '${policy.requiredCapability ?? 'read_only'}',\n});\n\nexport async function runGuardedTask(prompt: string) {\n return guardedClient.chat.completions.create({\n model: '${escapeTs(profile.primaryModel)}',\n messages: [{ role: 'user', content: prompt }],\n });\n}\n`;
|
|
146
|
+
}
|
|
147
|
+
function renderQuickstartPy(policy, profile) {
|
|
148
|
+
const caps = policy.caps.map((cap) => {
|
|
149
|
+
const args = [`amountCents=${cap.amountCents}`, `window='${cap.window}'`, `action='${cap.action}'`];
|
|
150
|
+
if (cap.downgradeTo)
|
|
151
|
+
args.push(`downgradeTo='${escapePy(cap.downgradeTo)}'`);
|
|
152
|
+
return ` SpendCap(${args.join(', ')}),`;
|
|
153
|
+
}).join('\n');
|
|
154
|
+
return `from openai import OpenAI\nfrom agentguard_spend import with_spend_guard\nfrom agentguard_spend.types import SpendPolicy, SpendCap\n\npolicy = SpendPolicy(\n id='${escapePy(policy.id)}',\n name='${escapePy(policy.name)}',\n scope={'tenantId': '${escapePy(profile.tenantId)}'},\n caps=[\n${caps}\n ],\n mode='${policy.mode}',\n requiredCapability='${policy.requiredCapability ?? 'read_only'}',\n version=${policy.version},\n effectiveFrom='${escapePy(policy.effectiveFrom)}',\n)\n\nopenrouter = OpenAI(base_url='https://openrouter.ai/api/v1')\nguarded_client = with_spend_guard(\n openrouter,\n policy=policy,\n scope={'tenantId': '${escapePy(profile.tenantId)}', 'agentId': '${escapePy(profile.vertical)}'},\n capability_claim='${policy.requiredCapability ?? 'read_only'}',\n)\n`;
|
|
155
|
+
}
|
|
156
|
+
function renderSavingsTable(savings) {
|
|
157
|
+
const rows = [
|
|
158
|
+
'Projected monthly savings',
|
|
159
|
+
`Before AgentGuard: ${(0, conversation_1.formatCents)(savings.monthlyBeforeCents)}`,
|
|
160
|
+
`After AgentGuard: ${(0, conversation_1.formatCents)(savings.monthlyAfterCents)}`,
|
|
161
|
+
`Savings: ${(0, conversation_1.formatCents)(savings.monthlySavingsCents)} (${savings.savingsPercent}%)`,
|
|
162
|
+
];
|
|
163
|
+
return rows.join('\n');
|
|
164
|
+
}
|
|
165
|
+
function atomicWrite(file, content, mode) {
|
|
166
|
+
const temp = `${file}.${process.pid}.${Date.now()}.tmp`;
|
|
167
|
+
fs.writeFileSync(temp, content, { encoding: 'utf8', mode });
|
|
168
|
+
fs.renameSync(temp, file);
|
|
169
|
+
fs.chmodSync(file, mode);
|
|
170
|
+
}
|
|
171
|
+
function assertWritableTarget(file) {
|
|
172
|
+
if (!fs.existsSync(file))
|
|
173
|
+
return;
|
|
174
|
+
fs.accessSync(file, fs.constants.W_OK);
|
|
175
|
+
}
|
|
176
|
+
function whyForWindow(window) {
|
|
177
|
+
if (window === 'per_call')
|
|
178
|
+
return 'Bounds one agent action and routes overflow to the fallback model.';
|
|
179
|
+
if (window === 'per_day')
|
|
180
|
+
return 'Catches runaway loops and unexpected daily volume.';
|
|
181
|
+
if (window === 'per_month')
|
|
182
|
+
return 'Keeps the finance view predictable for the billing cycle.';
|
|
183
|
+
return 'Limits spend inside the selected time window.';
|
|
184
|
+
}
|
|
185
|
+
function systemInstructions(profile) {
|
|
186
|
+
const posture = (0, posture_1.postureProfile)(profile.posture);
|
|
187
|
+
return `Run ${profile.vertical} tasks with ${profile.requiredCapability} capability under ${posture.label} governance posture. Prefer ${profile.primaryModel} for high-value work and ${profile.fallbackModel} for routine work. Keep evidence pointers in outputs and escalate anything outside the configured capability tier.`;
|
|
188
|
+
}
|
|
189
|
+
function quoteYaml(value) {
|
|
190
|
+
return JSON.stringify(value);
|
|
191
|
+
}
|
|
192
|
+
function indent(value, spaces) {
|
|
193
|
+
const prefix = ' '.repeat(spaces);
|
|
194
|
+
return value.split('\n').map((line) => prefix + line).join('\n');
|
|
195
|
+
}
|
|
196
|
+
function escapeTs(value) {
|
|
197
|
+
return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
198
|
+
}
|
|
199
|
+
function escapePy(value) {
|
|
200
|
+
return value.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=output.js.map
|