pikiloom 0.4.26 → 0.4.27
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/dashboard/dist/assets/{AgentTab-BNJ73P0m.js → AgentTab-DIP-y4dl.js} +1 -1
- package/dashboard/dist/assets/ConnectionModal-BCfvhkiI.js +1 -0
- package/dashboard/dist/assets/{DirBrowser-D-GT-G-w.js → DirBrowser-Dot7ua9-.js} +1 -1
- package/dashboard/dist/assets/{ExtensionsTab-BrJMulJR.js → ExtensionsTab-GioMx4S6.js} +1 -1
- package/dashboard/dist/assets/{IMAccessTab-auPnx468.js → IMAccessTab-C9_r8jJP.js} +1 -1
- package/dashboard/dist/assets/{Modal-lYfO9m-I.js → Modal-M1AP1sgR.js} +1 -1
- package/dashboard/dist/assets/{Modals-PRdWOIY9.js → Modals-CCm3UUfJ.js} +1 -1
- package/dashboard/dist/assets/{Select-BhbU-rll.js → Select-YubDM16P.js} +1 -1
- package/dashboard/dist/assets/{SessionPanel-_0dLWvEb.js → SessionPanel-Cnv9o96n.js} +1 -1
- package/dashboard/dist/assets/SystemTab-VgNivIe3.js +1 -0
- package/dashboard/dist/assets/index-BY7l20bi.js +23 -0
- package/dashboard/dist/assets/index-BlqvzDUL.js +3 -0
- package/dashboard/dist/assets/index-CXIN3nTr.css +1 -0
- package/dashboard/dist/assets/{shared-C5uXvhZJ.js → shared-C0SAInnT.js} +1 -1
- package/dashboard/dist/index.html +2 -2
- package/dist/agent/acp-client.js +0 -59
- package/dist/agent/artifacts.js +1 -38
- package/dist/agent/auto-update.js +2 -78
- package/dist/agent/await-resume.js +0 -20
- package/dist/agent/cli/auth.js +3 -51
- package/dist/agent/cli/catalog.js +0 -3
- package/dist/agent/cli/detector.js +1 -19
- package/dist/agent/cli/index.js +0 -3
- package/dist/agent/cli/registry.js +0 -25
- package/dist/agent/driver.js +0 -14
- package/dist/agent/drivers/claude-tui.js +2 -769
- package/dist/agent/drivers/claude.js +12 -631
- package/dist/agent/drivers/codex.js +11 -162
- package/dist/agent/drivers/gemini.js +6 -114
- package/dist/agent/drivers/hermes.js +0 -128
- package/dist/agent/goal.js +0 -45
- package/dist/agent/handover.js +1 -46
- package/dist/agent/images.js +7 -133
- package/dist/agent/index.js +1 -29
- package/dist/agent/mcp/bridge.js +1 -197
- package/dist/agent/mcp/extensions.js +5 -84
- package/dist/agent/mcp/oauth.js +2 -69
- package/dist/agent/mcp/registry.js +2 -33
- package/dist/agent/mcp/session-server.js +2 -45
- package/dist/agent/mcp/tools/ask-user.js +0 -6
- package/dist/agent/mcp/tools/await-resume.js +0 -15
- package/dist/agent/mcp/tools/goal.js +0 -25
- package/dist/agent/mcp/tools/types.js +0 -5
- package/dist/agent/mcp/tools/workspace.js +0 -23
- package/dist/agent/npm.js +0 -14
- package/dist/agent/session.js +86 -196
- package/dist/agent/skill-installer.js +3 -70
- package/dist/agent/skills.js +0 -43
- package/dist/agent/stream.js +5 -148
- package/dist/agent/types.js +0 -12
- package/dist/agent/utils.js +2 -120
- package/dist/bot/bot.js +3 -468
- package/dist/bot/command-ui.js +0 -45
- package/dist/bot/commands.js +0 -51
- package/dist/bot/headless-bot.js +0 -21
- package/dist/bot/host.js +1 -5
- package/dist/bot/human-loop.js +0 -8
- package/dist/bot/menu.js +0 -3
- package/dist/bot/orchestration.js +0 -3
- package/dist/bot/render-shared.js +0 -63
- package/dist/bot/session-hub.js +14 -92
- package/dist/bot/session-status.js +1 -5
- package/dist/bot/streaming.js +0 -53
- package/dist/browser-profile.js +0 -51
- package/dist/browser-supervisor.js +0 -75
- package/dist/catalog/cli-tools.js +0 -53
- package/dist/catalog/index.js +0 -18
- package/dist/catalog/local-models.js +0 -18
- package/dist/catalog/mcp-servers.js +0 -35
- package/dist/catalog/skill-repos.js +0 -32
- package/dist/channels/base.js +0 -19
- package/dist/channels/dingtalk/bot.js +0 -3
- package/dist/channels/dingtalk/channel.js +0 -33
- package/dist/channels/discord/bot.js +0 -7
- package/dist/channels/discord/channel.js +0 -22
- package/dist/channels/feishu/bot.js +0 -71
- package/dist/channels/feishu/channel.js +0 -78
- package/dist/channels/feishu/markdown.js +0 -5
- package/dist/channels/feishu/render.js +0 -45
- package/dist/channels/health.js +0 -46
- package/dist/channels/slack/bot.js +0 -7
- package/dist/channels/slack/channel.js +1 -27
- package/dist/channels/states.js +0 -3
- package/dist/channels/telegram/bot.js +0 -60
- package/dist/channels/telegram/channel.js +2 -99
- package/dist/channels/telegram/directory.js +0 -3
- package/dist/channels/telegram/live-preview.js +0 -8
- package/dist/channels/telegram/render.js +0 -30
- package/dist/channels/wecom/bot.js +0 -3
- package/dist/channels/wecom/channel.js +0 -58
- package/dist/channels/weixin/api.js +0 -9
- package/dist/channels/weixin/bot.js +0 -88
- package/dist/channels/weixin/channel.js +0 -6
- package/dist/cli/autostart.js +1 -44
- package/dist/cli/channel-supervisor.js +1 -59
- package/dist/cli/channels.js +0 -6
- package/dist/cli/main.js +1 -145
- package/dist/cli/onboarding.js +0 -6
- package/dist/cli/run.js +0 -11
- package/dist/cli/setup-wizard.js +0 -3
- package/dist/core/config/runtime-config.js +0 -38
- package/dist/core/config/user-config.js +0 -63
- package/dist/core/config/validation.js +0 -9
- package/dist/core/constants.js +0 -268
- package/dist/core/git.js +0 -31
- package/dist/core/legacy-compat.js +1 -28
- package/dist/core/logging.js +0 -3
- package/dist/core/platform.js +0 -28
- package/dist/core/process-control.js +0 -8
- package/dist/core/secrets/index.js +0 -17
- package/dist/core/secrets/inline-seal.js +0 -7
- package/dist/core/secrets/ref.js +0 -19
- package/dist/core/secrets/resolver.js +0 -8
- package/dist/core/secrets/store.js +1 -12
- package/dist/core/utils.js +1 -37
- package/dist/core/version.js +0 -3
- package/dist/dashboard/platform.js +1 -35
- package/dist/dashboard/routes/agents.js +2 -71
- package/dist/dashboard/routes/cli.js +0 -27
- package/dist/dashboard/routes/config.js +0 -54
- package/dist/dashboard/routes/extensions.js +0 -132
- package/dist/dashboard/routes/local-models.js +0 -68
- package/dist/dashboard/routes/models.js +0 -46
- package/dist/dashboard/routes/sessions.js +0 -100
- package/dist/dashboard/runtime.js +1 -58
- package/dist/dashboard/server.js +0 -49
- package/dist/dashboard/session-control.js +2 -69
- package/dist/model/catalog.js +1 -17
- package/dist/model/index.js +0 -15
- package/dist/model/injector.js +1 -181
- package/dist/model/provider-models.js +1 -48
- package/dist/model/responses-bridge.js +3 -45
- package/dist/model/store.js +0 -17
- package/dist/model/types.js +0 -12
- package/dist/model/validation.js +1 -18
- package/dist/pikichannel/adapter-pikiloom.js +0 -31
- package/dist/pikichannel/code.js +0 -12
- package/dist/pikichannel/codec.js +0 -14
- package/dist/pikichannel/host.js +4 -33
- package/dist/pikichannel/protocol.js +0 -52
- package/dist/pikichannel/rendezvous-broker.js +5 -26
- package/dist/pikichannel/rendezvous-host.js +3 -16
- package/dist/pikichannel/server.js +6 -55
- package/dist/pikichannel/transport.js +0 -25
- package/dist/pikichannel/transports/webrtc-host.js +0 -18
- package/dist/pikichannel/transports/webrtc-shared.js +4 -34
- package/dist/pikichannel/transports/websocket-host.js +1 -14
- package/dist/pikichannel/turn.js +2 -69
- package/dist/pikichannel/web/sdk.js +14 -71
- package/package.json +1 -1
- package/dashboard/dist/assets/ConnectionModal-Dt05H2f9.js +0 -1
- package/dashboard/dist/assets/SystemTab-CN_QrRKt.js +0 -1
- package/dashboard/dist/assets/index-CP3LYJR2.js +0 -23
- package/dashboard/dist/assets/index-C_neLnaO.js +0 -3
- package/dashboard/dist/assets/index-CyCspgtc.css +0 -1
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Persistent user configuration (~/.pikiloom/setting.json) load/save/sync.
|
|
3
|
-
*/
|
|
4
1
|
import fs from 'node:fs';
|
|
5
2
|
import os from 'node:os';
|
|
6
3
|
import path from 'node:path';
|
|
@@ -26,23 +23,10 @@ const MANAGED_ENV_KEYS = [
|
|
|
26
23
|
'WECOM_BOT_SECRET',
|
|
27
24
|
'WECOM_ENDPOINT',
|
|
28
25
|
];
|
|
29
|
-
// Snapshot env vars present at module load — these were set externally by the
|
|
30
|
-
// process launcher (docker `-e`, shell `export`, systemd unit, ...) and reflect
|
|
31
|
-
// the operator's intent. `applyUserConfig` with `clearMissing` must never
|
|
32
|
-
// delete them, even if setting.json is silent on the same key. Without this,
|
|
33
|
-
// `docker run -e TELEGRAM_BOT_TOKEN=...` would survive only until the first
|
|
34
|
-
// config sync tick, at which point the token gets wiped from the environment.
|
|
35
26
|
const EXTERNAL_ENV_PRESET = new Set(MANAGED_ENV_KEYS.filter(key => {
|
|
36
27
|
const value = process.env[key];
|
|
37
28
|
return typeof value === 'string' && value.trim() !== '';
|
|
38
29
|
}));
|
|
39
|
-
/**
|
|
40
|
-
* Channel-credential env vars that should hydrate a missing setting.json value
|
|
41
|
-
* back into the in-memory config. Display surfaces (dashboard channel cards,
|
|
42
|
-
* setup wizard) and channel resolution all read `config.telegramBotToken`-style
|
|
43
|
-
* fields, so if the operator only provided env vars (the docker default) the
|
|
44
|
-
* UI would otherwise show "not configured" even though the bot works fine.
|
|
45
|
-
*/
|
|
46
30
|
const ENV_TO_CONFIG_KEY = [
|
|
47
31
|
['telegramBotToken', 'TELEGRAM_BOT_TOKEN'],
|
|
48
32
|
['telegramAllowedChatIds', 'TELEGRAM_ALLOWED_CHAT_IDS'],
|
|
@@ -60,14 +44,6 @@ const ENV_TO_CONFIG_KEY = [
|
|
|
60
44
|
['wecomBotSecret', 'WECOM_BOT_SECRET'],
|
|
61
45
|
['wecomEndpoint', 'WECOM_ENDPOINT'],
|
|
62
46
|
];
|
|
63
|
-
/**
|
|
64
|
-
* Return a copy of `config` with channel credential fields hydrated from
|
|
65
|
-
* matching env vars when the setting.json value is empty. The returned object
|
|
66
|
-
* must NOT be used as input to `saveUserConfig` — that would persist env-only
|
|
67
|
-
* values into setting.json, which would defeat the purpose of running with
|
|
68
|
-
* `-e TELEGRAM_BOT_TOKEN=...` (the operator wants the env var to remain the
|
|
69
|
-
* source of truth across container restarts).
|
|
70
|
-
*/
|
|
71
47
|
export function applyChannelEnvFallback(config) {
|
|
72
48
|
let next = null;
|
|
73
49
|
for (const [key, envName] of ENV_TO_CONFIG_KEY) {
|
|
@@ -86,13 +62,6 @@ export function applyChannelEnvFallback(config) {
|
|
|
86
62
|
const USER_CONFIG_DIRNAME = STATE_DIR_NAME;
|
|
87
63
|
const USER_CONFIG_FILENAME = 'setting.json';
|
|
88
64
|
let activeUserConfig = {};
|
|
89
|
-
// Parsed-config cache keyed by setting.json identity (path + mtime + size).
|
|
90
|
-
// loadUserConfig() is hit from ~60 call sites — several times per HTTP request and
|
|
91
|
-
// per agent stream (the MCP bridge resolves GUI config + per-extension OAuth) — so
|
|
92
|
-
// re-reading + JSON.parse + normalize on every call is pure waste. A cache hit costs
|
|
93
|
-
// one statSync (~100x cheaper). saveUserConfig refreshes this entry so writes are
|
|
94
|
-
// visible immediately regardless of mtime granularity. Callers treat the result as
|
|
95
|
-
// read-only and spread to mutate (the same contract getActiveUserConfig already uses).
|
|
96
65
|
let userConfigCache = null;
|
|
97
66
|
const userConfigListeners = new Set();
|
|
98
67
|
let userConfigSyncTimer = null;
|
|
@@ -100,7 +69,6 @@ let userConfigSyncRefCount = 0;
|
|
|
100
69
|
let userConfigSyncRaw = '';
|
|
101
70
|
let userConfigSyncOverrides = {};
|
|
102
71
|
const expandHomeDir = expandTilde;
|
|
103
|
-
/** Normalize workspace entries — resolve paths, deduplicate, sort by order. */
|
|
104
72
|
function normalizeWorkspaces(raw) {
|
|
105
73
|
if (!Array.isArray(raw))
|
|
106
74
|
return [];
|
|
@@ -133,10 +101,6 @@ function normalizeWorkspaces(raw) {
|
|
|
133
101
|
entries.sort((a, b) => (a.order ?? 999) - (b.order ?? 999));
|
|
134
102
|
return entries;
|
|
135
103
|
}
|
|
136
|
-
/**
|
|
137
|
-
* Single canonical config path: ~/.pikiloom/setting.json
|
|
138
|
-
* Both CLI and dashboard read/write this file exclusively.
|
|
139
|
-
*/
|
|
140
104
|
export function getDevUserConfigPath() {
|
|
141
105
|
return path.join(os.homedir(), USER_CONFIG_DIRNAME, 'dev', USER_CONFIG_FILENAME);
|
|
142
106
|
}
|
|
@@ -306,10 +270,6 @@ export function applyUserConfig(config, _channel, options = {}) {
|
|
|
306
270
|
const next = managed[key];
|
|
307
271
|
const prev = process.env[key] ?? '';
|
|
308
272
|
if (!next) {
|
|
309
|
-
// Never clobber an env var the launcher set externally — that's the
|
|
310
|
-
// `docker run -e ...` / `export FOO=...` contract. We only clear keys we
|
|
311
|
-
// know were written by a previous `applyUserConfig` (i.e. *not* in the
|
|
312
|
-
// boot-time snapshot).
|
|
313
273
|
if (clearMissing && key in process.env && !EXTERNAL_ENV_PRESET.has(key)) {
|
|
314
274
|
delete process.env[key];
|
|
315
275
|
changedKeys.push(key);
|
|
@@ -334,9 +294,6 @@ export function setUserWorkdir(workdir, options = {}) {
|
|
|
334
294
|
const resolvedWorkdir = resolveUserWorkdir({ workdir });
|
|
335
295
|
const config = normalizeUserConfig({ ...loadUserConfig(), workdir: resolvedWorkdir });
|
|
336
296
|
const configPath = saveUserConfig(config);
|
|
337
|
-
// Don't pin workdir into userConfigSyncOverrides: the periodic sync reads
|
|
338
|
-
// setting.json fresh each tick, so an external `npx pikiloom@latest` that
|
|
339
|
-
// updates the file should be honored, not clobbered by an in-memory lock.
|
|
340
297
|
applyUserConfig(config, undefined, { overwrite: true, clearMissing: true, notify: options.notify ?? true });
|
|
341
298
|
return { configPath, workdir: resolvedWorkdir, config };
|
|
342
299
|
}
|
|
@@ -370,18 +327,10 @@ export function startUserConfigSync(options = {}) {
|
|
|
370
327
|
userConfigSyncOverrides = {};
|
|
371
328
|
};
|
|
372
329
|
}
|
|
373
|
-
// ---------------------------------------------------------------------------
|
|
374
|
-
// Known chat persistence
|
|
375
|
-
// ---------------------------------------------------------------------------
|
|
376
330
|
const KNOWN_CHAT_CONFIG_KEY = {
|
|
377
331
|
feishu: 'feishuKnownChatIds',
|
|
378
332
|
telegram: 'telegramKnownChatIds',
|
|
379
333
|
};
|
|
380
|
-
/**
|
|
381
|
-
* Append `chatId` to the persisted known-chat list for `channelType` if it
|
|
382
|
-
* isn't already there. The list survives crashes (env-based hand-off does
|
|
383
|
-
* not) so `sendStartupNotice` can greet known chats after any restart path.
|
|
384
|
-
*/
|
|
385
334
|
export function recordKnownChatId(channelType, chatId) {
|
|
386
335
|
const id = String(chatId ?? '').trim();
|
|
387
336
|
if (!id)
|
|
@@ -397,7 +346,6 @@ export function recordKnownChatId(channelType, chatId) {
|
|
|
397
346
|
}
|
|
398
347
|
catch { }
|
|
399
348
|
}
|
|
400
|
-
/** Load the persisted known-chat list for a channel. */
|
|
401
349
|
export function loadKnownChatIds(channelType) {
|
|
402
350
|
const key = KNOWN_CHAT_CONFIG_KEY[channelType];
|
|
403
351
|
const config = loadUserConfig();
|
|
@@ -406,15 +354,10 @@ export function loadKnownChatIds(channelType) {
|
|
|
406
354
|
? list.map(v => String(v ?? '').trim()).filter(Boolean)
|
|
407
355
|
: [];
|
|
408
356
|
}
|
|
409
|
-
// ---------------------------------------------------------------------------
|
|
410
|
-
// Workspace registry
|
|
411
|
-
// ---------------------------------------------------------------------------
|
|
412
|
-
/** Load registered workspaces from config. Returns empty array if none. */
|
|
413
357
|
export function loadWorkspaces() {
|
|
414
358
|
const config = loadUserConfig();
|
|
415
359
|
return normalizeWorkspaces(config.workspaces);
|
|
416
360
|
}
|
|
417
|
-
/** Add a workspace. Returns the new entry. Deduplicates by resolved path. */
|
|
418
361
|
export function addWorkspace(workspacePath, name) {
|
|
419
362
|
const resolved = path.resolve(expandHomeDir(workspacePath));
|
|
420
363
|
const config = loadUserConfig();
|
|
@@ -436,7 +379,6 @@ export function addWorkspace(workspacePath, name) {
|
|
|
436
379
|
saveUserConfig({ ...config, workspaces });
|
|
437
380
|
return entry;
|
|
438
381
|
}
|
|
439
|
-
/** Remove a workspace by path. Returns true if removed. */
|
|
440
382
|
export function removeWorkspace(workspacePath) {
|
|
441
383
|
const resolved = path.resolve(expandHomeDir(workspacePath));
|
|
442
384
|
const config = loadUserConfig();
|
|
@@ -448,7 +390,6 @@ export function removeWorkspace(workspacePath) {
|
|
|
448
390
|
saveUserConfig({ ...config, workspaces: filtered });
|
|
449
391
|
return true;
|
|
450
392
|
}
|
|
451
|
-
/** Rename a workspace. Returns the updated entry or null if not found. */
|
|
452
393
|
export function renameWorkspace(workspacePath, newName) {
|
|
453
394
|
const resolved = path.resolve(expandHomeDir(workspacePath));
|
|
454
395
|
const config = loadUserConfig();
|
|
@@ -460,7 +401,6 @@ export function renameWorkspace(workspacePath, newName) {
|
|
|
460
401
|
saveUserConfig({ ...config, workspaces });
|
|
461
402
|
return entry;
|
|
462
403
|
}
|
|
463
|
-
/** Reorder workspaces by providing paths in desired order. */
|
|
464
404
|
export function reorderWorkspaces(orderedPaths) {
|
|
465
405
|
const config = loadUserConfig();
|
|
466
406
|
const workspaces = normalizeWorkspaces(config.workspaces);
|
|
@@ -476,7 +416,6 @@ export function reorderWorkspaces(orderedPaths) {
|
|
|
476
416
|
seen.add(resolved);
|
|
477
417
|
}
|
|
478
418
|
}
|
|
479
|
-
// Append any workspaces not in the ordered list
|
|
480
419
|
for (const entry of workspaces) {
|
|
481
420
|
if (!seen.has(entry.path)) {
|
|
482
421
|
entry.order = reordered.length;
|
|
@@ -486,7 +425,6 @@ export function reorderWorkspaces(orderedPaths) {
|
|
|
486
425
|
saveUserConfig({ ...config, workspaces: reordered });
|
|
487
426
|
return reordered;
|
|
488
427
|
}
|
|
489
|
-
/** Update workspace preferences (preferredAgent, etc.) */
|
|
490
428
|
export function updateWorkspace(workspacePath, patch) {
|
|
491
429
|
const resolved = path.resolve(expandHomeDir(workspacePath));
|
|
492
430
|
const config = loadUserConfig();
|
|
@@ -503,7 +441,6 @@ export function updateWorkspace(workspacePath, patch) {
|
|
|
503
441
|
saveUserConfig({ ...config, workspaces });
|
|
504
442
|
return entry;
|
|
505
443
|
}
|
|
506
|
-
/** Find a workspace entry by path. */
|
|
507
444
|
export function findWorkspace(workspacePath) {
|
|
508
445
|
const resolved = path.resolve(expandHomeDir(workspacePath));
|
|
509
446
|
return loadWorkspaces().find(w => w.path === resolved) || null;
|
|
@@ -1,6 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Channel credential validation for Telegram, Feishu, and WeChat.
|
|
3
|
-
*/
|
|
4
1
|
import * as lark from '@larksuiteoapi/node-sdk';
|
|
5
2
|
import { validateTelegramToken } from '../../cli/setup-wizard.js';
|
|
6
3
|
import { VALIDATION_TIMEOUTS } from '../constants.js';
|
|
@@ -220,7 +217,6 @@ export async function validateFeishuConfig(appId, appSecret, options = {}) {
|
|
|
220
217
|
app: null,
|
|
221
218
|
};
|
|
222
219
|
}
|
|
223
|
-
// Try to fetch bot display name using the tenant access token
|
|
224
220
|
let botDisplayName = null;
|
|
225
221
|
try {
|
|
226
222
|
const botResp = await withTimeout(fetch(`${apiDomain}/open-apis/bot/v3/info`, {
|
|
@@ -232,7 +228,6 @@ export async function validateFeishuConfig(appId, appSecret, options = {}) {
|
|
|
232
228
|
}
|
|
233
229
|
}
|
|
234
230
|
catch {
|
|
235
|
-
// Non-critical — proceed without bot name
|
|
236
231
|
}
|
|
237
232
|
const app = { appId: trimmedAppId, displayName: botDisplayName };
|
|
238
233
|
const identity = botDisplayName
|
|
@@ -490,10 +485,6 @@ export async function validateWecomConfig(botId, botSecret, _options = {}) {
|
|
|
490
485
|
bot: null,
|
|
491
486
|
};
|
|
492
487
|
}
|
|
493
|
-
// The Smart Bot WS endpoint cannot be probed via a simple HTTP request;
|
|
494
|
-
// we accept the configured credentials and let the websocket subscribe ack
|
|
495
|
-
// surface real auth errors at runtime. A non-empty pair already covers the
|
|
496
|
-
// most common configuration mistake.
|
|
497
488
|
return {
|
|
498
489
|
state: readyChannelState('wecom', `WeChat Work bot ${trimmedId} configured.`),
|
|
499
490
|
bot: { botId: trimmedId },
|
package/dist/core/constants.js
CHANGED
|
@@ -1,408 +1,140 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* constants.ts — Centralized timeout, retry, and numeric constants.
|
|
3
|
-
*
|
|
4
|
-
* Grouped by domain / module so each subsystem can import only the
|
|
5
|
-
* bucket it needs.
|
|
6
|
-
*/
|
|
7
1
|
import path from 'node:path';
|
|
8
|
-
// ---------------------------------------------------------------------------
|
|
9
|
-
// MCP bridge
|
|
10
|
-
// ---------------------------------------------------------------------------
|
|
11
|
-
/** Timeouts for the per-stream MCP callback server and tool operations. */
|
|
12
2
|
export const MCP_TIMEOUTS = {
|
|
13
|
-
/** Max time to wait for the sendFile callback to complete. */
|
|
14
3
|
sendFile: 60_000,
|
|
15
|
-
/** Max time to receive the HTTP request body on the callback server. */
|
|
16
4
|
requestBody: 10_000,
|
|
17
|
-
/** Server-level: max time for an entire request lifecycle. */
|
|
18
5
|
serverRequest: 90_000,
|
|
19
|
-
/** Server-level: max time to receive request headers. */
|
|
20
6
|
serverHeaders: 10_000,
|
|
21
|
-
/** Timeout for `codex mcp add` registration commands. */
|
|
22
7
|
codexMcpAdd: 10_000,
|
|
23
|
-
/** Timeout for `codex mcp remove` cleanup commands. */
|
|
24
8
|
codexMcpRemove: 5_000,
|
|
25
9
|
};
|
|
26
|
-
/** Maximum artifact file size the MCP bridge will accept (20 MB). */
|
|
27
10
|
export const MCP_ARTIFACT_MAX_BYTES = 20 * 1024 * 1024;
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
// Dashboard
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
/** Timeouts used by the dashboard HTTP server and its status endpoints. */
|
|
32
11
|
export const DASHBOARD_TIMEOUTS = {
|
|
33
|
-
/** Timeout for agent model discovery (Codex cold-start can be slow). */
|
|
34
12
|
agentStatusModels: 4_000,
|
|
35
|
-
/** Timeout for agent usage data fetch. */
|
|
36
13
|
agentStatusUsage: 1_500,
|
|
37
|
-
/** Timeout for channel credential validation requests. */
|
|
38
14
|
channelStatusValidation: 3_000,
|
|
39
|
-
/** How long validated channel states are cached before re-checking. */
|
|
40
15
|
channelStatusCacheTtl: 20_000,
|
|
41
|
-
/** How long the full agent-status response is cached (SWR). */
|
|
42
16
|
agentStatusCacheTtl: 30_000,
|
|
43
|
-
/** Timeout for agent npm install via the dashboard. */
|
|
44
17
|
agentInstall: 10 * 60_000,
|
|
45
|
-
/** Default timeout for dashboard-spawned shell commands. */
|
|
46
18
|
runCommand: 30_000,
|
|
47
19
|
};
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
// Browser automation
|
|
50
|
-
// ---------------------------------------------------------------------------
|
|
51
|
-
// ---------------------------------------------------------------------------
|
|
52
|
-
// Brand / state-dir / env identifiers — single source of truth
|
|
53
|
-
// ---------------------------------------------------------------------------
|
|
54
|
-
/** Home state directory name: `~/.pikiloom`. */
|
|
55
20
|
export const STATE_DIR_NAME = '.pikiloom';
|
|
56
|
-
/** Env var prefix for all pikiloom-specific variables. */
|
|
57
21
|
export const ENV_PREFIX = 'PIKILOOM_';
|
|
58
|
-
/**
|
|
59
|
-
* Pre-rename identifier (`pikiclaw`). Kept ONLY for the one-time state-dir
|
|
60
|
-
* migration, the env-var fallback (see core/legacy-compat.ts) and project-skill
|
|
61
|
-
* discovery, so the real pikiclaw install base is never orphaned. Kept as lists
|
|
62
|
-
* so a future rename only appends one entry. Drop a couple releases later.
|
|
63
|
-
*/
|
|
64
22
|
export const LEGACY_STATE_DIR_NAMES = ['.pikiclaw'];
|
|
65
23
|
export const LEGACY_ENV_PREFIXES = ['PIKICLAW_'];
|
|
66
|
-
/**
|
|
67
|
-
* Stable relative path for the managed Chrome profile under the home directory.
|
|
68
|
-
* Keep this outside config-specific directories so `npm run dev` and the main
|
|
69
|
-
* runtime share the same browser login state.
|
|
70
|
-
*/
|
|
71
24
|
export const MANAGED_BROWSER_PROFILE_SUBPATH = path.join(STATE_DIR_NAME, 'browser', 'chrome-profile');
|
|
72
|
-
/** Base Playwright MCP args for the managed browser integration. */
|
|
73
25
|
export const PLAYWRIGHT_MCP_PACKAGE_NAME = '@playwright/mcp';
|
|
74
26
|
export const PLAYWRIGHT_MCP_PACKAGE_VERSION = '0.0.75';
|
|
75
27
|
export const PLAYWRIGHT_MCP_PACKAGE_SPEC = `${PLAYWRIGHT_MCP_PACKAGE_NAME}@${PLAYWRIGHT_MCP_PACKAGE_VERSION}`;
|
|
76
28
|
export const PLAYWRIGHT_MCP_BROWSER_ARGS = ['--browser', 'chrome', '--viewport-size', '1920x1080'];
|
|
77
|
-
/**
|
|
78
|
-
* Env var name for pointing pikiloom at an external Chrome DevTools Protocol
|
|
79
|
-
* endpoint (e.g. `http://chromium:9222`) instead of launching a local Chrome.
|
|
80
|
-
* Primary use cases: Docker deployments that run a sidecar like
|
|
81
|
-
* `lscr.io/linuxserver/chromium`, or attaching to a remote browser the user
|
|
82
|
-
* already manages. When set, browser-supervisor skips every local-launch
|
|
83
|
-
* codepath (no Chrome detection, no pid SIGKILL on restart) and pipes the URL
|
|
84
|
-
* through to Playwright MCP's `--cdp-endpoint`.
|
|
85
|
-
*/
|
|
86
29
|
export const PIKILOOM_BROWSER_CDP_URL_ENV = 'PIKILOOM_BROWSER_CDP_URL';
|
|
87
|
-
/** Dashboard session pagination limits. */
|
|
88
30
|
export const DASHBOARD_PAGINATION = {
|
|
89
31
|
defaultPageSize: 6,
|
|
90
32
|
maxPageSize: 30,
|
|
91
33
|
};
|
|
92
|
-
/** Timeouts for macOS permission checks and JXA scripts (dashboard). */
|
|
93
34
|
export const DASHBOARD_PERMISSION_TIMEOUTS = {
|
|
94
|
-
/** Default timeout for osascript / JXA calls. */
|
|
95
35
|
jxaDefault: 5_000,
|
|
96
|
-
/** Timeout for screencapture permission probe. */
|
|
97
36
|
screenRecordingProbe: 5_000,
|
|
98
|
-
/** Timeout for CGPreflight screen capture check. */
|
|
99
37
|
screenRecordingPreflight: 4_000,
|
|
100
|
-
/** Timeout for CGRequest screen capture request. */
|
|
101
38
|
screenRecordingRequest: 6_000,
|
|
102
|
-
/** Timeout for `open` command to launch System Preferences. */
|
|
103
39
|
openSystemPreferences: 3_000,
|
|
104
|
-
/** Timeout for parent process tree detection. */
|
|
105
40
|
detectTerminal: 3_000,
|
|
106
41
|
};
|
|
107
|
-
/**
|
|
108
|
-
* TTL for cached dashboard permission / host-terminal probes. `/api/state` is
|
|
109
|
-
* polled (~1.5s while a channel validates) and each probe spawns subprocesses
|
|
110
|
-
* (screencapture, an `ls` shell, a `ps` process-tree walk), so the raw checks
|
|
111
|
-
* must not run per request. The host terminal is immutable per process;
|
|
112
|
-
* permission grants change rarely and `requestPermission` invalidates the cache
|
|
113
|
-
* on user action, so a short TTL surfaces grants without per-request spawns.
|
|
114
|
-
*/
|
|
115
42
|
export const DASHBOARD_PERMISSION_CACHE_TTL_MS = 30_000;
|
|
116
|
-
// ---------------------------------------------------------------------------
|
|
117
|
-
// CLI / Daemon
|
|
118
|
-
// ---------------------------------------------------------------------------
|
|
119
|
-
/** Daemon (watchdog) restart timing constants. */
|
|
120
43
|
export const DAEMON_TIMEOUTS = {
|
|
121
|
-
/** Initial delay before restarting a crashed child. */
|
|
122
44
|
restartDelay: 3_000,
|
|
123
|
-
/** Maximum back-off delay for repeated rapid crashes. */
|
|
124
45
|
maxRestartDelay: 60_000,
|
|
125
|
-
/** If the child runs shorter than this, treat it as a rapid crash. */
|
|
126
46
|
rapidCrashWindow: 10_000,
|
|
127
|
-
/** Polling interval while waiting for dashboard config to become ready. */
|
|
128
47
|
configPollInterval: 1_000,
|
|
129
48
|
};
|
|
130
|
-
// ---------------------------------------------------------------------------
|
|
131
|
-
// Bot orchestration / shutdown
|
|
132
|
-
// ---------------------------------------------------------------------------
|
|
133
|
-
/** Time to wait before force-exiting during bot shutdown. */
|
|
134
49
|
export const BOT_SHUTDOWN_FORCE_EXIT_MS = 3_000;
|
|
135
|
-
// ---------------------------------------------------------------------------
|
|
136
|
-
// Bot runtime
|
|
137
|
-
// ---------------------------------------------------------------------------
|
|
138
|
-
/** Bot-level timing constants. */
|
|
139
50
|
export const BOT_TIMEOUTS = {
|
|
140
|
-
/** Default run timeout for agent streams (seconds). */
|
|
141
51
|
defaultRunTimeoutS: 7200,
|
|
142
|
-
/** Interval for macOS user-activity caffeinate pulses. */
|
|
143
52
|
macosUserActivityPulseInterval: 20_000,
|
|
144
|
-
/** Timeout (seconds) for the caffeinate assertion per pulse. */
|
|
145
53
|
macosUserActivityPulseTimeoutS: 30,
|
|
146
54
|
};
|
|
147
|
-
// ---------------------------------------------------------------------------
|
|
148
|
-
// Live preview (stream feedback)
|
|
149
|
-
// ---------------------------------------------------------------------------
|
|
150
|
-
/** Timing constants for the channel-agnostic live preview controller. */
|
|
151
55
|
export const STREAM_PREVIEW_TIMEOUTS = {
|
|
152
|
-
/** Interval between heartbeat edits that refresh the elapsed timer. */
|
|
153
56
|
heartbeat: 5_000,
|
|
154
|
-
/** Interval between typing indicator pulses. */
|
|
155
57
|
typing: 4_000,
|
|
156
|
-
/** After this idle time, a "stalled" notice is shown. */
|
|
157
58
|
stalledNotice: 15_000,
|
|
158
59
|
};
|
|
159
|
-
// ---------------------------------------------------------------------------
|
|
160
|
-
// Channels — Telegram
|
|
161
|
-
// ---------------------------------------------------------------------------
|
|
162
|
-
/** Telegram channel transport constants. */
|
|
163
60
|
export const TELEGRAM_LIMITS = {
|
|
164
|
-
/** Maximum text length per Telegram message. */
|
|
165
61
|
maxMessageLength: 4096,
|
|
166
|
-
/** Maximum file size for send/receive (20 MB). */
|
|
167
62
|
fileMaxBytes: 20 * 1024 * 1024,
|
|
168
|
-
/** Maximum back-off delay for polling/connect retries. */
|
|
169
63
|
maxRetryDelay: 60_000,
|
|
170
64
|
};
|
|
171
|
-
// ---------------------------------------------------------------------------
|
|
172
|
-
// Channels — Feishu
|
|
173
|
-
// ---------------------------------------------------------------------------
|
|
174
|
-
/** Feishu channel transport constants. */
|
|
175
65
|
export const FEISHU_LIMITS = {
|
|
176
|
-
/** Card markdown budget (card JSON limit ~30 KB). */
|
|
177
66
|
cardMax: 28_000,
|
|
178
|
-
/** Maximum file size for send/receive (20 MB). */
|
|
179
67
|
fileMaxBytes: 20 * 1024 * 1024,
|
|
180
|
-
/** Maximum back-off delay for WebSocket reconnection retries. */
|
|
181
68
|
wsStartRetryMaxDelay: 60_000,
|
|
182
|
-
/** Initial retry delay for Feishu WebSocket connection. */
|
|
183
69
|
wsStartRetryInitialDelay: 3_000,
|
|
184
70
|
};
|
|
185
|
-
/** Feishu bot rendering limit for card payloads. */
|
|
186
71
|
export const FEISHU_BOT_CARD_MAX = 25_000;
|
|
187
|
-
// ---------------------------------------------------------------------------
|
|
188
|
-
// Channels — Weixin
|
|
189
|
-
// ---------------------------------------------------------------------------
|
|
190
|
-
/** Weixin channel transport constants. */
|
|
191
72
|
export const WEIXIN_LIMITS = {
|
|
192
|
-
/** Conservative text split budget for plain-text replies. */
|
|
193
73
|
maxMessageLength: 1200,
|
|
194
|
-
/** Long-poll timeout for getupdates. */
|
|
195
74
|
longPollTimeout: 35_000,
|
|
196
|
-
/** Maximum back-off delay for polling retries. */
|
|
197
75
|
maxRetryDelay: 60_000,
|
|
198
76
|
};
|
|
199
|
-
// ---------------------------------------------------------------------------
|
|
200
|
-
// Channels — Slack
|
|
201
|
-
// ---------------------------------------------------------------------------
|
|
202
|
-
/** Slack channel transport constants. */
|
|
203
77
|
export const SLACK_LIMITS = {
|
|
204
|
-
/** Slack chat.postMessage hard limit is 40000; cap at 35k for safety. */
|
|
205
78
|
maxMessageLength: 35_000,
|
|
206
|
-
/** Slack file upload size cap (1 GB); we keep parity with other channels at 20 MB. */
|
|
207
79
|
fileMaxBytes: 20 * 1024 * 1024,
|
|
208
|
-
/** Maximum back-off delay for socket-mode reconnect retries. */
|
|
209
80
|
maxRetryDelay: 60_000,
|
|
210
|
-
/** Initial back-off delay for socket-mode reconnect. */
|
|
211
81
|
initialRetryDelay: 3_000,
|
|
212
82
|
};
|
|
213
|
-
// ---------------------------------------------------------------------------
|
|
214
|
-
// Channels — Discord
|
|
215
|
-
// ---------------------------------------------------------------------------
|
|
216
|
-
/** Discord channel transport constants. */
|
|
217
83
|
export const DISCORD_LIMITS = {
|
|
218
|
-
/** Hard message cap is 2000 chars; leave a small buffer. */
|
|
219
84
|
maxMessageLength: 1900,
|
|
220
|
-
/** File size cap for non-Nitro guilds is 25 MB; we keep parity at 20 MB. */
|
|
221
85
|
fileMaxBytes: 20 * 1024 * 1024,
|
|
222
|
-
/** Maximum back-off delay for gateway reconnect retries. */
|
|
223
86
|
maxRetryDelay: 60_000,
|
|
224
|
-
/** Initial back-off delay for gateway reconnect. */
|
|
225
87
|
initialRetryDelay: 3_000,
|
|
226
88
|
};
|
|
227
|
-
// ---------------------------------------------------------------------------
|
|
228
|
-
// Channels — DingTalk
|
|
229
|
-
// ---------------------------------------------------------------------------
|
|
230
|
-
/** DingTalk channel transport constants. */
|
|
231
89
|
export const DINGTALK_LIMITS = {
|
|
232
|
-
/** Conservative text limit per message (markdown segments split here). */
|
|
233
90
|
maxMessageLength: 5_000,
|
|
234
|
-
/** Maximum back-off delay for stream reconnect retries. */
|
|
235
91
|
maxRetryDelay: 60_000,
|
|
236
|
-
/** Initial back-off delay for stream reconnect. */
|
|
237
92
|
initialRetryDelay: 3_000,
|
|
238
93
|
};
|
|
239
|
-
// ---------------------------------------------------------------------------
|
|
240
|
-
// Channels — WeChat Work (企业微信 智能机器人)
|
|
241
|
-
// ---------------------------------------------------------------------------
|
|
242
|
-
/** WeChat Work Smart Bot WebSocket transport constants. */
|
|
243
94
|
export const WECOM_LIMITS = {
|
|
244
|
-
/** Smart Bot text message hard cap is roughly 5KB chars. */
|
|
245
95
|
maxMessageLength: 4_000,
|
|
246
|
-
/** Heartbeat interval to keep the websocket alive. */
|
|
247
96
|
heartbeatInterval: 30_000,
|
|
248
|
-
/** Maximum back-off delay for websocket reconnect retries. */
|
|
249
97
|
maxRetryDelay: 60_000,
|
|
250
|
-
/** Initial back-off delay for websocket reconnect. */
|
|
251
98
|
initialRetryDelay: 1_000,
|
|
252
|
-
/** Default smart bot websocket endpoint. */
|
|
253
99
|
defaultEndpoint: 'wss://openws.work.weixin.qq.com/wssvr/',
|
|
254
100
|
};
|
|
255
|
-
// ---------------------------------------------------------------------------
|
|
256
|
-
// Config validation
|
|
257
|
-
// ---------------------------------------------------------------------------
|
|
258
|
-
/** Timeouts for channel credential validation flows. */
|
|
259
101
|
export const VALIDATION_TIMEOUTS = {
|
|
260
|
-
/** Default timeout for Feishu credential validation. */
|
|
261
102
|
feishuDefault: 15_000,
|
|
262
|
-
/** Timeout for fetching Feishu bot info after credential validation. */
|
|
263
103
|
feishuBotInfo: 5_000,
|
|
264
|
-
/** Timeout for Telegram token validation (setup wizard). */
|
|
265
104
|
telegramToken: 8_000,
|
|
266
|
-
/** Default timeout for Weixin credential validation. */
|
|
267
105
|
weixinDefault: 8_000,
|
|
268
|
-
/** Long-poll timeout for dashboard QR login wait calls. */
|
|
269
106
|
weixinQrPoll: 35_000,
|
|
270
|
-
/** Default timeout for Slack credential validation. */
|
|
271
107
|
slackDefault: 8_000,
|
|
272
|
-
/** Default timeout for Discord credential validation. */
|
|
273
108
|
discordDefault: 8_000,
|
|
274
|
-
/** Default timeout for DingTalk credential validation (gettoken endpoint). */
|
|
275
109
|
dingtalkDefault: 8_000,
|
|
276
|
-
/** Default timeout for WeChat Work bot validation handshake. */
|
|
277
110
|
wecomDefault: 8_000,
|
|
278
111
|
};
|
|
279
|
-
// ---------------------------------------------------------------------------
|
|
280
|
-
// Agent auto-update
|
|
281
|
-
// ---------------------------------------------------------------------------
|
|
282
|
-
/** Timeouts for the background agent auto-update system. */
|
|
283
112
|
export const AGENT_UPDATE_TIMEOUTS = {
|
|
284
|
-
/** After this duration a stale lock file is removed. */
|
|
285
113
|
lockStale: 60 * 60_000,
|
|
286
|
-
/** Maximum time for an agent update command to run. */
|
|
287
114
|
commandTimeout: 15 * 60_000,
|
|
288
|
-
/** Timeout for `npm prefix -g`. */
|
|
289
115
|
npmPrefix: 10_000,
|
|
290
|
-
/** Timeout for `npm view <pkg> version`. */
|
|
291
116
|
npmView: 20_000,
|
|
292
|
-
/** Max time an agent spawn waits for an in-flight reinstall of that agent's
|
|
293
|
-
* own CLI to finish before exec'ing. A concurrent `npm install -g` / `brew
|
|
294
|
-
* upgrade` (this process OR the prod self-bootstrap) briefly removes the bin
|
|
295
|
-
* symlink, so racing it yields exit 127 "command not found"; the wait
|
|
296
|
-
* resolves early the instant the install ends. */
|
|
297
117
|
spawnWait: 2 * 60_000,
|
|
298
|
-
/** Poll interval while a spawn waits out an in-flight reinstall. */
|
|
299
118
|
spawnWaitPoll: 200,
|
|
300
119
|
};
|
|
301
|
-
// ---------------------------------------------------------------------------
|
|
302
|
-
// Code agent (shared layer)
|
|
303
|
-
// ---------------------------------------------------------------------------
|
|
304
|
-
/** Caching TTLs for agent detection and version lookups. */
|
|
305
120
|
export const AGENT_DETECT_TIMEOUTS = {
|
|
306
|
-
/** How long a binary-detection result is cached. */
|
|
307
121
|
detectTtl: 1_000,
|
|
308
|
-
/** How long a version string is cached. */
|
|
309
122
|
versionTtl: 5 * 60_000,
|
|
310
|
-
/** Timeout for the `--version` command itself. */
|
|
311
123
|
versionCommand: 3_000,
|
|
312
124
|
};
|
|
313
|
-
/** Grace period added to the user-configured timeout before hard-killing the agent. */
|
|
314
125
|
export const AGENT_STREAM_HARD_KILL_GRACE_MS = 10_000;
|
|
315
|
-
/**
|
|
316
|
-
* On user abort, wait this long for the agent CLI to flush its session JSONL
|
|
317
|
-
* (including any `[Request interrupted]` marker) before falling back to
|
|
318
|
-
* SIGTERM. Keeps the partial assistant response persisted so the next task,
|
|
319
|
-
* resumed via --resume, can see it in the transcript.
|
|
320
|
-
*/
|
|
321
126
|
export const AGENT_GRACEFUL_ABORT_GRACE_MS = 2_000;
|
|
322
|
-
/**
|
|
323
|
-
* claude-tui stall watchdog — claude CLI is known to freeze mid-turn (observed
|
|
324
|
-
* 2026-06-02 on 2.1.160: after a tool_result lands, the next assistant segment
|
|
325
|
-
* never starts; the process stays alive, the JSONL goes permanently quiet, no
|
|
326
|
-
* Stop hook ever fires). When every live signal (main JSONL, hook tool events,
|
|
327
|
-
* sub-agent sidecars, hook lifecycle state) is silent past the threshold the
|
|
328
|
-
* driver SIGTERMs the PTY and the dispatch wrapper auto-resumes the session
|
|
329
|
-
* once. Quiet threshold must sit safely above the longest healthy gap between
|
|
330
|
-
* JSONL events — a single max-effort inference can take a few minutes before
|
|
331
|
-
* its first content block lands.
|
|
332
|
-
*/
|
|
333
127
|
export const CLAUDE_TUI_STALL_QUIET_MS = 10 * 60_000;
|
|
334
|
-
/**
|
|
335
|
-
* Stall threshold while a hook-reported tool is still executing (PreToolUse
|
|
336
|
-
* seen, no matching PostToolUse). Claude's own Bash timeout caps foreground
|
|
337
|
-
* commands at ~10 minutes and fires PostToolUse either way, so a pending tool
|
|
338
|
-
* silent for this long means the freeze hit mid-execution.
|
|
339
|
-
*/
|
|
340
128
|
export const CLAUDE_TUI_STALL_PENDING_TOOL_MS = 30 * 60_000;
|
|
341
|
-
/**
|
|
342
|
-
* Fast-path stall: a healthy claude TUI repaints continuously while a turn is
|
|
343
|
-
* in flight (spinner frames, stream ticks, status line) — the PTY never goes
|
|
344
|
-
* byte-silent for minutes. If NO PTY output arrives for this long AND every
|
|
345
|
-
* structured signal is equally quiet, the process event loop itself is gone
|
|
346
|
-
* (the 2.1.160 mid-turn freeze: attachment lands → next API call never
|
|
347
|
-
* assembles). Declare the stall now instead of waiting out the 10/30-minute
|
|
348
|
-
* quiet thresholds — turns a 10-30 分钟「卡死」into a ~3 分钟自愈。
|
|
349
|
-
* False-positive safe: long thinking / long Bash keep painting frames, which
|
|
350
|
-
* refreshes the PTY signal and defers this path to the slow thresholds.
|
|
351
|
-
*/
|
|
352
129
|
export const CLAUDE_TUI_STALL_PTY_DEAD_MS = 3 * 60_000;
|
|
353
|
-
/**
|
|
354
|
-
* Settle window after the TUI paints the "selected model is unavailable" banner
|
|
355
|
-
* (a 404 model_not_found). The notice is terminal — claude paints it then idles
|
|
356
|
-
* at the REPL forever: no JSONL is written, no Stop hook fires. We wait this
|
|
357
|
-
* brief window to cross-validate that nothing substantive followed (the banner
|
|
358
|
-
* alone is evidence, not a verdict — same discipline as resolveClaudeTuiLimitOutcome)
|
|
359
|
-
* before ending the turn, instead of waiting out the 3–10 minute stall watchdog.
|
|
360
|
-
*/
|
|
361
130
|
export const CLAUDE_TUI_MODEL_ERROR_SETTLE_MS = 2_500;
|
|
362
|
-
/**
|
|
363
|
-
* TTL for the post-Stop `hold-background` path. The hold protects
|
|
364
|
-
* run_in_background agents living inside the claude process — but a live
|
|
365
|
-
* agent keeps emitting hook/sidecar/JSONL traffic. If the hold sees no
|
|
366
|
-
* activity on ANY channel for this long, the pending count is phantom (lost
|
|
367
|
-
* <task-notification>, agents already finished): release as a NORMAL Stop.
|
|
368
|
-
* Without this TTL the stall watchdog eventually fires instead, mislabels the
|
|
369
|
-
* cleanly-finished turn 'stalled', and injects a confusing auto-resume prompt
|
|
370
|
-
* (the「回合明明答完了还被注入 Continue」symptom).
|
|
371
|
-
*/
|
|
372
131
|
export const CLAUDE_TUI_STOP_HOLD_QUIET_TTL_MS = 10 * 60_000;
|
|
373
|
-
/** Codex-specific grace period added to the user-configured timeout. */
|
|
374
132
|
export const CODEX_STREAM_HARD_KILL_GRACE_MS = 5_000;
|
|
375
|
-
/**
|
|
376
|
-
* If a session file was modified more recently than this threshold,
|
|
377
|
-
* consider the session "running". Shared across Claude, Codex, and Gemini drivers.
|
|
378
|
-
*/
|
|
379
133
|
export const SESSION_RUNNING_THRESHOLD_MS = 10_000;
|
|
380
|
-
// ---------------------------------------------------------------------------
|
|
381
|
-
// Driver — Codex
|
|
382
|
-
// ---------------------------------------------------------------------------
|
|
383
|
-
/** Timeout for the Codex app-server to become ready after spawn. */
|
|
384
134
|
export const CODEX_APPSERVER_SPAWN_TIMEOUT_MS = 15_000;
|
|
385
|
-
// ---------------------------------------------------------------------------
|
|
386
|
-
// Driver — Gemini
|
|
387
|
-
// ---------------------------------------------------------------------------
|
|
388
|
-
/** Timeouts for Gemini usage / quota queries. */
|
|
389
135
|
export const GEMINI_USAGE_TIMEOUTS = {
|
|
390
|
-
/** Max time for the curl quota request. */
|
|
391
136
|
request: 5_000,
|
|
392
|
-
/** Extra buffer added to the curl timeout for the execSync wrapper. */
|
|
393
137
|
execSyncBuffer: 3_000,
|
|
394
138
|
};
|
|
395
|
-
// ---------------------------------------------------------------------------
|
|
396
|
-
// User config sync
|
|
397
|
-
// ---------------------------------------------------------------------------
|
|
398
|
-
/** Default interval for the user config file sync poll. */
|
|
399
139
|
export const USER_CONFIG_SYNC_DEFAULT_INTERVAL_MS = 1_000;
|
|
400
|
-
// ---------------------------------------------------------------------------
|
|
401
|
-
// Git status
|
|
402
|
-
// ---------------------------------------------------------------------------
|
|
403
|
-
/**
|
|
404
|
-
* Upper bound for a single `git status` invocation. Bounded so a huge repo or a
|
|
405
|
-
* stuck `.git/index.lock` can never block `/status` or a workspace poll. Matches
|
|
406
|
-
* the timeout used by the existing `/api/git-changes` endpoint.
|
|
407
|
-
*/
|
|
408
140
|
export const GIT_STATUS_TIMEOUT_MS = 5_000;
|