@yss123/cage-ai 0.0.0-stage → 0.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 (81) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +77 -2
  3. package/dist/budget.d.ts +64 -0
  4. package/dist/budget.js +54 -0
  5. package/dist/budget.js.map +1 -0
  6. package/dist/context-read.d.ts +38 -0
  7. package/dist/context-read.js +124 -0
  8. package/dist/context-read.js.map +1 -0
  9. package/dist/context-schema.d.ts +9 -0
  10. package/dist/context-schema.js +16 -0
  11. package/dist/context-schema.js.map +1 -0
  12. package/dist/context.d.ts +27 -0
  13. package/dist/context.js +83 -0
  14. package/dist/context.js.map +1 -0
  15. package/dist/execution-schema.d.ts +9 -0
  16. package/dist/execution-schema.js +20 -0
  17. package/dist/execution-schema.js.map +1 -0
  18. package/dist/history.d.ts +43 -0
  19. package/dist/history.js +139 -0
  20. package/dist/history.js.map +1 -0
  21. package/dist/http.d.ts +15 -0
  22. package/dist/http.js +197 -0
  23. package/dist/http.js.map +1 -0
  24. package/dist/index.d.ts +33 -0
  25. package/dist/index.js +100 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/model-failure.d.ts +66 -0
  28. package/dist/model-failure.js +85 -0
  29. package/dist/model-failure.js.map +1 -0
  30. package/dist/model.d.ts +50 -0
  31. package/dist/model.js +93 -0
  32. package/dist/model.js.map +1 -0
  33. package/dist/models.d.ts +75 -0
  34. package/dist/models.js +241 -0
  35. package/dist/models.js.map +1 -0
  36. package/dist/personalities.d.ts +87 -0
  37. package/dist/personalities.js +191 -0
  38. package/dist/personalities.js.map +1 -0
  39. package/dist/personality-presets.d.ts +14 -0
  40. package/dist/personality-presets.js +24 -0
  41. package/dist/personality-presets.js.map +1 -0
  42. package/dist/prompt.d.ts +67 -0
  43. package/dist/prompt.js +148 -0
  44. package/dist/prompt.js.map +1 -0
  45. package/dist/query.d.ts +13 -0
  46. package/dist/query.js +82 -0
  47. package/dist/query.js.map +1 -0
  48. package/dist/request-plan.d.ts +59 -0
  49. package/dist/request-plan.js +168 -0
  50. package/dist/request-plan.js.map +1 -0
  51. package/dist/responses.d.ts +29 -0
  52. package/dist/responses.js +134 -0
  53. package/dist/responses.js.map +1 -0
  54. package/dist/runtime.d.ts +172 -0
  55. package/dist/runtime.js +1189 -0
  56. package/dist/runtime.js.map +1 -0
  57. package/dist/schema.d.ts +11 -0
  58. package/dist/schema.js +51 -0
  59. package/dist/schema.js.map +1 -0
  60. package/dist/security.d.ts +23 -0
  61. package/dist/security.js +73 -0
  62. package/dist/security.js.map +1 -0
  63. package/dist/state.d.ts +238 -0
  64. package/dist/state.js +11 -0
  65. package/dist/state.js.map +1 -0
  66. package/dist/store.d.ts +113 -0
  67. package/dist/store.js +456 -0
  68. package/dist/store.js.map +1 -0
  69. package/dist/text-stream.d.ts +62 -0
  70. package/dist/text-stream.js +99 -0
  71. package/dist/text-stream.js.map +1 -0
  72. package/dist/tool-catalog.d.ts +23 -0
  73. package/dist/tool-catalog.js +53 -0
  74. package/dist/tool-catalog.js.map +1 -0
  75. package/dist/tools.d.ts +54 -0
  76. package/dist/tools.js +259 -0
  77. package/dist/tools.js.map +1 -0
  78. package/dist/types.d.ts +283 -0
  79. package/dist/types.js +16 -0
  80. package/dist/types.js.map +1 -0
  81. package/package.json +41 -3
