@calliopelabs/cli 3.2.1 → 3.3.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 +1 -0
- package/dist/acp.d.ts +11 -3
- package/dist/acp.d.ts.map +1 -1
- package/dist/acp.js +114 -27
- package/dist/acp.js.map +1 -1
- package/dist/attach.d.ts +95 -0
- package/dist/attach.d.ts.map +1 -0
- package/dist/attach.js +306 -0
- package/dist/attach.js.map +1 -0
- package/dist/bin.js +27 -5
- package/dist/bin.js.map +1 -1
- package/dist/brain/actions.d.ts +1 -1
- package/dist/brain/actions.d.ts.map +1 -1
- package/dist/brain/actions.js.map +1 -1
- package/dist/brain/cli.d.ts +1 -1
- package/dist/brain/cli.d.ts.map +1 -1
- package/dist/brain/cli.js +47 -5
- package/dist/brain/cli.js.map +1 -1
- package/dist/brain/exchange-json.d.ts +4 -0
- package/dist/brain/exchange-json.d.ts.map +1 -0
- package/dist/brain/exchange-json.js +77 -0
- package/dist/brain/exchange-json.js.map +1 -0
- package/dist/brain/exchange.d.ts +26 -0
- package/dist/brain/exchange.d.ts.map +1 -0
- package/dist/brain/exchange.js +86 -0
- package/dist/brain/exchange.js.map +1 -0
- package/dist/brain/index.d.ts +3 -0
- package/dist/brain/index.d.ts.map +1 -1
- package/dist/brain/index.js +3 -0
- package/dist/brain/index.js.map +1 -1
- package/dist/brain/journal.js +3 -3
- package/dist/brain/journal.js.map +1 -1
- package/dist/brain/kg-claims.d.ts +13 -0
- package/dist/brain/kg-claims.d.ts.map +1 -0
- package/dist/brain/kg-claims.js +156 -0
- package/dist/brain/kg-claims.js.map +1 -0
- package/dist/brain/kg-export.d.ts +13 -0
- package/dist/brain/kg-export.d.ts.map +1 -0
- package/dist/brain/kg-export.js +116 -0
- package/dist/brain/kg-export.js.map +1 -0
- package/dist/brain/kg-transfer.d.ts +29 -0
- package/dist/brain/kg-transfer.d.ts.map +1 -0
- package/dist/brain/kg-transfer.js +156 -0
- package/dist/brain/kg-transfer.js.map +1 -0
- package/dist/brain/kg.d.ts.map +1 -1
- package/dist/brain/kg.js +89 -16
- package/dist/brain/kg.js.map +1 -1
- package/dist/brain/presentation.d.ts.map +1 -1
- package/dist/brain/presentation.js +10 -0
- package/dist/brain/presentation.js.map +1 -1
- package/dist/brain/store.d.ts +1 -1
- package/dist/brain/store.d.ts.map +1 -1
- package/dist/brain/store.js +8 -2
- package/dist/brain/store.js.map +1 -1
- package/dist/brain/transfer-report.d.ts +38 -0
- package/dist/brain/transfer-report.d.ts.map +1 -0
- package/dist/brain/transfer-report.js +10 -0
- package/dist/brain/transfer-report.js.map +1 -0
- package/dist/brain/transfer.d.ts +29 -21
- package/dist/brain/transfer.d.ts.map +1 -1
- package/dist/brain/transfer.js +120 -89
- package/dist/brain/transfer.js.map +1 -1
- package/dist/brain/validation.d.ts +1 -0
- package/dist/brain/validation.d.ts.map +1 -1
- package/dist/brain/validation.js +7 -6
- package/dist/brain/validation.js.map +1 -1
- package/dist/config.d.ts +4 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js.map +1 -1
- package/dist/execution/authority.d.ts.map +1 -1
- package/dist/execution/authority.js +4 -2
- package/dist/execution/authority.js.map +1 -1
- package/dist/execution/files.d.ts.map +1 -1
- package/dist/execution/files.js +9 -6
- package/dist/execution/files.js.map +1 -1
- package/dist/execution/ledger.d.ts.map +1 -1
- package/dist/execution/ledger.js +3 -1
- package/dist/execution/ledger.js.map +1 -1
- package/dist/execution/project-spend.d.ts.map +1 -1
- package/dist/execution/project-spend.js +9 -6
- package/dist/execution/project-spend.js.map +1 -1
- package/dist/execution/writer-recovery.d.ts.map +1 -1
- package/dist/execution/writer-recovery.js +14 -10
- package/dist/execution/writer-recovery.js.map +1 -1
- package/dist/goals/store.d.ts.map +1 -1
- package/dist/goals/store.js +3 -1
- package/dist/goals/store.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/judgment/cli.d.ts +20 -0
- package/dist/judgment/cli.d.ts.map +1 -0
- package/dist/judgment/cli.js +141 -0
- package/dist/judgment/cli.js.map +1 -0
- package/dist/judgment/evaluate.d.ts +47 -0
- package/dist/judgment/evaluate.d.ts.map +1 -0
- package/dist/judgment/evaluate.js +369 -0
- package/dist/judgment/evaluate.js.map +1 -0
- package/dist/judgment/index.d.ts +8 -0
- package/dist/judgment/index.d.ts.map +1 -0
- package/dist/judgment/index.js +5 -0
- package/dist/judgment/index.js.map +1 -0
- package/dist/judgment/policy.d.ts +61 -0
- package/dist/judgment/policy.d.ts.map +1 -0
- package/dist/judgment/policy.js +143 -0
- package/dist/judgment/policy.js.map +1 -0
- package/dist/judgment/types.d.ts +73 -0
- package/dist/judgment/types.d.ts.map +1 -0
- package/dist/judgment/types.js +9 -0
- package/dist/judgment/types.js.map +1 -0
- package/dist/model-detection.d.ts.map +1 -1
- package/dist/model-detection.js +40 -7
- package/dist/model-detection.js.map +1 -1
- package/dist/models/metadata.d.ts +2 -0
- package/dist/models/metadata.d.ts.map +1 -1
- package/dist/models/metadata.js +2 -2
- package/dist/models/metadata.js.map +1 -1
- package/dist/orchestration/execution-store.d.ts.map +1 -1
- package/dist/orchestration/execution-store.js +14 -3
- package/dist/orchestration/execution-store.js.map +1 -1
- package/dist/orchestration/store.d.ts.map +1 -1
- package/dist/orchestration/store.js +3 -1
- package/dist/orchestration/store.js.map +1 -1
- package/dist/policy.d.ts +8 -1
- package/dist/policy.d.ts.map +1 -1
- package/dist/policy.js +74 -5
- package/dist/policy.js.map +1 -1
- package/dist/providers/anthropic.d.ts.map +1 -1
- package/dist/providers/anthropic.js +10 -5
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/openai.d.ts.map +1 -1
- package/dist/providers/openai.js +3 -2
- package/dist/providers/openai.js.map +1 -1
- package/dist/routing/select.d.ts +7 -0
- package/dist/routing/select.d.ts.map +1 -1
- package/dist/routing/select.js +18 -1
- package/dist/routing/select.js.map +1 -1
- package/dist/session-management/files.d.ts.map +1 -1
- package/dist/session-management/files.js +9 -6
- package/dist/session-management/files.js.map +1 -1
- package/dist/sessions/history.d.ts.map +1 -1
- package/dist/sessions/history.js +12 -6
- package/dist/sessions/history.js.map +1 -1
- package/dist/spawning/store.d.ts.map +1 -1
- package/dist/spawning/store.js +10 -8
- package/dist/spawning/store.js.map +1 -1
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +5 -2
- package/dist/tools.js.map +1 -1
- package/dist/types.js +1 -1
- package/dist/ui/agent.d.ts.map +1 -1
- package/dist/ui/agent.js +3 -2
- package/dist/ui/agent.js.map +1 -1
- package/dist/ui/commands.d.ts.map +1 -1
- package/dist/ui/commands.js +20 -12
- package/dist/ui/commands.js.map +1 -1
- package/dist/ui/model-commands.d.ts.map +1 -1
- package/dist/ui/model-commands.js +3 -2
- package/dist/ui/model-commands.js.map +1 -1
- package/package.json +5 -5
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { type Answer, type JudgmentEngine, type JudgmentResponse, type Question } from './types.js';
|
|
2
|
+
/** Exactly one operator per rule, matching its question's primitive. */
|
|
3
|
+
export interface DenyRule {
|
|
4
|
+
question: string;
|
|
5
|
+
reason: string;
|
|
6
|
+
/** noul: deny when the probability of yes exceeds this. */
|
|
7
|
+
above?: number;
|
|
8
|
+
/** choice: deny when this option is selected. */
|
|
9
|
+
is?: string;
|
|
10
|
+
/** score: deny when the weighted level reaches this. */
|
|
11
|
+
atLeast?: number;
|
|
12
|
+
/** choice/score: ignore the match below this confidence. */
|
|
13
|
+
minConfidence?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface PolicyRules {
|
|
16
|
+
questions: Record<string, Question>;
|
|
17
|
+
deny: DenyRule[];
|
|
18
|
+
}
|
|
19
|
+
export interface PolicyVerdict {
|
|
20
|
+
decision: 'allow' | 'deny';
|
|
21
|
+
reason?: string;
|
|
22
|
+
rule?: DenyRule;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Validate rules against their own questions, so a typo or a mismatched
|
|
26
|
+
* operator fails when the policy is written rather than when a tool is judged.
|
|
27
|
+
*/
|
|
28
|
+
export declare function validatePolicyRules(input: unknown): PolicyRules;
|
|
29
|
+
/** Deny wins, and the first matching rule supplies the reason. */
|
|
30
|
+
export declare function decidePolicy(rules: PolicyRules, answers: Record<string, Answer>): PolicyVerdict;
|
|
31
|
+
/** A configured engine name is operator input, so it is checked like any other. */
|
|
32
|
+
export declare function validateJudgmentEngine(value: unknown): JudgmentEngine;
|
|
33
|
+
export interface JudgeToolCallOptions {
|
|
34
|
+
rulesPath: string;
|
|
35
|
+
provider?: JudgmentEngine;
|
|
36
|
+
model?: string;
|
|
37
|
+
signal?: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Judge one pending tool call against a rules file. Shared by the CLI engine
|
|
41
|
+
* and the built-in `policy.judgment` setting so both decide identically.
|
|
42
|
+
*/
|
|
43
|
+
export declare function judgeToolCall(toolCall: unknown, options: JudgeToolCallOptions): Promise<{
|
|
44
|
+
verdict: PolicyVerdict;
|
|
45
|
+
response: JudgmentResponse;
|
|
46
|
+
}>;
|
|
47
|
+
export interface PolicyRunOptions {
|
|
48
|
+
provider?: JudgmentEngine;
|
|
49
|
+
model?: string;
|
|
50
|
+
signal?: AbortSignal;
|
|
51
|
+
json?: boolean;
|
|
52
|
+
stdin?: () => string;
|
|
53
|
+
write?: (text: string) => void;
|
|
54
|
+
writeErr?: (text: string) => void;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Exit 0 allows, 1 denies by rule, 2 denies because the engine could not decide.
|
|
58
|
+
* The hook treats every non-zero exit as a denial and reads stderr as the reason.
|
|
59
|
+
*/
|
|
60
|
+
export declare function runJudgePolicy(rulesPath: string, options?: PolicyRunOptions): Promise<number>;
|
|
61
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../../src/judgment/policy.ts"],"names":[],"mappings":"AASA,OAAO,EAAiB,KAAK,MAAM,EAAE,KAAK,cAAc,EAAE,KAAK,gBAAgB,EAAE,KAAK,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEnH,wEAAwE;AACxE,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,wDAAwD;IACxD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,4DAA4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpC,IAAI,EAAE,QAAQ,EAAE,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,QAAQ,CAAC;CACjB;AAaD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,OAAO,GAAG,WAAW,CAwC/D;AAED,kEAAkE;AAClE,wBAAgB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,aAAa,CAW/F;AAED,mFAAmF;AACnF,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,cAAc,CAKrE;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,gBAAgB,CAAA;CAAE,CAAC,CAKrJ;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBvG"}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Judgment-backed policy engine for the pre-tool hook (see docs/governance.md).
|
|
3
|
+
* Reads a pending tool call on stdin, judges it against reviewed questions, and
|
|
4
|
+
* exits 0 to allow or non-zero to deny. Every failure denies: a policy engine
|
|
5
|
+
* that cannot decide must never wave a tool through.
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs';
|
|
8
|
+
import * as config from '../config.js';
|
|
9
|
+
import { evaluate } from './evaluate.js';
|
|
10
|
+
import { JudgmentError } from './types.js';
|
|
11
|
+
function invalid(message) { throw new JudgmentError('invalid-request', message); }
|
|
12
|
+
function isRecord(value) {
|
|
13
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
|
+
}
|
|
15
|
+
function probability(id, field, value) {
|
|
16
|
+
if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1)
|
|
17
|
+
invalid(`Rule for "${id}": "${field}" must be a number between 0 and 1.`);
|
|
18
|
+
return value;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Validate rules against their own questions, so a typo or a mismatched
|
|
22
|
+
* operator fails when the policy is written rather than when a tool is judged.
|
|
23
|
+
*/
|
|
24
|
+
export function validatePolicyRules(input) {
|
|
25
|
+
if (!isRecord(input))
|
|
26
|
+
invalid('Policy rules must be an object with "questions" and "deny".');
|
|
27
|
+
if (!isRecord(input.questions))
|
|
28
|
+
invalid('Policy rules need a "questions" map.');
|
|
29
|
+
if (!Array.isArray(input.deny) || input.deny.length === 0)
|
|
30
|
+
invalid('Policy rules need a non-empty "deny" array.');
|
|
31
|
+
const questions = input.questions;
|
|
32
|
+
const deny = input.deny.map((value, index) => {
|
|
33
|
+
if (!isRecord(value))
|
|
34
|
+
invalid(`Deny rule ${index} must be an object.`);
|
|
35
|
+
const id = value.question;
|
|
36
|
+
if (typeof id !== 'string' || !Object.hasOwn(questions, id))
|
|
37
|
+
invalid(`Deny rule ${index} names unknown question ${JSON.stringify(id)}.`);
|
|
38
|
+
if (typeof value.reason !== 'string' || !value.reason.trim())
|
|
39
|
+
invalid(`Deny rule for "${id}" needs a reason.`);
|
|
40
|
+
const question = questions[id];
|
|
41
|
+
const operators = ['above', 'is', 'atLeast'].filter(name => value[name] !== undefined);
|
|
42
|
+
if (operators.length !== 1)
|
|
43
|
+
invalid(`Deny rule for "${id}" needs exactly one of above, is or atLeast.`);
|
|
44
|
+
const rule = { question: id, reason: value.reason };
|
|
45
|
+
if (value.minConfidence !== undefined) {
|
|
46
|
+
if (question.type === 'noul')
|
|
47
|
+
invalid(`Deny rule for "${id}": a noul answer carries no confidence.`);
|
|
48
|
+
rule.minConfidence = probability(id, 'minConfidence', value.minConfidence);
|
|
49
|
+
}
|
|
50
|
+
switch (operators[0]) {
|
|
51
|
+
case 'above':
|
|
52
|
+
if (question.type !== 'noul')
|
|
53
|
+
invalid(`Deny rule for "${id}": "above" applies to a noul question.`);
|
|
54
|
+
rule.above = probability(id, 'above', value.above);
|
|
55
|
+
break;
|
|
56
|
+
case 'is': {
|
|
57
|
+
if (question.type !== 'choice')
|
|
58
|
+
invalid(`Deny rule for "${id}": "is" applies to a choice question.`);
|
|
59
|
+
if (typeof value.is !== 'string' || !Object.hasOwn(question.criteria, value.is))
|
|
60
|
+
invalid(`Deny rule for "${id}": "is" must name one of its options.`);
|
|
61
|
+
rule.is = value.is;
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
default: {
|
|
65
|
+
if (question.type !== 'score')
|
|
66
|
+
invalid(`Deny rule for "${id}": "atLeast" applies to a score question.`);
|
|
67
|
+
const levels = question.criteria.length - 1;
|
|
68
|
+
if (typeof value.atLeast !== 'number' || !Number.isFinite(value.atLeast) || value.atLeast < 0 || value.atLeast > levels)
|
|
69
|
+
invalid(`Deny rule for "${id}": "atLeast" must be between 0 and ${levels}.`);
|
|
70
|
+
rule.atLeast = value.atLeast;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return rule;
|
|
75
|
+
});
|
|
76
|
+
return { questions, deny };
|
|
77
|
+
}
|
|
78
|
+
/** Deny wins, and the first matching rule supplies the reason. */
|
|
79
|
+
export function decidePolicy(rules, answers) {
|
|
80
|
+
for (const rule of rules.deny) {
|
|
81
|
+
const answer = answers[rule.question];
|
|
82
|
+
if (!answer)
|
|
83
|
+
throw new JudgmentError('model-output', `No answer returned for question "${rule.question}".`);
|
|
84
|
+
if (rule.minConfidence !== undefined && 'confidence' in answer && answer.confidence < rule.minConfidence)
|
|
85
|
+
continue;
|
|
86
|
+
const matched = answer.type === 'noul' ? rule.above !== undefined && answer.noul > rule.above
|
|
87
|
+
: answer.type === 'choice' ? answer.choice === rule.is
|
|
88
|
+
: rule.atLeast !== undefined && answer.score >= rule.atLeast;
|
|
89
|
+
if (matched)
|
|
90
|
+
return { decision: 'deny', reason: rule.reason, rule };
|
|
91
|
+
}
|
|
92
|
+
return { decision: 'allow' };
|
|
93
|
+
}
|
|
94
|
+
/** A configured engine name is operator input, so it is checked like any other. */
|
|
95
|
+
export function validateJudgmentEngine(value) {
|
|
96
|
+
if (value === 'typesafe')
|
|
97
|
+
return 'typesafe';
|
|
98
|
+
if (typeof value !== 'string' || (value !== 'auto' && !config.getProviderNames().includes(value)))
|
|
99
|
+
invalid(`Unknown judgment provider ${JSON.stringify(value)}.`);
|
|
100
|
+
return value;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Judge one pending tool call against a rules file. Shared by the CLI engine
|
|
104
|
+
* and the built-in `policy.judgment` setting so both decide identically.
|
|
105
|
+
*/
|
|
106
|
+
export async function judgeToolCall(toolCall, options) {
|
|
107
|
+
const rules = validatePolicyRules(JSON.parse(fs.readFileSync(options.rulesPath, 'utf8')));
|
|
108
|
+
if (!isRecord(toolCall))
|
|
109
|
+
invalid('The pending tool call must be a JSON object.');
|
|
110
|
+
const response = await evaluate({ state: toolCall, questions: rules.questions }, { provider: options.provider, model: options.model, signal: options.signal });
|
|
111
|
+
return { verdict: decidePolicy(rules, response.answers), response };
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Exit 0 allows, 1 denies by rule, 2 denies because the engine could not decide.
|
|
115
|
+
* The hook treats every non-zero exit as a denial and reads stderr as the reason.
|
|
116
|
+
*/
|
|
117
|
+
export async function runJudgePolicy(rulesPath, options = {}) {
|
|
118
|
+
const write = options.write ?? ((text) => { process.stdout.write(text); });
|
|
119
|
+
const writeErr = options.writeErr ?? ((text) => { process.stderr.write(text); });
|
|
120
|
+
const stdin = options.stdin ?? (() => fs.readFileSync(0, 'utf8'));
|
|
121
|
+
try {
|
|
122
|
+
let toolCall;
|
|
123
|
+
try {
|
|
124
|
+
toolCall = JSON.parse(stdin());
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
invalid('The pending tool call on stdin is not valid JSON.');
|
|
128
|
+
}
|
|
129
|
+
const { verdict, response } = await judgeToolCall(toolCall, { rulesPath, ...(options.provider ? { provider: options.provider } : {}), ...(options.model ? { model: options.model } : {}), ...(options.signal ? { signal: options.signal } : {}) });
|
|
130
|
+
if (options.json)
|
|
131
|
+
write(JSON.stringify({ version: 1, type: 'judgment-policy', ...verdict, provider: response.provider, model: response.model, answers: response.answers, usage: response.usage }) + '\n');
|
|
132
|
+
if (verdict.decision === 'allow')
|
|
133
|
+
return 0;
|
|
134
|
+
writeErr(`${verdict.reason}\n`);
|
|
135
|
+
return 1;
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
const message = error instanceof JudgmentError || error instanceof Error ? error.message : String(error);
|
|
139
|
+
writeErr(`policy engine could not decide: ${message}\n`);
|
|
140
|
+
return 2;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../../src/judgment/policy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed judgments: small, composable units of semantic judgment that code can
|
|
3
|
+
* threshold, weight and combine. One request evaluates a `state` against a map
|
|
4
|
+
* of typed questions and returns one probabilistic answer per question.
|
|
5
|
+
*/
|
|
6
|
+
import type { LLMProvider } from '../types.js';
|
|
7
|
+
/** Any chat backend (prompted judgments) or the native TypeSafe endpoint. */
|
|
8
|
+
export type JudgmentEngine = LLMProvider | 'typesafe';
|
|
9
|
+
/** Free text, or structured guidance (definitions, contrasts, examples). */
|
|
10
|
+
export type Instructions = string | Record<string, unknown> | unknown[];
|
|
11
|
+
/** A yes/no judgment. The answer is the probability of yes. */
|
|
12
|
+
export interface NoulQuestion {
|
|
13
|
+
type: 'noul';
|
|
14
|
+
instructions: Instructions;
|
|
15
|
+
criteria?: {
|
|
16
|
+
true?: string;
|
|
17
|
+
false?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/** One option from a defined set. `null` means the option needs no rubric. */
|
|
21
|
+
export interface ChoiceQuestion {
|
|
22
|
+
type: 'choice';
|
|
23
|
+
instructions: Instructions;
|
|
24
|
+
criteria: Record<string, string | null>;
|
|
25
|
+
}
|
|
26
|
+
/** A position along ordered levels; the answer can land between levels. */
|
|
27
|
+
export interface ScoreQuestion {
|
|
28
|
+
type: 'score';
|
|
29
|
+
instructions: Instructions;
|
|
30
|
+
criteria: string[];
|
|
31
|
+
}
|
|
32
|
+
export type Question = NoulQuestion | ChoiceQuestion | ScoreQuestion;
|
|
33
|
+
export interface JudgmentRequest {
|
|
34
|
+
/** Text or structured data to judge. */
|
|
35
|
+
state: unknown;
|
|
36
|
+
/** Keys are for the caller's code; they are never sent to the model. */
|
|
37
|
+
questions: Record<string, Question>;
|
|
38
|
+
}
|
|
39
|
+
export interface NoulAnswer {
|
|
40
|
+
type: 'noul';
|
|
41
|
+
noul: number;
|
|
42
|
+
}
|
|
43
|
+
export interface ChoiceAnswer {
|
|
44
|
+
type: 'choice';
|
|
45
|
+
choice: string;
|
|
46
|
+
probabilities: Record<string, number>;
|
|
47
|
+
/** How far the leading outcome sits above chance: 1 is peaked, 0 is uniform. */
|
|
48
|
+
confidence: number;
|
|
49
|
+
}
|
|
50
|
+
export interface ScoreAnswer {
|
|
51
|
+
type: 'score';
|
|
52
|
+
/** Probability-weighted level index; between levels is a valid result. */
|
|
53
|
+
score: number;
|
|
54
|
+
legend: Record<string, string>;
|
|
55
|
+
probabilities: Record<string, number>;
|
|
56
|
+
confidence: number;
|
|
57
|
+
}
|
|
58
|
+
export type Answer = NoulAnswer | ChoiceAnswer | ScoreAnswer;
|
|
59
|
+
export interface JudgmentResponse {
|
|
60
|
+
provider: JudgmentEngine;
|
|
61
|
+
model: string;
|
|
62
|
+
answers: Record<string, Answer>;
|
|
63
|
+
usage: {
|
|
64
|
+
input_tokens: number;
|
|
65
|
+
output_tokens: number;
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
export type JudgmentErrorCode = 'invalid-request' | 'model-output' | 'unavailable';
|
|
69
|
+
export declare class JudgmentError extends Error {
|
|
70
|
+
readonly code: JudgmentErrorCode;
|
|
71
|
+
constructor(code: JudgmentErrorCode, message: string);
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/judgment/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,6EAA6E;AAC7E,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,UAAU,CAAC;AAEtD,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,EAAE,CAAC;AAExE,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C;AAED,8EAA8E;AAC9E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,QAAQ,CAAC;IACf,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;CACzC;AAED,2EAA2E;AAC3E,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,YAAY,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,QAAQ,GAAG,YAAY,GAAG,cAAc,GAAG,aAAa,CAAC;AAErE,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,KAAK,EAAE,OAAO,CAAC;IACf,wEAAwE;IACxE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,UAAU;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE;AAC1D,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,gFAAgF;IAChF,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,UAAU,EAAE,MAAM,CAAC;CACpB;AACD,MAAM,MAAM,MAAM,GAAG,UAAU,GAAG,YAAY,GAAG,WAAW,CAAC;AAE7D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,KAAK,EAAE;QAAE,YAAY,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAC;CACxD;AAED,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,GAAG,cAAc,GAAG,aAAa,CAAC;AAEnF,qBAAa,aAAc,SAAQ,KAAK;IAC1B,QAAQ,CAAC,IAAI,EAAE,iBAAiB;IAA5C,YAAqB,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,MAAM,EAG5D;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/judgment/types.ts"],"names":[],"mappings":"AAsEA,MAAM,OAAO,aAAc,SAAQ,KAAK;IACjB,IAAI;IAAzB,YAAqB,IAAuB,EAAE,OAAe;QAC3D,KAAK,CAAC,OAAO,CAAC,CAAC;oBADI,IAAI;QAEvB,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;IAC9B,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"model-detection.d.ts","sourceRoot":"","sources":["../src/model-detection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAK9C,OAAO,EAA+I,KAAK,SAAS,EAA0B,MAAM,mBAAmB,CAAC;AACxN,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAItE,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;yEACqE;IACrE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAoCD,wFAAwF;AACxF,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAMrH;
|
|
1
|
+
{"version":3,"file":"model-detection.d.ts","sourceRoot":"","sources":["../src/model-detection.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAK9C,OAAO,EAA+I,KAAK,SAAS,EAA0B,MAAM,mBAAmB,CAAC;AACxN,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAItE,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,mFAAmF;IACnF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;yEACqE;IACrE,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAoCD,wFAAwF;AACxF,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,GAAE,iBAAsB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAMrH;AAkID,8EAA8E;AAC9E,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,WAAW,GAAG,SAAS,EAAE,GAAG,SAAS,CAG1F;AAMD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,WAAW,GAAG,SAAS,EAAE,GAAG,SAAS,CAIlF;AAED,+EAA+E;AAC/E,wBAAsB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC,CAoBlI;AAED;;GAEG;AACH,wBAAsB,wBAAwB,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqC5F;AAifD;;;GAGG;AACH,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAqBrE;AA8ZD;;GAEG;AACH,wBAAgB,eAAe,CAAC,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI,CAQ5D;AAED;;;GAGG;AACH,wBAAsB,iBAAiB,CAAC,YAAY,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CASjF;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,CAY1F;AAwDD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAmBnF;AAwBD;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAchF"}
|
package/dist/model-detection.js
CHANGED
|
@@ -112,13 +112,22 @@ const INCOMPATIBLE_MODEL_PATTERNS = {
|
|
|
112
112
|
/-similarity-/, // Similarity models
|
|
113
113
|
/-edit-/, // Edit models
|
|
114
114
|
/^chatgpt-4o-latest/, // Internal/unstable aliases
|
|
115
|
+
/image/, // Image generation (gpt-image-*, chatgpt-image-latest)
|
|
116
|
+
/audio|realtime|transcribe|tts|whisper|^gpt-live/, // Speech and live-voice models
|
|
117
|
+
/^sora/, // Video generation
|
|
118
|
+
/-search-preview|-search-api/, // Search-only endpoints
|
|
119
|
+
/deep-research/, // Background research agents, not chat
|
|
120
|
+
/computer-use/, // Requires the dedicated Computer Use tool contract
|
|
115
121
|
],
|
|
116
122
|
google: [
|
|
117
123
|
/^embedding/, // Embedding models
|
|
118
124
|
/^text-embedding/, // Text embedding
|
|
119
125
|
/^aqa/, // Attributed QA (not chat)
|
|
120
126
|
/embedding$/, // Any model ending in embedding
|
|
127
|
+
/embedding/, // gemini-embedding-*
|
|
121
128
|
/computer-use/i, // Requires the dedicated Computer Use tool contract
|
|
129
|
+
/robotics/, // Embodied-reasoning models
|
|
130
|
+
/-live|-tts|transcribe|translate|native-audio|-image/, // Live, speech, and image modalities
|
|
122
131
|
],
|
|
123
132
|
groq: [
|
|
124
133
|
/^whisper/, // Speech-to-text
|
|
@@ -373,13 +382,13 @@ async function getAnthropicModels(options = {}) {
|
|
|
373
382
|
const models = await modelPages(`${(config.getBaseUrl('anthropic') || 'https://api.anthropic.com').replace(/\/v1\/?$/, '').replace(/\/$/, '')}/v1/models`, 'anthropic', { 'x-api-key': apiKey, 'anthropic-version': '2023-06-01' });
|
|
374
383
|
return models
|
|
375
384
|
.filter(model => model.id.startsWith('claude'))
|
|
385
|
+
.sort((a, b) => releaseOrder(Date.parse(a.created_at ?? ''), Date.parse(b.created_at ?? ''), a.id, b.id)) // Newest first
|
|
376
386
|
.map(model => ({
|
|
377
387
|
id: model.id,
|
|
378
388
|
name: model.display_name || formatModelName(model.id),
|
|
379
389
|
description: getAnthropicModelDescription(model.id),
|
|
380
390
|
...anthropicMetadata(model),
|
|
381
|
-
}))
|
|
382
|
-
.sort((a, b) => b.id.localeCompare(a.id)); // Newest first
|
|
391
|
+
}));
|
|
383
392
|
}
|
|
384
393
|
catch (error) {
|
|
385
394
|
// Emergency fallback when the API is unreachable. Keep these as the current
|
|
@@ -388,8 +397,8 @@ async function getAnthropicModels(options = {}) {
|
|
|
388
397
|
throw error;
|
|
389
398
|
logModelDetectionWarning('Failed to fetch Anthropic models, using fallback list', error, options);
|
|
390
399
|
return [
|
|
391
|
-
{ id: 'claude-opus-
|
|
392
|
-
{ id: 'claude-sonnet-
|
|
400
|
+
{ id: 'claude-opus-5', name: 'Claude Opus 5', description: 'Most capable model', contextLength: 1000000 },
|
|
401
|
+
{ id: 'claude-sonnet-5', name: 'Claude Sonnet 5', description: 'Balanced intelligence and speed', contextLength: 1000000 },
|
|
393
402
|
{ id: 'claude-haiku-4-5', name: 'Claude Haiku 4.5', description: 'Fast and affordable', contextLength: 200000 },
|
|
394
403
|
].map(model => ({ ...model, evidence: { source: 'emergency', at: new Date().toISOString() } }));
|
|
395
404
|
}
|
|
@@ -435,7 +444,7 @@ async function getGoogleModels(options = {}) {
|
|
|
435
444
|
maxOutputTokens: positiveLimit(model.outputTokenLimit),
|
|
436
445
|
capabilities: { chat: stringList(model.supportedGenerationMethods)?.includes('generateContent'), thinking: capability(model.thinking) },
|
|
437
446
|
}))
|
|
438
|
-
.sort((a, b) =>
|
|
447
|
+
.sort((a, b) => geminiOrder(a.id, b.id)); // Newest first
|
|
439
448
|
}
|
|
440
449
|
catch (error) {
|
|
441
450
|
// Fallback to known models if API fails
|
|
@@ -451,6 +460,16 @@ async function getGoogleModels(options = {}) {
|
|
|
451
460
|
].map(model => ({ ...model, evidence: { source: 'emergency', at: new Date().toISOString() } }));
|
|
452
461
|
}
|
|
453
462
|
}
|
|
463
|
+
/**
|
|
464
|
+
* Gemini ids carry the generation in the name and the API reports no release
|
|
465
|
+
* date, so order by version (3.8 before 3.1 before 2.5), then pro before flash
|
|
466
|
+
* before flash-lite, then the shortest id. Unversioned rolling aliases sort last.
|
|
467
|
+
*/
|
|
468
|
+
function geminiOrder(aId, bId) {
|
|
469
|
+
const version = (id) => { const m = /^gemini-(\d+(?:\.\d+)?)/.exec(id); return m ? Number(m[1]) : -1; };
|
|
470
|
+
const tier = (id) => id.includes('-pro') ? 0 : id.includes('flash-lite') ? 2 : id.includes('flash') ? 1 : 3;
|
|
471
|
+
return version(bId) - version(aId) || tier(aId) - tier(bId) || aId.length - bId.length || aId.localeCompare(bId);
|
|
472
|
+
}
|
|
454
473
|
/**
|
|
455
474
|
* Get OpenAI models
|
|
456
475
|
*/
|
|
@@ -461,19 +480,33 @@ async function getOpenAIModels() {
|
|
|
461
480
|
const client = new OpenAI({ apiKey, baseURL: config.getBaseUrl('openai'), ...discoveryTransportOptions() });
|
|
462
481
|
const response = await client.models.list();
|
|
463
482
|
// Filter for chat-compatible models (GPT and reasoning models)
|
|
483
|
+
const family = (id) => id.replace(/-\d{4}-\d{2}-\d{2}$/, '');
|
|
484
|
+
const familyCreated = new Map();
|
|
485
|
+
for (const model of response.data)
|
|
486
|
+
familyCreated.set(family(model.id), Math.max(familyCreated.get(family(model.id)) ?? -Infinity, model.created * 1000));
|
|
464
487
|
return response.data
|
|
465
488
|
.filter(model => isCompatibleModel(model.id, 'openai') && (model.id.includes('gpt') ||
|
|
466
489
|
model.id.startsWith('o1') ||
|
|
467
490
|
model.id.startsWith('o3') ||
|
|
468
491
|
model.id.startsWith('o4') ||
|
|
469
492
|
model.id.startsWith('gpt-5')))
|
|
493
|
+
.sort((a, b) => releaseOrder(familyCreated.get(family(a.id)), familyCreated.get(family(b.id)), a.id, b.id)) // Newest first
|
|
470
494
|
.map(model => ({
|
|
471
495
|
id: model.id,
|
|
472
496
|
name: model.id,
|
|
473
497
|
description: getOpenAIModelDescription(model.id),
|
|
474
498
|
...compatibleMetadata(model),
|
|
475
|
-
}))
|
|
476
|
-
|
|
499
|
+
}));
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Newest release first; within a release family, the short alias precedes its
|
|
503
|
+
* dated snapshot (gpt-5.5 before gpt-5.5-2026-04-23). Unknown dates sort last.
|
|
504
|
+
*/
|
|
505
|
+
function releaseOrder(aCreated, bCreated, aId, bId) {
|
|
506
|
+
const a = Number.isFinite(aCreated) ? aCreated : -Infinity, b = Number.isFinite(bCreated) ? bCreated : -Infinity;
|
|
507
|
+
if (a !== b)
|
|
508
|
+
return b - a;
|
|
509
|
+
return aId.length - bId.length || aId.localeCompare(bId);
|
|
477
510
|
}
|
|
478
511
|
/**
|
|
479
512
|
* Get OpenRouter models
|