forked from ChaiHao/BPOS-MVP
M2: 基座能力 —— memory / toolbox / channel / message
- memory 任务记忆四性质(只追加·信封盖戳·治理先行·归侧)、活动记忆四层与条目三件套、
任务日志两级投影(结构化零 LLM / 叙述性小结不入事实库)、度量八指标只读投影
- toolbox 注册两审(静态审 + 试运行审)、效应等级决定运行时待遇、契约演进只增不破坏、
白名单与纯工具私有作用域、ToolInvoker(两缝之二,live/record/replay)
- channel 通道实例配置、入站归一(解析 → 系统写 → 数据事件)、出站发送与关联记录登记
- message 通知 / 跨任务征答(就地作答 · 驳回重答只增不改)/ 死信 / 无主兜底
app:message 接上 event 的 MessageFallback;派发器按目标 ID 取 advisory lock 串行消费 +
消费幂等表;/api/ingest 模拟邮件通道(mock 只在外界)
已验证:无主 RFQ 邮件入站 → 归属解析 no-match → 事件落库 → 兜底落 OP 岗位的消息要素
门禁五道全绿;150 个单元测试 + 1 个 PG 集成测试
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
co-authored by
Claude Opus 5
parent
14d4fa046a
commit
f0444f1417
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
* module: toolbox —— 对外类型(编码规范 §10.1)。
|
||||
*
|
||||
* 两条缝之二(§7.3):`ToolInvoker` 支持 record | replay | live ——
|
||||
* **任何工具执行不经 ToolInvoker,回放审就对它失明**(§12.5#10)。
|
||||
*/
|
||||
import type { ActionIntent, TaskId } from '@contracts';
|
||||
import type { AuditFinding } from './internal/domain/registration-audit.ts';
|
||||
import type { CallDisposition, EffectLevel, EvolutionViolation, Preauthorization, ToolContract } from './internal/domain/tool-contract.ts';
|
||||
export type { ActionIntent, AuditFinding, CallDisposition, EffectLevel, EvolutionViolation, Preauthorization, ToolContract };
|
||||
export declare const INVOKER_MODES: readonly ["live", "record", "replay"];
|
||||
export type InvokerMode = (typeof INVOKER_MODES)[number];
|
||||
export declare class ToolNotFoundError extends Error {
|
||||
readonly tool: string;
|
||||
constructor(tool: string);
|
||||
}
|
||||
export declare class ToolNotAllowedError extends Error {
|
||||
readonly tool: string;
|
||||
readonly activityId: string;
|
||||
constructor(tool: string, activityId: string);
|
||||
}
|
||||
export declare class ToolDisabledError extends Error {
|
||||
readonly tool: string;
|
||||
constructor(tool: string);
|
||||
}
|
||||
export declare class ToolReplayMissError extends Error {
|
||||
readonly key: string;
|
||||
constructor(key: string);
|
||||
}
|
||||
export declare class RegistrationRejectedError extends Error {
|
||||
readonly findings: readonly AuditFinding[];
|
||||
constructor(findings: readonly AuditFinding[]);
|
||||
}
|
||||
export type ToolCall = {
|
||||
readonly tool: string;
|
||||
readonly operation?: string;
|
||||
readonly input: Record<string, unknown>;
|
||||
readonly activityId: string;
|
||||
readonly taskId?: TaskId;
|
||||
readonly stepNo?: number;
|
||||
};
|
||||
export type ToolResult = {
|
||||
readonly ok: boolean;
|
||||
readonly output?: Record<string, unknown>;
|
||||
readonly error?: {
|
||||
readonly code: string;
|
||||
readonly retryable: boolean;
|
||||
readonly message: string;
|
||||
};
|
||||
readonly latencyMs: number;
|
||||
readonly mode: InvokerMode;
|
||||
};
|
||||
/** 调用留痕:入参快照、出参、时延与错误自动留痕入任务记忆(OS 7.3) */
|
||||
export type InvocationTrace = {
|
||||
readonly tool: string;
|
||||
readonly input: Record<string, unknown>;
|
||||
readonly result: ToolResult;
|
||||
readonly at: string;
|
||||
};
|
||||
/**
|
||||
* 工具调用器 —— 活动基座六件里的「工具(调用契约)」。
|
||||
* **读类**过程中自由调用;**写类**登记为动作意向,放行后落地(除契约显式预授权者)。
|
||||
*/
|
||||
export type ToolInvoker = {
|
||||
readonly mode: InvokerMode;
|
||||
/** 判定运行时待遇 —— 调用方据此决定是即调还是登记意向 */
|
||||
disposition(call: ToolCall, preauthorized: readonly Preauthorization[]): Promise<CallDisposition>;
|
||||
invoke(call: ToolCall): Promise<ToolResult>;
|
||||
/** 落地预检第四项:工具契约含 validate 能力时调之(ADR-005) */
|
||||
validate(call: ToolCall): Promise<ToolResult | undefined>;
|
||||
withMode(mode: InvokerMode): ToolInvoker;
|
||||
};
|
||||
export type RegisterToolInput = {
|
||||
readonly contract: ToolContract;
|
||||
/** 契约测试集:样例入参 → 期望出参形状;试运行审的依据 */
|
||||
readonly samples: ReadonlyArray<{
|
||||
input: Record<string, unknown>;
|
||||
expectShape: Record<string, unknown>;
|
||||
}>;
|
||||
/** 连接配置的值 —— 只存治理台,加密落库(ADR-009) */
|
||||
readonly connectionValues?: Readonly<Record<string, string>>;
|
||||
};
|
||||
export type RegistrationVerdict = {
|
||||
readonly accepted: boolean;
|
||||
readonly staticFindings: readonly AuditFinding[];
|
||||
readonly evolution: readonly EvolutionViolation[];
|
||||
readonly trialRun: {
|
||||
readonly ran: number;
|
||||
readonly passed: number;
|
||||
readonly failures: readonly string[];
|
||||
};
|
||||
};
|
||||
export type ToolboxService = {
|
||||
/** 注册两审:静态审读清单,试运行审验代码 */
|
||||
register(input: RegisterToolInput): Promise<RegistrationVerdict>;
|
||||
list(): Promise<ToolContract[]>;
|
||||
get(name: string): Promise<ToolContract | undefined>;
|
||||
/** 有活动声明引用的工具不得删除;可停用 —— 停用后调用返回结构化错误 */
|
||||
setEnabled(name: string, enabled: boolean): Promise<void>;
|
||||
bindConnection(name: string, values: Readonly<Record<string, string>>): Promise<void>;
|
||||
/** 白名单:活动只经调用契约用工具,授权在白名单与契约,不在活动代码 */
|
||||
setAllowlist(activityId: string, tools: readonly string[]): Promise<void>;
|
||||
allowlistOf(activityId: string): Promise<string[]>;
|
||||
/** 安装静态审:活动声明的工具契约齐备?装不齐不上架 */
|
||||
assertContractsAvailable(names: readonly string[]): Promise<{
|
||||
ok: boolean;
|
||||
missing: string[];
|
||||
}>;
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
/**
|
||||
* module: toolbox —— 唯一出口。只做 re-export,不写逻辑(编码规范 §10.1)。
|
||||
*/
|
||||
export type { ActionIntent, AuditFinding, CallDisposition, EffectLevel, EvolutionViolation, InvocationTrace, InvokerMode, Preauthorization, RegisterToolInput, RegistrationVerdict, ToolCall, ToolContract, ToolInvoker, ToolResult, ToolboxService, } from './contract.ts';
|
||||
export { INVOKER_MODES, RegistrationRejectedError, ToolDisabledError, ToolNotAllowedError, ToolNotFoundError, ToolReplayMissError, } from './contract.ts';
|
||||
export type { Clock, IdGenerator, SchemaValidator, SecretBox, ToolRegistry, ToolReplayStore, ToolRuntime, } from './port.ts';
|
||||
export type { ToolInvokerDeps } from './internal/usecase/tool-invoker.ts';
|
||||
export { createToolInvoker, toolReplayKey } from './internal/usecase/tool-invoker.ts';
|
||||
export type { ToolboxServiceDeps } from './internal/usecase/toolbox-service.ts';
|
||||
export { createToolboxService } from './internal/usecase/toolbox-service.ts';
|
||||
export { checkEvolution, dispositionOf, EFFECT_LEVEL_LABEL, EFFECT_LEVELS } from './internal/domain/tool-contract.ts';
|
||||
export { auditPassed, staticAudit } from './internal/domain/registration-audit.ts';
|
||||
export type { ToolHandler } from './internal/adapter/toolbox-store.ts';
|
||||
export { createSchemaValidator, createToolRegistry, createToolReplayStore, createToolRuntime, isAllowed, } from './internal/adapter/toolbox-store.ts';
|
||||
export { replayToolTable, toolAllowlistTable, toolTable } from './internal/adapter/toolbox-schema.ts';
|
||||
@@ -0,0 +1,68 @@
|
||||
/**
|
||||
* module: toolbox —— 本模块要外界提供的能力(编码规范 §10.1 / §5.3)。
|
||||
*/
|
||||
import type { ToolContract } from './internal/domain/tool-contract.ts';
|
||||
import type { ToolCall, ToolResult } from './contract.ts';
|
||||
export type Clock = {
|
||||
now(): Date;
|
||||
};
|
||||
export type IdGenerator = {
|
||||
next(): string;
|
||||
};
|
||||
/** 凭证密封 —— 与 llm 同一实现,由 app 注入(ADR-009) */
|
||||
export type SecretBox = {
|
||||
seal(plaintext: string): string;
|
||||
open(cipher: string): string;
|
||||
};
|
||||
export type ToolRegistry = {
|
||||
list(): Promise<ToolContract[]>;
|
||||
get(name: string): Promise<ToolContract | undefined>;
|
||||
isEnabled(name: string): Promise<boolean>;
|
||||
upsert(contract: ToolContract, connectionCipher: Record<string, string> | null): Promise<void>;
|
||||
setEnabled(name: string, enabled: boolean): Promise<void>;
|
||||
connectionCipher(name: string): Promise<Record<string, string> | undefined>;
|
||||
setAllowlist(activityId: string, tools: readonly string[]): Promise<void>;
|
||||
allowlistOf(activityId: string): Promise<string[]>;
|
||||
/** 有活动声明引用即不得删除 */
|
||||
referencedBy(name: string): Promise<string[]>;
|
||||
};
|
||||
/** 工具录制回放存储 —— 与 llm 的 ReplayStore 同构,另存一表(§7.3) */
|
||||
export type ToolReplayStore = {
|
||||
put(record: {
|
||||
key: string;
|
||||
call: ToolCall;
|
||||
result: ToolResult;
|
||||
recordedAt: Date;
|
||||
}): Promise<void>;
|
||||
get(key: string): Promise<{
|
||||
call: ToolCall;
|
||||
result: ToolResult;
|
||||
} | undefined>;
|
||||
};
|
||||
/**
|
||||
* 工具执行 —— 实现对系统:server 侧执行代码,运行时受限,
|
||||
* **只可访问注册申报的连接目标,无其他环境能力**(OS 7.3)。
|
||||
*/
|
||||
export type ToolRuntime = {
|
||||
execute(input: {
|
||||
readonly contract: ToolContract;
|
||||
readonly connection: Readonly<Record<string, string>>;
|
||||
readonly call: ToolCall;
|
||||
readonly idempotencyKey?: string;
|
||||
}): Promise<{
|
||||
ok: boolean;
|
||||
output?: Record<string, unknown>;
|
||||
error?: {
|
||||
code: string;
|
||||
retryable: boolean;
|
||||
message: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
/** JSON Schema 校验 —— ajv 在 adapter,usecase 只见本端口(ADR-003) */
|
||||
export type SchemaValidator = {
|
||||
validate(schema: Record<string, unknown>, value: unknown): {
|
||||
ok: boolean;
|
||||
errors: string[];
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user