@loicngr/kobo 2.1.16 → 2.1.19
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.
- package/AGENTS.md +101 -0
- package/CHANGELOG.md +12 -0
- package/CONFIGURATION.md +108 -17
- package/README.md +6 -2
- package/dist/mcp-server/kobo-tasks-server.js +28 -6
- package/dist/mcp-server/progress-bar-client.js +20 -0
- package/dist/mcp-server/workspace-dialogue-client.js +27 -7
- package/dist/server/db/migrations.js +2 -0
- package/dist/server/db/progress-bar-schema.js +27 -0
- package/dist/server/db/schema.js +2 -0
- package/dist/server/index.js +6 -0
- package/dist/server/middleware/workspace-creation-maintenance.js +13 -0
- package/dist/server/routes/maintenance.js +32 -0
- package/dist/server/routes/mcp.js +19 -9
- package/dist/server/routes/progress-bars.js +56 -0
- package/dist/server/routes/pull-requests.js +2 -1
- package/dist/server/routes/workspaces.js +35 -64
- package/dist/server/services/agent/engines/claude-code/engine.js +59 -16
- package/dist/server/services/agent/engines/claude-code/options-builder.js +13 -34
- package/dist/server/services/agent/engines/claude-code/stop-hook.js +8 -27
- package/dist/server/services/agent/engines/codex/engine.js +8 -1
- package/dist/server/services/agent/engines/codex/options-builder.js +11 -16
- package/dist/server/services/agent/orchestrator.js +73 -11
- package/dist/server/services/auto-loop-final-review-service.js +1 -1
- package/dist/server/services/auto-loop-service.js +10 -10
- package/dist/server/services/cron-service.js +7 -0
- package/dist/server/services/progress-bar-mcp-service.js +44 -0
- package/dist/server/services/progress-bar-runtime.js +29 -0
- package/dist/server/services/progress-bar-service.js +232 -0
- package/dist/server/services/quota-backoff-service.js +7 -0
- package/dist/server/services/update-maintenance-service.js +44 -0
- package/dist/server/services/wakeup-service.js +21 -3
- package/dist/server/services/workspace-creation-mcp-service.js +16 -0
- package/dist/shared/auto-loop-prompts.js +12 -12
- package/dist/shared/launch-instructions.js +57 -0
- package/dist/shared/progress-bar-prompts.js +7 -0
- package/dist/shared/progress-bar-tools.js +73 -0
- package/dist/shared/progress-bars.js +3 -0
- package/docker-compose.vps.yml +60 -0
- package/docs/deployment-vps.md +506 -0
- package/docs/getting-started.md +9 -0
- package/package.json +8 -1
- package/scripts/kobo-gh +9 -0
- package/scripts/kobo-github-app-token +190 -0
- package/scripts/kobo-install +392 -0
- package/scripts/kobo-update +499 -0
- package/src/client/dist/pwa/assets/ActivityFeed-DiUxnmGJ.js +2 -0
- package/src/client/dist/pwa/assets/{AutoLoopFinalReviewSettings-Bbrq02Xt.js → AutoLoopFinalReviewSettings-f4VDR5dd.js} +1 -1
- package/src/client/dist/pwa/assets/{ChangelogPage-BJfkAVYp.js → ChangelogPage-dEWpjTlp.js} +1 -1
- package/src/client/dist/pwa/assets/ComparisonPanel-Bwbqgvr4.js +2 -0
- package/src/client/dist/pwa/assets/CreatePage-CCCCAhrx.js +2 -0
- package/src/client/dist/pwa/assets/{DashboardPage-DZYsAh5y.js → DashboardPage-3byhBITf.js} +1 -1
- package/src/client/dist/pwa/assets/DiffViewer-Bj_NTfCF.js +8 -0
- package/src/client/dist/pwa/assets/{DocumentsPanel-BfPlfiwU.js → DocumentsPanel-xyLDV3T1.js} +1 -1
- package/src/client/dist/pwa/assets/{DrawerToggleButton-DG1Qjqk1.js → DrawerToggleButton-pwBSstQP.js} +1 -1
- package/src/client/dist/pwa/assets/GitPanel-DvIdrkVw.js +3 -0
- package/src/client/dist/pwa/assets/{HealthPage-_VXG1Zeo.js → HealthPage-BSwhZQRo.js} +1 -1
- package/src/client/dist/pwa/assets/MainLayout-DZJ9BvZw.js +2 -0
- package/src/client/dist/pwa/assets/{MainLayout-DnmUxNk7.css → MainLayout-DoAEgANU.css} +1 -1
- package/src/client/dist/pwa/assets/{MemoryPanel-CVlvGZXZ.js → MemoryPanel-ChR032zP.js} +1 -1
- package/src/client/dist/pwa/assets/{MemoryProposalList-SJsnzUAM.js → MemoryProposalList-BRKSoS4K.js} +1 -1
- package/src/client/dist/pwa/assets/{QBtnDropdown-DBgGsN-D.js → QBtnDropdown-o3QH0Bb8.js} +1 -1
- package/src/client/dist/pwa/assets/{QExpansionItem-DKgaMJ_l.js → QExpansionItem-BhFHiyq9.js} +1 -1
- package/src/client/dist/pwa/assets/{QScrollArea-D3OCsq3g.js → QScrollArea-BsNY6slB.js} +1 -1
- package/src/client/dist/pwa/assets/QSelect-bEq3g_io.js +1 -0
- package/src/client/dist/pwa/assets/{QTooltip-X5ps8Opw.js → QTooltip-xYZ6KNu2.js} +1 -1
- package/src/client/dist/pwa/assets/{SchedulePanel-Ww_FVlW5.js → SchedulePanel-DIFv_FTY.js} +1 -1
- package/src/client/dist/pwa/assets/{SearchPage-B87WEHf3.js → SearchPage-BqTBIt5E.js} +1 -1
- package/src/client/dist/pwa/assets/SettingsPage-BLD0xWFB.js +9 -0
- package/src/client/dist/pwa/assets/{SplitWorkspacePage-B99AJUbG.js → SplitWorkspacePage-D6r2pl5g.js} +1 -1
- package/src/client/dist/pwa/assets/{TerminalPanel-DnA1MXwu.js → TerminalPanel-CladK9Vv.js} +9 -9
- package/src/client/dist/pwa/assets/{ToolCallItem-2vFggaur.js → ToolCallItem-CdzEME4w.js} +3 -3
- package/src/client/dist/pwa/assets/{TouchPan-BSU3z0aO.js → TouchPan-B4gQPwGN.js} +1 -1
- package/src/client/dist/pwa/assets/{TourReplayButton-DQwS2xdD.js → TourReplayButton-B0j6AZwU.js} +1 -1
- package/src/client/dist/pwa/assets/{WorkspaceAttentionLabels-CM1tGDje.js → WorkspaceAttentionLabels-CeVhoidC.js} +1 -1
- package/src/client/dist/pwa/assets/WorkspacePage-CK5XCuG_.js +4 -0
- package/src/client/dist/pwa/assets/{WorkspacePage-B248nKIU.css → WorkspacePage-w2bF8wTd.css} +1 -1
- package/src/client/dist/pwa/assets/{browser-DPsupI9Q.js → browser-B8tNScg1.js} +1 -1
- package/src/client/dist/pwa/assets/{build-path-tree-CbIdt-p9.js → build-path-tree-kmVAcvs_.js} +1 -1
- package/src/client/dist/pwa/assets/custom-sounds-CJwd-8TL.js +1 -0
- package/src/client/dist/pwa/assets/{de-D3Ycvf_F.js → de-BaO6kbdO.js} +2 -2
- package/src/client/dist/pwa/assets/{editor.api-DvgAtnOj.js → editor.api-CgbPVW9s.js} +1 -1
- package/src/client/dist/pwa/assets/{efforts-nmxfTVQD.js → efforts-y7Wf_Rgd.js} +2 -2
- package/src/client/dist/pwa/assets/{es-TgeS5898.js → es-DTvSsbD0.js} +2 -2
- package/src/client/dist/pwa/assets/{expand-template-Brn5O4a1.js → expand-template-BFbbjj7X.js} +1 -1
- package/src/client/dist/pwa/assets/{format-DfJ3Fv1i.js → format-BETfc4z9.js} +1 -1
- package/src/client/dist/pwa/assets/{formatters-B30bNFhq.js → formatters-C22K9vlC.js} +1 -1
- package/src/client/dist/pwa/assets/{fr-CJafryNb.js → fr-BH7V66Yz.js} +2 -2
- package/src/client/dist/pwa/assets/{freemarker2-DnZe74tc.js → freemarker2-DiRVvp9O.js} +1 -1
- package/src/client/dist/pwa/assets/{handlebars-CmuMfxzO.js → handlebars-BLYRroSQ.js} +1 -1
- package/src/client/dist/pwa/assets/{html-BD7OJFGX.js → html-DAW2vteY.js} +1 -1
- package/src/client/dist/pwa/assets/i18n-DnuTmw3O.js +1 -0
- package/src/client/dist/pwa/assets/index-CbyHfF8I.js +20 -0
- package/src/client/dist/pwa/assets/{it-C5mN8Y61.js → it-DZGbkkoy.js} +2 -2
- package/src/client/dist/pwa/assets/{javascript-Y-OrgcmW.js → javascript-Bb5J8n0k.js} +1 -1
- package/src/client/dist/pwa/assets/{liquid-BqOkKePH.js → liquid-Dqx3adnJ.js} +1 -1
- package/src/client/dist/pwa/assets/{mdx-D-58x2h0.js → mdx-D_7igLV3.js} +1 -1
- package/src/client/dist/pwa/assets/{monaco-contributions-BW4ZMKO6.js → monaco-contributions-C-0CbrAy.js} +1 -1
- package/src/client/dist/pwa/assets/{monaco.contribution-DJWqzNG-.js → monaco.contribution-c6JPBEZI.js} +2 -2
- package/src/client/dist/pwa/assets/network-auth-BE4qbvWm.js +1 -0
- package/src/client/dist/pwa/assets/notify-theme-BVFBBGrJ.js +1 -0
- package/src/client/dist/pwa/assets/{project-color-gB5yeZPN.js → project-color-CHOR2jB5.js} +1 -1
- package/src/client/dist/pwa/assets/{python-BkBj1wDC.js → python-Dqubw1F5.js} +1 -1
- package/src/client/dist/pwa/assets/{razor-DOOJ_0b8.js → razor-BQphc9Kt.js} +1 -1
- package/src/client/dist/pwa/assets/{typescript-Bheo43G5.js → typescript-Dep00l0X.js} +1 -1
- package/src/client/dist/pwa/assets/{use-search-index-status-CBpnyV-R.js → use-search-index-status-CQHHvHwM.js} +1 -1
- package/src/client/dist/pwa/assets/{use-tours-BHNasCvg.js → use-tours-IVbXTmz2.js} +2 -2
- package/src/client/dist/pwa/assets/{use-worktree-restore-CgABsWno.js → use-worktree-restore-B3s5xDGR.js} +1 -1
- package/src/client/dist/pwa/assets/{workspace-templates-BnFkigYg.js → workspace-templates-CyuTpztP.js} +1 -1
- package/src/client/dist/pwa/assets/{xml-vHt2BD26.js → xml-BMS2dvaF.js} +1 -1
- package/src/client/dist/pwa/assets/{yaml-BvhLPzP9.js → yaml-CYw92aic.js} +1 -1
- package/src/client/dist/pwa/index.html +1 -1
- package/src/client/dist/pwa/sw.js +1 -1
- package/src/mcp-server/README.md +88 -1
- package/src/mcp-server/kobo-tasks-server.ts +34 -6
- package/src/mcp-server/progress-bar-client.ts +27 -0
- package/src/mcp-server/workspace-dialogue-client.ts +26 -7
- package/src/client/dist/pwa/assets/ActivityFeed-tJmJhmtl.js +0 -2
- package/src/client/dist/pwa/assets/ComparisonPanel-BfP8APKY.js +0 -2
- package/src/client/dist/pwa/assets/CreatePage-BbtNfo0x.js +0 -2
- package/src/client/dist/pwa/assets/DiffViewer-4Q-GJgyA.js +0 -8
- package/src/client/dist/pwa/assets/GitPanel-ECnbb_rx.js +0 -3
- package/src/client/dist/pwa/assets/MainLayout-BH6grTuW.js +0 -2
- package/src/client/dist/pwa/assets/QSelect-Cb_s_nox.js +0 -1
- package/src/client/dist/pwa/assets/SettingsPage-BAZLGUyg.js +0 -9
- package/src/client/dist/pwa/assets/WorkspacePage-CQN6EKIn.js +0 -4
- package/src/client/dist/pwa/assets/custom-sounds-DR68eyF8.js +0 -1
- package/src/client/dist/pwa/assets/i18n-BY4JeBjk.js +0 -1
- package/src/client/dist/pwa/assets/index-C5fAw9ll.js +0 -20
- package/src/client/dist/pwa/assets/network-auth-BGPRhUa6.js +0 -1
- package/src/client/dist/pwa/assets/notify-theme-DZDzfxph.js +0 -1
package/AGENTS.md
CHANGED
|
@@ -41,6 +41,7 @@ npm run typecheck:tests # type check backend test fixtures and tests
|
|
|
41
41
|
npm test # backend vitest suite
|
|
42
42
|
(cd src/client && npm test) # client stores, utilities, composables and components
|
|
43
43
|
npm run test:all # backend + client suites
|
|
44
|
+
npm run test:deployment # Python 3.10+ / OpenSSL tooling tests; no Docker/network/production data
|
|
44
45
|
make ci # install, audit, lint, type checks, build, both suites
|
|
45
46
|
npm run test:watch # vitest in watch mode
|
|
46
47
|
|
|
@@ -125,6 +126,7 @@ src/
|
|
|
125
126
|
| `workspace_activity` | significant lifecycle/PR events for the absence digest |
|
|
126
127
|
| `search_*` | derived logical-message search index and indexing progress; see `search-schema.ts` |
|
|
127
128
|
| `workspace_message_batches` | immutable recipient snapshots, request fingerprint and per-recipient delivery outcomes (v53); no stored message body |
|
|
129
|
+
| `session_progress_bars` | agent-reported session activities, producer ordering, terminal state and durable individual dismissal (v54); CASCADE DELETE on workspace/session |
|
|
128
130
|
| `mcp_message_requests` | durable external-message idempotency ledger; independent of event retention |
|
|
129
131
|
| `schema_migrations` | applied migration versions, names and timestamps |
|
|
130
132
|
| `workspace_chat_history` | chat-input history per workspace: message text + `created_at`, ordered by autoincrement id, capped at 200 entries by the service; CASCADE DELETE on workspace |
|
|
@@ -199,6 +201,31 @@ Every feature that touches the schema:
|
|
|
199
201
|
|
|
200
202
|
## WebSocket protocol
|
|
201
203
|
|
|
204
|
+
Session progress bars use the separate `progress:changed` ephemeral event with a
|
|
205
|
+
public record payload and workspace/session envelope. Persist the row before
|
|
206
|
+
broadcasting; never append numeric updates to chat history or overload native
|
|
207
|
+
`subagent:progress`. Clients hydrate on selected-session changes and reconnect,
|
|
208
|
+
merge server revisions, and preserve dismissal across races. Success visibility
|
|
209
|
+
expires at the stored completion time plus five seconds, not five seconds after
|
|
210
|
+
each fetch. Three rows are initially visible with bounded expandable overflow.
|
|
211
|
+
|
|
212
|
+
The four progress MCP tools share service validation across workspace stdio,
|
|
213
|
+
global stdio and HTTP. Internal ownership comes from the dedicated per-launch
|
|
214
|
+
`KOBO_PROGRESS_SESSION_TOKEN`, independent of memory modes/budgets; external
|
|
215
|
+
calls explicitly select an existing workspace/session. Revoke internal writers
|
|
216
|
+
when stopping starts, but interrupt their remaining bars only on confirmed
|
|
217
|
+
controller closure. Late callbacks must not affect a replacement launch or
|
|
218
|
+
reopen a closed database. Startup reconciles lost internal reporters while
|
|
219
|
+
preserving external ones. An interrupted reporter is not proof of cancelled
|
|
220
|
+
background work. Operational reporting never satisfies auto-loop verification.
|
|
221
|
+
|
|
222
|
+
Retain scoped activity-key fingerprints, producer sequences and dismissed rows
|
|
223
|
+
for retries; subsequent updates cannot resurrect a dismissed indicator or undo a
|
|
224
|
+
terminal state. Bound labels, steps, page size, active/retained records and update
|
|
225
|
+
frequency. Launch prompts instruct parent agents and their delegates to report
|
|
226
|
+
long-running work; restricted review/handoff launches receive only the explicit
|
|
227
|
+
operational-tool exception, never broader mutation permissions.
|
|
228
|
+
|
|
202
229
|
Claude streaming input is correlated by per-message UUIDs. A result can cover
|
|
203
230
|
several prompts through `user_message_uuids` (messages folded into one turn),
|
|
204
231
|
not one result per sent message. Retire only the matching yielded inputs;
|
|
@@ -248,6 +275,57 @@ Two emit flavors in `websocket-service.ts`:
|
|
|
248
275
|
|
|
249
276
|
## External integrations
|
|
250
277
|
|
|
278
|
+
### VPS deployment tooling
|
|
279
|
+
|
|
280
|
+
`docker-compose.vps.yml` is the standalone fresh-instance example for an existing
|
|
281
|
+
Traefik network. It persists `/root`, mounts project paths identically on host and
|
|
282
|
+
container, and leaves the Docker socket opt-in. `docs/deployment-vps.md` owns the
|
|
283
|
+
operator walkthrough; `CONFIGURATION.md` compares all Compose topologies.
|
|
284
|
+
|
|
285
|
+
`scripts/kobo-install` guides a fresh installation; it does not adopt existing
|
|
286
|
+
unmanaged stacks. Preserve its read-only `--check`, explicit Docker-socket opt-in,
|
|
287
|
+
managed-file fingerprints, shared updater lock, and durable start phases. Completed
|
|
288
|
+
reruns must never restart containers or replace credentials. Only the updater's
|
|
289
|
+
image pin may differ from the managed Compose fingerprint. Interrupted starts
|
|
290
|
+
require diagnosis instead of automatic recreation. This tool reuses the updater's
|
|
291
|
+
release resolution/build helpers; no separate public image registry is assumed.
|
|
292
|
+
|
|
293
|
+
Optional GitHub App authentication uses `scripts/kobo-gh` and
|
|
294
|
+
`scripts/kobo-github-app-token`, mounted read-only with the user's RSA key. The
|
|
295
|
+
wrapper honors explicit `GH_TOKEN` / `GITHUB_TOKEN`, otherwise obtains a renewable
|
|
296
|
+
installation token from the private, locked cache. Keep JWTs, PEM contents and
|
|
297
|
+
tokens out of logs/errors. HTTPS Git uses the same wrapper via a github.com-scoped
|
|
298
|
+
credential helper; commit author identity is configured separately. Never bake
|
|
299
|
+
credentials into an image or add web settings for these host-managed secrets.
|
|
300
|
+
|
|
301
|
+
`scripts/kobo-update` is a Python 3.10+ operator tool for this layout, separate
|
|
302
|
+
from the backend's update notifications. Preserve explicit invocation, idle checks,
|
|
303
|
+
unique image tags, private stopped-volume backups, migration tests on a copy,
|
|
304
|
+
and durable failure records. The authenticated `/api/maintenance/update` reservation
|
|
305
|
+
checks runtime ownership and closes agent admission synchronously before shutdown.
|
|
306
|
+
Track in-flight workspace creations and PR checkouts through all asynchronous
|
|
307
|
+
steps and rollback. Maintenance and creation admission must exclude each other
|
|
308
|
+
synchronously; rejecting only the final agent start is too late. Direct HTTP and
|
|
309
|
+
MCP creation paths share this guard.
|
|
310
|
+
Scheduled cron/wakeup/quota deliveries defer without consuming persisted intent;
|
|
311
|
+
valid pending wakeups get `retry_at=target_at` before successful reservation (only
|
|
312
|
+
when `retry_at` was null), so long maintenance does not expire them at boot. Keep
|
|
313
|
+
the requested deadline/prompt and existing retry metadata; do not revive already
|
|
314
|
+
stale, never-attempted wakeups. New wakeups scheduled during maintenance get the
|
|
315
|
+
same durable deferral marker.
|
|
316
|
+
Replaced timers must invalidate deferred callbacks. Legacy runtimes without this
|
|
317
|
+
protocol refuse automatic deployment while `--prepare` remains available. Failed
|
|
318
|
+
pre-stop requests release their reservation; uncertain stops must be confirmed
|
|
319
|
+
before restarting. A crashed updater may require the documented manual recovery. Never automatically run an old image against a
|
|
320
|
+
potentially migrated database or restore snapshots after new work may have run.
|
|
321
|
+
No deployment-specific hostname, App credentials or private source paths belong
|
|
322
|
+
in this script. Its deterministic tests run through `npm run test:deployment`,
|
|
323
|
+
`make ci` and the PR workflow; live deployment is not a CI test.
|
|
324
|
+
Installer/updater Compose commands explicitly select the stack's `.env` and strip
|
|
325
|
+
the template's Kobo/Traefik interpolation variables plus `COMPOSE_*` from a copy
|
|
326
|
+
of the child environment. Apply the same policy to captured and logged commands;
|
|
327
|
+
never mutate the parent environment or lose Docker/forge authentication settings.
|
|
328
|
+
|
|
251
329
|
### Forge providers
|
|
252
330
|
|
|
253
331
|
`src/server/services/forge/` implements `ForgeProvider` for `github` (`gh`), `gitlab` (`glab`), `bitbucket-community` (`bkt`), and `none` (disables PR/MR features). `getForgeProvider(id)` resolves a provider; `resolveForge(projectPath)` first reads the explicit project setting, then classifies the `origin` URL by `github.com`, `gitlab`, or `bitbucket`, falling back to `none`. Successful remote reads are cached for five minutes. PR routes and the watcher use the resolved provider. **Kōbō ships no forge credentials**: users authenticate `gh`/`glab` themselves; Bitbucket uses the email and API token entered in Settings, passed to `bkt` and excluded from settings exports. Missing or unauthenticated CLIs disable PR/MR actions with an explanation.
|
|
@@ -267,6 +345,29 @@ When adding features touching `notion-service.ts`, remember: **no token = no fea
|
|
|
267
345
|
|
|
268
346
|
See the "Notion integration" section of the README for the end-user setup guide.
|
|
269
347
|
|
|
348
|
+
### Launch instructions
|
|
349
|
+
|
|
350
|
+
`src/shared/launch-instructions.ts` composes application-owned MCP discovery,
|
|
351
|
+
permissions, progress reporting and continuation rules for both engines on every
|
|
352
|
+
fresh/resumed launch. Prefer discovering the available tool schemas to embedding
|
|
353
|
+
a duplicate catalogue. Keep Plan conversation-only; template approval cannot
|
|
354
|
+
expand tool permissions. Initial writable auto-loop launches seed tasks and end;
|
|
355
|
+
manual launches implement under the workflow policy. Preserve custom templates
|
|
356
|
+
and frozen migration text when changing generated guidance.
|
|
357
|
+
|
|
358
|
+
The engine's `onPromptPrepared` callback supplies only its textual Kōbō prefix and
|
|
359
|
+
system append. Initial creation and pending initial retries opt into a single
|
|
360
|
+
session-scoped `user:message` with `sender: system-prompt`, displayed as Kōbō
|
|
361
|
+
instructions. Snapshot the orchestration context before memory is appended; never
|
|
362
|
+
serialize engine options, capability tokens or memory bodies into chat. This is
|
|
363
|
+
a prepared-launch record, not delivery confirmation. Snapshot failures must not
|
|
364
|
+
prevent launch. Require durable snapshot persistence before clearing the pending
|
|
365
|
+
initial prompt, using a compare-and-clear against the original mission. Async
|
|
366
|
+
preparation failures must leave that pending prompt available for retry. Historical rows remain unchanged. Handoff generation is enforced
|
|
367
|
+
read-only with only its managed capability-scoped report and operational progress
|
|
368
|
+
metadata exceptions. Ordinary Claude Plan launches cannot promote themselves
|
|
369
|
+
through `ExitPlanMode`; a permission change requires a new launch.
|
|
370
|
+
|
|
270
371
|
### Agent engines
|
|
271
372
|
|
|
272
373
|
Two engines live under `src/server/services/agent/engines/`, both implementing the `AgentEngine` contract in `types.ts`:
|
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,18 @@ All notable changes to Kōbō are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/). Each release is an `## <version>`
|
|
5
5
|
section — the in-app "What's new" dialog reads this file.
|
|
6
6
|
|
|
7
|
+
## 2.1.19
|
|
8
|
+
|
|
9
|
+
- feat(progress): add session activity bars and improve launch prompts
|
|
10
|
+
|
|
11
|
+
## 2.1.18
|
|
12
|
+
|
|
13
|
+
- fix(tests): resolve deployment paths on macos
|
|
14
|
+
|
|
15
|
+
## 2.1.17
|
|
16
|
+
|
|
17
|
+
- feat(kobo): add VPS tooling and touch drawer resizing
|
|
18
|
+
|
|
7
19
|
## 2.1.16
|
|
8
20
|
|
|
9
21
|
- feat(workspaces): add group messaging and expand mcp lifecycle tools
|
package/CONFIGURATION.md
CHANGED
|
@@ -35,6 +35,8 @@ Reference for Kōbō configuration and external integrations. The tables cover t
|
|
|
35
35
|
- [Quick local test — docker-compose.local.yml](#quick-local-test--docker-composelocalyml)
|
|
36
36
|
- [Rehearsing the reverse-proxy stack — docker-compose.local-traefikyml](#rehearsing-the-reverse-proxy-stack--docker-composelocal-traefikyml)
|
|
37
37
|
- [Real deployment — docker-compose.exampleyml](#real-deployment--docker-composeexampleyml)
|
|
38
|
+
- [VPS with existing Traefik](#vps-with-existing-traefik)
|
|
39
|
+
- [Docker updates and backups](#docker-updates-and-backups)
|
|
38
40
|
- [Troubleshooting](#troubleshooting)
|
|
39
41
|
- [Agent runtimes](#agent-runtimes)
|
|
40
42
|
- [Claude Code](#claude-code)
|
|
@@ -255,6 +257,12 @@ When working from source, `npm run install-all` installs the root, client, and
|
|
|
255
257
|
build-only Workbox dependencies and is required by `npm run build`, but not by
|
|
256
258
|
the normal development client.
|
|
257
259
|
|
|
260
|
+
On touch screens, drag the inner edge of either side panel to resize it. The
|
|
261
|
+
horizontal divider inside the right panel can also be dragged. Widths and the
|
|
262
|
+
split position are remembered in this browser; on small screens, a strip of the
|
|
263
|
+
chat remains visible so you can tap outside a panel to close it. Sidebar actions
|
|
264
|
+
wrap onto additional lines when needed, keeping Settings and Create accessible.
|
|
265
|
+
|
|
258
266
|
## Custom change-source-branch script
|
|
259
267
|
|
|
260
268
|
The **Change source branch** action uses the effective `changeSourceBranchScript`:
|
|
@@ -849,6 +857,44 @@ The **External LLM access (MCP)** panel within global Network access settings pr
|
|
|
849
857
|
|
|
850
858
|
External senders can supply `idempotency_key` once per intended message and reuse it on retries. The durable receipt survives backend restarts and event retention. An uncertain delivery is explicitly reported and never automatically sent again; see the MCP guide for response codes and limitations.
|
|
851
859
|
|
|
860
|
+
## Session progress bars
|
|
861
|
+
|
|
862
|
+
Agents can report long-running tests, builds or reviews through the
|
|
863
|
+
`create_progress_bar`, `update_progress_bar`, `finish_progress_bar` and
|
|
864
|
+
`list_progress_bars` MCP tools. These tools are available through the workspace
|
|
865
|
+
MCP server, global stdio and the external HTTP endpoint. External clients select
|
|
866
|
+
an existing workspace and session; reporting progress never launches an agent.
|
|
867
|
+
|
|
868
|
+
Bars appear above the message input for the **selected session**, even while you
|
|
869
|
+
scroll its conversation. Each has an activity label, an optional current step,
|
|
870
|
+
and either measured progress or an indeterminate indicator. Three bars are shown
|
|
871
|
+
initially; **See others** expands a bounded list. Progress is reported by the
|
|
872
|
+
agent, not measured automatically by Kōbō, and does not validate workspace tasks
|
|
873
|
+
or acceptance criteria.
|
|
874
|
+
|
|
875
|
+
A successful bar disappears five seconds after its recorded completion. Failed
|
|
876
|
+
activities stay visible until you dismiss them. Closing a bar only hides that
|
|
877
|
+
indicator: work continues, later updates cannot bring it back, and new activities
|
|
878
|
+
still appear. Dismissal is saved on the server and shared across browser tabs
|
|
879
|
+
and reloads. Reconnecting does not restart the success display timer.
|
|
880
|
+
|
|
881
|
+
If an internal reporter's agent runtime closes before completion, its bar shows
|
|
882
|
+
that **reporting was interrupted**. This does not prove that an independently
|
|
883
|
+
running shell command was cancelled. On server restart, internal reporters from
|
|
884
|
+
the previous process are interrupted; external reporters may still be running
|
|
885
|
+
elsewhere, so their last state is preserved. A new internal launch uses a new
|
|
886
|
+
reporting identity.
|
|
887
|
+
|
|
888
|
+
Workspace launch instructions require agents to use these tools for long tasks
|
|
889
|
+
and pass the requirement to subagents. When a restricted subagent cannot access
|
|
890
|
+
the tools, its parent reports the activity on its behalf. Reporting permissions
|
|
891
|
+
do not grant permission to edit project files or complete tasks during a review.
|
|
892
|
+
|
|
893
|
+
The service retains at most 1,000 indicators per session, with at most 32 running
|
|
894
|
+
at once. Hidden records are retained so retries cannot recreate dismissed bars.
|
|
895
|
+
The [MCP progress guide](src/mcp-server/README.md#session-progress-tools) documents
|
|
896
|
+
arguments, ordering, retry behavior and update limits.
|
|
897
|
+
|
|
852
898
|
## Persistent memory
|
|
853
899
|
|
|
854
900
|
Kōbō stores deliberate, concise facts in SQLite, independently of Claude Code's native memory and provider chat history. Claude Code and Codex read the same Kōbō scopes, so a fact saved in one engine can be available to the other. There is no background transcript extractor or extra LLM call: agents must deliberately use the memory tools to save useful knowledge.
|
|
@@ -1108,27 +1154,31 @@ For the concrete Docker setup (which compose file, which env vars, which volumes
|
|
|
1108
1154
|
|
|
1109
1155
|
## Docker deployment
|
|
1110
1156
|
|
|
1111
|
-
Kōbō ships an official `Dockerfile` and
|
|
1112
|
-
|
|
1157
|
+
Kōbō ships an official `Dockerfile` and four Compose examples. Choose whether you
|
|
1158
|
+
want to reuse host credentials or start an independent instance, and whether
|
|
1159
|
+
Traefik already exists. Build the image from a source checkout before starting.
|
|
1113
1160
|
|
|
1114
1161
|
### Choosing a compose file
|
|
1115
1162
|
|
|
1116
1163
|
| File | Topology | Use it for |
|
|
1117
1164
|
|---|---|---|
|
|
1118
|
-
| [`docker-compose.local.yml`](./docker-compose.local.yml) | Kōbō only, port `3000` published directly. No Traefik,
|
|
1165
|
+
| [`docker-compose.local.yml`](./docker-compose.local.yml) | Kōbō only, port `3000` published directly. No Traefik, TLS, published SSH port or Docker socket. | Trying Kōbō out or poking at a change locally — the fastest path to a running instance. |
|
|
1119
1166
|
| [`docker-compose.local-traefik.yml`](./docker-compose.local-traefik.yml) | Traefik in front, Kōbō never on a published port, `kobo.localhost` (auto-resolves to `127.0.0.1`, no `/etc/hosts` editing). | Rehearsing the exact reverse-proxy topology/auth/mount setup locally, before touching a real VPS. |
|
|
1167
|
+
| [`docker-compose.vps.yml`](./docker-compose.vps.yml) | Kōbō only, existing external Traefik network, persistent `/root`, no published ports or host credential mounts. | A fresh, independent remote instance; follow the [VPS guide](./docs/deployment-vps.md). |
|
|
1120
1168
|
| [`docker-compose.example.yml`](./docker-compose.example.yml) | Traefik + Let's Encrypt (real domain, real TLS), SSH access, optional Docker-socket passthrough. | The reference for an actual production deployment (VPS behind a reverse proxy). |
|
|
1121
1169
|
|
|
1122
|
-
All
|
|
1123
|
-
|
|
1124
|
-
|
|
1170
|
+
All four use the same underlying image (`docker build -t kobo:local .` from the
|
|
1171
|
+
repo root). The original three mount provider/Git configuration from the host;
|
|
1172
|
+
the VPS example keeps independent credentials in a persistent container home.
|
|
1173
|
+
The VPS example overrides the entrypoint to start Node directly; the original
|
|
1174
|
+
files use the image entrypoint, which starts `sshd` even when port 22 is not published.
|
|
1125
1175
|
|
|
1126
1176
|
### The image
|
|
1127
1177
|
|
|
1128
1178
|
Multi-stage `Dockerfile`, `node:24.19.0-slim` base:
|
|
1129
1179
|
|
|
1130
1180
|
- **Build stage**: installs root, client, and PWA deps, then runs `npm run build` (client via Quasar, server via `tsc`).
|
|
1131
|
-
- **Runtime stage**: production deps only, plus OS tooling the agents and forge CLIs need — `git`, `openssh-client` + `openssh-server`, `ripgrep`, `fd-find`, `jq`, `curl`, Python + build tools, the Docker CLI (talks to a mounted host socket, see [Volumes](#volumes)), `gh`, `glab`, `tmux`, `vim`/`nano`, and more for interactive shell use.
|
|
1181
|
+
- **Runtime stage**: production deps only, plus OS tooling the agents and forge CLIs need — `git`, `openssh-client` + `openssh-server`, `ripgrep`, `fd-find`, `jq`, `curl`, Python + build tools, the Docker CLI and Compose plugin (`docker compose`, talks to a mounted host socket, see [Volumes](#volumes)), `gh`, `glab`, `tmux`, `vim`/`nano`, and more for interactive shell use.
|
|
1132
1182
|
- **Global CLIs**: `@anthropic-ai/claude-code` and `@openai/codex` are installed globally for interactive login (`claude /login`, `codex login` over SSH) — separate from Kōbō's own bundled SDK/subprocess usage, which needs no global install.
|
|
1133
1183
|
- **`git config --system --add safe.directory '*'`**: the container runs as root, but bind-mounted project repos keep the *host* user's UID on disk. Git's ownership check (CVE-2022-24765 mitigation) refuses to touch a repo it doesn't "own" unless told otherwise. This line pre-trusts every mounted path — fine for a single-user dev container, not something you'd do on a multi-tenant host.
|
|
1134
1184
|
- **`HEALTHCHECK`**: `curl -f http://localhost:$SERVER_PORT/api/health` every 30s. `/api/health` is exempt from the network-access token gate unconditionally (even with `networkAccessBehindProxy` on) — Docker's `HEALTHCHECK` process has no way to supply the runtime-generated token, and without the exemption a "behind a reverse proxy" container never reports healthy, which makes Traefik's Docker provider filter it out of its router table entirely (Traefik drops unhealthy/starting containers from routing).
|
|
@@ -1142,11 +1192,13 @@ Beyond the [general environment variables](#environment-variables), these matter
|
|
|
1142
1192
|
|
|
1143
1193
|
| Variable | Where it's set | Purpose |
|
|
1144
1194
|
|---|---|---|
|
|
1145
|
-
| `KOBO_HOME` | all
|
|
1146
|
-
| `KOBO_NETWORK_ACCESS_ENABLED` | all
|
|
1147
|
-
| `KOBO_NETWORK_ACCESS_BEHIND_PROXY` | `local-traefik.yml`, `example.yml` | Disables the loopback-trust bypass entirely — needed whenever a reverse proxy sits in front, since every request now looks like it comes from the proxy. Not set in `local.yml`, which publishes Kōbō's port directly with no proxy in between. |
|
|
1148
|
-
| `GH_TOKEN` / `GITLAB_TOKEN` | `example.yml` (bring your own via `.env`) |
|
|
1149
|
-
| `KOBO_PROJECTS_DIR` |
|
|
1195
|
+
| `KOBO_HOME` | all four Compose files | Kōbō state at `/root/.config/kobo`, inside a named volume; survives `docker compose down` without `-v`. The VPS example persists all of `/root`. |
|
|
1196
|
+
| `KOBO_NETWORK_ACCESS_ENABLED` | all four | Binds Kōbō to `0.0.0.0` inside the container at boot — required, since a Docker-forwarded or Traefik-proxied connection never looks like true loopback from Kōbō's point of view, even locally. Without it the container's `127.0.0.1`-only default blocks every external route. |
|
|
1197
|
+
| `KOBO_NETWORK_ACCESS_BEHIND_PROXY` | `local-traefik.yml`, `example.yml`, `vps.yml` | Disables the loopback-trust bypass entirely — needed whenever a reverse proxy sits in front, since every request now looks like it comes from the proxy. Not set in `local.yml`, which publishes Kōbō's port directly with no proxy in between. |
|
|
1198
|
+
| `GH_TOKEN` / `GITLAB_TOKEN` | `example.yml` (bring your own via `.env`) | Optional non-interactive auth for `gh`/`glab` inside the container. A CLI browser/device flow can also be completed from your PC. Expiring GitHub App tokens need a [renewable helper](./docs/deployment-vps.md#github-app-bot-authentication), not a static token in `.env`. |
|
|
1199
|
+
| `KOBO_PROJECTS_DIR` | Compose interpolation on the host | Original three: source for `/projects`, default `./kobo-projects`. VPS: required existing absolute directory, mounted at the **same path** in the container for host-Docker bind mounts. |
|
|
1200
|
+
| `KOBO_DOMAIN` | `vps.yml`, Compose interpolation | Public hostname used in the Traefik rule and `KOBO_NETWORK_ACCESS_PROXY_HOST`; required, without `https://`. |
|
|
1201
|
+
| `TRAEFIK_NETWORK` / `TRAEFIK_ENTRYPOINT` / `TRAEFIK_CERTRESOLVER` | `vps.yml`, Compose interpolation | Existing Traefik names; defaults `web` / `websecure` / `letsencrypt`. Adapt to your proxy. |
|
|
1150
1202
|
|
|
1151
1203
|
Both `KOBO_NETWORK_ACCESS_ENABLED` and `KOBO_NETWORK_ACCESS_BEHIND_PROXY` are read once at boot —
|
|
1152
1204
|
this is what lets the container come up fully configured with no manual Settings-UI step (there's
|
|
@@ -1157,14 +1209,15 @@ retrieved once — see [Token / login flow](#token--login-flow).
|
|
|
1157
1209
|
|
|
1158
1210
|
| Mount | RO/RW | Purpose |
|
|
1159
1211
|
|---|---|---|
|
|
1212
|
+
| `kobo-home:/root` (`vps.yml`, named volume) | RW | Independent Kōbō, Claude/Codex, Git and forge state. Authenticate inside the container; no PC credential files are required. |
|
|
1160
1213
|
| `<name>-data:/root/.config/kobo` (named volume) | RW | Kōbō's own state — SQLite DB, `settings.json`, etc. Named (not bind-mounted) so it survives `docker compose down` without `-v`, and so it can be deliberately **shared** across compose files by reusing the same volume name (see the two local files, both `kobo-test-data`). |
|
|
1161
|
-
| `${KOBO_PROJECTS_DIR:-./kobo-projects}:/projects` | RW |
|
|
1214
|
+
| `${KOBO_PROJECTS_DIR:-./kobo-projects}:/projects` | RW | Your project repositories. Ensure the configured worktree directory is also persistent. For project Docker bind mounts, use the VPS example’s identical host/container paths; see the [path setup](./docs/deployment-vps.md#optional-project-docker-environments). |
|
|
1162
1215
|
| `${HOME}/.ssh:/root/.ssh` | RO | Git SSH auth — needed to push/pull over SSH remotes. |
|
|
1163
1216
|
| `${HOME}/.gitconfig:/root/.gitconfig` | RO | Commit author identity. Without it, agent-authored commits fail with "please tell me who you are". |
|
|
1164
1217
|
| `${HOME}/.claude.json:/root/.claude.json` | RW | Claude Code auth + MCP server registrations. **Must already exist as a file on the host** (run `claude /login` locally first if it doesn't) — Docker silently creates an empty *directory* instead of erroring on a missing bind-mount source, which breaks auth in a confusing way. |
|
|
1165
1218
|
| `${HOME}/.claude:/root/.claude` | RW | Claude Code's full state directory (skills/plugins cache, session transcripts, memory) — Claude Code writes into this tree during normal operation. |
|
|
1166
1219
|
| `${HOME}/.codex:/root/.codex` | RW | Codex's full state directory (`auth.json`, `config.toml`). Harmless to mount even if you only use Claude Code. |
|
|
1167
|
-
| `/var/run/docker.sock:/var/run/docker.sock` | RW, `example.yml`
|
|
1220
|
+
| `/var/run/docker.sock:/var/run/docker.sock` | RW, enabled in `example.yml`, opt-in in `vps.yml` | Lets the dev-server panel start/stop/tail logs for your projects' own `docker compose` stacks. **DANGER**: grants the container root-equivalent control over the host — anyone who can run a command inside `kobo` can spawn a privileged container that mounts the host filesystem. Remove this line if you don't need the dev-server panel. |
|
|
1168
1221
|
|
|
1169
1222
|
### Ports
|
|
1170
1223
|
|
|
@@ -1175,12 +1228,12 @@ retrieved once — see [Token / login flow](#token--login-flow).
|
|
|
1175
1228
|
| `443` | `example.yml` | Traefik's TLS entrypoint (Let's Encrypt via the `le` cert resolver), routes your real domain. |
|
|
1176
1229
|
| `2222 → 22` (published) | `example.yml` only | SSH into the container (`ssh -p 2222 root@<host>`), key-based auth only via the same mounted `~/.ssh`, no password login. The one exception to "no published ports" — Traefik proxies HTTP/WS, not raw TCP, so SSH needs its own path. Rebuilding the image regenerates the SSH host keys, so expect a one-time "host key changed" warning from your SSH client after a rebuild. |
|
|
1177
1230
|
|
|
1178
|
-
Kōbō itself is **never** published directly in the
|
|
1231
|
+
Kōbō itself is **never** published directly in the three Traefik-fronted files — only Traefik is
|
|
1179
1232
|
reachable, matching the real production posture.
|
|
1180
1233
|
|
|
1181
1234
|
### Token / login flow
|
|
1182
1235
|
|
|
1183
|
-
All
|
|
1236
|
+
All four files pre-enable network access via env vars, so there's no interactive Settings-UI step.
|
|
1184
1237
|
Retrieve the auto-generated token from the container's boot log, then bookmark the token-bearing URL:
|
|
1185
1238
|
|
|
1186
1239
|
```bash
|
|
@@ -1264,6 +1317,36 @@ Open `https://kobo.example.com/?token=<token>`. SSH access: `ssh -p 2222 root@<h
|
|
|
1264
1317
|
only). See [Ports](#ports) and [Volumes](#volumes) above for the full rationale on the Docker socket
|
|
1265
1318
|
and SSH tradeoffs before deploying this to a real machine.
|
|
1266
1319
|
|
|
1320
|
+
### VPS with existing Traefik
|
|
1321
|
+
|
|
1322
|
+
Use [`docker-compose.vps.yml`](./docker-compose.vps.yml) and the
|
|
1323
|
+
[step-by-step VPS guide](./docs/deployment-vps.md). This variant runs only Kōbō,
|
|
1324
|
+
keeps agent credentials in its own persistent home and joins an existing proxy
|
|
1325
|
+
network. Your browser's project picker refers to paths on the VPS/container,
|
|
1326
|
+
not your PC. The guide covers provider login, GitHub App bots, Git HTTPS helpers
|
|
1327
|
+
and the host/container path requirements for project Docker environments.
|
|
1328
|
+
|
|
1329
|
+
For a fresh stack, [`scripts/kobo-install`](./scripts/kobo-install) guides domain,
|
|
1330
|
+
project path, existing Traefik settings and optional GitHub App credentials.
|
|
1331
|
+
`--check` performs read-only checks; `--prepare` builds without starting. Its
|
|
1332
|
+
private manifest protects managed files from accidental replacement. GitHub App
|
|
1333
|
+
configuration stays in private host files with read-only container mounts, outside
|
|
1334
|
+
web settings. See the [guided installation](./docs/deployment-vps.md#guided-installation)
|
|
1335
|
+
and [manual bot configuration](./docs/deployment-vps.md#github-app-bot-authentication).
|
|
1336
|
+
|
|
1337
|
+
### Docker updates and backups
|
|
1338
|
+
|
|
1339
|
+
For the independent VPS layout, [`scripts/kobo-update`](./scripts/kobo-update)
|
|
1340
|
+
accepts a stable version or defaults to npm `latest`. It has `--check`, `--prepare`
|
|
1341
|
+
and `--directory` options. See [updater usage and recovery](./docs/deployment-vps.md#update-with-kobo-update).
|
|
1342
|
+
This is an operator-invoked script; the in-app update banner does not install releases.
|
|
1343
|
+
|
|
1344
|
+
A source-built image needs rebuilding for a new release; `docker compose pull`
|
|
1345
|
+
alone cannot update an image that only exists locally. Recreate the service
|
|
1346
|
+
with the same persistent volumes and credential mounts after backing up its
|
|
1347
|
+
state. Preserve repository/worktree data and project databases separately.
|
|
1348
|
+
An old image alone is not a complete rollback after database migrations.
|
|
1349
|
+
|
|
1267
1350
|
### Troubleshooting
|
|
1268
1351
|
|
|
1269
1352
|
- **`fatal: detected dubious ownership in repository at '/projects/<name>'`** — only happens if you
|
|
@@ -2042,11 +2125,19 @@ for the same reason the API refuses the change. A change returns HTTP 409 while
|
|
|
2042
2125
|
|
|
2043
2126
|
Fresh defaults are manual. Existing settings/workspaces migrate to the previous automatic behavior for compatibility. Manual requires an explicit user request for that action; automatic supplies the workflow preference for the mission. Narrower user instructions always win. Publish means PR/MR creation, description updates and comments; merging needs separate authorization. Explicit Git-panel actions remain available. These preferences are agent instructions, not a shell-command filter or an OS sandbox.
|
|
2044
2127
|
|
|
2045
|
-
Plan is never promoted to Bypass by auto-loop preparation, an agent tool event, or loop enablement.
|
|
2128
|
+
Plan is never promoted to Bypass by auto-loop preparation, an agent tool event, or loop enablement. The initial Plan session provides its plan in the conversation without saving files or seeding tasks. Autonomous task preparation, execution and finalization block with an actionable message until an execution mode is explicitly selected.
|
|
2046
2129
|
|
|
2047
2130
|
Notion token environment overrides are applied consistently to both token variables passed to the child process. Explicit `OPENAPI_MCP_HEADERS` remain authoritative for compatibility and are not replaced by the resolved token. Direct integration configuration and legacy fallback are only read when an integration is used; opening Settings does not start a Notion users lookup. Connection tests and users refresh are explicit actions.
|
|
2048
2131
|
|
|
2049
2132
|
|
|
2133
|
+
### Initial Kōbō instructions
|
|
2134
|
+
|
|
2135
|
+
New workspaces receive the mission, repository context, current permissions, current phase and expected result. Agents first consult the available managed MCP tool descriptions and schemas, then prefer relevant Kōbō tools for workspace operations. This is not a request to call every tool or poll. Long tasks and delegated work use labeled progress bars; dismissing a bar hides only that activity and does not cancel its work.
|
|
2136
|
+
|
|
2137
|
+
Plan launches remain conversation-only. Writable auto-loop launches prepare the plan and task list before returning control to the loop; writable manual launches implement after plan approval, under the configured Git policy. Custom brainstorming, Notion and Sentry templates are preserved; they cannot expand launch permissions or authorize commits automatically. Review returns and handoff reports remain read-only, with only their scoped report and operational progress tools allowed. Plan approval does not change permissions; explicitly select an execution mode in Kōbō and start a new launch to implement.
|
|
2138
|
+
|
|
2139
|
+
The expandable **Kōbō instructions** chat entry records the application-owned text prepared by the engine builder for the initial launch or a pending initial-prompt retry, including progress guidance, continuation rules, workflow policy and managed integration notices. The pending initial mission is retained until this entry is durably recorded, so a failure during asynchronous launch preparation remains retryable. A later replacement mission is never cleared by an earlier launch. Preparation is not proof of provider delivery. The provider's own system preset is not included. Retrieved memory bodies and capability tokens are not copied to chat; memory usage remains visible separately in the Memory panel. Existing historical prompt entries retain their original content. Ordinary resumes receive current instructions without creating another initial-prompt entry.
|
|
2140
|
+
|
|
2050
2141
|
### Managed integration MCPs in agent sessions
|
|
2051
2142
|
|
|
2052
2143
|
**Test connection** uses the saved direct configuration when present, otherwise the
|
package/README.md
CHANGED
|
@@ -24,6 +24,8 @@ Kōbō (工房, "workshop") turns *one agent, one terminal* into a real workflow
|
|
|
24
24
|
|
|
25
25
|
Use [group messages](CONFIGURATION.md#group-workspace-messages) to send one instruction to selected workspaces, filtered by tags and status, from the interface or MCP. Auto-loops receive it on their next iteration; each recipient has a durable delivery result.
|
|
26
26
|
|
|
27
|
+
[Session progress bars](CONFIGURATION.md#session-progress-bars) show labelled long-running activities above the message input, including work delegated to subagents. Agents report progress through internal or external MCP; you can dismiss an individual bar without stopping its work.
|
|
28
|
+
|
|
27
29
|
## Quick start
|
|
28
30
|
|
|
29
31
|
Requires Node.js ≥ 24.15, Git, Bash and your own Claude Code **or** Codex authentication. No skill plugin or ticket integration is required. Kōbō is a local, single-user tool; each user installs their own instance.
|
|
@@ -116,7 +118,9 @@ for credential priority and native-configuration scope.
|
|
|
116
118
|
|
|
117
119
|
### Docker
|
|
118
120
|
|
|
119
|
-
An official `Dockerfile` and
|
|
121
|
+
An official `Dockerfile` and four Compose examples ship in this repository: a local test stack, a local Traefik rehearsal, a deployment including Traefik, and a fresh VPS instance behind an existing Traefik.
|
|
122
|
+
|
|
123
|
+
**Working remotely on your own VPS?** The [VPS deployment guide](./docs/deployment-vps.md) includes a guided `kobo-install` installer, optional renewable GitHub App authentication, persistent agent logins and Docker updates. Your browser runs on your PC; repositories and agents run on the VPS. See [`CONFIGURATION.md`](./CONFIGURATION.md#docker-deployment) for the Compose comparison and shared settings.
|
|
120
124
|
|
|
121
125
|
### Network access
|
|
122
126
|
|
|
@@ -164,4 +168,4 @@ GPL-3.0-or-later. See [`LICENSE`](./LICENSE).
|
|
|
164
168
|
|
|
165
169
|
Report reproducible bugs and feature requests in [GitHub Issues](https://github.com/loicngr/Kobo/issues). Read [Contributing](./CONTRIBUTING.md) and the [Code of conduct](./CODE_OF_CONDUCT.md) before participating. Vulnerabilities belong in the private channel described in [Security](./SECURITY.md), not public issues. Support is maintained on a best-effort basis; no response-time commitment is implied.
|
|
166
170
|
|
|
167
|
-
|
|
171
|
+
Linux is locally exercised; macOS CI, WSL and real-provider beta sessions require their own evidence. See [third-party notices](./THIRD_PARTY_NOTICES.md) for redistributed assets.
|
|
@@ -4,12 +4,14 @@ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js'
|
|
|
4
4
|
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
5
5
|
import { getDb } from '../server/db/index.js';
|
|
6
6
|
import { EXTERNAL_MEMORY_TOOL_DEFINITIONS, isMemoryToolName, MEMORY_TOOL_DEFINITIONS } from '../shared/memory-tools.js';
|
|
7
|
+
import { INTERNAL_PROGRESS_BAR_TOOLS, isProgressBarTool, PROGRESS_BAR_TOOLS } from '../shared/progress-bar-tools.js';
|
|
7
8
|
import { isWorkspaceCreationTool, MAX_MCP_CREATION_REQUEST_BYTES, WORKSPACE_CREATION_TOOLS, } from '../shared/workspace-creation-tools.js';
|
|
8
9
|
import { WORKSPACE_DIALOGUE_TOOLS } from '../shared/workspace-dialogue-tools.js';
|
|
9
10
|
import { isWorkspaceGroupMessageTool, WORKSPACE_GROUP_MESSAGE_TOOLS } from '../shared/workspace-group-message-tools.js';
|
|
10
11
|
import { isWorkspaceLifecycleTool, WORKSPACE_LIFECYCLE_TOOLS } from '../shared/workspace-lifecycle-tools.js';
|
|
11
12
|
import { createTaskHandler, cronListHandler, deleteTaskHandler, getDevServerStatusHandler, getSessionUsageHandler, getSettingsHandler, getTicketSourcesHandler, getWorkspaceInfoHandler, listDocumentsHandler, listTasksHandler, listWorkspaceImagesHandler, listWorkspacesHandler, logThoughtHandler, markAutoLoopReadyHandler, markTaskDoneHandler, readDocumentHandler, readWorkspaceEventsCsvHandler, setWorkspaceAgentDescriptionHandler, updateTaskHandler, } from './kobo-tasks-handlers.js';
|
|
12
13
|
import { callMemoryTool, isMemoryOutputSuppressed } from './memory-client.js';
|
|
14
|
+
import { callProgressBarTool } from './progress-bar-client.js';
|
|
13
15
|
import { callWorkspaceDialogueTool } from './workspace-dialogue-client.js';
|
|
14
16
|
const finalReviewToken = process.env.KOBO_FINAL_REVIEW_TOKEN;
|
|
15
17
|
const finalReviewSessionId = process.env.KOBO_FINAL_REVIEW_SESSION_ID;
|
|
@@ -213,7 +215,7 @@ const WORKSPACE_SCOPED_TOOLS = [
|
|
|
213
215
|
},
|
|
214
216
|
{
|
|
215
217
|
name: 'mark_auto_loop_ready',
|
|
216
|
-
description: 'CALL
|
|
218
|
+
description: 'CALL at the end of authorized auto-loop preparation, either during initial workspace creation with auto-loop or a later `/kobo-prep-autoloop` grooming session. First ensure tasks are atomic, implementable, and include the required verification/finalization work. Marks preparation ready; this is a mutation and cannot be called from a read-only launch. Do NOT call during unrelated normal sessions.',
|
|
217
219
|
inputSchema: { type: 'object', properties: {}, required: [] },
|
|
218
220
|
annotations: { destructiveHint: false, openWorldHint: false },
|
|
219
221
|
},
|
|
@@ -328,7 +330,7 @@ const WORKSPACE_SCOPED_TOOLS = [
|
|
|
328
330
|
},
|
|
329
331
|
{
|
|
330
332
|
name: 'cron_create',
|
|
331
|
-
description: 'Schedule a recurring trigger on THIS workspace. At each fire, Kōbō
|
|
333
|
+
description: 'Schedule a recurring trigger on THIS workspace. At each fire, Kōbō checks that the workspace is idle (no active session), then injects `prompt` into the conversation pinned when scheduled (`mode=resume`) or starts a new session (`mode=fresh`). Skip-if-active: if a session is already running when the timer fires, that occurrence is skipped, the next occurrence is computed, and the cron continues. The cron persists across server restarts (skip-missed semantics on boot — no catchup spam). Delete with `cron_delete(id)`. Multiple crons per workspace are allowed.',
|
|
332
334
|
inputSchema: {
|
|
333
335
|
type: 'object',
|
|
334
336
|
properties: {
|
|
@@ -538,7 +540,7 @@ const WORKSPACE_SCOPED_TOOLS = [
|
|
|
538
540
|
},
|
|
539
541
|
{
|
|
540
542
|
name: 'schedule_wakeup',
|
|
541
|
-
description: 'WHEN:
|
|
543
|
+
description: 'WHEN: the parent agent needs a durable later check for detached work or external state without a tracked completion notification. Do not duplicate SDK tracked-job continuation or schedule merely to advance auto-loop; subagents must leave the one workspace wakeup to their parent. Delay is measured from this call and clamped to [60, 21600] seconds. The wakeup targets this workspace and the session selected at scheduling time, not whichever session is newest later. It is deferred while busy when it cannot be delivered to the waiting controller; active auto-loop receives it as a queued instruction. Replaces the existing pending wakeup on this workspace, so preserve unrelated scheduled intent. Supply a concrete follow-up prompt and optional reason. End the current turn normally; delivery timing also depends on workspace availability. Prefer this durable Kōbō tool over native ScheduleWakeup',
|
|
542
544
|
inputSchema: {
|
|
543
545
|
type: 'object',
|
|
544
546
|
properties: {
|
|
@@ -566,6 +568,7 @@ const WORKSPACE_SCOPED_TOOLS = [
|
|
|
566
568
|
annotations: { destructiveHint: false, openWorldHint: false },
|
|
567
569
|
},
|
|
568
570
|
...MEMORY_TOOL_DEFINITIONS,
|
|
571
|
+
...INTERNAL_PROGRESS_BAR_TOOLS,
|
|
569
572
|
];
|
|
570
573
|
const GLOBAL_TOOLS = [
|
|
571
574
|
...WORKSPACE_DIALOGUE_TOOLS,
|
|
@@ -573,6 +576,7 @@ const GLOBAL_TOOLS = [
|
|
|
573
576
|
...WORKSPACE_LIFECYCLE_TOOLS,
|
|
574
577
|
...WORKSPACE_GROUP_MESSAGE_TOOLS,
|
|
575
578
|
...EXTERNAL_MEMORY_TOOL_DEFINITIONS,
|
|
579
|
+
...PROGRESS_BAR_TOOLS,
|
|
576
580
|
{
|
|
577
581
|
name: 'list_workspaces',
|
|
578
582
|
description: 'List Kōbō workspaces with their id, title, status, tags, and creation date. Set tag to return only workspaces carrying that exact tag. Works even when the Kōbō backend server is not running (reads the database directly). Use this to discover existing workspaces before creating one or targeting one with archive_workspace/stop_workspace.',
|
|
@@ -617,12 +621,19 @@ function availableTools() {
|
|
|
617
621
|
// A workspace process exposes the capability-bound memory tools exactly once.
|
|
618
622
|
// Unbound/global stdio exposes the external bridge variant instead.
|
|
619
623
|
const tools = workspaceId
|
|
620
|
-
? [
|
|
624
|
+
? [
|
|
625
|
+
...WORKSPACE_SCOPED_TOOLS,
|
|
626
|
+
...GLOBAL_TOOLS.filter((tool) => !isMemoryToolName(tool.name) && !isProgressBarTool(tool.name)),
|
|
627
|
+
]
|
|
621
628
|
: GLOBAL_TOOLS;
|
|
622
629
|
return tools.filter((tool) => handoffId && handoffToken
|
|
623
|
-
? tool.name === 'submit_session_handoff' ||
|
|
630
|
+
? tool.name === 'submit_session_handoff' ||
|
|
631
|
+
tool.annotations?.readOnlyHint === true ||
|
|
632
|
+
(isProgressBarTool(tool.name) && !!process.env.KOBO_PROGRESS_SESSION_TOKEN)
|
|
624
633
|
: finalReviewToken && finalReviewSessionId
|
|
625
|
-
? tool.name === 'submit_final_review' ||
|
|
634
|
+
? tool.name === 'submit_final_review' ||
|
|
635
|
+
tool.annotations?.readOnlyHint === true ||
|
|
636
|
+
(isProgressBarTool(tool.name) && !!process.env.KOBO_PROGRESS_SESSION_TOKEN)
|
|
626
637
|
: tool.name !== 'submit_session_handoff' && tool.name !== 'submit_final_review');
|
|
627
638
|
}
|
|
628
639
|
server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: availableTools() }));
|
|
@@ -676,6 +687,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
676
687
|
report: a.report,
|
|
677
688
|
}));
|
|
678
689
|
}
|
|
690
|
+
if (isProgressBarTool(name)) {
|
|
691
|
+
if (!workspaceId)
|
|
692
|
+
return await callWorkspaceDialogueTool(backendUrl, name, a, process.env.KOBO_NETWORK_TOKEN, process.env.KOBO_MCP_CLIENT_NAME ?? server.getClientVersion()?.name);
|
|
693
|
+
return await callProgressBarTool({
|
|
694
|
+
backendUrl,
|
|
695
|
+
name,
|
|
696
|
+
args: a,
|
|
697
|
+
capability: process.env.KOBO_PROGRESS_SESSION_TOKEN,
|
|
698
|
+
networkToken: process.env.KOBO_NETWORK_TOKEN,
|
|
699
|
+
});
|
|
700
|
+
}
|
|
679
701
|
if (isMemoryToolName(name)) {
|
|
680
702
|
if (!workspaceId) {
|
|
681
703
|
return await callWorkspaceDialogueTool(backendUrl, name, a, process.env.KOBO_NETWORK_TOKEN, process.env.KOBO_MCP_CLIENT_NAME ?? server.getClientVersion()?.name);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { isProgressBarTool } from '../shared/progress-bar-tools.js';
|
|
2
|
+
export async function callProgressBarTool(input) {
|
|
3
|
+
if (!isProgressBarTool(input.name))
|
|
4
|
+
throw new TypeError('Unknown progress tool');
|
|
5
|
+
if (!input.capability)
|
|
6
|
+
throw new Error('Progress capability is unavailable for this process');
|
|
7
|
+
const headers = {
|
|
8
|
+
'Content-Type': 'application/json',
|
|
9
|
+
'X-Kobo-Progress-Session': input.capability,
|
|
10
|
+
};
|
|
11
|
+
if (input.networkToken)
|
|
12
|
+
headers['X-Kobo-Token'] = input.networkToken;
|
|
13
|
+
const response = await (input.fetcher ?? fetch)(`${input.backendUrl.replace(/\/$/, '')}/api/progress-bars/agent/${input.name}`, { method: 'POST', headers, body: JSON.stringify(input.args), signal: AbortSignal.timeout(30_000) });
|
|
14
|
+
const data = (await response.json());
|
|
15
|
+
return {
|
|
16
|
+
content: [{ type: 'text', text: JSON.stringify(data) }],
|
|
17
|
+
structuredContent: data,
|
|
18
|
+
...(!response.ok ? { isError: true } : {}),
|
|
19
|
+
};
|
|
20
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
2
|
import { StreamableHTTPClientTransport } from '@modelcontextprotocol/sdk/client/streamableHttp.js';
|
|
3
3
|
import { isMemoryToolName, validateMemoryToolArguments } from '../shared/memory-tools.js';
|
|
4
|
+
import { isProgressBarTool, validateProgressBarArguments } from '../shared/progress-bar-tools.js';
|
|
4
5
|
import { isWorkspaceCreationTool, validateWorkspaceCreationArguments } from '../shared/workspace-creation-tools.js';
|
|
5
6
|
import { validateDialogueArguments } from '../shared/workspace-dialogue-tools.js';
|
|
6
7
|
import { isWorkspaceGroupMessageTool, validateWorkspaceGroupMessageArguments, } from '../shared/workspace-group-message-tools.js';
|
|
@@ -8,15 +9,34 @@ import { isWorkspaceLifecycleTool, validateWorkspaceLifecycleArguments } from '.
|
|
|
8
9
|
import { normalizeClientName } from '../shared/workspace-message-types.js';
|
|
9
10
|
/** Stateless HTTP bridge: external stdio clients never own agent runtime state. */
|
|
10
11
|
export async function callWorkspaceDialogueTool(backendUrl, name, args, token, clientName) {
|
|
12
|
+
if (isProgressBarTool(name)) {
|
|
13
|
+
try {
|
|
14
|
+
validateProgressBarArguments(name, args, true);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
const data = {
|
|
18
|
+
error: error instanceof Error ? error.message : 'Invalid arguments',
|
|
19
|
+
status: 400,
|
|
20
|
+
code: 'invalid_arguments',
|
|
21
|
+
};
|
|
22
|
+
return {
|
|
23
|
+
isError: true,
|
|
24
|
+
content: [{ type: 'text', text: JSON.stringify(data) }],
|
|
25
|
+
structuredContent: data,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
11
29
|
const arguments_ = isMemoryToolName(name)
|
|
12
30
|
? validateMemoryToolArguments(name, args, true)
|
|
13
|
-
:
|
|
14
|
-
?
|
|
15
|
-
:
|
|
16
|
-
?
|
|
17
|
-
:
|
|
18
|
-
?
|
|
19
|
-
:
|
|
31
|
+
: isProgressBarTool(name)
|
|
32
|
+
? args
|
|
33
|
+
: isWorkspaceCreationTool(name)
|
|
34
|
+
? validateWorkspaceCreationArguments(name, args)
|
|
35
|
+
: isWorkspaceLifecycleTool(name)
|
|
36
|
+
? validateWorkspaceLifecycleArguments(name, args)
|
|
37
|
+
: isWorkspaceGroupMessageTool(name)
|
|
38
|
+
? validateWorkspaceGroupMessageArguments(name, args)
|
|
39
|
+
: validateDialogueArguments(name, args);
|
|
20
40
|
const client = new Client({ name: 'kobo-stdio-bridge', version: '1.0.0' });
|
|
21
41
|
// Creation can include forge reads, worktree setup and user setup scripts.
|
|
22
42
|
// A timed-out creation is ambiguous and must never be retried automatically.
|
|
@@ -2,6 +2,7 @@ import { initAutoLoopFinalReviewSchema } from './auto-loop-final-review-schema.j
|
|
|
2
2
|
import { initAutoLoopSchema } from './auto-loop-schema.js';
|
|
3
3
|
import { initMcpMessageSchema } from './mcp-message-schema.js';
|
|
4
4
|
import { migrateMemorySchema } from './memory-schema.js';
|
|
5
|
+
import { initProgressBarSchema } from './progress-bar-schema.js';
|
|
5
6
|
import { initReviewReturnSchema, migrateDurableReviewReturns } from './review-return-schema.js';
|
|
6
7
|
import { initSchema } from './schema.js';
|
|
7
8
|
import { initSearchSchema } from './search-schema.js';
|
|
@@ -810,6 +811,7 @@ export const migrations = [
|
|
|
810
811
|
},
|
|
811
812
|
},
|
|
812
813
|
{ version: 53, name: 'workspace-group-message-receipts', migrate: initWorkspaceMessageBatchSchema },
|
|
814
|
+
{ version: 54, name: 'session-progress-bars', migrate: initProgressBarSchema },
|
|
813
815
|
];
|
|
814
816
|
/** Current schema version — always equals the highest migration version. */
|
|
815
817
|
export const SCHEMA_VERSION = migrations.length > 0 ? migrations[migrations.length - 1].version : 1;
|