Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
228 commits
Select commit Hold shift + click to select a range
de60a52
Initial prototype agentic system up and running
wasbridge Apr 15, 2026
da622bf
start getting agent logic to work better
wasbridge Apr 16, 2026
4a85ca2
The system is really working, its now properly asking the user for in…
wasbridge Apr 16, 2026
4f1391a
cleaning up the visualization engine
wasbridge Apr 16, 2026
72fb54e
use logger instead of console
wasbridge Apr 16, 2026
3b921b2
improved visualization generation
wasbridge Apr 16, 2026
c6e620a
seperate HTTP server and websocket server ports - and make it easy to…
wasbridge Apr 17, 2026
1662047
externalized temp dir
wasbridge Apr 17, 2026
88b6763
sandbox the visualization engine
wasbridge Apr 17, 2026
72aaa52
Prepping for integration with Stella - make core commands a part of t…
wasbridge Apr 17, 2026
25e1a64
Cleanup the Agent when the websocket disconnects
wasbridge Apr 18, 2026
e414af8
make ganos-lal less annoying to listen to
wasbridge Apr 20, 2026
a01e69c
added a stop iteration command and moved the max iteration into the a…
wasbridge Apr 20, 2026
561f0df
remove all show intermediate model commands
wasbridge Apr 20, 2026
ffd9ad8
simplified visualization engine, fixed broken agent configuration, be…
wasbridge Apr 20, 2026
5839f6e
fixed visualization engine not generating PNGs
wasbridge Apr 20, 2026
c78df39
Merge branch 'main' into agentic
wasbridge Apr 20, 2026
5d03b45
Merge branch 'main' into agentic
wasbridge Apr 20, 2026
76da8ca
fixed feedback loop dominance plot code
wasbridge Apr 20, 2026
5dbcd6c
make the agents be markdown files -- increase visualization DPI
wasbridge Apr 21, 2026
77fdb5c
re-expanded the structured output since there is no limit to the depth
wasbridge Apr 21, 2026
0acdfe1
make editing tools that are filesystem based for large models
wasbridge Apr 21, 2026
346d0bc
Support compaction and editing large models, refactor builtin tools
wasbridge Apr 21, 2026
fab9a59
bump the size of models edited with standard tools -- stop truncating…
wasbridge Apr 22, 2026
a502e66
Cleanup and simply code/naming is more accurate
wasbridge Apr 22, 2026
041e79d
fix visualization engine not generating PNGs
wasbridge Apr 22, 2026
9309c44
move LTM specification into agent files
wasbridge Apr 22, 2026
2d520c0
Allow any variable type to be used
wasbridge Apr 22, 2026
a3bc83a
optional config to switch between claude-agent-sdk and our own loop
wasbridge Apr 22, 2026
eccdd94
cleanup tool definitions
wasbridge Apr 22, 2026
52a611d
Allow the AI to request detailed run data for plotting purposes
wasbridge Apr 22, 2026
dd76749
switch to SVG for visualization engine
wasbridge Apr 22, 2026
0790df7
update the documentation for the agent tool
wasbridge Apr 22, 2026
cfeb275
update main readme with a link to the agent readme
wasbridge Apr 22, 2026
dd88768
remove dumb instruction from myrddin
wasbridge Apr 22, 2026
08f91d9
strip dead code -- get specific on feedbackContent formats
wasbridge Apr 22, 2026
42faa09
tell agents they can't edit SFD or CLD layout
wasbridge Apr 22, 2026
07369b3
let ganos-lal be more complex
wasbridge Apr 23, 2026
1cc7cdb
the agent config determines claude sdk or my home rolled loop. ganos…
wasbridge Apr 23, 2026
981b264
fix stop agent call with agent-sdk
wasbridge Apr 23, 2026
b59af11
parallelization command
wasbridge Apr 23, 2026
dff1871
update agent config text to not look like old yaml
wasbridge Apr 23, 2026
bfc3d3a
detect the overloaded error and retry
wasbridge Apr 23, 2026
f6c7da7
remove the recoverable attribute of errors, it wasn't being used
wasbridge Apr 23, 2026
5f9d8ba
Test session compaction with the manual loop
wasbridge Apr 23, 2026
b594421
unit warning system prompt
wasbridge Apr 23, 2026
8e73b65
refactor: tools document what modes and models they support so that t…
wasbridge Apr 24, 2026
826955b
SFD & CLD capitalizations
wasbridge Apr 24, 2026
ccc6079
fixed references in universal instructions
wasbridge Apr 24, 2026
396bd21
cleanup the engine wrapper
wasbridge Apr 24, 2026
f9f821b
update historical message schema
wasbridge Apr 24, 2026
764c8d5
Make sure initial messages are smartly compacted
wasbridge Apr 24, 2026
26d437e
don't give the LLM control over the underlying-llm
wasbridge Apr 24, 2026
40e15a1
always preserve conversation context on switching agents
wasbridge Apr 24, 2026
ae5f14f
dont change the underlying-llm
wasbridge Apr 24, 2026
bfcfc97
tweak prior context tuning
wasbridge Apr 24, 2026
edeb5ee
fixed current message replay bug and removed more agent control over llm
wasbridge Apr 24, 2026
9c13459
make visualization engine have seperate install script
wasbridge Apr 27, 2026
9238acb
clean-up client tools -- get them passed to agent-sdk
wasbridge Apr 27, 2026
bcde0c0
Got Stella client tools working
wasbridge Apr 27, 2026
443927a
fix agent configs to stop needlessly calling load_calibration_data an…
wasbridge Apr 28, 2026
e8483fd
install python dependences for the user, not the system, will stop er…
wasbridge Apr 28, 2026
0a0ef19
windows third party installation system
wasbridge Apr 28, 2026
03b3274
fixed causal chains so that it works on windows too.
wasbridge Apr 28, 2026
231cf30
installing python deps for the user doesn't work
wasbridge Apr 28, 2026
6baed0a
changed defaults to ganos-lal
wasbridge Apr 28, 2026
73535b3
option to skip third party pieces during install
wasbridge Apr 28, 2026
8f13a40
update README
wasbridge Apr 28, 2026
3d5018b
extra logging for visualization engine, and preventing cleanup for te…
wasbridge Apr 28, 2026
407269b
put back the cleanup code
wasbridge Apr 28, 2026
295b41f
don't log messages
wasbridge Apr 28, 2026
649f991
make this far cheaper to run by keeping models and variable data out …
wasbridge Apr 28, 2026
98d1058
switched agent names and added agent roles
wasbridge Apr 28, 2026
97bc1d1
remove stray underscores
wasbridge Apr 28, 2026
6a9796d
be more efficient about loading big stuff into the context and using …
wasbridge Apr 28, 2026
1b045d3
reduce token usage again - fix session compaction for non claude sdk
wasbridge Apr 28, 2026
bf6c91c
fixed ltm narrative tool and model tool switchover sizes
wasbridge Apr 28, 2026
5b2a17a
tell it about the // operator!
wasbridge Apr 28, 2026
b998768
implement smart caching with claude to be cheaper!
wasbridge Apr 28, 2026
b0cdfd1
fixed session summarization tests
wasbridge Apr 28, 2026
b121002
improve visualization engine prompting
wasbridge Apr 29, 2026
8c0135f
Application setup to sandbox with bubblewrap
wasbridge Apr 29, 2026
9495121
build in more critique
wasbridge Apr 29, 2026
0775fb4
take the model out of the LLM context for update model too!
wasbridge Apr 29, 2026
f7f9d02
log way more about bwrap failures, and automatically failover to no b…
wasbridge Apr 29, 2026
678b660
try 2 for dealing with bwrap
wasbridge Apr 29, 2026
ce1e1ea
more sandboxing for linux issues
wasbridge Apr 29, 2026
09284c2
make sure there is always a place to put the socket
wasbridge Apr 29, 2026
5a55cc0
make it possible to switch agents in production?
wasbridge Apr 29, 2026
9956313
unique socket names so we can switch agents painlessly
wasbridge Apr 29, 2026
bdc5a38
leave sandbox cleanup to the spawner
wasbridge Apr 29, 2026
49631d4
if bwrap breaks, don't automatically fallover to unsafe stuff
wasbridge Apr 29, 2026
68640d7
try to snipe SMOOTH builtin out!
wasbridge Apr 29, 2026
d44cffa
deal with overloaded anthropic!
wasbridge Apr 29, 2026
ce480a9
handle missing feedback much more gracefully
wasbridge Apr 30, 2026
42dded0
don't even put blank models in the session
wasbridge Apr 30, 2026
4cac009
fixed edit model tools, and added the auto layout tool
wasbridge Apr 30, 2026
25fb29f
clientId is not required
wasbridge Apr 30, 2026
c04161d
tell seldon to be brief when called internally
wasbridge Apr 30, 2026
3afd9fa
changed the visualization engine to be file based
wasbridge May 1, 2026
8b28982
better parsing of feedback content
wasbridge May 1, 2026
2e05ddb
fixed visualization engine halluncinations
wasbridge May 1, 2026
a0e232a
cleaned up system prompts
wasbridge May 1, 2026
337f827
visualization engine transformation to file fed done?
wasbridge May 1, 2026
0e959e5
have the AI check if a run exists before complaining
wasbridge May 1, 2026
ac4ee9d
improve AI generated plots
wasbridge May 1, 2026
feba448
allow targeted editing with medium models
wasbridge May 1, 2026
c2771da
increase timeout for github
wasbridge May 1, 2026
cb1b46c
hook up seldon derived tools directly to data smarter
wasbridge May 1, 2026
591e7ba
add support for RK4 integration method
wasbridge May 4, 2026
d59021d
fix highlight periods to be keyed off of label, and make sure all leg…
wasbridge May 4, 2026
cbc3216
reduce costs of running this tool by reducing thinking
wasbridge May 4, 2026
222c580
experiment with merlin on my loop
wasbridge May 4, 2026
b04afe8
leave merlin on claude code loop for now
wasbridge May 4, 2026
c3b2d4c
support gemini for socrates and anthropic-sdk for merlin
wasbridge May 5, 2026
5ce0f6e
make merlin less ambitious for doing its own thing, and let it tell t…
wasbridge May 5, 2026
fd8381f
anthropic to low effort
wasbridge May 5, 2026
c8f234a
remove useless parens from system prompts
wasbridge May 5, 2026
3677b08
logging of token usage
wasbridge May 5, 2026
cb60226
Gut the system prompts
wasbridge May 5, 2026
9847031
stop lockup on agent switch -- move both back to anthropic
wasbridge May 5, 2026
9971ab3
fixed anthropic-manual loop
wasbridge May 5, 2026
af465ba
universal instructions
wasbridge May 5, 2026
236751b
don't treat max iterations hit as an error
wasbridge May 6, 2026
6379f2d
make the large model tools much more XMILE friendly... case insensiti…
wasbridge May 6, 2026
3cc4003
agent collect token usage
wasbridge May 6, 2026
a043ca4
update the TokenUsageReporter to work with the engines as well and to…
wasbridge May 6, 2026
25f473a
cleaned up usage reporting
wasbridge May 6, 2026
bcb37ee
added gpt 5.5
wasbridge May 6, 2026
3994b5d
cleanup model list
wasbridge May 6, 2026
23228ed
compute pricing for all api requests
wasbridge May 6, 2026
036d087
clean up logging!
wasbridge May 6, 2026
954e3af
make the edit model section tool be more case sensitive
wasbridge May 6, 2026
a80ce3b
fix duplicate logging
wasbridge May 6, 2026
2e1965a
document token reporting
wasbridge May 6, 2026
741e50a
make sure the client always has the current model before starting!
wasbridge May 6, 2026
4dbbf56
stop bwrap double logging
wasbridge May 6, 2026
649f9b9
fixed missing client ids!
wasbridge May 6, 2026
effb1d7
merlin and socrates for google
wasbridge May 6, 2026
294d46f
fix blank polarity for gemini adk
wasbridge May 6, 2026
a7a0a28
play with cutoffs for tools
wasbridge May 6, 2026
ef02dc9
getPricing always returns something -- and spams the log if it can't …
wasbridge May 6, 2026
e076462
use cheaper 5 min caching.
wasbridge May 6, 2026
73b4984
take away write and edit file directly commands -- nothign good happe…
wasbridge May 6, 2026
f82b4e3
change agent names to include their provider for now
wasbridge May 6, 2026
48be9f9
fix unit test
wasbridge May 6, 2026
2ba33a4
Fixed gemini billing!
wasbridge May 6, 2026
e08cb2a
I am now confident that cached tokens are subtracted from input token…
wasbridge May 6, 2026
ceedb37
organize config.js better
wasbridge May 6, 2026
c8d37c5
silence warning about max listeners
wasbridge May 7, 2026
53e87a2
handle interupting messages better!
wasbridge May 7, 2026
069a432
get rid of documentation tool -- ive never seen it used, and its bett…
wasbridge May 7, 2026
cab843d
allow the LLM to work harder if it thinks the problem is difficult
wasbridge May 7, 2026
ca727c1
remove the test client... I haven't been keeping it up to date
wasbridge May 7, 2026
7ce66dd
force LLM to contend with variable data
wasbridge May 7, 2026
90ae8fd
fix gemini cache timeouts
wasbridge May 7, 2026
11854f6
fixed seldon mentor tool bug!
wasbridge May 7, 2026
59e9727
fixed viz engine LLM Wrapper
wasbridge May 7, 2026
c689666
throw more descriptive error if we fail to write to disk
wasbridge May 7, 2026
8c48021
fixed gemini->anthropic conversion
wasbridge May 7, 2026
8705b96
fix tool content failure
wasbridge May 7, 2026
570a7e9
make the provider be an option, not a property of the agent itself.
wasbridge May 7, 2026
ec18795
remove race condition on setting up bwrap plus if we fail retry 3 tim…
wasbridge May 7, 2026
55ed57a
fixed the agent worker test to match the new API
wasbridge May 7, 2026
25aa0f4
updated readme documentation
wasbridge May 7, 2026
ef2a92b
make errors and unit warnings more prominent
wasbridge May 11, 2026
f8634d9
make a /lock command to take the server offline (for rolling deployme…
wasbridge May 11, 2026
f95ec53
fixed backwards bool!
wasbridge May 11, 2026
f51e041
expose the ports via environment variables
wasbridge May 11, 2026
129c0cf
bob wants lock to always return 200
wasbridge May 11, 2026
c2b9627
rule on embedded constants
wasbridge May 11, 2026
e325156
return 226 when there are sessions
wasbridge May 11, 2026
ed869d9
properly remove the /lock route
wasbridge May 12, 2026
5d1559f
fix session compression of tool calls
wasbridge May 12, 2026
612adbd
allow specification of custom agents by the client
wasbridge May 12, 2026
262b945
use the proper summarization model!
wasbridge May 13, 2026
da6460a
adjust logging
wasbridge May 13, 2026
d780ced
clean up error log
wasbridge May 13, 2026
668fd2a
visualization engine is much better about units!
wasbridge May 13, 2026
6fdc92b
the server sends the current provider when the agent is chosen
wasbridge May 13, 2026
2ba0ac9
log client id with token usage
wasbridge May 13, 2026
d02c2a9
don't log causal chains supportedModes issues
wasbridge May 13, 2026
efa7374
getting things to work on windows
wasbridge May 13, 2026
707b52d
more gemini sanitization of JSON schemas
wasbridge May 13, 2026
999f07b
added pricing for gemini-3.1-flash-preview
wasbridge May 13, 2026
d94e81f
more fixes for windows formatting
wasbridge May 13, 2026
54af048
longer timeout
wasbridge May 13, 2026
cccb9a2
simplify/cleanup agent orchestrator code
wasbridge May 14, 2026
8b28acc
remove legacy junk
wasbridge May 14, 2026
4dad097
use private methods for non-exposed items
wasbridge May 14, 2026
d13b1d0
Add support for queues ovens and conveyors, you opt-in to them in one…
wasbridge May 14, 2026
d3bed8d
make sure we always get an agent complete
wasbridge May 14, 2026
6fbc006
make sure we never double send agent_complete messages
wasbridge May 14, 2026
88305c3
more rules about subtypes
wasbridge May 14, 2026
d47f0e8
cleanup the SubType setup for Stella specific entity types
wasbridge May 14, 2026
b4a1c2e
cleaned up leak fraction prompts
wasbridge May 14, 2026
fccc5d6
give large model tools ability to do advanced sub-types
wasbridge May 15, 2026
a52ed39
remove useless warning
wasbridge May 15, 2026
00bd387
fix error message for large model tools
wasbridge May 15, 2026
ada4d93
remove unused properties
wasbridge May 18, 2026
aee69a0
remove another unused property
wasbridge May 18, 2026
a742c2d
edit model section now uses exactly the same schema as LLMWrapper so …
wasbridge May 18, 2026
c60a844
filter duplicates token logging using a WeakSet
wasbridge May 18, 2026
507ee6d
log potential duplicates
wasbridge May 18, 2026
49ff329
log session tmp dir filesystem issues
wasbridge May 18, 2026
df59a1c
added support for delay converters
wasbridge May 18, 2026
a77ecf5
clean up all resources appropriately
wasbridge May 19, 2026
a96b8b9
catch missing token usage from session summaries
wasbridge May 19, 2026
8918662
found the source of the duplicate SDK and ADK token costs
wasbridge May 19, 2026
35d2b4f
report potential duplicate token usages
wasbridge May 19, 2026
c0b3925
fixed null typo
wasbridge May 19, 2026
0b17132
capture anthropic sdk costs with the singular message at the end unle…
wasbridge May 19, 2026
18e80b2
break the large model tools up to be easier to work with
wasbridge May 19, 2026
d580717
added support for running the BEAMS evals on the agents
wasbridge May 19, 2026
a78b8ea
fixed the agent evals they can run models properly now using pysd
wasbridge May 19, 2026
81da0b7
add support for gemini 3.5 flash
wasbridge May 20, 2026
1b0269d
fix issues in reasoning tests that were making them wrongly difficult
wasbridge May 20, 2026
a20c5a0
test runner reduce data being sent/recieved
wasbridge May 20, 2026
32c4ba1
make it easier for the LLM to keep complex model stuff out of models
wasbridge May 20, 2026
83765a1
the agent eval runner needs to support modules (for tests) and pysd s…
wasbridge May 20, 2026
e505112
properly handle feedback content in the agent eval harness
wasbridge May 20, 2026
98bec7e
potential fix for not writing the model to the session temp dir
wasbridge May 20, 2026
6fb11c3
disallow model.sdjsonn reading by socrates!
wasbridge May 20, 2026
1498aae
run with claude defaults... its more efficient this way on our tasks
wasbridge May 20, 2026
839b79a
update agent instructions with the new tools that help with optimizat…
wasbridge May 21, 2026
4f48ddd
fixed the anthropic manual route with thinking enabled
wasbridge May 21, 2026
4d668a0
another shot at not being able to write model.sdjson
wasbridge May 21, 2026
a2dcd67
each services gets its own portion of the temp dir to manage, and doe…
wasbridge May 21, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 213 additions & 10 deletions README.md

Large diffs are not rendered by default.

1,748 changes: 1,748 additions & 0 deletions agent/AgentOrchestrator.js

Large diffs are not rendered by default.

232 changes: 232 additions & 0 deletions agent/AgentWorker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
/**
* Agent Worker Process
*
* Runs inside a bwrap sandbox on Linux (or unsandboxed on dev platforms).
* Receives IPC messages from the main process, runs AgentOrchestrator, and
* relays all outbound client messages back over IPC.
*
* IPC transport:
* - Sandboxed (bwrap): Unix domain socket at WORKER_IPC_SOCKET, newline-
* delimited JSON. The socket lives in /session so it crosses the sandbox
* boundary without needing --forward-fd.
* - Unsandboxed (fork fallback): standard Node.js process IPC channel.
*
* IPC messages IN (main → worker):
* initialize – session data; must arrive before select_agent
* select_agent – agentId; creates/replaces AgentOrchestrator
* chat – user message; starts an agent conversation
* stop – abort the current agent iteration
* tool_response – callId + result; resolves a pending client tool promise
* model_updated – new client model object
* get_context – requestId; worker replies with current conversation history
* shutdown – clean exit
*
* IPC messages OUT (worker → main):
* to_client – relay to the WebSocket client verbatim
* context_response – reply to get_context
* worker_error – unhandled top-level error
*/

import { AgentOrchestrator } from './AgentOrchestrator.js';
import { SessionManager } from './utilities/SessionManager.js';
import logger from '../utilities/logger.js';
import config from '../config.js';
import { join } from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
import net from 'net';
import { createInterface } from 'readline';

const __dirname = dirname(fileURLToPath(import.meta.url));

const SESSION_ID = process.env.SESSION_ID;
const SESSION_TEMP_DIR = process.env.SESSION_TEMP_DIR;

if (!SESSION_ID || !SESSION_TEMP_DIR) {
process.stderr.write('AgentWorker: SESSION_ID and SESSION_TEMP_DIR must be set\n');
process.exit(1);
}

class AgentWorker {
// Mock WebSocket: SessionManager stores a ws-shaped object, but in the worker
// all real sends go through toClient() which is passed directly to AgentOrchestrator.
#mockWs = { readyState: 1, send: () => {} };

// Worker has its own SessionManager. Cleanup timers are disabled — lifetime is
// managed by the main process which kills this process on disconnect/timeout.
#sessionManager = new SessionManager({ disableCleanup: true });

#orchestrator = null;

// Set on first chat after an agent switch so AgentOrchestrator can bridge context
// from the previous agent into the new session.
#pendingIsAgentSwitch = false;

#conversationRunning = false;

// IPC send function — overridden by #setupSocketIpc when using bwrap sandbox
#sendToMain = (msg) => process.send(msg);

constructor() {
const ipcSocketPath = process.env.WORKER_IPC_SOCKET;
if (ipcSocketPath) {
this.#setupSocketIpc(ipcSocketPath);
} else {
process.on('message', (msg) => this.#handleMessage(msg));
}

process.on('uncaughtException', (err) => {
logger.error(`[worker:${SESSION_ID}] Uncaught exception:`, err);
this.#toMain({ type: 'worker_error', error: err.message });
});

process.on('unhandledRejection', (reason) => {
logger.error(`[worker:${SESSION_ID}] Unhandled rejection:`, reason);
this.#toMain({ type: 'worker_error', error: String(reason) });
});
}

#setupSocketIpc(socketPath) {
const sock = net.createConnection(socketPath);

sock.on('error', (err) => {
logger.error(`[worker:${SESSION_ID}] IPC socket error: ${err.message}`);
process.exit(1);
});

this.#sendToMain = (msg) => {
if (!sock.destroyed) sock.write(JSON.stringify(msg) + '\n');
};

const rl = createInterface({ input: sock, crlfDelay: Infinity });
rl.on('line', (line) => {
if (!line.trim()) return;
try { this.#handleMessage(JSON.parse(line)); }
catch (e) { logger.error(`[worker:${SESSION_ID}] IPC parse error: ${e.message}`); }
});

rl.on('close', () => process.exit(0));
}

#toMain(msg) { this.#sendToMain(msg); }
#toClient(msg) { this.#toMain({ type: 'to_client', message: msg }); }

async #handleMessage(msg) {
try {
switch (msg.type) {

case 'initialize': {
this.#sessionManager.createSessionWithId(SESSION_ID, this.#mockWs, SESSION_TEMP_DIR);
const capabilities = {
supportsArrays: msg.supportsArrays,
supportsModules: msg.supportsModules,
supportsSubTypes: msg.supportsSubTypes,
};
this.#sessionManager.initializeSession(SESSION_ID, msg.mode, msg.model, msg.tools, msg.context, msg.clientId, capabilities);
for (const h of (msg.conversationHistory || [])) {
this.#sessionManager.addToConversationHistory(SESSION_ID, h);
}
this.#pendingIsAgentSwitch = msg.isAgentSwitch ?? false;
break;
}

case 'select_agent': {
const agentConfig = msg.agentConfig !== undefined
? { markdownContent: msg.agentConfig }
: { path: join(__dirname, 'config', `${msg.agentId}.md`) };
const provider = msg.provider ?? config.agentDefaultProvider;
this.#orchestrator = new AgentOrchestrator(this.#sessionManager, SESSION_ID, (m) => this.#toClient(m), agentConfig, provider);
break;
}

case 'chat': {
if (!this.#orchestrator) {
this.#toClient({ type: 'error', sessionId: SESSION_ID, error: 'No agent selected', code: 'NO_AGENT' });
break;
}
if (this.#conversationRunning) {
this.#orchestrator.queueMessage(msg.message);
break;
}
const previousContext = this.#pendingIsAgentSwitch
? this.#sessionManager.getConversationContext(SESSION_ID)
: null;
this.#pendingIsAgentSwitch = false;
this.#conversationRunning = true;
this.#orchestrator.startConversation(msg.message, previousContext)
.finally(() => { this.#conversationRunning = false; });
break;
}

case 'stop': {
this.#orchestrator?.stopIteration();
break;
}

case 'tool_response': {
const { callId, result, isError } = msg;
const session = this.#sessionManager.getSession(SESSION_ID);
if (!session) break;

// Try the standard pending tool calls (DynamicToolProvider)
if (!this.#sessionManager.resolvePendingToolCall(SESSION_ID, callId, result, isError)) {
// Try feedback requests (discussModelWithSeldon, discussModelAcrossRuns, getFeedbackInformation)
if (session.pendingFeedbackRequests?.has(callId)) {
const pending = session.pendingFeedbackRequests.get(callId);
clearTimeout(pending.timeout);
isError ? pending.reject(new Error(typeof result === 'string' ? result : JSON.stringify(result))) : pending.resolve(result);
session.pendingFeedbackRequests.delete(callId);
// Try model requests (clientInteractionTools, generateQuantitativeModel, etc.)
} else if (session.pendingModelRequests?.has(callId)) {
const pending = session.pendingModelRequests.get(callId);
clearTimeout(pending.timeout);
isError ? pending.reject(new Error(typeof result === 'string' ? result : JSON.stringify(result))) : pending.resolve(result);
session.pendingModelRequests.delete(callId);
} else {
logger.warn(`[worker:${SESSION_ID}] Unknown callId in tool_response: ${callId}`);
}
}
break;
}

case 'model_updated': {
this.#sessionManager.updateClientModel(SESSION_ID, msg.model);
break;
}

case 'get_context': {
const context = this.#sessionManager.getConversationContext(SESSION_ID);
this.#toMain({ type: 'context_response', requestId: msg.requestId, context });
break;
}

case 'shutdown': {
// Abort any in-flight conversation so the Agent SDK can clean up
// the claude CLI subprocess it may have spawned.
this.#orchestrator?.stopIteration();
// Kill our entire process group. On the fork fallback (macOS/dev)
// this catches grandchild processes (claude CLI) that would otherwise
// be orphaned at 100% CPU. Inside a bwrap PID namespace this kills
// all container processes. Safe because the fork is spawned with
// detached:true (own process group) and bwrap runs in its own namespace.
if (process.platform !== 'win32') {
try { process.kill(-process.pid, 'SIGKILL'); } catch { /* already exiting */ }
}
// Temp-dir cleanup is the host SessionManager's responsibility.
// Inside the bwrap sandbox /session is a bind mount and can't be
// rmdir'd; in the fork fallback the host also calls deleteSession.
process.exit(0);
break;
}

default:
logger.warn(`[worker:${SESSION_ID}] Unknown IPC message type: ${msg.type}`);
}
} catch (err) {
logger.error(`[worker:${SESSION_ID}] Unhandled error processing ${msg.type}:`, err);
this.#toMain({ type: 'worker_error', error: err.message });
}
}
}

new AgentWorker();
Loading
Loading