@calliopelabs/cli 3.2.1 → 3.3.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.
Files changed (163) hide show
  1. package/README.md +1 -0
  2. package/dist/acp.d.ts +11 -3
  3. package/dist/acp.d.ts.map +1 -1
  4. package/dist/acp.js +114 -27
  5. package/dist/acp.js.map +1 -1
  6. package/dist/attach.d.ts +149 -0
  7. package/dist/attach.d.ts.map +1 -0
  8. package/dist/attach.js +450 -0
  9. package/dist/attach.js.map +1 -0
  10. package/dist/bin.d.ts +1 -0
  11. package/dist/bin.d.ts.map +1 -1
  12. package/dist/bin.js +30 -6
  13. package/dist/bin.js.map +1 -1
  14. package/dist/brain/actions.d.ts +1 -1
  15. package/dist/brain/actions.d.ts.map +1 -1
  16. package/dist/brain/actions.js.map +1 -1
  17. package/dist/brain/cli.d.ts +1 -1
  18. package/dist/brain/cli.d.ts.map +1 -1
  19. package/dist/brain/cli.js +47 -5
  20. package/dist/brain/cli.js.map +1 -1
  21. package/dist/brain/exchange-json.d.ts +4 -0
  22. package/dist/brain/exchange-json.d.ts.map +1 -0
  23. package/dist/brain/exchange-json.js +77 -0
  24. package/dist/brain/exchange-json.js.map +1 -0
  25. package/dist/brain/exchange.d.ts +26 -0
  26. package/dist/brain/exchange.d.ts.map +1 -0
  27. package/dist/brain/exchange.js +86 -0
  28. package/dist/brain/exchange.js.map +1 -0
  29. package/dist/brain/index.d.ts +3 -0
  30. package/dist/brain/index.d.ts.map +1 -1
  31. package/dist/brain/index.js +3 -0
  32. package/dist/brain/index.js.map +1 -1
  33. package/dist/brain/journal.js +3 -3
  34. package/dist/brain/journal.js.map +1 -1
  35. package/dist/brain/kg-claims.d.ts +13 -0
  36. package/dist/brain/kg-claims.d.ts.map +1 -0
  37. package/dist/brain/kg-claims.js +156 -0
  38. package/dist/brain/kg-claims.js.map +1 -0
  39. package/dist/brain/kg-export.d.ts +13 -0
  40. package/dist/brain/kg-export.d.ts.map +1 -0
  41. package/dist/brain/kg-export.js +116 -0
  42. package/dist/brain/kg-export.js.map +1 -0
  43. package/dist/brain/kg-transfer.d.ts +29 -0
  44. package/dist/brain/kg-transfer.d.ts.map +1 -0
  45. package/dist/brain/kg-transfer.js +156 -0
  46. package/dist/brain/kg-transfer.js.map +1 -0
  47. package/dist/brain/kg.d.ts.map +1 -1
  48. package/dist/brain/kg.js +89 -16
  49. package/dist/brain/kg.js.map +1 -1
  50. package/dist/brain/presentation.d.ts.map +1 -1
  51. package/dist/brain/presentation.js +10 -0
  52. package/dist/brain/presentation.js.map +1 -1
  53. package/dist/brain/store.d.ts +1 -1
  54. package/dist/brain/store.d.ts.map +1 -1
  55. package/dist/brain/store.js +8 -2
  56. package/dist/brain/store.js.map +1 -1
  57. package/dist/brain/transfer-report.d.ts +38 -0
  58. package/dist/brain/transfer-report.d.ts.map +1 -0
  59. package/dist/brain/transfer-report.js +10 -0
  60. package/dist/brain/transfer-report.js.map +1 -0
  61. package/dist/brain/transfer.d.ts +29 -21
  62. package/dist/brain/transfer.d.ts.map +1 -1
  63. package/dist/brain/transfer.js +120 -89
  64. package/dist/brain/transfer.js.map +1 -1
  65. package/dist/brain/validation.d.ts +1 -0
  66. package/dist/brain/validation.d.ts.map +1 -1
  67. package/dist/brain/validation.js +7 -6
  68. package/dist/brain/validation.js.map +1 -1
  69. package/dist/config.d.ts +4 -0
  70. package/dist/config.d.ts.map +1 -1
  71. package/dist/config.js.map +1 -1
  72. package/dist/execution/authority.d.ts.map +1 -1
  73. package/dist/execution/authority.js +4 -2
  74. package/dist/execution/authority.js.map +1 -1
  75. package/dist/execution/files.d.ts.map +1 -1
  76. package/dist/execution/files.js +9 -6
  77. package/dist/execution/files.js.map +1 -1
  78. package/dist/execution/ledger.d.ts.map +1 -1
  79. package/dist/execution/ledger.js +3 -1
  80. package/dist/execution/ledger.js.map +1 -1
  81. package/dist/execution/project-spend.d.ts.map +1 -1
  82. package/dist/execution/project-spend.js +9 -6
  83. package/dist/execution/project-spend.js.map +1 -1
  84. package/dist/execution/writer-recovery.d.ts.map +1 -1
  85. package/dist/execution/writer-recovery.js +14 -10
  86. package/dist/execution/writer-recovery.js.map +1 -1
  87. package/dist/goals/store.d.ts.map +1 -1
  88. package/dist/goals/store.js +3 -1
  89. package/dist/goals/store.js.map +1 -1
  90. package/dist/index.d.ts +2 -0
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +1 -0
  93. package/dist/index.js.map +1 -1
  94. package/dist/judgment/cli.d.ts +20 -0
  95. package/dist/judgment/cli.d.ts.map +1 -0
  96. package/dist/judgment/cli.js +141 -0
  97. package/dist/judgment/cli.js.map +1 -0
  98. package/dist/judgment/evaluate.d.ts +47 -0
  99. package/dist/judgment/evaluate.d.ts.map +1 -0
  100. package/dist/judgment/evaluate.js +369 -0
  101. package/dist/judgment/evaluate.js.map +1 -0
  102. package/dist/judgment/index.d.ts +8 -0
  103. package/dist/judgment/index.d.ts.map +1 -0
  104. package/dist/judgment/index.js +5 -0
  105. package/dist/judgment/index.js.map +1 -0
  106. package/dist/judgment/policy.d.ts +61 -0
  107. package/dist/judgment/policy.d.ts.map +1 -0
  108. package/dist/judgment/policy.js +143 -0
  109. package/dist/judgment/policy.js.map +1 -0
  110. package/dist/judgment/types.d.ts +73 -0
  111. package/dist/judgment/types.d.ts.map +1 -0
  112. package/dist/judgment/types.js +9 -0
  113. package/dist/judgment/types.js.map +1 -0
  114. package/dist/model-detection.d.ts.map +1 -1
  115. package/dist/model-detection.js +40 -7
  116. package/dist/model-detection.js.map +1 -1
  117. package/dist/models/metadata.d.ts +2 -0
  118. package/dist/models/metadata.d.ts.map +1 -1
  119. package/dist/models/metadata.js +2 -2
  120. package/dist/models/metadata.js.map +1 -1
  121. package/dist/orchestration/execution-store.d.ts.map +1 -1
  122. package/dist/orchestration/execution-store.js +14 -3
  123. package/dist/orchestration/execution-store.js.map +1 -1
  124. package/dist/orchestration/store.d.ts.map +1 -1
  125. package/dist/orchestration/store.js +3 -1
  126. package/dist/orchestration/store.js.map +1 -1
  127. package/dist/policy.d.ts +8 -1
  128. package/dist/policy.d.ts.map +1 -1
  129. package/dist/policy.js +74 -5
  130. package/dist/policy.js.map +1 -1
  131. package/dist/providers/anthropic.d.ts.map +1 -1
  132. package/dist/providers/anthropic.js +10 -5
  133. package/dist/providers/anthropic.js.map +1 -1
  134. package/dist/providers/openai.d.ts.map +1 -1
  135. package/dist/providers/openai.js +3 -2
  136. package/dist/providers/openai.js.map +1 -1
  137. package/dist/routing/select.d.ts +7 -0
  138. package/dist/routing/select.d.ts.map +1 -1
  139. package/dist/routing/select.js +18 -1
  140. package/dist/routing/select.js.map +1 -1
  141. package/dist/session-management/files.d.ts.map +1 -1
  142. package/dist/session-management/files.js +9 -6
  143. package/dist/session-management/files.js.map +1 -1
  144. package/dist/sessions/history.d.ts.map +1 -1
  145. package/dist/sessions/history.js +12 -6
  146. package/dist/sessions/history.js.map +1 -1
  147. package/dist/spawning/store.d.ts.map +1 -1
  148. package/dist/spawning/store.js +10 -8
  149. package/dist/spawning/store.js.map +1 -1
  150. package/dist/tools.d.ts.map +1 -1
  151. package/dist/tools.js +5 -2
  152. package/dist/tools.js.map +1 -1
  153. package/dist/types.js +1 -1
  154. package/dist/ui/agent.d.ts.map +1 -1
  155. package/dist/ui/agent.js +3 -2
  156. package/dist/ui/agent.js.map +1 -1
  157. package/dist/ui/commands.d.ts.map +1 -1
  158. package/dist/ui/commands.js +20 -12
  159. package/dist/ui/commands.js.map +1 -1
  160. package/dist/ui/model-commands.d.ts.map +1 -1
  161. package/dist/ui/model-commands.js +3 -2
  162. package/dist/ui/model-commands.js.map +1 -1
  163. 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":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,MAAM,MAAM,cAAc,CAAC;AACvC,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,aAAa,EAA0E,MAAM,YAAY,CAAC;AA2BnH,SAAS,OAAO,CAAC,OAAe,IAAW,MAAM,IAAI,aAAa,CAAC,iBAAiB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;AAEjG,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,WAAW,CAAC,EAAU,EAAE,KAAa,EAAE,KAAc;IAC5D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,aAAa,EAAE,OAAO,KAAK,qCAAqC,CAAC,CAAC;IAC9J,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,6DAA6D,CAAC,CAAC;IAC7F,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC;QAAE,OAAO,CAAC,sCAAsC,CAAC,CAAC;IAChF,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,CAAC,6CAA6C,CAAC,CAAC;IAClH,MAAM,SAAS,GAAG,KAAK,CAAC,SAAqC,CAAC;IAC9D,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;QAC3C,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,OAAO,CAAC,aAAa,KAAK,qBAAqB,CAAC,CAAC;QACvE,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC;QAC1B,IAAI,OAAO,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC;YAAE,OAAO,CAAC,aAAa,KAAK,2BAA2B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;QACzI,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE;YAAE,OAAO,CAAC,kBAAkB,EAAE,mBAAmB,CAAC,CAAC;QAC/G,MAAM,QAAQ,GAAG,SAAS,CAAC,EAAE,CAAE,CAAC;QAChC,MAAM,SAAS,GAAI,CAAC,OAAO,EAAE,IAAI,EAAE,SAAS,CAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAAC;QAClG,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,kBAAkB,EAAE,8CAA8C,CAAC,CAAC;QACxG,MAAM,IAAI,GAAa,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC;QAC9D,IAAI,KAAK,CAAC,aAAa,KAAK,SAAS,EAAE,CAAC;YACtC,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM;gBAAE,OAAO,CAAC,kBAAkB,EAAE,yCAAyC,CAAC,CAAC;YACrG,IAAI,CAAC,aAAa,GAAG,WAAW,CAAC,EAAE,EAAE,eAAe,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC;QAC7E,CAAC;QACD,QAAQ,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;YACrB,KAAK,OAAO;gBACV,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM;oBAAE,OAAO,CAAC,kBAAkB,EAAE,wCAAwC,CAAC,CAAC;gBACpG,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;gBACnD,MAAM;YACR,KAAK,IAAI,EAAE,CAAC;gBACV,IAAI,QAAQ,CAAC,IAAI,KAAK,QAAQ;oBAAE,OAAO,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAC;gBACrG,IAAI,OAAO,KAAK,CAAC,EAAE,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;oBAAE,OAAO,CAAC,kBAAkB,EAAE,uCAAuC,CAAC,CAAC;gBACtJ,IAAI,CAAC,EAAE,GAAG,KAAK,CAAC,EAAE,CAAC;gBACnB,MAAM;YACR,CAAC;YACD,SAAS,CAAC;gBACR,IAAI,QAAQ,CAAC,IAAI,KAAK,OAAO;oBAAE,OAAO,CAAC,kBAAkB,EAAE,2CAA2C,CAAC,CAAC;gBACxG,MAAM,MAAM,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC;gBAC5C,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,IAAI,KAAK,CAAC,OAAO,GAAG,MAAM;oBAAE,OAAO,CAAC,kBAAkB,EAAE,sCAAsC,MAAM,GAAG,CAAC,CAAC;gBACtM,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;gBAC7B,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;AAC7B,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,YAAY,CAAC,KAAkB,EAAE,OAA+B;IAC9E,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACtC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,aAAa,CAAC,cAAc,EAAE,oCAAoC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;QAC5G,IAAI,IAAI,CAAC,aAAa,KAAK,SAAS,IAAI,YAAY,IAAI,MAAM,IAAI,MAAM,CAAC,UAAU,GAAG,IAAI,CAAC,aAAa;YAAE,SAAS;QACnH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,GAAG,IAAI,CAAC,KAAK;YAC3F,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,IAAI,CAAC,EAAE;gBACtD,CAAC,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,CAAC;QAC/D,IAAI,OAAO;YAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC;IACtE,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;AAC/B,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,sBAAsB,CAAC,KAAc;IACnD,IAAI,KAAK,KAAK,UAAU;QAAE,OAAO,UAAU,CAAC;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,KAAK,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,QAAQ,CAAC,KAAc,CAAC,CAAC;QACxG,OAAO,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACjE,OAAO,KAAuB,CAAC;AACjC,CAAC;AASD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAiB,EAAE,OAA6B;IAClF,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1F,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,CAAC,8CAA8C,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/J,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,EAAE,CAAC;AACtE,CAAC;AAYD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,SAAiB,EAAE,OAAO,GAAqB,EAAE;IACpF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IAClE,IAAI,CAAC;QACH,IAAI,QAAiB,CAAC;QACtB,IAAI,CAAC;YAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;QAAC,CAAC;QACvC,MAAM,CAAC;YAAC,OAAO,CAAC,mDAAmD,CAAC,CAAC;QAAC,CAAC;QACvE,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,aAAa,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnP,IAAI,OAAO,CAAC,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1M,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO;YAAE,OAAO,CAAC,CAAC;QAC3C,QAAQ,CAAC,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;QAChC,OAAO,CAAC,CAAC;IACX,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,aAAa,IAAI,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzG,QAAQ,CAAC,mCAAmC,OAAO,IAAI,CAAC,CAAC;QACzD,OAAO,CAAC,CAAC;IACX,CAAC;AACH,CAAC"}
@@ -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,9 @@
1
+ export class JudgmentError extends Error {
2
+ code;
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.code = code;
6
+ this.name = 'JudgmentError';
7
+ }
8
+ }
9
+ //# sourceMappingURL=types.js.map
@@ -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;AAyHD,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;AAydD;;;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"}
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"}
@@ -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-4-8', name: 'Claude Opus 4.8', description: 'Most capable model', contextLength: 1000000 },
392
- { id: 'claude-sonnet-4-6', name: 'Claude Sonnet 4.6', description: 'Balanced intelligence and speed', contextLength: 1000000 },
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) => b.id.localeCompare(a.id)); // Newest first
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
- .sort((a, b) => a.name.localeCompare(b.name));
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