@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/index.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import { Logger } from 'tslog';
2
2
  import * as fs4 from 'fs';
3
- import fs4__default, { readFileSync, mkdirSync, appendFileSync, writeFileSync, constants } from 'fs';
3
+ import fs4__default, { readFileSync, mkdirSync, appendFileSync, writeFileSync, renameSync, constants } from 'fs';
4
4
  import * as path17 from 'path';
5
5
  import path17__default, { dirname, join, basename, resolve } from 'path';
6
6
  import * as fs16 from 'fs/promises';
7
- import fs16__default, { access, readFile, readdir, writeFile, mkdir, rm } from 'fs/promises';
7
+ import fs16__default, { access, readFile, readdir, writeFile, mkdir } from 'fs/promises';
8
8
  import { randomUUID, randomBytes, createHash } from 'crypto';
9
9
  import * as http from 'http';
10
+ import { createServer } from 'http';
10
11
  import { fileURLToPath, URL as URL$1 } from 'url';
11
12
  import { exec, execFile, execSync, execFileSync, spawn } from 'child_process';
12
13
  import { setGlobalDispatcher, EnvHttpProxyAgent } from 'undici';
@@ -10607,16 +10608,16 @@ var QualityEvaluator = class {
10607
10608
  * Find source files in project, adapting to the detected language stack.
10608
10609
  */
10609
10610
  async findSourceFiles() {
10610
- const { access: access14 } = await import('fs/promises');
10611
- const { join: join20 } = await import('path');
10611
+ const { access: access13 } = await import('fs/promises');
10612
+ const { join: join19 } = await import('path');
10612
10613
  let isJava = false;
10613
10614
  try {
10614
- await access14(join20(this.projectPath, "pom.xml"));
10615
+ await access13(join19(this.projectPath, "pom.xml"));
10615
10616
  isJava = true;
10616
10617
  } catch {
10617
10618
  for (const f of ["build.gradle", "build.gradle.kts"]) {
10618
10619
  try {
10619
- await access14(join20(this.projectPath, f));
10620
+ await access13(join19(this.projectPath, f));
10620
10621
  isJava = true;
10621
10622
  break;
10622
10623
  } catch {
@@ -20352,300 +20353,6 @@ function getAgentManager() {
20352
20353
  return agentManagerInstance;
20353
20354
  }
20354
20355
 
20355
- // src/cli/repl/modes.ts
20356
- var AGENT_MODES = {
20357
- ask: {
20358
- id: "ask",
20359
- label: "Ask",
20360
- description: "Answer questions and explain code without modifying files.",
20361
- readOnly: true,
20362
- preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_definition"],
20363
- requiresVerification: false
20364
- },
20365
- plan: {
20366
- id: "plan",
20367
- label: "Plan",
20368
- description: "Explore and produce an implementation plan with read-only tools.",
20369
- readOnly: true,
20370
- preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_workspace_symbols"],
20371
- requiresVerification: false
20372
- },
20373
- build: {
20374
- id: "build",
20375
- label: "Build",
20376
- description: "Implement code changes and verify them.",
20377
- readOnly: false,
20378
- preferredTools: ["read_file", "edit_file", "write_file", "bash_exec", "run_tests"],
20379
- requiresVerification: true
20380
- },
20381
- debug: {
20382
- id: "debug",
20383
- label: "Debug",
20384
- description: "Reproduce failures, trace root cause, patch, and verify.",
20385
- readOnly: false,
20386
- preferredTools: ["bash_exec", "read_file", "grep", "lsp_references", "edit_file"],
20387
- requiresVerification: true
20388
- },
20389
- review: {
20390
- id: "review",
20391
- label: "Review",
20392
- description: "Inspect code quality, security, behavior changes, and test gaps.",
20393
- readOnly: true,
20394
- preferredTools: ["git_diff", "read_file", "grep", "review_code", "calculate_quality"],
20395
- requiresVerification: false
20396
- },
20397
- architect: {
20398
- id: "architect",
20399
- label: "Architect",
20400
- description: "Design architecture and split work for architect/editor execution.",
20401
- readOnly: true,
20402
- preferredTools: ["codebase_map", "lsp_workspace_symbols", "grep", "create_agent_plan"],
20403
- requiresVerification: false
20404
- }
20405
- };
20406
- function getAgentMode(mode) {
20407
- return AGENT_MODES[mode];
20408
- }
20409
- function listAgentModes() {
20410
- return Object.values(AGENT_MODES);
20411
- }
20412
-
20413
- // src/cli/repl/sessions/storage.ts
20414
- init_paths();
20415
- var DEFAULT_CONFIG2 = {
20416
- storageDir: CONFIG_PATHS.sessions,
20417
- autoSaveInterval: 3e4,
20418
- maxSessionsPerProject: 20,
20419
- compressOldSessions: false
20420
- };
20421
- var SessionStore = class {
20422
- config;
20423
- initialized = false;
20424
- constructor(config = {}) {
20425
- this.config = { ...DEFAULT_CONFIG2, ...config };
20426
- }
20427
- async ensureInitialized() {
20428
- if (this.initialized) return;
20429
- await mkdir(this.config.storageDir, { recursive: true });
20430
- this.initialized = true;
20431
- }
20432
- getSessionFiles(sessionId) {
20433
- const sessionDir = this.getSessionDir(sessionId);
20434
- return {
20435
- metadata: join(sessionDir, "metadata.json"),
20436
- conversation: join(sessionDir, "conversation.jsonl"),
20437
- context: join(sessionDir, "context.json")
20438
- };
20439
- }
20440
- getSessionDir(sessionId) {
20441
- return join(this.config.storageDir, sessionId);
20442
- }
20443
- async exists(sessionId) {
20444
- try {
20445
- const files = this.getSessionFiles(sessionId);
20446
- await access(files.metadata);
20447
- return true;
20448
- } catch {
20449
- return false;
20450
- }
20451
- }
20452
- async save(session) {
20453
- await this.ensureInitialized();
20454
- const files = this.getSessionFiles(session.id);
20455
- const sessionDir = this.getSessionDir(session.id);
20456
- await mkdir(sessionDir, { recursive: true });
20457
- const metadata = {
20458
- id: session.id,
20459
- projectPath: session.projectPath,
20460
- startedAt: session.startedAt,
20461
- lastSavedAt: /* @__PURE__ */ new Date(),
20462
- config: session.config,
20463
- messageCount: session.messages.length,
20464
- totalTokens: this.calculateTokens(session),
20465
- title: this.generateTitle(session),
20466
- status: "active"
20467
- };
20468
- await writeFile(files.metadata, JSON.stringify(metadata, null, 2), "utf-8");
20469
- const conversationLines = session.messages.map((msg) => {
20470
- const serialized = {
20471
- role: msg.role,
20472
- content: msg.content,
20473
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
20474
- };
20475
- return JSON.stringify(serialized);
20476
- });
20477
- await writeFile(files.conversation, conversationLines.join("\n"), "utf-8");
20478
- const context = {
20479
- tokenUsage: this.calculateTokens(session)
20480
- };
20481
- await writeFile(files.context, JSON.stringify(context, null, 2), "utf-8");
20482
- }
20483
- async load(sessionId) {
20484
- await this.ensureInitialized();
20485
- const files = this.getSessionFiles(sessionId);
20486
- try {
20487
- const metadataContent = await readFile(files.metadata, "utf-8");
20488
- const metadata = JSON.parse(metadataContent);
20489
- const conversationContent = await readFile(files.conversation, "utf-8");
20490
- const messages = conversationContent.split("\n").filter((line) => line.trim()).map((line) => {
20491
- const parsed = JSON.parse(line);
20492
- return {
20493
- role: parsed.role,
20494
- content: parsed.content
20495
- };
20496
- });
20497
- const session = {
20498
- id: metadata.id,
20499
- startedAt: new Date(metadata.startedAt),
20500
- messages,
20501
- projectPath: metadata.projectPath,
20502
- config: metadata.config,
20503
- trustedTools: /* @__PURE__ */ new Set()
20504
- };
20505
- return session;
20506
- } catch {
20507
- return null;
20508
- }
20509
- }
20510
- async listSessions(projectPath) {
20511
- await this.ensureInitialized();
20512
- const sessions = [];
20513
- try {
20514
- const entries = await readdir(this.config.storageDir, {
20515
- withFileTypes: true
20516
- });
20517
- for (const entry of entries) {
20518
- if (!entry.isDirectory()) continue;
20519
- const metadataPath = join(this.config.storageDir, entry.name, "metadata.json");
20520
- try {
20521
- const content = await readFile(metadataPath, "utf-8");
20522
- const metadata = JSON.parse(content);
20523
- metadata.startedAt = new Date(metadata.startedAt);
20524
- metadata.lastSavedAt = new Date(metadata.lastSavedAt);
20525
- if (!projectPath || metadata.projectPath === projectPath) {
20526
- sessions.push(metadata);
20527
- }
20528
- } catch {
20529
- continue;
20530
- }
20531
- }
20532
- } catch {
20533
- return [];
20534
- }
20535
- sessions.sort((a, b) => new Date(b.lastSavedAt).getTime() - new Date(a.lastSavedAt).getTime());
20536
- return sessions;
20537
- }
20538
- async delete(sessionId) {
20539
- await this.ensureInitialized();
20540
- const sessionDir = this.getSessionDir(sessionId);
20541
- try {
20542
- await rm(sessionDir, { recursive: true, force: true });
20543
- return true;
20544
- } catch {
20545
- return false;
20546
- }
20547
- }
20548
- async getMostRecent(projectPath) {
20549
- const sessions = await this.listSessions(projectPath);
20550
- return sessions[0] ?? null;
20551
- }
20552
- /**
20553
- * Append messages to an existing session's conversation file
20554
- * Creates the file if it doesn't exist
20555
- * @param sessionId - The session ID
20556
- * @param messages - Messages to append
20557
- */
20558
- async appendMessages(sessionId, messages) {
20559
- await this.ensureInitialized();
20560
- const files = this.getSessionFiles(sessionId);
20561
- const sessionDir = this.getSessionDir(sessionId);
20562
- await mkdir(sessionDir, { recursive: true });
20563
- const newLines = messages.map((msg) => {
20564
- const serialized = {
20565
- role: msg.role,
20566
- content: msg.content,
20567
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
20568
- };
20569
- return JSON.stringify(serialized);
20570
- });
20571
- let existingContent = "";
20572
- try {
20573
- existingContent = await readFile(files.conversation, "utf-8");
20574
- if (existingContent && !existingContent.endsWith("\n")) {
20575
- existingContent += "\n";
20576
- }
20577
- } catch {
20578
- }
20579
- await writeFile(files.conversation, existingContent + newLines.join("\n"), "utf-8");
20580
- }
20581
- /**
20582
- * Prune old sessions to keep storage manageable
20583
- * Keeps the most recent maxSessionsPerProject sessions per project
20584
- * @param projectPath - Optional project path to prune (prunes all if not specified)
20585
- * @returns Number of sessions deleted
20586
- */
20587
- async pruneOldSessions(projectPath) {
20588
- await this.ensureInitialized();
20589
- const allSessions = await this.listSessions();
20590
- const sessionsByProject = /* @__PURE__ */ new Map();
20591
- for (const session of allSessions) {
20592
- if (projectPath && session.projectPath !== projectPath) {
20593
- continue;
20594
- }
20595
- const existing = sessionsByProject.get(session.projectPath) ?? [];
20596
- existing.push(session);
20597
- sessionsByProject.set(session.projectPath, existing);
20598
- }
20599
- let deletedCount = 0;
20600
- for (const [, sessions] of sessionsByProject) {
20601
- const sessionsToDelete = sessions.slice(this.config.maxSessionsPerProject);
20602
- for (const session of sessionsToDelete) {
20603
- const deleted = await this.delete(session.id);
20604
- if (deleted) {
20605
- deletedCount++;
20606
- }
20607
- }
20608
- }
20609
- return deletedCount;
20610
- }
20611
- calculateTokens(session) {
20612
- if (session.contextManager) {
20613
- const stats = session.contextManager.getUsageStats();
20614
- return {
20615
- input: stats.used,
20616
- output: 0
20617
- };
20618
- }
20619
- let input = 0;
20620
- let output = 0;
20621
- for (const msg of session.messages) {
20622
- const content = typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content);
20623
- const tokens = Math.ceil(content.length / 4);
20624
- if (msg.role === "user") {
20625
- input += tokens;
20626
- } else {
20627
- output += tokens;
20628
- }
20629
- }
20630
- return { input, output };
20631
- }
20632
- generateTitle(session) {
20633
- for (const msg of session.messages) {
20634
- if (msg.role === "user" && typeof msg.content === "string") {
20635
- const content = msg.content.trim();
20636
- if (content.length > 10) {
20637
- const firstLine = content.split("\n")[0] ?? content;
20638
- return firstLine.length > 50 ? firstLine.slice(0, 47) + "..." : firstLine;
20639
- }
20640
- }
20641
- }
20642
- return "Untitled session";
20643
- }
20644
- };
20645
- function createSessionStore(config) {
20646
- return new SessionStore(config);
20647
- }
20648
-
20649
20356
  // src/runtime/agent-runtime.ts
20650
20357
  init_env();
20651
20358
  init_errors();
@@ -31415,7 +31122,7 @@ var HTTPTransport = class {
31415
31122
 
31416
31123
  // src/mcp/transport/sse.ts
31417
31124
  init_errors2();
31418
- var DEFAULT_CONFIG3 = {
31125
+ var DEFAULT_CONFIG2 = {
31419
31126
  initialReconnectDelay: 1e3,
31420
31127
  maxReconnectDelay: 3e4,
31421
31128
  maxReconnectAttempts: 10
@@ -31431,7 +31138,7 @@ var SSETransport = class {
31431
31138
  errorHandler = null;
31432
31139
  closeHandler = null;
31433
31140
  constructor(config) {
31434
- this.config = { ...DEFAULT_CONFIG3, ...config };
31141
+ this.config = { ...DEFAULT_CONFIG2, ...config };
31435
31142
  }
31436
31143
  /**
31437
31144
  * Connect to the SSE endpoint
@@ -32397,6 +32104,100 @@ function createFullToolRegistry() {
32397
32104
  registerAllTools(registry);
32398
32105
  return registry;
32399
32106
  }
32107
+
32108
+ // src/runtime/agent-modes.ts
32109
+ var AGENT_MODES = {
32110
+ ask: {
32111
+ id: "ask",
32112
+ label: "Ask",
32113
+ description: "Answer questions and explain code without modifying files.",
32114
+ readOnly: true,
32115
+ preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_definition"],
32116
+ requiresVerification: false
32117
+ },
32118
+ plan: {
32119
+ id: "plan",
32120
+ label: "Plan",
32121
+ description: "Explore and produce an implementation plan with read-only tools.",
32122
+ readOnly: true,
32123
+ preferredTools: ["read_file", "grep", "glob", "codebase_map", "lsp_workspace_symbols"],
32124
+ requiresVerification: false
32125
+ },
32126
+ build: {
32127
+ id: "build",
32128
+ label: "Build",
32129
+ description: "Implement code changes and verify them.",
32130
+ readOnly: false,
32131
+ preferredTools: ["read_file", "edit_file", "write_file", "bash_exec", "run_tests"],
32132
+ requiresVerification: true
32133
+ },
32134
+ debug: {
32135
+ id: "debug",
32136
+ label: "Debug",
32137
+ description: "Reproduce failures, trace root cause, patch, and verify.",
32138
+ readOnly: false,
32139
+ preferredTools: ["bash_exec", "read_file", "grep", "lsp_references", "edit_file"],
32140
+ requiresVerification: true
32141
+ },
32142
+ review: {
32143
+ id: "review",
32144
+ label: "Review",
32145
+ description: "Inspect code quality, security, behavior changes, and test gaps.",
32146
+ readOnly: true,
32147
+ preferredTools: ["git_diff", "read_file", "grep", "review_code", "calculate_quality"],
32148
+ requiresVerification: false
32149
+ },
32150
+ architect: {
32151
+ id: "architect",
32152
+ label: "Architect",
32153
+ description: "Design architecture and split work for architect/editor execution.",
32154
+ readOnly: true,
32155
+ preferredTools: ["codebase_map", "lsp_workspace_symbols", "grep", "create_agent_plan"],
32156
+ requiresVerification: false
32157
+ }
32158
+ };
32159
+ function getAgentMode(mode) {
32160
+ return AGENT_MODES[mode];
32161
+ }
32162
+ function listAgentModes() {
32163
+ return Object.values(AGENT_MODES);
32164
+ }
32165
+ function isAgentMode(value) {
32166
+ return value in AGENT_MODES;
32167
+ }
32168
+
32169
+ // src/runtime/default-turn-runner.ts
32170
+ var DefaultRuntimeTurnRunner = class {
32171
+ async run(input, context) {
32172
+ const messages = [
32173
+ ...context.session.messages,
32174
+ {
32175
+ role: "user",
32176
+ content: input.content
32177
+ }
32178
+ ];
32179
+ const response = await context.provider.chat(messages, {
32180
+ model: input.options?.model,
32181
+ maxTokens: input.options?.maxTokens,
32182
+ temperature: input.options?.temperature,
32183
+ stopSequences: input.options?.stopSequences,
32184
+ system: context.session.instructions ?? input.options?.system,
32185
+ timeout: input.options?.timeout,
32186
+ signal: input.options?.signal,
32187
+ thinking: input.options?.thinking
32188
+ });
32189
+ return {
32190
+ sessionId: context.session.id,
32191
+ content: response.content,
32192
+ usage: response.usage,
32193
+ model: response.model,
32194
+ mode: context.session.mode
32195
+ };
32196
+ }
32197
+ };
32198
+ function createDefaultRuntimeTurnRunner() {
32199
+ return new DefaultRuntimeTurnRunner();
32200
+ }
32400
32201
  var InMemoryEventLog = class {
32401
32202
  events = [];
32402
32203
  record(type, data = {}) {
@@ -32548,6 +32349,22 @@ var DefaultPermissionPolicy = class {
32548
32349
  }
32549
32350
  return { allowed: true, risk };
32550
32351
  }
32352
+ canExecuteToolInput(mode, tool, input) {
32353
+ if (tool.name !== "run_linter") {
32354
+ return this.canExecuteTool(mode, tool);
32355
+ }
32356
+ const definition = getAgentMode(mode);
32357
+ const fixEnabled = input["fix"] === true;
32358
+ const decision = fixEnabled ? { allowed: true, risk: "write" } : { allowed: true, risk: "read-only" };
32359
+ if (definition.readOnly && fixEnabled) {
32360
+ return {
32361
+ allowed: false,
32362
+ reason: `${definition.label} mode is read-only; run_linter with fix=true can modify files.`,
32363
+ risk: "write"
32364
+ };
32365
+ }
32366
+ return decision;
32367
+ }
32551
32368
  };
32552
32369
  function createPermissionPolicy() {
32553
32370
  return new DefaultPermissionPolicy();
@@ -32587,108 +32404,135 @@ var ProviderRegistry = class {
32587
32404
  function createProviderRegistry() {
32588
32405
  return new ProviderRegistry();
32589
32406
  }
32590
-
32591
- // src/runtime/agent-runtime.ts
32592
- var AgentRuntime = class {
32593
- constructor(options) {
32594
- this.options = options;
32595
- this.providerRegistry = createProviderRegistry();
32596
- this.toolRegistry = options.toolRegistry ?? createFullToolRegistry();
32597
- this.sessionStore = options.sessionStore ?? createSessionStore({});
32598
- this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
32599
- this.eventLog = options.eventLog ?? (options.eventLogPath ? createFileEventLog(options.eventLogPath) : createEventLog());
32600
- this.providerType = options.providerType;
32601
- this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
32407
+ function createSessionId() {
32408
+ return `rt_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 10)}`;
32409
+ }
32410
+ function cloneSession(session) {
32411
+ return structuredClone(session);
32412
+ }
32413
+ var InMemoryRuntimeSessionStore = class {
32414
+ sessions = /* @__PURE__ */ new Map();
32415
+ create(options = {}) {
32416
+ const now = (/* @__PURE__ */ new Date()).toISOString();
32417
+ const session = {
32418
+ id: options.id ?? createSessionId(),
32419
+ createdAt: now,
32420
+ updatedAt: now,
32421
+ mode: options.mode ?? "ask",
32422
+ messages: options.messages ? options.messages.map((message) => ({ ...message })) : [],
32423
+ instructions: options.instructions,
32424
+ metadata: { ...options.metadata }
32425
+ };
32426
+ this.sessions.set(session.id, cloneSession(session));
32427
+ return cloneSession(session);
32602
32428
  }
32603
- options;
32604
- providerRegistry;
32605
- toolRegistry;
32606
- sessionStore;
32607
- permissionPolicy;
32608
- eventLog;
32609
- providerType;
32610
- model;
32611
- async initialize() {
32612
- const providerInjected = Boolean(this.options.provider);
32613
- const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
32614
- ...this.options.providerConfig,
32615
- model: this.getModel()
32616
- });
32617
- this.publishToGlobalBridge(provider);
32618
- this.eventLog.record(providerInjected ? "provider.attached" : "provider.created", {
32619
- provider: this.providerType,
32620
- model: this.getModel(),
32621
- createdByRuntime: !providerInjected
32622
- });
32623
- this.eventLog.record("runtime.initialized", { snapshot: this.snapshot() });
32429
+ get(id) {
32430
+ const session = this.sessions.get(id);
32431
+ return session ? cloneSession(session) : void 0;
32432
+ }
32433
+ update(session) {
32434
+ const updated = {
32435
+ ...session,
32436
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
32437
+ messages: session.messages.map((message) => ({ ...message })),
32438
+ metadata: { ...session.metadata }
32439
+ };
32440
+ this.sessions.set(updated.id, cloneSession(updated));
32441
+ return cloneSession(updated);
32624
32442
  }
32625
- getModel() {
32626
- return this.model;
32443
+ list() {
32444
+ return [...this.sessions.values()].map(cloneSession);
32627
32445
  }
32628
- updateProvider(providerType, model2, provider) {
32629
- this.providerType = providerType;
32630
- this.model = model2 ?? getDefaultModel(providerType);
32631
- this.publishToGlobalBridge(provider);
32632
- this.eventLog.record("provider.updated", {
32633
- provider: this.providerType,
32634
- model: this.model
32635
- });
32446
+ delete(id) {
32447
+ return this.sessions.delete(id);
32636
32448
  }
32637
- publishToGlobalBridge(provider) {
32638
- if (this.options.publishToGlobalBridge !== true) return;
32639
- setAgentProvider(provider);
32640
- setAgentToolRegistry(this.toolRegistry);
32449
+ };
32450
+ var FileRuntimeSessionStore = class {
32451
+ constructor(filePath) {
32452
+ this.filePath = filePath;
32453
+ mkdirSync(dirname(filePath), { recursive: true });
32454
+ this.sessions = this.readSessionsFromDisk();
32641
32455
  }
32642
- snapshot() {
32643
- const capability = this.providerRegistry.getCapability(this.providerType, this.getModel());
32644
- const toolNames = this.toolRegistry.getAll().map((tool) => tool.name).sort();
32645
- return {
32646
- provider: {
32647
- type: this.providerType,
32648
- model: this.getModel(),
32649
- capability
32650
- },
32651
- tools: {
32652
- count: toolNames.length,
32653
- names: toolNames
32654
- },
32655
- modes: listAgentModes()
32456
+ filePath;
32457
+ sessions = /* @__PURE__ */ new Map();
32458
+ create(options = {}) {
32459
+ const now = (/* @__PURE__ */ new Date()).toISOString();
32460
+ const session = {
32461
+ id: options.id ?? createSessionId(),
32462
+ createdAt: now,
32463
+ updatedAt: now,
32464
+ mode: options.mode ?? "ask",
32465
+ messages: options.messages ? options.messages.map((message) => ({ ...message })) : [],
32466
+ instructions: options.instructions,
32467
+ metadata: { ...options.metadata }
32656
32468
  };
32469
+ const sessions = this.readSessionsFromDisk();
32470
+ sessions.set(session.id, cloneSession(session));
32471
+ this.sessions = sessions;
32472
+ this.persist(sessions);
32473
+ return cloneSession(session);
32657
32474
  }
32658
- assertToolAllowed(mode, toolName) {
32659
- const tool = this.toolRegistry.get(toolName);
32660
- if (!tool) {
32661
- this.eventLog.record("tool.blocked", {
32662
- mode,
32663
- tool: toolName,
32664
- reason: "Tool not registered."
32665
- });
32666
- return false;
32475
+ get(id) {
32476
+ this.sessions = this.readSessionsFromDisk();
32477
+ const session = this.sessions.get(id);
32478
+ return session ? cloneSession(session) : void 0;
32479
+ }
32480
+ update(session) {
32481
+ const updated = {
32482
+ ...session,
32483
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
32484
+ messages: session.messages.map((message) => ({ ...message })),
32485
+ metadata: { ...session.metadata }
32486
+ };
32487
+ const sessions = this.readSessionsFromDisk();
32488
+ sessions.set(updated.id, cloneSession(updated));
32489
+ this.sessions = sessions;
32490
+ this.persist(sessions);
32491
+ return cloneSession(updated);
32492
+ }
32493
+ list() {
32494
+ this.sessions = this.readSessionsFromDisk();
32495
+ return [...this.sessions.values()].map(cloneSession);
32496
+ }
32497
+ delete(id) {
32498
+ const sessions = this.readSessionsFromDisk();
32499
+ const deleted = sessions.delete(id);
32500
+ this.sessions = sessions;
32501
+ if (deleted) this.persist(sessions);
32502
+ return deleted;
32503
+ }
32504
+ readSessionsFromDisk() {
32505
+ let raw;
32506
+ try {
32507
+ raw = readFileSync(this.filePath, "utf-8");
32508
+ } catch (error) {
32509
+ if (error && typeof error === "object" && "code" in error && error.code === "ENOENT") {
32510
+ return /* @__PURE__ */ new Map();
32511
+ }
32512
+ throw error;
32667
32513
  }
32668
- const decision = this.permissionPolicy.canExecuteTool(mode, tool);
32669
- this.eventLog.record(decision.allowed ? "tool.allowed" : "tool.blocked", {
32670
- mode,
32671
- tool: toolName,
32672
- ...decision
32673
- });
32674
- return decision.allowed;
32514
+ if (!raw.trim()) return /* @__PURE__ */ new Map();
32515
+ const parsed = JSON.parse(raw);
32516
+ if (parsed.version !== 1 || !Array.isArray(parsed.sessions)) {
32517
+ throw new Error(`Unsupported runtime session store format: ${this.filePath}`);
32518
+ }
32519
+ return new Map(parsed.sessions.map((session) => [session.id, cloneSession(session)]));
32520
+ }
32521
+ persist(sessions) {
32522
+ const payload = {
32523
+ version: 1,
32524
+ sessions: [...sessions.values()].map(cloneSession)
32525
+ };
32526
+ const tempPath = `${this.filePath}.${randomUUID()}.tmp`;
32527
+ writeFileSync(tempPath, JSON.stringify(payload, null, 2) + "\n", "utf-8");
32528
+ renameSync(tempPath, this.filePath);
32675
32529
  }
32676
32530
  };
32677
- async function createAgentRuntime(options) {
32678
- const runtime = new AgentRuntime(options);
32679
- await runtime.initialize();
32680
- return runtime;
32531
+ function createRuntimeSessionStore() {
32532
+ return new InMemoryRuntimeSessionStore();
32681
32533
  }
32682
-
32683
- // src/runtime/extension-manifests.ts
32684
- function createMcpToolPolicy(server, tool, risk, allowedModes = ["ask", "plan", "build", "debug", "review", "architect"]) {
32685
- return {
32686
- server,
32687
- tool,
32688
- risk,
32689
- requiresConfirmation: risk === "destructive" || risk === "secrets-sensitive",
32690
- allowedModes
32691
- };
32534
+ function createFileRuntimeSessionStore(filePath) {
32535
+ return new FileRuntimeSessionStore(filePath);
32692
32536
  }
32693
32537
 
32694
32538
  // src/runtime/workflow-registry.ts
@@ -32883,11 +32727,572 @@ function createWorkflowRegistry(workflows) {
32883
32727
  return createWorkflowCatalog(workflows);
32884
32728
  }
32885
32729
 
32730
+ // src/runtime/workflow-engine.ts
32731
+ var WorkflowEngine = class {
32732
+ constructor(catalog = createWorkflowCatalog(), eventLog = createEventLog()) {
32733
+ this.catalog = catalog;
32734
+ this.eventLog = eventLog;
32735
+ }
32736
+ catalog;
32737
+ eventLog;
32738
+ handlers = /* @__PURE__ */ new Map();
32739
+ registerHandler(workflowId, handler) {
32740
+ if (!this.catalog.get(workflowId)) {
32741
+ throw new Error(`Unknown workflow: ${workflowId}`);
32742
+ }
32743
+ this.handlers.set(workflowId, handler);
32744
+ }
32745
+ createPlan(workflowId, input) {
32746
+ return this.catalog.createPlan(workflowId, input, this.eventLog);
32747
+ }
32748
+ async run(request) {
32749
+ const workflow = this.catalog.get(request.workflowId);
32750
+ if (!workflow) {
32751
+ throw new Error(`Unknown workflow: ${request.workflowId}`);
32752
+ }
32753
+ const handler = this.handlers.get(request.workflowId);
32754
+ if (!handler) {
32755
+ throw new Error(`No handler registered for workflow: ${request.workflowId}`);
32756
+ }
32757
+ const plan = request.plan ?? this.createPlan(request.workflowId, request.input);
32758
+ const startedAt = (/* @__PURE__ */ new Date()).toISOString();
32759
+ const runId = `${request.workflowId}-run-${Date.now().toString(36)}`;
32760
+ this.eventLog.record("workflow.started", {
32761
+ workflowId: request.workflowId,
32762
+ planId: plan.id,
32763
+ runId
32764
+ });
32765
+ try {
32766
+ const output = await handler(request.input, {
32767
+ workflow,
32768
+ plan,
32769
+ eventLog: this.eventLog
32770
+ });
32771
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
32772
+ const result = {
32773
+ id: runId,
32774
+ workflowId: request.workflowId,
32775
+ status: "completed",
32776
+ output,
32777
+ startedAt,
32778
+ completedAt
32779
+ };
32780
+ this.eventLog.record("workflow.completed", {
32781
+ workflowId: request.workflowId,
32782
+ planId: plan.id,
32783
+ runId
32784
+ });
32785
+ return result;
32786
+ } catch (error) {
32787
+ const completedAt = (/* @__PURE__ */ new Date()).toISOString();
32788
+ const message = error instanceof Error ? error.message : String(error);
32789
+ this.eventLog.record("workflow.failed", {
32790
+ workflowId: request.workflowId,
32791
+ planId: plan.id,
32792
+ runId,
32793
+ error: message
32794
+ });
32795
+ return {
32796
+ id: runId,
32797
+ workflowId: request.workflowId,
32798
+ status: "failed",
32799
+ output: null,
32800
+ startedAt,
32801
+ completedAt,
32802
+ error: message
32803
+ };
32804
+ }
32805
+ }
32806
+ };
32807
+ function createWorkflowEngine(catalog, eventLog) {
32808
+ return new WorkflowEngine(catalog, eventLog);
32809
+ }
32810
+
32811
+ // src/runtime/agent-runtime.ts
32812
+ var AgentRuntime = class {
32813
+ constructor(options) {
32814
+ this.options = options;
32815
+ this.providerRegistry = createProviderRegistry();
32816
+ this.toolRegistry = options.toolRegistry ?? createFullToolRegistry();
32817
+ this.sessionStore = options.sessionStore;
32818
+ this.runtimeSessionStore = options.runtimeSessionStore ?? createRuntimeSessionStore();
32819
+ this.eventLog = options.eventLog ?? (options.eventLogPath ? createFileEventLog(options.eventLogPath) : createEventLog());
32820
+ this.workflowEngine = options.workflowEngine ?? createWorkflowEngine(void 0, this.eventLog);
32821
+ this.permissionPolicy = options.permissionPolicy ?? createPermissionPolicy();
32822
+ this.turnRunner = options.turnRunner ?? createDefaultRuntimeTurnRunner();
32823
+ this.providerType = options.providerType;
32824
+ this.model = options.model ?? options.providerConfig?.model ?? getDefaultModel(options.providerType);
32825
+ }
32826
+ options;
32827
+ providerRegistry;
32828
+ toolRegistry;
32829
+ sessionStore;
32830
+ runtimeSessionStore;
32831
+ workflowEngine;
32832
+ permissionPolicy;
32833
+ eventLog;
32834
+ turnRunner;
32835
+ providerType;
32836
+ model;
32837
+ provider;
32838
+ async initialize() {
32839
+ const providerInjected = Boolean(this.options.provider);
32840
+ const provider = this.options.provider ?? await this.providerRegistry.createProvider(this.providerType, {
32841
+ ...this.options.providerConfig,
32842
+ model: this.getModel()
32843
+ });
32844
+ this.provider = provider;
32845
+ this.publishToGlobalBridge(provider);
32846
+ this.eventLog.record(providerInjected ? "provider.attached" : "provider.created", {
32847
+ provider: this.providerType,
32848
+ model: this.getModel(),
32849
+ createdByRuntime: !providerInjected
32850
+ });
32851
+ this.eventLog.record("runtime.initialized", { snapshot: this.snapshot() });
32852
+ }
32853
+ getModel() {
32854
+ return this.model;
32855
+ }
32856
+ updateProvider(providerType, model2, provider) {
32857
+ this.providerType = providerType;
32858
+ this.model = model2 ?? getDefaultModel(providerType);
32859
+ this.provider = provider;
32860
+ this.publishToGlobalBridge(provider);
32861
+ this.eventLog.record("provider.updated", {
32862
+ provider: this.providerType,
32863
+ model: this.model
32864
+ });
32865
+ }
32866
+ publishToGlobalBridge(provider) {
32867
+ if (this.options.publishToGlobalBridge !== true) return;
32868
+ setAgentProvider(provider);
32869
+ setAgentToolRegistry(this.toolRegistry);
32870
+ }
32871
+ snapshot() {
32872
+ const capability = this.providerRegistry.getCapability(this.providerType, this.getModel());
32873
+ const toolNames = this.toolRegistry.getAll().map((tool) => tool.name).sort();
32874
+ return {
32875
+ provider: {
32876
+ type: this.providerType,
32877
+ model: this.getModel(),
32878
+ capability
32879
+ },
32880
+ tools: {
32881
+ count: toolNames.length,
32882
+ names: toolNames
32883
+ },
32884
+ modes: listAgentModes()
32885
+ };
32886
+ }
32887
+ createSession(options = {}) {
32888
+ const session = this.runtimeSessionStore.create(options);
32889
+ this.eventLog.record("session.created", {
32890
+ sessionId: session.id,
32891
+ mode: session.mode,
32892
+ metadataKeys: Object.keys(session.metadata).sort()
32893
+ });
32894
+ return session;
32895
+ }
32896
+ getSession(sessionId) {
32897
+ return this.runtimeSessionStore.get(sessionId);
32898
+ }
32899
+ listSessions() {
32900
+ return this.runtimeSessionStore.list();
32901
+ }
32902
+ async runTurn(input) {
32903
+ const provider = this.provider;
32904
+ if (!provider) {
32905
+ throw new Error("Runtime provider is not initialized.");
32906
+ }
32907
+ const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
32908
+ if (!session) {
32909
+ throw new Error(`Runtime session not found: ${input.sessionId}`);
32910
+ }
32911
+ const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
32912
+ this.eventLog.record("turn.started", {
32913
+ sessionId: effectiveSession.id,
32914
+ provider: this.providerType,
32915
+ model: this.getModel(),
32916
+ mode: effectiveSession.mode,
32917
+ runtimeApi: true
32918
+ });
32919
+ try {
32920
+ const result = await this.turnRunner.run(input, {
32921
+ runtime: this,
32922
+ session: effectiveSession,
32923
+ provider,
32924
+ toolRegistry: this.toolRegistry,
32925
+ permissionPolicy: this.permissionPolicy,
32926
+ eventLog: this.eventLog
32927
+ });
32928
+ const updatedSession = this.runtimeSessionStore.update({
32929
+ ...effectiveSession,
32930
+ messages: [
32931
+ ...effectiveSession.messages,
32932
+ { role: "user", content: input.content },
32933
+ { role: "assistant", content: result.content }
32934
+ ]
32935
+ });
32936
+ this.eventLog.record("session.updated", {
32937
+ sessionId: updatedSession.id,
32938
+ messages: updatedSession.messages.length
32939
+ });
32940
+ this.eventLog.record("turn.completed", {
32941
+ sessionId: updatedSession.id,
32942
+ inputTokens: result.usage.inputTokens,
32943
+ outputTokens: result.usage.outputTokens,
32944
+ model: result.model,
32945
+ runtimeApi: true
32946
+ });
32947
+ return { ...result, sessionId: updatedSession.id, mode: updatedSession.mode };
32948
+ } catch (error) {
32949
+ this.eventLog.record("turn.failed", {
32950
+ sessionId: effectiveSession.id,
32951
+ error: error instanceof Error ? error.message : String(error),
32952
+ runtimeApi: true
32953
+ });
32954
+ throw error;
32955
+ }
32956
+ }
32957
+ async *streamTurn(input) {
32958
+ const provider = this.provider;
32959
+ if (!provider) {
32960
+ throw new Error("Runtime provider is not initialized.");
32961
+ }
32962
+ const session = input.sessionId ? this.runtimeSessionStore.get(input.sessionId) : this.createSession({ mode: input.mode, metadata: input.metadata });
32963
+ if (!session) {
32964
+ throw new Error(`Runtime session not found: ${input.sessionId}`);
32965
+ }
32966
+ const effectiveSession = input.mode && input.mode !== session.mode ? { ...session, mode: input.mode } : session;
32967
+ const messages = [
32968
+ ...effectiveSession.messages,
32969
+ {
32970
+ role: "user",
32971
+ content: input.content
32972
+ }
32973
+ ];
32974
+ this.eventLog.record("turn.started", {
32975
+ sessionId: effectiveSession.id,
32976
+ provider: this.providerType,
32977
+ model: this.getModel(),
32978
+ mode: effectiveSession.mode,
32979
+ streaming: true,
32980
+ runtimeApi: true
32981
+ });
32982
+ let content = "";
32983
+ let completed = false;
32984
+ let failed = false;
32985
+ try {
32986
+ for await (const chunk of provider.stream(messages, {
32987
+ model: input.options?.model,
32988
+ maxTokens: input.options?.maxTokens,
32989
+ temperature: input.options?.temperature,
32990
+ stopSequences: input.options?.stopSequences,
32991
+ system: effectiveSession.instructions ?? input.options?.system,
32992
+ timeout: input.options?.timeout,
32993
+ signal: input.options?.signal,
32994
+ thinking: input.options?.thinking
32995
+ })) {
32996
+ if (chunk.type === "text" && chunk.text) {
32997
+ content += chunk.text;
32998
+ yield {
32999
+ type: "text",
33000
+ sessionId: effectiveSession.id,
33001
+ text: chunk.text
33002
+ };
33003
+ }
33004
+ }
33005
+ const updatedSession = this.runtimeSessionStore.update({
33006
+ ...effectiveSession,
33007
+ messages: [
33008
+ ...effectiveSession.messages,
33009
+ { role: "user", content: input.content },
33010
+ { role: "assistant", content }
33011
+ ]
33012
+ });
33013
+ const result = {
33014
+ sessionId: updatedSession.id,
33015
+ content,
33016
+ usage: {
33017
+ inputTokens: provider.countTokens(input.content),
33018
+ outputTokens: provider.countTokens(content),
33019
+ estimated: true
33020
+ },
33021
+ model: input.options?.model ?? this.getModel(),
33022
+ mode: updatedSession.mode
33023
+ };
33024
+ this.eventLog.record("session.updated", {
33025
+ sessionId: updatedSession.id,
33026
+ messages: updatedSession.messages.length
33027
+ });
33028
+ this.eventLog.record("turn.completed", {
33029
+ sessionId: updatedSession.id,
33030
+ inputTokens: result.usage.inputTokens,
33031
+ outputTokens: result.usage.outputTokens,
33032
+ model: result.model,
33033
+ streaming: true,
33034
+ runtimeApi: true
33035
+ });
33036
+ completed = true;
33037
+ yield { type: "done", sessionId: updatedSession.id, result };
33038
+ } catch (error) {
33039
+ failed = true;
33040
+ const message = error instanceof Error ? error.message : String(error);
33041
+ this.eventLog.record("turn.failed", {
33042
+ sessionId: effectiveSession.id,
33043
+ error: message,
33044
+ streaming: true,
33045
+ runtimeApi: true
33046
+ });
33047
+ yield {
33048
+ type: "error",
33049
+ sessionId: effectiveSession.id,
33050
+ error: message
33051
+ };
33052
+ } finally {
33053
+ if (!completed && !failed) {
33054
+ this.eventLog.record("turn.cancelled", {
33055
+ sessionId: effectiveSession.id,
33056
+ outputTokens: provider.countTokens(content),
33057
+ streaming: true,
33058
+ runtimeApi: true
33059
+ });
33060
+ }
33061
+ }
33062
+ }
33063
+ async executeTool(input) {
33064
+ const startedAt = performance.now();
33065
+ const session = input.sessionId ? this.getSession(input.sessionId) : void 0;
33066
+ if (input.sessionId && !session) {
33067
+ const decision2 = {
33068
+ allowed: false,
33069
+ reason: `Runtime session not found: ${input.sessionId}`,
33070
+ risk: "read-only"
33071
+ };
33072
+ this.eventLog.record("tool.blocked", {
33073
+ sessionId: input.sessionId,
33074
+ mode: input.mode ?? "ask",
33075
+ tool: input.toolName,
33076
+ reason: decision2.reason,
33077
+ runtimeApi: true
33078
+ });
33079
+ return {
33080
+ toolName: input.toolName,
33081
+ success: false,
33082
+ error: decision2.reason,
33083
+ duration: performance.now() - startedAt,
33084
+ decision: decision2
33085
+ };
33086
+ }
33087
+ const mode = input.mode ?? session?.mode ?? "ask";
33088
+ const tool = this.toolRegistry.get(input.toolName);
33089
+ if (!tool) {
33090
+ const decision2 = {
33091
+ allowed: false,
33092
+ reason: "Tool not registered.",
33093
+ risk: "read-only"
33094
+ };
33095
+ this.eventLog.record("tool.blocked", {
33096
+ sessionId: input.sessionId,
33097
+ mode,
33098
+ tool: input.toolName,
33099
+ reason: decision2.reason,
33100
+ runtimeApi: true
33101
+ });
33102
+ return {
33103
+ toolName: input.toolName,
33104
+ success: false,
33105
+ error: decision2.reason,
33106
+ duration: performance.now() - startedAt,
33107
+ decision: decision2
33108
+ };
33109
+ }
33110
+ const decision = this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input.input) : this.permissionPolicy.canExecuteTool(mode, tool);
33111
+ if (!decision.allowed || decision.requiresConfirmation && input.confirmed !== true) {
33112
+ const reason = decision.reason ?? (decision.requiresConfirmation ? "Tool requires explicit runtime confirmation." : "Tool is not allowed.");
33113
+ this.eventLog.record("tool.blocked", {
33114
+ sessionId: input.sessionId,
33115
+ mode,
33116
+ tool: input.toolName,
33117
+ reason,
33118
+ risk: decision.risk,
33119
+ requiresConfirmation: decision.requiresConfirmation,
33120
+ runtimeApi: true
33121
+ });
33122
+ return {
33123
+ toolName: input.toolName,
33124
+ success: false,
33125
+ error: reason,
33126
+ duration: performance.now() - startedAt,
33127
+ decision
33128
+ };
33129
+ }
33130
+ this.eventLog.record("tool.started", {
33131
+ sessionId: input.sessionId,
33132
+ mode,
33133
+ tool: input.toolName,
33134
+ risk: decision.risk,
33135
+ runtimeApi: true,
33136
+ metadataKeys: Object.keys(input.metadata ?? {}).sort()
33137
+ });
33138
+ const result = await this.toolRegistry.execute(input.toolName, input.input);
33139
+ this.eventLog.record("tool.completed", {
33140
+ sessionId: input.sessionId,
33141
+ mode,
33142
+ tool: input.toolName,
33143
+ success: result.success,
33144
+ duration: result.duration,
33145
+ runtimeApi: true
33146
+ });
33147
+ return {
33148
+ toolName: input.toolName,
33149
+ success: result.success,
33150
+ output: result.data,
33151
+ error: result.error,
33152
+ duration: result.duration,
33153
+ decision
33154
+ };
33155
+ }
33156
+ assertToolAllowed(mode, toolName, input) {
33157
+ const tool = this.toolRegistry.get(toolName);
33158
+ if (!tool) {
33159
+ this.eventLog.record("tool.blocked", {
33160
+ mode,
33161
+ tool: toolName,
33162
+ reason: "Tool not registered."
33163
+ });
33164
+ return false;
33165
+ }
33166
+ const decision = input && this.permissionPolicy.canExecuteToolInput ? this.permissionPolicy.canExecuteToolInput(mode, tool, input) : this.permissionPolicy.canExecuteTool(mode, tool);
33167
+ this.eventLog.record(decision.allowed ? "tool.allowed" : "tool.blocked", {
33168
+ mode,
33169
+ tool: toolName,
33170
+ ...decision
33171
+ });
33172
+ return decision.allowed;
33173
+ }
33174
+ };
33175
+ async function createAgentRuntime(options) {
33176
+ const runtime = new AgentRuntime(options);
33177
+ await runtime.initialize();
33178
+ return runtime;
33179
+ }
33180
+ var HttpRequestError = class extends Error {
33181
+ constructor(message, status) {
33182
+ super(message);
33183
+ this.status = status;
33184
+ }
33185
+ status;
33186
+ };
33187
+ async function readJsonBody(request, maxBodyBytes) {
33188
+ const chunks = [];
33189
+ let size = 0;
33190
+ for await (const chunk of request) {
33191
+ const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
33192
+ size += buffer.length;
33193
+ if (size > maxBodyBytes) {
33194
+ throw new HttpRequestError(`Request body exceeds ${maxBodyBytes} bytes.`, 413);
33195
+ }
33196
+ chunks.push(buffer);
33197
+ }
33198
+ const raw = Buffer.concat(chunks).toString("utf-8").trim();
33199
+ try {
33200
+ return raw ? JSON.parse(raw) : {};
33201
+ } catch {
33202
+ throw new HttpRequestError("Invalid JSON request body.", 400);
33203
+ }
33204
+ }
33205
+ function sendJson(response, status, body) {
33206
+ response.statusCode = status;
33207
+ response.setHeader("content-type", "application/json; charset=utf-8");
33208
+ response.end(JSON.stringify(body, null, 2));
33209
+ }
33210
+ function notFound(response) {
33211
+ sendJson(response, 404, { error: "Not found" });
33212
+ }
33213
+ function assertValidMode(mode) {
33214
+ if (mode === void 0) return void 0;
33215
+ if (typeof mode === "string" && isAgentMode(mode)) return mode;
33216
+ throw new HttpRequestError("Invalid runtime mode.", 400);
33217
+ }
33218
+ function createRuntimeHttpServer(runtime, options = {}) {
33219
+ const maxBodyBytes = options.maxBodyBytes ?? 1024 * 1024;
33220
+ return createServer(async (request, response) => {
33221
+ try {
33222
+ const url = new URL(request.url ?? "/", "http://localhost");
33223
+ const parts = url.pathname.split("/").filter(Boolean);
33224
+ if (request.method === "POST" && url.pathname === "/sessions") {
33225
+ const body = await readJsonBody(request, maxBodyBytes);
33226
+ const session = runtime.createSession({
33227
+ mode: assertValidMode(body.mode),
33228
+ instructions: body.instructions,
33229
+ metadata: body.metadata
33230
+ });
33231
+ sendJson(response, 201, session);
33232
+ return;
33233
+ }
33234
+ if (request.method === "GET" && parts[0] === "sessions" && parts[1] && parts.length === 2) {
33235
+ const session = runtime.getSession(parts[1]);
33236
+ if (!session) {
33237
+ notFound(response);
33238
+ return;
33239
+ }
33240
+ sendJson(response, 200, session);
33241
+ return;
33242
+ }
33243
+ if (request.method === "POST" && parts[0] === "sessions" && parts[1] && parts[2] === "messages") {
33244
+ const body = await readJsonBody(request, maxBodyBytes);
33245
+ if (!body.content || typeof body.content !== "string") {
33246
+ sendJson(response, 400, { error: "content is required" });
33247
+ return;
33248
+ }
33249
+ if (!runtime.getSession(parts[1])) {
33250
+ notFound(response);
33251
+ return;
33252
+ }
33253
+ const result = await runtime.runTurn({
33254
+ ...body,
33255
+ mode: assertValidMode(body.mode),
33256
+ sessionId: parts[1]
33257
+ });
33258
+ sendJson(response, 200, result);
33259
+ return;
33260
+ }
33261
+ if (request.method === "GET" && parts[0] === "sessions" && parts[1] && parts[2] === "events") {
33262
+ const events = runtime.eventLog.list().filter((event) => event.data["sessionId"] === parts[1]);
33263
+ sendJson(response, 200, { events });
33264
+ return;
33265
+ }
33266
+ if (request.method === "GET" && url.pathname === "/state") {
33267
+ sendJson(response, 200, runtime.snapshot());
33268
+ return;
33269
+ }
33270
+ notFound(response);
33271
+ } catch (error) {
33272
+ const status = error instanceof HttpRequestError ? error.status : 500;
33273
+ sendJson(response, status, {
33274
+ error: error instanceof Error ? error.message : String(error)
33275
+ });
33276
+ }
33277
+ });
33278
+ }
33279
+
33280
+ // src/runtime/extension-manifests.ts
33281
+ function createMcpToolPolicy(server, tool, risk, allowedModes = ["ask", "plan", "build", "debug", "review", "architect"]) {
33282
+ return {
33283
+ server,
33284
+ tool,
33285
+ risk,
33286
+ requiresConfirmation: risk === "destructive" || risk === "secrets-sensitive",
33287
+ allowedModes
33288
+ };
33289
+ }
33290
+
32886
33291
  // src/index.ts
32887
33292
  init_errors();
32888
33293
  init_logger();
32889
33294
  init_proxy();
32890
33295
 
32891
- export { ADRGenerator, AgentRuntime, AnthropicProvider, ArchitectureGenerator, BacklogGenerator, CICDGenerator, CocoError, CodeGenerator, CodeReviewer, CompleteExecutor, ConfigError, ConvergeExecutor, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DiscoveryEngine, DockerGenerator, DocsGenerator, FileEventLog, InMemoryEventLog, OrchestrateExecutor, OutputExecutor, PhaseError, ProviderRegistry, SessionManager, SpecificationGenerator, TaskError, TaskIterator, ToolRegistry, VERSION, WorkflowCatalog, WorkflowRegistry, configExists, createADRGenerator, createAgentRuntime, createAnthropicProvider, createArchitectureGenerator, createBacklogGenerator, createCICDGenerator, createCodeGenerator, createCodeReviewer, createCompleteExecutor, createConvergeExecutor, createDefaultConfig, createDiscoveryEngine, createDockerGenerator, createDocsGenerator, createEventLog, createFileEventLog, createFullToolRegistry, createLogger, createMcpToolPolicy, createOrchestrateExecutor, createOrchestrator, createOutputExecutor, createPermissionPolicy, createProvider, createProviderRegistry, createSessionManager, createSpecificationGenerator, createTaskIterator, createToolRegistry, createWorkflowCatalog, createWorkflowRegistry, installProxyDispatcher, loadConfig, registerAllTools, saveConfig };
33296
+ export { ADRGenerator, AGENT_MODES, AgentRuntime, AnthropicProvider, ArchitectureGenerator, BacklogGenerator, CICDGenerator, CocoError, CodeGenerator, CodeReviewer, CompleteExecutor, ConfigError, ConvergeExecutor, DEFAULT_WORKFLOWS, DefaultPermissionPolicy, DefaultRuntimeTurnRunner, DiscoveryEngine, DockerGenerator, DocsGenerator, FileEventLog, FileRuntimeSessionStore, InMemoryEventLog, InMemoryRuntimeSessionStore, OrchestrateExecutor, OutputExecutor, PhaseError, ProviderRegistry, SessionManager, SpecificationGenerator, TaskError, TaskIterator, ToolRegistry, VERSION, WorkflowCatalog, WorkflowEngine, WorkflowRegistry, configExists, createADRGenerator, createAgentRuntime, createAnthropicProvider, createArchitectureGenerator, createBacklogGenerator, createCICDGenerator, createCodeGenerator, createCodeReviewer, createCompleteExecutor, createConvergeExecutor, createDefaultConfig, createDefaultRuntimeTurnRunner, createDiscoveryEngine, createDockerGenerator, createDocsGenerator, createEventLog, createFileEventLog, createFileRuntimeSessionStore, createFullToolRegistry, createLogger, createMcpToolPolicy, createOrchestrateExecutor, createOrchestrator, createOutputExecutor, createPermissionPolicy, createProvider, createProviderRegistry, createRuntimeHttpServer, createRuntimeSessionStore, createSessionManager, createSpecificationGenerator, createTaskIterator, createToolRegistry, createWorkflowCatalog, createWorkflowEngine, createWorkflowRegistry, getAgentMode, installProxyDispatcher, isAgentMode, listAgentModes, loadConfig, registerAllTools, saveConfig };
32892
33297
  //# sourceMappingURL=index.js.map
32893
33298
  //# sourceMappingURL=index.js.map