fix(ai): extend opencode timeouts

This commit is contained in:
Guillaume ARM 2026-06-11 20:53:58 +02:00
parent 7d0d69e5b5
commit f56d54c180
8 changed files with 64 additions and 11 deletions

View File

@ -1,8 +1,8 @@
local PING_PROMPT = 'reply with exactly: pong'; local PING_PROMPT = 'reply with exactly: pong';
local DEFAULT_TIMEOUT_SECONDS = 60; local DEFAULT_TIMEOUT_SECONDS = 60;
local MAX_TIMEOUT_SECONDS = 60; local MAX_TIMEOUT_SECONDS = 120;
local DEFAULT_POLL_TIMEOUT_SECONDS = 300; local DEFAULT_POLL_TIMEOUT_SECONDS = 600;
local DEFAULT_POLL_INTERVAL_SECONDS = 2; local DEFAULT_POLL_INTERVAL_SECONDS = 2;
local DEFAULT_LUA_EXEC_MAX_RETRIES = 2; local DEFAULT_LUA_EXEC_MAX_RETRIES = 2;
local DEFAULT_LUA_EXEC_TIMEOUT_SECONDS = 5; local DEFAULT_LUA_EXEC_TIMEOUT_SECONDS = 5;

View File

@ -126,8 +126,8 @@ set opencc.model_id claude-opus-4-7
Optional timeout settings: Optional timeout settings:
```sh ```sh
set opencc.timeout_seconds 60 set opencc.timeout_seconds 120
set opencc.poll_timeout_seconds 300 set opencc.poll_timeout_seconds 600
set opencc.poll_interval_seconds 2 set opencc.poll_interval_seconds 2
``` ```

View File

@ -1,6 +1,6 @@
{ {
"name": "TrapOS", "name": "TrapOS",
"version": "0.8.10", "version": "0.8.11",
"branch": "next", "branch": "next",
"packages": [ "packages": [
"trapos" "trapos"

View File

@ -5,8 +5,8 @@
"trapos-boot": "0.3.2", "trapos-boot": "0.3.2",
"trapos-net": "0.3.0", "trapos-net": "0.3.0",
"trapos-ui": "0.2.2", "trapos-ui": "0.2.2",
"trapos-ai": "0.6.8", "trapos-ai": "0.6.9",
"trapos-sandbox": "0.2.1", "trapos-sandbox": "0.2.1",
"trapos": "0.8.10" "trapos": "0.8.11"
} }
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "trapos-ai", "name": "trapos-ai",
"version": "0.6.8", "version": "0.6.9",
"description": "TrapOS AI client for opencode serve", "description": "TrapOS AI client for opencode serve",
"dependencies": ["trapos-core"], "dependencies": ["trapos-core"],
"files": [ "files": [

View File

@ -1,6 +1,6 @@
{ {
"name": "trapos", "name": "trapos",
"version": "0.8.10", "version": "0.8.11",
"description": "TrapOS full install meta-package", "description": "TrapOS full install meta-package",
"dependencies": [ "dependencies": [
"trapos-boot", "trapos-boot",

View File

@ -52,8 +52,8 @@ local function printUsage()
print(' opencc.agent (e.g. atm10-expert)'); print(' opencc.agent (e.g. atm10-expert)');
print(' opencc.provider_id (e.g. anthropic)'); print(' opencc.provider_id (e.g. anthropic)');
print(' opencc.model_id (e.g. claude-opus-4-7)'); print(' opencc.model_id (e.g. claude-opus-4-7)');
print(' opencc.timeout_seconds (per HTTP call, max 60)'); print(' opencc.timeout_seconds (per HTTP call, max 120)');
print(' opencc.poll_timeout_seconds (default: 300)'); print(' opencc.poll_timeout_seconds (default: 600)');
print(' opencc.poll_interval_seconds (default: 2)'); print(' opencc.poll_interval_seconds (default: 2)');
end end

View File

@ -812,6 +812,59 @@ testlib.test('ask polling tolerates assistant message without parts', function()
testlib.assertEquals(#httpStub.getCalls, 2); testlib.assertEquals(#httpStub.getCalls, 2);
end); end);
testlib.test('ask polling default timeout allows ten minute replies', function()
local httpStub = fakeHttp(
{ sessionResp('ses_1'), asyncResp() },
{
messageListResp({ userMessage('msg_1', 'hello'), assistantMessage('msg_2', 'partial', false) }),
messageListResp({ userMessage('msg_1', 'hello'), assistantMessage('msg_2', 'partial', false) }),
messageListResp({ userMessage('msg_1', 'hello'), assistantMessage('msg_2', 'reply', true) }),
}
);
local settingsStub = fakeAsyncSettings();
local now = 0;
local elFactory = fakeEventloopFactory();
local advancingFactory = function()
local loop = elFactory();
local origSet = loop.setTimeout;
loop.setTimeout = function(fn, delay)
now = now + (delay or 0);
return origSet(fn, delay);
end
return loop;
end;
local ai = createAi({
http = httpStub,
settings = settingsStub,
now = function() return now; end,
eventloop = advancingFactory,
});
local ok, result = ai.ask('hello', { messageId = 'msg_1', pollIntervalSeconds = 300 });
testlib.assertTrue(ok, tostring(result));
testlib.assertEquals(result.reply, 'reply');
testlib.assertEquals(#httpStub.getCalls, 3);
end);
testlib.test('ask caps per-call HTTP timeout at two minutes', function()
local httpStub = fakeHttp(
{ sessionResp('ses_1'), messageResp('reply') },
{}
);
local settingsStub = fakeSettings({
['opencc.server_url'] = 'http://host',
['opencc.timeout_seconds'] = 500,
});
local ai = createAi({ http = httpStub, settings = settingsStub });
local ok = ai.ask('hello');
testlib.assertTrue(ok);
testlib.assertEquals(httpStub.postCalls[1].timeout, 120);
testlib.assertEquals(httpStub.postCalls[2].timeout, 120);
end);
testlib.test('ask polling times out', function() testlib.test('ask polling times out', function()
local httpStub = fakeHttp( local httpStub = fakeHttp(
{ sessionResp('ses_1'), asyncResp() }, { sessionResp('ses_1'), asyncResp() },