@mingyuxu/core 0.1.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/README.md +7 -0
- package/dist/coding/agent.d.ts +64 -0
- package/dist/coding/agent.d.ts.map +1 -0
- package/dist/coding/agent.js +179 -0
- package/dist/coding/agent.js.map +1 -0
- package/dist/coding/tools.d.ts +45 -0
- package/dist/coding/tools.d.ts.map +1 -0
- package/dist/coding/tools.js +327 -0
- package/dist/coding/tools.js.map +1 -0
- package/dist/commander.d.ts +108 -0
- package/dist/commander.d.ts.map +1 -0
- package/dist/commander.js +246 -0
- package/dist/commander.js.map +1 -0
- package/dist/extensions.d.ts +26 -0
- package/dist/extensions.d.ts.map +1 -0
- package/dist/extensions.js +66 -0
- package/dist/extensions.js.map +1 -0
- package/dist/goal-loop.d.ts +30 -0
- package/dist/goal-loop.d.ts.map +1 -0
- package/dist/goal-loop.js +96 -0
- package/dist/goal-loop.js.map +1 -0
- package/dist/hooks.d.ts +17 -0
- package/dist/hooks.d.ts.map +1 -0
- package/dist/hooks.js +44 -0
- package/dist/hooks.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -0
- package/dist/loop.d.ts +42 -0
- package/dist/loop.d.ts.map +1 -0
- package/dist/loop.js +86 -0
- package/dist/loop.js.map +1 -0
- package/dist/orchestrator.d.ts +48 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +194 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/reconcile.d.ts +5 -0
- package/dist/reconcile.d.ts.map +1 -0
- package/dist/reconcile.js +28 -0
- package/dist/reconcile.js.map +1 -0
- package/dist/sandbox.d.ts +14 -0
- package/dist/sandbox.d.ts.map +1 -0
- package/dist/sandbox.js +36 -0
- package/dist/sandbox.js.map +1 -0
- package/dist/session.d.ts +43 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +104 -0
- package/dist/session.js.map +1 -0
- package/dist/subagents/dispatch.d.ts +34 -0
- package/dist/subagents/dispatch.d.ts.map +1 -0
- package/dist/subagents/dispatch.js +80 -0
- package/dist/subagents/dispatch.js.map +1 -0
- package/dist/task-graph.d.ts +32 -0
- package/dist/task-graph.d.ts.map +1 -0
- package/dist/task-graph.js +77 -0
- package/dist/task-graph.js.map +1 -0
- package/dist/tools.d.ts +24 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +54 -0
- package/dist/tools.js.map +1 -0
- package/dist/workspace.d.ts +92 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +346 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +34 -0
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 目标驱动构建循环(v2 架构)—— 收敛条件不是「走完相位」,而是「自评达到标准」。
|
|
3
|
+
* build-attempt(拆规则/定方案/出候选) → 自评 → 达标? → 未达标则反思迭代重评 → 达标→交人(HITL)→冻结
|
|
4
|
+
* 与旧 BuildLoop 的区别:停机看自评体系(agent.selfEvaluate 返回 met),未达标走 agent.reflect 反思。
|
|
5
|
+
* build-attempt 阶段复用 advanceOnePhase(reconcile/预算/错误归约不重造);自评+反思是新的外层循环。
|
|
6
|
+
*/
|
|
7
|
+
import { BudgetExceeded, LLMError } from "@mingyuxu/ai";
|
|
8
|
+
import { advanceOnePhase, AWAITING_APPROVAL, FROZEN, BUDGET_EXCEEDED, LLM_ERROR } from "./loop.js";
|
|
9
|
+
import { TERMINAL } from "./session.js";
|
|
10
|
+
export const STANDARD_NOT_MET = "standard_not_met"; // 反思到顶仍未达自评标准(交人裁决)
|
|
11
|
+
export const NEEDS_HUMAN_EVAL = "needs_human_eval"; // 无评测体系可判达标 → 只能交人
|
|
12
|
+
const BUILD_PHASES = ["analyze", "observe", "propose"];
|
|
13
|
+
export class GoalLoop {
|
|
14
|
+
agent;
|
|
15
|
+
policy;
|
|
16
|
+
constructor(agent, policy) {
|
|
17
|
+
this.agent = agent;
|
|
18
|
+
this.policy = policy;
|
|
19
|
+
}
|
|
20
|
+
async run(session, _opts = {}) {
|
|
21
|
+
const ws = this.agent.workspace;
|
|
22
|
+
// ── 冻结再入:达标后 session.phase="freeze",批准后来到这里执行冻结 ──
|
|
23
|
+
if (session.phase === TERMINAL)
|
|
24
|
+
return this.stop(session, FROZEN, 0);
|
|
25
|
+
if (session.phase === "freeze") {
|
|
26
|
+
if (!session.approved)
|
|
27
|
+
return this.stop(session, AWAITING_APPROVAL, 0);
|
|
28
|
+
try {
|
|
29
|
+
await this.agent.runPhase(session);
|
|
30
|
+
} // freeze()(机器门:桩审计/grounding + 需已批准)
|
|
31
|
+
catch (e) {
|
|
32
|
+
throw e;
|
|
33
|
+
} // 机器门拒绝上抛给 CLI 显示
|
|
34
|
+
session.phase = TERMINAL;
|
|
35
|
+
session.event(ws, "phase_advanced", { to: TERMINAL }, this.agent.now());
|
|
36
|
+
session.save(ws, this.agent.now());
|
|
37
|
+
return this.stop(session, FROZEN, 0);
|
|
38
|
+
}
|
|
39
|
+
// ── build attempt:推进到 test 边界(复用相位原语的 reconcile/错误归约)──
|
|
40
|
+
while (BUILD_PHASES.includes(session.phase)) {
|
|
41
|
+
const res = await advanceOnePhase(this.agent, session);
|
|
42
|
+
if (!res.ok)
|
|
43
|
+
return this.stop(session, res.reason, 0);
|
|
44
|
+
}
|
|
45
|
+
// ── 自评 → 反思 外层循环:达标才停 ──
|
|
46
|
+
const maxReflect = Number(this.policy.loop?.max_reflect_iterations ?? 3);
|
|
47
|
+
let iter = 0;
|
|
48
|
+
while (true) {
|
|
49
|
+
let ev;
|
|
50
|
+
try {
|
|
51
|
+
ev = await this.agent.selfEvaluate(session);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
if (e instanceof BudgetExceeded) {
|
|
55
|
+
session.event(ws, "budget_exceeded", {}, this.agent.now());
|
|
56
|
+
return this.stop(session, BUDGET_EXCEEDED, iter);
|
|
57
|
+
}
|
|
58
|
+
if (e instanceof LLMError) {
|
|
59
|
+
session.event(ws, "llm_error", {}, this.agent.now());
|
|
60
|
+
return this.stop(session, LLM_ERROR, iter);
|
|
61
|
+
}
|
|
62
|
+
throw e;
|
|
63
|
+
}
|
|
64
|
+
session.event(ws, "self_eval", { iter, met: ev.met, summary: ev.summary }, this.agent.now());
|
|
65
|
+
if (ev.met === true) { // 达标 → 交人(HITL)
|
|
66
|
+
session.phase = "freeze";
|
|
67
|
+
session.save(ws, this.agent.now());
|
|
68
|
+
return this.stop(session, AWAITING_APPROVAL, iter);
|
|
69
|
+
}
|
|
70
|
+
if (ev.met === null) { // 无评测体系可判 → 交人裁决
|
|
71
|
+
session.phase = "freeze";
|
|
72
|
+
session.save(ws, this.agent.now());
|
|
73
|
+
return this.stop(session, NEEDS_HUMAN_EVAL, iter);
|
|
74
|
+
}
|
|
75
|
+
if (iter >= maxReflect) { // 反思到顶仍不达标 → 交人
|
|
76
|
+
session.phase = "freeze";
|
|
77
|
+
session.save(ws, this.agent.now());
|
|
78
|
+
return this.stop(session, STANDARD_NOT_MET, iter);
|
|
79
|
+
}
|
|
80
|
+
iter += 1;
|
|
81
|
+
const rr = await this.agent.reflect(session); // 反思迭代:读 trace 归因 → 定向修改
|
|
82
|
+
session.event(ws, "reflect", { iter, revised: rr.revised, note: rr.note }, this.agent.now());
|
|
83
|
+
if (!rr.revised) { // 改无可改 → 别空转,交人
|
|
84
|
+
session.phase = "freeze";
|
|
85
|
+
session.save(ws, this.agent.now());
|
|
86
|
+
return this.stop(session, STANDARD_NOT_MET, iter);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
stop(session, reason, iterations) {
|
|
91
|
+
session.save(this.agent.workspace, this.agent.now());
|
|
92
|
+
session.event(this.agent.workspace, "goal_loop_stopped", { reason }, this.agent.now());
|
|
93
|
+
return { stop: reason, phase: session.phase, iterations };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=goal-loop.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"goal-loop.js","sourceRoot":"","sources":["../src/goal-loop.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const HOOK_POINTS: readonly ["pre_phase", "post_phase", "on_llm_call", "on_artifact", "on_stop", "on_heartbeat"];
|
|
2
|
+
export type HookPoint = (typeof HOOK_POINTS)[number];
|
|
3
|
+
export type HookFn = (payload: Record<string, unknown>) => void;
|
|
4
|
+
export declare class HookBus {
|
|
5
|
+
private shellHooks;
|
|
6
|
+
private timeoutMs;
|
|
7
|
+
private handlers;
|
|
8
|
+
failures: {
|
|
9
|
+
point: string;
|
|
10
|
+
error: string;
|
|
11
|
+
}[];
|
|
12
|
+
constructor(shellHooks?: Record<string, string[]>, // {point: [命令...]},payload 从 stdin 喂
|
|
13
|
+
timeoutMs?: number);
|
|
14
|
+
register(point: HookPoint, fn: HookFn): void;
|
|
15
|
+
emit(point: string, payload: Record<string, unknown>): void;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,WAAW,+FAEd,CAAC;AACX,MAAM,MAAM,SAAS,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AACrD,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;AAEhE,qBAAa,OAAO;IAKhB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,SAAS;IALnB,OAAO,CAAC,QAAQ,CAAkC;IAClD,QAAQ,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAM;gBAGxC,UAAU,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAM,EAAI,qCAAqC;IAClF,SAAS,SAAS;IAG5B,QAAQ,CAAC,KAAK,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,GAAG,IAAI;IAK5C,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;CAW5D"}
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hook 机制 —— 生命周期扩展点,观测/联动不侵入内核流程。
|
|
3
|
+
* 六点位:pre_phase / post_phase / on_llm_call / on_artifact / on_stop / on_heartbeat。
|
|
4
|
+
* hook 失败只记账不炸主流程。从 Python tracing/hooks.py 移植(python 回调面)。
|
|
5
|
+
*/
|
|
6
|
+
import { execFileSync } from "node:child_process";
|
|
7
|
+
export const HOOK_POINTS = [
|
|
8
|
+
"pre_phase", "post_phase", "on_llm_call", "on_artifact", "on_stop", "on_heartbeat",
|
|
9
|
+
];
|
|
10
|
+
export class HookBus {
|
|
11
|
+
shellHooks;
|
|
12
|
+
timeoutMs;
|
|
13
|
+
handlers = new Map();
|
|
14
|
+
failures = [];
|
|
15
|
+
constructor(shellHooks = {}, // {point: [命令...]},payload 从 stdin 喂
|
|
16
|
+
timeoutMs = 30_000) {
|
|
17
|
+
this.shellHooks = shellHooks;
|
|
18
|
+
this.timeoutMs = timeoutMs;
|
|
19
|
+
}
|
|
20
|
+
register(point, fn) {
|
|
21
|
+
if (!HOOK_POINTS.includes(point))
|
|
22
|
+
throw new Error(`未知 hook 点位: ${point}`);
|
|
23
|
+
(this.handlers.get(point) ?? this.handlers.set(point, []).get(point)).push(fn);
|
|
24
|
+
}
|
|
25
|
+
emit(point, payload) {
|
|
26
|
+
for (const fn of this.handlers.get(point) ?? []) {
|
|
27
|
+
try {
|
|
28
|
+
fn(payload);
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
this.failures.push({ point, error: `${e.name}: ${e.message}` });
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
for (const cmd of this.shellHooks[point] ?? []) { // shell hook:payload JSON 从 stdin 传
|
|
35
|
+
try {
|
|
36
|
+
execFileSync("/bin/sh", ["-c", cmd], { input: JSON.stringify(payload), timeout: this.timeoutMs, env: { ...process.env, KC_HOOK_POINT: point } });
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
this.failures.push({ point, error: `shell: ${e.message}` });
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,WAAW,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,cAAc;CAC1E,CAAC;AAIX,MAAM,OAAO,OAAO;IAKR;IACA;IALF,QAAQ,GAAG,IAAI,GAAG,EAAuB,CAAC;IAClD,QAAQ,GAAuC,EAAE,CAAC;IAElD,YACU,aAAuC,EAAE,EAAI,qCAAqC;IAClF,YAAY,MAAM;QADlB,eAAU,GAAV,UAAU,CAA+B;QACzC,cAAS,GAAT,SAAS,CAAS;IACzB,CAAC;IAEJ,QAAQ,CAAC,KAAgB,EAAE,EAAU;QACnC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,eAAe,KAAK,EAAE,CAAC,CAAC;QAC1E,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,IAAI,CAAC,KAAa,EAAE,OAAgC;QAClD,KAAK,MAAM,EAAE,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAkB,CAAC,IAAI,EAAE,EAAE,CAAC;YAC7D,IAAI,CAAC;gBAAC,EAAE,CAAC,OAAO,CAAC,CAAC;YAAC,CAAC;YACpB,OAAO,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,GAAI,CAAW,CAAC,IAAI,KAAM,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAAC,CAAC;QACtG,CAAC;QACD,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC,CAAK,oCAAoC;YACxF,IAAI,CAAC;gBACH,YAAY,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;YACnJ,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,UAAW,CAAW,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAAC,CAAC;QACzF,CAAC;IACH,CAAC;CACF"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mingyuxu/core —— 通用 agent 运行时(对标 @earendil-works/pi-agent-core)。
|
|
3
|
+
* 不认识"核查"——只提供通用能力。领域(核查)作为扩展从 check 层插进来。依赖:只 @mingyuxu/ai。
|
|
4
|
+
*/
|
|
5
|
+
export { ToolRegistry, ToolDenied } from "./tools.js";
|
|
6
|
+
export type { ToolFn, ToolLog } from "./tools.js";
|
|
7
|
+
export { ExtensionRegistry, loadExtensions } from "./extensions.js";
|
|
8
|
+
export type { Skill } from "./extensions.js";
|
|
9
|
+
export { reconcile, PHASE_MINIMUM } from "./reconcile.js";
|
|
10
|
+
export { Session, PHASES, TERMINAL, IDENTITY } from "./session.js";
|
|
11
|
+
export type { SessionData } from "./session.js";
|
|
12
|
+
export { HookBus, HOOK_POINTS } from "./hooks.js";
|
|
13
|
+
export type { HookPoint, HookFn } from "./hooks.js";
|
|
14
|
+
export { advanceOnePhase, BuildLoop, FROZEN, PHASE_CHECKPOINT, AWAITING_APPROVAL, RECONCILE_FAILED, BUDGET_EXCEEDED, STUCK, MAX_STEPS, LLM_ERROR, INTERRUPTED, } from "./loop.js";
|
|
15
|
+
export type { Agent, StepResult, LoopResult } from "./loop.js";
|
|
16
|
+
export { GoalLoop, STANDARD_NOT_MET, NEEDS_HUMAN_EVAL } from "./goal-loop.js";
|
|
17
|
+
export type { GoalAgent, GoalResult } from "./goal-loop.js";
|
|
18
|
+
export { Orchestrator, PLAYBOOK, ORCH_SYSTEM, mockDecide } from "./orchestrator.js";
|
|
19
|
+
export type { OrchestratorAgent, Decision, DecideFn, Say } from "./orchestrator.js";
|
|
20
|
+
export { Commander, COMMANDER_SYSTEM, mockCommanderDecide } from "./commander.js";
|
|
21
|
+
export type { CommanderAgent, CommanderAction, CommanderDecision, CommanderDecide, CommanderEvent, CommanderResult, CommanderStep, CommanderStepStatus, CommanderOp, AgentPlan, Capability, CapabilityResult, PromotionState, } from "./commander.js";
|
|
22
|
+
export { lintBrief, spawnSubagent, pollSubagent, waitSubagent, killSubagent } from "./subagents/dispatch.js";
|
|
23
|
+
export type { TypedBrief, SubagentHandle } from "./subagents/dispatch.js";
|
|
24
|
+
export { Sandbox, SandboxViolation } from "./sandbox.js";
|
|
25
|
+
export { CodeAgent, CODE_AGENT_SYSTEM } from "./coding/agent.js";
|
|
26
|
+
export type { CodeAgentOptions, CodeAgentEvent } from "./coding/agent.js";
|
|
27
|
+
export { codingTools, defaultExec, READ_FILE, LIST_DIR, GLOB, GREP, WRITE_FILE, EDIT_FILE, BASH, ASK_MODEL, SPAWN_AGENT, } from "./coding/tools.js";
|
|
28
|
+
export type { CodingTool, ToolContext, ApprovalGate, ExecFn } from "./coding/tools.js";
|
|
29
|
+
export { WorkspaceManager } from "./workspace.js";
|
|
30
|
+
export type { WorkspaceMeta, WorkspaceStatus, WorkspacePaths, WorkspaceEvent, CreateWorkspaceOptions, WorkspaceLease, } from "./workspace.js";
|
|
31
|
+
export { validateTaskGraph, readyTasks, applyGoalPatch } from "./task-graph.js";
|
|
32
|
+
export type { TaskGraph, TaskNode, TaskNodeStatus, GoalPatch } from "./task-graph.js";
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AACtD,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACpE,YAAY,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACnE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClD,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,EACL,eAAe,EAAE,SAAS,EAC1B,MAAM,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAC7D,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,GAC1D,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAC9E,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpF,YAAY,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAClF,YAAY,EACV,cAAc,EAAE,eAAe,EAAE,iBAAiB,EAAE,eAAe,EAAE,cAAc,EACnF,eAAe,EAAE,aAAa,EAAE,mBAAmB,EAAE,WAAW,EAAE,SAAS,EAC3E,UAAU,EAAE,gBAAgB,EAAE,cAAc,GAC7C,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC7G,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACjE,YAAY,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,EACL,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,GACrF,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClD,YAAY,EACV,aAAa,EAAE,eAAe,EAAE,cAAc,EAAE,cAAc,EAAE,sBAAsB,EACtF,cAAc,GACf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAChF,YAAY,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @mingyuxu/core —— 通用 agent 运行时(对标 @earendil-works/pi-agent-core)。
|
|
3
|
+
* 不认识"核查"——只提供通用能力。领域(核查)作为扩展从 check 层插进来。依赖:只 @mingyuxu/ai。
|
|
4
|
+
*/
|
|
5
|
+
export { ToolRegistry, ToolDenied } from "./tools.js";
|
|
6
|
+
export { ExtensionRegistry, loadExtensions } from "./extensions.js";
|
|
7
|
+
export { reconcile, PHASE_MINIMUM } from "./reconcile.js";
|
|
8
|
+
export { Session, PHASES, TERMINAL, IDENTITY } from "./session.js";
|
|
9
|
+
export { HookBus, HOOK_POINTS } from "./hooks.js";
|
|
10
|
+
export { advanceOnePhase, BuildLoop, FROZEN, PHASE_CHECKPOINT, AWAITING_APPROVAL, RECONCILE_FAILED, BUDGET_EXCEEDED, STUCK, MAX_STEPS, LLM_ERROR, INTERRUPTED, } from "./loop.js";
|
|
11
|
+
export { GoalLoop, STANDARD_NOT_MET, NEEDS_HUMAN_EVAL } from "./goal-loop.js";
|
|
12
|
+
export { Orchestrator, PLAYBOOK, ORCH_SYSTEM, mockDecide } from "./orchestrator.js";
|
|
13
|
+
export { Commander, COMMANDER_SYSTEM, mockCommanderDecide } from "./commander.js";
|
|
14
|
+
export { lintBrief, spawnSubagent, pollSubagent, waitSubagent, killSubagent } from "./subagents/dispatch.js";
|
|
15
|
+
export { Sandbox, SandboxViolation } from "./sandbox.js";
|
|
16
|
+
export { CodeAgent, CODE_AGENT_SYSTEM } from "./coding/agent.js";
|
|
17
|
+
export { codingTools, defaultExec, READ_FILE, LIST_DIR, GLOB, GREP, WRITE_FILE, EDIT_FILE, BASH, ASK_MODEL, SPAWN_AGENT, } from "./coding/tools.js";
|
|
18
|
+
export { WorkspaceManager } from "./workspace.js";
|
|
19
|
+
export { validateTaskGraph, readyTasks, applyGoalPatch } from "./task-graph.js";
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEtD,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAEnE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAElD,OAAO,EACL,eAAe,EAAE,SAAS,EAC1B,MAAM,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,gBAAgB,EAC7D,eAAe,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,WAAW,GAC1D,MAAM,WAAW,CAAC;AAEnB,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAE9E,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpF,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAMlF,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAE7G,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEjE,OAAO,EACL,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,GACrF,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAKlD,OAAO,EAAE,iBAAiB,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/loop.d.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Session } from "./session.js";
|
|
2
|
+
export declare const FROZEN = "frozen";
|
|
3
|
+
export declare const PHASE_CHECKPOINT = "phase_checkpoint";
|
|
4
|
+
export declare const AWAITING_APPROVAL = "awaiting_approval";
|
|
5
|
+
export declare const RECONCILE_FAILED = "reconcile_failed";
|
|
6
|
+
export declare const BUDGET_EXCEEDED = "budget_exceeded";
|
|
7
|
+
export declare const STUCK = "stuck";
|
|
8
|
+
export declare const MAX_STEPS = "max_steps";
|
|
9
|
+
export declare const LLM_ERROR = "llm_error";
|
|
10
|
+
export declare const INTERRUPTED = "interrupted";
|
|
11
|
+
/** core 依赖的 agent 契约(check 提供具体实现)——分层单向:core 不认识核查。 */
|
|
12
|
+
export interface Agent {
|
|
13
|
+
workspace: string;
|
|
14
|
+
now(): number;
|
|
15
|
+
runPhase(session: Session): void | Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
export interface StepResult {
|
|
18
|
+
ok: boolean;
|
|
19
|
+
reason: string;
|
|
20
|
+
phase: string;
|
|
21
|
+
ran: boolean;
|
|
22
|
+
nextPhase?: string;
|
|
23
|
+
missing?: string[];
|
|
24
|
+
}
|
|
25
|
+
export declare function advanceOnePhase(agent: Agent, session: Session): Promise<StepResult>;
|
|
26
|
+
export interface LoopResult {
|
|
27
|
+
stop: string;
|
|
28
|
+
phase: string;
|
|
29
|
+
steps: number;
|
|
30
|
+
missing?: string[];
|
|
31
|
+
}
|
|
32
|
+
/** 无人值守驱动器:沿相位推进;相位边界按 auto 决定停不停;freeze 永远等 approve。 */
|
|
33
|
+
export declare class BuildLoop {
|
|
34
|
+
private agent;
|
|
35
|
+
private policy;
|
|
36
|
+
constructor(agent: Agent, policy: Record<string, any>);
|
|
37
|
+
run(session: Session, opts?: {
|
|
38
|
+
auto?: boolean;
|
|
39
|
+
}): Promise<LoopResult>;
|
|
40
|
+
private stop;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=loop.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,EAAY,MAAM,cAAc,CAAC;AAGjD,eAAO,MAAM,MAAM,WAAW,CAAC;AAC/B,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,eAAO,MAAM,iBAAiB,sBAAsB,CAAC;AACrD,eAAO,MAAM,gBAAgB,qBAAqB,CAAC;AACnD,eAAO,MAAM,eAAe,oBAAoB,CAAC;AACjD,eAAO,MAAM,KAAK,UAAU,CAAC;AAC7B,eAAO,MAAM,SAAS,cAAc,CAAC;AACrC,eAAO,MAAM,SAAS,cAAc,CAAC;AACrC,eAAO,MAAM,WAAW,gBAAgB,CAAC;AAEzC,wDAAwD;AACxD,MAAM,WAAW,KAAK;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,IAAI,MAAM,CAAC;IACd,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,OAAO,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,wBAAsB,eAAe,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CA8BzF;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,yDAAyD;AACzD,qBAAa,SAAS;IAElB,OAAO,CAAC,KAAK;IACb,OAAO,CAAC,MAAM;gBADN,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;IAG/B,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,GAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAA;KAAO,GAAG,OAAO,CAAC,UAAU,CAAC;IAmB/E,OAAO,CAAC,IAAI;CAKb"}
|
package/dist/loop.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 长时程推进循环 + 单相位原语(对标 pi-agent-core 的 agent-loop)。
|
|
3
|
+
* advanceOnePhase 是 BuildLoop 与 Orchestrator 共用的原语(单相位语义只一处实现)。
|
|
4
|
+
* 从 Python loop.py 忠实移植(BudgetExceeded/LLMError 归约为停止原因,不炸进程)。
|
|
5
|
+
*/
|
|
6
|
+
import { BudgetExceeded, LLMError } from "@mingyuxu/ai";
|
|
7
|
+
import { reconcile } from "./reconcile.js";
|
|
8
|
+
import { TERMINAL } from "./session.js";
|
|
9
|
+
// 停止原因
|
|
10
|
+
export const FROZEN = "frozen";
|
|
11
|
+
export const PHASE_CHECKPOINT = "phase_checkpoint";
|
|
12
|
+
export const AWAITING_APPROVAL = "awaiting_approval";
|
|
13
|
+
export const RECONCILE_FAILED = "reconcile_failed";
|
|
14
|
+
export const BUDGET_EXCEEDED = "budget_exceeded";
|
|
15
|
+
export const STUCK = "stuck";
|
|
16
|
+
export const MAX_STEPS = "max_steps";
|
|
17
|
+
export const LLM_ERROR = "llm_error";
|
|
18
|
+
export const INTERRUPTED = "interrupted";
|
|
19
|
+
export async function advanceOnePhase(agent, session) {
|
|
20
|
+
const ws = agent.workspace;
|
|
21
|
+
const phase = session.phase;
|
|
22
|
+
const before = session.lastProgressAt;
|
|
23
|
+
try {
|
|
24
|
+
await agent.runPhase(session);
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
if (e instanceof BudgetExceeded) {
|
|
28
|
+
session.event(ws, "budget_exceeded", { error: String(e) }, agent.now());
|
|
29
|
+
return { ok: false, reason: BUDGET_EXCEEDED, phase, ran: false };
|
|
30
|
+
}
|
|
31
|
+
if (e instanceof LLMError) { // 瞬时故障:落账可续跑,不炸进程
|
|
32
|
+
session.event(ws, "llm_error", { error: String(e) }, agent.now());
|
|
33
|
+
return { ok: false, reason: LLM_ERROR, phase, ran: false };
|
|
34
|
+
}
|
|
35
|
+
throw e; // 机器门拒绝(桩审计/grounding)等 → 上抛给调用方
|
|
36
|
+
}
|
|
37
|
+
const missing = reconcile(session.home(ws), phase, session.artifacts[phase] ?? []);
|
|
38
|
+
if (missing.length) {
|
|
39
|
+
session.event(ws, "ghost_completion", { missing }, agent.now());
|
|
40
|
+
session.save(ws, agent.now());
|
|
41
|
+
return { ok: false, reason: RECONCILE_FAILED, phase, ran: true, missing };
|
|
42
|
+
}
|
|
43
|
+
if (session.lastProgressAt <= before) {
|
|
44
|
+
return { ok: false, reason: STUCK, phase, ran: true };
|
|
45
|
+
}
|
|
46
|
+
session.phase = session.nextPhase();
|
|
47
|
+
session.event(ws, "phase_advanced", { to: session.phase }, agent.now());
|
|
48
|
+
session.save(ws, agent.now());
|
|
49
|
+
return { ok: true, reason: "", phase, ran: true, nextPhase: session.phase };
|
|
50
|
+
}
|
|
51
|
+
/** 无人值守驱动器:沿相位推进;相位边界按 auto 决定停不停;freeze 永远等 approve。 */
|
|
52
|
+
export class BuildLoop {
|
|
53
|
+
agent;
|
|
54
|
+
policy;
|
|
55
|
+
constructor(agent, policy) {
|
|
56
|
+
this.agent = agent;
|
|
57
|
+
this.policy = policy;
|
|
58
|
+
}
|
|
59
|
+
async run(session, opts = {}) {
|
|
60
|
+
const auto = opts.auto ?? false;
|
|
61
|
+
const maxSteps = Number(this.policy.steps.builder_loop_max_steps);
|
|
62
|
+
let steps = 0;
|
|
63
|
+
while (session.phase !== TERMINAL) {
|
|
64
|
+
if (steps >= maxSteps)
|
|
65
|
+
return this.stop(session, MAX_STEPS, steps);
|
|
66
|
+
if (session.phase === "freeze" && !session.approved) {
|
|
67
|
+
return this.stop(session, AWAITING_APPROVAL, steps);
|
|
68
|
+
}
|
|
69
|
+
const res = await advanceOnePhase(this.agent, session);
|
|
70
|
+
if (res.ran)
|
|
71
|
+
steps += 1;
|
|
72
|
+
if (!res.ok)
|
|
73
|
+
return this.stop(session, res.reason, steps, res.missing);
|
|
74
|
+
if (!auto && session.phase !== TERMINAL) {
|
|
75
|
+
return this.stop(session, PHASE_CHECKPOINT, steps);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return this.stop(session, FROZEN, steps);
|
|
79
|
+
}
|
|
80
|
+
stop(session, reason, steps, missing) {
|
|
81
|
+
session.save(this.agent.workspace, this.agent.now());
|
|
82
|
+
session.event(this.agent.workspace, "loop_stopped", { reason }, this.agent.now());
|
|
83
|
+
return { stop: reason, phase: session.phase, steps, ...(missing ? { missing } : {}) };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=loop.js.map
|
package/dist/loop.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loop.js","sourceRoot":"","sources":["../src/loop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { type ToolRegistry } from "./tools.js";
|
|
2
|
+
import { type Agent } from "./loop.js";
|
|
3
|
+
import { Session } from "./session.js";
|
|
4
|
+
export declare const PLAYBOOK: Record<string, [string, string, string]>;
|
|
5
|
+
export interface OrchestratorAgent extends Agent {
|
|
6
|
+
tools: ToolRegistry;
|
|
7
|
+
ledgerSummary(): Record<string, unknown>;
|
|
8
|
+
llm: {
|
|
9
|
+
mode: string;
|
|
10
|
+
completeJson(system: string, user: string): Promise<Record<string, unknown>>;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
export interface Decision {
|
|
14
|
+
narration?: string;
|
|
15
|
+
action?: {
|
|
16
|
+
kind?: string;
|
|
17
|
+
text?: string;
|
|
18
|
+
tool?: string;
|
|
19
|
+
args?: Record<string, unknown>;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export type DecideFn = (session: Session, userMsg: string, obs: string | null) => Promise<Decision> | Decision;
|
|
23
|
+
export type Say = (role: string, text: string) => void;
|
|
24
|
+
export declare class Orchestrator {
|
|
25
|
+
private agent;
|
|
26
|
+
private maxSteps;
|
|
27
|
+
private tailN;
|
|
28
|
+
private decide;
|
|
29
|
+
private instructions;
|
|
30
|
+
constructor(agent: OrchestratorAgent, policy: Record<string, any>, // policy.orchestrator.{max_steps_per_turn,transcript_tail_n}
|
|
31
|
+
opts?: {
|
|
32
|
+
decideFn?: DecideFn;
|
|
33
|
+
instructions?: string;
|
|
34
|
+
});
|
|
35
|
+
turn(session: Session, userMsg: string, say?: Say): Promise<{
|
|
36
|
+
stop: string;
|
|
37
|
+
steps: number;
|
|
38
|
+
}>;
|
|
39
|
+
private doTool;
|
|
40
|
+
private doAdvance;
|
|
41
|
+
private gateReady;
|
|
42
|
+
private gateSummary;
|
|
43
|
+
private llmDecide;
|
|
44
|
+
}
|
|
45
|
+
export declare const ORCH_SYSTEM: string;
|
|
46
|
+
/** mock 决策器:无模型也能走通闭环(确定性、可测)。 */
|
|
47
|
+
export declare function mockDecide(_session: Session, userMsg: string, obs: string | null): Decision;
|
|
48
|
+
//# sourceMappingURL=orchestrator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orchestrator.d.ts","sourceRoot":"","sources":["../src/orchestrator.ts"],"names":[],"mappings":"AAOA,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,YAAY,CAAC;AAE3D,OAAO,EAAmB,KAAK,KAAK,EAAE,MAAM,WAAW,CAAC;AACxD,OAAO,EAAE,OAAO,EAAoB,MAAM,cAAc,CAAC;AAEzD,eAAO,MAAM,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAO7D,CAAC;AAEF,MAAM,WAAW,iBAAkB,SAAQ,KAAK;IAC9C,KAAK,EAAE,YAAY,CAAC;IACpB,aAAa,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACzC,GAAG,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;KAAE,CAAC;CACrG;AAED,MAAM,WAAW,QAAQ;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC;CAC1F;AACD,MAAM,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,KAAK,OAAO,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC;AAC/G,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;AAEvD,qBAAa,YAAY;IAQrB,OAAO,CAAC,KAAK;IAPf,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAW;IAEzB,OAAO,CAAC,YAAY,CAAS;gBAGnB,KAAK,EAAE,iBAAiB,EAChC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAW,6DAA6D;IACnG,IAAI,GAAE;QAAE,QAAQ,CAAC,EAAE,QAAQ,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAO;IAQrD,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,GAAE,GAAc,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;YAuD9F,MAAM;YAaN,SAAS;IAavB,OAAO,CAAC,SAAS;IAYjB,OAAO,CAAC,WAAW;YAUL,SAAS;CAgBxB;AAED,eAAO,MAAM,WAAW,QAK0B,CAAC;AAEnD,kCAAkC;AAClC,wBAAgB,UAAU,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,QAAQ,CAuB3F"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 意图层 Orchestrator —— 主 agent:narrate → 决策 → 观察 → 循环,直到交还用户。
|
|
3
|
+
* 决策五选一:reply / ask / tool / advance / propose_gate。失控三重顶:白名单+预算+步数。
|
|
4
|
+
* 从 Python orchestrator.py 移植。real 走 LLM 决策器、mock 走确定性关键词决策器(同一执行路径)。
|
|
5
|
+
*/
|
|
6
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { ToolDenied } from "./tools.js";
|
|
9
|
+
import { BudgetExceeded } from "@mingyuxu/ai";
|
|
10
|
+
import { advanceOnePhase } from "./loop.js";
|
|
11
|
+
import { PHASES, TERMINAL } from "./session.js";
|
|
12
|
+
export const PLAYBOOK = {
|
|
13
|
+
analyze: ["① 分析规则", "把规则拆成原子核查目标", "展示目标清单,请用户确认/删/改"],
|
|
14
|
+
observe: ["② 观察样本", "用样本修锚点 + researcher 查领域知识", "汇报锚点命中与领域发现"],
|
|
15
|
+
propose: ["③ 出方案", "多 proposer 出候选生产线", "展示候选对比,确认后才推进"],
|
|
16
|
+
test: ["④ 测试", "bake-off 打分 + refine 回改 + 对抗验证据", "展示排名/召回/评审页再谈冻结"],
|
|
17
|
+
freeze: ["⑤ 冻结", "晋升门(桩审计+grounding+人工批准)", "摊开门禁状态,等人工 approve"],
|
|
18
|
+
[TERMINAL]: ["已冻结", "生产线可直接调用", "kcagent run <场景> <文档>"],
|
|
19
|
+
};
|
|
20
|
+
export class Orchestrator {
|
|
21
|
+
agent;
|
|
22
|
+
maxSteps;
|
|
23
|
+
tailN;
|
|
24
|
+
decide;
|
|
25
|
+
instructions;
|
|
26
|
+
constructor(agent, policy, // policy.orchestrator.{max_steps_per_turn,transcript_tail_n}
|
|
27
|
+
opts = {}) {
|
|
28
|
+
this.agent = agent;
|
|
29
|
+
this.maxSteps = Number(policy.orchestrator?.max_steps_per_turn ?? 6);
|
|
30
|
+
this.tailN = Number(policy.orchestrator?.transcript_tail_n ?? 20);
|
|
31
|
+
this.instructions = opts.instructions ?? "";
|
|
32
|
+
this.decide = opts.decideFn ?? (this.agent.llm.mode === "real" ? this.llmDecide.bind(this) : mockDecide);
|
|
33
|
+
}
|
|
34
|
+
async turn(session, userMsg, say = () => { }) {
|
|
35
|
+
const ws = this.agent.workspace;
|
|
36
|
+
session.transcriptAppend(ws, "user", userMsg);
|
|
37
|
+
let obs = null;
|
|
38
|
+
for (let step = 0; step < this.maxSteps; step++) {
|
|
39
|
+
let decision;
|
|
40
|
+
try {
|
|
41
|
+
decision = await this.decide(session, userMsg, obs);
|
|
42
|
+
}
|
|
43
|
+
catch (e) {
|
|
44
|
+
say("agent", `(决策器不可用:${e.name})`);
|
|
45
|
+
return { stop: "decider_error", steps: step };
|
|
46
|
+
}
|
|
47
|
+
const narration = (decision.narration ?? "").trim();
|
|
48
|
+
if (narration) {
|
|
49
|
+
say("think", narration);
|
|
50
|
+
session.transcriptAppend(ws, "think", narration);
|
|
51
|
+
}
|
|
52
|
+
const act = decision.action ?? {};
|
|
53
|
+
const kind = act.kind ?? "reply";
|
|
54
|
+
if (kind === "reply" || kind === "ask") {
|
|
55
|
+
const text = (act.text ?? "").trim() || "(无话可说)";
|
|
56
|
+
say("agent", text);
|
|
57
|
+
session.transcriptAppend(ws, "agent", text);
|
|
58
|
+
return { stop: kind, steps: step + 1 };
|
|
59
|
+
}
|
|
60
|
+
if (kind === "propose_gate") {
|
|
61
|
+
const [ready, why] = this.gateReady(session);
|
|
62
|
+
if (!ready) {
|
|
63
|
+
obs = `晋升门未就绪:${why}。先把④测试补完(show_report 可看现状)。`;
|
|
64
|
+
session.transcriptAppend(ws, "obs", obs);
|
|
65
|
+
continue;
|
|
66
|
+
}
|
|
67
|
+
const summary = this.gateSummary(session);
|
|
68
|
+
say("agent", summary);
|
|
69
|
+
session.transcriptAppend(ws, "agent", summary);
|
|
70
|
+
return { stop: "gate_proposed", steps: step + 1 };
|
|
71
|
+
}
|
|
72
|
+
if (kind === "advance") {
|
|
73
|
+
obs = await this.doAdvance(session);
|
|
74
|
+
session.transcriptAppend(ws, "obs", obs);
|
|
75
|
+
continue;
|
|
76
|
+
}
|
|
77
|
+
if (kind === "tool") {
|
|
78
|
+
obs = await this.doTool(session, act);
|
|
79
|
+
session.transcriptAppend(ws, "obs", obs);
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
obs = `未知动作 kind=${kind}`;
|
|
83
|
+
session.transcriptAppend(ws, "obs", obs);
|
|
84
|
+
}
|
|
85
|
+
say("agent", "这一轮动作到顶了,先停下等你。(进度都在盘上)");
|
|
86
|
+
return { stop: "max_steps", steps: this.maxSteps };
|
|
87
|
+
}
|
|
88
|
+
async doTool(session, act) {
|
|
89
|
+
const name = act.tool ?? "";
|
|
90
|
+
try {
|
|
91
|
+
let out = this.agent.tools.call(name, { ...(act.args ?? {}), session });
|
|
92
|
+
if (out instanceof Promise)
|
|
93
|
+
out = await out; // 工具可异步(如 revise_targets 调 LLM)
|
|
94
|
+
return typeof out === "string" ? out : JSON.stringify(out).slice(0, 2000);
|
|
95
|
+
}
|
|
96
|
+
catch (e) {
|
|
97
|
+
if (e instanceof ToolDenied)
|
|
98
|
+
return `工具被拒(白名单):${e.message}`;
|
|
99
|
+
if (e instanceof BudgetExceeded)
|
|
100
|
+
return `预算熔断:${e.message}`;
|
|
101
|
+
return `工具 ${name} 失败:${e.name}: ${e.message}`;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async doAdvance(session) {
|
|
105
|
+
if (session.phase === TERMINAL)
|
|
106
|
+
return "已经冻结完成,无相位可推进。";
|
|
107
|
+
if (session.phase === "freeze" && !session.approved) {
|
|
108
|
+
const [ready, why] = this.gateReady(session);
|
|
109
|
+
return "到晋升门了。" + (ready ? this.gateSummary(session) : `但门未就绪:${why}`);
|
|
110
|
+
}
|
|
111
|
+
const res = await advanceOnePhase(this.agent, session);
|
|
112
|
+
if (!res.ok)
|
|
113
|
+
return `相位 ${res.phase} 未推进:${res.reason}`;
|
|
114
|
+
const done = PLAYBOOK[res.phase]?.[0] ?? res.phase;
|
|
115
|
+
const next = PLAYBOOK[res.nextPhase]?.[0] ?? res.nextPhase;
|
|
116
|
+
return `✓ ${done} 完成,进入 ${next}。建议:${PLAYBOOK[res.phase]?.[2] ?? ""}`;
|
|
117
|
+
}
|
|
118
|
+
gateReady(session) {
|
|
119
|
+
const home = session.home(this.agent.workspace);
|
|
120
|
+
if (!["freeze", "test"].includes(session.phase))
|
|
121
|
+
return [false, `当前相位 ${session.phase},还没走到测试/冻结`];
|
|
122
|
+
const report = join(home, "build", "test_report.json");
|
|
123
|
+
if (!existsSync(report))
|
|
124
|
+
return [false, "缺 build/test_report.json(④测试没跑)"];
|
|
125
|
+
const rep = JSON.parse(readFileSync(report, "utf-8"));
|
|
126
|
+
if (rep.ranking?.length && !existsSync(join(home, "build", "review.html"))) {
|
|
127
|
+
return [false, "缺 build/review.html(评审页没出)"];
|
|
128
|
+
}
|
|
129
|
+
return [true, ""];
|
|
130
|
+
}
|
|
131
|
+
gateSummary(session) {
|
|
132
|
+
let report = "";
|
|
133
|
+
try {
|
|
134
|
+
report = this.agent.tools.call("show_report", { session });
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
report = "(测试报告不可读)";
|
|
138
|
+
}
|
|
139
|
+
return ["———— 晋升门 ————", report, "", "批准冻结是人工专属动作:确认无误后输入 approve(我无权替你批)。"].join("\n");
|
|
140
|
+
}
|
|
141
|
+
async llmDecide(session, userMsg, obs) {
|
|
142
|
+
const ctx = {
|
|
143
|
+
phase: session.phase,
|
|
144
|
+
playbook: PLAYBOOK,
|
|
145
|
+
phases_order: PHASES,
|
|
146
|
+
artifacts: session.artifacts,
|
|
147
|
+
approved: session.approved,
|
|
148
|
+
tools: this.agent.tools.names(),
|
|
149
|
+
transcript_tail: session.transcriptTail(this.agent.workspace, this.tailN),
|
|
150
|
+
user_message: userMsg,
|
|
151
|
+
last_observation: obs ?? "",
|
|
152
|
+
budget: this.agent.ledgerSummary(),
|
|
153
|
+
};
|
|
154
|
+
const system = this.instructions ? `${this.instructions}\n\n${ORCH_SYSTEM}` : ORCH_SYSTEM;
|
|
155
|
+
return (await this.agent.llm.completeJson(system, JSON.stringify(ctx)));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
export const ORCH_SYSTEM = "你是核查生产线构建的主 agent(意图层)。每轮输出一个 JSON 决策:" +
|
|
159
|
+
'{"narration":"先说你准备做什么、为什么","action":{"kind":"reply|ask|tool|advance|propose_gate",' +
|
|
160
|
+
'"text":"对用户说的话","tool":"工具名","args":{}}}。五步是默认计划不是铁轨,用户可改道;' +
|
|
161
|
+
"用户要删/改目标时调 revise_targets(args.drop=[编号] 或 args.feedback=调整要求);" +
|
|
162
|
+
"propose_gate 前须有测试报告;冻结永远等人工 approve。只输出 JSON。";
|
|
163
|
+
/** mock 决策器:无模型也能走通闭环(确定性、可测)。 */
|
|
164
|
+
export function mockDecide(_session, userMsg, obs) {
|
|
165
|
+
if (obs !== null)
|
|
166
|
+
return { narration: "把刚才的结果交还给你。", action: { kind: "reply", text: obs } };
|
|
167
|
+
const has = (...kws) => kws.some((k) => userMsg.includes(k));
|
|
168
|
+
if (has("目标"))
|
|
169
|
+
return { narration: "你想看核查目标——调 show_targets。", action: { kind: "tool", tool: "show_targets" } };
|
|
170
|
+
if (has("方案", "候选", "skill"))
|
|
171
|
+
return { narration: "你想看候选生产线——调 show_specs。", action: { kind: "tool", tool: "show_specs" } };
|
|
172
|
+
if (has("报告", "评测", "测试", "结果"))
|
|
173
|
+
return { narration: "你想看评测结果——调 show_report。", action: { kind: "tool", tool: "show_report" } };
|
|
174
|
+
{
|
|
175
|
+
const dropM = userMsg.match(/删.*?(\d+)/g);
|
|
176
|
+
if (dropM) {
|
|
177
|
+
const nums = (userMsg.match(/\d+/g) ?? []).map(Number);
|
|
178
|
+
return { narration: `按你的要求删掉第 ${nums.join("、")} 个目标。`, action: { kind: "tool", tool: "revise_targets", args: { drop: nums } } };
|
|
179
|
+
}
|
|
180
|
+
if (has("改判据", "改目标", "修订", "只保留", "收紧", "放宽", "调整")) {
|
|
181
|
+
return { narration: "按你的调整要求修订目标清单。", action: { kind: "tool", tool: "revise_targets", args: { feedback: userMsg } } };
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
if (has("冻结", "批准", "上线", "固化"))
|
|
185
|
+
return { narration: "你想冻结——先过就绪门再摊开晋升门。", action: { kind: "propose_gate" } };
|
|
186
|
+
if (has("继续", "推进", "下一步", "开始"))
|
|
187
|
+
return { narration: "推进一个相位。", action: { kind: "advance" } };
|
|
188
|
+
const [title, what, review] = PLAYBOOK[_session.phase] ?? [_session.phase, "", ""];
|
|
189
|
+
return {
|
|
190
|
+
narration: "没匹配到明确意图,报个状态。",
|
|
191
|
+
action: { kind: "reply", text: `当前在 ${title}(${what})。可以说:继续 / 看目标 / 看方案 / 看报告 / 冻结。建议:${review}` },
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=orchestrator.js.map
|