@roll-agent/smart-reply-agent 1.2.0 → 1.2.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.
- package/SKILL.md +5 -2
- package/dist/diagnostics/effective-env.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/references/env.yaml +5 -0
package/SKILL.md
CHANGED
|
@@ -80,8 +80,9 @@ npm 包名:`@roll-agent/smart-reply-agent`
|
|
|
80
80
|
|
|
81
81
|
机器可读的 env 契约见 `references/env.yaml`。如果你是上层编排 Agent,请优先读取它来生成/校验 `agents.env.smart-reply-agent` 配置。
|
|
82
82
|
|
|
83
|
-
- `REPLY_AUTHORITY_URL` — Reply Authority Service
|
|
84
|
-
- `REPLY_AUTHORITY_BEARER_TOKEN` — 调用 `POST /generate-signed-reply` 的 Bearer token
|
|
83
|
+
- `REPLY_AUTHORITY_URL` — Reply Authority Service 基础地址(必填)
|
|
84
|
+
- `REPLY_AUTHORITY_BEARER_TOKEN` — 调用 `POST /generate-signed-reply` 的 Bearer token(必填)
|
|
85
|
+
- `REPLY_AUTHORITY_TIMEOUT_MS` — Reply Authority Service HTTP 请求超时毫秒数(可选,默认 `30000`)。非正整数或非法值会被静默忽略并回落到默认值
|
|
85
86
|
|
|
86
87
|
## 典型跨 Agent 工作流
|
|
87
88
|
|
|
@@ -103,4 +104,6 @@ agents:
|
|
|
103
104
|
smart-reply-agent:
|
|
104
105
|
REPLY_AUTHORITY_URL: https://reply-authority.duliday.com
|
|
105
106
|
REPLY_AUTHORITY_BEARER_TOKEN: ${REPLY_AUTHORITY_BEARER_TOKEN}
|
|
107
|
+
# 可选:自定义 HTTP 超时(毫秒,默认 30000)
|
|
108
|
+
# REPLY_AUTHORITY_TIMEOUT_MS: "45000"
|
|
106
109
|
```
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
-
export declare const SMART_REPLY_DECLARED_ENV_KEYS: readonly ["REPLY_AUTHORITY_URL", "REPLY_AUTHORITY_BEARER_TOKEN"];
|
|
2
|
+
export declare const SMART_REPLY_DECLARED_ENV_KEYS: readonly ["REPLY_AUTHORITY_URL", "REPLY_AUTHORITY_BEARER_TOKEN", "REPLY_AUTHORITY_TIMEOUT_MS"];
|
|
3
3
|
export declare const EffectiveEnvSourceSchema: z.ZodObject<{
|
|
4
4
|
present: z.ZodBoolean;
|
|
5
5
|
fingerprint: z.ZodOptional<z.ZodString>;
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{defineAgent as e}from"@roll-agent/sdk";import{defineTool as t}from"@roll-agent/sdk";import{z as r}from"zod";import{createHash as n}from"node:crypto";import{z as i}from"zod";var o=["REPLY_AUTHORITY_URL","REPLY_AUTHORITY_BEARER_TOKEN"],a=/^[0-9a-f]{8}$/,s=i.object({present:i.boolean(),fingerprint:i.string().regex(a).optional()}),c=i.record(s);function
|
|
1
|
+
import{defineAgent as e}from"@roll-agent/sdk";import{defineTool as t}from"@roll-agent/sdk";import{z as r}from"zod";import{createHash as n}from"node:crypto";import{z as i}from"zod";var o=["REPLY_AUTHORITY_URL","REPLY_AUTHORITY_BEARER_TOKEN","REPLY_AUTHORITY_TIMEOUT_MS"],a=/^[0-9a-f]{8}$/,s=i.object({present:i.boolean(),fingerprint:i.string().regex(a).optional()}),c=i.record(s);function u(e,t=process.env){return Object.fromEntries(e.map(e=>{const r=t[e];return"string"==typeof r&&r.length>0?[e,{present:!0,fingerprint:d(r)}]:[e,{present:!1}]}))}function d(e){return n("sha256").update(e).digest("hex").slice(0,8)}var g=r.object({effectiveEnvSources:c}),l=t({name:"diagnostic_status",description:"返回 smart-reply 运行态进程中已声明环境变量的存在状态与短指纹",input:r.object({}),output:g,execute:async(e,t)=>(t.logger.info("Querying smart-reply diagnostic status"),{effectiveEnvSources:u(o)})});import{defineTool as p}from"@roll-agent/sdk";import{randomUUID as m}from"node:crypto";import{z as f}from"zod";import{z as I}from"zod";var y=I.object({name:I.string(),baseURL:I.string(),description:I.string()}),b=I.record(I.string(),y),h=I.object({chatModel:I.string().optional(),classifyModel:I.string().optional(),replyModel:I.string().optional(),providerConfigs:b.optional()});import{z as v}from"zod";var R=["trust_building","private_channel","qualify_candidate","job_consultation","interview_scheduling","onboard_followup"],w=v.enum(R);import{z as E}from"zod";var S=E.object({name:E.string().optional(),position:E.string().optional(),expectedPosition:E.string().optional(),communicationPosition:E.string().optional(),age:E.string().optional(),gender:E.string().optional(),experience:E.string().optional(),education:E.string().optional(),expectedSalary:E.string().optional(),expectedLocation:E.string().optional(),jobAddress:E.string().optional(),height:E.string().optional(),weight:E.string().optional(),healthCertificate:E.boolean().optional(),activeTime:E.string().optional(),info:E.array(E.string()).optional(),fullText:E.string().optional()}),T=f.object({platform:f.literal("zhipin"),username:f.string().min(1),accountId:f.string().min(1).optional()}),A=f.object({platform:f.literal("zhipin"),tenantId:f.string().min(1).optional(),conversationId:f.string().min(1),candidateId:f.string().min(1)}),_=A.extend({recruiterBinding:T.optional(),recruiterUsername:f.string().min(1).optional()}).superRefine((e,t)=>{const r=void 0!==e.recruiterBinding,n=void 0!==e.recruiterUsername;r||n||t.addIssue({code:f.ZodIssueCode.custom,message:"target.recruiterBinding 或 target.recruiterUsername 至少需要提供一个。",path:["recruiterBinding"]}),r&&!n&&void 0===e.tenantId&&t.addIssue({code:f.ZodIssueCode.custom,message:"直接传 target.recruiterBinding 时,target.tenantId 也必须显式提供。",path:["tenantId"]}),r&&n&&void 0!==e.recruiterBinding&&e.recruiterBinding.username!==e.recruiterUsername&&t.addIssue({code:f.ZodIssueCode.custom,message:"target.recruiterUsername 必须与 target.recruiterBinding.username 一致。",path:["recruiterUsername"]})}),B=A.extend({tenantId:f.string().min(1),recruiterBinding:T}),U=f.object({candidateMessage:f.string().describe("候选人发送的消息"),conversationHistory:f.array(f.string()).optional().describe("对话历史(最近几轮)"),candidateInfo:S.optional().describe("候选人基本信息"),preferredBrand:f.string().optional().describe("偏好品牌"),channelType:f.enum(["public","private"]).optional().describe("渠道类型: public(BOSS直聘) 或 private(微信)"),defaultWechatId:f.string().optional().describe("默认微信号"),industryVoiceId:f.string().optional().describe("行业语调ID"),turnIndex:f.number().int().min(1).optional().describe("当前会话回复轮次"),modelConfig:h.optional().describe("模型配置覆盖"),target:_.describe("签名绑定目标:租户、会话和候选人标识")}),x=U.omit({target:!0}).extend({target:B,requestId:f.string().optional()}),j=f.object({suggestedReply:f.string(),signedEnvelope:f.string().describe("Reply Authority Service v2 紧凑签名信封"),envelopeExp:f.number().int(),confidence:f.number(),stage:w,replyPolicySource:f.enum(["file","default"]),latencyMs:f.number().optional(),shouldExchangeWechat:f.boolean().optional(),error:f.string().optional(),diagnostics:f.record(f.unknown()).optional()}),q=f.object({platform:f.literal("zhipin"),username:f.string().min(1),accountId:f.string().min(1).optional()}),$=f.object({tenantId:f.string().min(1),recruiterBinding:T}),O=f.object({statusCode:f.number().int(),error:f.string(),message:f.string()}),z=3e4;function M(){const e=process.env.REPLY_AUTHORITY_TIMEOUT_MS?.trim();if(!e)return z;const t=Number.parseInt(e,10);return!Number.isInteger(t)||t<=0||String(t)!==e?z:t}var P=class extends Error{meta;constructor(e,t){super(`${e} (${N(t.meta)})`,{cause:t.cause}),this.name="ReplyAuthorityRequestError",this.meta=t.meta}};function Y(e){const t=process.env[e]?.trim();if(!t)throw new Error(`${e} 未配置,smart-reply-agent 无法调用 Reply Authority Service。`);return t}function L(){return{baseUrl:Y("REPLY_AUTHORITY_URL"),bearerToken:Y("REPLY_AUTHORITY_BEARER_TOKEN")}}function C(e,t){const r=e.endsWith("/")?e:`${e}/`;return new URL(t,r).toString()}function k(e,t){return{"Content-Type":"application/json",Authorization:`Bearer ${e.bearerToken}`,"x-request-id":t.requestId}}function H(e,t){const r=O.safeParse(t);return r.success?`Reply Authority Service 请求失败 (${e}): ${r.data.message}`:`Reply Authority Service 请求失败 (${e})`}function N(e){const t=[`url=${e.url}`,`timeoutMs=${String(e.timeoutMs)}`];return void 0!==e.requestId&&t.push(`requestId=${e.requestId}`),t.join(", ")}function J(e,t,r){return{url:C(e.baseUrl,t),timeoutMs:r.timeoutMs,requestId:r.requestId}}function W(e,t){return e instanceof P?e:e instanceof Error&&"AbortError"===e.name?new P("Reply Authority Service 请求超时。",{cause:e,meta:t}):e instanceof Error?new P(e.message,{cause:e,meta:t}):new P("Reply Authority Service 请求失败。",{cause:e,meta:t})}function Z(e,t,r,n){const i=e.safeParse(t);if(i.success)return i.data;throw new P(`${n} 响应校验失败。`,{cause:i.error,meta:r})}async function K(e){const t=await e.text();if(0===t.trim().length)return null;try{return JSON.parse(t)}catch{throw new Error("Reply Authority Service 返回了非 JSON 响应。")}}async function D(e,t,r,n){const i=J(e,t,n);try{const t=await fetch(i.url,{method:"POST",headers:k(e,n),body:JSON.stringify(r),signal:n.signal}),o=await K(t);if(!t.ok)throw new Error(H(t.status,o));return o}catch(e){throw W(e,i)}}function F(e){return q.parse({platform:e.platform,username:e.recruiterUsername})}async function Q(e,t,r){const n=F(t),i=await D(e,"resolve-recruiter-binding",n,r);return Z($,i,J(e,"resolve-recruiter-binding",r),"Reply Authority Service recruiter 解析")}function V(e,t,r){if(void 0!==t.tenantId&&t.tenantId!==e.tenantId)throw new P(`Reply Authority Service recruiter 解析结果与 target.tenantId 不一致:${e.tenantId}`,{meta:r});return{tenantId:e.tenantId,recruiterBinding:e.recruiterBinding}}async function G(e,t,r){if(void 0!==e.target.recruiterBinding&&void 0!==e.target.tenantId)return x.parse({...e,target:{platform:e.target.platform,tenantId:e.target.tenantId,conversationId:e.target.conversationId,candidateId:e.target.candidateId,recruiterBinding:e.target.recruiterBinding},requestId:r.requestId});const n=V(await Q(t,e.target,r),e.target,J(t,"resolve-recruiter-binding",r));return x.parse({...e,target:{platform:e.target.platform,tenantId:n.tenantId,conversationId:e.target.conversationId,candidateId:e.target.candidateId,recruiterBinding:n.recruiterBinding},requestId:r.requestId})}async function X(e){const t=U.parse(e),r=x.safeParse(t),n=L(),i=M(),o=new AbortController,a={signal:o.signal,timeoutMs:i,requestId:m()},s=setTimeout(()=>o.abort(),i);try{const e=r.success?x.parse({...r.data,requestId:r.data.requestId??a.requestId}):await G(t,n,a),i=await D(n,"generate-signed-reply",e,a);return Z(j,i,J(n,"generate-signed-reply",a),"Reply Authority Service 签名回复")}finally{clearTimeout(s)}}var ee=p({name:"generate_reply",description:"根据候选人消息生成智能招聘回复,并向 Reply Authority Service 请求签名信封;调用方必须提供 target 以绑定会话和招聘者身份,可直接传 tenantId+recruiterBinding,或只传 recruiterUsername 交给 smart-reply 代理解析。",input:U,output:j,execute:async(e,t)=>{t.logger.info(`Processing message: ${e.candidateMessage.slice(0,50)}...`);const r=await X(e);return t.logger.info(`Signed reply generated. Stage: ${r.stage}, Confidence: ${r.confidence}`),r}}),te=e({name:"smart-reply-agent",tools:[ee,l]});te.listen().catch(e=>{console.error("Fatal error:",e),process.exit(1)});
|
package/package.json
CHANGED
package/references/env.yaml
CHANGED
|
@@ -5,3 +5,8 @@ required:
|
|
|
5
5
|
- name: REPLY_AUTHORITY_BEARER_TOKEN
|
|
6
6
|
purpose: Reply Authority Service Bearer token;服务端据此反查 clientId 并校验可访问的 tenantId
|
|
7
7
|
example: ${REPLY_AUTHORITY_BEARER_TOKEN}
|
|
8
|
+
optional:
|
|
9
|
+
- name: REPLY_AUTHORITY_TIMEOUT_MS
|
|
10
|
+
purpose: Reply Authority Service HTTP 请求超时(毫秒)。未设置或值无效时回落默认 30000
|
|
11
|
+
example: "30000"
|
|
12
|
+
default: "30000"
|