@corbat-tech/coco 2.36.0 → 2.37.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/dist/cli/index.js +648 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +226 -1043
- package/dist/index.js +799 -394
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -10,7 +10,7 @@ import { z } from 'zod';
|
|
|
10
10
|
import * as os4 from 'os';
|
|
11
11
|
import os4__default, { homedir } from 'os';
|
|
12
12
|
import * as fs35 from 'fs/promises';
|
|
13
|
-
import fs35__default, { mkdir, writeFile, readFile, access, readdir, rm
|
|
13
|
+
import fs35__default, { mkdir, writeFile, readFile, access, constants, readdir, rm } from 'fs/promises';
|
|
14
14
|
import JSON5 from 'json5';
|
|
15
15
|
import * as crypto from 'crypto';
|
|
16
16
|
import { randomUUID, randomBytes, createHash } from 'crypto';
|
|
@@ -40857,9 +40857,6 @@ function getSessionStore() {
|
|
|
40857
40857
|
}
|
|
40858
40858
|
return defaultStore;
|
|
40859
40859
|
}
|
|
40860
|
-
function createSessionStore(config) {
|
|
40861
|
-
return new SessionStore(config);
|
|
40862
|
-
}
|
|
40863
40860
|
|
|
40864
40861
|
// src/cli/repl/commands/resume.ts
|
|
40865
40862
|
function formatRelativeTime2(date) {
|
|
@@ -52606,7 +52603,7 @@ var repoMapCommand = {
|
|
|
52606
52603
|
}
|
|
52607
52604
|
};
|
|
52608
52605
|
|
|
52609
|
-
// src/
|
|
52606
|
+
// src/runtime/agent-modes.ts
|
|
52610
52607
|
var AGENT_MODES = {
|
|
52611
52608
|
ask: {
|
|
52612
52609
|
id: "ask",
|
|
@@ -57374,6 +57371,39 @@ init_providers();
|
|
|
57374
57371
|
|
|
57375
57372
|
// src/runtime/agent-runtime.ts
|
|
57376
57373
|
init_env();
|
|
57374
|
+
|
|
57375
|
+
// src/runtime/default-turn-runner.ts
|
|
57376
|
+
var DefaultRuntimeTurnRunner = class {
|
|
57377
|
+
async run(input, context) {
|
|
57378
|
+
const messages = [
|
|
57379
|
+
...context.session.messages,
|
|
57380
|
+
{
|
|
57381
|
+
role: "user",
|
|
57382
|
+
content: input.content
|
|
57383
|
+
}
|
|
57384
|
+
];
|
|
57385
|
+
const response = await context.provider.chat(messages, {
|
|
57386
|
+
model: input.options?.model,
|
|
57387
|
+
maxTokens: input.options?.maxTokens,
|
|
57388
|
+
temperature: input.options?.temperature,
|
|
57389
|
+
stopSequences: input.options?.stopSequences,
|
|
57390
|
+
system: context.session.instructions ?? input.options?.system,
|
|
57391
|
+
timeout: input.options?.timeout,
|
|
57392
|
+
signal: input.options?.signal,
|
|
57393
|
+
thinking: input.options?.thinking
|
|
57394
|
+
});
|
|
57395
|
+
return {
|
|
57396
|
+
sessionId: context.session.id,
|
|
57397
|
+
content: response.content,
|
|
57398
|
+
usage: response.usage,
|
|
57399
|
+
model: response.model,
|
|
57400
|
+
mode: context.session.mode
|
|
57401
|
+
};
|
|
57402
|
+
}
|
|
57403
|
+
};
|
|
57404
|
+
function createDefaultRuntimeTurnRunner() {
|
|
57405
|
+
return new DefaultRuntimeTurnRunner();
|
|
57406
|
+
}
|
|
57377
57407
|
var InMemoryEventLog = class {
|
|
57378
57408
|
events = [];
|
|
57379
57409
|
record(type, data = {}) {
|
|
@@ -57525,6 +57555,22 @@ var DefaultPermissionPolicy = class {
|
|
|
57525
57555
|
}
|
|
57526
57556
|
return { allowed: true, risk };
|
|
57527
57557
|
}
|
|
57558
|
+
canExecuteToolInput(mode, tool, input) {
|
|
57559
|
+
if (tool.name !== "run_linter") {
|
|
57560
|
+
return this.canExecuteTool(mode, tool);
|
|
57561
|
+
}
|
|
57562
|
+
const definition = getAgentMode(mode);
|
|
57563
|
+
const fixEnabled = input["fix"] === true;
|
|
57564
|
+
const decision = fixEnabled ? { allowed: true, risk: "write" } : { allowed: true, risk: "read-only" };
|
|
57565
|
+
if (definition.readOnly && fixEnabled) {
|
|
57566
|
+
return {
|
|
57567
|
+
allowed: false,
|
|
57568
|
+
reason: `${definition.label} mode is read-only; run_linter with fix=true can modify files.`,
|
|
57569
|
+
risk: "write"
|
|
57570
|
+
};
|
|
57571
|
+
}
|
|
57572
|
+
return decision;
|
|
57573
|
+
}
|
|
57528
57574
|
};
|
|
57529
57575
|
function createPermissionPolicy() {
|
|
57530
57576
|
return new DefaultPermissionPolicy();
|
|
@@ -57566,6 +57612,321 @@ var ProviderRegistry = class {
|
|
|
57566
57612
|
function createProviderRegistry() {
|
|
57567
57613
|
return new ProviderRegistry();
|
|
57568
57614
|
}
|
|
57615
|
+
function createSessionId() {
|
|
57616
|
+
return `rt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
|
|
57617
|
+
}
|
|
57618
|
+
function cloneSession(session) {
|
|
57619
|
+
return structuredClone(session);
|
|
57620
|
+
}
|
|
57621
|
+
var InMemoryRuntimeSessionStore = class {
|
|
57622
|
+
sessions = /* @__PURE__ */ new Map();
|
|
57623
|
+
create(options = {}) {
|
|
57624
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
57625
|
+
const session = {
|
|
57626
|
+
id: options.id ?? createSessionId(),
|
|
57627
|
+
createdAt: now,
|
|
57628
|
+
updatedAt: now,
|
|
57629
|
+
mode: options.mode ?? "ask",
|
|
57630
|
+
messages: options.messages ? options.messages.map((message) => ({ ...message })) : [],
|
|
57631
|
+
instructions: options.instructions,
|
|
57632
|
+
metadata: { ...options.metadata }
|
|
57633
|
+
};
|
|
57634
|
+
this.sessions.set(session.id, cloneSession(session));
|
|
57635
|
+
return cloneSession(session);
|
|
57636
|
+
}
|
|
57637
|
+
get(id) {
|
|
57638
|
+
const session = this.sessions.get(id);
|
|
57639
|
+
return session ? cloneSession(session) : void 0;
|
|
57640
|
+
}
|
|
57641
|
+
update(session) {
|
|
57642
|
+
const updated = {
|
|
57643
|
+
...session,
|
|
57644
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57645
|
+
messages: session.messages.map((message) => ({ ...message })),
|
|
57646
|
+
metadata: { ...session.metadata }
|
|
57647
|
+
};
|
|
57648
|
+
this.sessions.set(updated.id, cloneSession(updated));
|
|
57649
|
+
return cloneSession(updated);
|
|
57650
|
+
}
|
|
57651
|
+
list() {
|
|
57652
|
+
return [...this.sessions.values()].map(cloneSession);
|
|
57653
|
+
}
|
|
57654
|
+
delete(id) {
|
|
57655
|
+
return this.sessions.delete(id);
|
|
57656
|
+
}
|
|
57657
|
+
};
|
|
57658
|
+
function createRuntimeSessionStore() {
|
|
57659
|
+
return new InMemoryRuntimeSessionStore();
|
|
57660
|
+
}
|
|
57661
|
+
|
|
57662
|
+
// src/runtime/workflow-registry.ts
|
|
57663
|
+
function cloneWorkflow(workflow) {
|
|
57664
|
+
return {
|
|
57665
|
+
...workflow,
|
|
57666
|
+
checks: [...workflow.checks],
|
|
57667
|
+
steps: workflow.steps.map((step) => ({
|
|
57668
|
+
...step,
|
|
57669
|
+
requiredTools: [...step.requiredTools]
|
|
57670
|
+
}))
|
|
57671
|
+
};
|
|
57672
|
+
}
|
|
57673
|
+
var WorkflowCatalog = class {
|
|
57674
|
+
workflows = /* @__PURE__ */ new Map();
|
|
57675
|
+
constructor(workflows = DEFAULT_WORKFLOWS) {
|
|
57676
|
+
for (const workflow of workflows) {
|
|
57677
|
+
this.register(workflow);
|
|
57678
|
+
}
|
|
57679
|
+
}
|
|
57680
|
+
register(workflow) {
|
|
57681
|
+
this.workflows.set(workflow.id, cloneWorkflow(workflow));
|
|
57682
|
+
}
|
|
57683
|
+
get(id) {
|
|
57684
|
+
const workflow = this.workflows.get(id);
|
|
57685
|
+
return workflow ? cloneWorkflow(workflow) : void 0;
|
|
57686
|
+
}
|
|
57687
|
+
list() {
|
|
57688
|
+
return [...this.workflows.values()].map(cloneWorkflow).sort((a, b) => a.id.localeCompare(b.id));
|
|
57689
|
+
}
|
|
57690
|
+
createPlan(workflowId, input, eventLog) {
|
|
57691
|
+
const workflow = this.get(workflowId);
|
|
57692
|
+
if (!workflow) {
|
|
57693
|
+
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
57694
|
+
}
|
|
57695
|
+
const plan = {
|
|
57696
|
+
id: `${workflowId}-${Date.now().toString(36)}`,
|
|
57697
|
+
workflowId,
|
|
57698
|
+
input,
|
|
57699
|
+
status: "planned",
|
|
57700
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
57701
|
+
};
|
|
57702
|
+
eventLog?.record("workflow.planned", {
|
|
57703
|
+
workflowId,
|
|
57704
|
+
planId: plan.id,
|
|
57705
|
+
replayable: workflow.replayable,
|
|
57706
|
+
checks: workflow.checks
|
|
57707
|
+
});
|
|
57708
|
+
return plan;
|
|
57709
|
+
}
|
|
57710
|
+
};
|
|
57711
|
+
var DEFAULT_WORKFLOWS = [
|
|
57712
|
+
{
|
|
57713
|
+
id: "architect-editor-verifier",
|
|
57714
|
+
name: "Architect / Editor / Verifier",
|
|
57715
|
+
description: "Plan read-only, apply approved changes, then verify and summarize risks.",
|
|
57716
|
+
inputSchema: "task: string; approvedPlan?: string",
|
|
57717
|
+
outputKind: "patch",
|
|
57718
|
+
replayable: true,
|
|
57719
|
+
checks: ["pnpm check", "diff summary", "review risks"],
|
|
57720
|
+
steps: [
|
|
57721
|
+
{
|
|
57722
|
+
id: "architect",
|
|
57723
|
+
description: "Inspect context and produce a read-only implementation plan.",
|
|
57724
|
+
requiredTools: ["repo_context", "read_file", "git_diff"],
|
|
57725
|
+
risk: "read-only"
|
|
57726
|
+
},
|
|
57727
|
+
{
|
|
57728
|
+
id: "editor",
|
|
57729
|
+
description: "Apply the approved plan without reinterpreting the objective.",
|
|
57730
|
+
requiredTools: ["read_file", "edit_file", "write_file"],
|
|
57731
|
+
risk: "write"
|
|
57732
|
+
},
|
|
57733
|
+
{
|
|
57734
|
+
id: "verifier",
|
|
57735
|
+
description: "Run checks, review diff, and report residual risk.",
|
|
57736
|
+
requiredTools: ["bash_exec", "git_diff", "review_code"],
|
|
57737
|
+
risk: "destructive"
|
|
57738
|
+
}
|
|
57739
|
+
]
|
|
57740
|
+
},
|
|
57741
|
+
{
|
|
57742
|
+
id: "provider-diagnosis",
|
|
57743
|
+
name: "Provider Diagnosis",
|
|
57744
|
+
description: "Probe provider/model capabilities, endpoint strategy, credentials, and fallbacks.",
|
|
57745
|
+
inputSchema: "provider?: string; model?: string; live?: boolean",
|
|
57746
|
+
outputKind: "json",
|
|
57747
|
+
replayable: true,
|
|
57748
|
+
checks: ["provider capability matrix", "optional live probe"],
|
|
57749
|
+
steps: [
|
|
57750
|
+
{
|
|
57751
|
+
id: "capability",
|
|
57752
|
+
description: "Resolve catalog metadata and runtime endpoint strategy.",
|
|
57753
|
+
requiredTools: [],
|
|
57754
|
+
risk: "read-only"
|
|
57755
|
+
},
|
|
57756
|
+
{
|
|
57757
|
+
id: "fallbacks",
|
|
57758
|
+
description: "Suggest fallback provider/model choices when unsupported.",
|
|
57759
|
+
requiredTools: [],
|
|
57760
|
+
risk: "read-only"
|
|
57761
|
+
}
|
|
57762
|
+
]
|
|
57763
|
+
},
|
|
57764
|
+
{
|
|
57765
|
+
id: "review-pr",
|
|
57766
|
+
name: "Review PR",
|
|
57767
|
+
description: "Review a branch or PR read-only and emit severity-ranked findings.",
|
|
57768
|
+
inputSchema: "target: string",
|
|
57769
|
+
outputKind: "markdown",
|
|
57770
|
+
replayable: true,
|
|
57771
|
+
checks: ["git diff", "tests gap review", "security review"],
|
|
57772
|
+
steps: [
|
|
57773
|
+
{
|
|
57774
|
+
id: "collect-diff",
|
|
57775
|
+
description: "Collect PR diff and related context.",
|
|
57776
|
+
requiredTools: ["git_diff", "repo_context"],
|
|
57777
|
+
risk: "read-only"
|
|
57778
|
+
},
|
|
57779
|
+
{
|
|
57780
|
+
id: "findings",
|
|
57781
|
+
description: "Produce prioritized findings with file and line references.",
|
|
57782
|
+
requiredTools: ["read_file", "review_code"],
|
|
57783
|
+
risk: "read-only"
|
|
57784
|
+
}
|
|
57785
|
+
]
|
|
57786
|
+
},
|
|
57787
|
+
{
|
|
57788
|
+
id: "best-of-n",
|
|
57789
|
+
name: "Best Of N",
|
|
57790
|
+
description: "Run multiple isolated attempts, score them, and select a winning patch.",
|
|
57791
|
+
inputSchema: "task: string; attempts: number",
|
|
57792
|
+
outputKind: "patch",
|
|
57793
|
+
replayable: true,
|
|
57794
|
+
checks: ["worktree isolation", "checks pass", "diff risk score"],
|
|
57795
|
+
steps: [
|
|
57796
|
+
{
|
|
57797
|
+
id: "fanout",
|
|
57798
|
+
description: "Create isolated attempts in temporary worktrees.",
|
|
57799
|
+
requiredTools: ["git_status", "bash_exec"],
|
|
57800
|
+
risk: "destructive"
|
|
57801
|
+
},
|
|
57802
|
+
{
|
|
57803
|
+
id: "score",
|
|
57804
|
+
description: "Run checks and compare quality, cost, latency, and diff risk.",
|
|
57805
|
+
requiredTools: ["bash_exec", "git_diff"],
|
|
57806
|
+
risk: "destructive"
|
|
57807
|
+
},
|
|
57808
|
+
{
|
|
57809
|
+
id: "apply-winner",
|
|
57810
|
+
description: "Apply the winning patch only if conservative checks pass.",
|
|
57811
|
+
requiredTools: ["git_diff", "edit_file"],
|
|
57812
|
+
risk: "write"
|
|
57813
|
+
}
|
|
57814
|
+
]
|
|
57815
|
+
},
|
|
57816
|
+
{
|
|
57817
|
+
id: "release",
|
|
57818
|
+
name: "Release",
|
|
57819
|
+
description: "Follow the project release skill: changelog, version bump, PR, merge, tag, publish verify.",
|
|
57820
|
+
inputSchema: "bump?: patch|minor|major",
|
|
57821
|
+
outputKind: "release",
|
|
57822
|
+
replayable: true,
|
|
57823
|
+
checks: ["pnpm check", "PR checks", "release.yml", "npm view"],
|
|
57824
|
+
steps: [
|
|
57825
|
+
{
|
|
57826
|
+
id: "preflight",
|
|
57827
|
+
description: "Verify branch, clean tree, GitHub auth, and remote state.",
|
|
57828
|
+
requiredTools: ["git_status", "bash_exec"],
|
|
57829
|
+
risk: "destructive"
|
|
57830
|
+
},
|
|
57831
|
+
{
|
|
57832
|
+
id: "version",
|
|
57833
|
+
description: "Update changelog and package versions using the release skill.",
|
|
57834
|
+
requiredTools: ["read_file", "edit_file", "bash_exec"],
|
|
57835
|
+
risk: "destructive"
|
|
57836
|
+
},
|
|
57837
|
+
{
|
|
57838
|
+
id: "publish",
|
|
57839
|
+
description: "Merge release PR, tag main, and verify release workflow outputs.",
|
|
57840
|
+
requiredTools: ["bash_exec"],
|
|
57841
|
+
risk: "destructive"
|
|
57842
|
+
}
|
|
57843
|
+
]
|
|
57844
|
+
}
|
|
57845
|
+
];
|
|
57846
|
+
function createWorkflowCatalog(workflows) {
|
|
57847
|
+
return new WorkflowCatalog(workflows);
|
|
57848
|
+
}
|
|
57849
|
+
|
|
57850
|
+
// src/runtime/workflow-engine.ts
|
|
57851
|
+
var WorkflowEngine = class {
|
|
57852
|
+
constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
|
|
57853
|
+
this.catalog = catalog;
|
|
57854
|
+
this.eventLog = eventLog;
|
|
57855
|
+
}
|
|
57856
|
+
catalog;
|
|
57857
|
+
eventLog;
|
|
57858
|
+
handlers = /* @__PURE__ */ new Map();
|
|
57859
|
+
registerHandler(workflowId, handler) {
|
|
57860
|
+
if (!this.catalog.get(workflowId)) {
|
|
57861
|
+
throw new Error(`Unknown workflow: ${workflowId}`);
|
|
57862
|
+
}
|
|
57863
|
+
this.handlers.set(workflowId, handler);
|
|
57864
|
+
}
|
|
57865
|
+
createPlan(workflowId, input) {
|
|
57866
|
+
return this.catalog.createPlan(workflowId, input, this.eventLog);
|
|
57867
|
+
}
|
|
57868
|
+
async run(request) {
|
|
57869
|
+
const workflow = this.catalog.get(request.workflowId);
|
|
57870
|
+
if (!workflow) {
|
|
57871
|
+
throw new Error(`Unknown workflow: ${request.workflowId}`);
|
|
57872
|
+
}
|
|
57873
|
+
const handler = this.handlers.get(request.workflowId);
|
|
57874
|
+
if (!handler) {
|
|
57875
|
+
throw new Error(`No handler registered for workflow: ${request.workflowId}`);
|
|
57876
|
+
}
|
|
57877
|
+
const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
|
|
57878
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57879
|
+
const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
|
|
57880
|
+
this.eventLog.record("workflow.started", {
|
|
57881
|
+
workflowId: request.workflowId,
|
|
57882
|
+
planId: plan.id,
|
|
57883
|
+
runId
|
|
57884
|
+
});
|
|
57885
|
+
try {
|
|
57886
|
+
const output = await handler(request.input, {
|
|
57887
|
+
workflow,
|
|
57888
|
+
plan,
|
|
57889
|
+
eventLog: this.eventLog
|
|
57890
|
+
});
|
|
57891
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57892
|
+
const result = {
|
|
57893
|
+
id: runId,
|
|
57894
|
+
workflowId: request.workflowId,
|
|
57895
|
+
status: "completed",
|
|
57896
|
+
output,
|
|
57897
|
+
startedAt,
|
|
57898
|
+
completedAt
|
|
57899
|
+
};
|
|
57900
|
+
this.eventLog.record("workflow.completed", {
|
|
57901
|
+
workflowId: request.workflowId,
|
|
57902
|
+
planId: plan.id,
|
|
57903
|
+
runId
|
|
57904
|
+
});
|
|
57905
|
+
return result;
|
|
57906
|
+
} catch (error) {
|
|
57907
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
57908
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
57909
|
+
this.eventLog.record("workflow.failed", {
|
|
57910
|
+
workflowId: request.workflowId,
|
|
57911
|
+
planId: plan.id,
|
|
57912
|
+
runId,
|
|
57913
|
+
error: message
|
|
57914
|
+
});
|
|
57915
|
+
return {
|
|
57916
|
+
id: runId,
|
|
57917
|
+
workflowId: request.workflowId,
|
|
57918
|
+
status: "failed",
|
|
57919
|
+
output: null,
|
|
57920
|
+
startedAt,
|
|
57921
|
+
completedAt,
|
|
57922
|
+
error: message
|
|
57923
|
+
};
|
|
57924
|
+
}
|
|
57925
|
+
}
|
|
57926
|
+
};
|
|
57927
|
+
function createWorkflowEngine(catalog, eventLog) {
|
|
57928
|
+
return new WorkflowEngine(catalog, eventLog);
|
|
57929
|
+
}
|
|
57569
57930
|
|
|
57570
57931
|
// src/runtime/agent-runtime.ts
|
|
57571
57932
|
var AgentRuntime = class {
|
|
@@ -57573,9 +57934,12 @@ var AgentRuntime = class {
|
|
|
57573
57934
|
this.options = options;
|
|
57574
57935
|
this.providerRegistry = createProviderRegistry();
|
|
57575
57936
|
this.toolRegistry = options.toolRegistry ?? createFullToolRegistry();
|
|
57576
|
-
this.sessionStore = options.sessionStore
|
|
57577
|
-
this.
|
|
57937
|
+
this.sessionStore = options.sessionStore;
|
|
57938
|
+
this.runtimeSessionStore = options.runtimeSessionStore ?? createRuntimeSessionStore();
|
|
57578
57939
|
this.eventLog = options.eventLog ?? (options.eventLogPath ? createFileEventLog(options.eventLogPath) : createEventLog());
|
|
57940
|
+
this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog);
|
|
57941
|
+
this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
|
|
57942
|
+
this.turnRunner = options.turnRunner ?? createDefaultRuntimeTurnRunner();
|
|
57579
57943
|
this.providerType = options.providerType;
|
|
57580
57944
|
this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
|
|
57581
57945
|
}
|
|
@@ -57583,16 +57947,21 @@ var AgentRuntime = class {
|
|
|
57583
57947
|
providerRegistry;
|
|
57584
57948
|
toolRegistry;
|
|
57585
57949
|
sessionStore;
|
|
57950
|
+
runtimeSessionStore;
|
|
57951
|
+
workflowEngine;
|
|
57586
57952
|
permissionPolicy;
|
|
57587
57953
|
eventLog;
|
|
57954
|
+
turnRunner;
|
|
57588
57955
|
providerType;
|
|
57589
57956
|
model;
|
|
57957
|
+
provider;
|
|
57590
57958
|
async initialize() {
|
|
57591
57959
|
const providerInjected = Boolean(this.options.provider);
|
|
57592
57960
|
const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
|
|
57593
57961
|
...this.options.providerConfig,
|
|
57594
57962
|
model: this.getModel()
|
|
57595
57963
|
});
|
|
57964
|
+
this.provider = provider;
|
|
57596
57965
|
this.publishToGlobalBridge(provider);
|
|
57597
57966
|
this.eventLog.record(providerInjected ? "provider.attached" : "provider.created", {
|
|
57598
57967
|
provider: this.providerType,
|
|
@@ -57607,6 +57976,7 @@ var AgentRuntime = class {
|
|
|
57607
57976
|
updateProvider(providerType, model2, provider) {
|
|
57608
57977
|
this.providerType = providerType;
|
|
57609
57978
|
this.model = model2 ?? getDefaultModel(providerType);
|
|
57979
|
+
this.provider = provider;
|
|
57610
57980
|
this.publishToGlobalBridge(provider);
|
|
57611
57981
|
this.eventLog.record("provider.updated", {
|
|
57612
57982
|
provider: this.providerType,
|
|
@@ -57634,7 +58004,276 @@ var AgentRuntime = class {
|
|
|
57634
58004
|
modes: listAgentModes()
|
|
57635
58005
|
};
|
|
57636
58006
|
}
|
|
57637
|
-
|
|
58007
|
+
createSession(options = {}) {
|
|
58008
|
+
const session = this.runtimeSessionStore.create(options);
|
|
58009
|
+
this.eventLog.record("session.created", {
|
|
58010
|
+
sessionId: session.id,
|
|
58011
|
+
mode: session.mode,
|
|
58012
|
+
metadataKeys: Object.keys(session.metadata).sort()
|
|
58013
|
+
});
|
|
58014
|
+
return session;
|
|
58015
|
+
}
|
|
58016
|
+
getSession(sessionId) {
|
|
58017
|
+
return this.runtimeSessionStore.get(sessionId);
|
|
58018
|
+
}
|
|
58019
|
+
listSessions() {
|
|
58020
|
+
return this.runtimeSessionStore.list();
|
|
58021
|
+
}
|
|
58022
|
+
async runTurn(input) {
|
|
58023
|
+
const provider = this.provider;
|
|
58024
|
+
if (!provider) {
|
|
58025
|
+
throw new Error("Runtime provider is not initialized.");
|
|
58026
|
+
}
|
|
58027
|
+
const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
|
|
58028
|
+
if (!session) {
|
|
58029
|
+
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
58030
|
+
}
|
|
58031
|
+
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
58032
|
+
this.eventLog.record("turn.started", {
|
|
58033
|
+
sessionId: effectiveSession.id,
|
|
58034
|
+
provider: this.providerType,
|
|
58035
|
+
model: this.getModel(),
|
|
58036
|
+
mode: effectiveSession.mode,
|
|
58037
|
+
runtimeApi: true
|
|
58038
|
+
});
|
|
58039
|
+
try {
|
|
58040
|
+
const result = await this.turnRunner.run(input, {
|
|
58041
|
+
runtime: this,
|
|
58042
|
+
session: effectiveSession,
|
|
58043
|
+
provider,
|
|
58044
|
+
toolRegistry: this.toolRegistry,
|
|
58045
|
+
permissionPolicy: this.permissionPolicy,
|
|
58046
|
+
eventLog: this.eventLog
|
|
58047
|
+
});
|
|
58048
|
+
const updatedSession = this.runtimeSessionStore.update({
|
|
58049
|
+
...effectiveSession,
|
|
58050
|
+
messages: [
|
|
58051
|
+
...effectiveSession.messages,
|
|
58052
|
+
{ role: "user", content: input.content },
|
|
58053
|
+
{ role: "assistant", content: result.content }
|
|
58054
|
+
]
|
|
58055
|
+
});
|
|
58056
|
+
this.eventLog.record("session.updated", {
|
|
58057
|
+
sessionId: updatedSession.id,
|
|
58058
|
+
messages: updatedSession.messages.length
|
|
58059
|
+
});
|
|
58060
|
+
this.eventLog.record("turn.completed", {
|
|
58061
|
+
sessionId: updatedSession.id,
|
|
58062
|
+
inputTokens: result.usage.inputTokens,
|
|
58063
|
+
outputTokens: result.usage.outputTokens,
|
|
58064
|
+
model: result.model,
|
|
58065
|
+
runtimeApi: true
|
|
58066
|
+
});
|
|
58067
|
+
return { ...result, sessionId: updatedSession.id, mode: updatedSession.mode };
|
|
58068
|
+
} catch (error) {
|
|
58069
|
+
this.eventLog.record("turn.failed", {
|
|
58070
|
+
sessionId: effectiveSession.id,
|
|
58071
|
+
error: error instanceof Error ? error.message : String(error),
|
|
58072
|
+
runtimeApi: true
|
|
58073
|
+
});
|
|
58074
|
+
throw error;
|
|
58075
|
+
}
|
|
58076
|
+
}
|
|
58077
|
+
async *streamTurn(input) {
|
|
58078
|
+
const provider = this.provider;
|
|
58079
|
+
if (!provider) {
|
|
58080
|
+
throw new Error("Runtime provider is not initialized.");
|
|
58081
|
+
}
|
|
58082
|
+
const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
|
|
58083
|
+
if (!session) {
|
|
58084
|
+
throw new Error(`Runtime session not found: ${input.sessionId}`);
|
|
58085
|
+
}
|
|
58086
|
+
const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
|
|
58087
|
+
const messages = [
|
|
58088
|
+
...effectiveSession.messages,
|
|
58089
|
+
{
|
|
58090
|
+
role: "user",
|
|
58091
|
+
content: input.content
|
|
58092
|
+
}
|
|
58093
|
+
];
|
|
58094
|
+
this.eventLog.record("turn.started", {
|
|
58095
|
+
sessionId: effectiveSession.id,
|
|
58096
|
+
provider: this.providerType,
|
|
58097
|
+
model: this.getModel(),
|
|
58098
|
+
mode: effectiveSession.mode,
|
|
58099
|
+
streaming: true,
|
|
58100
|
+
runtimeApi: true
|
|
58101
|
+
});
|
|
58102
|
+
let content = "";
|
|
58103
|
+
let completed = false;
|
|
58104
|
+
let failed = false;
|
|
58105
|
+
try {
|
|
58106
|
+
for await (const chunk of provider.stream(messages, {
|
|
58107
|
+
model: input.options?.model,
|
|
58108
|
+
maxTokens: input.options?.maxTokens,
|
|
58109
|
+
temperature: input.options?.temperature,
|
|
58110
|
+
stopSequences: input.options?.stopSequences,
|
|
58111
|
+
system: effectiveSession.instructions ?? input.options?.system,
|
|
58112
|
+
timeout: input.options?.timeout,
|
|
58113
|
+
signal: input.options?.signal,
|
|
58114
|
+
thinking: input.options?.thinking
|
|
58115
|
+
})) {
|
|
58116
|
+
if (chunk.type === "text" && chunk.text) {
|
|
58117
|
+
content += chunk.text;
|
|
58118
|
+
yield {
|
|
58119
|
+
type: "text",
|
|
58120
|
+
sessionId: effectiveSession.id,
|
|
58121
|
+
text: chunk.text
|
|
58122
|
+
};
|
|
58123
|
+
}
|
|
58124
|
+
}
|
|
58125
|
+
const updatedSession = this.runtimeSessionStore.update({
|
|
58126
|
+
...effectiveSession,
|
|
58127
|
+
messages: [
|
|
58128
|
+
...effectiveSession.messages,
|
|
58129
|
+
{ role: "user", content: input.content },
|
|
58130
|
+
{ role: "assistant", content }
|
|
58131
|
+
]
|
|
58132
|
+
});
|
|
58133
|
+
const result = {
|
|
58134
|
+
sessionId: updatedSession.id,
|
|
58135
|
+
content,
|
|
58136
|
+
usage: {
|
|
58137
|
+
inputTokens: provider.countTokens(input.content),
|
|
58138
|
+
outputTokens: provider.countTokens(content),
|
|
58139
|
+
estimated: true
|
|
58140
|
+
},
|
|
58141
|
+
model: input.options?.model ?? this.getModel(),
|
|
58142
|
+
mode: updatedSession.mode
|
|
58143
|
+
};
|
|
58144
|
+
this.eventLog.record("session.updated", {
|
|
58145
|
+
sessionId: updatedSession.id,
|
|
58146
|
+
messages: updatedSession.messages.length
|
|
58147
|
+
});
|
|
58148
|
+
this.eventLog.record("turn.completed", {
|
|
58149
|
+
sessionId: updatedSession.id,
|
|
58150
|
+
inputTokens: result.usage.inputTokens,
|
|
58151
|
+
outputTokens: result.usage.outputTokens,
|
|
58152
|
+
model: result.model,
|
|
58153
|
+
streaming: true,
|
|
58154
|
+
runtimeApi: true
|
|
58155
|
+
});
|
|
58156
|
+
completed = true;
|
|
58157
|
+
yield { type: "done", sessionId: updatedSession.id, result };
|
|
58158
|
+
} catch (error) {
|
|
58159
|
+
failed = true;
|
|
58160
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
58161
|
+
this.eventLog.record("turn.failed", {
|
|
58162
|
+
sessionId: effectiveSession.id,
|
|
58163
|
+
error: message,
|
|
58164
|
+
streaming: true,
|
|
58165
|
+
runtimeApi: true
|
|
58166
|
+
});
|
|
58167
|
+
yield {
|
|
58168
|
+
type: "error",
|
|
58169
|
+
sessionId: effectiveSession.id,
|
|
58170
|
+
error: message
|
|
58171
|
+
};
|
|
58172
|
+
} finally {
|
|
58173
|
+
if (!completed && !failed) {
|
|
58174
|
+
this.eventLog.record("turn.cancelled", {
|
|
58175
|
+
sessionId: effectiveSession.id,
|
|
58176
|
+
outputTokens: provider.countTokens(content),
|
|
58177
|
+
streaming: true,
|
|
58178
|
+
runtimeApi: true
|
|
58179
|
+
});
|
|
58180
|
+
}
|
|
58181
|
+
}
|
|
58182
|
+
}
|
|
58183
|
+
async executeTool(input) {
|
|
58184
|
+
const startedAt = performance.now();
|
|
58185
|
+
const session = input.sessionId ? this.getSession(input.sessionId) : void 0;
|
|
58186
|
+
if (input.sessionId && !session) {
|
|
58187
|
+
const decision2 = {
|
|
58188
|
+
allowed: false,
|
|
58189
|
+
reason: `Runtime session not found: ${input.sessionId}`,
|
|
58190
|
+
risk: "read-only"
|
|
58191
|
+
};
|
|
58192
|
+
this.eventLog.record("tool.blocked", {
|
|
58193
|
+
sessionId: input.sessionId,
|
|
58194
|
+
mode: input.mode ?? "ask",
|
|
58195
|
+
tool: input.toolName,
|
|
58196
|
+
reason: decision2.reason,
|
|
58197
|
+
runtimeApi: true
|
|
58198
|
+
});
|
|
58199
|
+
return {
|
|
58200
|
+
toolName: input.toolName,
|
|
58201
|
+
success: false,
|
|
58202
|
+
error: decision2.reason,
|
|
58203
|
+
duration: performance.now() - startedAt,
|
|
58204
|
+
decision: decision2
|
|
58205
|
+
};
|
|
58206
|
+
}
|
|
58207
|
+
const mode = input.mode ?? session?.mode ?? "ask";
|
|
58208
|
+
const tool = this.toolRegistry.get(input.toolName);
|
|
58209
|
+
if (!tool) {
|
|
58210
|
+
const decision2 = {
|
|
58211
|
+
allowed: false,
|
|
58212
|
+
reason: "Tool not registered.",
|
|
58213
|
+
risk: "read-only"
|
|
58214
|
+
};
|
|
58215
|
+
this.eventLog.record("tool.blocked", {
|
|
58216
|
+
sessionId: input.sessionId,
|
|
58217
|
+
mode,
|
|
58218
|
+
tool: input.toolName,
|
|
58219
|
+
reason: decision2.reason,
|
|
58220
|
+
runtimeApi: true
|
|
58221
|
+
});
|
|
58222
|
+
return {
|
|
58223
|
+
toolName: input.toolName,
|
|
58224
|
+
success: false,
|
|
58225
|
+
error: decision2.reason,
|
|
58226
|
+
duration: performance.now() - startedAt,
|
|
58227
|
+
decision: decision2
|
|
58228
|
+
};
|
|
58229
|
+
}
|
|
58230
|
+
const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58231
|
+
if (!decision.allowed || decision.requiresConfirmation && input.confirmed !== true) {
|
|
58232
|
+
const reason = decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
|
|
58233
|
+
this.eventLog.record("tool.blocked", {
|
|
58234
|
+
sessionId: input.sessionId,
|
|
58235
|
+
mode,
|
|
58236
|
+
tool: input.toolName,
|
|
58237
|
+
reason,
|
|
58238
|
+
risk: decision.risk,
|
|
58239
|
+
requiresConfirmation: decision.requiresConfirmation,
|
|
58240
|
+
runtimeApi: true
|
|
58241
|
+
});
|
|
58242
|
+
return {
|
|
58243
|
+
toolName: input.toolName,
|
|
58244
|
+
success: false,
|
|
58245
|
+
error: reason,
|
|
58246
|
+
duration: performance.now() - startedAt,
|
|
58247
|
+
decision
|
|
58248
|
+
};
|
|
58249
|
+
}
|
|
58250
|
+
this.eventLog.record("tool.started", {
|
|
58251
|
+
sessionId: input.sessionId,
|
|
58252
|
+
mode,
|
|
58253
|
+
tool: input.toolName,
|
|
58254
|
+
risk: decision.risk,
|
|
58255
|
+
runtimeApi: true,
|
|
58256
|
+
metadataKeys: Object.keys(input.metadata ?? {}).sort()
|
|
58257
|
+
});
|
|
58258
|
+
const result = await this.toolRegistry.execute(input.toolName, input.input);
|
|
58259
|
+
this.eventLog.record("tool.completed", {
|
|
58260
|
+
sessionId: input.sessionId,
|
|
58261
|
+
mode,
|
|
58262
|
+
tool: input.toolName,
|
|
58263
|
+
success: result.success,
|
|
58264
|
+
duration: result.duration,
|
|
58265
|
+
runtimeApi: true
|
|
58266
|
+
});
|
|
58267
|
+
return {
|
|
58268
|
+
toolName: input.toolName,
|
|
58269
|
+
success: result.success,
|
|
58270
|
+
output: result.data,
|
|
58271
|
+
error: result.error,
|
|
58272
|
+
duration: result.duration,
|
|
58273
|
+
decision
|
|
58274
|
+
};
|
|
58275
|
+
}
|
|
58276
|
+
assertToolAllowed(mode, toolName, input) {
|
|
57638
58277
|
const tool = this.toolRegistry.get(toolName);
|
|
57639
58278
|
if (!tool) {
|
|
57640
58279
|
this.eventLog.record("tool.blocked", {
|
|
@@ -57644,7 +58283,7 @@ var AgentRuntime = class {
|
|
|
57644
58283
|
});
|
|
57645
58284
|
return false;
|
|
57646
58285
|
}
|
|
57647
|
-
const decision = this.permissionPolicy.canExecuteTool(mode, tool);
|
|
58286
|
+
const decision = input && this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input) : this.permissionPolicy.canExecuteTool(mode, tool);
|
|
57648
58287
|
this.eventLog.record(decision.allowed ? "tool.allowed" : "tool.blocked", {
|
|
57649
58288
|
mode,
|
|
57650
58289
|
tool: toolName,
|