clisbot 0.1.51 → 0.1.52

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.
Files changed (3) hide show
  1. package/README.md +10 -8
  2. package/dist/main.js +67 -16
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -69,8 +69,8 @@ It is not just a tmux bridge with chat glued on top. `clisbot` treats Slack and
69
69
  ### I Just Want To Know What Changed Recently
70
70
 
71
71
  - start with [Recent Release Highlights](#recent-release-highlights)
72
- - then read [v0.1.51 Release Notes](docs/releases/v0.1.51.md) or the
73
- [v0.1.51 Release Guide](docs/updates/releases/v0.1.51-release-guide.md)
72
+ - then read [v0.1.52 Release Notes](docs/releases/v0.1.52.md) or the
73
+ [v0.1.52 Release Guide](docs/updates/releases/v0.1.52-release-guide.md)
74
74
 
75
75
  ## Why I Built This
76
76
 
@@ -89,7 +89,7 @@ The challenge is not whether AI is useful. It is how to make it work at enterpri
89
89
  - Team-first by design, with `AGENTS`, `USER`, and `MEMORY` context bootstrapping shaped for shared team reality instead of only personal solo-assistant flows.
90
90
  - Shared-surface permission control is a first-class feature: a bot can be in a team group but still answer only the specific people you allow there, while sensitive control actions stay behind explicit auth roles and permissions.
91
91
  - Useful for coding, operations, teamwork, and general assistant work, with fast chat controls such as `!<command>`, `/bash <command>`, `/queue`, `/loop`, `/streaming`, and `/mention`.
92
- - New in the `v0.1.50` to `v0.1.51` stable line: the AI-native control experience is much better, and `v0.1.51` also stretches the default runner startup window to 60 seconds so slower Codex, Claude, and Gemini launches do not time out so early.
92
+ - New in the `v0.1.50` to `v0.1.52` stable line: the AI-native control experience is much better, the default runner startup window is now 60 seconds, and stale old startup-delay pins no longer silently keep upgraded installs on shorter timeouts.
93
93
 
94
94
  ## Who This Fits Best
95
95
 
@@ -185,12 +185,12 @@ Next steps:
185
185
  - `clisbot` also has a smart autopairing path to reduce first-run friction. If
186
186
  you send the bot a DM within the first 30 minutes, you can usually claim the
187
187
  owner role immediately and start using it without a separate pairing round.
188
- - New from the current `v0.1.50` to `v0.1.51` stable line: the AI-native operator experience is much stronger. You
188
+ - New from the current `v0.1.50` to `v0.1.52` stable line: the AI-native operator experience is much stronger. You
189
189
  can increasingly ask the bot through chat to explain how to use it, update
190
190
  itself and summarize what's new, help onboard you, create or add a new bot or
191
191
  agent, or set up loops and schedules for recurring work instead of relying
192
192
  only on slash commands.
193
- - Existing configs from any version before `0.1.50` still update directly on first run when you install `v0.1.51`. clisbot writes a backup first under `~/.clisbot/backups/`, then rewrites the config to the current `0.1.50` schema shape.
193
+ - Existing configs from any version before `0.1.50` still update directly on first run when you install `v0.1.52`. clisbot writes a backup first under `~/.clisbot/backups/`, then rewrites the config to the current `0.1.50` schema shape.
194
194
  - Shared Slack channels, Slack groups, Telegram groups, and Telegram topics are a separate gate: normal users need an explicit route such as `group:<id>` or `topic:<chatId>:<topicId>` before the bot will talk there. Legacy Slack `channel:<id>` input still works for compatibility.
195
195
  - After a shared surface is admitted, per-surface sender control comes from the bot's default shared rule `groups["*"]` plus any route-local `allowUsers` or `blockUsers`.
196
196
  - With that permission model, a bot can be added to a team group but still be
@@ -237,6 +237,7 @@ What happens next:
237
237
 
238
238
  ## Recent Release Highlights
239
239
 
240
+ - `v0.1.52`: clarifies shared-route setup so `routes add ...` clearly means “use the agent currently assigned to that bot by default,” and prunes stale short `startupDelayMs` overrides so upgraded installs can actually inherit the newer 60-second startup default.
240
241
  - `v0.1.51`: raises the default runner startup window to 60 seconds across the
241
242
  standard CLI families and the shared runner fallback, so slower fresh launches
242
243
  are less likely to fail before the first prompt can be submitted.
@@ -271,6 +272,7 @@ Read the full notes here:
271
272
 
272
273
  - [CHANGELOG.md](CHANGELOG.md)
273
274
  - [Release Notes Index](docs/releases/README.md)
275
+ - [v0.1.52 Release Notes](docs/releases/v0.1.52.md)
274
276
  - [v0.1.51 Release Notes](docs/releases/v0.1.51.md)
275
277
  - [v0.1.50 Release Notes](docs/releases/v0.1.50.md)
276
278
  - [v0.1.43 Release Notes](docs/releases/v0.1.43.md)
@@ -306,9 +308,9 @@ Update note for existing installs:
306
308
  - Older installs before `v0.1.50` now update directly on first run with a
307
309
  backup written first, so most people can update and restart without a manual
308
310
  migration pass.
309
- - `v0.1.51` keeps that direct-upgrade path and does not introduce a new config
310
- schema bump; the main runtime change is a longer default runner startup
311
- window.
311
+ - `v0.1.52` keeps that direct-upgrade path and does not introduce a new config
312
+ schema bump; it also cleans up stale short startup-delay overrides that would
313
+ otherwise keep some upgraded installs on older timeout behavior.
312
314
  - After you are on the `v0.1.50` schema line, future upgrades should feel much
313
315
  more AI-native:
314
316
  in many cases you can simply ask the bot to update `clisbot` to the latest
package/dist/main.js CHANGED
@@ -62223,6 +62223,7 @@ function assertNoLegacyPrivilegeCommands(value, path = "root") {
62223
62223
  import { basename, dirname as dirname4, join as join5 } from "node:path";
62224
62224
 
62225
62225
  // src/config/persisted-config.ts
62226
+ var MIN_PERSISTED_AGENT_STARTUP_DELAY_MS = 30000;
62226
62227
  var defaultOwnedRunnerFields = {
62227
62228
  codex: ["startupDelayMs", "startupReadyPattern"],
62228
62229
  gemini: [
@@ -62265,9 +62266,22 @@ function deleteIfEmpty(owner, key) {
62265
62266
  function defaultRunner(toolId) {
62266
62267
  return buildRunnerFromToolTemplate(toolId, DEFAULT_AGENT_TOOL_TEMPLATES[toolId], undefined);
62267
62268
  }
62269
+ function isStaleStartupDelay(value) {
62270
+ return typeof value === "number" && Number.isInteger(value) && value > 0 && value < MIN_PERSISTED_AGENT_STARTUP_DELAY_MS;
62271
+ }
62272
+ function deleteStaleStartupDelay(owner) {
62273
+ if (!owner || !isStaleStartupDelay(owner.startupDelayMs)) {
62274
+ return false;
62275
+ }
62276
+ delete owner.startupDelayMs;
62277
+ return true;
62278
+ }
62268
62279
  function pruneDefaultOwnedFields(params) {
62269
62280
  const defaults = defaultRunner(params.toolId);
62270
62281
  for (const field of defaultOwnedRunnerFields[params.toolId] ?? []) {
62282
+ if (field === "startupDelayMs" && deleteStaleStartupDelay(params.target)) {
62283
+ continue;
62284
+ }
62271
62285
  if (params.force || Object.hasOwn(params.target, field) && areJsonEqual(params.target[field], defaults[field])) {
62272
62286
  delete params.target[field];
62273
62287
  }
@@ -62279,6 +62293,7 @@ function pruneAgentRunnerOverride(runner, cli) {
62279
62293
  return;
62280
62294
  }
62281
62295
  const defaults = defaultRunner(toolId);
62296
+ deleteStaleStartupDelay(runner);
62282
62297
  for (const field of [
62283
62298
  "command",
62284
62299
  "args",
@@ -62296,6 +62311,14 @@ function pruneAgentRunnerOverride(runner, cli) {
62296
62311
  }
62297
62312
  }
62298
62313
  }
62314
+ function pruneAgentRunnerDefaultOverride(runner) {
62315
+ const defaults = runner.defaults;
62316
+ if (!isRecord5(defaults)) {
62317
+ return;
62318
+ }
62319
+ deleteStaleStartupDelay(defaults);
62320
+ deleteIfEmpty(runner, "defaults");
62321
+ }
62299
62322
  function pruneRunnerDefaults(config, forceRunnerStartupDefaults) {
62300
62323
  const runner = nestedRecord(config, ["agents", "defaults", "runner"]);
62301
62324
  if (!runner) {
@@ -62304,6 +62327,9 @@ function pruneRunnerDefaults(config, forceRunnerStartupDefaults) {
62304
62327
  const runnerDefaults = runner.defaults;
62305
62328
  if (isRecord5(runnerDefaults)) {
62306
62329
  for (const [field, defaultValue] of Object.entries(defaultOwnedRunnerDefaultFields)) {
62330
+ if (field === "startupDelayMs" && deleteStaleStartupDelay(runnerDefaults)) {
62331
+ continue;
62332
+ }
62307
62333
  if (forceRunnerStartupDefaults || Object.hasOwn(runnerDefaults, field) && areJsonEqual(runnerDefaults[field], defaultValue)) {
62308
62334
  delete runnerDefaults[field];
62309
62335
  }
@@ -62329,6 +62355,7 @@ function pruneAgentOverrides(config) {
62329
62355
  if (!isRecord5(agent) || !isRecord5(agent.runner)) {
62330
62356
  continue;
62331
62357
  }
62358
+ pruneAgentRunnerDefaultOverride(agent.runner);
62332
62359
  const cli = typeof agent.cli === "string" ? inferAgentCliToolId(agent.cli) ?? undefined : undefined;
62333
62360
  pruneAgentRunnerOverride(agent.runner, cli);
62334
62361
  deleteIfEmpty(agent, "runner");
@@ -62386,15 +62413,34 @@ function pruneCurrentSchemaStartupDefaults(config) {
62386
62413
  const defaults = isRecord6(agents?.defaults) ? agents.defaults : undefined;
62387
62414
  const runner = isRecord6(defaults?.runner) ? defaults.runner : undefined;
62388
62415
  const runnerDefaults = isRecord6(runner?.defaults) ? runner.defaults : undefined;
62389
- const codexRunner = isRecord6(runner?.codex) ? runner.codex : undefined;
62416
+ const familyRunners = ["codex", "claude", "gemini"].map((family) => isRecord6(runner?.[family]) ? runner[family] : undefined);
62417
+ const agentList = Array.isArray(agents?.list) ? agents.list : [];
62390
62418
  let pruned = false;
62391
- if (runnerDefaults?.startupDelayMs === 3000) {
62392
- delete runnerDefaults.startupDelayMs;
62419
+ if (deleteStaleStartupDelay(runnerDefaults)) {
62393
62420
  pruned = true;
62394
62421
  }
62395
- if (codexRunner?.startupDelayMs === 3000) {
62396
- delete codexRunner.startupDelayMs;
62397
- pruned = true;
62422
+ for (const familyRunner of familyRunners) {
62423
+ if (deleteStaleStartupDelay(familyRunner)) {
62424
+ pruned = true;
62425
+ }
62426
+ }
62427
+ for (const agent of agentList) {
62428
+ if (!isRecord6(agent) || !isRecord6(agent.runner)) {
62429
+ continue;
62430
+ }
62431
+ if (deleteStaleStartupDelay(agent.runner)) {
62432
+ pruned = true;
62433
+ }
62434
+ const runnerDefaultsOverride = isRecord6(agent.runner.defaults) ? agent.runner.defaults : undefined;
62435
+ if (deleteStaleStartupDelay(runnerDefaultsOverride)) {
62436
+ if (runnerDefaultsOverride && Object.keys(runnerDefaultsOverride).length === 0) {
62437
+ delete agent.runner.defaults;
62438
+ }
62439
+ if (Object.keys(agent.runner).length === 0) {
62440
+ delete agent.runner;
62441
+ }
62442
+ pruned = true;
62443
+ }
62398
62444
  }
62399
62445
  if (pruned) {
62400
62446
  nextConfig.meta = {
@@ -75477,8 +75523,11 @@ function renderSlackRouteChoiceMessage(params) {
75477
75523
  return [
75478
75524
  "clisbot: this Slack channel is not configured yet.",
75479
75525
  "",
75480
- "Ask the bot owner to do these:",
75526
+ "Ask the bot owner to do this first:",
75481
75527
  `- ${renderCliCommand(`routes add --channel slack group:${params.channelId} --bot default`, { inline: true })}`,
75528
+ " This channel will use the agent currently assigned to this bot by default.",
75529
+ "",
75530
+ "Only if this channel should use a different agent than the one currently assigned to this bot by default:",
75482
75531
  `- ${renderCliCommand(`routes set-agent --channel slack group:${params.channelId} --bot default --agent <id>`, { inline: true })}`,
75483
75532
  "",
75484
75533
  `After that, ${botReference} and send \`\\start\`, \`\\status\`, or \`\\mention\` here.`
@@ -78538,16 +78587,17 @@ function renderTelegramRouteChoiceMessage(params) {
78538
78587
  const lines = [
78539
78588
  topicId != null ? "clisbot: this Telegram topic is not configured yet." : "clisbot: this Telegram group is not configured yet.",
78540
78589
  "",
78541
- "Ask the bot owner to choose one of these:",
78590
+ "Ask the bot owner to do this first:",
78542
78591
  "",
78543
- "Add the whole group to the allowlist:",
78592
+ "Add the whole group route:",
78544
78593
  renderCliCommand(`routes add --channel telegram group:${chatId} --bot default`, { inline: true }),
78594
+ "That group will use the agent currently assigned to that bot by default.",
78545
78595
  "",
78546
- "Bind the whole group to a specific agent:",
78596
+ "Only if that group should use a different agent than the one currently assigned to that bot by default:",
78547
78597
  renderCliCommand(`routes set-agent --channel telegram group:${chatId} --bot default --agent <id>`, { inline: true })
78548
78598
  ];
78549
78599
  if (topicId != null) {
78550
- lines.push("", "Or bind only this topic to a specific agent:", renderCliCommand(`routes add --channel telegram topic:${chatId}:${topicId} --bot default`, { inline: true }), renderCliCommand(`routes set-agent --channel telegram topic:${chatId}:${topicId} --bot default --agent <id>`, { inline: true }));
78600
+ lines.push("", "Or add only this topic route:", renderCliCommand(`routes add --channel telegram topic:${chatId}:${topicId} --bot default`, { inline: true }), "That topic will use the agent currently assigned to that bot by default.", "", "Only if this topic should use a different agent than the one currently assigned to that bot by default:", renderCliCommand(`routes set-agent --channel telegram topic:${chatId}:${topicId} --bot default --agent <id>`, { inline: true }));
78551
78601
  }
78552
78602
  if (params.includeConfigPath) {
78553
78603
  lines.push("", topicId != null ? `Config path: \`bots.telegram.default.groups."${chatId}".topics."${topicId}"\`` : `Config path: \`bots.telegram.default.groups."${chatId}"\``);
@@ -84868,8 +84918,8 @@ function appendChannelNextStepLines(lines, summary, prefix = "") {
84868
84918
  lines.push(`${prefix}- DM the Slack bot first to confirm it responds normally`);
84869
84919
  }
84870
84920
  lines.push(`${prefix}- after DM works, add the bot to the target Slack channel or Telegram group/topic`);
84871
- lines.push(`${prefix}- add the route with ${renderCliCommand("routes add --channel slack group:<channelId> --bot default", { inline: true })} or ${renderCliCommand("routes add --channel telegram group:<chatId> --bot default", { inline: true })}`);
84872
- lines.push(`${prefix}- bind the agent with ${renderCliCommand("routes set-agent --channel slack group:<channelId> --bot default --agent <id>", { inline: true })} or ${renderCliCommand("routes set-agent --channel telegram group:<chatId> --bot default --agent <id>", { inline: true })}`);
84921
+ lines.push(`${prefix}- add the route with ${renderCliCommand("routes add --channel slack group:<channelId> --bot default", { inline: true })} or ${renderCliCommand("routes add --channel telegram group:<chatId> --bot default", { inline: true })}; that route uses the agent currently assigned to that bot by default`);
84922
+ lines.push(`${prefix}- only if you want a different agent there than the one currently assigned to that bot by default, bind it with ${renderCliCommand("routes set-agent --channel slack group:<channelId> --bot default --agent <id>", { inline: true })} or ${renderCliCommand("routes set-agent --channel telegram group:<chatId> --bot default --agent <id>", { inline: true })}`);
84873
84923
  if (telegramEnabled) {
84874
84924
  lines.push(`${prefix}- Telegram: send \`/start\` in the target DM, group, or topic to get onboarding or pairing guidance`);
84875
84925
  }
@@ -85013,9 +85063,9 @@ function appendChannelSetupNote(lines, summary, channel, prefix) {
85013
85063
  lines.push(`${prefix} dms: ${channel.directMessagesEnabled ? `enabled (${channel.directMessagesPolicy})` : "disabled"}`);
85014
85064
  lines.push(`${prefix} sharedDefault: ${channel.sharedDefaultPolicy ?? "n/a"}`);
85015
85065
  lines.push(`${prefix} add group: ${renderCliCommand("routes add --channel telegram group:<chatId> --bot default", { inline: true })}`);
85016
- lines.push(`${prefix} bind group: ${renderCliCommand("routes set-agent --channel telegram group:<chatId> --bot default --agent <id>", { inline: true })}`);
85066
+ lines.push(`${prefix} route uses the agent currently assigned to that bot by default`);
85017
85067
  lines.push(`${prefix} add topic: ${renderCliCommand("routes add --channel telegram topic:<chatId>:<topicId> --bot default", { inline: true })}`);
85018
- lines.push(`${prefix} bind topic: ${renderCliCommand("routes set-agent --channel telegram topic:<chatId>:<topicId> --bot default --agent <id>", { inline: true })}`);
85068
+ lines.push(`${prefix} optional agent override if that surface should use a different agent than the one currently assigned to that bot by default: ${renderCliCommand("routes set-agent --channel telegram group:<chatId> --bot default --agent <id>", { inline: true })} or ${renderCliCommand("routes set-agent --channel telegram topic:<chatId>:<topicId> --bot default --agent <id>", { inline: true })}`);
85019
85069
  lines.push(`${prefix} adjust later: ${renderPrivilegedChatHint(summary, "run in-chat commands here")}`);
85020
85070
  return;
85021
85071
  }
@@ -85023,7 +85073,8 @@ function appendChannelSetupNote(lines, summary, channel, prefix) {
85023
85073
  lines.push(`${prefix} dms: ${channel.directMessagesEnabled ? `enabled (${channel.directMessagesPolicy})` : "disabled"}`);
85024
85074
  lines.push(`${prefix} sharedDefault: ${channel.sharedDefaultPolicy ?? "n/a"}`);
85025
85075
  lines.push(`${prefix} add group: ${renderCliCommand("routes add --channel slack group:<channelId> --bot default", { inline: true })}`);
85026
- lines.push(`${prefix} bind group: ${renderCliCommand("routes set-agent --channel slack group:<channelId> --bot default --agent <id>", { inline: true })}`);
85076
+ lines.push(`${prefix} route uses the agent currently assigned to that bot by default`);
85077
+ lines.push(`${prefix} optional agent override if that route should use a different agent than the one currently assigned to that bot by default: ${renderCliCommand("routes set-agent --channel slack group:<channelId> --bot default --agent <id>", { inline: true })}`);
85027
85078
  lines.push(`${prefix} adjust later: ${renderPrivilegedChatHint(summary, "run in-chat commands here")}`);
85028
85079
  }
85029
85080
  function appendBootstrapGuidance(lines, summary) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clisbot",
3
- "version": "0.1.51",
3
+ "version": "0.1.52",
4
4
  "private": false,
5
5
  "description": "Chat surfaces for durable AI coding agents running in tmux",
6
6
  "license": "MIT",