Commit Graph
100 Commits
Author SHA1 Message Date
gavrielc 657110cb0b Merge pull request #2251 from axxml/main
Add namespacedPlatformId exclusion for DeltaChat
2026-05-04 18:32:18 +03:00
gavrielc 7ed149057d Merge branch 'main' into main 2026-05-04 18:32:09 +03:00
gavrielc 8d489ee19e Merge pull request #2242 from mashkovtsevlx/fix/mcp-allowlist-sdk-filter
fix(agent-runner): derive MCP allowedTools from registered mcpServers
2026-05-04 18:30:54 +03:00
gavrielc dcf8d2096f Merge branch 'main' into fix/mcp-allowlist-sdk-filter 2026-05-04 18:30:43 +03:00
gavrielc 9e8f256dd2 Merge pull request #2245 from alipgoldberg/setup-windowed-fmt-duration
fix(setup): use fmtDuration in the container-build spinner
2026-05-04 17:57:44 +03:00
gavrielc 057f0d174c Merge branch 'main' into setup-windowed-fmt-duration 2026-05-04 17:57:35 +03:00
gavrielc 1c16b09c84 Merge pull request #2252 from Koshkoshinsk/g-check
feat(setup): warn when running on a Google Compute Engine VM
2026-05-04 17:56:34 +03:00
gavrielc cf71f961d3 Merge branch 'main' into g-check 2026-05-04 17:56:25 +03:00
gavrielc e0e4f0189b Merge pull request #2250 from Koshkoshinsk/install-specs
Warn when host is below recommended hardware specs
2026-05-04 16:15:24 +03:00
gavrielc ebb11a1127 Merge pull request #2222 from qwibitai/fix/update-nanoclaw-skill-v2
fix: update /update-nanoclaw skill for v2 architecture
2026-05-04 10:08:50 +03:00
gavrielc 9b067b2d8e Merge branch 'main' into fix/update-nanoclaw-skill-v2 2026-05-04 10:08:43 +03:00
gavrielc 517e719146 Merge pull request #2212 from alipgoldberg/setup-headless-auth-message
feat(setup): headless-aware Claude sign-in pre-message
2026-05-04 10:08:05 +03:00
gavrielc 5eda6c160e Merge branch 'main' into setup-headless-auth-message 2026-05-04 10:07:56 +03:00
gavrielc 2902d86ac8 Merge pull request #2235 from Koshkoshinsk/migration-fixes-combined
fix: migration UX improvements + legacy OneCLI container cleanup
2026-05-04 10:05:35 +03:00
gavrielc 8bdc5c4217 Merge pull request #2229 from SebTardif/fix/verify-anthropic-auth-token
Recognize ANTHROPIC_AUTH_TOKEN in setup verification
2026-05-03 21:05:04 +03:00
gavrielc c0a7538dbe Merge pull request #2213 from ziv-daniel/fix/media-only-messages
fix: accept media-only messages (photo/video/file without caption)
2026-05-03 17:04:42 +03:00
gavrielc 6936e97fe2 Merge pull request #2206 from javexed/feat/setup-other-channel
feat(setup): add "Other…" option to channel picker
2026-05-03 15:42:11 +03:00
gavrielc dd055bbb8e Merge branch 'main' into feat/setup-other-channel 2026-05-03 15:42:00 +03:00
gavrielc 63f88356eb Merge pull request #1467 from ingyukoh/docs/add-contributor-ingyukoh
docs: add ingyukoh to contributors
2026-05-03 12:55:29 +03:00
gavrielc b01b13323e Merge branch 'main' into docs/add-contributor-ingyukoh 2026-05-03 12:55:17 +03:00
gavrielc 52051d4aa5 Merge pull request #2181 from mnolet/fix/slash-commands-on-warm-containers
fix(poll-loop): slash commands silently broken on warm containers
2026-05-02 21:37:31 +03:00
gavrielc 64769feae7 Merge branch 'main' into fix/slash-commands-on-warm-containers 2026-05-02 21:37:21 +03:00
gavrielc 6b76c1a56c Merge pull request #2183 from cfis/fix/host-sweep-outbound-db-rw
fix(host-sweep): reopen outbound DB as writable for orphan claim cleanup
2026-05-02 21:23:27 +03:00
gavrielc cb1d8dd791 Merge branch 'main' into fix/host-sweep-outbound-db-rw 2026-05-02 21:23:20 +03:00
82216b536d Add /add-deltachat skill
Skill files only — copied from PR #2192 (channels branch).
Source adapter (src/channels/deltachat.ts) lives on the channels
branch and is installed by the skill.

