Commit Graph

2051 Commits

Author SHA1 Message Date
gavrielc 53ffa3d347 PR3: apply per-wiring thread policy and declared auto-create defaults in router
- Auto-created messaging_groups take unknown_sender_policy from the channel
  declaration (DM vs group context); undeclared adapters resolve through the
  behavior-faithful fallback, identical to the old hardcoded value
- Fanout computes each wiring's effectiveThreadId via resolveThreadPolicy
  (threads override, declaration, live capability) and threads it through
  sticky engage lookup, session-mode force, resolveSession, delivery address,
  typing, and the subscribe gate; event.replyTo is operator intent and never
  policy-stripped
- Capability pre-strip for non-threaded adapters stays unchanged
- Tests: NULL-threads inherit parity, threads=0 opt-out, replyTo exemption,
  declared vs fallback auto-create policy; metadata-preservation tests now
  register a live threaded adapter (the realistic config the router sees)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJkDAnLGWJUqjgJNXpyqGZ
2026-07-10 23:19:49 +03:00
gavrielc 8d39368352 PR2: add wiring threads override migration + declaration-aware ncl create/update
- Migration 019: nullable messaging_group_agents.threads (NULL = inherit
  adapter declaration, 1/0 = per-wiring override), no backfill; schema.ts
  reference DDL and MessagingGroupAgent type updated to match.
- crud.ts genericCreate restructured into two passes with a new
  ResourceDef.resolveDefaults hook between explicit-arg collection and
  static col.default, so static defaults never pre-empt context-aware
  resolution; new preUpdate hook gives update the same cross-checks.
- wirings resource: new --threads and --priority flags, engage defaults
  filled from the channel declaration ({name} substituted), validation on
  create AND update (pattern-needs-pattern, mentions:'never' rejection,
  sticky->mention coercion when the effective thread policy is off).
- messaging-groups resource fills unknown_sender_policy from the channel
  declaration; hasDeclaredChannelDefaults gates both hooks so stale
  (undeclared) adapters keep the legacy static defaults exactly.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJkDAnLGWJUqjgJNXpyqGZ
2026-07-10 23:19:49 +03:00
gavrielc 59fc8e3cc7 PR1: add channel default declarations + tiered resolution foundation
- ChannelContextDefaults/ChannelDefaults types on ChannelAdapter, ChannelRegistration, and ChatSdkBridgeConfig (bridge copies verbatim like supportsThreads)
- getChannelDefaults tiered lookup (live instance -> live channelType -> registration key -> registration channelType -> fallback) with behavior-faithful fallbackChannelDefaults(supportsThreads)
- new channel-defaults.ts helpers: resolveWiringDefaults ({name} substitution, sticky->mention coercion, pattern validation), resolveUnknownSenderPolicy, resolveThreadPolicy (hard-AND with capability)
- CLI adapter declares its defaults; fix stale isMention doc claiming a router text-match fallback

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJkDAnLGWJUqjgJNXpyqGZ
2026-07-10 23:19:49 +03:00
github-actions[bot] 45f656f21c chore: bump version to 2.1.45 2026-07-10 20:03:08 +00:00
gavrielc a4513f292f Merge pull request #3009 from nanocoai/whatsapp-formatting-to-channels
Move channel formatting skills (whatsapp, slack) from trunk to the channels branch
2026-07-10 23:02:40 +03:00
gavrielc 38eb5a44df docs: scope the formatting-skills migration to installs with the channel wired
/update-nanoclaw is agent-driven; an unscoped 're-run /add-whatsapp'
would install the whole Baileys adapter on channel-free installs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2YZQDTw9TQrH3m8NBtVAW
2026-07-10 23:00:57 +03:00
gavrielc 6d397fc116 docs: tighten the channel formatting skills changelog entry
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2YZQDTw9TQrH3m8NBtVAW
2026-07-10 22:57:28 +03:00
gavrielc cb2bbcc7aa feat!: move slack-formatting container skill to the channels branch
Same treatment as whatsapp-formatting (previous commit): slack-formatting
is channel payload, not trunk. It ships only a SKILL.md (no composed-doc
fragment) and reaches agents via ~/.claude/skills; /add-slack and the
slack setup installers now copy it from the channels branch, which
already carries an identical copy. Changelog entry combined for both.

