clisbot 0.1.32 → 0.1.36
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/config/clisbot.json.template +2 -0
- package/dist/main.js +334 -229
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -54713,8 +54713,8 @@ function renderCliHelp() {
|
|
|
54713
54713
|
" clear-token <slack-app|slack-bot|telegram-bot>",
|
|
54714
54714
|
" See `clisbot channels --help` for route policy notes and defaults such as `requireMention`.",
|
|
54715
54715
|
" accounts Manage Slack and Telegram provider accounts plus persistence state.",
|
|
54716
|
-
" add telegram --account <id> --token <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
54717
|
-
" add slack --account <id> --app-token <ENV_NAME|${ENV_NAME}|literal> --bot-token <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
54716
|
+
" add telegram --account <id> (--token|--telegram-bot-token) <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
54717
|
+
" add slack --account <id> (--app-token|--slack-app-token) <ENV_NAME|${ENV_NAME}|literal> (--bot-token|--slack-bot-token) <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
54718
54718
|
" persist --channel <slack|telegram> --account <id>",
|
|
54719
54719
|
" persist --all",
|
|
54720
54720
|
" See `clisbot accounts --help` for env-vs-mem-vs-persist behavior.",
|
|
@@ -55261,6 +55261,8 @@ var DEFAULT_AGENT_TOOL_TEMPLATES = {
|
|
|
55261
55261
|
],
|
|
55262
55262
|
trustWorkspace: true,
|
|
55263
55263
|
startupDelayMs: 3000,
|
|
55264
|
+
startupRetryCount: 2,
|
|
55265
|
+
startupRetryDelayMs: 1000,
|
|
55264
55266
|
promptSubmitDelayMs: 150,
|
|
55265
55267
|
sessionId: {
|
|
55266
55268
|
create: {
|
|
@@ -55292,6 +55294,8 @@ var DEFAULT_AGENT_TOOL_TEMPLATES = {
|
|
|
55292
55294
|
startupOptions: ["--dangerously-skip-permissions"],
|
|
55293
55295
|
trustWorkspace: true,
|
|
55294
55296
|
startupDelayMs: 3000,
|
|
55297
|
+
startupRetryCount: 2,
|
|
55298
|
+
startupRetryDelayMs: 1000,
|
|
55295
55299
|
promptSubmitDelayMs: 150,
|
|
55296
55300
|
sessionId: {
|
|
55297
55301
|
create: {
|
|
@@ -55320,6 +55324,8 @@ var DEFAULT_AGENT_TOOL_TEMPLATES = {
|
|
|
55320
55324
|
startupOptions: ["--approval-mode=yolo", "--sandbox=false"],
|
|
55321
55325
|
trustWorkspace: true,
|
|
55322
55326
|
startupDelayMs: 15000,
|
|
55327
|
+
startupRetryCount: 2,
|
|
55328
|
+
startupRetryDelayMs: 1000,
|
|
55323
55329
|
startupReadyPattern: "Type your message or @path/to/file",
|
|
55324
55330
|
startupBlockers: [
|
|
55325
55331
|
{
|
|
@@ -55359,6 +55365,8 @@ function buildRunnerFromToolTemplate(toolId, template, startupOptions) {
|
|
|
55359
55365
|
args: [...options, "-C", "{workspace}"],
|
|
55360
55366
|
trustWorkspace: template.trustWorkspace,
|
|
55361
55367
|
startupDelayMs: template.startupDelayMs,
|
|
55368
|
+
startupRetryCount: template.startupRetryCount,
|
|
55369
|
+
startupRetryDelayMs: template.startupRetryDelayMs,
|
|
55362
55370
|
startupReadyPattern: template.startupReadyPattern,
|
|
55363
55371
|
startupBlockers: template.startupBlockers?.map((entry) => ({ ...entry })),
|
|
55364
55372
|
promptSubmitDelayMs: template.promptSubmitDelayMs,
|
|
@@ -55383,6 +55391,8 @@ function buildRunnerFromToolTemplate(toolId, template, startupOptions) {
|
|
|
55383
55391
|
args: [...options],
|
|
55384
55392
|
trustWorkspace: template.trustWorkspace,
|
|
55385
55393
|
startupDelayMs: template.startupDelayMs,
|
|
55394
|
+
startupRetryCount: template.startupRetryCount,
|
|
55395
|
+
startupRetryDelayMs: template.startupRetryDelayMs,
|
|
55386
55396
|
startupReadyPattern: template.startupReadyPattern,
|
|
55387
55397
|
startupBlockers: template.startupBlockers?.map((entry) => ({ ...entry })),
|
|
55388
55398
|
promptSubmitDelayMs: template.promptSubmitDelayMs,
|
|
@@ -60047,6 +60057,8 @@ var runnerSchema = exports_external.object({
|
|
|
60047
60057
|
]),
|
|
60048
60058
|
trustWorkspace: exports_external.boolean().default(true),
|
|
60049
60059
|
startupDelayMs: exports_external.number().int().positive().default(3000),
|
|
60060
|
+
startupRetryCount: exports_external.number().int().min(0).default(2),
|
|
60061
|
+
startupRetryDelayMs: exports_external.number().int().min(0).default(1000),
|
|
60050
60062
|
startupReadyPattern: exports_external.string().min(1).optional(),
|
|
60051
60063
|
startupBlockers: exports_external.array(runnerStartupBlockerSchema).optional(),
|
|
60052
60064
|
promptSubmitDelayMs: exports_external.number().int().min(0).default(150),
|
|
@@ -60083,6 +60095,8 @@ var runnerOverrideSchema = exports_external.object({
|
|
|
60083
60095
|
args: exports_external.array(exports_external.string()).optional(),
|
|
60084
60096
|
trustWorkspace: exports_external.boolean().optional(),
|
|
60085
60097
|
startupDelayMs: exports_external.number().int().positive().optional(),
|
|
60098
|
+
startupRetryCount: exports_external.number().int().min(0).optional(),
|
|
60099
|
+
startupRetryDelayMs: exports_external.number().int().min(0).optional(),
|
|
60086
60100
|
startupReadyPattern: exports_external.string().min(1).optional(),
|
|
60087
60101
|
startupBlockers: exports_external.array(runnerStartupBlockerSchema).optional(),
|
|
60088
60102
|
promptSubmitDelayMs: exports_external.number().int().min(0).optional(),
|
|
@@ -60125,6 +60139,8 @@ var agentDefaultsSchema = exports_external.object({
|
|
|
60125
60139
|
],
|
|
60126
60140
|
trustWorkspace: true,
|
|
60127
60141
|
startupDelayMs: 3000,
|
|
60142
|
+
startupRetryCount: 2,
|
|
60143
|
+
startupRetryDelayMs: 1000,
|
|
60128
60144
|
promptSubmitDelayMs: 150,
|
|
60129
60145
|
sessionId: defaultRunnerSessionIdConfig
|
|
60130
60146
|
}),
|
|
@@ -60789,6 +60805,8 @@ function renderDefaultConfigTemplate(options = {}) {
|
|
|
60789
60805
|
],
|
|
60790
60806
|
trustWorkspace: true,
|
|
60791
60807
|
startupDelayMs: 3000,
|
|
60808
|
+
startupRetryCount: 2,
|
|
60809
|
+
startupRetryDelayMs: 1000,
|
|
60792
60810
|
startupReadyPattern: undefined,
|
|
60793
60811
|
promptSubmitDelayMs: 150,
|
|
60794
60812
|
sessionId: {
|
|
@@ -61148,6 +61166,157 @@ function resolveTopLevelBoundAgentId(config, match) {
|
|
|
61148
61166
|
});
|
|
61149
61167
|
}
|
|
61150
61168
|
|
|
61169
|
+
// src/control/channel-bootstrap-flags.ts
|
|
61170
|
+
function isLiteralToken(token) {
|
|
61171
|
+
return token?.kind === "mem";
|
|
61172
|
+
}
|
|
61173
|
+
function parseBotType(rawValue) {
|
|
61174
|
+
const value = rawValue.trim().toLowerCase();
|
|
61175
|
+
if (value === "personal") {
|
|
61176
|
+
return "personal-assistant";
|
|
61177
|
+
}
|
|
61178
|
+
if (value === "team") {
|
|
61179
|
+
return "team-assistant";
|
|
61180
|
+
}
|
|
61181
|
+
throw new Error(`Invalid bot type: ${rawValue}. Expected personal or team.`);
|
|
61182
|
+
}
|
|
61183
|
+
function parseOptionValue(args, name, index) {
|
|
61184
|
+
const value = args[index + 1]?.trim();
|
|
61185
|
+
if (!value) {
|
|
61186
|
+
throw new Error(`Missing value for ${name}`);
|
|
61187
|
+
}
|
|
61188
|
+
return value;
|
|
61189
|
+
}
|
|
61190
|
+
function getOrCreateSlackAccount(accounts, accountId) {
|
|
61191
|
+
let account = accounts.find((entry) => entry.accountId === accountId);
|
|
61192
|
+
if (!account) {
|
|
61193
|
+
account = { accountId };
|
|
61194
|
+
accounts.push(account);
|
|
61195
|
+
}
|
|
61196
|
+
return account;
|
|
61197
|
+
}
|
|
61198
|
+
function getOrCreateTelegramAccount(accounts, accountId) {
|
|
61199
|
+
let account = accounts.find((entry) => entry.accountId === accountId);
|
|
61200
|
+
if (!account) {
|
|
61201
|
+
account = { accountId };
|
|
61202
|
+
accounts.push(account);
|
|
61203
|
+
}
|
|
61204
|
+
return account;
|
|
61205
|
+
}
|
|
61206
|
+
function ensureUniqueAccount(accounts, accountId, flagName) {
|
|
61207
|
+
if (accounts.some((entry) => entry.accountId === accountId)) {
|
|
61208
|
+
throw new Error(`Duplicate ${flagName} ${accountId}`);
|
|
61209
|
+
}
|
|
61210
|
+
}
|
|
61211
|
+
function validateSlackAccount(account) {
|
|
61212
|
+
if (!account.appToken || !account.botToken) {
|
|
61213
|
+
throw new Error(`Slack account ${account.accountId} requires both app token and bot token`);
|
|
61214
|
+
}
|
|
61215
|
+
if (account.appToken.kind !== account.botToken.kind) {
|
|
61216
|
+
throw new Error(`Slack account ${account.accountId} must use one credential source kind for both app and bot tokens`);
|
|
61217
|
+
}
|
|
61218
|
+
}
|
|
61219
|
+
function validateTelegramAccount(account) {
|
|
61220
|
+
if (!account.botToken) {
|
|
61221
|
+
throw new Error(`Telegram account ${account.accountId} requires a bot token`);
|
|
61222
|
+
}
|
|
61223
|
+
}
|
|
61224
|
+
function parseBootstrapFlags(args) {
|
|
61225
|
+
const slackAccounts = [];
|
|
61226
|
+
const telegramAccounts = [];
|
|
61227
|
+
let currentSlackAccountId;
|
|
61228
|
+
let currentTelegramAccountId;
|
|
61229
|
+
let cliTool;
|
|
61230
|
+
let bootstrap;
|
|
61231
|
+
let persist = false;
|
|
61232
|
+
let sawCredentialFlags = false;
|
|
61233
|
+
let sawSlackFlags = false;
|
|
61234
|
+
let sawTelegramFlags = false;
|
|
61235
|
+
for (let index = 0;index < args.length; index += 1) {
|
|
61236
|
+
const arg = args[index];
|
|
61237
|
+
if (arg === "--cli") {
|
|
61238
|
+
cliTool = parseOptionValue(args, arg, index);
|
|
61239
|
+
index += 1;
|
|
61240
|
+
continue;
|
|
61241
|
+
}
|
|
61242
|
+
if (arg === "--bot-type") {
|
|
61243
|
+
bootstrap = parseBotType(parseOptionValue(args, arg, index));
|
|
61244
|
+
index += 1;
|
|
61245
|
+
continue;
|
|
61246
|
+
}
|
|
61247
|
+
if (arg === "--persist") {
|
|
61248
|
+
persist = true;
|
|
61249
|
+
continue;
|
|
61250
|
+
}
|
|
61251
|
+
if (arg === "--slack-account") {
|
|
61252
|
+
const accountId = parseOptionValue(args, arg, index);
|
|
61253
|
+
ensureUniqueAccount(slackAccounts, accountId, "--slack-account");
|
|
61254
|
+
currentSlackAccountId = accountId;
|
|
61255
|
+
getOrCreateSlackAccount(slackAccounts, accountId);
|
|
61256
|
+
sawSlackFlags = true;
|
|
61257
|
+
index += 1;
|
|
61258
|
+
continue;
|
|
61259
|
+
}
|
|
61260
|
+
if (arg === "--telegram-account") {
|
|
61261
|
+
const accountId = parseOptionValue(args, arg, index);
|
|
61262
|
+
ensureUniqueAccount(telegramAccounts, accountId, "--telegram-account");
|
|
61263
|
+
currentTelegramAccountId = accountId;
|
|
61264
|
+
getOrCreateTelegramAccount(telegramAccounts, accountId);
|
|
61265
|
+
sawTelegramFlags = true;
|
|
61266
|
+
index += 1;
|
|
61267
|
+
continue;
|
|
61268
|
+
}
|
|
61269
|
+
if (arg === "--slack-app-token") {
|
|
61270
|
+
const token = parseTokenInput(parseOptionValue(args, arg, index));
|
|
61271
|
+
const account = getOrCreateSlackAccount(slackAccounts, currentSlackAccountId ?? "default");
|
|
61272
|
+
account.appToken = token;
|
|
61273
|
+
sawCredentialFlags = true;
|
|
61274
|
+
sawSlackFlags = true;
|
|
61275
|
+
index += 1;
|
|
61276
|
+
continue;
|
|
61277
|
+
}
|
|
61278
|
+
if (arg === "--slack-bot-token") {
|
|
61279
|
+
const token = parseTokenInput(parseOptionValue(args, arg, index));
|
|
61280
|
+
const account = getOrCreateSlackAccount(slackAccounts, currentSlackAccountId ?? "default");
|
|
61281
|
+
account.botToken = token;
|
|
61282
|
+
sawCredentialFlags = true;
|
|
61283
|
+
sawSlackFlags = true;
|
|
61284
|
+
index += 1;
|
|
61285
|
+
continue;
|
|
61286
|
+
}
|
|
61287
|
+
if (arg === "--telegram-bot-token") {
|
|
61288
|
+
const token = parseTokenInput(parseOptionValue(args, arg, index));
|
|
61289
|
+
const account = getOrCreateTelegramAccount(telegramAccounts, currentTelegramAccountId ?? "default");
|
|
61290
|
+
account.botToken = token;
|
|
61291
|
+
sawCredentialFlags = true;
|
|
61292
|
+
sawTelegramFlags = true;
|
|
61293
|
+
index += 1;
|
|
61294
|
+
continue;
|
|
61295
|
+
}
|
|
61296
|
+
throw new Error(`Unknown option for start/init: ${arg}`);
|
|
61297
|
+
}
|
|
61298
|
+
for (const account of slackAccounts) {
|
|
61299
|
+
validateSlackAccount(account);
|
|
61300
|
+
}
|
|
61301
|
+
for (const account of telegramAccounts) {
|
|
61302
|
+
validateTelegramAccount(account);
|
|
61303
|
+
}
|
|
61304
|
+
return {
|
|
61305
|
+
cliTool,
|
|
61306
|
+
bootstrap,
|
|
61307
|
+
persist,
|
|
61308
|
+
slackAccounts,
|
|
61309
|
+
telegramAccounts,
|
|
61310
|
+
sawCredentialFlags,
|
|
61311
|
+
sawSlackFlags,
|
|
61312
|
+
sawTelegramFlags,
|
|
61313
|
+
literalWarnings: []
|
|
61314
|
+
};
|
|
61315
|
+
}
|
|
61316
|
+
function hasLiteralBootstrapCredentials(flags) {
|
|
61317
|
+
return flags.slackAccounts.some((account) => isLiteralToken(account.appToken) || isLiteralToken(account.botToken)) || flags.telegramAccounts.some((account) => isLiteralToken(account.botToken));
|
|
61318
|
+
}
|
|
61319
|
+
|
|
61151
61320
|
// src/control/agents-cli.ts
|
|
61152
61321
|
function getEditableConfigPath() {
|
|
61153
61322
|
return process.env.CLISBOT_CONFIG_PATH;
|
|
@@ -61194,8 +61363,8 @@ function renderAgentsHelp() {
|
|
|
61194
61363
|
" clisbot agents --help",
|
|
61195
61364
|
" clisbot agents help",
|
|
61196
61365
|
" clisbot agents list [--bindings] [--json]",
|
|
61197
|
-
" clisbot agents add <id> --cli <codex|claude|gemini> [--workspace <path>] [--startup-option <arg>]... [--
|
|
61198
|
-
" clisbot agents bootstrap <id> --
|
|
61366
|
+
" clisbot agents add <id> --cli <codex|claude|gemini> [--workspace <path>] [--startup-option <arg>]... [--bot-type <personal|team>] [--bind <channel[:accountId]>]...",
|
|
61367
|
+
" clisbot agents bootstrap <id> --bot-type <personal|team> [--force]",
|
|
61199
61368
|
" clisbot agents bindings [--agent <id>] [--json]",
|
|
61200
61369
|
" clisbot agents bind --agent <id> --bind <channel[:accountId]>",
|
|
61201
61370
|
" clisbot agents unbind --agent <id> [--bind <channel[:accountId]> | --all]",
|
|
@@ -61372,7 +61541,13 @@ async function addAgentToEditableConfig(params) {
|
|
|
61372
61541
|
async function addAgent(args) {
|
|
61373
61542
|
const agentId = args[0]?.trim();
|
|
61374
61543
|
if (!agentId) {
|
|
61375
|
-
throw new Error("Usage: agents add <id> --cli <codex|claude|gemini> [--workspace <path>] [--startup-option <arg>]... [--
|
|
61544
|
+
throw new Error("Usage: agents add <id> --cli <codex|claude|gemini> [--workspace <path>] [--startup-option <arg>]... [--bot-type <personal|team>] [--bind <channel[:accountId]>]...");
|
|
61545
|
+
}
|
|
61546
|
+
if (hasFlag(args, "--bootstrap")) {
|
|
61547
|
+
throw new Error("agents add no longer accepts --bootstrap; use --bot-type personal or --bot-type team");
|
|
61548
|
+
}
|
|
61549
|
+
if (hasFlag(args, "--mode")) {
|
|
61550
|
+
throw new Error("agents add does not use --mode; use --bot-type personal or --bot-type team");
|
|
61376
61551
|
}
|
|
61377
61552
|
const cliTool = parseSingleOption(args, "--cli");
|
|
61378
61553
|
if (!cliTool || !(cliTool in DEFAULT_AGENT_TOOL_TEMPLATES)) {
|
|
@@ -61380,9 +61555,10 @@ async function addAgent(args) {
|
|
|
61380
61555
|
}
|
|
61381
61556
|
const workspace = parseSingleOption(args, "--workspace");
|
|
61382
61557
|
const startupOptions = parseRepeatedOption(args, "--startup-option");
|
|
61383
|
-
|
|
61384
|
-
|
|
61385
|
-
|
|
61558
|
+
let bootstrap;
|
|
61559
|
+
const botType = parseSingleOption(args, "--bot-type");
|
|
61560
|
+
if (botType) {
|
|
61561
|
+
bootstrap = parseBotType(botType);
|
|
61386
61562
|
}
|
|
61387
61563
|
const bindings = parseRepeatedOption(args, "--bind").map(parseBinding);
|
|
61388
61564
|
const result = await addAgentToEditableConfig({
|
|
@@ -61404,12 +61580,19 @@ async function addAgent(args) {
|
|
|
61404
61580
|
async function bootstrapAgent(args) {
|
|
61405
61581
|
const agentId = args[0]?.trim();
|
|
61406
61582
|
if (!agentId) {
|
|
61407
|
-
throw new Error("Usage: agents bootstrap <id> --
|
|
61583
|
+
throw new Error("Usage: agents bootstrap <id> --bot-type <personal|team> [--force]");
|
|
61584
|
+
}
|
|
61585
|
+
if (hasFlag(args, "--mode")) {
|
|
61586
|
+
throw new Error("agents bootstrap no longer accepts --mode; use --bot-type personal or --bot-type team");
|
|
61587
|
+
}
|
|
61588
|
+
if (hasFlag(args, "--bootstrap")) {
|
|
61589
|
+
throw new Error("agents bootstrap does not use --bootstrap; use --bot-type personal or --bot-type team");
|
|
61408
61590
|
}
|
|
61409
|
-
const
|
|
61410
|
-
if (!
|
|
61411
|
-
throw new Error("agents bootstrap requires --
|
|
61591
|
+
const botType = parseSingleOption(args, "--bot-type");
|
|
61592
|
+
if (!botType) {
|
|
61593
|
+
throw new Error("agents bootstrap requires --bot-type personal or --bot-type team");
|
|
61412
61594
|
}
|
|
61595
|
+
const mode = parseBotType(botType);
|
|
61413
61596
|
const force = hasFlag(args, "--force");
|
|
61414
61597
|
const { config, configPath } = await readEditableConfig(getEditableConfigPath());
|
|
61415
61598
|
const entry = ensureAgentExists(config, agentId);
|
|
@@ -64959,6 +65142,8 @@ var PASTE_CAPTURE_REVALIDATE_POLL_INTERVAL_MS = 40;
|
|
|
64959
65142
|
var PASTE_CAPTURE_REVALIDATE_MAX_WAIT_MS = 160;
|
|
64960
65143
|
var SUBMIT_CONFIRM_POLL_INTERVAL_MS = 40;
|
|
64961
65144
|
var SUBMIT_CONFIRM_MAX_WAIT_MS = 160;
|
|
65145
|
+
var SUBMIT_SNAPSHOT_CONFIRM_POLL_INTERVAL_MS = 40;
|
|
65146
|
+
var SUBMIT_SNAPSHOT_CONFIRM_MAX_WAIT_MS = 320;
|
|
64962
65147
|
var TMUX_MISSING_TARGET_PATTERN = /(?:no current target|can't find pane|can't find window)/i;
|
|
64963
65148
|
var TMUX_MISSING_SESSION_PATTERN = /(?:can't find session:|no server running on )/i;
|
|
64964
65149
|
var TMUX_SERVER_UNAVAILABLE_PATTERN = /(?:No such file or directory|error connecting to|failed to connect to server)/i;
|
|
@@ -64998,15 +65183,18 @@ async function submitTmuxSessionInput(params) {
|
|
|
64998
65183
|
logLatencyDebug("tmux-paste-unconfirmed", params.timingContext, {
|
|
64999
65184
|
sessionName: params.sessionName
|
|
65000
65185
|
});
|
|
65001
|
-
|
|
65186
|
+
preSubmitState = prePasteState;
|
|
65187
|
+
} else {
|
|
65188
|
+
preSubmitState = await params.tmux.getPaneState(params.sessionName);
|
|
65002
65189
|
}
|
|
65003
|
-
preSubmitState = await params.tmux.getPaneState(params.sessionName);
|
|
65004
65190
|
}
|
|
65005
65191
|
await params.tmux.sendKey(params.sessionName, "Enter");
|
|
65006
65192
|
if (await waitForPaneSubmitConfirmation({
|
|
65007
65193
|
tmux: params.tmux,
|
|
65008
65194
|
sessionName: params.sessionName,
|
|
65009
|
-
baseline: preSubmitState
|
|
65195
|
+
baseline: preSubmitState,
|
|
65196
|
+
baselineSnapshot: prePasteSnapshot,
|
|
65197
|
+
captureLines
|
|
65010
65198
|
})) {
|
|
65011
65199
|
return;
|
|
65012
65200
|
}
|
|
@@ -65017,10 +65205,15 @@ async function submitTmuxSessionInput(params) {
|
|
|
65017
65205
|
if (await waitForPaneSubmitConfirmation({
|
|
65018
65206
|
tmux: params.tmux,
|
|
65019
65207
|
sessionName: params.sessionName,
|
|
65020
|
-
baseline: preSubmitState
|
|
65208
|
+
baseline: preSubmitState,
|
|
65209
|
+
baselineSnapshot: prePasteSnapshot,
|
|
65210
|
+
captureLines
|
|
65021
65211
|
})) {
|
|
65022
65212
|
return;
|
|
65023
65213
|
}
|
|
65214
|
+
if (!pasteSettlement.visible) {
|
|
65215
|
+
throw new Error("tmux paste was not confirmed before Enter, and submission still could not be confirmed after Enter. clisbot did not treat the prompt as truthfully delivered.");
|
|
65216
|
+
}
|
|
65024
65217
|
logLatencyDebug("tmux-submit-unconfirmed", params.timingContext, {
|
|
65025
65218
|
sessionName: params.sessionName
|
|
65026
65219
|
});
|
|
@@ -65190,6 +65383,16 @@ async function waitForPaneSubmitConfirmation(params) {
|
|
|
65190
65383
|
if (hasPaneStateChanged(params.baseline, state)) {
|
|
65191
65384
|
return true;
|
|
65192
65385
|
}
|
|
65386
|
+
const snapshotChanged = await waitForPaneSubmitSnapshotConfirmation({
|
|
65387
|
+
tmux: params.tmux,
|
|
65388
|
+
sessionName: params.sessionName,
|
|
65389
|
+
baselineSnapshot: params.baselineSnapshot,
|
|
65390
|
+
captureLines: params.captureLines,
|
|
65391
|
+
maxWaitMs: Math.min(SUBMIT_SNAPSHOT_CONFIRM_MAX_WAIT_MS, Math.max(0, deadline - Date.now()))
|
|
65392
|
+
});
|
|
65393
|
+
if (snapshotChanged) {
|
|
65394
|
+
return true;
|
|
65395
|
+
}
|
|
65193
65396
|
const remainingMs = deadline - Date.now();
|
|
65194
65397
|
if (remainingMs <= 0) {
|
|
65195
65398
|
return false;
|
|
@@ -65197,6 +65400,20 @@ async function waitForPaneSubmitConfirmation(params) {
|
|
|
65197
65400
|
await sleep(Math.min(SUBMIT_CONFIRM_POLL_INTERVAL_MS, remainingMs));
|
|
65198
65401
|
}
|
|
65199
65402
|
}
|
|
65403
|
+
async function waitForPaneSubmitSnapshotConfirmation(params) {
|
|
65404
|
+
const deadline = Date.now() + params.maxWaitMs;
|
|
65405
|
+
while (true) {
|
|
65406
|
+
const snapshot = normalizePaneText(await params.tmux.capturePane(params.sessionName, params.captureLines));
|
|
65407
|
+
if (snapshot !== params.baselineSnapshot) {
|
|
65408
|
+
return true;
|
|
65409
|
+
}
|
|
65410
|
+
const remainingMs = deadline - Date.now();
|
|
65411
|
+
if (remainingMs <= 0) {
|
|
65412
|
+
return false;
|
|
65413
|
+
}
|
|
65414
|
+
await sleep(Math.min(SUBMIT_SNAPSHOT_CONFIRM_POLL_INTERVAL_MS, remainingMs));
|
|
65415
|
+
}
|
|
65416
|
+
}
|
|
65200
65417
|
async function waitForPanePasteSettlement(params) {
|
|
65201
65418
|
await sleep(params.minDelayMs);
|
|
65202
65419
|
let currentState = await params.tmux.getPaneState(params.sessionName);
|
|
@@ -65513,32 +65730,38 @@ class RunnerService {
|
|
|
65513
65730
|
pollIntervalMs: capture.pollIntervalMs
|
|
65514
65731
|
});
|
|
65515
65732
|
}
|
|
65516
|
-
async retryFreshStartWithClearedSessionId(target, resolved,
|
|
65517
|
-
if (
|
|
65733
|
+
async retryFreshStartWithClearedSessionId(target, resolved, remainingFreshRetries) {
|
|
65734
|
+
if (remainingFreshRetries <= 0) {
|
|
65518
65735
|
return null;
|
|
65519
65736
|
}
|
|
65520
65737
|
await this.tmux.killSession(resolved.sessionName);
|
|
65521
65738
|
await this.sessionState.clearSessionIdEntry(resolved, {
|
|
65522
65739
|
runnerCommand: resolved.runner.command
|
|
65523
65740
|
});
|
|
65741
|
+
if (resolved.runner.startupRetryDelayMs > 0) {
|
|
65742
|
+
await sleep(resolved.runner.startupRetryDelayMs);
|
|
65743
|
+
}
|
|
65524
65744
|
return this.ensureSessionReady(target, {
|
|
65525
|
-
|
|
65745
|
+
remainingFreshRetries: remainingFreshRetries - 1
|
|
65526
65746
|
});
|
|
65527
65747
|
}
|
|
65528
|
-
async retryAfterStartupFault(target, resolved, error,
|
|
65748
|
+
async retryAfterStartupFault(target, resolved, error, remainingFreshRetries) {
|
|
65529
65749
|
if (!isRecoverableStartupSessionLoss(error)) {
|
|
65530
65750
|
return null;
|
|
65531
65751
|
}
|
|
65532
|
-
return this.retryFreshStartWithClearedSessionId(target, resolved,
|
|
65533
|
-
allowRetry: allowFreshRetry,
|
|
65534
|
-
nextAllowFreshRetry: false
|
|
65535
|
-
});
|
|
65752
|
+
return this.retryFreshStartWithClearedSessionId(target, resolved, remainingFreshRetries);
|
|
65536
65753
|
}
|
|
65537
|
-
async retryAfterStartupTimeout(target, resolved,
|
|
65538
|
-
return this.retryFreshStartWithClearedSessionId(target, resolved,
|
|
65539
|
-
|
|
65540
|
-
|
|
65541
|
-
|
|
65754
|
+
async retryAfterStartupTimeout(target, resolved, remainingFreshRetries) {
|
|
65755
|
+
return this.retryFreshStartWithClearedSessionId(target, resolved, remainingFreshRetries);
|
|
65756
|
+
}
|
|
65757
|
+
resolveRemainingFreshRetries(resolved, options) {
|
|
65758
|
+
if (typeof options.remainingFreshRetries === "number") {
|
|
65759
|
+
return options.remainingFreshRetries;
|
|
65760
|
+
}
|
|
65761
|
+
if (options.allowFreshRetry === false) {
|
|
65762
|
+
return 0;
|
|
65763
|
+
}
|
|
65764
|
+
return resolved.runner.startupRetryCount;
|
|
65542
65765
|
}
|
|
65543
65766
|
async abortUnreadySession(resolved, reason, snapshot) {
|
|
65544
65767
|
await this.tmux.killSession(resolved.sessionName);
|
|
@@ -65612,6 +65835,7 @@ class RunnerService {
|
|
|
65612
65835
|
sessionKey: resolved.sessionKey,
|
|
65613
65836
|
sessionName: resolved.sessionName
|
|
65614
65837
|
};
|
|
65838
|
+
const remainingFreshRetries = this.resolveRemainingFreshRetries(resolved, options);
|
|
65615
65839
|
logLatencyDebug("ensure-session-ready-start", timingContext);
|
|
65616
65840
|
await ensureDir2(resolved.workspacePath);
|
|
65617
65841
|
await ensureDir2(dirname11(this.loadedConfig.raw.tmux.socketPath));
|
|
@@ -65684,7 +65908,7 @@ class RunnerService {
|
|
|
65684
65908
|
await this.abortUnreadySession(resolved, bootstrapResult.message, bootstrapResult.snapshot);
|
|
65685
65909
|
}
|
|
65686
65910
|
if (bootstrapResult.status === "timeout" && resolved.runner.startupReadyPattern) {
|
|
65687
|
-
const retried = await this.retryAfterStartupTimeout(target, resolved,
|
|
65911
|
+
const retried = await this.retryAfterStartupTimeout(target, resolved, remainingFreshRetries);
|
|
65688
65912
|
if (retried) {
|
|
65689
65913
|
return retried;
|
|
65690
65914
|
}
|
|
@@ -65695,7 +65919,7 @@ class RunnerService {
|
|
|
65695
65919
|
runnerCommand: runnerLaunch.command
|
|
65696
65920
|
});
|
|
65697
65921
|
} catch (error) {
|
|
65698
|
-
const retried = await this.retryAfterStartupFault(target, resolved, error,
|
|
65922
|
+
const retried = await this.retryAfterStartupFault(target, resolved, error, remainingFreshRetries);
|
|
65699
65923
|
if (retried) {
|
|
65700
65924
|
return retried;
|
|
65701
65925
|
}
|
|
@@ -65750,10 +65974,7 @@ class RunnerService {
|
|
|
65750
65974
|
if (options.allowFreshRetryBeforePrompt === false || !isRecoverableStartupSessionLoss(error)) {
|
|
65751
65975
|
throw await this.mapSessionError(error, resolved.sessionName, "before prompt submission", resolved.sessionName ? await this.captureSessionSnapshot(resolved).catch(() => "") : "");
|
|
65752
65976
|
}
|
|
65753
|
-
const retried = await this.retryFreshStartWithClearedSessionId(target, resolved,
|
|
65754
|
-
allowRetry: true,
|
|
65755
|
-
nextAllowFreshRetry: false
|
|
65756
|
-
});
|
|
65977
|
+
const retried = await this.retryFreshStartWithClearedSessionId(target, resolved, resolved.runner.startupRetryCount);
|
|
65757
65978
|
if (!retried) {
|
|
65758
65979
|
throw await this.mapSessionError(error, resolved.sessionName, "before prompt submission", resolved.sessionName ? await this.captureSessionSnapshot(resolved).catch(() => "") : "");
|
|
65759
65980
|
}
|
|
@@ -66262,6 +66483,29 @@ class SessionService {
|
|
|
66262
66483
|
canSteerActiveRun(target) {
|
|
66263
66484
|
return this.activeRuns.get(target.sessionKey)?.steeringReady ?? false;
|
|
66264
66485
|
}
|
|
66486
|
+
async submitSessionInput(target, text) {
|
|
66487
|
+
const result = await this.runnerSessions.submitSessionInput(target, text);
|
|
66488
|
+
const run = this.activeRuns.get(target.sessionKey);
|
|
66489
|
+
if (!run) {
|
|
66490
|
+
return result;
|
|
66491
|
+
}
|
|
66492
|
+
const startedAt = Date.now();
|
|
66493
|
+
run.startedAt = startedAt;
|
|
66494
|
+
if (run.latestUpdate.status === "detached") {
|
|
66495
|
+
run.latestUpdate = this.createRunUpdate({
|
|
66496
|
+
resolved: run.resolved,
|
|
66497
|
+
status: "running",
|
|
66498
|
+
snapshot: run.latestUpdate.snapshot,
|
|
66499
|
+
fullSnapshot: run.latestUpdate.fullSnapshot,
|
|
66500
|
+
initialSnapshot: run.latestUpdate.initialSnapshot
|
|
66501
|
+
});
|
|
66502
|
+
}
|
|
66503
|
+
await this.sessionState.setSessionRuntime(run.resolved, {
|
|
66504
|
+
state: "running",
|
|
66505
|
+
startedAt
|
|
66506
|
+
});
|
|
66507
|
+
return result;
|
|
66508
|
+
}
|
|
66265
66509
|
async stop() {
|
|
66266
66510
|
this.stopping = true;
|
|
66267
66511
|
const activeRuns = [...this.activeRuns.values()];
|
|
@@ -66706,7 +66950,7 @@ class AgentService {
|
|
|
66706
66950
|
return this.activeRuns.canSteerActiveRun(target);
|
|
66707
66951
|
}
|
|
66708
66952
|
async submitSessionInput(target, text) {
|
|
66709
|
-
return this.
|
|
66953
|
+
return this.activeRuns.submitSessionInput(target, text);
|
|
66710
66954
|
}
|
|
66711
66955
|
isSessionBusy(target) {
|
|
66712
66956
|
return this.activeRuns.hasActiveRun(target) || this.queue.isBusy(target.sessionKey);
|
|
@@ -74523,7 +74767,7 @@ function extractLinuxProcState(raw) {
|
|
|
74523
74767
|
function getEditableConfigPath5() {
|
|
74524
74768
|
return process.env.CLISBOT_CONFIG_PATH;
|
|
74525
74769
|
}
|
|
74526
|
-
function
|
|
74770
|
+
function parseOptionValue2(args, name) {
|
|
74527
74771
|
const index = args.findIndex((arg) => arg === name);
|
|
74528
74772
|
if (index === -1) {
|
|
74529
74773
|
return;
|
|
@@ -74534,6 +74778,21 @@ function parseOptionValue(args, name) {
|
|
|
74534
74778
|
}
|
|
74535
74779
|
return value;
|
|
74536
74780
|
}
|
|
74781
|
+
function parseAliasedOptionValue(args, names, label) {
|
|
74782
|
+
const values = names.flatMap((name) => {
|
|
74783
|
+
const value = parseOptionValue2(args, name);
|
|
74784
|
+
return value === undefined ? [] : [{ name, value }];
|
|
74785
|
+
});
|
|
74786
|
+
if (values.length === 0) {
|
|
74787
|
+
return;
|
|
74788
|
+
}
|
|
74789
|
+
const distinctValues = Array.from(new Set(values.map((entry) => entry.value)));
|
|
74790
|
+
if (distinctValues.length > 1) {
|
|
74791
|
+
const seen = values.map((entry) => `${entry.name}=${entry.value}`).join(", ");
|
|
74792
|
+
throw new Error(`Conflicting values for ${label}: ${seen}`);
|
|
74793
|
+
}
|
|
74794
|
+
return values[values.length - 1]?.value;
|
|
74795
|
+
}
|
|
74537
74796
|
function hasFlag2(args, name) {
|
|
74538
74797
|
return args.includes(name);
|
|
74539
74798
|
}
|
|
@@ -74564,13 +74823,14 @@ function renderAccountsHelp() {
|
|
|
74564
74823
|
"Usage:",
|
|
74565
74824
|
" clisbot accounts --help",
|
|
74566
74825
|
" clisbot accounts help",
|
|
74567
|
-
" clisbot accounts add telegram --account <id> --token <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
74568
|
-
" clisbot accounts add slack --account <id> --app-token <ENV_NAME|${ENV_NAME}|literal> --bot-token <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
74826
|
+
" clisbot accounts add telegram --account <id> (--token | --telegram-bot-token) <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
74827
|
+
" clisbot accounts add slack --account <id> (--app-token | --slack-app-token) <ENV_NAME|${ENV_NAME}|literal> (--bot-token | --slack-bot-token) <ENV_NAME|${ENV_NAME}|literal> [--persist]",
|
|
74569
74828
|
" clisbot accounts persist --channel <slack|telegram> --account <id>",
|
|
74570
74829
|
" clisbot accounts persist --all",
|
|
74571
74830
|
"",
|
|
74572
74831
|
"Notes:",
|
|
74573
74832
|
" - env-style input such as `TELEGRAM_BOT_TOKEN` or `${TELEGRAM_BOT_TOKEN}` keeps the account env-backed in config",
|
|
74833
|
+
" - `accounts add` accepts both the short account-local flags and the bootstrap-style channel flags",
|
|
74574
74834
|
" - literal token input without `--persist` stays runtime-only and requires a running clisbot runtime",
|
|
74575
74835
|
" - `--persist` writes canonical token files so later plain `clisbot start` can reuse the account safely",
|
|
74576
74836
|
" - `persist --all` converts every configured `credentialType=mem` account into canonical token files"
|
|
@@ -74578,8 +74838,8 @@ function renderAccountsHelp() {
|
|
|
74578
74838
|
`);
|
|
74579
74839
|
}
|
|
74580
74840
|
async function addTelegramAccount(args, deps) {
|
|
74581
|
-
const accountId =
|
|
74582
|
-
const token = parseTokenInput(
|
|
74841
|
+
const accountId = parseOptionValue2(args, "--account") ?? "default";
|
|
74842
|
+
const token = parseTokenInput(parseAliasedOptionValue(args, ["--token", "--telegram-bot-token"], "telegram bot token") ?? "");
|
|
74583
74843
|
const persist = hasFlag2(args, "--persist");
|
|
74584
74844
|
const runtimeStatus = await deps.getRuntimeStatus();
|
|
74585
74845
|
if (token.kind === "mem" && !persist && !runtimeStatus.running) {
|
|
@@ -74615,9 +74875,9 @@ async function addTelegramAccount(args, deps) {
|
|
|
74615
74875
|
console.log(`config: ${configPath}`);
|
|
74616
74876
|
}
|
|
74617
74877
|
async function addSlackAccount(args, deps) {
|
|
74618
|
-
const accountId =
|
|
74619
|
-
const appToken = parseTokenInput(
|
|
74620
|
-
const botToken = parseTokenInput(
|
|
74878
|
+
const accountId = parseOptionValue2(args, "--account") ?? "default";
|
|
74879
|
+
const appToken = parseTokenInput(parseAliasedOptionValue(args, ["--app-token", "--slack-app-token"], "slack app token") ?? "");
|
|
74880
|
+
const botToken = parseTokenInput(parseAliasedOptionValue(args, ["--bot-token", "--slack-bot-token"], "slack bot token") ?? "");
|
|
74621
74881
|
const persist = hasFlag2(args, "--persist");
|
|
74622
74882
|
const runtimeStatus = await deps.getRuntimeStatus();
|
|
74623
74883
|
if (appToken.kind !== botToken.kind) {
|
|
@@ -74772,8 +75032,8 @@ async function runAccountsCli(args, deps = {}) {
|
|
|
74772
75032
|
await persistAllConfiguredAccounts(resolvedDeps);
|
|
74773
75033
|
return;
|
|
74774
75034
|
}
|
|
74775
|
-
const provider =
|
|
74776
|
-
const accountId =
|
|
75035
|
+
const provider = parseOptionValue2(args, "--channel");
|
|
75036
|
+
const accountId = parseOptionValue2(args, "--account") ?? "default";
|
|
74777
75037
|
if (provider !== "slack" && provider !== "telegram") {
|
|
74778
75038
|
throw new Error(renderAccountsHelp());
|
|
74779
75039
|
}
|
|
@@ -75273,7 +75533,7 @@ function parseResponseModeTarget(channel, raw) {
|
|
|
75273
75533
|
}
|
|
75274
75534
|
return target;
|
|
75275
75535
|
}
|
|
75276
|
-
function
|
|
75536
|
+
function parseOptionValue3(args, name) {
|
|
75277
75537
|
const index = args.findIndex((arg) => arg === name);
|
|
75278
75538
|
if (index === -1) {
|
|
75279
75539
|
return;
|
|
@@ -75285,7 +75545,7 @@ function parseOptionValue2(args, name) {
|
|
|
75285
75545
|
return value;
|
|
75286
75546
|
}
|
|
75287
75547
|
function parseBooleanOption(args, name, fallback) {
|
|
75288
|
-
const raw =
|
|
75548
|
+
const raw = parseOptionValue3(args, name);
|
|
75289
75549
|
if (!raw) {
|
|
75290
75550
|
return fallback;
|
|
75291
75551
|
}
|
|
@@ -75298,7 +75558,7 @@ function parseBooleanOption(args, name, fallback) {
|
|
|
75298
75558
|
throw new Error(`${name} requires true or false`);
|
|
75299
75559
|
}
|
|
75300
75560
|
function getAgentId(args) {
|
|
75301
|
-
return
|
|
75561
|
+
return parseOptionValue3(args, "--agent") ?? "default";
|
|
75302
75562
|
}
|
|
75303
75563
|
async function setChannelEnabled(action, channel) {
|
|
75304
75564
|
const { config, configPath } = await readEditableConfig(getEditableConfigPath7());
|
|
@@ -75322,7 +75582,7 @@ async function addTelegramGroup(args) {
|
|
|
75322
75582
|
throw new Error("Usage: clisbot channels add telegram-group <chatId> [--topic <topicId>] [--agent <id>] [--require-mention true|false]");
|
|
75323
75583
|
}
|
|
75324
75584
|
const { config, configPath } = await readEditableConfig(getEditableConfigPath7());
|
|
75325
|
-
const topicId =
|
|
75585
|
+
const topicId = parseOptionValue3(args, "--topic");
|
|
75326
75586
|
const agentId = getAgentId(args);
|
|
75327
75587
|
const requireMention = parseBooleanOption(args, "--require-mention", true);
|
|
75328
75588
|
const groupRoute = config.channels.telegram.groups[chatId] ?? {
|
|
@@ -75375,7 +75635,7 @@ async function removeTelegramGroup(args) {
|
|
|
75375
75635
|
throw new Error("Usage: clisbot channels remove telegram-group <chatId> [--topic <topicId>]");
|
|
75376
75636
|
}
|
|
75377
75637
|
const { config, configPath } = await readEditableConfig(getEditableConfigPath7());
|
|
75378
|
-
const topicId =
|
|
75638
|
+
const topicId = parseOptionValue3(args, "--topic");
|
|
75379
75639
|
const groupRoute = config.channels.telegram.groups[chatId];
|
|
75380
75640
|
if (!groupRoute) {
|
|
75381
75641
|
console.log(`telegram group route ${chatId} is not configured`);
|
|
@@ -75517,9 +75777,9 @@ async function runResponseModeCli(args) {
|
|
|
75517
75777
|
}
|
|
75518
75778
|
const responseMode = action === "set" ? parseResponseMode2(args[1]) : undefined;
|
|
75519
75779
|
const optionArgs = action === "set" ? args.slice(2) : args.slice(1);
|
|
75520
|
-
const channel = parseResponseModeChannel(
|
|
75521
|
-
const target = parseResponseModeTarget(channel,
|
|
75522
|
-
const topic =
|
|
75780
|
+
const channel = parseResponseModeChannel(parseOptionValue3(optionArgs, "--channel"));
|
|
75781
|
+
const target = parseResponseModeTarget(channel, parseOptionValue3(optionArgs, "--target"));
|
|
75782
|
+
const topic = parseOptionValue3(optionArgs, "--topic");
|
|
75523
75783
|
if (channel === "slack" && topic) {
|
|
75524
75784
|
throw new Error("Slack response-mode commands do not support --topic");
|
|
75525
75785
|
}
|
|
@@ -75551,9 +75811,9 @@ async function runAdditionalMessageModeCli(args) {
|
|
|
75551
75811
|
}
|
|
75552
75812
|
const additionalMessageMode = action === "set" ? parseAdditionalMessageMode2(args[1]) : undefined;
|
|
75553
75813
|
const optionArgs = action === "set" ? args.slice(2) : args.slice(1);
|
|
75554
|
-
const channel = parseResponseModeChannel(
|
|
75555
|
-
const target = parseResponseModeTarget(channel,
|
|
75556
|
-
const topic =
|
|
75814
|
+
const channel = parseResponseModeChannel(parseOptionValue3(optionArgs, "--channel"));
|
|
75815
|
+
const target = parseResponseModeTarget(channel, parseOptionValue3(optionArgs, "--target"));
|
|
75816
|
+
const topic = parseOptionValue3(optionArgs, "--topic");
|
|
75557
75817
|
if (channel === "slack" && topic) {
|
|
75558
75818
|
throw new Error("Slack additional-message-mode commands do not support --topic");
|
|
75559
75819
|
}
|
|
@@ -75843,7 +76103,7 @@ function parseRepeatedOption3(args, name) {
|
|
|
75843
76103
|
}
|
|
75844
76104
|
return values;
|
|
75845
76105
|
}
|
|
75846
|
-
function
|
|
76106
|
+
function parseOptionValue4(args, name) {
|
|
75847
76107
|
const values = parseRepeatedOption3(args, name);
|
|
75848
76108
|
return values.length > 0 ? values.at(-1) : undefined;
|
|
75849
76109
|
}
|
|
@@ -75856,7 +76116,7 @@ function parseMessageBodyFileOption(args) {
|
|
|
75856
76116
|
return bodyFileValues.at(-1) ?? messageFileValues.at(-1);
|
|
75857
76117
|
}
|
|
75858
76118
|
function parseIntegerOption(args, name) {
|
|
75859
|
-
const raw =
|
|
76119
|
+
const raw = parseOptionValue4(args, name);
|
|
75860
76120
|
if (!raw) {
|
|
75861
76121
|
return;
|
|
75862
76122
|
}
|
|
@@ -75885,34 +76145,34 @@ function parseMessageCommand(args) {
|
|
|
75885
76145
|
}
|
|
75886
76146
|
const action = rawAction;
|
|
75887
76147
|
const rest = args.slice(1);
|
|
75888
|
-
const channel =
|
|
76148
|
+
const channel = parseOptionValue4(rest, "--channel");
|
|
75889
76149
|
if (channel !== "slack" && channel !== "telegram") {
|
|
75890
76150
|
throw new Error("--channel <slack|telegram> is required");
|
|
75891
76151
|
}
|
|
75892
76152
|
return {
|
|
75893
76153
|
action,
|
|
75894
76154
|
channel,
|
|
75895
|
-
account:
|
|
75896
|
-
target:
|
|
75897
|
-
message:
|
|
76155
|
+
account: parseOptionValue4(rest, "--account"),
|
|
76156
|
+
target: parseOptionValue4(rest, "--target"),
|
|
76157
|
+
message: parseOptionValue4(rest, "--message") ?? parseOptionValue4(rest, "-m"),
|
|
75898
76158
|
messageFile: parseMessageBodyFileOption(rest),
|
|
75899
|
-
media:
|
|
75900
|
-
messageId:
|
|
75901
|
-
emoji:
|
|
76159
|
+
media: parseOptionValue4(rest, "--media"),
|
|
76160
|
+
messageId: parseOptionValue4(rest, "--message-id"),
|
|
76161
|
+
emoji: parseOptionValue4(rest, "--emoji"),
|
|
75902
76162
|
remove: hasFlag4(rest, "--remove"),
|
|
75903
|
-
threadId:
|
|
75904
|
-
replyTo:
|
|
76163
|
+
threadId: parseOptionValue4(rest, "--thread-id"),
|
|
76164
|
+
replyTo: parseOptionValue4(rest, "--reply-to"),
|
|
75905
76165
|
limit: parseIntegerOption(rest, "--limit"),
|
|
75906
|
-
query:
|
|
75907
|
-
pollQuestion:
|
|
76166
|
+
query: parseOptionValue4(rest, "--query"),
|
|
76167
|
+
pollQuestion: parseOptionValue4(rest, "--poll-question"),
|
|
75908
76168
|
pollOptions: parseRepeatedOption3(rest, "--poll-option"),
|
|
75909
76169
|
forceDocument: hasFlag4(rest, "--force-document"),
|
|
75910
76170
|
silent: hasFlag4(rest, "--silent"),
|
|
75911
76171
|
progress: hasFlag4(rest, "--progress"),
|
|
75912
76172
|
final: hasFlag4(rest, "--final"),
|
|
75913
76173
|
json: hasFlag4(rest, "--json"),
|
|
75914
|
-
inputFormat: parseMessageInputFormat(
|
|
75915
|
-
renderMode: parseMessageRenderMode(
|
|
76174
|
+
inputFormat: parseMessageInputFormat(parseOptionValue4(rest, "--input")),
|
|
76175
|
+
renderMode: parseMessageRenderMode(parseOptionValue4(rest, "--render"))
|
|
75916
76176
|
};
|
|
75917
76177
|
}
|
|
75918
76178
|
function renderMessageHelp() {
|
|
@@ -76017,162 +76277,6 @@ async function runMessageCli(args, dependencies = defaultMessageCliDependencies)
|
|
|
76017
76277
|
dependencies.print(JSON.stringify(execution.result, null, 2));
|
|
76018
76278
|
}
|
|
76019
76279
|
|
|
76020
|
-
// src/control/channel-bootstrap-flags.ts
|
|
76021
|
-
function isLiteralToken(token) {
|
|
76022
|
-
return token?.kind === "mem";
|
|
76023
|
-
}
|
|
76024
|
-
function parseBotType(rawValue) {
|
|
76025
|
-
const value = rawValue.trim().toLowerCase();
|
|
76026
|
-
if (value === "personal" || value === "personal-assistant") {
|
|
76027
|
-
return "personal-assistant";
|
|
76028
|
-
}
|
|
76029
|
-
if (value === "team" || value === "team-assistant") {
|
|
76030
|
-
return "team-assistant";
|
|
76031
|
-
}
|
|
76032
|
-
throw new Error(`Invalid bot type: ${rawValue}`);
|
|
76033
|
-
}
|
|
76034
|
-
function parseOptionValue4(args, name, index) {
|
|
76035
|
-
const value = args[index + 1]?.trim();
|
|
76036
|
-
if (!value) {
|
|
76037
|
-
throw new Error(`Missing value for ${name}`);
|
|
76038
|
-
}
|
|
76039
|
-
return value;
|
|
76040
|
-
}
|
|
76041
|
-
function getOrCreateSlackAccount(accounts, accountId) {
|
|
76042
|
-
let account = accounts.find((entry) => entry.accountId === accountId);
|
|
76043
|
-
if (!account) {
|
|
76044
|
-
account = { accountId };
|
|
76045
|
-
accounts.push(account);
|
|
76046
|
-
}
|
|
76047
|
-
return account;
|
|
76048
|
-
}
|
|
76049
|
-
function getOrCreateTelegramAccount(accounts, accountId) {
|
|
76050
|
-
let account = accounts.find((entry) => entry.accountId === accountId);
|
|
76051
|
-
if (!account) {
|
|
76052
|
-
account = { accountId };
|
|
76053
|
-
accounts.push(account);
|
|
76054
|
-
}
|
|
76055
|
-
return account;
|
|
76056
|
-
}
|
|
76057
|
-
function ensureUniqueAccount(accounts, accountId, flagName) {
|
|
76058
|
-
if (accounts.some((entry) => entry.accountId === accountId)) {
|
|
76059
|
-
throw new Error(`Duplicate ${flagName} ${accountId}`);
|
|
76060
|
-
}
|
|
76061
|
-
}
|
|
76062
|
-
function validateSlackAccount(account) {
|
|
76063
|
-
if (!account.appToken || !account.botToken) {
|
|
76064
|
-
throw new Error(`Slack account ${account.accountId} requires both app token and bot token`);
|
|
76065
|
-
}
|
|
76066
|
-
if (account.appToken.kind !== account.botToken.kind) {
|
|
76067
|
-
throw new Error(`Slack account ${account.accountId} must use one credential source kind for both app and bot tokens`);
|
|
76068
|
-
}
|
|
76069
|
-
}
|
|
76070
|
-
function validateTelegramAccount(account) {
|
|
76071
|
-
if (!account.botToken) {
|
|
76072
|
-
throw new Error(`Telegram account ${account.accountId} requires a bot token`);
|
|
76073
|
-
}
|
|
76074
|
-
}
|
|
76075
|
-
function parseBootstrapFlags(args) {
|
|
76076
|
-
const slackAccounts = [];
|
|
76077
|
-
const telegramAccounts = [];
|
|
76078
|
-
let currentSlackAccountId;
|
|
76079
|
-
let currentTelegramAccountId;
|
|
76080
|
-
let cliTool;
|
|
76081
|
-
let bootstrap;
|
|
76082
|
-
let persist = false;
|
|
76083
|
-
let sawCredentialFlags = false;
|
|
76084
|
-
let sawSlackFlags = false;
|
|
76085
|
-
let sawTelegramFlags = false;
|
|
76086
|
-
for (let index = 0;index < args.length; index += 1) {
|
|
76087
|
-
const arg = args[index];
|
|
76088
|
-
if (arg === "--cli") {
|
|
76089
|
-
cliTool = parseOptionValue4(args, arg, index);
|
|
76090
|
-
index += 1;
|
|
76091
|
-
continue;
|
|
76092
|
-
}
|
|
76093
|
-
if (arg === "--bootstrap") {
|
|
76094
|
-
bootstrap = parseBotType(parseOptionValue4(args, arg, index));
|
|
76095
|
-
index += 1;
|
|
76096
|
-
continue;
|
|
76097
|
-
}
|
|
76098
|
-
if (arg === "--bot-type") {
|
|
76099
|
-
bootstrap = parseBotType(parseOptionValue4(args, arg, index));
|
|
76100
|
-
index += 1;
|
|
76101
|
-
continue;
|
|
76102
|
-
}
|
|
76103
|
-
if (arg === "--persist") {
|
|
76104
|
-
persist = true;
|
|
76105
|
-
continue;
|
|
76106
|
-
}
|
|
76107
|
-
if (arg === "--slack-account") {
|
|
76108
|
-
const accountId = parseOptionValue4(args, arg, index);
|
|
76109
|
-
ensureUniqueAccount(slackAccounts, accountId, "--slack-account");
|
|
76110
|
-
currentSlackAccountId = accountId;
|
|
76111
|
-
getOrCreateSlackAccount(slackAccounts, accountId);
|
|
76112
|
-
sawSlackFlags = true;
|
|
76113
|
-
index += 1;
|
|
76114
|
-
continue;
|
|
76115
|
-
}
|
|
76116
|
-
if (arg === "--telegram-account") {
|
|
76117
|
-
const accountId = parseOptionValue4(args, arg, index);
|
|
76118
|
-
ensureUniqueAccount(telegramAccounts, accountId, "--telegram-account");
|
|
76119
|
-
currentTelegramAccountId = accountId;
|
|
76120
|
-
getOrCreateTelegramAccount(telegramAccounts, accountId);
|
|
76121
|
-
sawTelegramFlags = true;
|
|
76122
|
-
index += 1;
|
|
76123
|
-
continue;
|
|
76124
|
-
}
|
|
76125
|
-
if (arg === "--slack-app-token") {
|
|
76126
|
-
const token = parseTokenInput(parseOptionValue4(args, arg, index));
|
|
76127
|
-
const account = getOrCreateSlackAccount(slackAccounts, currentSlackAccountId ?? "default");
|
|
76128
|
-
account.appToken = token;
|
|
76129
|
-
sawCredentialFlags = true;
|
|
76130
|
-
sawSlackFlags = true;
|
|
76131
|
-
index += 1;
|
|
76132
|
-
continue;
|
|
76133
|
-
}
|
|
76134
|
-
if (arg === "--slack-bot-token") {
|
|
76135
|
-
const token = parseTokenInput(parseOptionValue4(args, arg, index));
|
|
76136
|
-
const account = getOrCreateSlackAccount(slackAccounts, currentSlackAccountId ?? "default");
|
|
76137
|
-
account.botToken = token;
|
|
76138
|
-
sawCredentialFlags = true;
|
|
76139
|
-
sawSlackFlags = true;
|
|
76140
|
-
index += 1;
|
|
76141
|
-
continue;
|
|
76142
|
-
}
|
|
76143
|
-
if (arg === "--telegram-bot-token") {
|
|
76144
|
-
const token = parseTokenInput(parseOptionValue4(args, arg, index));
|
|
76145
|
-
const account = getOrCreateTelegramAccount(telegramAccounts, currentTelegramAccountId ?? "default");
|
|
76146
|
-
account.botToken = token;
|
|
76147
|
-
sawCredentialFlags = true;
|
|
76148
|
-
sawTelegramFlags = true;
|
|
76149
|
-
index += 1;
|
|
76150
|
-
continue;
|
|
76151
|
-
}
|
|
76152
|
-
throw new Error(`Unknown option for start/init: ${arg}`);
|
|
76153
|
-
}
|
|
76154
|
-
for (const account of slackAccounts) {
|
|
76155
|
-
validateSlackAccount(account);
|
|
76156
|
-
}
|
|
76157
|
-
for (const account of telegramAccounts) {
|
|
76158
|
-
validateTelegramAccount(account);
|
|
76159
|
-
}
|
|
76160
|
-
return {
|
|
76161
|
-
cliTool,
|
|
76162
|
-
bootstrap,
|
|
76163
|
-
persist,
|
|
76164
|
-
slackAccounts,
|
|
76165
|
-
telegramAccounts,
|
|
76166
|
-
sawCredentialFlags,
|
|
76167
|
-
sawSlackFlags,
|
|
76168
|
-
sawTelegramFlags,
|
|
76169
|
-
literalWarnings: []
|
|
76170
|
-
};
|
|
76171
|
-
}
|
|
76172
|
-
function hasLiteralBootstrapCredentials(flags) {
|
|
76173
|
-
return flags.slackAccounts.some((account) => isLiteralToken(account.appToken) || isLiteralToken(account.botToken)) || flags.telegramAccounts.some((account) => isLiteralToken(account.botToken));
|
|
76174
|
-
}
|
|
76175
|
-
|
|
76176
76280
|
// src/control/activity-store.ts
|
|
76177
76281
|
import { dirname as dirname14 } from "node:path";
|
|
76178
76282
|
class ActivityStore {
|
|
@@ -76413,10 +76517,11 @@ function appendBootstrapGuidance(lines, summary) {
|
|
|
76413
76517
|
lines.push("");
|
|
76414
76518
|
lines.push("Guidance:");
|
|
76415
76519
|
for (const agent of pendingBootstrap) {
|
|
76520
|
+
const botType = agent.bootstrapMode === "team-assistant" ? "team" : "personal";
|
|
76416
76521
|
if (agent.bootstrapState === "missing") {
|
|
76417
76522
|
lines.push(` Agent ${agent.id} is missing bootstrap files.`);
|
|
76418
76523
|
lines.push(` workspace: ${agent.workspacePath}`);
|
|
76419
|
-
lines.push(` run: clisbot agents bootstrap ${agent.id} --
|
|
76524
|
+
lines.push(` run: clisbot agents bootstrap ${agent.id} --bot-type ${botType}`);
|
|
76420
76525
|
continue;
|
|
76421
76526
|
}
|
|
76422
76527
|
lines.push(` Agent ${agent.id} still needs bootstrap completion.`);
|