- Add Dockerfile, docker-compose.yml, and .dockerignore for Bun dev container
- Fix sdkLogger to use logger.warn instead of logger.log for warnings
- Add proper warn method to logger (writes to file instead of console)
- Use console.log for daemon startup messages to keep them visible
- Update cashu-ts getDecodedToken call with explicit well-known-pubkeys
- Use proof.amount.toNumber() for updated cashu-ts Amount type
- daemon/index.ts: add makeSdkLogger() factory, wire daemonSdkLogger into
createBunSqliteDriver, createProviderRegistryFromStore, ModelManager, ProviderManager
- daemon/http/index.ts: add makeSdkLogger() factory, generate per-request
reqId via randomBytes(4), pass reqLogger = sdkLogger.child("req:${reqId}")
to routeRequests so every log line from a request is prefixed [req:XXXXXXXX]
- start-daemon.ts: remove >> logfile 2>&1 redirect and getTodayLogFile();
all file logging now goes through the daemon's writeLog() with daily rotation
Result: Every log line from a request is prefixed [req:XXXXXXXX], all entries
have [ISO] [INFO/ERROR/DEBUG] timestamps, no duplicates, and the log file
rotates correctly at midnight.
After bootstrapProviders runs, newly discovered URLs (e.g. privateprovider.xyz)
were only known to the ModelManager cache and never written into the store's
baseUrlsList. This caused `providers list` and `models -m <id>` to show
different sets of providers. Now the bootstrap step merges any new URLs into
the store so both commands draw from the same source of truth.
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
When cocod cannot assemble enough proofs to send (e.g. due to
denomination fragmentation or stale proof state), it returns
"Send failed: Not enough proofs to send". This was propagating
as a generic Error, causing the HTTP handler to return 500 instead
of the structured 402 insufficient_balance response.
Map that cocod error to InsufficientBalanceError in walletAdapter.sendToken
so the existing handler path returns the correct 402.
Co-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>
- Add ownerNpub?: string to ClientEntry and DaemonClient interfaces
- Update getClientsFromStore() to preserve ownerNpub field
- GET /clients: include ownerNpub in daemon response
- POST /clients/add: accept and store ownerNpub from auth proxy
- Remove getNpubSuffix/addSuffixToId/removeSuffixFromId from clients.ts (moved to auth proxy)
- Remove CLI-side suffixing in addDaemonClient and deleteClientAction
- Remove config loading from getClientsList (no longer needed for filtering)
- CLI output now shows raw client IDs without suffix stripping
When multiple routstrd processes (or CLI auto-starts) bootstrap simultaneously,
each process found cocod/routstrd unreachable, spawned its own copy, and
contended for the same database socket. The paired ~200ms burst timestamps
in the logs were the symptom.
Fixes applied:
- Add cross-process startup lock (process-lock.ts)
- Uses atomic mkdir as the lock primitive.
- Stores PID + UUID token; verifies ownership on release to avoid
removing a lock taken by a new process after the original crashed.
- Removes stale locks (unreachable PID or lock older than staleAfterMs).
- Exports withCrossProcessLock() for simple RAII-style usage.
- Fix cocod startup race (cocod-client.ts)
- Wrap ensureDaemonRunning() in a socket-derived lock path.
- Re-ping inside the lock before spawning; if another process just started
cocod, the current process detects it and connects instead of spawning.
- Switch from 'cocod daemon' to 'cocod init' for cleaner daemonization.
- Allow exit code 0 from 'cocod init' (normal daemon exit without error).
- Consolidate routstrd daemon startup (daemon-client.ts)
- startDaemonProcess() now delegates to startDaemon() from start-daemon.ts,
sharing the same lock and health-check logic.
- Add cross-process lock to routstrd daemon startup (start-daemon.ts)
- Performs pre-lock isDaemonHealthy() check to skip lock entirely when
already running.
- Performs re-check inside the lock before spawning to avoid duplicate
daemon processes.
- Created reusable refreshModelsAndIntegrations() function that combines
model refresh with client integration refresh
- Updated src/daemon/index.ts to use the new function in both the scheduled
refresh job and the initial bootstrap refresh
- Merged two chained .then() calls into one in the initial bootstrap flow
- Removed redundant imports (runIntegrationsForClients, getClientsList) from
daemon/index.ts since they're now encapsulated in the function
Replace direct store.getState().clientIds access with a shared utility:
- getClientsFromStore(store) for daemon/local usage
- getClientsList() for remote CLI usage via daemon API
This ensures integration refresh logic and client management work
consistently whether running inside the daemon or connecting to a
remote daemon where store access is unavailable.
Updated:
- src/daemon/index.ts: use getClientsFromStore for integration refresh
- src/daemon/http/index.ts: use getClientsFromStore in /clients endpoints
- src/utils/daemon-client.ts: use getClientsList in ensureDaemonClient
- src/cli.ts: use getClientsList in clients list command
- clients add --pi-agent/--opencode/--openclaw/--claude-code now call
/clients/add on the daemon instead of writing to local Bun SQLite
- add ensureIntegrationClient helper that creates via daemon and falls
back to fetching existing client on 409
- update install*Integration signatures to accept apiKey instead of SdkStore
- update onboard setupIntegration to use daemon-backed path
- update daemon scheduled refresh to pass apiKeys directly
Allow overriding the default cocod config directory (~/.cocod)
via the COCOD_DIR environment variable. Falls back to existing
HOME/USERPROFILE logic when unset.
Bump version to 0.2.6.
Updates all user-facing log messages to include the /v1 path suffix,
so clients know to use http://localhost:${port}/v1 when configuring
their API endpoints.
- src/cli.ts:717 — clients add --setup-all flow
- src/cli.ts:757 — clients add -n ${name} flow
- src/daemon/index.ts:206 — daemon startup message
- src/start-daemon.ts:29 — daemon already running message
Add -m/--model option to models serving a
specific model with their pricing details (prompt, completion, request,
max_cost in sats). Providers are sorted by max_cost (cheapest first).
New endpoint: GET /models/:id/providers
New function: getModelProviders() in model service
- Removed broken merge artifact with createUsageTracker
- Updated createDaemonRequestHandler to use usageTrackingDriver for all usage tracking
- Added walletClient to deps type
- Removed unused runWalletCommand and parseBalances from deps type
- Cleaned up unused imports in daemon/index.ts