From f56d54c180783dc93a6cc871b5bad4e7935e8089 Mon Sep 17 00:00:00 2001 From: Guillaume ARM Date: Thu, 11 Jun 2026 20:53:58 +0200 Subject: [PATCH] fix(ai): extend opencode timeouts --- apis/libai.lua | 4 +-- docs/opencode_server_guide.md | 4 +-- manifest.json | 2 +- packages/index.json | 4 +-- packages/trapos-ai/ccpm.json | 2 +- packages/trapos/ccpm.json | 2 +- programs/ai.lua | 4 +-- tests/ai.lua | 53 +++++++++++++++++++++++++++++++++++ 8 files changed, 64 insertions(+), 11 deletions(-) diff --git a/apis/libai.lua b/apis/libai.lua index 120794d..811eaab 100644 --- a/apis/libai.lua +++ b/apis/libai.lua @@ -1,8 +1,8 @@ local PING_PROMPT = 'reply with exactly: pong'; local DEFAULT_TIMEOUT_SECONDS = 60; -local MAX_TIMEOUT_SECONDS = 60; -local DEFAULT_POLL_TIMEOUT_SECONDS = 300; +local MAX_TIMEOUT_SECONDS = 120; +local DEFAULT_POLL_TIMEOUT_SECONDS = 600; local DEFAULT_POLL_INTERVAL_SECONDS = 2; local DEFAULT_LUA_EXEC_MAX_RETRIES = 2; local DEFAULT_LUA_EXEC_TIMEOUT_SECONDS = 5; diff --git a/docs/opencode_server_guide.md b/docs/opencode_server_guide.md index 1ebd733..85cf6bb 100644 --- a/docs/opencode_server_guide.md +++ b/docs/opencode_server_guide.md @@ -126,8 +126,8 @@ set opencc.model_id claude-opus-4-7 Optional timeout settings: ```sh -set opencc.timeout_seconds 60 -set opencc.poll_timeout_seconds 300 +set opencc.timeout_seconds 120 +set opencc.poll_timeout_seconds 600 set opencc.poll_interval_seconds 2 ``` diff --git a/manifest.json b/manifest.json index 7493b8a..bdd358d 100644 --- a/manifest.json +++ b/manifest.json @@ -1,6 +1,6 @@ { "name": "TrapOS", - "version": "0.8.10", + "version": "0.8.11", "branch": "next", "packages": [ "trapos" diff --git a/packages/index.json b/packages/index.json index a753677..f2f1493 100644 --- a/packages/index.json +++ b/packages/index.json @@ -5,8 +5,8 @@ "trapos-boot": "0.3.2", "trapos-net": "0.3.0", "trapos-ui": "0.2.2", - "trapos-ai": "0.6.8", + "trapos-ai": "0.6.9", "trapos-sandbox": "0.2.1", - "trapos": "0.8.10" + "trapos": "0.8.11" } } diff --git a/packages/trapos-ai/ccpm.json b/packages/trapos-ai/ccpm.json index 709cabd..747684e 100644 --- a/packages/trapos-ai/ccpm.json +++ b/packages/trapos-ai/ccpm.json @@ -1,6 +1,6 @@ { "name": "trapos-ai", - "version": "0.6.8", + "version": "0.6.9", "description": "TrapOS AI client for opencode serve", "dependencies": ["trapos-core"], "files": [ diff --git a/packages/trapos/ccpm.json b/packages/trapos/ccpm.json index 53c5a9d..c8ba8aa 100644 --- a/packages/trapos/ccpm.json +++ b/packages/trapos/ccpm.json @@ -1,6 +1,6 @@ { "name": "trapos", - "version": "0.8.10", + "version": "0.8.11", "description": "TrapOS full install meta-package", "dependencies": [ "trapos-boot", diff --git a/programs/ai.lua b/programs/ai.lua index eeb20e8..162cf24 100644 --- a/programs/ai.lua +++ b/programs/ai.lua @@ -52,8 +52,8 @@ local function printUsage() print(' opencc.agent (e.g. atm10-expert)'); print(' opencc.provider_id (e.g. anthropic)'); print(' opencc.model_id (e.g. claude-opus-4-7)'); - print(' opencc.timeout_seconds (per HTTP call, max 60)'); - print(' opencc.poll_timeout_seconds (default: 300)'); + print(' opencc.timeout_seconds (per HTTP call, max 120)'); + print(' opencc.poll_timeout_seconds (default: 600)'); print(' opencc.poll_interval_seconds (default: 2)'); end diff --git a/tests/ai.lua b/tests/ai.lua index 834e026..b4dc25f 100644 --- a/tests/ai.lua +++ b/tests/ai.lua @@ -812,6 +812,59 @@ testlib.test('ask polling tolerates assistant message without parts', function() testlib.assertEquals(#httpStub.getCalls, 2); 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() local httpStub = fakeHttp( { sessionResp('ses_1'), asyncResp() },