Commit Graph

534 Commits

Author SHA1 Message Date
Eyejoker
79a8a2639e feat: add structured room role metadata 2026-03-28 19:30:32 +09:00
Eyejoker
806e5e4ff1 fix: keep codex approval wording role-based 2026-03-28 17:02:50 +09:00
Eyejoker
772fea45df refactor: share owner prompts and tighten silent output guidance 2026-03-28 07:46:13 +09:00
Eyejoker
b97d1a6260 refactor: unify typing policy across services 2026-03-28 06:52:57 +09:00
Eyejoker
de913985ba fix: promote visible progress after silent final 2026-03-28 06:27:36 +09:00
Eyejoker
38d96578a4 refactor: move retry and recovery paths to structured output helpers 2026-03-28 06:17:52 +09:00
Eyejoker
47dda19ded fix: block malformed structured silent envelope leaks 2026-03-28 06:04:26 +09:00
Eyejoker
0eb2270030 style: sync structured output formatting fallout 2026-03-28 05:57:50 +09:00
Eyejoker
fe6314108c feat: add structured silent output contract 2026-03-28 05:56:58 +09:00
Eyejoker
e1fdc47552 style: sync pre-commit formatting fallout 2026-03-28 05:41:16 +09:00
Eyejoker
ba9f6871b6 feat: add codex review failover and suppress output hardening 2026-03-28 05:40:38 +09:00
Eyejoker
d1c693fb17 fix: treat signal-killed agents as success when output was delivered
Two bugs fixed:

1. agent-runner: process close handler only checked `code !== 0`,
   but signal kills (SIGTERM/SIGKILL from post-close cleanup) set
   code=null which was misclassified as error even after successful
   output delivery. Now checks `code === null && signal` and resolves
   as success when hadStreamingOutput is true.

2. message-agent-executor: wrappedOnOutput persisted newSessionId
   before checking for poisoned session, allowing a stale session to
   be re-saved after clearSession. Reordered to check poison first
   and guard persist with !resetSessionRequested.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 21:25:30 +09:00