BREAKING CHANGE: existing Slack installs lose the slack-formatting skill
from ~/.claude/skills after updating; re-run /add-slack (idempotent).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2YZQDTw9TQrH3m8NBtVAW
2026-07-10 22:45:23 +03:00
gavrielc b9998a4bf1 feat!: move whatsapp-formatting container skill to the channels branch
Trunk shipped WhatsApp formatting instructions to every install — the
skill-whatsapp-formatting.md fragment landed in every agent's composed
CLAUDE.md whether or not WhatsApp was wired. The skill is channel payload:
it now lives on the channels branch and is copied in by /add-whatsapp and
the setup installers (install-whatsapp.sh, add-whatsapp.sh).

BREAKING CHANGE: existing WhatsApp installs lose the fragment on their
next container spawn after updating; re-run /add-whatsapp (idempotent)
to restore it. See CHANGELOG.md for the manual copy alternative.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2YZQDTw9TQrH3m8NBtVAW
2026-07-10 22:43:06 +03:00
github-actions[bot] 0d41f0ef94 chore: bump version to 2.1.44 2026-07-10 18:22:21 +00:00
gavrielc 3363a0be0f Merge pull request #3003 from Shufel83/fix/agent-browser-bounded-wait
docs(agent-browser): require bounded waits for custom conditions
2026-07-10 21:22:08 +03:00
gavrielc 05cf44035e Merge branch 'main' into fix/agent-browser-bounded-wait 2026-07-10 21:21:34 +03:00
github-actions[bot] c1eb1079cc docs: update token count to 225k tokens · 113% of context window 2026-07-10 18:20:35 +00:00
gavrielc 1725d86fbd Merge pull request #3006 from nanocoai/fix/local-time-display
fix: ISO storage + local-time display for all timestamps
2026-07-10 21:20:21 +03:00
gavrielc e3bd22f96f style: prettier
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2YZQDTw9TQrH3m8NBtVAW
2026-07-10 21:11:38 +03:00
gavrielc c2e5b14bf8 fix: ISO storage + local-time display for all timestamps
Storage: every JS-side datetime('now') write becomes new Date().toISOString()
(messages_out all writers, processing_ack all stamps, delivered, retry
backoff, roles/members/destinations, skill SQL via strftime ISO-Z). Dormant
deliver_after raw string compares wrapped in datetime().

Display: ncl human output renders ISO instants as local "YYYY-MM-DD HH:mm"
(host + container renderers; --json stays ISO; the stamp shape round-trips
through parseZonedToUtc). Task run logs, conversation archive filenames,
clidash, the dashboard pusher, and the uninstall backup stamp all render
local; instruction texts updated in lockstep. CLAUDE.md documents the
convention.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2YZQDTw9TQrH3m8NBtVAW
2026-07-10 21:06:33 +03:00
github-actions[bot] 1ccef326dc chore: bump version to 2.1.43 2026-07-10 17:17:24 +00:00
gavrielc 39e7604526 Merge pull request #3005 from nanocoai/fix/task-timestamp-iso
fix: stamp task rows with ISO timestamps
2026-07-10 20:17:10 +03:00
gavrielc c0e591f2fb fix: stamp task rows with ISO timestamps
insertTaskRow used SQL datetime('now') — a naive-UTC stamp the container
formatter parses as local time, rendering <task time> hours off from the
ISO-Z chat timestamps beside it. Stamp ISO like every other messages_in
writer.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A2YZQDTw9TQrH3m8NBtVAW
2026-07-10 19:54:35 +03:00
exe.dev user df4929d61d docs(agent-browser): require bounded waits for custom conditions
Improvised `until … do sleep; done` polling loops with no timeout can
loop forever when a page condition never becomes true (page fails to
load, selector changes, network stalls). This doesn't just fail the
command — it wedges the whole agent turn: the runner keeps the model
stream open, later messages are pushed in and silently marked complete
without a reply, and heartbeat freshness masks it from the host's
stuck-detection, so a session can hang for hours.

