This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-TMP-REPO/activities/quote-pricing/src/manifest.ts
T
ChaiHaoandClaude Opus 5 da8ac8f9bc 模型实例卡重做:名字不截、密钥不撒谎、不可用就别摆统计;只留 flash 与 pro 两条
三条毛病一次改净:

**① 名字被截断**。用途名是活动里声明的那个名,看不全等于没显示 —— 卡面改成
   40px 图标 + **名字独占一行、折行也不截**(overflow-wrap: anywhere),
   厂商与型号退到第二行小字。

**② 「已绑定」是谎**。种子从前塞一个 `sk-placeholder` 冒充密钥,卡上写着「已绑定」,
   一自检就是 `api key ... is invalid`;抽屉里那格也照「是不是新建」写占位,
   于是没钥匙的实例也显示「已绑定 · 留空保持原值」。现在:
     · 种子**读不到环境密钥就不绑**,如实显示未绑定;
     · 抽屉的占位与判词改看 `keyBound` —— 没绑就写「还没有密钥 —— 不填这条实例调不动」。
   **界面撒谎比缺功能更坏**:缺功能人会去补,撒谎的人会照着假状态做决定。

**③ 不可用还摆一排统计**。没密钥连调都调不起来,「系统用途/端点」那些格没有意义 ——
   未绑定时卡上只剩一句判词 +「去配置」;绑好了才谈端点与「测试」。
   系统用途从卡面撤了(用户:不要管是不是系统用途,两条都能用)。

**只留两条实例**:`deepseek-v4-flash` 与 `deepseek-v4-pro`,都不预设系统用途。
配套两件:
  · `pickSystemUse` 加**回落** —— 没人勾就取第一条能用的(启用且已绑密钥);
    从前非勾不可,没勾那天系统叙述整条哑掉,那是配置疏忽不该变成功能缺失(补了三条测试);
  · 六个活动包里声明的用途名 `quote-extractor` 改指 `deepseek-v4-flash`,各升一个补丁版。

顺带补 `DELETE /api/gov/llm/:id`(卡上 ⋯ 菜单):还有活动声明着这个用途名就拒(409)——
删了那些活动一调模型就是「用途名未绑定」,而人当时以为只是清一条没用的记录。
实测:用它把库里遗留的 quote-extractor 删掉,现在库里就是那两条,卡上如实写「未绑定密钥 · 不可用」。
五闸绿。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-30 01:53:42 +08:00