Eyejoker
c4744177e9 style: format extractWatchCiTarget line wrap
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:59:25 +09:00
Eyejoker
7b63ba859d fix: deduplicate CI watchers and remove task ID from watcher prompts
Prevent duplicate CI completion notifications in paired rooms by checking
for existing active watchers with the same channel+provider+metadata before
creating a new one. Remove Task ID from watcher prompt construction to
avoid router secret redaction (task- IDs contain sk- pattern), passing
EJCLAW_RUNTIME_TASK_ID via env var instead and making cancel_task
auto-resolve when task_id is omitted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:57:59 +09:00
Eyejoker
b6dc500daf docs: add ouroboros prompt design attribution to README
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 20:40:50 +09:00
Eyejoker
18d7b315ea chore: clean remaining nanoclaw references from skill files
Update add-compact, add-voice-transcription, customize, and
update-skills SKILL.md files to reference EJClaw instead of NanoClaw.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 19:11:41 +09:00
Eyejoker
2fd4cfc9d0 chore: align setup with EJClaw dual-service architecture 2026-03-26 19:10:07 +09:00
Eyejoker
3efacbdda1 chore: remove legacy nanoclaw CI workflows
Remove bump-version, update-tokens, and merge-forward-skills workflows
inherited from upstream nanoclaw. These require APP_ID/APP_PRIVATE_KEY
secrets not configured for EJClaw and are unnecessary for the current
direct-deploy model. Only ci.yml (PR checks) is retained.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 16:56:13 +09:00
Eyejoker
9152a4ee18 style: format Claude usage cache migration guard 2026-03-26 16:37:38 +09:00
Eyejoker
d865a6b07f fix: stabilize Claude usage cache across token refreshes 2026-03-26 16:37:00 +09:00
Eyejoker
34c9ecd10b docs: update README to reflect current architecture and features
Add multi-account token rotation, provider fallback, CI monitoring,
usage dashboard. Fix Codex description (SDK, not app-server). Add
Authentication section with setup-token instructions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-26 11:37:30 +09:00
Eyejoker
f79baf1ff8 fix: avoid Claude token refresh races across services 2026-03-26 10:25:09 +09:00
Eyejoker
2b74e6fe40 style: format streamed output evaluator test 2026-03-26 10:13:02 +09:00
Eyejoker
a330ebdf2a fix: suppress Claude 502 provider errors from chat output 2026-03-26 10:11:24 +09:00
Eyejoker
bba19b0c0f docs: clarify Claude internal visibility rules 2026-03-25 23:43:46 +09:00
Eyejoker
8b5624731c docs: add GitHub CI watcher usage guide to platform prompts
Both Claude and Codex platform prompts now include a short
section explaining when to use structured GitHub fields
(ci_provider, ci_repo, ci_run_id) for the host-driven fast
path instead of the generic LLM-per-tick watcher.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 23:19:26 +09:00
Eyejoker
5c2e8e4fdc feat: allow status dashboard header without room details 2026-03-25 23:00:39 +09:00
Eyejoker
c7ba983ea6 feat: show watcher counts in status dashboard header 2026-03-25 22:52:02 +09:00
Eyejoker
20ca6c10fc style: fix prettier formatting in GitHub watcher scheduler tests 2026-03-25 22:44:02 +09:00
Eyejoker
09b4309d96 feat: add GitHub watcher backoff and auto-pause safeguards 2026-03-25 22:43:35 +09:00
Eyejoker
f51f282eb1 chore: update agent-runner package-lock.json
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 22:31:57 +09:00
Eyejoker
57f2045ca6 style: fix prettier formatting in github-ci and scheduler tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 22:31:52 +09:00
Eyejoker
33fcf9c788 feat: add host-driven GitHub Actions CI watcher (Level 3)
Replace LLM-per-tick polling with direct `gh api` calls for GitHub
Actions watchers. New `ci_provider` discriminator column routes tasks
to either the host-driven path (zero LLM tokens) or the existing
generic LLM path. GitHub watchers poll at 15s intervals (min 10s)
via `checkGitHubActionsRun()` in the scheduler, with completion
messages sent directly to chat on terminal state.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 22:31:42 +09:00
Eyejoker
07c1437055 style: fix prettier formatting in ipc processing loop 2026-03-25 22:00:52 +09:00
Eyejoker
691dbc3310 fix: claim IPC files before processing to avoid duplicates 2026-03-25 22:00:36 +09:00
Eyejoker
fad85ef027 style: fix prettier formatting in db migration 2026-03-25 21:54:27 +09:00
Eyejoker
c3c75882e4 fix: add watcher TTL and cleanup task-scoped artifacts 2026-03-25 21:54:15 +09:00
Eyejoker
113c540f10 style: fix prettier formatting in task-scheduler test 2026-03-25 21:41:08 +09:00
Eyejoker
24d93d5c78 fix: fail fast on missing host IPC dir for task runtimes 2026-03-25 21:40:34 +09:00
Eyejoker
5620301024 fix: pass EJCLAW_HOST_IPC_DIR to MCP server env for both runners
Watcher tasks get task-scoped IPC dirs (data/ipc/{group}/tasks/{taskId}/),
but the MCP server used HOST_IPC_DIR to write IPC files. Without
EJCLAW_HOST_IPC_DIR, it fell back to the task-scoped path, writing
cancel_task/send_message files to nested dirs the IPC watcher never scans.

This caused 11 zombie watchers stuck in infinite loops — self-cancel
calls silently failed with ~4000 stranded IPC files accumulating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 21:05:22 +09:00
Eyejoker
c89242b6dd fix: harden stripToolCallLeaks regex for CJK/non-ASCII garbage tokens
The previous regex used \w+ for descriptor tokens between the function
name and JSON body, which only matches ASCII word characters. Model
hallucinations often inject CJK/non-ASCII text (e.g. 彩神争霸) in this
position. Switch to (?:\s+[^\s{}]+)+ to match any whitespace-separated
non-brace tokens regardless of character set.