package/dist/query.js ADDED
@@ -0,0 +1,82 @@
1
+ /**
2
+ * 把模型提交的有限查询计划编译到已授权聚合的 safe 视图。
3
+ * 由助理查询工具调用,字段来自注册表、值使用参数绑定;不接受任意 SQL、关联表或隐藏字段,结果在审计成功后才交给模型。
4
+ */
5
+ import { cageError, snake, isRelation, canUnmask } from '@yss123/cage-kernel';
6
+ import { queryPlanSchema } from '@yss123/cage-ai-protocol';
7
+ import { sql } from 'kysely';
8
+ import { parse } from './security.js';
9
+ /** NL2Query 编译到有限查询计划;标识符来自注册表,值永远参数化,执行账号只能读 safe。 */
10
+ /**
11
+ * 验证查询计划与聚合 read 能力,并构造受限投影、过滤、排序和分组指标。
12
+ * 隐藏字段、关系和 JSON 不参与计划;对敏感字段做过滤/排序/汇总要求解掩码能力,sum/avg 仅支持数值字段。
13
+ * 在安全只读事务内设置 5 秒语句超时,取 limit+1 行判断截断;随后可靠写入用途审计,审计失败不交付已查询数据。
14
+ * 返回来源、前 limit 行与 truncated 标记;结果受当前租户/范围约束,不能把截断页当作完整统计。
15
+ */
16
+ export async function queryPlan(kernel, ctx, input) {
17
+ const plan = parse(queryPlanSchema, input), agg = kernel.registry.aggregate(plan.aggregate);
18
+ if (!agg || !ctx.capabilities.has(`${agg.name}.read`))
19
+ throw cageError('FORBIDDEN');
20
+ const system = { id: 'id', status: 'status', version: 'version', createdAt: 'created_at', updatedAt: 'updated_at' };
21
+ // 标识符只从系统字段和注册字段映射;对敏感值做过滤/排序/汇总可能泄漏信息,因此 operation 额外要求解掩码权。
22
+ const field = (name, operation = false) => {
23
+ if (Object.hasOwn(system, name))
24
+ return system[name];
25
+ const f = agg.fields[name];
26
+ if (!f || f.isHidden || isRelation(f) || f.sql === 'jsonb')
27
+ throw cageError('INVALID_INPUT', '字段不支持查询计划');
28
+ if (operation && f.sensitiveKind && !canUnmask(ctx, agg.name, f.sensitiveKind))
29
+ throw cageError('FORBIDDEN');
30
+ return snake(name);
31
+ };
32
+ if (plan.metrics.length && plan.select?.some(n => !plan.groupBy.includes(n)))
33
+ throw cageError('INVALID_INPUT', '汇总查询只能选择分组字段和指标');
34
+ if (plan.groupBy.length && !plan.metrics.length)
35
+ throw cageError('INVALID_INPUT', '分组必须包含指标');
36
+ const selected = plan.select ?? (plan.metrics.length ? plan.groupBy : ['id', 'status', 'version']);
37
+ const aliases = new Set(selected);
38
+ const projections = selected.map(n => sql.ref(field(n, plan.metrics.length > 0)).as(n));
39
+ for (const metric of plan.metrics) {
40
+ if (aliases.has(metric.as))
41
+ throw cageError('INVALID_INPUT', '指标名称重复');
42
+ aliases.add(metric.as);
43
+ const ref = metric.field ? sql.ref(field(metric.field, true)) : sql.raw('*');
44
+ if (metric.op !== 'count' && !metric.field)
45
+ throw cageError('INVALID_INPUT', '该指标需要字段');
46
+ if (['sum', 'avg'].includes(metric.op) && !['int', 'number', 'money'].includes(agg.fields[metric.field]?.kind))
47
+ throw cageError('INVALID_INPUT', '汇总需要数值字段');
48
+ const expr = metric.op === 'count' ? sql `count(${ref})` : metric.op === 'sum' ? sql `sum(${ref})` : metric.op === 'avg' ? sql `avg(${ref})` : metric.op === 'min' ? sql `min(${ref})` : sql `max(${ref})`;
49
+ projections.push(expr.as(metric.as));
50
+ }
51
+ if (!projections.length)
52
+ throw cageError('INVALID_INPUT', '必须选择字段或指标');
53
+ const rows = await kernel.read.tx(ctx, async (tx) => {
54
+ await sql `select set_config('statement_timeout', '5000', true)`.execute(tx);
55
+ let query = tx.selectFrom(`safe.${agg.table.name}`).select(projections).where('status', '<>', 'deleted');
56
+ const ops = { eq: '=', ne: '<>', gt: '>', gte: '>=', lt: '<', lte: '<=', in: 'in' };
57
+ for (const where of plan.where) {
58
+ const column = field(where.field, true), f = agg.fields[where.field];
59
+ const values = where.op === 'in' ? where.value : [where.value];
60
+ if (!Array.isArray(values) || !values.length || values.length > 100 || values.some(v => v === null || typeof v === 'object'))
61
+ throw cageError('INVALID_INPUT', '过滤值必须是有界标量');
62
+ if (f)
63
+ for (const value of values)
64
+ parse(f.base, value);
65
+ query = query.where(sql.ref(column), ops[where.op], where.value);
66
+ }
67
+ for (const group of plan.groupBy)
68
+ query = query.groupBy(sql.ref(field(group, true)));
69
+ if (plan.orderBy) {
70
+ if (plan.metrics.length && !aliases.has(plan.orderBy.field))
71
+ throw cageError('INVALID_INPUT', '只能按所选字段排序');
72
+ query = query.orderBy(sql.ref(plan.metrics.length && aliases.has(plan.orderBy.field) ? plan.orderBy.field : field(plan.orderBy.field, true)), plan.orderBy.direction);
73
+ }
74
+ return query.limit(plan.limit + 1).execute();
75
+ });
76
+ // 计划可能读取敏感明文;审计失败时不向模型交付结果。
77
+ await kernel.writeAudit(kernel.app, { tenantId: ctx.tenantId, actor: ctx.actor.id, actorKind: ctx.actor.kind, source: ctx.source,
78
+ kind: 'read', capability: `${agg.name}.read`, aggregate: agg.name, result: 'ok', requestId: ctx.requestId,
79
+ diff: { purpose: 'ai.queryPlan', fields: selected, metrics: plan.metrics, rows: rows.length } });
80
+ return { source: `aggregate:${agg.name}`, rows: rows.slice(0, plan.limit), truncated: rows.length > plan.limit, limit: plan.limit };
81
+ }
82
+ //# sourceMappingURL=query.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ import { type ModelBudget } from './budget.js';
2
+ import { type RemoteHistory, type ToolPlan } from './state.js';
3
+ import { type Tool } from './tools.js';
4
+ import type { AiContextOptions, Execution, ModelMessage, ModelProvider } from './types.js';
5
+ /**
6
+ * 可被运行时原子记录的单次模型请求计划。
7
+ * 所有字段来自同一 provider 和预算快照,避免请求参数、预留用量及后续工具加载使用不同配置。
8
+ */
9
+ export interface ModelPlan {
10
+ /**
11
+ * 最终模型消息,可能包含明确的上下文展开引用。
12
+ */
13
+ messages: ModelMessage[];
14
+ /**
15
+ * 本轮完整可执行工具对象;发送协议时只提取公开 schema。
16
+ */
17
+ tools: Tool[];
18
+ /**
19
+ * 实际装载的业务命令/查询本体 key,不包括基础工具。
20
+ */
21
+ keys: string[];
22
+ /**
23
+ * 本轮全量/发现模式及可复用的工具预算。
24
+ */
25
+ selection: ToolPlan;
26
+ /**
27
+ * 已核对配置键和历史游标的远端状态;null 表示本地重建。
28
+ */
29
+ remote: RemoteHistory | null;
30
+ /**
31
+ * 本轮输入加已知远端历史的 Token 估算值。
32
+ */
33
+ estimatedInput: number;
34
+ /**
35
+ * 不超过模型输出配置及本轮剩余累计预算的输出 Token 上限。
36
+ */
37
+ outputLimit: number;
38
+ /**
39
+ * 本次请求是否省略或缩小资料,需要向模型明示。
40
+ */
41
+ reduced: boolean;
42
+ /**
43
+ * 本次请求共用的窗口、累计消耗及工具容量快照。
44
+ */
45
+ budget: ModelBudget;
46
+ }
47
+ /** 只装配请求,不执行模型或更改状态。一次规划共享模型配置和预算快照。 */
48
+ /**
49
+ * 核验轮数、尝试次数及累计 Token 预算,再选择全量工具或助理发现模式。
50
+ * 有效远端接续先扣除已知历史成本,不能因为启用压缩就假定窗口变小;接续装不下时从本地历史重新规划。
51
+ * 审批不能降级为工具发现;当容量不足实际来自累计预算而非模型窗口时,映射为 AI_BUDGET_EXCEEDED,便于区分配置与本次运行耗尽。
52
+ */
53
+ export declare function planModelRequest(execution: Execution, provider: ModelProvider, options?: AiContextOptions): ModelPlan;
54
+ /** 搜索加载与显式加载共用同一容量规则;返回值与 tool_keys 在动作回执事务中一起保存。 */
55
+ /**
56
+ * 依据上轮已持久化的 tool_plan 装载搜索或显式请求的工具。
57
+ * 显式加载要求所有完整定义都装下,否则拒绝并提示减少数量;搜索加载允许预算内部分命中。返回的 keys 由调用方与动作回执同事务保存,不在此更改运行状态。
58
+ */
59
+ export declare function discoveredToolKeys(execution: Execution, requested: string[], explicit: boolean): string[];
@@ -0,0 +1,168 @@
1
+ /**
2
+ * 将运行快照、模型配置、授权工具和上下文预算组装为单次模型请求计划。
3
+ * 由运行时在发起外部请求前调用,发现工具也复用同一容量规则;这里只规划,不发网络请求、不修改运行记录,持久化由租约事务完成。
4
+ */
5
+ import { cageError } from '@yss123/cage-kernel';
6
+ import { modelBudget, checkModelBudget } from './budget.js';
7
+ import { SYSTEM_PROMPT, ONTOLOGY_PROMPT, DISCOVERY_PROMPT } from './context.js';
8
+ import { personalityPrompt } from './personalities.js';
9
+ import { packPrompt, toolTokens } from './prompt.js';
10
+ import { remoteHistory } from './state.js';
11
+ import { authorizedToolKeys, candidateToolKeys } from './tool-catalog.js';
12
+ import { toolsFor } from './tools.js';
13
+ /**
14
+ * 按运行模式组合系统指令。
15
+ * 审批仅加入节点策略与审核工具约束,不使用助理性格;助理加入本体发现、业务指令与表达资料,工具是否已全量加载决定发现提示。
16
+ */
17
+ function instructions(execution, discovery) {
18
+ const { run } = execution;
19
+ if (run.mode === 'approval')
20
+ return `${SYSTEM_PROMPT}\n仅使用本审批节点的审核策略、已声明查询和 review_decide;资料不足应继续取证或转人工。\n${run.instructions}`;
21
+ const toolGuide = discovery
22
+ ? DISCOVERY_PROMPT
23
+ : '本轮已装载当前主体可调用的全部业务命令和查询。需要系统规则仍应查询本体;不能编造未提供的工具。';
24
+ return [
25
+ SYSTEM_PROMPT,
26
+ ONTOLOGY_PROMPT,
27
+ toolGuide,
28
+ run.instructions,
29
+ run.personality ? personalityPrompt(run.personality) : '',
30
+ ].join('\n');
31
+ }
32
+ /**
33
+ * 按候选先后顺序去重并装入完整工具定义,分别约束数量与 Token。
34
+ * 基础工具本身放不下立即失败;单个候选过大则跳过继续尝试后续候选,不裁剪工具参数 schema。返回真正装载的 key 和工具列表。
35
+ */
36
+ function fitCandidates(base, business, candidates, selection) {
37
+ const tools = [...base], keys = [];
38
+ if (tools.length > selection.maxTools || toolTokens(tools) > selection.tokenBudget)
39
+ throw new Error('AI_CONTEXT_TOO_LARGE');
40
+ for (const key of new Set(candidates)) {
41
+ const tool = business.get(key);
42
+ if (!tool)
43
+ continue;
44
+ if (tools.length === selection.maxTools)
45
+ break;
46
+ if (toolTokens([...tools, tool]) > selection.tokenBudget)
47
+ continue;
48
+ tools.push(tool);
49
+ keys.push(key);
50
+ }
51
+ return { keys, tools };
52
+ }
53
+ /** 只装配请求,不执行模型或更改状态。一次规划共享模型配置和预算快照。 */
54
+ /**
55
+ * 核验轮数、尝试次数及累计 Token 预算,再选择全量工具或助理发现模式。
56
+ * 有效远端接续先扣除已知历史成本,不能因为启用压缩就假定窗口变小;接续装不下时从本地历史重新规划。
57
+ * 审批不能降级为工具发现;当容量不足实际来自累计预算而非模型窗口时,映射为 AI_BUDGET_EXCEEDED,便于区分配置与本次运行耗尽。
58
+ */
59
+ export function planModelRequest(execution, provider, options = {}) {
60
+ const { run } = execution;
61
+ const budget = modelBudget(provider, run.limits, run.tokens, options);
62
+ checkModelBudget(run.limits, run.steps, run.model_attempts, budget);
63
+ const key = provider.continuation?.key;
64
+ const remote = run.continuation_disabled_key === key ? null : remoteHistory(run.model_state, key, run.history.length);
65
+ const allKeys = run.mode === 'assistant' ? authorizedToolKeys(execution) : [];
66
+ const full = toolsFor(execution, { keys: allKeys, discovery: false });
67
+ // 单次装配可尝试远端接续或本地历史;两条路径共用已解析 provider 和预算,失败才切换,避免参数快照漂移。
68
+ function assemble(state) {
69
+ // 没有实际压缩结果的用量不能凭开关假定缩小。接续超预算时使用本地完整交互重新装配。
70
+ const chainTokens = state?.contextTokens ?? 0;
71
+ const inputLimit = budget.inputLimit - chainTokens;
72
+ if (run.mode === 'approval' && full.length > budget.maxTools)
73
+ throw new Error('AI_CONTEXT_TOO_LARGE');
74
+ const pack = (tools, discovery) => packPrompt({
75
+ instructions: instructions(execution, discovery),
76
+ context: run.context,
77
+ tools,
78
+ history: state ? run.history.slice(state.historyLength) : run.history,
79
+ historyOmitted: !state && run.history_omitted,
80
+ continuation: !!state,
81
+ stateKey: key,
82
+ maxInputTokens: inputLimit,
83
+ });
84
+ let keys = allKeys, tools = full;
85
+ const baseAll = full.filter((tool) => !tool.key);
86
+ const baselineAll = pack(baseAll, false);
87
+ const allAvailable = inputLimit - (baselineAll.estimatedInput - toolTokens(baseAll));
88
+ const defaultAllowance = Math.max(budget.toolTokens, toolTokens(baseAll));
89
+ let selection = {
90
+ mode: 'all',
91
+ tokenBudget: Math.min(options.maxToolTokens ?? defaultAllowance, allAvailable),
92
+ maxTools: budget.maxTools,
93
+ };
94
+ let packed;
95
+ if (run.mode === 'approval' || (full.length <= budget.maxTools && toolTokens(full) <= selection.tokenBudget)) {
96
+ try {
97
+ packed = pack(full, false);
98
+ }
99
+ catch (error) {
100
+ if (!(error instanceof Error) || error.message !== 'AI_CONTEXT_TOO_LARGE')
101
+ throw error;
102
+ }
103
+ }
104
+ if (!packed) {
105
+ if (run.mode === 'approval')
106
+ throw new Error('AI_CONTEXT_TOO_LARGE');
107
+ const base = toolsFor(execution, { keys: [], discovery: true });
108
+ const baseline = pack(base, true);
109
+ const available = inputLimit - (baseline.estimatedInput - toolTokens(base));
110
+ selection = {
111
+ mode: 'discovery',
112
+ tokenBudget: Math.min(options.maxToolTokens ?? Math.max(budget.toolTokens, toolTokens(base)), available),
113
+ maxTools: budget.maxTools,
114
+ };
115
+ const business = new Map(full.filter((tool) => tool.key).map((tool) => [tool.key, tool]));
116
+ ({ keys, tools } = fitCandidates(base, business, candidateToolKeys(execution), selection));
117
+ packed = pack(tools, true);
118
+ }
119
+ const estimatedInput = packed.estimatedInput + chainTokens;
120
+ return {
121
+ ...packed,
122
+ tools,
123
+ keys,
124
+ selection,
125
+ remote: state,
126
+ estimatedInput,
127
+ budget,
128
+ outputLimit: Math.min(budget.outputLimit, budget.remaining - estimatedInput),
129
+ };
130
+ }
131
+ try {
132
+ if (remote) {
133
+ try {
134
+ return assemble(remote);
135
+ }
136
+ catch (error) {
137
+ if (!(error instanceof Error) || error.message !== 'AI_CONTEXT_TOO_LARGE')
138
+ throw error;
139
+ }
140
+ }
141
+ return assemble(null);
142
+ }
143
+ catch (error) {
144
+ if (error instanceof Error &&
145
+ error.message === 'AI_CONTEXT_TOO_LARGE' &&
146
+ budget.inputLimit < budget.windowInputLimit)
147
+ throw new Error('AI_BUDGET_EXCEEDED');
148
+ throw error;
149
+ }
150
+ }
151
+ /** 搜索加载与显式加载共用同一容量规则;返回值与 tool_keys 在动作回执事务中一起保存。 */
152
+ /**
153
+ * 依据上轮已持久化的 tool_plan 装载搜索或显式请求的工具。
154
+ * 显式加载要求所有完整定义都装下,否则拒绝并提示减少数量;搜索加载允许预算内部分命中。返回的 keys 由调用方与动作回执同事务保存,不在此更改运行状态。
155
+ */
156
+ export function discoveredToolKeys(execution, requested, explicit) {
157
+ const selection = execution.run.tool_plan;
158
+ if (!selection)
159
+ throw cageError('CONFLICT', '工具预算尚未装配,请重新发起任务');
160
+ const full = toolsFor(execution, { keys: requested, discovery: false });
161
+ const business = new Map(full.filter((tool) => tool.key).map((tool) => [tool.key, tool]));
162
+ const base = toolsFor(execution, { keys: [], discovery: true });
163
+ const { keys } = fitCandidates(base, business, requested, selection);
164
+ if (explicit && keys.length !== requested.length)
165
+ throw cageError('INVALID_INPUT', '工具完整定义超出本轮上下文预算,请减少加载数量或配置更大的窗口');
166
+ return keys;
167
+ }
168
+ //# sourceMappingURL=request-plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-plan.js","sourceRoot":"","sources":["../src/request-plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ import { type ChatModelOptions } from './model.js';
2
+ import type { ModelProvider } from './types.js';
3
+ /**
4
+ * Responses 配置复用模型主机、凭据与窗口设置,并可显式启用厂商上下文压缩。
5
+ * 压缩是协议能力声明,不会自动验证网关支持;不启用自动截断来静默丢弃业务历史。
6
+ */
7
+ export interface ResponsesModelOptions extends ChatModelOptions {
8
+ /** 只在服务支持 context_management 时启用;不使用自动丢弃历史的 truncation。 */
9
+ compaction?: boolean;
10
+ }
11
+ /**
12
+ * 通知运行时从本地持久历史重建请求的内部异常。
13
+ * 仅用于尚未向用户输出文本的远端历史失效或网关不支持接续;它不是模型业务结论,也不是任意网络失败的重试许可。
14
+ */
15
+ export declare class ResponseHistoryExpired extends Error {
16
+ readonly reason: 'expired' | 'unsupported';
17
+ /**
18
+ * 创建接续失效信号;expired 允许以后继续使用有效远端历史,unsupported 由运行时记录该配置不支持接续。
19
+ */
20
+ constructor(reason?: 'expired' | 'unsupported');
21
+ }
22
+ /** Responses 与 Chat 共用连接器边界;接续 ID、工具回执和每次重发的指令由框架组装。 */
23
+ /**
24
+ * 构造 Responses provider;声明 spec 的摘要作为远端历史配置键。
25
+ * 每次请求重新发送系统指令,关闭自动 truncation,并显式使用非 strict 工具 schema 以保留合法可选参数。
26
+ * 只接受唯一 completed 终态,核对创建/结束响应 ID 和流式/最终文本;函数调用之外只保留 reasoning、compaction 项,其他工具类型拒绝执行。
27
+ * 404 或不支持 previous_response_id 且尚无文本时抛恢复信号;已有文本的失败直接上抛,避免静默重放造成重复输出。
28
+ */
29
+ export declare function responsesModel(name: string, options: ResponsesModelOptions): ModelProvider;
@@ -0,0 +1,134 @@
1
+ /**
2
+ * 适配 Responses 流式协议及远端会话接续。
3
+ * 与 Chat provider 共用连接器安全边界,保留同配置的 provider 原始输出以恢复推理/压缩项;远端历史不可用时向运行时发恢复信号,不直接重放业务工具。
4
+ */
5
+ import { connector, ConnectorError, stage, streamJson } from '@yss123/cage-connectors';
6
+ import { validateModelResult } from './model.js';
7
+ import { digest } from './security.js';
8
+ import { ModelResponseError, parseModelJson, providerErrorCode } from './model-failure.js';
9
+ /**
10
+ * 通知运行时从本地持久历史重建请求的内部异常。
11
+ * 仅用于尚未向用户输出文本的远端历史失效或网关不支持接续;它不是模型业务结论,也不是任意网络失败的重试许可。
12
+ */
13
+ export class ResponseHistoryExpired extends Error {
14
+ reason;
15
+ /**
16
+ * 创建接续失效信号;expired 允许以后继续使用有效远端历史,unsupported 由运行时记录该配置不支持接续。
17
+ */
18
+ constructor(reason = 'expired') {
19
+ super('RESPONSES_HISTORY_EXPIRED');
20
+ this.reason = reason;
21
+ }
22
+ }
23
+ /**
24
+ * 将统一消息映射为 Responses input 项。
25
+ * 系统指令由调用方单独重发;工具回执保留 call_id,只有 providerItems 的配置 key 相等时才复用原始项,防止不同模型配置的私有状态混用。
26
+ */
27
+ function inputItems(messages, key) {
28
+ const items = [];
29
+ for (const message of messages) {
30
+ if (message.role === 'system')
31
+ continue;
32
+ if (message.role === 'tool')
33
+ items.push({ type: 'function_call_output', call_id: message.toolCallId, output: message.content });
34
+ else if (message.role === 'assistant' && message.providerItems && message.providerItems.key === key)
35
+ items.push(...message.providerItems.items);
36
+ else {
37
+ if (message.content)
38
+ items.push({ role: message.role, content: message.content });
39
+ for (const call of message.toolCalls ?? [])
40
+ items.push({ type: 'function_call', call_id: call.id, name: call.name, arguments: JSON.stringify(call.arguments) });
41
+ }
42
+ }
43
+ return items;
44
+ }
45
+ /** Responses 与 Chat 共用连接器边界;接续 ID、工具回执和每次重发的指令由框架组装。 */
46
+ /**
47
+ * 构造 Responses provider;声明 spec 的摘要作为远端历史配置键。
48
+ * 每次请求重新发送系统指令,关闭自动 truncation,并显式使用非 strict 工具 schema 以保留合法可选参数。
49
+ * 只接受唯一 completed 终态,核对创建/结束响应 ID 和流式/最终文本;函数调用之外只保留 reasoning、compaction 项,其他工具类型拒绝执行。
50
+ * 404 或不支持 previous_response_id 且尚无文本时抛恢复信号;已有文本的失败直接上抛,避免静默重放造成重复输出。
51
+ */
52
+ export function responsesModel(name, options) {
53
+ const transport = connector(name, { hosts: options.hosts, secret: options.secret, timeoutMs: options.timeoutMs ?? 90_000,
54
+ rateLimit: options.rateLimit, operations: {} });
55
+ const path = options.path ?? '/v1/responses', window = options.contextWindowTokens ?? 32768;
56
+ const spec = { kind: 'responses', name, model: options.model, hosts: options.hosts, secret: options.secret, path,
57
+ timeoutMs: transport.timeoutMs, environment: options.environment, protocol: options.protocol, contextWindowTokens: window, compaction: !!options.compaction };
58
+ const key = digest(spec);
59
+ return { spec, contextWindowTokens: window, continuation: { key, compaction: !!options.compaction },
60
+ async generate(request) {
61
+ const environment = options.environment ?? stage();
62
+ if (environment === 'fake') {
63
+ if (!options.fake)
64
+ throw new Error('模型未配置 fake;真实联调需显式选择 test/prod 阶段');
65
+ return validateModelResult(await options.fake(request));
66
+ }
67
+ let final, streamed = '', responseId;
68
+ const body = { model: options.model, stream: true, store: true, truncation: 'disabled', max_output_tokens: request.maxOutputTokens,
69
+ include: ['reasoning.encrypted_content'],
70
+ instructions: request.messages.filter(m => m.role === 'system').map(m => m.content).join('\n\n'),
71
+ input: inputItems(request.messages, request.stateKey ?? key),
72
+ ...(request.previousResponseId ? { previous_response_id: request.previousResponseId } : {}),
73
+ ...(options.compaction ? { context_management: [{ type: 'compaction', compact_threshold: Math.floor(window * .6) }] } : {}),
74
+ // Cage 输入存在合法可选字段;不能让 Responses 默认 strict 转换将其变成必填。
75
+ ...(request.tools.length ? { tools: request.tools.map(t => ({ type: 'function', name: t.name, description: t.description, parameters: t.input, strict: false })) } : {}),
76
+ };
77
+ try {
78
+ await streamJson(transport, path, body, request.signal, async (data) => {
79
+ if (data === '[DONE]')
80
+ return;
81
+ const event = parseModelJson(data, 'invalid_json');
82
+ if (!event || typeof event !== 'object')
83
+ throw new ModelResponseError('invalid_output');
84
+ if (['error', 'response.failed', 'response.incomplete'].includes(event.type)) {
85
+ const stopReason = providerErrorCode(event.response?.incomplete_details?.reason);
86
+ const reason = event.type === 'response.incomplete'
87
+ ? stopReason === 'max_output_tokens' ? 'output_limit' : 'incomplete' : 'provider_error';
88
+ throw new ModelResponseError(reason, { stopReason, providerCode: providerErrorCode(event.code ?? event.error?.code ?? event.response?.error?.code) });
89
+ }
90
+ if (event.type === 'response.created')
91
+ responseId = event.response?.id;
92
+ if (event.type === 'response.output_text.delta' && typeof event.delta === 'string') {
93
+ streamed += event.delta;
94
+ await request.onText?.(event.delta);
95
+ }
96
+ if (event.type === 'response.completed') {
97
+ if (final || event.response?.status !== 'completed')
98
+ throw new ModelResponseError('invalid_terminal');
99
+ final = event.response;
100
+ }
101
+ }, { environment, protocol: options.protocol, credential: options.credential });
102
+ }
103
+ catch (error) {
104
+ // 缺失的远端会话可从本地记录恢复;有文本输出的失败不能重放而产生重复流。
105
+ const unavailable = error instanceof ConnectorError && (error.status === 404 || error.providerCode === 'PREVIOUS_RESPONSE_ID_UNSUPPORTED');
106
+ if (request.previousResponseId && !streamed && unavailable)
107
+ throw new ResponseHistoryExpired(error instanceof ConnectorError && error.providerCode === 'PREVIOUS_RESPONSE_ID_UNSUPPORTED' ? 'unsupported' : 'expired');
108
+ throw error;
109
+ }
110
+ if (!final || !Array.isArray(final.output) || !final.id || (responseId && responseId !== final.id))
111
+ throw new ModelResponseError('incomplete');
112
+ let text = '';
113
+ const calls = [];
114
+ for (const item of final.output) {
115
+ if (item.type === 'message') {
116
+ for (const content of item.content ?? [])
117
+ if (content.type === 'output_text')
118
+ text += content.text;
119
+ else if (content.type === 'refusal')
120
+ text += content.refusal;
121
+ }
122
+ else if (item.type === 'function_call')
123
+ calls.push({ id: item.call_id, name: item.name, arguments: parseModelJson(item.arguments, 'invalid_arguments') });
124
+ else if (!['reasoning', 'compaction'].includes(item.type))
125
+ throw new ModelResponseError('unexpected_tool');
126
+ }
127
+ if (streamed && streamed !== text)
128
+ throw new ModelResponseError('text_mismatch');
129
+ return validateModelResult({ text, calls, responseId: final.id, outputItems: final.output,
130
+ ...(final.usage ? { usage: { inputTokens: final.usage.input_tokens, outputTokens: final.usage.output_tokens } } : {}) });
131
+ },
132
+ };
133
+ }
134
+ //# sourceMappingURL=responses.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"responses.js","sourceRoot":"","sources":["../src/responses.ts"],"names":[],"mappings":"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"}