195 lines
7.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 活动包清单 —— 统一报价 A4 · 成本定价。
*
* 业务素材:docs/MVP示例工作流.html §1.2(S1 取价基准 → S2 逐条定价 → S3 底价自检)。
* README《已裁定的落地决策》③:**A4 = flow** —— 取价、查表定价、自检的判断
* **全部装进 DMN 决策表确定性求值**;一旦出现「由 AI 决定怎么办」,按 AM 2.1 上升。
*/
import type { ActivityManifest, DmnModel } from '@contracts';
import { PRICING_SKILLS } from './skills.ts';
import { CMMN_XML, NARRATIVE } from './case-model.ts';
import { activityIdSchema } from '@contracts';
import { PRICING_BASIS, PRICING_PRICED, PRICING_RELEASE } from './views/report.ts';
const DOMAIN = 'quote_pricing';
const ACTIVITY_ID = activityIdSchema.parse('quote-pricing');
/**
* 利润模型 P-01 —— 品牌 × 类型 × 客户等级 × 数量档 → 目标毛利。
* 「经验」段落不入决策表(那是技能 / 活动记忆种子:载方法不载权力)。
*/
export const P01_DMN: DmnModel = {
drd: [
{ decision: 'p01-margin', requires: [], inputs: ['customerGrade', 'materialType', 'volumeTier'] },
{ decision: 'p02-floor', requires: ['p01-margin'], inputs: ['quotedPrice', 'floorPrice'] },
],
tables: [
{
id: 'p01-margin',
label: '利润模型 P-01',
hitPolicy: 'FIRST',
inputs: [
{ name: 'customerGrade', expression: 'customerGrade' },
{ name: 'materialType', expression: 'materialType' },
{ name: 'volumeTier', expression: 'volumeTier' },
],
outputs: [{ name: 'marginLow' }, { name: 'marginHigh' }],
rules: [
{ id: 'p01-1', when: ['"战略客户"', '"A"', '"大批量"'], then: [0.08, 0.1], annotation: '战略客户 A 类标准件大批量 8%–10%' },
{ id: 'p01-2', when: ['"普通客户"', '"A"', '-'], then: [0.12, 0.15], annotation: '普通客户 A 类标准件 12%–15%' },
{ id: 'p01-3', when: ['-', '"B"', '-'], then: [0.15, 0.2], annotation: 'B 类波动件 15%–20%' },
{ id: 'p01-4', when: ['-', '"C"', '-'], then: [0.2, 0.5], annotation: 'C 类替代/EOL ≥20% 或一事一议' },
{ id: 'p01-default', when: ['-', '-', '-'], then: [0.12, 0.15], annotation: '兜底按普通客户标准件' },
],
},
{
/** 底价门禁 P-02 —— 偏离底价 ±20% 即止 */
id: 'p02-floor',
label: '底价门禁 P-02',
hitPolicy: 'FIRST',
inputs: [{ name: 'deviation', expression: 'deviation' }],
outputs: [{ name: 'disposition' }, { name: 'passable' }],
rules: [
{ id: 'p02-1', when: ['>= 0'], then: ['直接放行', true], annotation: '≥底价 → 直接放行' },
{ id: 'p02-2', when: ['[-0.20..0)'], then: ['PM 附理由放行', true], annotation: '低于底价 ≤20% → PM 附理由' },
{ id: 'p02-3', when: ['< -0.20'], then: ['拦截 · BOSS 拍板', false], annotation: '低于底价 >20% → 拦截' },
],
},
],
};
export const manifest: ActivityManifest = {
identity: {
activityId: ACTIVITY_ID,
name: 'A4 · 成本定价',
packageVersion: '0.1.6',
category: '统一报价',
sdkVersion: '0.1.0-m5',
checksum: 'dev-checksum-quote-pricing',
},
contract: {
activityId: ACTIVITY_ID,
version: '0.1.0',
input: {
data: {
type: 'object',
required: ['customerCode', 'records'],
properties: {
customerCode: { type: 'string' },
records: { type: 'array' },
// B/C 类由 A3/A2 交回的底价与替代方案;A 类直通时为空
floorPrices: { type: 'array' },
},
},
messageAllowed: true,
},
output: {
mandatory: [
{
name: 'draft',
payload: {
type: 'object',
required: ['items'],
properties: { items: { type: 'array' } },
},
description: '报价草案(逐条带偏离度)',
},
],
selective: [],
},
requiredDeliverables: [{ key: 'quote-draft', label: '报价草案(全条目带偏离度)' }],
acceptanceCriteria: [
{ key: 'all-priced', label: '每条都有拟报单价与毛利率', level: 'L1', predicate: 'unpriced = 0' },
// 底价门禁沉为 L2 机检 —— 「约束力收缩」的终点
{ key: 'floor-gate', label: '偏离底价 ≤±20%,超限者已回调或注明理由', level: 'L2', modelRef: 'p02-floor' },
{ key: 'pm-release', label: 'BD 放行', level: 'L5' },
],
prohibitions: [
{ key: 'no-silent-override', statement: '不得静默绕开 P-02 的结论;要破线只能走「人 · 决策」' },
{ key: 'no-stale-floor', statement: '底价超一周未更新的,先刷底价再判' },
],
authorization: {
discretion: [{ key: 'margin-band', statement: '在 P-01 给出的毛利区间内自决;出区间必须调人决策' }],
preauthorizedActions: [],
humanCallBudget: 3,
},
resources: {
tools: [{ name: 'quote-pricing.basis' }, { name: 'crm.history-price-read' }],
skills: PRICING_SKILLS.map((s) => s.id),
models: ['deepseek-v4-flash'],
roles: ['BD'],
budget: { steps: 60, tokens: 150_000, activeMinutes: 120, humanCalls: 3 },
},
},
declarations: {
models: ['deepseek-v4-flash'],
tools: [{ name: 'crm.history-price-read' }, { name: 'quote-pricing.basis' }],
ledger: [
{
domain: DOMAIN,
object: 'draft',
label: '报价草案',
fields: [
{ name: 'pn', type: 'text', primaryKey: true, masked: false, label: 'PN' },
{ name: 'quoted_price', type: 'number', primaryKey: false, masked: false, label: '拟报单价' },
{ name: 'margin', type: 'number', primaryKey: false, masked: false, label: '毛利率' },
{ name: 'last_price', type: 'number', primaryKey: false, masked: false, label: '基准价' },
{ name: 'deviation', type: 'number', primaryKey: false, masked: false, label: '偏离度' },
{ name: 'disposition', type: 'text', primaryKey: false, masked: false, label: '门禁处置' },
],
},
],
listeners: [
{
origin: 'static',
eventType: 'human',
keyFilter: { kind: 'decision' },
semantic: 'complete-step',
deadline: 'PT4H',
escalation: ['nudge', 'escalate'],
},
],
// SLA <2h(MVP示例 §1.2 留痕 · SLA)
harness: {
memoryWindow: 20,
stallAfter: 'PT2H',
nudge: [{ after: 'PT1H', action: 'nudge' }],
retry: { times: 2, backoff: 'PT30S' },
},
},
assets: {
/* 资产初始版:案例模型(2026-07-29 起活动只有这一种业务模型) */
businessModel: {
cmmnXml: CMMN_XML,
narrative: NARRATIVE,
dmn: P01_DMN,
},
skills: PRICING_SKILLS,
viewTemplates: [
{ name: 'pricing-basis', html: PRICING_BASIS },
{ name: 'pricing-priced', html: PRICING_PRICED },
{ name: 'pricing-release', html: PRICING_RELEASE },
],
cardSchemas: {},
distillHooks: [
{
on: 'terminal',
prompt: '归纳本单定价的经验:哪些组合的毛利档被人回调过、底价门禁拦下的形态、破线的理由。',
},
],
},
samples: [
{
name: '战略客户 A 类大批量',
input: { customerCode: 'C001', records: [{ pn: 'LM358DR', type: 'A' }] },
expect: { ports: ['draft'] },
},
],
entry: { file: 'index.js', checksum: 'dev-entry-quote-pricing' },
};