Also removes stale backward-compat re-exports from index.ts and updates
the test import for composeDashboardContent.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 18:06:31 +09:00
Eyejoker
6806001ed6 style: fix prettier formatting after type union refactor
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:46:54 +09:00
Eyejoker
94eeaa5e3e refactor: introduce AgentTriggerReason type union as SSOT for error reason strings
Replace scattered reason string literals with a centralized type hierarchy:
- AgentTriggerReason: all possible trigger reasons
- ClaudeRotationReason, CodexRotationReason, NoFallbackCooldownReason:
  derived subtypes for specific contexts
- AgentErrorClassification, FallbackTriggerResult, CodexRotationTriggerResult:
  discriminated unions for compile-time narrowing

Remove dead export isUsageExhausted() (superseded by
isPrimaryNoFallbackCooldownActive). Replace NO_FALLBACK_COOLDOWN_REASONS
Set with isNoFallbackCooldownReason() type guard.

Add tests for agent-error-detection and provider-retry (423 total passing).

Known limitation: 6 `as CodexRotationReason` casts in Codex rotation paths
where streamed trigger reason is AgentTriggerReason but runtime value is
always CodexRotationReason-compatible.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:46:43 +09:00
Eyejoker
b86fd1ad89 style: fix prettier formatting in streamed-output-evaluator ternary chain
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:24:25 +09:00
Eyejoker
60a9fe86ec fix: detect org-access-denied errors, suppress chat output, and rotate Claude tokens
When a Claude account is suspended, the API returns "Your organization does
not have access to Claude" on the success path or "Failed to authenticate.
API Error: 403 terminated" on the error path. Both are now classified as
'org-access-denied', suppressed from Discord output, and trigger automatic
token rotation. If all tokens are exhausted, enters cooldown without Kimi
fallback (same as usage-exhausted and auth-expired).

Changes:
- agent-error-detection: add isClaudeOrgAccessDeniedMessage(), expand
  classifyClaudeAuthError() and shouldRotateClaudeToken()
- streamed-output-evaluator: detect org-access-denied in success-path chain
- provider-fallback: add NO_FALLBACK_COOLDOWN_REASONS set and
  isPrimaryNoFallbackCooldownActive() helper
- provider-retry: handle org-access-denied in rotation loop
- message-agent-executor / task-scheduler: use generalized no-fallback
  cooldown check
- Tests: +8 test cases across 5 test files (415 total passing)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 17:24:10 +09:00
Eyejoker
3e1e032346 style: fix prettier formatting in formatting tests
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:51:25 +09:00
Eyejoker
273d52d3da fix: unify agentType value domain to 'claude-code' | 'codex'
The streamed-output-evaluator used 'claude' while the rest of the
codebase used 'claude-code'. Align the evaluator type and all call
sites (message-agent-executor, task-scheduler) to use the canonical
'claude-code' | 'codex' domain consistently.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:51:09 +09:00
Eyejoker
8fee2ab3fc fix: strip leaked tool-call serialization text in formatOutbound()
When Codex enters a degenerate loop, it emits tool-call intent as
plaintext (e.g. `to=functions.exec_command code {"cmd":"..."}`) instead
of actual tool calls. Add stripToolCallLeaks() defense layer to remove
these patterns before they reach Discord. Pure garbage output becomes
empty and is suppressed entirely.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:51:03 +09:00
Eyejoker
f62aa261e6 refactor: replace boolean trio with explicit RunPhase state machine in GroupQueue
Replace `active/closingStdin/isTaskProcess` booleans with a single `runPhase`
enum (idle | running_messages | running_task | closing_messages). Add
`resetRunState()` to eliminate 7-field reset duplication, and
`assertRunPhaseInvariants()` for runtime validation of field consistency
after every phase transition. Add 3 transition tests covering the full
lifecycle, closeStdin during tasks, and sendMessage phase gating.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:55:51 +09:00
Eyejoker
61786cacbf test: add streamed-output-evaluator unit tests
22 tests covering all code paths: success/error forwarding,
Claude banner detection (usage-exhausted, auth-expired), duplicate
trigger suppression, auth error suppression, null-result tracking,
fallback/rotation trigger dispatch, and state immutability.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 12:40:44 +09:00