Add a "Waiting for a custom condition — ALWAYS bound it" section to the
agent-browser skill: prefer built-in `wait` subcommands, ban unbounded
loops, and give a ready pattern capped by both `timeout` and a
max-attempts counter that always exits. Treat a timeout as a real
failure (snapshot + report), not grounds to re-enter the wait.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-10 13:11:34 +00:00
github-actions[bot] 14f528c895 docs: update token count to 224k tokens · 112% of context window 2026-07-10 06:42:50 +00:00
github-actions[bot] 366c5f06f1 chore: bump version to 2.1.42 2026-07-10 06:42:46 +00:00
glifocat 077ce6fd9d Merge pull request #2416 from glifocat/fix/ncl-create-handlers
fix(cli): provision companion rows on `ncl groups create` and `ncl wirings create`
2026-07-10 08:42:32 +02:00
github-actions[bot] 0c0f4c2592 docs: update token count to 223k tokens · 111% of context window 2026-07-09 08:24:27 +00:00
github-actions[bot] 92635f1934 chore: bump version to 2.1.41 2026-07-09 08:24:22 +00:00
gavrielc f7a43ef881 Merge pull request #2981 from nanocoai/tasks/02-ncl-tasks-core
Scheduled tasks: ncl tasks control plane, isolated sessions, script gate
2026-07-09 11:24:07 +03:00
omri-maya 5459925c65 Apply suggestions from code review
Co-authored-by: omri-maya <omri@nanoco.ai>
2026-07-09 11:23:08 +03:00
Omri Maya b0c76ce4c5 feat(tasks): ncl tasks control plane — isolated per-series sessions, strict verb contract, script gate
Scheduled tasks move from MCP tools to a first-class ncl resource:
list / get / create / update / cancel / pause / resume / run / append-log,
with args declared on every verb (strict validation, fix-carrying errors)
and deep per-verb help with executable examples.

A series is CronJob-like: the live (pending/paused) row is the next
occurrence, completed rows are its run history. tasks list reads as a
compact run-history table, server-rendered so the container agent prints
the same aligned table. Short named ids (<slug>-<hex>) are
filesystem/thread-safe and copy-pasteable. Agents keep a per-series work
journal: the run log at tasks/<series>.md (append-log + auto-logged
final text).

Each series runs in its own isolated system session
(system:tasks:<series>); the live-task cap is dropped — isolation
replaces throttling. Spent task sessions are GC'd by the sweep.

--script on a task runs a bash gate BEFORE the agent wakes. It prints a
JSON verdict as its last stdout line: {"wakeAgent": bool, "data": {...}}.
wakeAgent:false handles the occurrence without waking the agent; data is
threaded into the fire's prompt, so a gate can fetch/inspect and hand the
agent exactly what changed. Failing scripts back off exponentially
(2·2^(n-1) min, cap 60) and auto-pause the series after 8 consecutive
failures with a host-written run-log note; manual runs are excluded from
the streak.

BREAKING: the schedule_task / list_tasks / update_task / cancel_task /
pause_task / resume_task MCP tools are removed. Agents schedule via
ncl tasks (available under cli_scope=group). Existing task rows keep
firing — storage (messages_in kind='task') is unchanged; only the
management surface moved. Migration: docs/ncl-tasks-migration.md.
Review round (gavrielc):
- Recurrence frequency guard: create/update refuse a recurrence more
  frequent than 4 fires/day with a warning steering to gate scripts;
  --dangerously-override-recurrence-limit bypasses after explicit user
  confirmation. Counted over the next 24h in the instance TZ. Guarded on
  update too, so create-slow-then-update cannot sneak past.
- ncl tasks help scripts: resource help topics (new helpTopics seam on
  registerResource) carry the full gate-script guide — contract, examples,
  state, failure/backoff semantics, testing directions.
- Agent-facing scheduling instructions slimmed: no recurring-frequency
  prose in the fragment; one pointer to the help topic.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 17:04:45 +03:00
Gabi Simons 87a2d3af8d Merge pull request #2978 from nanocoai/feat/core-team-pr-label
ci: auto-label PRs from core team members
2026-07-08 14:49:23 +03:00
Gabi Simons 68ebc02114 Update CONTRIBUTING.md 2026-07-08 14:48:25 +03:00
Gabi Simons d4e73c5523 Merge branch 'main' into feat/core-team-pr-label 2026-07-08 14:35:23 +03:00
github-actions[bot] 9a103f4f93 docs: update token count to 213k tokens · 106% of context window 2026-07-08 11:29:45 +00:00
github-actions[bot] a8554c6248 chore: bump version to 2.1.40 2026-07-08 11:29:40 +00:00
gavrielc 2480ae7cb8 Merge pull request #2980 from nanocoai/tasks/01-cli-verb-args-human-view
ncl CLI: verb-level args, deep help, server-rendered human view
2026-07-08 14:29:24 +03:00
Omri Maya 763a3f757b feat(cli): verb-level args, deep help, server-rendered human view
Every ncl verb now declares its args: strict validation with fix-carrying
error messages, generated per-verb --help, and multi-word custom-op key
resolution (spaces vs dashes). Longest-prefix command fallback keeps dashed
positional ids intact.

