stable-harness 0.0.2 → 0.0.4
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/dist/cli.js +1 -1
- package/dist/compat/agent-harness.js +1 -1
- package/dist/index.d.ts +29 -6
- package/dist/index.js +1 -1
- package/dist/runtime/compat/agent-harness-compat-runner.js +1 -1
- package/dist/runtime/compat/json.js +1 -1
- package/dist/runtime/compat/presentation.js +1 -1
- package/dist/runtime/compat/prompts.js +1 -1
- package/dist/runtime/model/ollama.js +1 -1
- package/dist/runtime/skills/skill-metadata.js +1 -1
- package/dist/workspace/compile.js +1 -1
- package/package.json +14 -10
- package/packages/adapter-deepagents/dist/src/adapter.d.ts +1 -0
- package/packages/adapter-deepagents/dist/src/adapter.js +1 -1
- package/packages/adapter-deepagents/dist/src/index.d.ts +1 -0
- package/packages/adapter-deepagents/dist/src/index.js +1 -1
- package/packages/adapter-deepagents/dist/src/internal/builtin-args.d.ts +4 -0
- package/packages/adapter-deepagents/dist/src/internal/builtin-args.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.d.ts +39 -0
- package/packages/adapter-deepagents/dist/src/internal/builtin-tool-policy.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/gateway-tools.d.ts +32 -0
- package/packages/adapter-deepagents/dist/src/internal/gateway-tools.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/messages.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/raw-tool-call-parser.d.ts +12 -0
- package/packages/adapter-deepagents/dist/src/internal/raw-tool-call-parser.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/skill-file-policy.d.ts +10 -0
- package/packages/adapter-deepagents/dist/src/internal/skill-file-policy.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/stream-events.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/tool-repeat-visibility.d.ts +4 -0
- package/packages/adapter-deepagents/dist/src/internal/tool-repeat-visibility.js +1 -0
- package/packages/adapter-deepagents/dist/src/internal/trace-projection.d.ts +16 -0
- package/packages/adapter-deepagents/dist/src/internal/trace-projection.js +1 -0
- package/packages/adapter-deepagents/dist/src/memory.d.ts +5 -0
- package/packages/adapter-deepagents/dist/src/memory.js +1 -0
- package/packages/adapter-deepagents/dist/src/model-providers.d.ts +4 -0
- package/packages/adapter-deepagents/dist/src/model-providers.js +1 -0
- package/packages/adapter-deepagents/dist/src/retry-policy.js +1 -1
- package/packages/adapter-deepagents/dist/src/types.d.ts +7 -1
- package/packages/adapter-deepagents/package.json +1 -0
- package/packages/adapter-langgraph/dist/src/graph.d.ts +3 -0
- package/packages/adapter-langgraph/dist/src/graph.js +1 -0
- package/packages/adapter-langgraph/dist/src/index.d.ts +8 -0
- package/packages/adapter-langgraph/dist/src/index.js +1 -0
- package/packages/adapter-langgraph/dist/src/runtime.d.ts +3 -0
- package/packages/adapter-langgraph/dist/src/runtime.js +1 -0
- package/packages/adapter-langgraph/dist/src/skill-providers.d.ts +29 -0
- package/packages/adapter-langgraph/dist/src/skill-providers.js +1 -0
- package/packages/adapter-langgraph/dist/src/types.d.ts +60 -0
- package/packages/adapter-langgraph/dist/src/types.js +1 -0
- package/packages/adapter-langgraph/package.json +16 -0
- package/packages/cli/dist/src/args.d.ts +25 -0
- package/packages/cli/dist/src/args.js +1 -0
- package/packages/cli/dist/src/cli.js +1 -1
- package/packages/cli/dist/src/event-view.d.ts +9 -0
- package/packages/cli/dist/src/event-view.js +1 -0
- package/packages/cli/dist/src/index.d.ts +3 -0
- package/packages/cli/dist/src/index.js +1 -1
- package/packages/cli/dist/src/langgraph-env.d.ts +5 -0
- package/packages/cli/dist/src/langgraph-env.js +1 -0
- package/packages/cli/dist/src/langgraph-official.d.ts +13 -0
- package/packages/cli/dist/src/langgraph-official.js +1 -0
- package/packages/cli/dist/src/memory/lifecycle.d.ts +2 -0
- package/packages/cli/dist/src/memory/lifecycle.js +1 -0
- package/packages/cli/dist/src/memory/providers.d.ts +3 -0
- package/packages/cli/dist/src/memory/providers.js +1 -0
- package/packages/cli/dist/src/output.d.ts +8 -0
- package/packages/cli/dist/src/output.js +1 -0
- package/packages/cli/dist/src/server.d.ts +5 -0
- package/packages/cli/dist/src/server.js +1 -0
- package/packages/cli/package.json +3 -0
- package/packages/core/dist/evaluations/index.d.ts +18 -0
- package/packages/core/dist/evaluations/index.js +1 -0
- package/packages/core/dist/execution-contract.d.ts +1 -0
- package/packages/core/dist/execution-contract.js +1 -1
- package/packages/core/dist/index.d.ts +8 -4
- package/packages/core/dist/index.js +1 -1
- package/packages/core/dist/memory-plugins/maintenance.d.ts +42 -0
- package/packages/core/dist/memory-plugins/maintenance.js +1 -0
- package/packages/core/dist/memory-plugins/shared.d.ts +8 -0
- package/packages/core/dist/memory-plugins/shared.js +1 -0
- package/packages/core/dist/memory-plugins.d.ts +5 -48
- package/packages/core/dist/memory-plugins.js +1 -1
- package/packages/core/dist/recovery/tool-call.d.ts +28 -0
- package/packages/core/dist/recovery/tool-call.js +1 -0
- package/packages/core/dist/runtime/completion.d.ts +17 -0
- package/packages/core/dist/runtime/completion.js +1 -0
- package/packages/core/dist/runtime/direct-tool-call.d.ts +10 -0
- package/packages/core/dist/runtime/direct-tool-call.js +1 -0
- package/packages/core/dist/runtime/events.d.ts +204 -0
- package/packages/core/dist/runtime/events.js +1 -0
- package/packages/core/dist/runtime/memory.d.ts +23 -0
- package/packages/core/dist/runtime/memory.js +1 -0
- package/packages/core/dist/{artifacts.d.ts → runtime/persistence/artifacts.d.ts} +1 -1
- package/packages/core/dist/runtime/persistence/artifacts.js +1 -0
- package/packages/core/dist/{inspection.d.ts → runtime/persistence/inspection.d.ts} +1 -1
- package/packages/core/dist/runtime/persistence/inspection.js +1 -0
- package/packages/core/dist/{queue.d.ts → runtime/persistence/queue.d.ts} +1 -1
- package/packages/core/dist/runtime/persistence/queue.js +1 -0
- package/packages/core/dist/{stores.d.ts → runtime/persistence/stores.d.ts} +1 -1
- package/packages/core/dist/runtime/persistence/stores.js +1 -0
- package/packages/core/dist/runtime/progress-narration.d.ts +33 -0
- package/packages/core/dist/runtime/progress-narration.js +1 -0
- package/packages/core/dist/runtime/tool-gateway.d.ts +40 -0
- package/packages/core/dist/runtime/tool-gateway.js +1 -0
- package/packages/core/dist/runtime/types.d.ts +168 -0
- package/packages/core/dist/runtime/types.js +1 -0
- package/packages/core/dist/runtime.d.ts +7 -3
- package/packages/core/dist/runtime.js +1 -1
- package/packages/core/dist/spec-driven/config.d.ts +4 -0
- package/packages/core/dist/spec-driven/config.js +1 -0
- package/packages/core/dist/spec-driven/events.d.ts +11 -0
- package/packages/core/dist/spec-driven/events.js +1 -0
- package/packages/core/dist/spec-driven/index.d.ts +4 -0
- package/packages/core/dist/spec-driven/index.js +1 -0
- package/packages/core/dist/spec-driven/lifecycle.d.ts +11 -0
- package/packages/core/dist/spec-driven/lifecycle.js +1 -0
- package/packages/core/dist/spec-driven/types.d.ts +38 -0
- package/packages/core/dist/spec-driven/types.js +1 -0
- package/packages/core/dist/trace.d.ts +1 -1
- package/packages/core/dist/trace.js +1 -1
- package/packages/core/dist/types.d.ts +31 -426
- package/packages/core/dist/workflows/index.d.ts +70 -0
- package/packages/core/dist/workflows/index.js +1 -0
- package/packages/core/dist/workflows/runtime.d.ts +12 -0
- package/packages/core/dist/workflows/runtime.js +1 -0
- package/packages/core/dist/workspace/types.d.ts +101 -0
- package/packages/core/dist/workspace/types.js +1 -0
- package/packages/governance/dist/src/skill-candidates.js +1 -1
- package/packages/governance/dist/src/types.d.ts +1 -1
- package/packages/memory/dist/src/langmem-service.js +1 -1
- package/packages/memory/dist/src/maintenance.js +1 -1
- package/packages/memory/dist/src/policy.js +1 -1
- package/packages/memory/dist/src/provider.js +1 -1
- package/packages/memory/dist/src/store.js +1 -1
- package/packages/protocols/dist/src/http-server.js +1 -1
- package/packages/protocols/dist/src/in-process-client.js +1 -1
- package/packages/protocols/dist/src/openai-compatible.js +1 -1
- package/packages/protocols/dist/src/openai-payload.d.ts +74 -0
- package/packages/protocols/dist/src/openai-payload.js +1 -0
- package/packages/protocols/dist/src/openai-stream.d.ts +39 -0
- package/packages/protocols/dist/src/openai-stream.js +1 -0
- package/packages/tool-gateway/dist/src/argument-guard.d.ts +2 -1
- package/packages/tool-gateway/dist/src/argument-guard.js +1 -1
- package/packages/tool-gateway/dist/src/in-memory.js +1 -1
- package/packages/tool-gateway/dist/src/module-loader.js +1 -1
- package/packages/tool-gateway/dist/src/schema-validation.d.ts +3 -0
- package/packages/tool-gateway/dist/src/schema-validation.js +1 -0
- package/packages/tool-gateway/dist/src/types.d.ts +3 -0
- package/packages/tool-gateway/package.json +1 -1
- package/packages/workspace-yaml/dist/discovery.d.ts +4 -0
- package/packages/workspace-yaml/dist/discovery.js +1 -0
- package/packages/workspace-yaml/dist/documents.d.ts +16 -0
- package/packages/workspace-yaml/dist/documents.js +1 -0
- package/packages/workspace-yaml/dist/evaluations.d.ts +9 -0
- package/packages/workspace-yaml/dist/evaluations.js +1 -0
- package/packages/workspace-yaml/dist/loader.js +1 -1
- package/packages/workspace-yaml/dist/workflows.d.ts +16 -0
- package/packages/workspace-yaml/dist/workflows.js +1 -0
- package/packages/adapter-deepagents/dist/src/builtin-tool-policy.d.ts +0 -18
- package/packages/adapter-deepagents/dist/src/builtin-tool-policy.js +0 -1
- package/packages/adapter-deepagents/dist/src/messages.js +0 -1
- package/packages/adapter-deepagents/dist/src/stream-events.js +0 -1
- package/packages/core/dist/artifacts.js +0 -1
- package/packages/core/dist/inspection.js +0 -1
- package/packages/core/dist/queue.js +0 -1
- package/packages/core/dist/stores.js +0 -1
- /package/packages/adapter-deepagents/dist/src/{messages.d.ts → internal/messages.d.ts} +0 -0
- /package/packages/adapter-deepagents/dist/src/{stream-events.d.ts → internal/stream-events.d.ts} +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { MemoryMaintenanceOperation, MemoryProvider } from "@stable-harness/memory";
|
|
2
|
+
import type { ApprovalQueue, SkillCandidateStore } from "@stable-harness/governance";
|
|
3
|
+
import type { CompiledWorkspace, RuntimeEmit, WorkspaceAgent } from "../types.js";
|
|
4
|
+
export type MemoryMaintenanceTarget = {
|
|
5
|
+
name: string;
|
|
6
|
+
run(input: MemoryMaintenanceTargetInput): Promise<MemoryMaintenanceResult>;
|
|
7
|
+
};
|
|
8
|
+
export type MemoryMaintenanceTargetInput = {
|
|
9
|
+
emit: RuntimeEmit;
|
|
10
|
+
requestId: string;
|
|
11
|
+
sessionId: string;
|
|
12
|
+
agent: WorkspaceAgent;
|
|
13
|
+
workspace: CompiledWorkspace;
|
|
14
|
+
prompt: string;
|
|
15
|
+
};
|
|
16
|
+
export type MemoryMaintenanceResult = {
|
|
17
|
+
operations?: MemoryMaintenanceOperation[];
|
|
18
|
+
metadata?: Record<string, unknown>;
|
|
19
|
+
};
|
|
20
|
+
export type MemoryMaintenanceDaemon = {
|
|
21
|
+
runOnce(input?: Partial<Pick<MemoryMaintenanceTargetInput, "requestId" | "sessionId" | "agent">>): Promise<MemoryMaintenanceResult[]>;
|
|
22
|
+
start(): void;
|
|
23
|
+
stop(): void;
|
|
24
|
+
};
|
|
25
|
+
export declare function createMemoryMaintenanceDaemon(input: {
|
|
26
|
+
workspace: CompiledWorkspace;
|
|
27
|
+
emit?: RuntimeEmit;
|
|
28
|
+
targets: MemoryMaintenanceTarget[];
|
|
29
|
+
intervalMs?: number;
|
|
30
|
+
prompt?: string;
|
|
31
|
+
defaultAgentId?: string;
|
|
32
|
+
}): MemoryMaintenanceDaemon;
|
|
33
|
+
export declare function createLangMemMaintenanceTarget(input: {
|
|
34
|
+
providers: MemoryProvider[] | undefined;
|
|
35
|
+
limit?: number;
|
|
36
|
+
}): MemoryMaintenanceTarget;
|
|
37
|
+
export declare function createSkillCandidateMinerTarget(input: {
|
|
38
|
+
providers: MemoryProvider[] | undefined;
|
|
39
|
+
store: SkillCandidateStore;
|
|
40
|
+
approvals?: ApprovalQueue;
|
|
41
|
+
minEvidenceCount?: number;
|
|
42
|
+
}): MemoryMaintenanceTarget;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{formatError as e,readRecord as t,readWorkspaceId as n,resolveEnabledMemories as a,resolveMemoryProvider as r,resolvePluginNamespace as s}from"./shared.js";export function createMemoryMaintenanceDaemon(e){let t;const n=e.emit??(()=>{});return{async runOnce(t={}){const a=t.agent??function resolveMaintenanceAgent(e,t){const n=e.agents.get(t??e.runtime.defaultAgentId);if(!n)throw new Error("Memory maintenance requires a configured default agent");return n}(e.workspace,e.defaultAgentId),r={emit:n,requestId:t.requestId??`memory-maintenance-${Date.now()}`,sessionId:t.sessionId??"memory-maintenance",agent:a,workspace:e.workspace,prompt:e.prompt??defaultMaintenancePrompt(e.workspace)},s=[];for(const t of e.targets)s.push(await runMaintenanceTarget(r,t));return s},start(){e.intervalMs&&!t&&(t=setInterval(()=>{this.runOnce()},e.intervalMs))},stop(){t&&(clearInterval(t),t=void 0)}}}export function createLangMemMaintenanceTarget(e){return{name:"LangMem",async run(t){const n=[];for(const o of a(t.workspace,"write")){const a=r(e.providers??[],o.provider);if(!a)continue;const i=s(t.workspace,t.agent,{input:"",sessionId:t.sessionId},o),c=mergeMemoryRecords(await a.search({namespace:i,query:t.prompt,limit:e.limit??100}),await a.search({namespace:i,query:"",limit:e.limit??100}));n.push(...await a.consolidate({records:c}))}return{operations:n}}}}export function createSkillCandidateMinerTarget(e){return{name:"skillCandidateMiner",async run(t){const n=await async function collectMaintenanceRecords(e,t){const n=[];for(const o of a(t.workspace,"all")){const a=r(e??[],o.provider);if(!a)continue;const i=s(t.workspace,t.agent,{input:"",sessionId:t.sessionId},o);n.push(...mergeMemoryRecords(await a.search({namespace:i,query:t.prompt,limit:100}),await a.search({namespace:i,query:"",limit:100})))}return mergeMemoryRecords(n,[])}(e.providers,t),o=function groupSkillCandidateRecords(e){const t=new Map;for(const n of e){const e=readSkillCandidateName(n);e&&t.set(e,[...t.get(e)??[],n])}return t}(n),i=[];for(const[n,a]of o){if(a.length<(e.minEvidenceCount??3))continue;const r=await e.store.upsert(createSkillCandidateInput(t.workspace,n,a));i.push(r),t.emit({type:"runtime.skill.candidate.created",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,candidateId:r.id,name:r.name,confidence:r.confidence,evidenceCount:r.evidenceCount,status:r.status,proposedPath:r.proposedPath}),await(e.approvals?.create({kind:"skill_candidate",reason:`Review mined skill candidate ${r.name}`,requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,subject:{candidate:r}}))}return{operations:[],metadata:{candidateCount:i.length}}}}}async function runMaintenanceTarget(t,n){t.emit({type:"runtime.memory.maintenance.started",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,target:n.name});try{const e=await n.run(t);return t.emit({type:"runtime.memory.maintenance.completed",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,target:n.name,operationCount:e.operations?.length??0}),e}catch(a){return t.emit({type:"runtime.memory.maintenance.failed",requestId:t.requestId,sessionId:t.sessionId,agentId:t.agent.id,target:n.name,error:e(a)}),{operations:[],metadata:{error:e(a)}}}}function mergeMemoryRecords(e,t){const n=new Map;for(const a of[...e,...t])n.set(a.id,a);return[...n.values()]}function readSkillCandidateName(e){const n=t(e.metadata?.skillCandidate),a=t(t(e.metadata?.requestMetadata)?.skillCandidate),r=n?.name??a?.name;return"string"==typeof r&&r.trim()?function slugify(e){return e.toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"")}(r):void 0}function createSkillCandidateInput(e,t,a){const r=function titleFromName(e){return e.split("-").filter(Boolean).map(e=>`${e[0]?.toUpperCase()??""}${e.slice(1)}`).join(" ")}(t);return{workspaceId:n(e),name:t,status:"review_required",confidence:Math.min(.95,.55+.1*a.length),proposedPath:`resources/skills/${t}/SKILL.md`,title:r,summary:`Repeated stable workflow mined from ${a.length} memory records.`,draftMarkdown:renderSkillDraft(r,a),evidence:a.map(e=>({evidenceType:"memory_record",evidenceRef:e.id,summary:e.summary??e.content.slice(0,160),weight:e.confidence}))}}function renderSkillDraft(e,t){return[`# ${e}`,"","## Purpose","","Apply this stable workflow when the task matches the evidence.","","## Evidence","",t.map(e=>`- ${e.summary??e.content}`).join("\n")].join("\n")}function defaultMaintenancePrompt(e){const n=t(e.runtime.memory?.maintenance);return"string"==typeof n?.prompt?n.prompt:"durable preferences workspace facts reusable procedures prior corrections stale duplicated contradicted memories"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { MemoryProvider } from "@stable-harness/memory";
|
|
2
|
+
import type { CompiledWorkspace, RuntimeRequest, WorkspaceAgent, WorkspaceMemory } from "../types.js";
|
|
3
|
+
export declare function resolveEnabledMemories(workspace: CompiledWorkspace, phase?: "all" | "recall" | "write"): WorkspaceMemory[];
|
|
4
|
+
export declare function resolvePluginNamespace(workspace: CompiledWorkspace, agent: WorkspaceAgent, request: RuntimeRequest, memory: WorkspaceMemory): string;
|
|
5
|
+
export declare function resolveMemoryProvider(providers: MemoryProvider[], configuredProvider: string): MemoryProvider | undefined;
|
|
6
|
+
export declare function readRecord(value: unknown): Record<string, unknown> | undefined;
|
|
7
|
+
export declare function readWorkspaceId(workspace: CompiledWorkspace): string;
|
|
8
|
+
export declare function formatError(error: unknown): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function resolveEnabledMemories(e,r="all"){const o=e.runtime.memory??{};if(!function isMemoryPhaseEnabled(e,r){return!1!==e.enabled&&("recall"!==r||!1!==e.recall&&!1!==e.read&&!1!==readMemoryFlag(e,"LangMem","read"))&&("write"!==r||!1!==e.write&&!1!==readMemoryFlag(e,"LangMem","write"))}(o,r))return[];const n=Array.isArray(o.refs)?o.refs.filter(e=>"string"==typeof e):[];return(n.length>0?n:[...e.memories.keys()]).map(r=>e.memories.get(r)).filter(e=>Boolean(e?.enabled))}export function resolvePluginNamespace(e,r,o,n){const t=readWorkspaceId(e),a=n.profile??n.id;return"agent"===a?`${t}:agent:${r.id}:${n.id}`:"user"===a?`${t}:user:${function readUserId(e){return e.metadata?.userId??"local"}(o)}:${n.id}`:"session"===a?`${t}:session:${o.sessionId??"default"}:${n.id}`:`${t}:${a}:${n.id}`}export function resolveMemoryProvider(e,r){return e.find(e=>e.name===r||e.name===`${r}-service`)}export function readRecord(e){return"object"!=typeof e||null===e||Array.isArray(e)?void 0:e}export function readWorkspaceId(e){return e.runtime.workspaceId??e.runtime.profile??e.root}export function formatError(e){return e instanceof Error?e.message:String(e)}function readMemoryFlag(e,r,o){const n=readRecord(e[r])??readRecord(e[r.toLowerCase()]);return"boolean"==typeof n?.[o]?n[o]:void 0}
|
|
@@ -1,27 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type {
|
|
3
|
-
|
|
4
|
-
export type MemoryMaintenanceTarget
|
|
5
|
-
|
|
6
|
-
run(input: MemoryMaintenanceTargetInput): Promise<MemoryMaintenanceResult>;
|
|
7
|
-
};
|
|
8
|
-
export type MemoryMaintenanceTargetInput = {
|
|
9
|
-
emit: RuntimeEmit;
|
|
10
|
-
requestId: string;
|
|
11
|
-
sessionId: string;
|
|
12
|
-
agent: WorkspaceAgent;
|
|
13
|
-
workspace: CompiledWorkspace;
|
|
14
|
-
prompt: string;
|
|
15
|
-
};
|
|
16
|
-
export type MemoryMaintenanceResult = {
|
|
17
|
-
operations?: MemoryMaintenanceOperation[];
|
|
18
|
-
metadata?: Record<string, unknown>;
|
|
19
|
-
};
|
|
20
|
-
export type MemoryMaintenanceDaemon = {
|
|
21
|
-
runOnce(input?: Partial<Pick<MemoryMaintenanceTargetInput, "requestId" | "sessionId" | "agent">>): Promise<MemoryMaintenanceResult[]>;
|
|
22
|
-
start(): void;
|
|
23
|
-
stop(): void;
|
|
24
|
-
};
|
|
1
|
+
import type { MemoryProvider, MemoryRecord } from "@stable-harness/memory";
|
|
2
|
+
import type { CompiledWorkspace, RuntimeEmit, RuntimeOutput, RuntimeRequest, WorkspaceAgent } from "./types.js";
|
|
3
|
+
export { resolveEnabledMemories, resolvePluginNamespace, } from "./memory-plugins/shared.js";
|
|
4
|
+
export type { MemoryMaintenanceDaemon, MemoryMaintenanceResult, MemoryMaintenanceTarget, MemoryMaintenanceTargetInput, } from "./memory-plugins/maintenance.js";
|
|
5
|
+
export { createLangMemMaintenanceTarget, createMemoryMaintenanceDaemon, createSkillCandidateMinerTarget, } from "./memory-plugins/maintenance.js";
|
|
25
6
|
export declare function runMemoryPlugins(input: {
|
|
26
7
|
providers: MemoryProvider[] | undefined;
|
|
27
8
|
emit: RuntimeEmit;
|
|
@@ -42,27 +23,3 @@ export declare function recallMemoryPlugins(input: {
|
|
|
42
23
|
records: MemoryRecord[];
|
|
43
24
|
context: string;
|
|
44
25
|
}>>;
|
|
45
|
-
export declare function resolveEnabledMemories(workspace: CompiledWorkspace, phase?: "all" | "recall" | "write"): WorkspaceMemory[];
|
|
46
|
-
export declare function resolveDeepAgentsNativeMemories(workspace: CompiledWorkspace): WorkspaceMemory[];
|
|
47
|
-
export declare function createMemoryMaintenanceDaemon(input: {
|
|
48
|
-
workspace: CompiledWorkspace;
|
|
49
|
-
emit?: RuntimeEmit;
|
|
50
|
-
targets: MemoryMaintenanceTarget[];
|
|
51
|
-
intervalMs?: number;
|
|
52
|
-
prompt?: string;
|
|
53
|
-
defaultAgentId?: string;
|
|
54
|
-
}): MemoryMaintenanceDaemon;
|
|
55
|
-
export declare function createLangMemMaintenanceTarget(input: {
|
|
56
|
-
providers: MemoryProvider[] | undefined;
|
|
57
|
-
limit?: number;
|
|
58
|
-
}): MemoryMaintenanceTarget;
|
|
59
|
-
export declare function createDeepAgentsMemoryMaintenanceTarget(input?: {
|
|
60
|
-
run?: (context: MemoryMaintenanceTargetInput) => Promise<MemoryMaintenanceResult>;
|
|
61
|
-
}): MemoryMaintenanceTarget;
|
|
62
|
-
export declare function createSkillCandidateMinerTarget(input: {
|
|
63
|
-
providers: MemoryProvider[] | undefined;
|
|
64
|
-
store: SkillCandidateStore;
|
|
65
|
-
approvals?: ApprovalQueue;
|
|
66
|
-
minEvidenceCount?: number;
|
|
67
|
-
}): MemoryMaintenanceTarget;
|
|
68
|
-
export declare function resolvePluginNamespace(workspace: CompiledWorkspace, agent: WorkspaceAgent, request: RuntimeRequest, memory: WorkspaceMemory): string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export async function runMemoryPlugins(
|
|
1
|
+
import{formatError as e,readRecord as r,readWorkspaceId as t,resolveEnabledMemories as n,resolveMemoryProvider as o,resolvePluginNamespace as a}from"./memory-plugins/shared.js";export{resolveEnabledMemories,resolvePluginNamespace}from"./memory-plugins/shared.js";export{createLangMemMaintenanceTarget,createMemoryMaintenanceDaemon,createSkillCandidateMinerTarget}from"./memory-plugins/maintenance.js";export async function runMemoryPlugins(e){const r=n(e.workspace,"write");if(e.providers?.length&&0!==r.length&&!1!==e.request.metadata?.memoryWrite)for(const t of r)await runMemoryPlugin(e,t)}export async function recallMemoryPlugins(e){const r=n(e.workspace,"recall");if(!e.providers?.length||0===r.length)return[];const t=await Promise.all(r.map(async r=>{try{return await async function recallMemoryPlugin(e,r){const t=o(e.providers??[],r.provider);if(!t)return;const n=a(e.workspace,e.agent,e.request,r),s=await t.search({namespace:n,query:buildRecallQuery(e),limit:readRecallLimit(e.workspace)});return{namespace:n,records:s,context:formatRecallContext(e.workspace,s)}}(e,r)}catch{return}}));return t.filter(e=>Boolean(e?.context))}async function runMemoryPlugin(r,t){const n=o(r.providers??[],t.provider);if(!n)return;const s=a(r.workspace,r.agent,r.request,t);r.emit({type:"runtime.memory.plugin.started",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s});try{const e=await n.propose(function createPluginProposeInput(e,r,t){return{namespace:t,content:[`User input:\n${e.request.input}`,`Agent output:\n${e.result.text}`].join("\n\n"),sourceType:"runtime-run",sourceRef:e.requestId,metadata:{memoryId:r.id,provider:r.provider,profile:r.profile,mode:r.mode,prompts:r.prompts,workspaceRoot:e.workspace.root,agentId:e.agent.id,sessionId:e.sessionId,requestMetadata:e.request.metadata}}}(r,t,s));r.emit({type:"runtime.memory.plugin.completed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,candidateCount:e.length})}catch(o){r.emit({type:"runtime.memory.plugin.failed",requestId:r.requestId,sessionId:r.sessionId,agentId:r.agent.id,memoryId:t.id,provider:n.name,namespace:s,error:e(o)})}}function buildRecallQuery(e){const r=[`task: ${e.request.input}`,`workspace: ${t(e.workspace)}`,`agent: ${e.agent.id}`,"memory_needed: durable preferences, workspace facts, reusable procedures, prior corrections"],n=function readRecentContext(e){return"string"==typeof e?.recentContext?e.recentContext.slice(0,3e3):Array.isArray(e?.recentTurns)?e.recentTurns.filter(e=>"string"==typeof e).slice(-6).join("\n").slice(0,3e3):void 0}(e.request.metadata);return n?[...r,`recent_context: ${n}`].join("\n"):r.join("\n")}function readRecallLimit(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall),o=n?.topK??n?.limit;return"number"==typeof o&&Number.isFinite(o)?o:10}function formatRecallContext(e,t){const n=function readRecallContextLimits(e){const t=r(e.runtime.memory?.LangMem),n=r(t?.recall);return{maxContextChars:readPositiveNumber(n?.maxContextChars)??4e3,maxRecordChars:readPositiveNumber(n?.maxRecordChars)??1e3}}(e),o=[];let a=n.maxContextChars;for(const e of t){if(a<=0)break;const r=truncateText(formatRecallRecord(e),Math.min(n.maxRecordChars,a));r.trim()&&(o.push(r),a-=r.length+1)}return o.join("\n")}function formatRecallRecord(e){return`- ${e.summary??e.content}\n ${e.content}`}function readPositiveNumber(e){return"number"==typeof e&&Number.isFinite(e)&&e>0?Math.floor(e):void 0}function truncateText(e,r){return e.length>r?`${e.slice(0,Math.max(0,r-13))}\n [truncated]`:e}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { RuntimeEvent, RuntimeRequest } from "../types.js";
|
|
2
|
+
export declare function toolCallRecoveryEnabled(policy: unknown): boolean;
|
|
3
|
+
export declare function isRecoverableAdapterError(error: unknown, policy: unknown): boolean;
|
|
4
|
+
export declare function buildAdapterErrorRecoveryPrompt(request: RuntimeRequest, error: unknown, policy: unknown): RuntimeRequest;
|
|
5
|
+
export declare function buildResultRecoveryRequest(input: {
|
|
6
|
+
request: RuntimeRequest;
|
|
7
|
+
output: string;
|
|
8
|
+
events: RuntimeEvent[];
|
|
9
|
+
availableToolIds?: string[];
|
|
10
|
+
policy: unknown;
|
|
11
|
+
}): RuntimeRequest | undefined;
|
|
12
|
+
export declare function buildExecutionContractRecoveryRequest(input: {
|
|
13
|
+
request: RuntimeRequest;
|
|
14
|
+
events: RuntimeEvent[];
|
|
15
|
+
policy: unknown;
|
|
16
|
+
}): RuntimeRequest | undefined;
|
|
17
|
+
export declare function assertNoRawToolCallOutput(output: string, policy: unknown): void;
|
|
18
|
+
export declare function containsRawToolCallOutput(output: string, policy: unknown): boolean;
|
|
19
|
+
export declare function containsRecoverableResultOutput(output: string, policy: unknown): boolean;
|
|
20
|
+
export declare function assertNoToolExecutionErrorOutput(output: string, policy: unknown): void;
|
|
21
|
+
export declare function rawToolCallFailureMessage(): string;
|
|
22
|
+
export declare function buildEvidenceSynthesisOutput(input: {
|
|
23
|
+
request: RuntimeRequest;
|
|
24
|
+
output: string;
|
|
25
|
+
events: RuntimeEvent[];
|
|
26
|
+
policy: unknown;
|
|
27
|
+
}): string | undefined;
|
|
28
|
+
export declare function rawToolCallOutputPreview(output: string): string;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function toolCallRecoveryEnabled(e){return!0===readToolCallRecovery(e).enabled}export function isRecoverableAdapterError(e,t){const o=readToolCallRecovery(t);if(!0!==o.enabled)return!1;const n=e instanceof Error?e.message:String(e);return readRegexps(o.adapterErrorPatterns,[/XML syntax error|tool.?call.*syntax|malformed.*(?:XML|tool)|Non string tool message content|repeat limit reached for tool/iu]).some(e=>e.test(n))}export function buildAdapterErrorRecoveryPrompt(e,t,o){const n=t instanceof Error?t.message:String(t),r=readToolCallRecovery(o).instruction;return recoverRequest(e,["Stable runtime recovery: the backend failed while parsing a tool call.",`Parser error: ${n}`,"string"==typeof r?r:"Continue the same user request using the backend's normal tool-calling mechanism, then return a final human-readable answer.","Do not print raw tool-call markup, JSON tool-call envelopes, or pseudo tool-call text in the final answer."])}export function buildResultRecoveryRequest(e){const t=readToolCallRecovery(e.policy);if(!0!==t.enabled)return;if(containsRawToolCallText(e.output,t)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer printed raw tool-call markup instead of executing the tool.","Continue the same user request by calling the available upstream tool normally when more evidence is required.","If you call a tool, the next assistant action must be the backend's structured tool call itself, with no prose before it.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"If the conversation context already contains enough evidence to answer, synthesize the final answer from that context instead.","Do not print XML, JSON, markdown fences, pseudo tool-call text, plans, or future-intent text such as saying you will call or wait for a tool.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}if(containsToolExecutionErrorText(e.output,t)){const t=recentToolEvidence(e.events,1e3);return recoverRequest(e.request,["Stable runtime recovery: your previous final answer exposed a backend tool execution error instead of handling it.","Continue the same user request using the backend's normal structured tool-calling mechanism.","Do not retry the same invalid tool arguments. If the failed tool is not required to answer the user, synthesize the final answer from the available context instead.",...e.availableToolIds?.length?[`Available configured tools: ${e.availableToolIds.join(", ")}`,"Do not invent, print, or call tools that are not in this list."]:[],"Do not print tool error stacks, schema validation diagnostics, raw tool-call markup, JSON tool-call envelopes, or pseudo tool-call text in the final answer.",...t.length>0?["","Recent executed tool evidence:",...t]:[],"","Previous invalid final answer:",e.output])}const o=function lastConfiguredEventHint(e,t){const o=function readEventRecoveryHints(e){return(Array.isArray(e)?e:[]).flatMap(e=>isRecord(e)&&"string"==typeof e.instruction?[{..."string"==typeof e.toolId?{toolId:e.toolId}:{},..."string"==typeof e.phase?{phase:e.phase}:{},..."string"==typeof e.outputIncludes?{outputIncludes:e.outputIncludes}:{},..."string"==typeof e.outputMatches?{outputMatches:e.outputMatches}:{},instruction:e.instruction}]:[])}(t.eventRecoveryHints);if(0!==o.length)return e.flatMap(e=>function readMatchingHints(e,t){const o="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;return o?t.filter(e=>function eventMatchesHint(e,t){return(!t.toolId||e.toolId===t.toolId)&&(!t.phase||e.phase===t.phase)&&(t.outputIncludes?"string"==typeof e.output&&e.output.includes(t.outputIncludes):!t.outputMatches||"string"==typeof e.output&&new RegExp(t.outputMatches,"u").test(e.output))}(o,e)).map(e=>({output:"string"==typeof o.output?o.output:"Adapter event matched configured recovery hint.",instruction:e.instruction})):[]}(e,o)).at(-1)}(e.events,t);return o?recoverRequest(e.request,["Stable runtime recovery: a previous adapter event matched a configured recovery hint.",o.output,o.instruction]):void 0}export function buildExecutionContractRecoveryRequest(e){if(!0!==readToolCallRecovery(e.policy).enabled)return;const t=function lastMissingEvidenceTools(e){for(let t=e.length-1;t>=0;t-=1){const o=e[t];if("runtime.execution.contract.failed"===o?.type)return readStringArray(o.missingEvidenceTools)}return[]}(e.events);return 0!==t.length?recoverRequest(e.request,["Stable runtime recovery: the execution contract was not satisfied.",`Required evidence tool(s) were missing: ${t.join(", ")}`,"Continue the same user request by calling the missing required evidence tool(s) through the backend's normal structured tool-calling mechanism.","Do not produce a final answer until the required evidence tool call has executed and you have synthesized its result.","Do not print XML, JSON, markdown fences, pseudo tool-call text, plans, or future-intent text in the final answer."]):void 0}export function assertNoRawToolCallOutput(e,t){if(containsRawToolCallOutput(e,t))throw new Error(`Adapter returned raw tool-call text as the final answer after recovery. The backend must execute tools instead of printing tool-call markup. Output preview: ${previewOutput(e)}`)}export function containsRawToolCallOutput(e,t){const o=readToolCallRecovery(t);return!0===o.enabled&&containsRawToolCallText(e,o)}export function containsRecoverableResultOutput(e,t){const o=readToolCallRecovery(t);return!0===o.enabled&&containsRecoverableResultFailureText(e,o)}export function assertNoToolExecutionErrorOutput(e,t){const o=readToolCallRecovery(t);if(!0===o.enabled&&containsToolExecutionErrorText(e,o))throw new Error(`Adapter returned a tool execution error as the final answer after recovery. Output preview: ${previewOutput(e)}`)}export function rawToolCallFailureMessage(){return["The model attempted to call a tool but returned the tool call as text instead of executing it.","Please retry the request or use a model/backend configuration with reliable tool calling for this workspace."].join(" ")}export function buildEvidenceSynthesisOutput(e){const t=readToolCallRecovery(e.policy);if(!0!==t.enabled||!1===t.synthesizeFromEvidenceOnFailure||!containsRecoverableResultFailureText(e.output,t))return;const o=recentToolEvidence(e.events,6e3);return 0!==o.length?"zh"==(/\p{Script=Han}/u.test(e.request.input)?"zh":"en")?function buildChineseEvidenceSynthesis(e,t){return["上游模型在已有工具证据后仍输出了伪工具调用;runtime 已拒绝该 raw 输出,并直接交付已执行工具返回的证据结果。","","已执行的工具证据:",...t,"",`被拒绝的最终输出预览:${previewRejectedOutput(e)}`].join("\n")}(e.output,o):function buildEnglishEvidenceSynthesis(e,t){return["The upstream model still returned pseudo tool-call text after tool evidence was available. The runtime rejected that raw output and is returning the executed tool evidence directly.","","Executed tool evidence:",...t,"",`Rejected final output preview: ${previewRejectedOutput(e)}`].join("\n")}(e.output,o):void 0}function previewOutput(e){const t=e.replace(/\s+/gu," ").trim();return t.length>300?`${t.slice(0,297)}...`:t}function previewRejectedOutput(e){return previewOutput(e).replace(/[<>]/gu,"")}export function rawToolCallOutputPreview(e){return previewOutput(e)}function recoverRequest(e,t){return{...e,input:[e.input,"",...t].join("\n"),metadata:{...e.metadata,stableHarnessRecovery:"tool_call"}}}function containsRawToolCallText(e,t){const o=readRegexps(t.rawOutputPatterns,[/\{\s*"name"\s*:\s*"[^"]+"\s*,\s*"arguments"\s*:/iu,/\{\s*"tool_name"\s*:\s*"[^"]+"\s*,\s*"parameters"\s*:/iu,/\{\s*"type"\s*:\s*"[^"]+"\s*,\s*"args"\s*:/iu,/^\s*[A-Za-z_][\w.-]*\s*\([^)]{0,2000}\)\s*$/iu,/^\s*[A-Za-z_][\w.-]*(?:_command|_tool|_analysis|_investigate|task)\s*$/iu,/```(?:json)?[\s\S]{0,4000}"(?:tool_name|tool|name|subagent_type)"\s*:/iu,/```(?:json)?[\s\S]{0,4000}"(?:tool_name|tool|name|subagent_type)"\s*:[\s\S]{0,4000}"(?:arguments|parameters|task)"\s*:/iu,/```(?:json)?[\s\S]{0,2000}"query"\s*:[\s\S]{0,2000}"(?:max_results|count|freshness|market)"\s*:/iu]);return!![/<\s*(?:tool_call|task)\b[^>]*>/iu,/<\s*\/\s*(?:tool_call|task)\s*>/iu,/<\s*\/?\s*tool_code\b[^>]*>/iu,/<\s*\/?\s*[A-Za-z_][\w.-]*(?:_command|_tool|_analysis|_investigate|_todos|task)\b[^>]*>/iu].some(t=>t.test(e))||function looksLikeStandaloneRecoveryCandidate(e){const t=e.trim();return t.length<=6e3||/^\s*(?:```|\{|\[|[A-Za-z_][\w.-]*\s*\()/u.test(t)}(e)&&(o.some(t=>t.test(e))||[/^[\s\S]{0,2400}\b(?:I need to|I will|I'll|I am going to|I'm going to)\s+(?:call|use|invoke|delegate)\b[\s\S]{0,1200}\b(?:tool|function|specialist|subagent)\b[\s\S]{0,400}$/iu,/^[\s\S]{0,2400}\b(?:I will|I'll|I am going to|I'm going to)\s+(?:investigate|gather|check)\b[\s\S]{0,1200}\b(?:evidence|cluster|system|results?)\b[\s\S]{0,400}$/iu,/^[\s\S]{0,2400}\b(?:waiting for|wait for)\b[\s\S]{0,1200}\b(?:tool|function|specialist|subagent)\b[\s\S]{0,400}$/iu,/^[\s\S]{0,2400}\b(?:Would you like me to|Do you want me to|Should I|I can help with)\b[\s\S]{0,1200}\?[\s\S]{0,400}$/iu,/^[\s\S]{0,2400}\bCould you please provide\b[\s\S]{0,1200}\b(?:tool|function|specialist|subagent|task)\b[\s\S]{0,400}$/iu,/^[\s\S]{0,2400}\b(?:I don't|I do not) have enough information\b[\s\S]{0,1200}\b(?:tool|function|specialist|subagent|task|context)\b[\s\S]{0,400}$/iu,/^[\s\S]{0,2400}\bLet me\s+(?:call|use|invoke|delegate|check|run|verify|gather|inspect)\b[\s\S]{0,1200}\b(?:tool|function|specialist|subagent|results?|data|evidence|commands?)\b[\s\S]{0,400}$/iu,/^[\s\S]{0,2400}(?:我需要|我要|我会|我将|让我|我来|接下来我(?:会|将)?)\s*(?:先)?(?:调用|使用|运行|执行|检查|读取|收集|调查|验证|查看)[\s\S]{0,1200}$/iu,/^[\s\S]{0,2400}(?:要不要|是否需要|需要我|你想让我)[\s\S]{0,1200}(?:继续|进一步|帮你|分析|检查)[\s\S]{0,1200}[??][\s\S]{0,400}$/iu].some(t=>t.test(e)))}function containsRecoverableResultFailureText(e,t){return containsRawToolCallText(e,t)||containsToolExecutionErrorText(e,t)}function containsToolExecutionErrorText(e,t){return readRegexps(t.toolFailureOutputPatterns,[/^Error invoking tool ['"][^'"]+['"] with kwargs /iu,/Received tool input did not match expected schema/iu,/ToolMessage.*status.*error/iu]).some(t=>t.test(e))}function recentToolEvidence(e,t){return e.flatMap(e=>{const o="runtime.adapter.event"===e.type&&isRecord(e.event)?e.event:void 0;return o&&"agent.tool.result"===o.phase&&"string"==typeof o.toolId?function isControlToolOutput(e){if("string"!=typeof e||!e.trim().startsWith("{"))return!1;try{const t=JSON.parse(e),o=isRecord(t)?t.status:void 0;return"duplicate_tool_call"===o||"repeated_tool_call_limit"===o||"tool_argument_error"===o}catch{return!1}}(o.output)?[]:[`- ${o.toolId}: ${formatToolEvidence(o,t)}`]:[]}).slice(-5)}function formatToolEvidence(e,t=1e3){return"string"==typeof e.output&&e.output.trim()?e.output.slice(0,t):"string"==typeof e.error&&e.error.trim()?`error: ${e.error.slice(0,t)}`:isRecord(e.args)?`completed with args: ${previewOutput(JSON.stringify(e.args))}`:"completed"}function readToolCallRecovery(e){if(!isRecord(e))return{};const t=isRecord(e.recovery)?e.recovery:{};return isRecord(t.toolCall)?t.toolCall:{}}function readRegexps(e,t){const o=(Array.isArray(e)?e:[]).filter(e=>"string"==typeof e&&e.length>0).map(e=>new RegExp(e,"iu"));return o.length>0?o:t}function readStringArray(e){return Array.isArray(e)?e.filter(e=>"string"==typeof e&&e.length>0):[]}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { RuntimeEvent, RuntimeOutput, RuntimeResponse, RuntimeStore, WorkspaceAgent } from "../types.js";
|
|
2
|
+
export declare function completeRun(input: {
|
|
3
|
+
store: RuntimeStore;
|
|
4
|
+
emit: (event: RuntimeEvent) => void;
|
|
5
|
+
requestId: string;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
agent: WorkspaceAgent;
|
|
8
|
+
result: RuntimeOutput;
|
|
9
|
+
}): RuntimeResponse;
|
|
10
|
+
export declare function failRun(input: {
|
|
11
|
+
store: RuntimeStore;
|
|
12
|
+
emit: (event: RuntimeEvent) => void;
|
|
13
|
+
requestId: string;
|
|
14
|
+
sessionId: string;
|
|
15
|
+
agent: WorkspaceAgent;
|
|
16
|
+
error: unknown;
|
|
17
|
+
}): RuntimeResponse;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function completeRun(e){const t=e.store.getRun(e.requestId);if("cancelled"===t?.state)return response(e,"cancelled",t.artifacts);if(t){const s=function mergeArtifacts(e,t){const s=new Map;for(const r of[...e??[],...t??[]])s.set(r.id,r);return[...s.values()]}(t.artifacts,e.result.artifacts??[]);e.store.updateRun(e.requestId,{state:"completed",output:e.result.text,metadata:{...t.metadata,...e.result.metadata},artifacts:s,completedAt:(new Date).toISOString()})}for(const t of e.result.artifacts??[])e.emit({type:"runtime.artifact.created",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,artifact:t});return e.emit({type:"runtime.request.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,output:e.result.text}),response(e,"completed",e.store.getRun(e.requestId)?.artifacts)}export function failRun(e){const t=e.error instanceof Error?e.error.message:String(e.error);return e.store.getRun(e.requestId)&&e.store.updateRun(e.requestId,{state:"failed",error:t,completedAt:(new Date).toISOString()}),e.emit({type:"runtime.request.failed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,error:t}),{requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,state:"failed",output:t}}function response(e,t,s){return{requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,state:t,output:e.result.text,metadata:e.result.metadata,artifacts:s??e.result.artifacts}}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CompiledWorkspace, RuntimeEvent, RuntimeOutput, RuntimeRequest, RuntimeToolGateway, WorkspaceAgent } from "../types.js";
|
|
2
|
+
export declare function runDirectToolCall(input: {
|
|
3
|
+
gateway: RuntimeToolGateway | undefined;
|
|
4
|
+
workspace: CompiledWorkspace;
|
|
5
|
+
emit: (event: RuntimeEvent) => void;
|
|
6
|
+
request: RuntimeRequest;
|
|
7
|
+
requestId: string;
|
|
8
|
+
sessionId: string;
|
|
9
|
+
agent: WorkspaceAgent;
|
|
10
|
+
}): Promise<RuntimeOutput>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export async function runDirectToolCall(o){const t=o.request.toolCall;if(!t)throw new Error("Direct tool call request is missing");if(!o.gateway)throw new Error("Runtime tool gateway is not configured");const e=await async function resolveDirectToolCall(o){if(o.agent.tools.includes(o.toolId)&&o.gateway.get(o.toolId))return{toolId:o.toolId,args:o.args};const t=await(o.gateway.repairToolCall?.({toolId:o.toolId,args:o.args,allowedToolIds:o.agent.tools,context:{workspaceRoot:o.workspace.root,requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id}}));if(t&&o.agent.tools.includes(t.toolId)&&o.gateway.get(t.toolId))return t;if(!o.agent.tools.includes(o.toolId))throw new Error(`Tool ${o.toolId} is not assigned to agent ${o.agent.id}`);throw new Error(`Tool is not registered: ${o.toolId}`)}({gateway:o.gateway,workspace:o.workspace,requestId:o.requestId,sessionId:o.sessionId,agent:o.agent,toolId:t.toolId,args:t.args});o.emit({type:"runtime.tool.direct.started",requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id,toolId:e.toolId});const s=await o.gateway.invoke({toolId:e.toolId,args:e.args,context:{workspaceRoot:o.workspace.root,requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id}});return o.emit({type:"runtime.tool.direct.completed",requestId:o.requestId,sessionId:o.sessionId,agentId:o.agent.id,toolId:s.toolId,output:s.output}),{text:(r=s.output,"string"==typeof r?r:JSON.stringify(r)),metadata:{toolCall:{toolId:s.toolId}}};var r}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import type { MemoryCandidate, MemoryDecision, MemoryRecord } from "@stable-harness/memory";
|
|
2
|
+
import type { ApprovalRequest } from "@stable-harness/governance";
|
|
3
|
+
import type { RuntimeArtifact } from "../types.js";
|
|
4
|
+
export type RuntimeEvent = {
|
|
5
|
+
type: "runtime.request.started";
|
|
6
|
+
requestId: string;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
agentId: string;
|
|
9
|
+
input?: string;
|
|
10
|
+
} | {
|
|
11
|
+
type: "runtime.request.completed";
|
|
12
|
+
requestId: string;
|
|
13
|
+
sessionId: string;
|
|
14
|
+
agentId: string;
|
|
15
|
+
output: string;
|
|
16
|
+
} | {
|
|
17
|
+
type: "runtime.request.failed";
|
|
18
|
+
requestId: string;
|
|
19
|
+
sessionId: string;
|
|
20
|
+
agentId: string;
|
|
21
|
+
error: string;
|
|
22
|
+
} | {
|
|
23
|
+
type: "runtime.request.cancelled";
|
|
24
|
+
requestId: string;
|
|
25
|
+
sessionId: string;
|
|
26
|
+
agentId: string;
|
|
27
|
+
reason?: string;
|
|
28
|
+
} | {
|
|
29
|
+
type: "runtime.artifact.created";
|
|
30
|
+
requestId: string;
|
|
31
|
+
sessionId: string;
|
|
32
|
+
agentId: string;
|
|
33
|
+
artifact: RuntimeArtifact;
|
|
34
|
+
} | {
|
|
35
|
+
type: "runtime.execution.contract.failed";
|
|
36
|
+
requestId: string;
|
|
37
|
+
sessionId: string;
|
|
38
|
+
agentId: string;
|
|
39
|
+
reason: string;
|
|
40
|
+
missingEvidenceTools?: string[];
|
|
41
|
+
} | {
|
|
42
|
+
type: "runtime.tool.direct.started";
|
|
43
|
+
requestId: string;
|
|
44
|
+
sessionId: string;
|
|
45
|
+
agentId: string;
|
|
46
|
+
toolId: string;
|
|
47
|
+
} | {
|
|
48
|
+
type: "runtime.tool.direct.completed";
|
|
49
|
+
requestId: string;
|
|
50
|
+
sessionId: string;
|
|
51
|
+
agentId: string;
|
|
52
|
+
toolId: string;
|
|
53
|
+
output: unknown;
|
|
54
|
+
} | {
|
|
55
|
+
type: "runtime.workflow.started";
|
|
56
|
+
requestId: string;
|
|
57
|
+
sessionId: string;
|
|
58
|
+
agentId: string;
|
|
59
|
+
workflowId: string;
|
|
60
|
+
adapter: string;
|
|
61
|
+
} | {
|
|
62
|
+
type: "runtime.workflow.completed";
|
|
63
|
+
requestId: string;
|
|
64
|
+
sessionId: string;
|
|
65
|
+
agentId: string;
|
|
66
|
+
workflowId: string;
|
|
67
|
+
adapter: string;
|
|
68
|
+
} | {
|
|
69
|
+
type: "runtime.specDriven.phase.started";
|
|
70
|
+
requestId: string;
|
|
71
|
+
sessionId: string;
|
|
72
|
+
agentId: string;
|
|
73
|
+
phaseId: string;
|
|
74
|
+
workflowId?: string;
|
|
75
|
+
} | {
|
|
76
|
+
type: "runtime.specDriven.phase.blocked";
|
|
77
|
+
requestId: string;
|
|
78
|
+
sessionId: string;
|
|
79
|
+
agentId: string;
|
|
80
|
+
phaseId: string;
|
|
81
|
+
workflowId?: string;
|
|
82
|
+
reason: string;
|
|
83
|
+
} | {
|
|
84
|
+
type: "runtime.specDriven.phase.completed";
|
|
85
|
+
requestId: string;
|
|
86
|
+
sessionId: string;
|
|
87
|
+
agentId: string;
|
|
88
|
+
phaseId: string;
|
|
89
|
+
workflowId?: string;
|
|
90
|
+
artifact?: RuntimeArtifact;
|
|
91
|
+
} | {
|
|
92
|
+
type: "runtime.specDriven.phase.verified";
|
|
93
|
+
requestId: string;
|
|
94
|
+
sessionId: string;
|
|
95
|
+
agentId: string;
|
|
96
|
+
phaseId: string;
|
|
97
|
+
workflowId?: string;
|
|
98
|
+
artifact?: RuntimeArtifact;
|
|
99
|
+
} | {
|
|
100
|
+
type: "runtime.memory.lifecycle";
|
|
101
|
+
requestId: string;
|
|
102
|
+
sessionId: string;
|
|
103
|
+
agentId: string;
|
|
104
|
+
hook: RuntimeMemoryHook;
|
|
105
|
+
} | {
|
|
106
|
+
type: "runtime.memory.recall.completed";
|
|
107
|
+
requestId: string;
|
|
108
|
+
sessionId: string;
|
|
109
|
+
agentId: string;
|
|
110
|
+
namespace: string;
|
|
111
|
+
recordIds: string[];
|
|
112
|
+
context: string;
|
|
113
|
+
} | {
|
|
114
|
+
type: "runtime.memory.candidate.submitted";
|
|
115
|
+
requestId: string;
|
|
116
|
+
sessionId: string;
|
|
117
|
+
agentId: string;
|
|
118
|
+
candidate: MemoryCandidate;
|
|
119
|
+
decision: MemoryDecision;
|
|
120
|
+
record?: MemoryRecord;
|
|
121
|
+
} | {
|
|
122
|
+
type: "runtime.memory.approval.requested";
|
|
123
|
+
requestId: string;
|
|
124
|
+
sessionId: string;
|
|
125
|
+
agentId: string;
|
|
126
|
+
approval: ApprovalRequest;
|
|
127
|
+
} | {
|
|
128
|
+
type: "runtime.memory.plugin.started";
|
|
129
|
+
requestId: string;
|
|
130
|
+
sessionId: string;
|
|
131
|
+
agentId: string;
|
|
132
|
+
memoryId: string;
|
|
133
|
+
provider: string;
|
|
134
|
+
namespace: string;
|
|
135
|
+
} | {
|
|
136
|
+
type: "runtime.memory.plugin.completed";
|
|
137
|
+
requestId: string;
|
|
138
|
+
sessionId: string;
|
|
139
|
+
agentId: string;
|
|
140
|
+
memoryId: string;
|
|
141
|
+
provider: string;
|
|
142
|
+
namespace: string;
|
|
143
|
+
candidateCount: number;
|
|
144
|
+
} | {
|
|
145
|
+
type: "runtime.memory.plugin.failed";
|
|
146
|
+
requestId: string;
|
|
147
|
+
sessionId: string;
|
|
148
|
+
agentId: string;
|
|
149
|
+
memoryId: string;
|
|
150
|
+
provider: string;
|
|
151
|
+
namespace: string;
|
|
152
|
+
error: string;
|
|
153
|
+
} | {
|
|
154
|
+
type: "runtime.memory.maintenance.started";
|
|
155
|
+
requestId: string;
|
|
156
|
+
sessionId: string;
|
|
157
|
+
agentId: string;
|
|
158
|
+
target: string;
|
|
159
|
+
} | {
|
|
160
|
+
type: "runtime.memory.maintenance.completed";
|
|
161
|
+
requestId: string;
|
|
162
|
+
sessionId: string;
|
|
163
|
+
agentId: string;
|
|
164
|
+
target: string;
|
|
165
|
+
operationCount: number;
|
|
166
|
+
} | {
|
|
167
|
+
type: "runtime.memory.maintenance.failed";
|
|
168
|
+
requestId: string;
|
|
169
|
+
sessionId: string;
|
|
170
|
+
agentId: string;
|
|
171
|
+
target: string;
|
|
172
|
+
error: string;
|
|
173
|
+
} | {
|
|
174
|
+
type: "runtime.skill.candidate.created";
|
|
175
|
+
requestId: string;
|
|
176
|
+
sessionId: string;
|
|
177
|
+
agentId: string;
|
|
178
|
+
candidateId: string;
|
|
179
|
+
name: string;
|
|
180
|
+
confidence: number;
|
|
181
|
+
evidenceCount: number;
|
|
182
|
+
status: string;
|
|
183
|
+
proposedPath?: string;
|
|
184
|
+
} | {
|
|
185
|
+
type: "runtime.progress.narration";
|
|
186
|
+
requestId: string;
|
|
187
|
+
sessionId: string;
|
|
188
|
+
agentId: string;
|
|
189
|
+
message: string;
|
|
190
|
+
provider: string;
|
|
191
|
+
sourceEventTypes: string[];
|
|
192
|
+
sourceEventIds?: string[];
|
|
193
|
+
model?: string;
|
|
194
|
+
style?: string;
|
|
195
|
+
} | {
|
|
196
|
+
type: "runtime.adapter.event";
|
|
197
|
+
requestId: string;
|
|
198
|
+
sessionId: string;
|
|
199
|
+
agentId: string;
|
|
200
|
+
event: unknown;
|
|
201
|
+
};
|
|
202
|
+
export type RuntimeMemoryHook = "read-before-plan" | "read-before-finalize" | "write-after-run";
|
|
203
|
+
export type RuntimeEventListener = (event: RuntimeEvent) => void;
|
|
204
|
+
export type RuntimeEmit = (event: RuntimeEvent) => void;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ApprovalQueue } from "@stable-harness/governance";
|
|
2
|
+
import type { RuntimeMemoryStore } from "@stable-harness/memory";
|
|
3
|
+
import type { CompiledWorkspace, RuntimeEvent, RuntimeMemoryContext, RuntimeRequest, WorkspaceAgent } from "../types.js";
|
|
4
|
+
export declare function emitMemoryLifecycle(memory: RuntimeMemoryStore | undefined, emit: (event: RuntimeEvent) => void, requestId: string, sessionId: string, agentId: string, hook: "read-before-plan" | "read-before-finalize" | "write-after-run"): void;
|
|
5
|
+
export declare function runMemoryRecall(input: {
|
|
6
|
+
memory: RuntimeMemoryStore | undefined;
|
|
7
|
+
emit: (event: RuntimeEvent) => void;
|
|
8
|
+
request: RuntimeRequest;
|
|
9
|
+
requestId: string;
|
|
10
|
+
sessionId: string;
|
|
11
|
+
agent: WorkspaceAgent;
|
|
12
|
+
workspace: CompiledWorkspace;
|
|
13
|
+
}): Promise<RuntimeMemoryContext | undefined>;
|
|
14
|
+
export declare function submitMemoryCandidates(input: {
|
|
15
|
+
memory: RuntimeMemoryStore | undefined;
|
|
16
|
+
approvals: ApprovalQueue | undefined;
|
|
17
|
+
emit: (event: RuntimeEvent) => void;
|
|
18
|
+
request: RuntimeRequest;
|
|
19
|
+
requestId: string;
|
|
20
|
+
sessionId: string;
|
|
21
|
+
agent: WorkspaceAgent;
|
|
22
|
+
workspace: CompiledWorkspace;
|
|
23
|
+
}): Promise<void>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function emitMemoryLifecycle(e,r,t,s,o,n){e&&r({type:"runtime.memory.lifecycle",requestId:t,sessionId:s,agentId:o,hook:n})}export async function runMemoryRecall(e){if(!e.memory)return;if(emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"read-before-plan"),!1===e.request.memory?.recall)return;const r=resolveMemoryNamespace(e.workspace,e.agent,e.request),t=e.request.memory?.recall?.query??e.request.input,s=await e.memory.recall({namespace:r,query:t,limit:e.request.memory?.recall?.limit});return e.emit({type:"runtime.memory.recall.completed",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,namespace:r,recordIds:s.records.map(e=>e.id),context:s.context}),{namespace:r,records:s.records,context:s.context}}export async function submitMemoryCandidates(e){if(!e.memory||!e.request.memory?.candidates?.length)return;emitMemoryLifecycle(e.memory,e.emit,e.requestId,e.sessionId,e.agent.id,"write-after-run");const r=resolveMemoryNamespace(e.workspace,e.agent,e.request);for(const t of e.request.memory.candidates){const s={...t,namespace:t.namespace??r},o=await e.memory.submitCandidate(s);if(e.emit({type:"runtime.memory.candidate.submitted",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,candidate:o.candidate,decision:o.decision,record:o.record}),"review"===o.decision.action&&e.approvals){const r=await e.approvals.create({kind:"memory_write",reason:o.decision.reason,requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,subject:{candidate:o.candidate,decision:o.decision}});e.emit({type:"runtime.memory.approval.requested",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agent.id,approval:r})}}}function resolveMemoryNamespace(e,r,t){return t.memory?.namespace??`${e.root}:${r.id}`}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as t,mkdirSync as e,readFileSync as r,writeFileSync as n}from"node:fs";import i from"node:path";export function createInMemoryArtifactStore(t){const e=new Map((t?.records??[]).map(t=>[t.id,cloneRecord(t)])),r=new Map(Object.entries(t?.contents??{}).map(([t,e])=>[t,structuredClone(e)]));return{createArtifact(t){const n=function toRecord(t){return{id:t.id,kind:t.kind,uri:t.uri,metadata:t.metadata,requestId:t.requestId,sessionId:t.sessionId,agentId:t.agentId,contentType:t.contentType,createdAt:t.createdAt??(new Date).toISOString(),size:(e=t.content,Buffer.byteLength(JSON.stringify(e??null),"utf8"))};var e}(t);return e.set(n.id,n),r.set(n.id,structuredClone(t.content??null)),cloneRecord(n)},listArtifacts:t=>[...e.values()].filter(e=>function matchesFilter(t,e){return!e||!(e.requestId&&e.requestId!==t.requestId||e.sessionId&&e.sessionId!==t.sessionId||e.agentId&&e.agentId!==t.agentId)}(e,t)).map(cloneRecord),readArtifact(t){if(!r.has(t))throw new Error(`Artifact not found: ${t}`);return structuredClone(r.get(t))}}}export function createJsonFileArtifactStore(c){const o=i.resolve(c),s=createInMemoryArtifactStore(function readArtifactFile(e){if(!t(e))return{records:[],contents:{}};const n=JSON.parse(r(e,"utf8"));if(!function isState(t){return"object"==typeof t&&null!==t&&Array.isArray(t.records)&&"object"==typeof t.contents}(n))throw new Error(`Invalid artifact store file: ${e}`);return n}(o));return{createArtifact(t){const r=s.createArtifact(t);return function writeArtifactFile(t,r){e(i.dirname(t),{recursive:!0}),n(t,`${JSON.stringify({version:1,...r},null,2)}\n`)}(o,function snapshot(t){const e=t.listArtifacts(),r=Object.fromEntries(e.map(e=>[e.id,t.readArtifact(e.id)]));return{records:e,contents:r}}(s)),r},listArtifacts:t=>s.listArtifacts(t),readArtifact:t=>s.readArtifact(t)}}function cloneRecord(t){return structuredClone(t)}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CompiledWorkspace, RuntimeRequestInspection, RuntimeRequestSummary, RuntimeRunRecord, RuntimeSessionSummary } from "
|
|
1
|
+
import type { CompiledWorkspace, RuntimeRequestInspection, RuntimeRequestSummary, RuntimeRunRecord, RuntimeSessionSummary } from "../../types.js";
|
|
2
2
|
export declare function projectRequestSummary(run: RuntimeRunRecord): RuntimeRequestSummary;
|
|
3
3
|
export declare function projectSessionSummaries(runs: RuntimeRunRecord[]): RuntimeSessionSummary[];
|
|
4
4
|
export declare function projectRequestInspection(workspace: CompiledWorkspace, run: RuntimeRunRecord): RuntimeRequestInspection;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{applySpecDrivenPhaseTransition as t,createSpecDrivenWorkflowState as e}from"../../spec-driven/index.js";export function projectRequestSummary(t){return{requestId:t.requestId,sessionId:t.sessionId,agentId:t.agentId,parentRunId:t.parentRunId,state:t.state,startedAt:t.startedAt,completedAt:t.completedAt,eventCount:t.events.length,artifactCount:t.artifacts.length}}export function projectSessionSummaries(t){const e=new Map;for(const n of t)e.set(n.sessionId,[...e.get(n.sessionId)??[],n]);return[...e.entries()].map(([t,e])=>function projectSessionSummary(t,e){const n=[...e].sort((t,e)=>t.startedAt.localeCompare(e.startedAt));return{sessionId:t,requestCount:e.length,agentIds:[...new Set(e.map(t=>t.agentId))].sort(),states:countStates(e),startedAt:n[0]?.startedAt??"",updatedAt:latestTimestamp(e)}}(t,e)).sort((t,e)=>e.updatedAt.localeCompare(t.updatedAt))}export function projectRequestInspection(t,e){return{summary:projectRequestSummary(e),input:e.input,output:e.output,error:e.error,metadata:e.metadata,artifacts:e.artifacts,runtimeSnapshot:projectBindingSnapshot(t,e.agentId),...t.runtime.specDrivenWorkflow?{specDrivenWorkflow:projectSpecDrivenState(t.runtime.specDrivenWorkflow,e)}:{},timeline:projectTimeline(e)}}function projectSpecDrivenState(n,r){const s=new Set(n.phases.map(t=>t.id));return r.events.map(specDrivenTransition).filter(t=>void 0!==t&&s.has(t.phaseId)).reduce(t,e(n))}function specDrivenTransition(t){if(!function isSpecDrivenPhaseEvent(t){return t.type.startsWith("runtime.specDriven.phase.")}(t))return;const e=t.type.slice(25);return["started","blocked","completed","verified"].includes(e)?{phaseId:t.phaseId,status:e,..."artifact"in t&&t.artifact?{artifact:t.artifact}:{},..."reason"in t?{reason:t.reason}:{}}:void 0}function projectBindingSnapshot(t,e){const n=t.agents.get(e);return{workspaceRoot:t.root,agentId:e,backend:n?.backend??"unknown",modelRef:n?.modelRef,tools:[...n?.tools??[]],skills:[...n?.skills??[]],subagents:[...n?.subagents??[]]}}function projectTimeline(t){return t.events.map((t,e)=>({index:e,type:t.type,event:t}))}function countStates(t){return t.reduce((t,e)=>(t[e.state]=(t[e.state]??0)+1,t),{})}function latestTimestamp(t){return t.map(t=>t.completedAt??t.startedAt).sort((t,e)=>e.localeCompare(t))[0]??""}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { RuntimeQueueStore } from "
|
|
1
|
+
import type { RuntimeQueueStore } from "../types.js";
|
|
2
2
|
export declare function createInMemoryRuntimeQueueStore(): RuntimeQueueStore;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function createInMemoryRuntimeQueueStore(){const e=new Map,t=new Map,r=new Map;return{enqueue(t){const r=t.enqueuedAt??(new Date).toISOString(),n=cloneQueueRecord({...t,enqueuedAt:r,attemptCount:t.attemptCount??0});return e.set(n.requestId,n),cloneQueueRecord(n)},listQueue:()=>sortQueue([...e.values()]).map(cloneQueueRecord),getQueuedRequest:t=>cloneOptional(e.get(t),cloneQueueRecord),claimNext(r){const n=function findClaimCandidate(e,t){const r=Date.parse(t.now??(new Date).toISOString());return sortQueue(e).find(e=>{const n=Date.parse(e.availableAt)<=r,o=!t.queueKey||e.queueKey===t.queueKey,u=!e.leaseExpiresAt||Date.parse(e.leaseExpiresAt)<=r;return n&&o&&u})}([...e.values()],r);if(!n)return;const o=r.now??(new Date).toISOString(),u=function claimRecord(e,t,r,n){return{...e,claimedBy:t,claimedAt:r,leaseExpiresAt:new Date(Date.parse(r)+n).toISOString(),attemptCount:e.attemptCount+1}}(n,r.workerId,o,r.leaseMs);return e.set(u.requestId,u),t.set(u.requestId,{requestId:u.requestId,cancelRequested:t.get(u.requestId)?.cancelRequested??!1,workerId:r.workerId,workerStartedAt:t.get(u.requestId)?.workerStartedAt??o,heartbeatAt:o}),cloneQueueRecord(u)},heartbeat(e){const r=t.get(e.requestId);if(!r||r.workerId!==e.workerId)return;const n={...r,heartbeatAt:e.now??(new Date).toISOString()};return t.set(e.requestId,n),cloneControl(n)},requestCancel(e){const r={...t.get(e.requestId),requestId:e.requestId,cancelRequested:!0,cancelReason:e.reason,cancelRequestedAt:e.now??(new Date).toISOString()};return t.set(e.requestId,r),cloneControl(r)},getControl:e=>cloneOptional(t.get(e),cloneControl),listStuck(r){const n=Date.parse(r.now??(new Date).toISOString());return[...e.values()].filter(e=>function isStuck(e,t,r,n){if(!e.claimedAt)return!1;const o=Date.parse(t?.heartbeatAt??e.claimedAt);return!!e.leaseExpiresAt&&Date.parse(e.leaseExpiresAt)<r||r-o>n}(e,t.get(e.requestId),n,r.staleAfterMs)).map(cloneQueueRecord)},saveRecoveryIntent:e=>(r.set(e.requestId,cloneRecovery(e)),cloneRecovery(e)),getRecoveryIntent:e=>cloneOptional(r.get(e),cloneRecovery),clearRecoveryIntent:e=>r.delete(e)}}function sortQueue(e){return[...e].sort((e,t)=>{const r=t.priority-e.priority;return 0===r?e.enqueuedAt.localeCompare(t.enqueuedAt):r})}function cloneOptional(e,t){return e?t(e):void 0}function cloneQueueRecord(e){return structuredClone(e)}function cloneControl(e){return structuredClone(e)}function cloneRecovery(e){return structuredClone(e)}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { RuntimeRunRecord, RuntimeStore } from "
|
|
1
|
+
import type { RuntimeRunRecord, RuntimeStore } from "../types.js";
|
|
2
2
|
export declare function createInMemoryRuntimeStore(initialRuns?: RuntimeRunRecord[]): RuntimeStore;
|
|
3
3
|
export declare function createJsonFileRuntimeStore(filePath: string): RuntimeStore;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{existsSync as e,mkdirSync as t,readFileSync as n,writeFileSync as r}from"node:fs";import u from"node:path";export function createInMemoryRuntimeStore(e=[]){const t=new Map(e.map(e=>[e.requestId,cloneRun(e)]));return{createRun(e){t.set(e.requestId,cloneRun(e))},updateRun(e,n){const r=t.get(e);if(r)return Object.assign(r,function clonePatch(e){return structuredClone(e)}(n)),cloneRun(r)},appendEvent(e){const n=t.get(e.requestId);if(!n)return;const r=function eventArtifact(e){return"artifact"in e&&e.artifact?e.artifact:void 0}(e);return r&&!n.artifacts.some(e=>e.id===r.id)&&n.artifacts.push(structuredClone(r)),n.events.push(function cloneEvent(e){return structuredClone(e)}(e)),cloneRun(n)},getRun:e=>function cloneOptionalRun(e){return e?cloneRun(e):void 0}(t.get(e)),listRuns:e=>[...t.values()].filter(t=>function matchesFilter(e,t){return!t||!(t.agentId&&t.agentId!==e.agentId||t.sessionId&&t.sessionId!==e.sessionId||t.state&&t.state!==e.state)}(t,e)).map(cloneRun)}}export function createJsonFileRuntimeStore(t){const r=u.resolve(t),i=createInMemoryRuntimeStore(function readStoreFile(t){if(!e(t))return[];const r=JSON.parse(n(t,"utf8"));if(!isRecord(r)||!Array.isArray(r.runs))throw new Error(`Invalid runtime store file: ${t}`);return r.runs.map(assertRunRecord)}(r));return{createRun(e){i.createRun(e),writeStoreFile(r,i.listRuns())},updateRun(e,t){const n=i.updateRun(e,t);return writeStoreFile(r,i.listRuns()),n},appendEvent(e){const t=i.appendEvent(e);return writeStoreFile(r,i.listRuns()),t},getRun:e=>i.getRun(e),listRuns:e=>i.listRuns(e)}}function writeStoreFile(e,n){t(u.dirname(e),{recursive:!0}),r(e,`${JSON.stringify({version:1,runs:n},null,2)}\n`)}function assertRunRecord(e){if(!isRecord(e)||"string"!=typeof e.requestId)throw new Error("Invalid runtime run record in store file");return cloneRun(e)}function cloneRun(e){return structuredClone(e)}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { RuntimeEvent } from "./events.js";
|
|
2
|
+
export type RuntimeProgressNarrationProvider = {
|
|
3
|
+
name: string;
|
|
4
|
+
narrate(event: RuntimeEvent, context: RuntimeProgressNarrationContext): RuntimeProgressNarrationResult;
|
|
5
|
+
};
|
|
6
|
+
export type RuntimeProgressNarrationResult = RuntimeProgressNarrationOutput | undefined | Promise<RuntimeProgressNarrationOutput | undefined>;
|
|
7
|
+
export type RuntimeProgressNarrationContext = {
|
|
8
|
+
style?: string;
|
|
9
|
+
model?: string;
|
|
10
|
+
};
|
|
11
|
+
export type RuntimeProgressNarrationOutput = {
|
|
12
|
+
message: string;
|
|
13
|
+
sourceEventTypes?: string[];
|
|
14
|
+
sourceEventIds?: string[];
|
|
15
|
+
model?: string;
|
|
16
|
+
style?: string;
|
|
17
|
+
};
|
|
18
|
+
export type RuntimeProgressNarrationOptions = {
|
|
19
|
+
enabled?: boolean;
|
|
20
|
+
style?: string;
|
|
21
|
+
model?: string;
|
|
22
|
+
provider?: RuntimeProgressNarrationProvider;
|
|
23
|
+
};
|
|
24
|
+
export declare function resolveProgressNarrator(input: {
|
|
25
|
+
options?: RuntimeProgressNarrationOptions | false;
|
|
26
|
+
policy?: Record<string, unknown>;
|
|
27
|
+
}): RuntimeProgressNarrationProvider | undefined;
|
|
28
|
+
export declare function createProgressNarrationEvent(input: {
|
|
29
|
+
source: RuntimeEvent;
|
|
30
|
+
narrator: RuntimeProgressNarrationProvider | undefined;
|
|
31
|
+
options?: RuntimeProgressNarrationOptions | false;
|
|
32
|
+
policy?: Record<string, unknown>;
|
|
33
|
+
}): RuntimeEvent | Promise<RuntimeEvent | undefined> | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function resolveProgressNarrator(e){if(!1===e.options)return;const t=readProgressPolicy(e.policy);return e.options?.enabled??t.enabled?e.options?.provider??function createTemplateProgressNarrator(){const e=new Map,t=new Map;return{name:"template",narrate(r,n){var o;"runtime.request.started"===r.type&&(e.set(r.requestId,{language:(o=r.input??"",/\p{Script=Han}/u.test(o)?"zh":void 0),input:r.input}),t.delete(r.requestId));const i=function templateMessage(e,t){const r="zh"===t?.language;return"runtime.request.started"===e.type?r?`我开始处理这个请求:${summarizeText(e.input)}`:`I'm starting on this request: ${summarizeText(e.input)}`:"runtime.request.completed"===e.type?r?"我已经完成执行链,正在交付最终结果。":"I've finished the execution chain and am returning the final result.":"runtime.request.failed"===e.type?r?"执行链失败了,我会保留具体错误方便定位。":"The execution chain failed; I'm keeping the concrete error visible for diagnosis.":"runtime.request.cancelled"===e.type?r?"这个请求已取消,后续执行会停止。":"The request was cancelled, so the remaining execution will stop.":"runtime.tool.direct.started"===e.type?r?`我正在运行 ${e.toolId}。`:`I'm running ${e.toolId}.`:"runtime.tool.direct.completed"===e.type?r?`${e.toolId} 已返回结果,我会继续使用这份证据。`:`${e.toolId} returned; I'll keep using that evidence.`:"runtime.workflow.started"===e.type?r?`我正在启动 workflow ${e.workflowId}。`:`I'm starting workflow ${e.workflowId}.`:"runtime.workflow.completed"===e.type?r?`workflow ${e.workflowId} 已完成。`:`Workflow ${e.workflowId} is complete.`:"runtime.specDriven.phase.started"===e.type?r?`我正在进入 spec-driven 阶段 ${e.phaseId}。`:`I'm starting spec-driven phase ${e.phaseId}.`:"runtime.specDriven.phase.blocked"===e.type?r?`spec-driven 阶段 ${e.phaseId} 被 gate 阻塞。`:`Spec-driven phase ${e.phaseId} is blocked by a gate.`:"runtime.specDriven.phase.completed"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已完成。`:`Spec-driven phase ${e.phaseId} is complete.`:"runtime.specDriven.phase.verified"===e.type?r?`spec-driven 阶段 ${e.phaseId} 已验证。`:`Spec-driven phase ${e.phaseId} is verified.`:"runtime.artifact.created"===e.type?r?"我已经保存一份运行产物。":"I've saved a runtime artifact.":"runtime.execution.contract.failed"===e.type?r?"运行证据没有满足执行契约,我会进入恢复或失败路径。":"The run evidence did not satisfy the execution contract, so I'll recover or fail explicitly.":"runtime.skill.candidate.created"===e.type?r?`我发现一个可沉淀的 skill 候选:${e.name}。`:`I found a reusable skill candidate: ${e.name}.`:e.type.startsWith("runtime.memory.")?function memoryMessage(e,t){return"runtime.memory.lifecycle"===e.type?t?`我进入记忆阶段:${e.hook}。`:`I'm in the memory lifecycle phase: ${e.hook}.`:"runtime.memory.recall.completed"===e.type?t?`我召回了 ${e.recordIds.length} 条相关记忆。`:`I recalled ${e.recordIds.length} relevant memory records.`:"runtime.memory.candidate.submitted"===e.type?t?"我提交了一条候选记忆。":"I submitted a memory candidate.":"runtime.memory.approval.requested"===e.type?t?"我提交了记忆审批请求。":"I requested memory approval.":"runtime.memory.plugin.started"===e.type?t?`我正在运行记忆插件 ${e.provider}。`:`I'm running memory plugin ${e.provider}.`:"runtime.memory.plugin.completed"===e.type?t?`记忆插件 ${e.provider} 已完成。`:`Memory plugin ${e.provider} completed.`:"runtime.memory.plugin.failed"===e.type?t?`记忆插件 ${e.provider} 失败了;主任务会继续,不把它当成执行结果。`:`Memory plugin ${e.provider} failed; the main task will continue without treating it as the result.`:"runtime.memory.maintenance.started"===e.type?t?`我正在维护 ${e.target} 记忆。`:`I'm maintaining ${e.target} memory.`:"runtime.memory.maintenance.completed"===e.type?t?`${e.target} 记忆维护完成。`:`${e.target} memory maintenance completed.`:"runtime.memory.maintenance.failed"===e.type?t?`${e.target} 记忆维护失败。`:`${e.target} memory maintenance failed.`:void 0}(e,r):"runtime.adapter.event"===e.type?function adapterMessage(e,t){if(isRecord(e))return"agent.handoff"===e.phase?t?"我把请求交给上游 agent backend,让它负责规划和执行。":"I'm handing the request to the upstream agent backend for planning and execution.":"agent.tool.start"===e.phase&&"string"==typeof e.toolId?function toolStartMessage(e,t,r){if("task"===e){const e=function readTaskTarget(e){const t=isRecord(e)?e:{};return readString(t.subagent_type)??readString(t.subagentType)}(t),n=function readDescription(e){const t=isRecord(e)?e:{};return summarizeText(readString(t.description)??readString(t.task))}(t);if(e&&n)return r?`我正在请求 task 工具委派给 ${e}:${n}`:`I'm asking the task tool to delegate to ${e}: ${n}`;if(e)return r?`我正在请求 task 工具委派给 ${e}。`:`I'm asking the task tool to delegate to ${e}.`}return r?`我正在运行 ${e} 收集证据。`:`I'm running ${e} to gather evidence.`}(e.toolId,e.args,t):"agent.tool.result"===e.phase&&"string"==typeof e.toolId?function toolResultMessage(e,t,r,n,o){if(r)return o?`${e} 返回错误:${summarizeText(String(r))}`:`${e} returned an error: ${summarizeText(String(r))}`;const i="string"==typeof n?n:function readToolControlStatus(e){const t=function parseToolOutputRecord(e){if(isRecord(e))return e;if("string"==typeof e)try{const t=JSON.parse(e);return isRecord(t)?t:void 0}catch{return}}(e);return"string"==typeof t?.status?t.status:"string"==typeof t?.error?t.error:"string"==typeof e&&e.startsWith("Task delegation target is not in the workspace inventory")?"task_inventory_blocked":void 0}(t);if(i)return function toolControlMessage(e,t,r){return"duplicate_tool_call"===t?r?`${e} 重复调用已复用已有证据。`:`${e} repeated an equivalent call, so the existing evidence was reused.`:"repeated_tool_call_limit"===t?r?`${e} 出现重复调用循环,我会基于已有证据继续收敛。`:`${e} entered a repeated-call loop, so I'll continue from the evidence already collected.`:"tool_argument_error"===t||"tool_argument_validation_failed"===t?r?`${e} 参数被工具 schema 拒绝,我会让 agent 修正参数或改用合适工具。`:`${e} arguments were rejected by the tool schema; I'll have the agent repair them or choose a suitable tool.`:"task_inventory_blocked"===t?r?"task 委派目标不在当前 workspace inventory 中,已被运行时策略阻止。":"The task delegation target is not in the current workspace inventory and was blocked by runtime policy.":r?`${e} 返回运行时控制状态:${t}。`:`${e} returned runtime control status: ${t}.`}(e,i,o);if("task"===e)return o?"委派任务已返回结果,我会基于这些证据继续推进。":"The delegated task returned; I'll keep going with that evidence.";const a=function summarizeToolOutput(e){if("string"==typeof e)return summarizeText(e);if(isRecord(e)){if("string"==typeof e.status)return summarizeText(e.status);if("string"==typeof e.summary)return summarizeText(e.summary)}}(t);return o?`${e} 已返回${a?`:${a}`:",我会继续判断下一步。"}`:`${e} returned${a?`: ${a}`:"; I'll decide the next step from here."}`}(e.toolId,e.output,e.error,e.controlStatus,t):"agent.langgraph.invoke"===e.phase?t?"我正在调用 workflow backend。":"I'm invoking the workflow backend.":"agent.node.completed"===e.phase&&"string"==typeof e.nodeId?t?`节点 ${e.nodeId} 已完成。`:`Node ${e.nodeId} is complete.`:void 0}(e.event,r):void 0}(r,e.get(r.requestId));if(i&&i!==t.get(r.requestId))return t.set(r.requestId,i),"runtime.request.failed"!==r.type&&"runtime.request.cancelled"!==r.type||(e.delete(r.requestId),t.delete(r.requestId)),function pruneRequestState(e,t){for(;e.size>200;){const r=e.keys().next().value;if(!r)break;e.delete(r),t.delete(r)}}(e,t),{message:i,style:n.style,model:n.model}}}}():void 0}export function createProgressNarrationEvent(e){if(!e.narrator||"runtime.progress.narration"===e.source.type)return;const t=readProgressPolicy(e.policy),r=!1===e.options?void 0:e.options,n=e.narrator.narrate(e.source,{style:r?.style??t.style,model:r?.model??t.model});return function isPromiseLike(e){return isRecord(e)&&"function"==typeof e.then}(n)?n.then(t=>toNarrationEvent(e.source,e.narrator,t)):toNarrationEvent(e.source,e.narrator,n)}function toNarrationEvent(e,t,r){if(r?.message.trim())return{type:"runtime.progress.narration",requestId:e.requestId,sessionId:e.sessionId,agentId:e.agentId,message:r.message,provider:t.name,sourceEventTypes:r.sourceEventTypes??[e.type],sourceEventIds:r.sourceEventIds,model:r.model,style:r.style}}function summarizeText(e){const t=e?.replace(/\s+/gu," ").trim();return t?t.length>120?`${t.slice(0,117)}...`:t:""}function readString(e){return"string"==typeof e&&e.trim()?e:void 0}function readProgressPolicy(e){const t=isRecord(e?.progress)?e.progress:{},r=isRecord(t.narration)?t.narration:{};return{enabled:"boolean"==typeof r.enabled?r.enabled:void 0,style:"string"==typeof r.style?r.style:void 0,model:"string"==typeof r.model?r.model:void 0}}function isRecord(e){return"object"==typeof e&&null!==e&&!Array.isArray(e)}
|