@roll-agent/smart-reply-agent 0.0.2
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/SKILL.md +44 -0
- package/data/brand-config.sample.json +72 -0
- package/data/reply-policy.json +153 -0
- package/dist/ai/model-registry.d.ts +104 -0
- package/dist/ai/model-registry.d.ts.map +1 -0
- package/dist/ai/model-registry.js +205 -0
- package/dist/ai/model-registry.js.map +1 -0
- package/dist/ai/structured-output.d.ts +50 -0
- package/dist/ai/structured-output.d.ts.map +1 -0
- package/dist/ai/structured-output.js +78 -0
- package/dist/ai/structured-output.js.map +1 -0
- package/dist/errors/app-error.d.ts +43 -0
- package/dist/errors/app-error.d.ts.map +1 -0
- package/dist/errors/app-error.js +95 -0
- package/dist/errors/app-error.js.map +1 -0
- package/dist/errors/error-codes.d.ts +49 -0
- package/dist/errors/error-codes.d.ts.map +1 -0
- package/dist/errors/error-codes.js +115 -0
- package/dist/errors/error-codes.js.map +1 -0
- package/dist/errors/error-factory.d.ts +31 -0
- package/dist/errors/error-factory.d.ts.map +1 -0
- package/dist/errors/error-factory.js +86 -0
- package/dist/errors/error-factory.js.map +1 -0
- package/dist/errors/error-utils.d.ts +40 -0
- package/dist/errors/error-utils.d.ts.map +1 -0
- package/dist/errors/error-utils.js +188 -0
- package/dist/errors/error-utils.js.map +1 -0
- package/dist/errors/index.d.ts +9 -0
- package/dist/errors/index.d.ts.map +1 -0
- package/dist/errors/index.js +5 -0
- package/dist/errors/index.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/log-control.d.ts +3 -0
- package/dist/log-control.d.ts.map +1 -0
- package/dist/log-control.js +15 -0
- package/dist/log-control.js.map +1 -0
- package/dist/pipeline/age-eligibility.d.ts +26 -0
- package/dist/pipeline/age-eligibility.d.ts.map +1 -0
- package/dist/pipeline/age-eligibility.js +176 -0
- package/dist/pipeline/age-eligibility.js.map +1 -0
- package/dist/pipeline/candidate-context.d.ts +9 -0
- package/dist/pipeline/candidate-context.d.ts.map +1 -0
- package/dist/pipeline/candidate-context.js +31 -0
- package/dist/pipeline/candidate-context.js.map +1 -0
- package/dist/pipeline/candidate-utils.d.ts +6 -0
- package/dist/pipeline/candidate-utils.d.ts.map +1 -0
- package/dist/pipeline/candidate-utils.js +33 -0
- package/dist/pipeline/candidate-utils.js.map +1 -0
- package/dist/pipeline/classification.d.ts +13 -0
- package/dist/pipeline/classification.d.ts.map +1 -0
- package/dist/pipeline/classification.js +206 -0
- package/dist/pipeline/classification.js.map +1 -0
- package/dist/pipeline/context-builder.d.ts +22 -0
- package/dist/pipeline/context-builder.d.ts.map +1 -0
- package/dist/pipeline/context-builder.js +404 -0
- package/dist/pipeline/context-builder.js.map +1 -0
- package/dist/pipeline/pipeline-progress.d.ts +10 -0
- package/dist/pipeline/pipeline-progress.d.ts.map +1 -0
- package/dist/pipeline/pipeline-progress.js +33 -0
- package/dist/pipeline/pipeline-progress.js.map +1 -0
- package/dist/pipeline/reply-gate.d.ts +20 -0
- package/dist/pipeline/reply-gate.d.ts.map +1 -0
- package/dist/pipeline/reply-gate.js +139 -0
- package/dist/pipeline/reply-gate.js.map +1 -0
- package/dist/pipeline/smart-reply.d.ts +64 -0
- package/dist/pipeline/smart-reply.d.ts.map +1 -0
- package/dist/pipeline/smart-reply.js +418 -0
- package/dist/pipeline/smart-reply.js.map +1 -0
- package/dist/pipeline.d.ts +21 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +12 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/services/brand-alias.d.ts +5 -0
- package/dist/services/brand-alias.d.ts.map +1 -0
- package/dist/services/brand-alias.js +184 -0
- package/dist/services/brand-alias.js.map +1 -0
- package/dist/services/brand-config-selectors.d.ts +8 -0
- package/dist/services/brand-config-selectors.d.ts.map +1 -0
- package/dist/services/brand-config-selectors.js +30 -0
- package/dist/services/brand-config-selectors.js.map +1 -0
- package/dist/services/config-loader.d.ts +7 -0
- package/dist/services/config-loader.d.ts.map +1 -0
- package/dist/services/config-loader.js +45 -0
- package/dist/services/config-loader.js.map +1 -0
- package/dist/services/duliday-api.d.ts +31 -0
- package/dist/services/duliday-api.d.ts.map +1 -0
- package/dist/services/duliday-api.js +160 -0
- package/dist/services/duliday-api.js.map +1 -0
- package/dist/services/duliday-mapper.d.ts +46 -0
- package/dist/services/duliday-mapper.d.ts.map +1 -0
- package/dist/services/duliday-mapper.js +536 -0
- package/dist/services/duliday-mapper.js.map +1 -0
- package/dist/tools/generate-reply.d.ts +73 -0
- package/dist/tools/generate-reply.d.ts.map +1 -0
- package/dist/tools/generate-reply.js +132 -0
- package/dist/tools/generate-reply.js.map +1 -0
- package/dist/tools/sync-brand-data.d.ts +12 -0
- package/dist/tools/sync-brand-data.d.ts.map +1 -0
- package/dist/tools/sync-brand-data.js +114 -0
- package/dist/tools/sync-brand-data.js.map +1 -0
- package/dist/types/brand-resolution.d.ts +84 -0
- package/dist/types/brand-resolution.d.ts.map +1 -0
- package/dist/types/brand-resolution.js +37 -0
- package/dist/types/brand-resolution.js.map +1 -0
- package/dist/types/classification.d.ts +182 -0
- package/dist/types/classification.d.ts.map +1 -0
- package/dist/types/classification.js +30 -0
- package/dist/types/classification.js.map +1 -0
- package/dist/types/config.d.ts +4 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +7 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/duliday-api.d.ts +6729 -0
- package/dist/types/duliday-api.d.ts.map +1 -0
- package/dist/types/duliday-api.js +235 -0
- package/dist/types/duliday-api.js.map +1 -0
- package/dist/types/geocoding.d.ts +24 -0
- package/dist/types/geocoding.d.ts.map +1 -0
- package/dist/types/geocoding.js +12 -0
- package/dist/types/geocoding.js.map +1 -0
- package/dist/types/reply-policy.d.ts +1391 -0
- package/dist/types/reply-policy.d.ts.map +1 -0
- package/dist/types/reply-policy.js +332 -0
- package/dist/types/reply-policy.js.map +1 -0
- package/dist/types/zhipin.d.ts +2201 -0
- package/dist/types/zhipin.d.ts.map +1 -0
- package/dist/types/zhipin.js +123 -0
- package/dist/types/zhipin.js.map +1 -0
- package/package.json +70 -0
- package/references/env.yaml +27 -0
package/SKILL.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: smart-reply-agent
|
|
3
|
+
description: 招聘智能回复 Agent。根据候选人消息、品牌数据和回复策略,生成个性化招聘回复。
|
|
4
|
+
metadata:
|
|
5
|
+
roll-transport: stdio
|
|
6
|
+
roll-command: node --experimental-strip-types src/index.ts
|
|
7
|
+
roll-env-file: references/env.yaml
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Smart Reply Agent
|
|
11
|
+
|
|
12
|
+
招聘场景智能回复 Agent,支持策略驱动的多阶段对话管理。
|
|
13
|
+
|
|
14
|
+
## Tools
|
|
15
|
+
|
|
16
|
+
- `generate_reply(candidateMessage, conversationHistory?, candidateInfo?, preferredBrand?, channelType?, defaultWechatId?, industryVoiceId?, modelConfig?)` — 根据候选人消息生成智能回复。输出建议回复文本、置信度、漏斗阶段等。内部流程:回合规划 → needs 驱动上下文构建 → 年龄资格校验 → 策略化回复生成 → FactGate 校验。
|
|
17
|
+
- `sync_brand_data(cityName, brandAlias?)` — 从 Duliday API 拉取并同步品牌配置数据(门店、岗位、薪资等)到本地。`cityName` 为必填城市名称(如"上海市"),`brandAlias` 为可选品牌别名过滤。Agent 运行依赖该数据,首次使用前需先调用此工具同步。
|
|
18
|
+
|
|
19
|
+
## Environment Variables
|
|
20
|
+
|
|
21
|
+
机器可读的 env 契约见 `references/env.yaml`。如果你是上层编排 Agent,请优先读取它来生成/校验 `agents.env.smart-reply-agent` 配置。
|
|
22
|
+
|
|
23
|
+
- `ANTHROPIC_API_KEY` — Anthropic/OpenAI/OhMyGPT 统一鉴权 key(回退读取 `OPENAI_API_KEY`)
|
|
24
|
+
- `SMART_REPLY_PROXY_BASE_URL` — 可选,统一代理地址(同时覆盖 anthropic/openai/ohmygpt 端点)
|
|
25
|
+
- `SMART_REPLY_CLASSIFY_MODEL` / `SMART_REPLY_REPLY_MODEL` — 可选,覆盖默认分类/回复模型;未设置时分别回退到 `openai/gpt-5-mini` / `openai/gpt-5.4`
|
|
26
|
+
- `DULIDAY_TOKEN` — Duliday 品牌别名 & 岗位 API 鉴权 token
|
|
27
|
+
- `DULIDAY_BRAND_LIST_URL` / `DULIDAY_JOB_LIST_URL` — 必填,Duliday 品牌/岗位 API 端点;public 仓库中不内置默认地址
|
|
28
|
+
|
|
29
|
+
## Recommended roll.config.yaml
|
|
30
|
+
|
|
31
|
+
建议通过 `roll-core` 的 `agents.env` 为本 Agent 注入环境变量,而不是要求终端用户手工 `export`:
|
|
32
|
+
|
|
33
|
+
```yaml
|
|
34
|
+
agents:
|
|
35
|
+
env:
|
|
36
|
+
smart-reply-agent:
|
|
37
|
+
ANTHROPIC_API_KEY: ${ANTHROPIC_API_KEY}
|
|
38
|
+
SMART_REPLY_PROXY_BASE_URL: ${SMART_REPLY_PROXY_BASE_URL}
|
|
39
|
+
SMART_REPLY_CLASSIFY_MODEL: qwen/qwen-plus-latest
|
|
40
|
+
SMART_REPLY_REPLY_MODEL: qwen/qwen-plus-latest
|
|
41
|
+
DULIDAY_TOKEN: ${DULIDAY_TOKEN}
|
|
42
|
+
DULIDAY_BRAND_LIST_URL: ${DULIDAY_BRAND_LIST_URL}
|
|
43
|
+
DULIDAY_JOB_LIST_URL: ${DULIDAY_JOB_LIST_URL}
|
|
44
|
+
```
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
{
|
|
2
|
+
"meta": {
|
|
3
|
+
"defaultBrandId": "10001",
|
|
4
|
+
"syncedAt": "2026-03-17T00:00:00.000Z",
|
|
5
|
+
"source": "sample"
|
|
6
|
+
},
|
|
7
|
+
"brands": [
|
|
8
|
+
{
|
|
9
|
+
"id": "10001",
|
|
10
|
+
"name": "示例品牌",
|
|
11
|
+
"stores": [
|
|
12
|
+
{
|
|
13
|
+
"id": "store-001",
|
|
14
|
+
"brandId": "10001",
|
|
15
|
+
"name": "示例品牌南山店",
|
|
16
|
+
"city": "深圳",
|
|
17
|
+
"location": "深圳市南山区科技园路1号",
|
|
18
|
+
"district": "南山区",
|
|
19
|
+
"subarea": "科技园",
|
|
20
|
+
"coordinates": { "lat": 22.5431, "lng": 113.9531 },
|
|
21
|
+
"positions": [
|
|
22
|
+
{
|
|
23
|
+
"id": "pos-001",
|
|
24
|
+
"name": "服务员",
|
|
25
|
+
"brandId": "10001",
|
|
26
|
+
"brandName": "示例品牌",
|
|
27
|
+
"timeSlots": ["08:00-14:00", "14:00-22:00"],
|
|
28
|
+
"salary": {
|
|
29
|
+
"base": 22,
|
|
30
|
+
"range": "20-25",
|
|
31
|
+
"memo": "时薪制,多劳多得"
|
|
32
|
+
},
|
|
33
|
+
"workHours": "6-8小时/天",
|
|
34
|
+
"benefits": {
|
|
35
|
+
"items": ["包工作餐", "交通补贴"]
|
|
36
|
+
},
|
|
37
|
+
"requirements": ["18-45岁", "健康证"],
|
|
38
|
+
"urgent": false,
|
|
39
|
+
"scheduleType": "flexible",
|
|
40
|
+
"attendancePolicy": {
|
|
41
|
+
"punctualityRequired": true,
|
|
42
|
+
"lateToleranceMinutes": 10,
|
|
43
|
+
"attendanceTracking": "strict",
|
|
44
|
+
"makeupShiftsAllowed": true
|
|
45
|
+
},
|
|
46
|
+
"availableSlots": [
|
|
47
|
+
{
|
|
48
|
+
"slot": "08:00-14:00",
|
|
49
|
+
"maxCapacity": 5,
|
|
50
|
+
"currentBooked": 3,
|
|
51
|
+
"isAvailable": true,
|
|
52
|
+
"priority": "high"
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"schedulingFlexibility": {
|
|
56
|
+
"canSwapShifts": true,
|
|
57
|
+
"advanceNoticeHours": 24,
|
|
58
|
+
"partTimeAllowed": true,
|
|
59
|
+
"weekendRequired": false,
|
|
60
|
+
"holidayRequired": false
|
|
61
|
+
},
|
|
62
|
+
"hiringRequirements": {
|
|
63
|
+
"minAge": 18,
|
|
64
|
+
"maxAge": 45
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
]
|
|
70
|
+
}
|
|
71
|
+
]
|
|
72
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
{
|
|
2
|
+
"stageGoals": {
|
|
3
|
+
"trust_building": {
|
|
4
|
+
"description": "初次接触,先自然接话并确认候选人的核心诉求",
|
|
5
|
+
"primaryGoal": "先回应候选人当前问题,再自然推进下一步",
|
|
6
|
+
"successCriteria": [
|
|
7
|
+
"候选人愿意继续沟通",
|
|
8
|
+
"候选人愿意补充1到2个关键信息"
|
|
9
|
+
],
|
|
10
|
+
"ctaStrategy": "先答当前问题;若需要补信息,单轮最多追问2个关键问题;避免表单式盘问",
|
|
11
|
+
"disallowedActions": [
|
|
12
|
+
"过早承诺具体待遇",
|
|
13
|
+
"首次接触一次性追问过多信息",
|
|
14
|
+
"在对方只表达兴趣时直接索要过多个人资料"
|
|
15
|
+
]
|
|
16
|
+
},
|
|
17
|
+
"private_channel": {
|
|
18
|
+
"description": "在合适时机引导用户从公域平台转到微信私聊",
|
|
19
|
+
"primaryGoal": "自然推进联系方式交换",
|
|
20
|
+
"successCriteria": [
|
|
21
|
+
"候选人愿意交换联系方式"
|
|
22
|
+
],
|
|
23
|
+
"ctaStrategy": "只在确有必要时再引导加微信,不要每轮都主动索要;若对方已加微信,优先确认收到,不再重复索要大量信息",
|
|
24
|
+
"disallowedActions": [
|
|
25
|
+
"强迫式要微信",
|
|
26
|
+
"对方刚表示已加微信时继续在公域一次性追问很多字段"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
"qualify_candidate": {
|
|
30
|
+
"description": "确认候选人基本匹配度,但保持自然聊天语气",
|
|
31
|
+
"primaryGoal": "确认最关键的1到2个匹配信息",
|
|
32
|
+
"successCriteria": [
|
|
33
|
+
"完成1到2个关键条件确认",
|
|
34
|
+
"候选人愿意继续往下沟通"
|
|
35
|
+
],
|
|
36
|
+
"ctaStrategy": "优先问当前最缺的1到2个信息;不要逐条盘问所有条件;已知信息不要重复问",
|
|
37
|
+
"disallowedActions": [
|
|
38
|
+
"直接否定候选人",
|
|
39
|
+
"一次问4个以上问题",
|
|
40
|
+
"使用明显审查口吻",
|
|
41
|
+
"已知年龄时仍重复问是否成年"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"job_consultation": {
|
|
45
|
+
"description": "回答岗位相关问题,但控制信息披露粒度",
|
|
46
|
+
"primaryGoal": "先准确回答当前问题,再做轻量推进",
|
|
47
|
+
"successCriteria": [
|
|
48
|
+
"候选人当前问题得到回应",
|
|
49
|
+
"候选人愿意继续确认具体安排"
|
|
50
|
+
],
|
|
51
|
+
"ctaStrategy": "优先正面回答当前问题;非明确追问时,不主动报过细数字、时段、地址;必要时先给概括答案,再补1到2个澄清问题",
|
|
52
|
+
"disallowedActions": [
|
|
53
|
+
"编造数字或政策",
|
|
54
|
+
"首次答复直接抛出过多具体薪资/时段/地址",
|
|
55
|
+
"对模糊问题直接展开完整门店清单"
|
|
56
|
+
]
|
|
57
|
+
},
|
|
58
|
+
"interview_scheduling": {
|
|
59
|
+
"description": "推动面试预约,确认时间和到店安排",
|
|
60
|
+
"primaryGoal": "推进到面试或到店环节",
|
|
61
|
+
"successCriteria": [
|
|
62
|
+
"候选人给出可面试时间"
|
|
63
|
+
],
|
|
64
|
+
"ctaStrategy": "给出明确下一步,但问题数量要克制",
|
|
65
|
+
"disallowedActions": [
|
|
66
|
+
"不确认候选人可到店性"
|
|
67
|
+
]
|
|
68
|
+
},
|
|
69
|
+
"onboard_followup": {
|
|
70
|
+
"description": "促进到岗并保持回访",
|
|
71
|
+
"primaryGoal": "促进到岗并保持跟进",
|
|
72
|
+
"successCriteria": [
|
|
73
|
+
"候选人确认上岗安排"
|
|
74
|
+
],
|
|
75
|
+
"ctaStrategy": "说明下一步动作与提醒,但保持简洁",
|
|
76
|
+
"disallowedActions": [
|
|
77
|
+
"承诺不确定资源"
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"persona": {
|
|
82
|
+
"tone": "口语化",
|
|
83
|
+
"warmth": "高",
|
|
84
|
+
"humor": "低",
|
|
85
|
+
"length": "short",
|
|
86
|
+
"questionStyle": "单轮最多两个关键问题",
|
|
87
|
+
"empathyStrategy": "先回应对方当前关切,再补最少必要问题",
|
|
88
|
+
"addressStyle": "使用你",
|
|
89
|
+
"professionalIdentity": "资深招聘专员",
|
|
90
|
+
"companyBackground": "连锁餐饮招聘"
|
|
91
|
+
},
|
|
92
|
+
"industryVoices": {
|
|
93
|
+
"default": {
|
|
94
|
+
"name": "餐饮连锁招聘",
|
|
95
|
+
"industryBackground": "门店密集、排班灵活、强调稳定出勤",
|
|
96
|
+
"jargon": ["排班", "到岗", "门店", "班次"],
|
|
97
|
+
"styleKeywords": ["直接", "清晰", "可信", "自然"],
|
|
98
|
+
"tabooPhrases": ["包过", "绝对", "随便都行", "你是否满足岗位基本入职要求", "身份证能不能正常上岗"],
|
|
99
|
+
"guidance": [
|
|
100
|
+
"先解决当前问题,再推进下一步",
|
|
101
|
+
"避免像表单一样连续追问",
|
|
102
|
+
"避免资格审查感"
|
|
103
|
+
]
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
"defaultIndustryVoiceId": "default",
|
|
107
|
+
"hardConstraints": {
|
|
108
|
+
"rules": [
|
|
109
|
+
{
|
|
110
|
+
"id": "no-fabrication",
|
|
111
|
+
"rule": "不得编造门店、薪资、排班、福利等事实信息",
|
|
112
|
+
"severity": "high"
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
"id": "no-insurance-promise",
|
|
116
|
+
"rule": "兼职场景不得承诺五险一金",
|
|
117
|
+
"severity": "high"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"id": "age-sensitive",
|
|
121
|
+
"rule": "年龄敏感场景使用合规自然话术,不暴露内部筛选线,不主动制造审查感",
|
|
122
|
+
"severity": "high"
|
|
123
|
+
},
|
|
124
|
+
{
|
|
125
|
+
"id": "no-form-interrogation",
|
|
126
|
+
"rule": "单轮不要像表单一样连续盘问多个字段,优先控制在1到2个关键问题",
|
|
127
|
+
"severity": "high"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"id": "no-over-detailed-first-reply",
|
|
131
|
+
"rule": "首次回复或对方未明确追问时,不主动暴露过细薪资数字、详细门店地址、完整班次列表",
|
|
132
|
+
"severity": "high"
|
|
133
|
+
}
|
|
134
|
+
]
|
|
135
|
+
},
|
|
136
|
+
"factGate": {
|
|
137
|
+
"mode": "strict",
|
|
138
|
+
"verifiableClaimTypes": ["salary", "location", "schedule", "policy", "availability"],
|
|
139
|
+
"fallbackBehavior": "generic_answer",
|
|
140
|
+
"forbiddenWhenMissingFacts": ["具体数字", "具体门店承诺", "明确福利承诺", "完整门店地址", "完整班次列表"]
|
|
141
|
+
},
|
|
142
|
+
"qualificationPolicy": {
|
|
143
|
+
"age": {
|
|
144
|
+
"enabled": true,
|
|
145
|
+
"revealRange": false,
|
|
146
|
+
"failStrategy": "礼貌说明当前不合适,避免承诺,也避免暴露内部筛选标准",
|
|
147
|
+
"unknownStrategy": "仅在确有必要时,自然核实关键资格条件,不直接使用审查口吻",
|
|
148
|
+
"passStrategy": "已知候选人明显符合基础条件时,不重复追问年龄,直接推进下一步",
|
|
149
|
+
"allowRedirect": true,
|
|
150
|
+
"redirectPriority": "medium"
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { LanguageModel } from "ai";
|
|
2
|
+
import type { ProviderConfig } from "../types/classification.ts";
|
|
3
|
+
export type ModelCategory = "chat" | "general";
|
|
4
|
+
export declare const MODEL_DICTIONARY: {
|
|
5
|
+
readonly "qwen/qwen-max-latest": {
|
|
6
|
+
readonly provider: "qwen";
|
|
7
|
+
readonly name: "Qwen Max Latest";
|
|
8
|
+
readonly categories: ModelCategory[];
|
|
9
|
+
};
|
|
10
|
+
readonly "qwen/qwen-plus-latest": {
|
|
11
|
+
readonly provider: "qwen";
|
|
12
|
+
readonly name: "Qwen Plus Latest";
|
|
13
|
+
readonly categories: ModelCategory[];
|
|
14
|
+
};
|
|
15
|
+
readonly "google/gemini-embedding-2-preview": {
|
|
16
|
+
readonly provider: "google";
|
|
17
|
+
readonly name: "Gemini Embedding 2 Preview";
|
|
18
|
+
readonly categories: ModelCategory[];
|
|
19
|
+
};
|
|
20
|
+
readonly "google/gemini-3.1-flash-lite-preview": {
|
|
21
|
+
readonly provider: "google";
|
|
22
|
+
readonly name: "Gemini 3.1 Flash Lite Preview";
|
|
23
|
+
readonly categories: ModelCategory[];
|
|
24
|
+
};
|
|
25
|
+
readonly "google/gemini-3.1-pro-preview": {
|
|
26
|
+
readonly provider: "google";
|
|
27
|
+
readonly name: "Gemini 3.1 Pro Preview";
|
|
28
|
+
readonly categories: ModelCategory[];
|
|
29
|
+
};
|
|
30
|
+
readonly "anthropic/claude-sonnet-4-6": {
|
|
31
|
+
readonly provider: "anthropic";
|
|
32
|
+
readonly name: "Claude Sonnet 4.6";
|
|
33
|
+
readonly categories: ModelCategory[];
|
|
34
|
+
};
|
|
35
|
+
readonly "anthropic/claude-opus-4-6": {
|
|
36
|
+
readonly provider: "anthropic";
|
|
37
|
+
readonly name: "Claude Opus 4.6";
|
|
38
|
+
readonly categories: ModelCategory[];
|
|
39
|
+
};
|
|
40
|
+
readonly "anthropic/claude-haiku-4-5": {
|
|
41
|
+
readonly provider: "anthropic";
|
|
42
|
+
readonly name: "Claude Haiku 4.5";
|
|
43
|
+
readonly categories: ModelCategory[];
|
|
44
|
+
};
|
|
45
|
+
readonly "openai/gpt-5.1": {
|
|
46
|
+
readonly provider: "openai";
|
|
47
|
+
readonly name: "GPT-5.1";
|
|
48
|
+
readonly categories: ModelCategory[];
|
|
49
|
+
};
|
|
50
|
+
readonly "openai/gpt-5.2": {
|
|
51
|
+
readonly provider: "openai";
|
|
52
|
+
readonly name: "GPT-5.2";
|
|
53
|
+
readonly categories: ModelCategory[];
|
|
54
|
+
};
|
|
55
|
+
readonly "openai/gpt-5.4": {
|
|
56
|
+
readonly provider: "openai";
|
|
57
|
+
readonly name: "GPT-5.4";
|
|
58
|
+
readonly categories: ModelCategory[];
|
|
59
|
+
};
|
|
60
|
+
readonly "openai/gpt-5-mini": {
|
|
61
|
+
readonly provider: "openai";
|
|
62
|
+
readonly name: "GPT-5 Mini";
|
|
63
|
+
readonly categories: ModelCategory[];
|
|
64
|
+
};
|
|
65
|
+
readonly "ohmygpt/gemini-3.1-flash-lite-preview": {
|
|
66
|
+
readonly provider: "ohmygpt";
|
|
67
|
+
readonly name: "Gemini 3.1 Flash Lite Preview (OhMyGPT)";
|
|
68
|
+
readonly categories: ModelCategory[];
|
|
69
|
+
};
|
|
70
|
+
readonly "ohmygpt/gemini-3.1-pro-preview": {
|
|
71
|
+
readonly provider: "ohmygpt";
|
|
72
|
+
readonly name: "Gemini 3.1 Pro Preview (OhMyGPT)";
|
|
73
|
+
readonly categories: ModelCategory[];
|
|
74
|
+
};
|
|
75
|
+
readonly "moonshotai/kimi-k2.5": {
|
|
76
|
+
readonly provider: "moonshotai";
|
|
77
|
+
readonly name: "Kimi K2.5";
|
|
78
|
+
readonly categories: ModelCategory[];
|
|
79
|
+
};
|
|
80
|
+
readonly "moonshotai/kimi-k2-thinking-turbo": {
|
|
81
|
+
readonly provider: "moonshotai";
|
|
82
|
+
readonly name: "Kimi K2 Thinking Turbo";
|
|
83
|
+
readonly categories: ModelCategory[];
|
|
84
|
+
};
|
|
85
|
+
readonly "deepseek/deepseek-chat": {
|
|
86
|
+
readonly provider: "deepseek";
|
|
87
|
+
readonly name: "DeepSeek Chat";
|
|
88
|
+
readonly categories: ModelCategory[];
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
export type ModelId = keyof typeof MODEL_DICTIONARY;
|
|
92
|
+
export declare const DEFAULT_PROVIDER_CONFIGS: Record<string, ProviderConfig>;
|
|
93
|
+
export declare const DEFAULT_MODEL_CONFIG: {
|
|
94
|
+
readonly chatModel: ModelId;
|
|
95
|
+
readonly classifyModel: "anthropic/claude-haiku-4-5" | "qwen/qwen-max-latest" | "qwen/qwen-plus-latest" | "google/gemini-embedding-2-preview" | "google/gemini-3.1-flash-lite-preview" | "google/gemini-3.1-pro-preview" | "anthropic/claude-sonnet-4-6" | "anthropic/claude-opus-4-6" | "openai/gpt-5.1" | "openai/gpt-5.2" | "openai/gpt-5.4" | "openai/gpt-5-mini" | "ohmygpt/gemini-3.1-flash-lite-preview" | "ohmygpt/gemini-3.1-pro-preview" | "moonshotai/kimi-k2.5" | "moonshotai/kimi-k2-thinking-turbo" | "deepseek/deepseek-chat";
|
|
96
|
+
readonly replyModel: "anthropic/claude-haiku-4-5" | "qwen/qwen-max-latest" | "qwen/qwen-plus-latest" | "google/gemini-embedding-2-preview" | "google/gemini-3.1-flash-lite-preview" | "google/gemini-3.1-pro-preview" | "anthropic/claude-sonnet-4-6" | "anthropic/claude-opus-4-6" | "openai/gpt-5.1" | "openai/gpt-5.2" | "openai/gpt-5.4" | "openai/gpt-5-mini" | "ohmygpt/gemini-3.1-flash-lite-preview" | "ohmygpt/gemini-3.1-pro-preview" | "moonshotai/kimi-k2.5" | "moonshotai/kimi-k2-thinking-turbo" | "deepseek/deepseek-chat";
|
|
97
|
+
};
|
|
98
|
+
/** 只暴露 registry 实际被消费的 languageModel 方法,避免 .d.ts 引用内部类型导致 TS2742 */
|
|
99
|
+
interface ModelRegistry {
|
|
100
|
+
languageModel(modelId: string): LanguageModel;
|
|
101
|
+
}
|
|
102
|
+
export declare function getDynamicRegistry(providerConfigs: Record<string, ProviderConfig>): ModelRegistry;
|
|
103
|
+
export {};
|
|
104
|
+
//# sourceMappingURL=model-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-registry.d.ts","sourceRoot":"","sources":["../../src/ai/model-registry.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAKxC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAKjE,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,SAAS,CAAC;AAE/C,eAAO,MAAM,gBAAgB;;;;6BAIE,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKP,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKvB,aAAa,EAAE;;;;;6BAKP,aAAa,EAAE;;;;;6BAKvB,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKP,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;;;;6BAKf,aAAa,EAAE;;CAE5C,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,MAAM,OAAO,gBAAgB,CAAC;AAsBpD,eAAO,MAAM,wBAAwB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAYnE,CAAC;AAEF,eAAO,MAAM,oBAAoB;wBACY,OAAO;;;CAI1C,CAAC;AAyEX,oEAAoE;AACpE,UAAU,aAAa;IACrB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,CAAC;CAC/C;AAKD,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,GAAG,aAAa,CAUjG"}
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
2
|
+
import { createAlibaba } from "@ai-sdk/alibaba";
|
|
3
|
+
import { createProviderRegistry } from "ai";
|
|
4
|
+
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
5
|
+
import { createDeepSeek } from "@ai-sdk/deepseek";
|
|
6
|
+
import { createGoogleGenerativeAI } from "@ai-sdk/google";
|
|
7
|
+
import { createOpenAI } from "@ai-sdk/openai";
|
|
8
|
+
import { verboseLog } from "../log-control.js";
|
|
9
|
+
export const MODEL_DICTIONARY = {
|
|
10
|
+
"qwen/qwen-max-latest": {
|
|
11
|
+
provider: "qwen",
|
|
12
|
+
name: "Qwen Max Latest",
|
|
13
|
+
categories: ["general"],
|
|
14
|
+
},
|
|
15
|
+
"qwen/qwen-plus-latest": {
|
|
16
|
+
provider: "qwen",
|
|
17
|
+
name: "Qwen Plus Latest",
|
|
18
|
+
categories: ["general"],
|
|
19
|
+
},
|
|
20
|
+
"google/gemini-embedding-2-preview": {
|
|
21
|
+
provider: "google",
|
|
22
|
+
name: "Gemini Embedding 2 Preview",
|
|
23
|
+
categories: ["general"],
|
|
24
|
+
},
|
|
25
|
+
"google/gemini-3.1-flash-lite-preview": {
|
|
26
|
+
provider: "google",
|
|
27
|
+
name: "Gemini 3.1 Flash Lite Preview",
|
|
28
|
+
categories: ["general", "chat"],
|
|
29
|
+
},
|
|
30
|
+
"google/gemini-3.1-pro-preview": {
|
|
31
|
+
provider: "google",
|
|
32
|
+
name: "Gemini 3.1 Pro Preview",
|
|
33
|
+
categories: ["chat", "general"],
|
|
34
|
+
},
|
|
35
|
+
"anthropic/claude-sonnet-4-6": {
|
|
36
|
+
provider: "anthropic",
|
|
37
|
+
name: "Claude Sonnet 4.6",
|
|
38
|
+
categories: ["chat", "general"],
|
|
39
|
+
},
|
|
40
|
+
"anthropic/claude-opus-4-6": {
|
|
41
|
+
provider: "anthropic",
|
|
42
|
+
name: "Claude Opus 4.6",
|
|
43
|
+
categories: ["chat", "general"],
|
|
44
|
+
},
|
|
45
|
+
"anthropic/claude-haiku-4-5": {
|
|
46
|
+
provider: "anthropic",
|
|
47
|
+
name: "Claude Haiku 4.5",
|
|
48
|
+
categories: ["chat", "general"],
|
|
49
|
+
},
|
|
50
|
+
"openai/gpt-5.1": {
|
|
51
|
+
provider: "openai",
|
|
52
|
+
name: "GPT-5.1",
|
|
53
|
+
categories: ["chat", "general"],
|
|
54
|
+
},
|
|
55
|
+
"openai/gpt-5.2": {
|
|
56
|
+
provider: "openai",
|
|
57
|
+
name: "GPT-5.2",
|
|
58
|
+
categories: ["general"],
|
|
59
|
+
},
|
|
60
|
+
"openai/gpt-5.4": {
|
|
61
|
+
provider: "openai",
|
|
62
|
+
name: "GPT-5.4",
|
|
63
|
+
categories: ["chat", "general"],
|
|
64
|
+
},
|
|
65
|
+
"openai/gpt-5-mini": {
|
|
66
|
+
provider: "openai",
|
|
67
|
+
name: "GPT-5 Mini",
|
|
68
|
+
categories: ["general"],
|
|
69
|
+
},
|
|
70
|
+
"ohmygpt/gemini-3.1-flash-lite-preview": {
|
|
71
|
+
provider: "ohmygpt",
|
|
72
|
+
name: "Gemini 3.1 Flash Lite Preview (OhMyGPT)",
|
|
73
|
+
categories: ["general"],
|
|
74
|
+
},
|
|
75
|
+
"ohmygpt/gemini-3.1-pro-preview": {
|
|
76
|
+
provider: "ohmygpt",
|
|
77
|
+
name: "Gemini 3.1 Pro Preview (OhMyGPT)",
|
|
78
|
+
categories: ["general"],
|
|
79
|
+
},
|
|
80
|
+
"moonshotai/kimi-k2.5": {
|
|
81
|
+
provider: "moonshotai",
|
|
82
|
+
name: "Kimi K2.5",
|
|
83
|
+
categories: ["chat", "general"],
|
|
84
|
+
},
|
|
85
|
+
"moonshotai/kimi-k2-thinking-turbo": {
|
|
86
|
+
provider: "moonshotai",
|
|
87
|
+
name: "Kimi K2 Thinking Turbo",
|
|
88
|
+
categories: ["chat", "general"],
|
|
89
|
+
},
|
|
90
|
+
"deepseek/deepseek-chat": {
|
|
91
|
+
provider: "deepseek",
|
|
92
|
+
name: "DeepSeek Chat",
|
|
93
|
+
categories: ["chat", "general"],
|
|
94
|
+
},
|
|
95
|
+
};
|
|
96
|
+
// ========== Default Configs ==========
|
|
97
|
+
/**
|
|
98
|
+
* Anthropic/OpenAI/OhMyGPT 默认走共享代理,保证“统一 key + 默认模型”开箱可用。
|
|
99
|
+
* 如果需要切换,优先使用 SMART_REPLY_PROXY_BASE_URL,或为单个 provider 指定专属 base URL。
|
|
100
|
+
*/
|
|
101
|
+
const PROXY_BASE_URL = process.env.SMART_REPLY_PROXY_BASE_URL;
|
|
102
|
+
const DEFAULT_SHARED_PROXY_BASE_URL = "https://apic1.ohmycdn.com/v1";
|
|
103
|
+
const SHARED_PROXY_BASE_URL = PROXY_BASE_URL || DEFAULT_SHARED_PROXY_BASE_URL;
|
|
104
|
+
const FALLBACK_URLS = {
|
|
105
|
+
anthropic: process.env.ANTHROPIC_BASE_URL || SHARED_PROXY_BASE_URL,
|
|
106
|
+
openai: process.env.OPENAI_BASE_URL || SHARED_PROXY_BASE_URL,
|
|
107
|
+
ohmygpt: process.env.OHMYGPT_BASE_URL || SHARED_PROXY_BASE_URL,
|
|
108
|
+
moonshotai: process.env.MOONSHOT_BASE_URL || "https://api.moonshot.cn/v1",
|
|
109
|
+
deepseek: process.env.DEEPSEEK_BASE_URL || "https://api.deepseek.com",
|
|
110
|
+
qwen: process.env.QWEN_BASE_URL || "https://dashscope.aliyuncs.com/compatible-mode/v1",
|
|
111
|
+
google: process.env.GOOGLE_BASE_URL || "https://generativelanguage.googleapis.com/v1beta",
|
|
112
|
+
};
|
|
113
|
+
export const DEFAULT_PROVIDER_CONFIGS = {
|
|
114
|
+
anthropic: {
|
|
115
|
+
name: "Anthropic",
|
|
116
|
+
baseURL: FALLBACK_URLS.anthropic,
|
|
117
|
+
description: "Anthropic Claude",
|
|
118
|
+
},
|
|
119
|
+
openai: { name: "OpenAI", baseURL: FALLBACK_URLS.openai, description: "OpenAI GPT" },
|
|
120
|
+
ohmygpt: { name: "OhMyGPT", baseURL: FALLBACK_URLS.ohmygpt, description: "OhMyGPT" },
|
|
121
|
+
moonshotai: { name: "MoonshotAI", baseURL: FALLBACK_URLS.moonshotai, description: "MoonshotAI" },
|
|
122
|
+
deepseek: { name: "DeepSeek", baseURL: FALLBACK_URLS.deepseek, description: "DeepSeek" },
|
|
123
|
+
qwen: { name: "Qwen", baseURL: FALLBACK_URLS.qwen, description: "Qwen" },
|
|
124
|
+
google: { name: "Google", baseURL: FALLBACK_URLS.google, description: "Google Gemini" },
|
|
125
|
+
};
|
|
126
|
+
export const DEFAULT_MODEL_CONFIG = {
|
|
127
|
+
chatModel: "anthropic/claude-haiku-4-5",
|
|
128
|
+
classifyModel: process.env.SMART_REPLY_CLASSIFY_MODEL || "openai/gpt-5-mini",
|
|
129
|
+
replyModel: process.env.SMART_REPLY_REPLY_MODEL || "openai/gpt-5.4",
|
|
130
|
+
};
|
|
131
|
+
function getSharedProxyApiKey() {
|
|
132
|
+
// 当前统一代理对 Anthropic/OpenAI/OhMyGPT 走同一套鉴权。
|
|
133
|
+
// 为兼容仓库里仍存在的 OPENAI_API_KEY 示例,回退读取 OPENAI_API_KEY。
|
|
134
|
+
return process.env.ANTHROPIC_API_KEY || process.env.OPENAI_API_KEY || "";
|
|
135
|
+
}
|
|
136
|
+
// ========== Custom Provider Factories ==========
|
|
137
|
+
function createCustomOpenAI(config) {
|
|
138
|
+
const openaiInstance = createOpenAI({
|
|
139
|
+
apiKey: config.apiKey || "",
|
|
140
|
+
...(config.baseURL !== undefined ? { baseURL: config.baseURL } : {}),
|
|
141
|
+
});
|
|
142
|
+
return new Proxy(openaiInstance, {
|
|
143
|
+
get(_target, prop) {
|
|
144
|
+
if (prop === "languageModel") {
|
|
145
|
+
return (modelId) => openaiInstance.chat(modelId);
|
|
146
|
+
}
|
|
147
|
+
if (prop === "chat" || prop === "completion") {
|
|
148
|
+
return openaiInstance[prop];
|
|
149
|
+
}
|
|
150
|
+
if (prop === "embeddingModel" || prop === "imageModel") {
|
|
151
|
+
const method = openaiInstance[prop];
|
|
152
|
+
return method || undefined;
|
|
153
|
+
}
|
|
154
|
+
return openaiInstance[prop];
|
|
155
|
+
},
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
// ========== Dynamic Registry ==========
|
|
159
|
+
function createDynamicRegistry(providerConfigs) {
|
|
160
|
+
const sharedProxyApiKey = getSharedProxyApiKey();
|
|
161
|
+
return createProviderRegistry({
|
|
162
|
+
anthropic: createAnthropic({
|
|
163
|
+
apiKey: sharedProxyApiKey,
|
|
164
|
+
baseURL: providerConfigs.anthropic?.baseURL || FALLBACK_URLS.anthropic,
|
|
165
|
+
}),
|
|
166
|
+
openai: createCustomOpenAI({
|
|
167
|
+
apiKey: sharedProxyApiKey,
|
|
168
|
+
baseURL: providerConfigs.openai?.baseURL || FALLBACK_URLS.openai,
|
|
169
|
+
}),
|
|
170
|
+
ohmygpt: createOpenAICompatible({
|
|
171
|
+
name: "ohmygpt",
|
|
172
|
+
baseURL: providerConfigs.ohmygpt?.baseURL || FALLBACK_URLS.ohmygpt,
|
|
173
|
+
apiKey: sharedProxyApiKey,
|
|
174
|
+
}),
|
|
175
|
+
moonshotai: createOpenAICompatible({
|
|
176
|
+
name: "moonshotai",
|
|
177
|
+
baseURL: providerConfigs.moonshotai?.baseURL || FALLBACK_URLS.moonshotai,
|
|
178
|
+
apiKey: process.env.MOONSHOT_API_KEY || "",
|
|
179
|
+
}),
|
|
180
|
+
deepseek: createDeepSeek({
|
|
181
|
+
baseURL: providerConfigs.deepseek?.baseURL || FALLBACK_URLS.deepseek,
|
|
182
|
+
apiKey: process.env.DEEPSEEK_API_KEY || "",
|
|
183
|
+
}),
|
|
184
|
+
google: createGoogleGenerativeAI({
|
|
185
|
+
apiKey: process.env.GEMINI_API_KEY || "",
|
|
186
|
+
baseURL: providerConfigs.google?.baseURL || FALLBACK_URLS.google,
|
|
187
|
+
}),
|
|
188
|
+
qwen: createAlibaba({
|
|
189
|
+
apiKey: process.env.DASHSCOPE_API_KEY || process.env.ALIBABA_API_KEY || "",
|
|
190
|
+
baseURL: providerConfigs.qwen?.baseURL || FALLBACK_URLS.qwen,
|
|
191
|
+
}),
|
|
192
|
+
}, { separator: "/" });
|
|
193
|
+
}
|
|
194
|
+
let cachedRegistry = null;
|
|
195
|
+
let lastConfigHash = null;
|
|
196
|
+
export function getDynamicRegistry(providerConfigs) {
|
|
197
|
+
const configHash = JSON.stringify(providerConfigs);
|
|
198
|
+
if (cachedRegistry && lastConfigHash === configHash)
|
|
199
|
+
return cachedRegistry;
|
|
200
|
+
cachedRegistry = createDynamicRegistry(providerConfigs);
|
|
201
|
+
lastConfigHash = configHash;
|
|
202
|
+
verboseLog("[DYNAMIC REGISTRY] 创建新的动态registry,配置哈希:", configHash.substring(0, 16) + "...");
|
|
203
|
+
return cachedRegistry;
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=model-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-registry.js","sourceRoot":"","sources":["../../src/ai/model-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,IAAI,CAAC;AAE5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAM/C,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,sBAAsB,EAAE;QACtB,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,iBAAiB;QACvB,UAAU,EAAE,CAAC,SAAS,CAAoB;KAC3C;IACD,uBAAuB,EAAE;QACvB,QAAQ,EAAE,MAAM;QAChB,IAAI,EAAE,kBAAkB;QACxB,UAAU,EAAE,CAAC,SAAS,CAAoB;KAC3C;IACD,mCAAmC,EAAE;QACnC,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,4BAA4B;QAClC,UAAU,EAAE,CAAC,SAAS,CAAoB;KAC3C;IACD,sCAAsC,EAAE;QACtC,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,+BAA+B;QACrC,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,CAAoB;KACnD;IACD,+BAA+B,EAAE;QAC/B,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,wBAAwB;QAC9B,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,6BAA6B,EAAE;QAC7B,QAAQ,EAAE,WAAW;QACrB,IAAI,EAAE,mBAAmB;QACzB,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,2BAA2B,EAAE;QAC3B,QAAQ,EAAE,WAAW;QACrB,IAAI,EAAE,iBAAiB;QACvB,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,4BAA4B,EAAE;QAC5B,QAAQ,EAAE,WAAW;QACrB,IAAI,EAAE,kBAAkB;QACxB,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,gBAAgB,EAAE;QAChB,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,SAAS;QACf,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,gBAAgB,EAAE;QAChB,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,SAAS;QACf,UAAU,EAAE,CAAC,SAAS,CAAoB;KAC3C;IACD,gBAAgB,EAAE;QAChB,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,SAAS;QACf,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,mBAAmB,EAAE;QACnB,QAAQ,EAAE,QAAQ;QAClB,IAAI,EAAE,YAAY;QAClB,UAAU,EAAE,CAAC,SAAS,CAAoB;KAC3C;IACD,uCAAuC,EAAE;QACvC,QAAQ,EAAE,SAAS;QACnB,IAAI,EAAE,yCAAyC;QAC/C,UAAU,EAAE,CAAC,SAAS,CAAoB;KAC3C;IACD,gCAAgC,EAAE;QAChC,QAAQ,EAAE,SAAS;QACnB,IAAI,EAAE,kCAAkC;QACxC,UAAU,EAAE,CAAC,SAAS,CAAoB;KAC3C;IACD,sBAAsB,EAAE;QACtB,QAAQ,EAAE,YAAY;QACtB,IAAI,EAAE,WAAW;QACjB,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,mCAAmC,EAAE;QACnC,QAAQ,EAAE,YAAY;QACtB,IAAI,EAAE,wBAAwB;QAC9B,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;IACD,wBAAwB,EAAE;QACxB,QAAQ,EAAE,UAAU;QACpB,IAAI,EAAE,eAAe;QACrB,UAAU,EAAE,CAAC,MAAM,EAAE,SAAS,CAAoB;KACnD;CACO,CAAC;AAIX,wCAAwC;AAExC;;;GAGG;AACH,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;AAC9D,MAAM,6BAA6B,GAAG,8BAA8B,CAAC;AACrE,MAAM,qBAAqB,GAAG,cAAc,IAAI,6BAA6B,CAAC;AAE9E,MAAM,aAAa,GAAG;IACpB,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,qBAAqB;IAClE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,qBAAqB;IAC5D,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,qBAAqB;IAC9D,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,4BAA4B;IACzE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,0BAA0B;IACrE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,mDAAmD;IACtF,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,kDAAkD;CACjF,CAAC;AAEX,MAAM,CAAC,MAAM,wBAAwB,GAAmC;IACtE,SAAS,EAAE;QACT,IAAI,EAAE,WAAW;QACjB,OAAO,EAAE,aAAa,CAAC,SAAS;QAChC,WAAW,EAAE,kBAAkB;KAChC;IACD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,YAAY,EAAE;IACpF,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE;IACpF,UAAU,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,aAAa,CAAC,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE;IAChG,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,CAAC,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE;IACxF,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,CAAC,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE;IACxE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,eAAe,EAAE;CACxF,CAAC;AAEF,MAAM,CAAC,MAAM,oBAAoB,GAAG;IAClC,SAAS,EAAE,4BAAuC;IAClD,aAAa,EACV,OAAO,CAAC,GAAG,CAAC,0BAAsC,IAAK,mBAA+B;IACzF,UAAU,EAAG,OAAO,CAAC,GAAG,CAAC,uBAAmC,IAAK,gBAA4B;CACrF,CAAC;AAEX,SAAS,oBAAoB;IAC3B,2CAA2C;IAC3C,oDAAoD;IACpD,OAAO,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE,CAAC;AAC3E,CAAC;AAED,kDAAkD;AAElD,SAAS,kBAAkB,CAAC,MAAoE;IAC9F,MAAM,cAAc,GAAG,YAAY,CAAC;QAClC,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,EAAE;QAC3B,GAAG,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CAAC,CAAC;IACH,OAAO,IAAI,KAAK,CAAC,cAAc,EAAE;QAC/B,GAAG,CAAC,OAAO,EAAE,IAAI;YACf,IAAI,IAAI,KAAK,eAAe,EAAE,CAAC;gBAC7B,OAAO,CAAC,OAAe,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3D,CAAC;YACD,IAAI,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;gBAC7C,OAAO,cAAc,CAAC,IAAmC,CAAC,CAAC;YAC7D,CAAC;YACD,IAAI,IAAI,KAAK,gBAAgB,IAAI,IAAI,KAAK,YAAY,EAAE,CAAC;gBACvD,MAAM,MAAM,GAAG,cAAc,CAAC,IAAmC,CAAC,CAAC;gBACnE,OAAO,MAAM,IAAI,SAAS,CAAC;YAC7B,CAAC;YACD,OAAO,cAAc,CAAC,IAAmC,CAAC,CAAC;QAC7D,CAAC;KACF,CAAC,CAAC;AACL,CAAC;AAED,yCAAyC;AAEzC,SAAS,qBAAqB,CAAC,eAA+C;IAC5E,MAAM,iBAAiB,GAAG,oBAAoB,EAAE,CAAC;IACjD,OAAO,sBAAsB,CAC3B;QACE,SAAS,EAAE,eAAe,CAAC;YACzB,MAAM,EAAE,iBAAiB;YACzB,OAAO,EAAE,eAAe,CAAC,SAAS,EAAE,OAAO,IAAI,aAAa,CAAC,SAAS;SACvE,CAAC;QACF,MAAM,EAAE,kBAAkB,CAAC;YACzB,MAAM,EAAE,iBAAiB;YACzB,OAAO,EAAE,eAAe,CAAC,MAAM,EAAE,OAAO,IAAI,aAAa,CAAC,MAAM;SACjE,CAAC;QACF,OAAO,EAAE,sBAAsB,CAAC;YAC9B,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,eAAe,CAAC,OAAO,EAAE,OAAO,IAAI,aAAa,CAAC,OAAO;YAClE,MAAM,EAAE,iBAAiB;SAC1B,CAAC;QACF,UAAU,EAAE,sBAAsB,CAAC;YACjC,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,eAAe,CAAC,UAAU,EAAE,OAAO,IAAI,aAAa,CAAC,UAAU;YACxE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;SAC3C,CAAC;QACF,QAAQ,EAAE,cAAc,CAAC;YACvB,OAAO,EAAE,eAAe,CAAC,QAAQ,EAAE,OAAO,IAAI,aAAa,CAAC,QAAQ;YACpE,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,IAAI,EAAE;SAC3C,CAAC;QACF,MAAM,EAAE,wBAAwB,CAAC;YAC/B,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,EAAE;YACxC,OAAO,EAAE,eAAe,CAAC,MAAM,EAAE,OAAO,IAAI,aAAa,CAAC,MAAM;SACjE,CAAC;QACF,IAAI,EAAE,aAAa,CAAC;YAClB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,EAAE;YAC1E,OAAO,EAAE,eAAe,CAAC,IAAI,EAAE,OAAO,IAAI,aAAa,CAAC,IAAI;SAC7D,CAAC;KACH,EACD,EAAE,SAAS,EAAE,GAAG,EAAE,CACnB,CAAC;AACJ,CAAC;AAOD,IAAI,cAAc,GAAyB,IAAI,CAAC;AAChD,IAAI,cAAc,GAAkB,IAAI,CAAC;AAEzC,MAAM,UAAU,kBAAkB,CAAC,eAA+C;IAChF,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC;IACnD,IAAI,cAAc,IAAI,cAAc,KAAK,UAAU;QAAE,OAAO,cAAc,CAAC;IAC3E,cAAc,GAAG,qBAAqB,CAAC,eAAe,CAAC,CAAC;IACxD,cAAc,GAAG,UAAU,CAAC;IAC5B,UAAU,CACR,yCAAyC,EACzC,UAAU,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CACpC,CAAC;IACF,OAAO,cAAc,CAAC;AACxB,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { type LanguageModel, type LanguageModelUsage } from "ai";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { type AppError } from "../errors/index.ts";
|
|
4
|
+
export interface SafeGenerateObjectOptions<T> {
|
|
5
|
+
model: LanguageModel;
|
|
6
|
+
schema: z.ZodType<T>;
|
|
7
|
+
schemaName?: string | undefined;
|
|
8
|
+
system?: string | undefined;
|
|
9
|
+
prompt: string;
|
|
10
|
+
onError?: ((error: AppError, rawText?: string) => void) | undefined;
|
|
11
|
+
}
|
|
12
|
+
export interface SafeGenerateObjectSuccess<T> {
|
|
13
|
+
success: true;
|
|
14
|
+
data: T;
|
|
15
|
+
usage?: LanguageModelUsage | undefined;
|
|
16
|
+
}
|
|
17
|
+
export interface SafeGenerateObjectFailure {
|
|
18
|
+
success: false;
|
|
19
|
+
error: AppError;
|
|
20
|
+
rawText?: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
export type SafeGenerateObjectResult<T> = SafeGenerateObjectSuccess<T> | SafeGenerateObjectFailure;
|
|
23
|
+
export declare function safeGenerateObject<T>(options: SafeGenerateObjectOptions<T>): Promise<SafeGenerateObjectResult<T>>;
|
|
24
|
+
export interface SafeGenerateTextOptions {
|
|
25
|
+
model: LanguageModel;
|
|
26
|
+
system?: string | undefined;
|
|
27
|
+
prompt: string;
|
|
28
|
+
timeoutMs?: number | undefined;
|
|
29
|
+
maxOutputTokens?: number | undefined;
|
|
30
|
+
context?: string | undefined;
|
|
31
|
+
onError?: ((error: AppError) => void) | undefined;
|
|
32
|
+
}
|
|
33
|
+
export interface SafeGenerateTextUsage {
|
|
34
|
+
inputTokens: number | undefined;
|
|
35
|
+
outputTokens: number | undefined;
|
|
36
|
+
totalTokens: number | undefined;
|
|
37
|
+
}
|
|
38
|
+
export interface SafeGenerateTextSuccess {
|
|
39
|
+
success: true;
|
|
40
|
+
text: string;
|
|
41
|
+
usage?: SafeGenerateTextUsage | undefined;
|
|
42
|
+
latencyMs: number;
|
|
43
|
+
}
|
|
44
|
+
export interface SafeGenerateTextFailure {
|
|
45
|
+
success: false;
|
|
46
|
+
error: AppError;
|
|
47
|
+
}
|
|
48
|
+
export type SafeGenerateTextResult = SafeGenerateTextSuccess | SafeGenerateTextFailure;
|
|
49
|
+
export declare function safeGenerateText(options: SafeGenerateTextOptions): Promise<SafeGenerateTextResult>;
|
|
50
|
+
//# sourceMappingURL=structured-output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"structured-output.d.ts","sourceRoot":"","sources":["../../src/ai/structured-output.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACxB,MAAM,IAAI,CAAC;AACZ,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAkC,KAAK,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAKnF,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACrE;AAED,MAAM,WAAW,yBAAyB,CAAC,CAAC;IAC1C,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,CAAC,CAAC;IACR,KAAK,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACxC;AAED,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAED,MAAM,MAAM,wBAAwB,CAAC,CAAC,IAAI,yBAAyB,CAAC,CAAC,CAAC,GAAG,yBAAyB,CAAC;AAEnG,wBAAsB,kBAAkB,CAAC,CAAC,EACxC,OAAO,EAAE,yBAAyB,CAAC,CAAC,CAAC,GACpC,OAAO,CAAC,wBAAwB,CAAC,CAAC,CAAC,CAAC,CAwBtC;AAOD,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,aAAa,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;CACnD;AAED,MAAM,WAAW,qBAAqB;IACpC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,YAAY,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,IAAI,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,qBAAqB,GAAG,SAAS,CAAC;IAC1C,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,QAAQ,CAAC;CACjB;AAED,MAAM,MAAM,sBAAsB,GAAG,uBAAuB,GAAG,uBAAuB,CAAC;AAEvF,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,GAC/B,OAAO,CAAC,sBAAsB,CAAC,CAmDjC"}
|