Responses gain a server-rendered 'human' frame field (formatHuman hook): the
host renders tables once and every client prints them verbatim — container
agents cannot import host formatters, so this is how they get aligned output
instead of a raw column dump. --help responses carry 'human' for clean
multi-line rendering.

Robustness fixes riding along:
- generic list returns newest rows first, so the LIMIT no longer hides
  recent rows
- stdout flushed before exit — >64KB responses were silently truncated

Additive only: new response-frame fields, no schema changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 12:39:10 +03:00
Gabi Simons 8943c1cbf4 ci: auto-label PRs from core team members
Extends the existing label-pr workflow with an author allowlist that
applies a core-team label. The label is auto-provisioned on first use
so no manual repo setup is needed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-08 10:11:43 +03:00
github-actions[bot] 559bb5ca1a chore: bump version to 2.1.39 2026-07-07 20:00:50 +00:00
gavrielc 04b364e828 Merge pull request #2965 from nanocoai/fix/rate-limit-event-shape
fix(agent-runner): match rate_limit_event as a top-level SDK message type
2026-07-07 23:00:36 +03:00
gavrielc 627ab23bad Merge branch 'main' into fix/rate-limit-event-shape 2026-07-07 23:00:24 +03:00
gavrielc 8986fef586 Apply suggestion from @gavrielc 2026-07-07 23:00:07 +03:00
gavrielc 7f49450c0c Merge pull request #2964 from nanocoai/docs-sdk-deep-dive
docs: update SDK deep-dive from 0.2.x to 0.3.197
2026-07-07 22:58:40 +03:00
gavrielc cdc519e1f4 Merge pull request #2963 from nanocoai/docs-rewrite-core
docs: rewrite architecture.md and agent-runner-details.md to match current code
2026-07-07 22:56:12 +03:00
gavrielc 1276645c3b Merge pull request #2962 from nanocoai/docs-fix-schema
docs: sync DB schema and entity docs with migrations 010-018
2026-07-07 22:55:40 +03:00
github-actions[bot] d3499b7d70 docs: update token count to 209k tokens · 104% of context window 2026-07-07 19:55:04 +00:00
gavrielc c2cf19ec28 Merge pull request #2961 from nanocoai/docs-fix-mechanical
docs: fix stale claims across README, CONTRIBUTING, CLAUDE.md and operational docs
2026-07-07 22:54:48 +03:00
glifocat 44f351349a docs: Output Delivery — messages_out comes from <message> envelope parsing, not raw results
The section still described the pre-envelope model where every provider
result was written to messages_out verbatim. Since the envelope parser
landed, the agent-runner parses the final text for <message to="name">
blocks (dispatchResultText, poll-loop.ts): one messages_out row per
block, bare/<internal> text is scratchpad (logged, never sent), unknown
destinations are dropped, unwrapped output gets a one-time re-wrap
nudge, and non-retryable error results are delivered as error notices
instead of being dropped.
2026-07-07 00:26:12 +00:00
glifocat e8a32207d8 fix(agent-runner): match rate_limit_event as a top-level SDK message type
The claude provider mapped rate-limit events with
`message.type === 'system' && subtype === 'rate_limit_event'`, but
`@anthropic-ai/claude-agent-sdk` 0.3.x ships rate limits as a top-level
`SDKRateLimitEvent` (`{ type: 'rate_limit_event', ... }`) with no `system`
subtype. The old condition never matched, so the quota-classified error
event was never emitted and rate-limit signals were silently dropped.

Match the top-level `type` instead.
2026-07-06 15:05:01 +00:00
glifocat 1dda751a48 docs: update SDK deep-dive from 0.2.x to 0.3.x 2026-07-06 14:52:03 +00:00
glifocat 4f1b17c737 docs: sync DB schema + entity docs with migrations 010-018 2026-07-06 13:04:14 +00:00
glifocat 967aee2c27 docs: fix stale claims vs v2.1.38 (skills lists, runtime claims, file refs) 2026-07-06 13:04:14 +00:00