Co-Authored-By: Axel McLaren <scm@axml.uk>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 21:21:58 +03:00
gavrielc 02650fa616 Merge pull request #1931 from qwibitai/feat/migrate-from-v1
feat: v1 → v2 migration to setup flow (experimental)
2026-05-02 19:14:25 +03:00
gavrielc 640303e4a9 Merge branch 'main' into feat/migrate-from-v1 2026-05-02 19:12:49 +03:00
Gavriel Cohen 3b5e5a24f4 fix(migrate-v2): reset auto-created messaging_group policy on re-run
If 1b-db is re-run after the v2 service has already started (e.g.
recovering from an earlier failure), the messaging_group it would
otherwise create may already exist — auto-created by the runtime router
on the first inbound message, with the router's default
unknown_sender_policy ('request_approval'), not the migration's intent
('public'). The previous reuse path skipped creation but never updated
the policy, so re-runs left the bot hanging every message waiting for
an approver that wasn't seeded yet.

When reusing an existing row that has zero wired agent_groups (signal
of a router auto-create), reset the policy to 'public'. Once any wiring
exists, the user has had a chance to tighten via the skill — leave it.

Also adds a CHANGELOG entry covering this and the two sibling fixes
(Discord DM resolution, symlink skip in copyTree).
2026-05-02 16:09:06 +00:00
Gavriel Cohen 7dbedad9bd fix(migrate-v2): skip symlinks in group copyTree
fs.copyFileSync follows symlinks, so a single broken/dangling link in v1
(e.g. .claude-shared.md → /app/CLAUDE.md, a container-side path that
doesn't resolve on the host) crashed the alphabetical traversal with
ENOENT — preventing later folders, including the actual registered
group, from being copied.

Check entry.isSymbolicLink() and skip with a one-line log. v2 uses
composed CLAUDE.md fragments, so v1's container-path symlinks have no v2
meaning and don't need to be carried forward.
2026-05-02 16:09:06 +00:00
Gavriel Cohen 8181054bdb fix(migrate-v2): resolve Discord DMs as discord:@me:<id>
The resolver only enumerated guild channels, so any v1 install whose
registered Discord chat was a DM (a common case for personal-bot
installs) failed 1b-db with "not found in any guild" — leaving the
migration without an agent_group or wiring, and the user with a bot that
received messages but had nowhere to route them.

Add an unresolved-channel classification pass: for any v1 channel id not
found in a guild, GET /channels/<id> and emit discord:@me:<id> when the
type is DM (1) or GROUP_DM (3). Matches the runtime adapter's
guild_id || "@me" encoding. Other types / 404 / 403 keep current
skip-with-warning behavior.

Caller passes the v1 channel id list (already on hand). Test coverage
extends the existing mock-fetch pattern with DM, GROUP_DM, orphan, and
dedupe cases.
2026-05-02 16:09:06 +00:00
Gavriel CohenandClaude Opus 4.7 7922a19af7 docs(migrate-from-v1): drop the blocker/deferred table
Trust the agent to figure out which failed steps actually stop
routing. The rule is the goal ("can the bot route one message?"),
not a hardcoded list.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:40:07 +03:00
Gavriel CohenandClaude Opus 4.7 8c1b209aeb docs(migrate-from-v1): 2b-channel-auth and 3c-auth are blockers
2b-channel-auth: copies the Baileys keystore + channel-specific env
keys. Without it WhatsApp can't connect — saw this firsthand when
the original candidatePaths bug left env_keys=0,files=0.

3c-auth: registers Anthropic credentials in OneCLI. 3b installs the
gateway; 3c puts the secret in the vault. Without 3c every agent
request 401s regardless of 3b's status.

1c-groups stays deferred — agent runs on stock CLAUDE.md without it,
but routing works.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:36:10 +03:00
Gavriel CohenandClaude Opus 4.7 2bc1279a12 docs(migrate-from-v1): trim Phase 0 to intent only
Previous version spelled out launchctl/systemctl commands, log lines
to grep for, diagnostic recipes — the agent reading this skill knows
all of that. Keep only the parts that aren't obvious from the rest of
the codebase: which steps are blocking vs deferred, the smoke-test
ordering, and the non-destructive framing for the user.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:31:23 +03:00
Gavriel CohenandClaude Opus 4.7 2617313f19 docs(migrate-from-v1): blockers-first + smoke test before deeper work
Phase 0 used to be "triage every failed step before doing anything
else", which front-loaded a bunch of fixes for things that don't
actually block the user from proving v2 works. Restructure:

- 0a — fix blockers only (1b/1d/2c/2d/3a/3b/3e). Defer non-blockers
  (1a, 1c, 1e, 2b, 3c) — most surface naturally in later phases.
- 0b — smoke test: switch v1 → v2, send a real message, verify the
  routing chain in logs/nanoclaw.log. AskUserQuestion gates whether
  to continue.
- Revert recipe (launchctl/systemctl) called out as always-available,
  not destructive — v1 process, data, and credentials are untouched.

Up-front list of what the script handled now also mentions the
WhatsApp LID resolution and Baileys keystore copy, so users see
exactly what continuity they're getting.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:28:46 +03:00
Gavriel CohenandClaude Opus 4.7 8439a180be docs(migrate-v2): collapsible README section + skill preflight
README: replace the one-line v1 migration note with a collapsed
<details> block. Quick Start stays compact for the common case (fresh
install) while v1 users get the actual instructions. Calls out
explicitly that the script must be run from a real terminal — not from
inside a Claude session — so the channel-select / switchover prompts
and the Node/pnpm/Docker bootstrap all work.

migrate-from-v1 skill: add a Preflight section that aborts if
logs/setup-migration/handoff.json is missing. Without this, invoking
the skill before the script just leads Claude to start guessing /
running shell commands. The new message redirects them to the script
and tells them it'll hand back to Claude on completion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 18:22:50 +03:00
Gavriel CohenandClaude Opus 4.7 dca02f5453 feat(migrate-v2): resolve WhatsApp LIDs from store/auth, alias DMs
v1 stored every WhatsApp DM as `<phone>@s.whatsapp.net`. v2's WA
adapter sometimes resolves the chat to `<lid>@lid` instead — when
WhatsApp delivers via the LID protocol and Baileys hasn't yet learned
a LID→phone mapping for that contact (cold cache after migration).
The router then can't find the phone-keyed messaging_group and
silently drops the message at router.ts:184.

Baileys persists every LID↔phone pair it has ever learned to disk as
`store/auth/lid-mapping-<phone>.json` (forward) and
`lid-mapping-<lid>_reverse.json` (reverse). v1 will already have these
populated for every contact it has talked to. New step 2d-whatsapp-lids
parses the reverse files and writes paired LID-keyed `messaging_groups`
+ `messaging_group_agents` rows so both `<phone>@s.whatsapp.net` and
`<lid>@lid` route to the same agent_group with the same engage rules.

No Baileys boot, no WhatsApp connectivity required — pure filesystem
read of files we've already copied via 2b-channel-auth. Step is
no-op-on-skip if either store/auth or whatsapp DM rows are missing.

Anything that slips through (a contact whose LID v1 never learned)
falls back to the runtime approval flow once the WA adapter sets
isMention=true on DMs — each unknown LID DM auto-creates an
approval-required messaging_group and the owner gets a one-tap
register prompt.

Verified end-to-end on a 12-group v1 install: 3 DM rows aliased,
inbound DM routed via the LID-keyed row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 15:39:36 +03:00
Gavriel CohenandClaude Opus 4.7 2a915e8af0 fix(migrate-v2): infer is_group from JID format
v1 didn't track is_group separately; db.ts hardcoded `is_group: 1` for
every messaging_group. v2 uses is_group=0 to collapse DM sub-thread
sessions and to drive routing decisions, so getting it wrong is latent
risk on otherwise-working installs.

New helper inferIsGroup(channelType, platformId) lives in shared.ts so
tasks.ts and any future migration step can reuse it. Inferred per
channel:
  - whatsapp: `<id>@g.us` is a group, anything else is a DM
  - telegram: negative chat IDs are groups, positive are DMs
  - everything else: default to 1 (least surprising for chats v1 chose
    to register, where DM auto-create paths weren't used)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 15:24:57 +03:00
Gavriel CohenandClaude Opus 4.7 416c283dcb fix(migrate-v2): bash 3.2 compatibility + reset coverage
migrate-v2.sh
  Replace `declare -A STEP_RESULTS` with two parallel indexed arrays
  (STEP_NAMES + STEP_STATUSES) plus a `record_step` helper. macOS ships
  bash 3.2 which has no associative arrays — `declare -A` errored out
  silently and every `STEP_RESULTS["1a-env"]=...` triggered a fatal
  bash arithmetic error (interpreting "1a" as a number). Visible
  symptom: `steps: {}` in handoff.json. Latent symptom: phase 2c's
  install loop sometimes bailed mid-iteration before invoking the
  channel install script, leaving channel code uninstalled while
  reporting `overall_status: success`.

migrate-v2-reset.sh
  Cover the gaps that left install side-effects in place between
  iterations:
    - Remove untracked adapter files in src/channels/ (mirror the
      pattern already used for container/skills/).
    - Restore tracked setup helpers that channel installs overwrite
      (setup/whatsapp-auth.ts, setup/pair-telegram.ts, setup/index.ts)
      and remove untracked ones they create (setup/groups.ts).
    - Restore package.json + pnpm-lock.yaml (channel installs add
      deps like @whiskeysockets/baileys).
  Setup/migrate-v2/* is intentionally not touched — that's where user
  WIP lives.

Verified end-to-end: reset → migrate → all 9 steps reported in
handoff.json with status "success", phase 2c install actually runs.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 14:50:21 +03:00
Gavriel CohenandClaude Opus 4.7 aec7ddd099 fix(migrate-v2): correct JID parsing, Discord guildId lookup, silent failures
- shared.ts: parseJid now recognizes raw Baileys WhatsApp JIDs
  (`<id>@s.whatsapp.net`, `@g.us`, etc.); v2PlatformId returns the raw
  JID for whatsapp to match what the runtime adapter emits. Without this,
  every WhatsApp group in a v1 install was silently skipped.

- discord-resolver.ts: new helper that uses DISCORD_BOT_TOKEN to look up
  channelId → guildId via the Discord API, since v1 stored only the
  channel id but v2 needs `discord:<guildId>:<channelId>`. Best-effort:
  on missing/invalid token or network error, returns empty resolver and
  the affected groups are skipped with the reason surfaced per channel.

- db.ts, tasks.ts: route Discord groups through the resolver; other
  channels go through v2PlatformId unchanged. Resolver only built when
  at least one Discord group exists, so non-Discord installs incur no
  network.

- db.ts: when every v1 group is skipped, exit non-zero with a FAIL line
  instead of `OK:groups=N,...,skipped=N`, so the wrapper doesn't hide
  total failure under a successful-looking summary.

- migrate-v2.sh: run_step now surfaces ERROR: lines from successful
  steps (with count + first 3 + raw log path); phase 2c install loop
  populates STEP_RESULTS so install failures show in handoff.json
  instead of silently passing.

- sessions.ts: copyTree skips dangling symlinks (e.g. v1's
  `.claude/debug/latest`) instead of crashing the entire step.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-02 14:32:34 +03:00
gavrielc 39c579ba2a Merge pull request #2151 from glifocat/fix/host-sweep-orphan-processing-ack
fix(host-sweep): clear orphan processing_ack rows on kill to prevent claim-stuck respawn loop
2026-05-01 19:03:00 +03:00
gavrielc dab4fb497b Merge branch 'main' into fix/host-sweep-orphan-processing-ack 2026-05-01 18:42:04 +03:00
gavrielc 20a17cbc44 Merge pull request #2160 from kky/pr/inbound-db-fresh-open
fix(agent-runner): open inbound.db fresh per messages_in read
2026-05-01 16:30:07 +03:00
gavrielc 0d836220d9 Merge branch 'main' into pr/inbound-db-fresh-open 2026-05-01 16:29:46 +03:00
gavrielc 7814e45570 Merge pull request #2001 from Hinotoi-agent/fix/outbox-path-confinement
[security] fix(container): prevent host file read/delete via container-controlled outbox paths
2026-05-01 01:28:07 +03:00
fc3c11b6b9 fix(session-manager): apply outbox path-confinement to inbound attachments
Mirrors the four defenses on the outbound side onto extractAttachmentFiles:

  1. Reject unsafe messageId via isSafeAttachmentName before any inbox path
     is built. WhatsApp passes msg.key.id through raw and that field is
     client generated, so a peer can craft it; future end to end encrypted
     adapters will have the same property.
  2. lstatSync on the inbox dir refuses a pre placed symlink before
     mkdirSync would silently follow it.
  3. realpathSync + isPathInside contains the resolved dir under the
     session inbox root.
  4. writeFileSync uses the wx flag so a pre placed symlink at the file
     path is refused atomically by the kernel; EEXIST surfaces as a
     logged skip.

Threat: the session dir is mounted writable into the container at
/workspace, so a compromised agent can pre place inbox/<future msgId>/
as a symlink and wait for a chat message with a matching id to redirect
the host write. The four guards together close that window.

Consolidates with the existing isSafeAttachmentName helper from
attachment-safety.ts rather than introducing a duplicate basename
validator inside session-manager.

Co-Authored-By: Daisuke Tsuji <dim0627@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 01:27:09 +03:00
gavrielc 212281ba8e Merge pull request #2055 from dooha333/pr/setup-local-bin-path
fix(setup): inject ~/.local/bin into PATH so post-install onecli is reachable
2026-05-01 01:20:07 +03:00
gavrielc 6db6bf9c40 Merge branch 'main' into pr/setup-local-bin-path 2026-05-01 01:19:58 +03:00
gavrielc d13f338af9 Merge pull request #2114 from robbyczgw-cla/fix/poll-loop-prescripts-on-followups
fix(poll-loop): apply pre-task scripts to follow-up injections too
2026-05-01 00:57:34 +03:00
5ab1a2733c review: catch follow-up poll errors + re-check done before push
Two fixes on top of the follow-up pre-task-script work:

1. The void async IIFE inside the interval handler had no catch, so a
   throw from the dynamic import or applyPreTaskScripts escaped as an
   unhandled rejection — terminating the container. The initial-batch
   path is wrapped by processQuery's outer try/catch; the follow-up
   path needs its own. Now logs the error and lets the next tick retry.

2. Re-check `done` immediately before query.push. The flag can flip
   true while applyPreTaskScripts is awaited (outer stream finishes
   during the script execution); without the re-check we'd push into a
   closed query. Claimed messages get released by the host's
   processing-claim sweep — same recovery posture as the rest of the
   poller.

Co-Authored-By: Michael Zazon <mzazon@gmail.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 00:55:46 +03:00
gavrielc 7d29888e59 Merge branch 'main' into fix/poll-loop-prescripts-on-followups 2026-05-01 00:34:45 +03:00
gavrielc 3e7fea0fde Merge pull request #2142 from mnolet/fix/schedule-task-routing
fix(scheduling): include routing in schedule_task content JSON
2026-05-01 00:31:04 +03:00
gavrielc d418f830db Merge branch 'main' into fix/schedule-task-routing 2026-05-01 00:30:11 +03:00
gavrielc 524ac221e1 Merge pull request #2111 from qwibitai/setup-scratch-agent-cleanup
feat(setup): delete scratch agent after ping-pong, simplify flow
2026-04-30 23:20:54 +03:00
gavrielc 69b4225916 Merge branch 'main' into setup-scratch-agent-cleanup 2026-04-30 23:20:32 +03:00
gavrielcandClaude Opus 4.7 3d6a9b74f3 review: surface ping-test cleanup failures + restore copy
Routes the post-ping `_ping-test` cleanup through `spawnQuiet` +
`setupLog.step` so a non-zero exit from `delete-cli-agent.ts` lands
in `logs/setup-steps/cleanup-cli-agent.log` and the progression log,
and prints a one-line warn to the user. Previously the spawnSync was
fire-and-forget with `stdio: 'ignore'`, leaving an orphan agent group
silently if cleanup failed.

Restores the original copy on the cli-agent step labels, the ping
explainer paragraph, and the post-ping spinner stop line — those
copy changes are out of scope for this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 23:16:34 +03:00
gavrielc dcc625f2b8 Merge pull request #2155 from qwibitai/setup-root-warning-v2
Add root user warning gate to Linux setup
2026-04-30 23:09:36 +03:00
gavrielc 99a8559b14 Merge remote-tracking branch 'origin/main' into setup-root-warning-v2
# Conflicts:
#	setup/auto.ts
2026-04-30 23:07:38 +03:00
gavrielc 3dc772cca0 Merge branch 'main' into setup-scratch-agent-cleanup 2026-04-30 23:05:09 +03:00
gavrielc 5ebad280ce Merge pull request #1502 from Koshkoshinsk/docs/pr-hygiene-check
Add PR hygiene check to CLAUDE.md and contributing guidelines
2026-04-30 23:00:43 +03:00
gavrielc d73b9e14ad Merge branch 'main' into docs/pr-hygiene-check 2026-04-30 23:00:10 +03:00
gavrielc 681a5b51c8 Merge pull request #2157 from qwibitai/setup-lazy-env-reuse
refactor(setup): per-step env var reuse instead of upfront all-or-nothing
2026-04-30 22:59:03 +03:00
gavrielc 8e45f4e964 Merge branch 'main' into setup-lazy-env-reuse 2026-04-30 22:58:53 +03:00
gavrielc eb9a5d706d Merge branch 'main' into setup-scratch-agent-cleanup 2026-04-30 22:54:48 +03:00
gavrielc 3ee07effea Merge pull request #2105 from qwibitai/feat/channel-approval-flow
feat: richer channel-approval flow with agent selection and free-text naming
2026-04-30 22:54:08 +03:00
gavrielc 462b9581b2 Merge branch 'main' into feat/channel-approval-flow 2026-04-30 22:54:00 +03:00
gavrielc a359f2555f Merge pull request #2158 from alipgoldberg/setup-splash-screen
feat(setup): show under-the-sea lobster splash at boot
2026-04-30 22:51:35 +03:00
gavrielc 6525926ca9 Merge branch 'main' into setup-splash-screen 2026-04-30 22:51:01 +03:00
gavrielc 35d35fefc3 Merge pull request #2154 from alipgoldberg/setup-fallback-url-in-prompt
feat(setup): move URL fallback into the open-browser prompt
2026-04-30 22:50:44 +03:00
gavrielc eab9110232 Merge branch 'main' into setup-fallback-url-in-prompt 2026-04-30 22:48:47 +03:00
gavrielc 2c0d0e9d44 Merge pull request #2146 from alipgoldberg/setup-headless-link-copy
feat(setup): label headless URL fallback with "Get started:"
2026-04-30 22:48:26 +03:00
gavrielc 17823dffae Merge branch 'main' into setup-headless-link-copy 2026-04-30 17:14:25 +03:00
gavrielc 941a75f65d Merge pull request #2145 from alipgoldberg/setup-headless-skip-browser
feat(setup): skip browser-open prompts on headless devices
2026-04-30 17:13:57 +03:00
gavrielc c2ee2b7c91 Merge branch 'main' into setup-headless-skip-browser 2026-04-30 17:11:35 +03:00
gavrielc ef62f57326 Merge pull request #2108 from alipgoldberg/setup-fmt-duration
feat(setup): switch elapsed-time suffixes to "Xm Ys" past 60s
2026-04-30 17:10:40 +03:00
gavrielc bb1b41800c Merge pull request #2156 from qwibitai/fix/telegram-spinner-overflow
fix: prevent telegram pairing spinner from flooding terminal
2026-04-30 15:30:54 +03:00
gavrielc 012292d063 Merge pull request #2115 from robbyczgw-cla/fix/session-manager-attachment-extensions
fix(session-manager): derive attachment extension from mimeType and att.type
2026-04-30 10:40:01 +03:00
gavrielc d2151ae848 Merge branch 'main' into fix/session-manager-attachment-extensions 2026-04-30 10:39:50 +03:00
gavrielc 6e5e568da1 sanitize agent sent file names to prevent path traversal 2026-04-30 10:33:46 +03:00
gavrielcandClaude Opus 4.7 2a3be9ec7f extract attachment-naming, harden mimeType guard, add tests
Move the MIME/type-to-extension maps and derivation helpers out of
session-manager.ts into a dedicated attachment-naming module — keeps
session-manager focused on session lifecycle and gives the helpers
a natural home for unit tests alongside the existing attachment-safety
module.

Two small fixes alongside the extraction:

- extForMime now guards `typeof mime !== 'string'` before .split, so a
  buggy bridge passing `mimeType: { ... }` (object) no longer crashes
  the inbound write loop.
- deriveAttachmentName computes Date.now() once per call instead of
  twice, and tightens the explicit-name check to a string-and-truthy
  guard so non-string values fall through to derivation.

Adds attachment-naming.test.ts with 11 cases covering MIME normalization
(case + parameters), Telegram type fallback, the non-string defensive
guard, and the bare-timestamp fallback.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-30 09:41:24 +03:00
gavrielc 597e282f88 Merge pull request #2110 from qwibitai/fix/credential-failure-ux
fix(credentials): require OneCLI gateway for container spawn
2026-04-29 18:30:05 +03:00
gavrielc 33a03f25a9 Merge remote-tracking branch 'origin/main' into fix/credential-failure-ux 2026-04-29 18:28:57 +03:00
gavrielcandClaude Opus 4.7 e31a6c7e34 revert(credentials): drop auth-required login-message handling
Removing the "Not logged in · Please run /login" detection and
substitution from this PR — narrowing scope to just the OneCLI
gateway transient-retry change. The login-message handling will be
addressed separately.

Reverts:
- AgentProvider.isAuthRequired / authRequiredMessage
- ClaudeProvider auth-required regex, classifier, and remediation text
- poll-loop writeAuthRequiredMessage helper + call sites
- claude.test.ts (auth-only test file)

OneCLI/wakeContainer changes (the remaining content of the PR) are
unaffected.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:26:04 +03:00
gavrielc d1a2505d20 Merge pull request #2116 from robbyczgw-cla/fix/compact-window-operator-override
fix(claude-provider): respect operator-set CLAUDE_CODE_AUTO_COMPACT_WINDOW (closes #1820)
2026-04-29 18:13:23 +03:00
gavrielcandClaude Opus 4.7 beb5e049ed fix(credentials): move auth-required remediation message into provider
Adds a paired `authRequiredMessage()` method to AgentProvider so
per-provider auth-failure remediation can differ. Claude returns the
Anthropic/`claude` instruction; future providers (Codex, OpenCode, …)
can return their own remediation text. The poll-loop calls
`provider.authRequiredMessage?.()` and falls back to a generic message
if a provider implements `isAuthRequired` without supplying its own
remediation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 18:03:25 +03:00
gavrielc 3c620bc8d0 Merge branch 'fix/credential-failure-ux' of https://github.com/qwibitai/nanoclaw into fix/credential-failure-ux 2026-04-29 17:52:17 +03:00
gavrielcandClaude Opus 4.7 d5b48e4742 fix(credentials): address review feedback
- wakeContainer now never throws — returns Promise<boolean>, catches
  internally. Closes the regression risk for the 5 awaited callers in
  agent-to-agent, interactive, and approvals/response-handler that the
  previous version left unwrapped. Router uses the boolean to stop the
  typing indicator on transient failure; host-sweep just awaits.
- Tighten AUTH_REQUIRED_RE: anchor to start-of-string with the specific
  `·` (U+00B7) separator the CLI uses, so an agent that quotes the
  banner mid-sentence in a normal reply doesn't trip the classifier.
- Log a one-line note from writeAuthRequiredMessage so substitutions
  are visible when debugging "user got the credentials message but I
  don't see why."
- Add unit tests for ClaudeProvider.isAuthRequired covering both banner
  variants, trailing content, mid-sentence quoting, leading-prose
  quoting, alternate separators, and unrelated text.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 17:51:32 +03:00
gavrielc 1dd8fabde9 Merge branch 'main' into fix/credential-failure-ux 2026-04-29 17:42:25 +03:00
gavrielcandClaude Opus 4.7 5f34e26240 fix(credentials): translate auth errors and require OneCLI for spawn
Two related fixes for the case where credentials aren't usable:

1. Replace Claude Code's "Not logged in / Invalid API key · Please run
   /login" output with a host-aware message. The user can't run /login
   from chat, so the raw text is unhelpful. Provider gains an optional
   isAuthRequired() classifier; the poll-loop substitutes the message
   on both result-text and error paths.

2. Treat OneCLI gateway failure as a transient hard error instead of
   spawning a credential-less container. The catch in container-runner
   now propagates; router and host-sweep wrap wakeContainer to log and
   leave the inbound row pending so the next 60s sweep tick retries.
   Router also stops the typing indicator on failure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 17:02:15 +03:00
gavrielc 9e45845000 Merge pull request #2104 from alipgoldberg/setup-assistant-green
feat(setup): paint "assistant" green in the agent-name prompt
2026-04-29 15:36:26 +03:00
gavrielc 9a919f4148 Merge branch 'main' into setup-assistant-green 2026-04-29 15:36:14 +03:00
gavrielc 1bf903a64d Merge pull request #2103 from alipgoldberg/setup-pronoun-green
feat(setup): paint "you" green in the display-name prompt
2026-04-29 15:25:12 +03:00
gavrielc 0044bba0e5 Merge branch 'main' into setup-pronoun-green 2026-04-29 15:25:02 +03:00
gavrielc 01131521ff Merge pull request #2102 from alipgoldberg/setup-color-choices
feat(setup): cyan highlight on active and submitted choices
2026-04-29 15:07:56 +03:00
gavrielc 3742165708 Merge branch 'main' into setup-color-choices 2026-04-29 15:07:00 +03:00
gavrielc 6ef147bc89 Merge pull request #2101 from alipgoldberg/setup-color-body
feat(setup): paint card and log bodies in brand cyan
2026-04-29 14:58:27 +03:00
gavrielc 7d153df710 Merge branch 'main' into setup-color-body 2026-04-29 14:58:02 +03:00
gavrielc 57a959028d Merge pull request #2098 from Koshkoshinsk/setup-token-headless
fix claude setup-token flow for headless/remote systems
2026-04-29 14:02:53 +03:00
gavrielc 9f564650c6 Merge branch 'main' into setup-token-headless 2026-04-29 14:02:45 +03:00
gavrielc 2acd71731a Merge pull request #2094 from qwibitai/fix/setup-reuse-existing-env
Detect existing .env and credentials on setup re-run
2026-04-29 14:01:03 +03:00
gavrielc c8e960314a Merge remote-tracking branch 'upstream/main' into fix/setup-reuse-existing-env
# Conflicts:
#	setup/channels/imessage.ts
#	setup/channels/telegram.ts
2026-04-29 13:58:21 +03:00