@kanyun-ai-infra/agenthub 1.14.0 → 1.15.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/CHANGELOG.md +31 -0
- package/dist/index.cjs +170 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -7
- package/dist/index.d.ts +37 -7
- package/dist/index.js +170 -17
- package/dist/index.js.map +1 -1
- package/dist/realtime.cjs +89 -2
- package/dist/realtime.cjs.map +1 -1
- package/dist/realtime.d.cts +50 -0
- package/dist/realtime.d.ts +50 -0
- package/dist/realtime.js +89 -2
- package/dist/realtime.js.map +1 -1
- package/package.json +1 -1
- package/skills/agenthub-sdk/SKILL.md +168 -26
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,37 @@
|
|
|
2
2
|
|
|
3
3
|
本文件从 1.12.0 开始记录;更早的版本见 git 历史中的 `chore(agenthub-sdk): release X.Y.Z` 提交。
|
|
4
4
|
|
|
5
|
+
## 1.15.0
|
|
6
|
+
|
|
7
|
+
浏览器实时语音入口新增播放对齐、页面工具执行与播放输出节点;其余为随共享契约内联的变化。
|
|
8
|
+
|
|
9
|
+
### 新增(`@kanyun-ai-infra/agenthub/realtime`)
|
|
10
|
+
|
|
11
|
+
- `onTranscriptPlayed(transcript)`:assistant 转写片段在音频实际播放到该片段时逐段触发,载荷带墙钟 `playedAt`。依赖网关在转写帧上带 `audioOffsetMs`;没有偏移的旧网关不触发此回调,被用户打断清空的片段也不触发。
|
|
12
|
+
- `onPlaybackState(state)`:`speaking` / `listening`,按实际可闻的播放状态触发,与按模型生成进度的 `onState` 区分。队列播干、播放被打断或通话停止时回到 `listening`。
|
|
13
|
+
- `onTranscript` 的 assistant 帧新增可选 `audioOffsetMs`:该片段在本轮音频中的起始毫秒数,用于把字幕或画面切到正在播放的位置。
|
|
14
|
+
- `onToolCall(call)`:执行 `voice.realtime.tools` 声明的模型工具调用;`call` 含 `callId`、`name`、`args`,可选 `turnSeq`。返回值作为工具结果回传(JSON,至多 32 KiB)。未提供处理函数回 `tool_unavailable`,处理函数抛错回 `tool_failed`,结果超限回 `tool_result_too_large`;页面不答时网关 10 秒后自行以 `tool_timeout` 答复,不会把模型卡死。
|
|
15
|
+
- `outputNode(context)`:把播放输出接到页面自建的音频节点(如变调等后处理),由页面继续接到 `context.destination`。缺省直连输出。
|
|
16
|
+
- 新导出类型:`RealtimeTranscriptPlayed`、`RealtimePlaybackState`、`RealtimeToolCall`。
|
|
17
|
+
|
|
18
|
+
### 随共享契约内联的变化
|
|
19
|
+
|
|
20
|
+
- agent 定义的 `voice.realtime` 新增可选 `tools`(1–16 个):每项含 `name`(匹配 `^[A-Za-z_][A-Za-z0-9_]{0,63}$`,重名拒绝)、`description`(1–1024 字符)与可选 `parameters`(JSON Schema 子集,嵌套至多 6 层、节点至多 128、序列化至多 8 KiB)。`publishVersion` / `applyManifest` 的本地校验接受该字段;不声明时行为不变。
|
|
21
|
+
- `voice.realtime` 新增可选 `greetOnConnect`:开启时网关在首通建立上游会话后替 agent 发一次初始文本回合,模型按 system prompt 主动开口;缺省或 `false` 关闭,只对首通生效,重连与接手不重发。
|
|
22
|
+
|
|
23
|
+
### 会话
|
|
24
|
+
|
|
25
|
+
- `sessions.create` 带 `memorySubjects` 的请求现在可以领取预热池:声明的业务主体替换池模板铸出的主体;`idempotencyScope` / `idempotencyKey` 与 `memorySubjects` 不再使请求失去领取资格。本次只有注释与文档变化,领取行为由服务端决定;服务端未升级时请求仍照旧冷启。
|
|
26
|
+
|
|
27
|
+
### 其他
|
|
28
|
+
|
|
29
|
+
- 语音开关的文档措辞改为 kill switch `voice_turns_disabled`(及同类 `*_DISABLED`),公开方法签名不变。
|
|
30
|
+
- 随包 `SKILL.md` 补充实时语音接入走查。
|
|
31
|
+
|
|
32
|
+
### 迁移说明
|
|
33
|
+
|
|
34
|
+
- 使用 `onTranscriptPlayed`、`onPlaybackState`、`onToolCall` 或 `outputNode` 的接入方须升级到 `@kanyun-ai-infra/agenthub@1.15.0`。1.14.0 没有这些回调;旧 SDK 在声明工具的 agent 上会忽略 `tool_call`,模型要等网关 10 秒超时答复后才继续。
|
|
35
|
+
|
|
5
36
|
## 1.14.0
|
|
6
37
|
|
|
7
38
|
### 随共享契约内联的语音变化
|
package/dist/index.cjs
CHANGED
|
@@ -3576,6 +3576,9 @@ var CreateSessionRequestSchema = import_zod10.z.object({
|
|
|
3576
3576
|
*
|
|
3577
3577
|
* 解析只发生一次、在会话创建事务内,结果冻结进 `sessions.memory_subjects`;写侧
|
|
3578
3578
|
* (抽取写回)与读侧(召回)之后都只读那一列(I7 写读同源)。
|
|
3579
|
+
*
|
|
3580
|
+
* 带它的请求**照样能领预热池**:领取收尾在同一条 UPDATE 里按这份声明重算冻结列(替换池模板
|
|
3581
|
+
* 铸的业务主体,`[]` = 只剩 agent 主体);绑不进去就退冷启,不会交出没有声明主体的会话。
|
|
3579
3582
|
*/
|
|
3580
3583
|
memorySubjects: import_zod10.z.array(SessionMemorySubjectDeclarationSchema).max(MAX_SESSION_MEMORY_SUBJECTS).optional(),
|
|
3581
3584
|
/**
|
|
@@ -3596,8 +3599,9 @@ var CreateSessionRequestSchema = import_zod10.z.object({
|
|
|
3596
3599
|
* `PILOT_END_USER_ID`、记忆主体(见下)、create 响应 `data.session.user`。
|
|
3597
3600
|
*
|
|
3598
3601
|
* **带它不吃池**:请求携带本字段即退出预热领用资格
|
|
3599
|
-
* (`canServeFromPrewarmPool
|
|
3600
|
-
*
|
|
3602
|
+
* (`canServeFromPrewarmPool`)——池里暖好的会话在调用方出现之前就冻结了身份,领用时
|
|
3603
|
+
* 换不掉。已知访客换 agent 应冷启带既有 id。(`memorySubjects` 不受这条限制:它在领取
|
|
3604
|
+
* 收尾时绑定,见该字段。)
|
|
3601
3605
|
*
|
|
3602
3606
|
* **不隐含记忆声明**:本字段本身不使这个 id 成为任何记忆主体;要让记忆落到它
|
|
3603
3607
|
* 名下,冷启路径须同时在 `memorySubjects` 里声明它(池路径由
|
|
@@ -4160,7 +4164,8 @@ var WorkloadManifestErrorCodeSchema = import_zod4.z.enum([
|
|
|
4160
4164
|
// `statusForManifestError`. Additive widening = patch (see
|
|
4161
4165
|
// `WORKLOAD_SLUG_TAKEN` above).
|
|
4162
4166
|
// - `LIVE_AGENTS_DISABLED` — the Revision's snapshot is `format: live` while
|
|
4163
|
-
// `
|
|
4167
|
+
// the kill switch `live_agents_disabled` is on (before #5069: `live_agents_enabled`
|
|
4168
|
+
// off). Same criterion as before; it used to throw
|
|
4164
4169
|
// the generic `MANIFEST_VALIDATION_ERROR`. Pipeline join reports the same
|
|
4165
4170
|
// condition earlier as `FILE_AGENT_LIVE_DISABLED`.
|
|
4166
4171
|
// - `LIVE_REVISION_UNSUPPORTED` — the merged, frozen live snapshot carries a
|
|
@@ -4515,7 +4520,79 @@ var RealtimeVoiceNameSchema = import_zod4.z.enum([
|
|
|
4515
4520
|
"Sadaltager",
|
|
4516
4521
|
"Sulafat"
|
|
4517
4522
|
]);
|
|
4518
|
-
var
|
|
4523
|
+
var RealtimeToolParameterSchema = import_zod4.z.lazy(
|
|
4524
|
+
() => import_zod4.z.object({
|
|
4525
|
+
type: import_zod4.z.enum(["string", "number", "integer", "boolean", "array", "object"]).optional(),
|
|
4526
|
+
description: import_zod4.z.string().max(1024).optional(),
|
|
4527
|
+
enum: import_zod4.z.array(import_zod4.z.string().max(256)).max(64).optional(),
|
|
4528
|
+
nullable: import_zod4.z.boolean().optional(),
|
|
4529
|
+
items: RealtimeToolParameterSchema.optional(),
|
|
4530
|
+
properties: import_zod4.z.record(import_zod4.z.string().max(64), RealtimeToolParameterSchema).optional(),
|
|
4531
|
+
required: import_zod4.z.array(import_zod4.z.string().max(64)).max(32).optional()
|
|
4532
|
+
}).strict()
|
|
4533
|
+
);
|
|
4534
|
+
function toolParameterProblem(parameters) {
|
|
4535
|
+
if (parameters === void 0) return void 0;
|
|
4536
|
+
let nodes = 0;
|
|
4537
|
+
let problem;
|
|
4538
|
+
const visit = (node, depth) => {
|
|
4539
|
+
var _a, _b;
|
|
4540
|
+
if (problem !== void 0) return;
|
|
4541
|
+
nodes += 1;
|
|
4542
|
+
if (depth > 6) {
|
|
4543
|
+
problem = "tool parameters nest deeper than 6 levels";
|
|
4544
|
+
return;
|
|
4545
|
+
}
|
|
4546
|
+
if (nodes > 128) {
|
|
4547
|
+
problem = "tool parameters contain more than 128 nodes";
|
|
4548
|
+
return;
|
|
4549
|
+
}
|
|
4550
|
+
if (node.type === "array" && node.items === void 0) {
|
|
4551
|
+
problem = "an array parameter must declare items";
|
|
4552
|
+
return;
|
|
4553
|
+
}
|
|
4554
|
+
if (node.required !== void 0) {
|
|
4555
|
+
const declared = new Set(Object.keys((_a = node.properties) != null ? _a : {}));
|
|
4556
|
+
const missing = node.required.find((name) => !declared.has(name));
|
|
4557
|
+
if (missing !== void 0) {
|
|
4558
|
+
problem = `required parameter ${missing} is not declared in properties`;
|
|
4559
|
+
return;
|
|
4560
|
+
}
|
|
4561
|
+
}
|
|
4562
|
+
for (const child of Object.values((_b = node.properties) != null ? _b : {})) visit(child, depth + 1);
|
|
4563
|
+
if (node.items !== void 0) visit(node.items, depth + 1);
|
|
4564
|
+
};
|
|
4565
|
+
visit(parameters, 1);
|
|
4566
|
+
if (problem !== void 0) return problem;
|
|
4567
|
+
if (new TextEncoder().encode(JSON.stringify(parameters)).length > 8192)
|
|
4568
|
+
return "tool parameters exceed 8192 bytes";
|
|
4569
|
+
return void 0;
|
|
4570
|
+
}
|
|
4571
|
+
var WORKLOAD_MANIFEST_REALTIME_TOOLS_MAX_LENGTH = 16;
|
|
4572
|
+
var WorkloadManifestRealtimeToolSchema = import_zod4.z.object({
|
|
4573
|
+
name: import_zod4.z.string().regex(
|
|
4574
|
+
/^[A-Za-z_][A-Za-z0-9_]{0,63}$/,
|
|
4575
|
+
"tool name must be an identifier of at most 64 chars"
|
|
4576
|
+
),
|
|
4577
|
+
description: import_zod4.z.string().min(1).max(1024),
|
|
4578
|
+
parameters: RealtimeToolParameterSchema.optional()
|
|
4579
|
+
}).strict();
|
|
4580
|
+
var WorkloadManifestRealtimeToolListSchema = import_zod4.z.array(WorkloadManifestRealtimeToolSchema).min(1).max(WORKLOAD_MANIFEST_REALTIME_TOOLS_MAX_LENGTH).superRefine((tools, ctx) => {
|
|
4581
|
+
const names = /* @__PURE__ */ new Set();
|
|
4582
|
+
for (const [index, tool] of tools.entries()) {
|
|
4583
|
+
if (names.has(tool.name))
|
|
4584
|
+
ctx.addIssue({
|
|
4585
|
+
code: "custom",
|
|
4586
|
+
path: [index, "name"],
|
|
4587
|
+
message: "tool names must be unique"
|
|
4588
|
+
});
|
|
4589
|
+
names.add(tool.name);
|
|
4590
|
+
const problem = toolParameterProblem(tool.parameters);
|
|
4591
|
+
if (problem !== void 0)
|
|
4592
|
+
ctx.addIssue({ code: "custom", path: [index, "parameters"], message: problem });
|
|
4593
|
+
}
|
|
4594
|
+
});
|
|
4595
|
+
var RealtimeVoiceWireSchema = import_zod4.z.object({
|
|
4519
4596
|
provider: import_zod4.z.literal("vertex-gemini-live"),
|
|
4520
4597
|
model: import_zod4.z.enum(["gemini-3.8-live", "gemini-live-2.5-flash-native-audio"]),
|
|
4521
4598
|
voice: RealtimeVoiceNameSchema,
|
|
@@ -4526,7 +4603,20 @@ var WorkloadManifestRealtimeVoiceSchema = import_zod4.z.object({
|
|
|
4526
4603
|
return false;
|
|
4527
4604
|
}
|
|
4528
4605
|
}, "language must be a BCP-47 language tag").optional(),
|
|
4529
|
-
turnDetection: import_zod4.z.object({ silenceMs: import_zod4.z.number().int().positive() }).strict().optional()
|
|
4606
|
+
turnDetection: import_zod4.z.object({ silenceMs: import_zod4.z.number().int().positive() }).strict().optional(),
|
|
4607
|
+
/**
|
|
4608
|
+
* 接通即开讲(#5221):开启时网关在通话首次建立上游会话后替 agent 发一次初始文本回合,
|
|
4609
|
+
* 模型按 system prompt 主动开口。缺省 / `false` 关闭,行为与声明前一致。只对首通生效:
|
|
4610
|
+
* 上游重连与带原 callId 的接手不重发。
|
|
4611
|
+
*/
|
|
4612
|
+
greetOnConnect: import_zod4.z.boolean().optional()
|
|
4613
|
+
}).strict();
|
|
4614
|
+
var WorkloadManifestRealtimeVoiceSchema = RealtimeVoiceWireSchema.extend({
|
|
4615
|
+
/**
|
|
4616
|
+
* Declared client tools. Optional and absent by default: an agent without it behaves exactly
|
|
4617
|
+
* as before, and the claim to an older gateway carries no tools key at all.
|
|
4618
|
+
*/
|
|
4619
|
+
tools: WorkloadManifestRealtimeToolListSchema.optional()
|
|
4530
4620
|
}).strict();
|
|
4531
4621
|
var WorkloadManifestVoiceSchema = import_zod4.z.object({
|
|
4532
4622
|
realtime: WorkloadManifestRealtimeVoiceSchema.optional(),
|
|
@@ -8884,6 +8974,20 @@ var EnvironmentRepointRecordSchema = import_zod59.z.object({
|
|
|
8884
8974
|
actor: import_zod59.z.string().nullable(),
|
|
8885
8975
|
createdAt: import_zod59.z.coerce.date()
|
|
8886
8976
|
}).strict();
|
|
8977
|
+
var EnvironmentExecutorWarningRevisionSchema = import_zod59.z.object({
|
|
8978
|
+
revisionId: import_zod59.z.string().uuid(),
|
|
8979
|
+
/** Which pointer of the slot carries the Revision. */
|
|
8980
|
+
arm: import_zod59.z.enum(["stable", "canary"]),
|
|
8981
|
+
format: import_zod59.z.string(),
|
|
8982
|
+
protocolVersion: import_zod59.z.string(),
|
|
8983
|
+
/** `absent` = judged as ENVCAP-3 (no readable declaration for the image). */
|
|
8984
|
+
declaration: import_zod59.z.enum(["absent", "present"]),
|
|
8985
|
+
/** Where the judged image came from; `kind` discriminates the remaining keys. */
|
|
8986
|
+
capabilitySource: import_zod59.z.object({ kind: import_zod59.z.string() }).passthrough()
|
|
8987
|
+
}).strict();
|
|
8988
|
+
var EnvironmentExecutorWarningSchema = import_zod59.z.object({
|
|
8989
|
+
revisions: import_zod59.z.array(EnvironmentExecutorWarningRevisionSchema).min(1)
|
|
8990
|
+
}).strict();
|
|
8887
8991
|
var EnvironmentReferenceSchema = import_zod59.z.object({
|
|
8888
8992
|
workloadId: import_zod59.z.string().uuid(),
|
|
8889
8993
|
workloadSlug: import_zod59.z.string(),
|
|
@@ -9691,7 +9795,7 @@ var VOICE_ERROR_CODES = {
|
|
|
9691
9795
|
REALTIME_CAPACITY_EXCEEDED: 409,
|
|
9692
9796
|
/** The platform concurrency store (realtime Redis) is unavailable; retry. */
|
|
9693
9797
|
REALTIME_ADMISSION_UNAVAILABLE: 503,
|
|
9694
|
-
/** `
|
|
9798
|
+
/** 紧急关闭 `voice_turns_disabled` 打开时任何语音回合派发被拒(VT-1)。 */
|
|
9695
9799
|
VOICE_TURNS_DISABLED: 400,
|
|
9696
9800
|
/** 语音附件时长 >60 秒或大小 >2MB(VA-3,上限只在语音路径)。 */
|
|
9697
9801
|
VOICE_INPUT_TOO_LONG: 400,
|
|
@@ -11617,8 +11721,10 @@ var EvalTriggerSchema = import_zod82.z.enum([
|
|
|
11617
11721
|
]);
|
|
11618
11722
|
var EvalSeveritySchema = import_zod82.z.enum(["gate", "soft"]);
|
|
11619
11723
|
var EvalGraderTypeSchema = import_zod82.z.enum(["transcript", "file", "llm", "script", "reply"]);
|
|
11724
|
+
var EvalLlmToolsSchema = import_zod82.z.enum(["full", "calls", "none"]);
|
|
11620
11725
|
var EvalPassPolicySchema = import_zod82.z.enum(["all", "any"]);
|
|
11621
11726
|
var EvalSuitePurposeSchema = import_zod82.z.enum(["regression", "capability"]);
|
|
11727
|
+
var EvalSuiteGateDowngradeSchema = import_zod82.z.enum(["allow", "never"]);
|
|
11622
11728
|
var EVAL_SKIP_REASON_MAX = 2048;
|
|
11623
11729
|
var EvalSuiteSkipSchema = import_zod82.z.object({ reason: import_zod82.z.string().min(1).max(EVAL_SKIP_REASON_MAX) }).strict();
|
|
11624
11730
|
var EvalSkippedSuiteSchema = import_zod82.z.object({ path: import_zod82.z.string().min(1), reason: import_zod82.z.string().min(1) }).strict();
|
|
@@ -11687,6 +11793,10 @@ var EvalFileShorthandExpectSchema = import_zod82.z.object({
|
|
|
11687
11793
|
matches: import_zod82.z.string().optional()
|
|
11688
11794
|
// 正则字符串
|
|
11689
11795
|
}).strict();
|
|
11796
|
+
var EvalFileToolSourceSchema = import_zod82.z.object({
|
|
11797
|
+
name: import_zod82.z.string().min(1),
|
|
11798
|
+
part: import_zod82.z.enum(["input", "output", "both"]).optional()
|
|
11799
|
+
}).strict();
|
|
11690
11800
|
var EvalFileGraderSchema = import_zod82.z.object({
|
|
11691
11801
|
type: import_zod82.z.literal("file"),
|
|
11692
11802
|
label: EvalGraderLabelSchema,
|
|
@@ -11696,7 +11806,12 @@ var EvalFileGraderSchema = import_zod82.z.object({
|
|
|
11696
11806
|
files: import_zod82.z.array(EvalFileEntrySchema).min(1).optional(),
|
|
11697
11807
|
// 简写形式
|
|
11698
11808
|
path: EvalRelativePathSchema.optional(),
|
|
11699
|
-
expect: EvalFileShorthandExpectSchema.optional()
|
|
11809
|
+
expect: EvalFileShorthandExpectSchema.optional(),
|
|
11810
|
+
/**
|
|
11811
|
+
* #5215:内容来源 = 工具产物而非工作区文件。与 `path` / `files` 恰用其一,
|
|
11812
|
+
* 且必须搭配 `expect`(suite 级 superRefine 校验)。
|
|
11813
|
+
*/
|
|
11814
|
+
tool: EvalFileToolSourceSchema.optional()
|
|
11700
11815
|
}).strict();
|
|
11701
11816
|
var EvalLlmGraderSchema = import_zod82.z.object({
|
|
11702
11817
|
type: import_zod82.z.literal("llm"),
|
|
@@ -11708,6 +11823,14 @@ var EvalLlmGraderSchema = import_zod82.z.object({
|
|
|
11708
11823
|
}),
|
|
11709
11824
|
dimensions: import_zod82.z.array(import_zod82.z.string().min(1)).optional(),
|
|
11710
11825
|
threshold: import_zod82.z.number().min(0).max(1),
|
|
11826
|
+
/**
|
|
11827
|
+
* #5215:判官材料是否带工具调用。缺省 `none`(只判回复文本,与既有 suite 的
|
|
11828
|
+
* 判分材料逐字节一致)。optional 字段叠加为增量变更、不升 apiVersion;老
|
|
11829
|
+
* worker 会以 `Unrecognized key` strict 拒(发布次序 = control-worker 先行)。
|
|
11830
|
+
* 工具段改变判分输入,但声明值在 case 对象里、进 `case_definition_digest`,
|
|
11831
|
+
* 因此不升 `engineVersion`(换值即换基线桶,不靠 engineVersion 区分)。
|
|
11832
|
+
*/
|
|
11833
|
+
tools: EvalLlmToolsSchema.optional(),
|
|
11711
11834
|
// 上界对齐 eval_grader_results.grader_version(PG int4,B1 硬列):graderVersion
|
|
11712
11835
|
// 是**作者可写**的单调整数,时间戳当版本号(Date.now() ≈ 1.7e12)一次就越界——
|
|
11713
11836
|
// 越界在解析期 400 告知作者,而不是等写明细行时 22003 连累父行回滚、整个 run
|
|
@@ -11754,12 +11877,17 @@ var EvalScriptGraderSchema = import_zod82.z.object({
|
|
|
11754
11877
|
expect: EvalScriptExpectSchema.optional()
|
|
11755
11878
|
}).strict();
|
|
11756
11879
|
var EvalReplyExpectSchema = import_zod82.z.object({
|
|
11880
|
+
/** 字面子串,不是正则。 */
|
|
11757
11881
|
includes: import_zod82.z.string().min(1).optional(),
|
|
11882
|
+
/** 字面子串,不是正则;「不许出现某段话」的确定写法见 `notMatches`。 */
|
|
11758
11883
|
excludes: import_zod82.z.string().min(1).optional(),
|
|
11759
11884
|
equals: import_zod82.z.string().optional(),
|
|
11760
11885
|
// 正则字符串;无效正则不在 schema 层拒——按 file grader 的 safeRegex 姿势在
|
|
11761
11886
|
// 判分侧判"不匹配",交给断言侧报 failed(不 errored)。
|
|
11762
|
-
matches: import_zod82.z.string().min(1).optional()
|
|
11887
|
+
matches: import_zod82.z.string().min(1).optional(),
|
|
11888
|
+
// 正则字符串,不允许匹配(`excludes` 的正则版)。无效正则**判 failed**而不是
|
|
11889
|
+
// passed:编译不出来时「没有匹配」是假的,绝不能因此绿灯(#5209)。
|
|
11890
|
+
notMatches: import_zod82.z.string().min(1).optional()
|
|
11763
11891
|
}).strict();
|
|
11764
11892
|
var EvalReplyGraderSchema = import_zod82.z.object({
|
|
11765
11893
|
type: import_zod82.z.literal("reply"),
|
|
@@ -12003,12 +12131,28 @@ var EvalSuiteSchema = import_zod82.z.object({
|
|
|
12003
12131
|
kind: import_zod82.z.literal(EVAL_SUITE_KIND),
|
|
12004
12132
|
purpose: EvalSuitePurposeSchema.optional(),
|
|
12005
12133
|
// U2,默认 regression
|
|
12134
|
+
gateDowngrade: EvalSuiteGateDowngradeSchema.optional(),
|
|
12135
|
+
// #5216,默认 allow
|
|
12006
12136
|
skip: EvalSuiteSkipSchema.optional(),
|
|
12007
12137
|
// §4 声明跳过(带必填理由)
|
|
12138
|
+
/**
|
|
12139
|
+
* #5215:pipeline 面按 **advisory** 跑——照常建 eval run 并后台执行,但不进
|
|
12140
|
+
* eval step 的等待、不进 conclusion 折叠,**不挡门禁**。结果仍挂在结论的
|
|
12141
|
+
* `evalRunIds` 下,流水线详情可见。缺省 false。与 `skip` 互斥(拒绝组合:
|
|
12142
|
+
* 一个说「不跑」一个说「跑但不判」,语义冲突)。
|
|
12143
|
+
*/
|
|
12144
|
+
advisory: import_zod82.z.boolean().optional(),
|
|
12008
12145
|
defaults: EvalSuiteDefaultsSchema.optional(),
|
|
12009
12146
|
cases: import_zod82.z.array(EvalCaseSchema).min(1)
|
|
12010
12147
|
}).strict().superRefine((suite, ctx) => {
|
|
12011
12148
|
var _a, _b;
|
|
12149
|
+
if (suite.advisory === true && suite.skip != null) {
|
|
12150
|
+
ctx.addIssue({
|
|
12151
|
+
code: import_zod82.z.ZodIssueCode.custom,
|
|
12152
|
+
path: ["advisory"],
|
|
12153
|
+
message: "`advisory: true` and `skip` are mutually exclusive \u2014 skip means the suite does not run in the pipeline at all; advisory means it runs but is excluded from the gate"
|
|
12154
|
+
});
|
|
12155
|
+
}
|
|
12012
12156
|
const seen = /* @__PURE__ */ new Set();
|
|
12013
12157
|
suite.cases.forEach((c, ci) => {
|
|
12014
12158
|
var _a2, _b2, _c, _d, _e;
|
|
@@ -12131,11 +12275,15 @@ var EvalSuiteSchema = import_zod82.z.object({
|
|
|
12131
12275
|
if (g.type === "file") {
|
|
12132
12276
|
const hasFiles = g.files != null;
|
|
12133
12277
|
const hasShorthand = g.path != null && g.expect != null;
|
|
12134
|
-
|
|
12278
|
+
const hasTool = g.tool != null && g.expect != null;
|
|
12279
|
+
const sourceCount = [hasFiles, hasShorthand, hasTool].filter(Boolean).length;
|
|
12280
|
+
const strayPath = g.path != null && g.expect == null;
|
|
12281
|
+
const strayTool = g.tool != null && g.expect == null;
|
|
12282
|
+
if (sourceCount !== 1 || strayTool || strayPath && !hasFiles) {
|
|
12135
12283
|
ctx.addIssue({
|
|
12136
12284
|
code: import_zod82.z.ZodIssueCode.custom,
|
|
12137
12285
|
path: ["cases", ci, "graders", gi],
|
|
12138
|
-
message: "file grader must use
|
|
12286
|
+
message: "file grader must use exactly one of `files[]`, `{path, expect}` or `{tool, expect}` (tool = assert on a tool call's input/output instead of a workspace file); a bare `path` without `expect` is ignored only when `files[]` is present (legacy tolerance)"
|
|
12139
12287
|
});
|
|
12140
12288
|
}
|
|
12141
12289
|
}
|
|
@@ -12173,12 +12321,12 @@ var EvalSuiteSchema = import_zod82.z.object({
|
|
|
12173
12321
|
}
|
|
12174
12322
|
const e = g.expect;
|
|
12175
12323
|
const hasEquals = e.equals != null;
|
|
12176
|
-
const hasOthers = e.includes != null || e.excludes != null || e.matches != null;
|
|
12324
|
+
const hasOthers = e.includes != null || e.excludes != null || e.matches != null || e.notMatches != null;
|
|
12177
12325
|
if (hasEquals && hasOthers) {
|
|
12178
12326
|
ctx.addIssue({
|
|
12179
12327
|
code: import_zod82.z.ZodIssueCode.custom,
|
|
12180
12328
|
path: ["cases", ci, "graders", gi, "expect"],
|
|
12181
|
-
message: "reply grader `expect.equals` is mutually exclusive with includes/excludes/matches"
|
|
12329
|
+
message: "reply grader `expect.equals` is mutually exclusive with includes/excludes/matches/notMatches"
|
|
12182
12330
|
});
|
|
12183
12331
|
}
|
|
12184
12332
|
if (!hasEquals && !hasOthers) {
|
|
@@ -13021,7 +13169,7 @@ var OnlineReplyGraderSchema = EvalReplyGraderSchema.pick({ type: true, label: tr
|
|
|
13021
13169
|
threshold: forbiddenThreshold,
|
|
13022
13170
|
expect: EvalReplyExpectSchema.pick({ excludes: true, matches: true })
|
|
13023
13171
|
}).strict();
|
|
13024
|
-
var OnlineLlmToolsSchema =
|
|
13172
|
+
var OnlineLlmToolsSchema = EvalLlmToolsSchema;
|
|
13025
13173
|
var onlineLlmFields = EvalLlmGraderSchema.pick({
|
|
13026
13174
|
type: true,
|
|
13027
13175
|
label: true,
|
|
@@ -13727,7 +13875,12 @@ var RealtimeClaimResponseSchema = import_zod87.z.object({
|
|
|
13727
13875
|
credentialSource: import_zod87.z.enum(REALTIME_CREDENTIAL_SOURCES).optional(),
|
|
13728
13876
|
config: import_zod87.z.object({
|
|
13729
13877
|
systemPrompt: import_zod87.z.string(),
|
|
13730
|
-
voice:
|
|
13878
|
+
voice: RealtimeVoiceWireSchema,
|
|
13879
|
+
/**
|
|
13880
|
+
* Client-executed tools frozen with the call. Stripped by readers that do not know it, which
|
|
13881
|
+
* is the intended rolling-deploy story: an older gateway answers the call without tools.
|
|
13882
|
+
*/
|
|
13883
|
+
tools: WorkloadManifestRealtimeToolListSchema.optional(),
|
|
13731
13884
|
recording: import_zod87.z.boolean().default(false),
|
|
13732
13885
|
upstream: RealtimeUpstreamCredentialSchema.optional()
|
|
13733
13886
|
})
|
|
@@ -15464,13 +15617,13 @@ var SessionsResource = class {
|
|
|
15464
15617
|
* The codes and their statuses are the server's voice error-code table.
|
|
15465
15618
|
*
|
|
15466
15619
|
* **`VOICE_TURNS_DISABLED` is NOT one of them on this path**, despite being
|
|
15467
|
-
* in that table: it answers a NON-empty-text turn while
|
|
15468
|
-
* is
|
|
15620
|
+
* in that table: it answers a NON-empty-text turn while the kill switch
|
|
15621
|
+
* `voice_turns_disabled` is on, and this method always sends `text: ""`. The switch being on is
|
|
15469
15622
|
* refused one step earlier as the ordinary empty-text `400`
|
|
15470
15623
|
* `VALIDATION_ERROR` (issue path `["text"]`).
|
|
15471
15624
|
*
|
|
15472
15625
|
* **Four different causes produce that one 400, and the body does not
|
|
15473
|
-
* distinguish them**: the switch
|
|
15626
|
+
* distinguish them**: the switch on; the agent not declaring `voice.input`;
|
|
15474
15627
|
* an extension outside the voice set; and an attachment that never looks like
|
|
15475
15628
|
* audio at all — raw bytes passed without `contentType` upload as
|
|
15476
15629
|
* `application/octet-stream` and fail the empty-text rule in
|