@loicngr/kobo 2.1.28 → 2.1.30
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 +60 -11
- package/CHANGELOG.md +20 -1
- package/CONFIGURATION.md +140 -35
- package/CONTRIBUTING.md +2 -2
- package/DESIGN.md +1 -1
- package/README.md +12 -9
- package/SECURITY.md +7 -2
- package/dist/server/db/memory-schema.js +5 -5
- package/dist/server/db/migrations.js +2 -0
- package/dist/server/db/mistral-memory-migration.js +40 -0
- package/dist/server/routes/engines.js +14 -0
- package/dist/server/routes/environment.js +1 -1
- package/dist/server/routes/health.js +14 -3
- package/dist/server/routes/settings.js +7 -1
- package/dist/server/routes/workspaces.js +116 -9
- package/dist/server/services/agent/engines/claude-code/capabilities.js +2 -0
- package/dist/server/services/agent/engines/claude-code/engine.js +3 -0
- package/dist/server/services/agent/engines/claude-code/resolve-binary.js +1 -1
- package/dist/server/services/agent/engines/codex/capabilities.js +2 -0
- package/dist/server/services/agent/engines/codex/engine.js +3 -0
- package/dist/server/services/agent/engines/configuration.js +14 -0
- package/dist/server/services/agent/engines/mistral-vibe/capabilities.js +13 -0
- package/dist/server/services/agent/engines/mistral-vibe/client.js +64 -0
- package/dist/server/services/agent/engines/mistral-vibe/configuration.js +76 -0
- package/dist/server/services/agent/engines/mistral-vibe/engine.js +361 -0
- package/dist/server/services/agent/engines/mistral-vibe/event-mapper.js +297 -0
- package/dist/server/services/agent/engines/mistral-vibe/options-builder.js +35 -0
- package/dist/server/services/agent/engines/mistral-vibe/server-requests.js +278 -0
- package/dist/server/services/agent/engines/mistral-vibe/spawn.js +176 -0
- package/dist/server/services/agent/engines/registry.js +2 -0
- package/dist/server/services/agent/engines/types.js +6 -0
- package/dist/server/services/agent/orchestrator.js +88 -25
- package/dist/server/services/agent/session-controller.js +5 -0
- package/dist/server/services/auto-loop-final-review-service.js +10 -3
- package/dist/server/services/dev-server-service.js +68 -4
- package/dist/server/services/environment-check-service.js +9 -3
- package/dist/server/services/memory-service.js +1 -1
- package/dist/server/services/mistral-options-service.js +145 -0
- package/dist/server/services/pr-watcher-service.js +40 -11
- package/dist/server/services/review-service.js +33 -9
- package/dist/server/services/session-handoff-service.js +28 -2
- package/dist/server/services/settings-defaults.js +1 -0
- package/dist/server/services/settings-service.js +19 -1
- package/dist/server/services/workspace-creation-mcp-service.js +50 -8
- package/dist/server/services/workspace-dialogue-service.js +2 -0
- package/dist/server/services/workspace-message-service.js +19 -1
- package/dist/server/services/workspace-permission-policy-service.js +24 -0
- package/dist/server/utils/bounded-process.js +1 -1
- package/dist/shared/launch-instructions.js +18 -7
- package/dist/shared/memory.js +1 -1
- package/dist/shared/mistral-models.js +9 -0
- package/dist/shared/mistral-options.js +1 -0
- package/dist/shared/question-selections.js +16 -0
- package/dist/shared/workspace-creation-tools.js +8 -2
- package/dist/shared/workspace-dialogue-tools.js +15 -4
- package/docs/deployment-vps.md +10 -3
- package/docs/getting-started.md +4 -3
- package/docs/troubleshooting.md +2 -2
- package/package.json +20 -14
- package/src/client/dist/pwa/assets/ActivityFeed-C5stmHXP.js +2 -0
- package/src/client/dist/pwa/assets/AutoLoopFinalReviewSettings-CIDSX32d.css +1 -0
- package/src/client/dist/pwa/assets/AutoLoopFinalReviewSettings-DG32W_0G.js +1 -0
- package/src/client/dist/pwa/assets/{ChangelogPage-CAAUEn5X.js → ChangelogPage-_vItY8vA.js} +1 -1
- package/src/client/dist/pwa/assets/{ClosePopup-CRV2hxHS.js → ClosePopup-rU8Bm-mC.js} +1 -1
- package/src/client/dist/pwa/assets/{ComparisonPanel-BCb7vB5E.js → ComparisonPanel-B3BMzQH0.js} +2 -2
- package/src/client/dist/pwa/assets/CreatePage-FlGrfmjX.js +2 -0
- package/src/client/dist/pwa/assets/CreatePage-oh8ihVC4.css +1 -0
- package/src/client/dist/pwa/assets/{DashboardPage-XE52EABP.js → DashboardPage-lJGwWQYQ.js} +1 -1
- package/src/client/dist/pwa/assets/DiffViewer-DIaQH3lA.js +8 -0
- package/src/client/dist/pwa/assets/{DocumentsPanel-L4pbQfz1.js → DocumentsPanel-Ct-nm4fX.js} +1 -1
- package/src/client/dist/pwa/assets/{DrawerToggleButton-DiOJm5he.js → DrawerToggleButton-M5qv4Io-.js} +1 -1
- package/src/client/dist/pwa/assets/GitPanel-BaHCgb3p.js +3 -0
- package/src/client/dist/pwa/assets/GitPanel-C8vw2qvW.css +1 -0
- package/src/client/dist/pwa/assets/HealthPage-DR3wa6iD.js +1 -0
- package/src/client/dist/pwa/assets/HealthPage-Dbn4J_DT.css +1 -0
- package/src/client/dist/pwa/assets/{MainLayout-DoAEgANU.css → MainLayout-CHi8qP1D.css} +1 -1
- package/src/client/dist/pwa/assets/MainLayout-WJabICsA.js +2 -0
- package/src/client/dist/pwa/assets/{MemoryPanel-DtEvh_b7.js → MemoryPanel-CRpWdfc0.js} +1 -1
- package/src/client/dist/pwa/assets/MemoryProposalList-DGz3lDbL.js +1 -0
- package/src/client/dist/pwa/assets/{QBadge-CW3Lw-kL.js → QBadge-DiwbRpte.js} +1 -1
- package/src/client/dist/pwa/assets/{QBanner-BT2ZemYu.js → QBanner-Cw89HSjk.js} +1 -1
- package/src/client/dist/pwa/assets/QBtn-kfhHFy7Q.js +1 -0
- package/src/client/dist/pwa/assets/{QBtnDropdown-CWPIugs8.js → QBtnDropdown-tt8rUNNR.js} +1 -1
- package/src/client/dist/pwa/assets/{QBtnGroup-CnM4vSJA.js → QBtnGroup-Bioxjp9q.js} +1 -1
- package/src/client/dist/pwa/assets/{QBtnToggle-DccOOtbh.js → QBtnToggle-Bod-x9im.js} +1 -1
- package/src/client/dist/pwa/assets/{QChip-Be16M4Ig.js → QChip-DvhtPv_L.js} +1 -1
- package/src/client/dist/pwa/assets/{QExpansionItem-D-EGL2b3.js → QExpansionItem-BkrI3UPL.js} +1 -1
- package/src/client/dist/pwa/assets/{QItemSection-MdJ1_ZK7.js → QItemSection-ahqRK4JF.js} +1 -1
- package/src/client/dist/pwa/assets/{QList-Cx1UfaUm.js → QList-CAUl0v66.js} +1 -1
- package/src/client/dist/pwa/assets/{QMarkupTable-UhP7fVUp.js → QMarkupTable-B4LLAly-.js} +1 -1
- package/src/client/dist/pwa/assets/{QPage-CqkGHokx.js → QPage-DIy_mRoT.js} +1 -1
- package/src/client/dist/pwa/assets/{QScrollArea-BMrqK-xd.js → QScrollArea-BvgnY-oA.js} +1 -1
- package/src/client/dist/pwa/assets/QSelect-BtZB1wrB.js +1 -0
- package/src/client/dist/pwa/assets/{QSpinnerDots-xdWyaE1i.js → QSpinnerDots-Bea6hAuJ.js} +1 -1
- package/src/client/dist/pwa/assets/{QTooltip-Bk8dLUtU.js → QTooltip-CDH6p745.js} +1 -1
- package/src/client/dist/pwa/assets/{SchedulePanel-CuxmxCKi.js → SchedulePanel-C2rWlh7l.js} +1 -1
- package/src/client/dist/pwa/assets/{SearchPage-DKnQPUqY.js → SearchPage-BFd4NQwJ.js} +1 -1
- package/src/client/dist/pwa/assets/{SettingsPage-B4rmd2WX.css → SettingsPage-Bm0TcarK.css} +1 -1
- package/src/client/dist/pwa/assets/SettingsPage-DDQCgnjL.js +9 -0
- package/src/client/dist/pwa/assets/{SplitWorkspacePage-WhQyX8fn.js → SplitWorkspacePage-DKCtOZO4.js} +1 -1
- package/src/client/dist/pwa/assets/TerminalPanel-BE_MSZF0.js +16 -0
- package/src/client/dist/pwa/assets/{ToolCallItem-DYubi-J0.js → ToolCallItem-BEYaOtgh.js} +4 -4
- package/src/client/dist/pwa/assets/{TouchPan-DDotyYLN.js → TouchPan-DeYoOjX5.js} +1 -1
- package/src/client/dist/pwa/assets/{TourReplayButton-kAnEMcy2.js → TourReplayButton-D5lMwIKt.js} +1 -1
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-BHEAsIoo.js +1 -0
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-v7ein__H.css +1 -0
- package/src/client/dist/pwa/assets/WorkspacePage-5_wsJPaJ.js +4 -0
- package/src/client/dist/pwa/assets/WorkspacePage-CtUXz0Cq.css +1 -0
- package/src/client/dist/pwa/assets/{browser-DVYLH8vl.js → browser-ogy_9LVv.js} +2 -2
- package/src/client/dist/pwa/assets/build-path-tree-CRXxaYkA.js +1 -0
- package/src/client/dist/pwa/assets/custom-sounds-iLTkCd_i.js +1 -0
- package/src/client/dist/pwa/assets/de-BqDU7iZH.js +17 -0
- package/src/client/dist/pwa/assets/detached-fullscreen-CHqMxB-8.js +1 -0
- package/src/client/dist/pwa/assets/dom-CRPVbmiy.js +2 -0
- package/src/client/dist/pwa/assets/ecl-94qehhXe.js +1 -0
- package/src/client/dist/pwa/assets/{editor.api-BC38eXAS.js → editor.api-Dx6TbfZG.js} +9 -9
- package/src/client/dist/pwa/assets/editor.worker-xrHNhPSq.js +33 -0
- package/src/client/dist/pwa/assets/efforts-DnJh2fW_.js +9 -0
- package/src/client/dist/pwa/assets/es-D4VMXQRk.js +17 -0
- package/src/client/dist/pwa/assets/expand-template-PUEVWny3.js +1 -0
- package/src/client/dist/pwa/assets/{format-OwxXBnDJ.js → format-yf9XM3dV.js} +48 -48
- package/src/client/dist/pwa/assets/{formatters-YgaCZcwJ.js → formatters-D0sXu9Oe.js} +1 -1
- package/src/client/dist/pwa/assets/fr-DIyaCFB3.js +17 -0
- package/src/client/dist/pwa/assets/{freemarker2-l7R42fI2.js → freemarker2-l_xIHxRf.js} +1 -1
- package/src/client/dist/pwa/assets/{handlebars-DFmPrgjH.js → handlebars-CYgq99yQ.js} +1 -1
- package/src/client/dist/pwa/assets/{html-CERIAlPM.js → html-C28GatN_.js} +1 -1
- package/src/client/dist/pwa/assets/i18n-2AmHIUy0.js +1 -0
- package/src/client/dist/pwa/assets/index-C0MApoXN.css +1 -0
- package/src/client/dist/pwa/assets/index-MMYMztJ_.js +20 -0
- package/src/client/dist/pwa/assets/it-CF6_4OS0.js +17 -0
- package/src/client/dist/pwa/assets/{javascript-BBYncplF.js → javascript-YCSueyyk.js} +1 -1
- package/src/client/dist/pwa/assets/{liquid-C1HqYyYU.js → liquid-CUBn90Gs.js} +1 -1
- package/src/client/dist/pwa/assets/{mdx-E74dsP22.js → mdx-C5WOHShJ.js} +1 -1
- package/src/client/dist/pwa/assets/monaco-contributions-DYwqbh7m.js +53 -0
- package/src/client/dist/pwa/assets/{monaco.contribution-DYdn9CwR.js → monaco.contribution-CoFzrPQl.js} +2 -2
- package/src/client/dist/pwa/assets/network-auth-BpJ6Noax.js +1 -0
- package/src/client/dist/pwa/assets/notify-theme-NPq4-Tup.js +1 -0
- package/src/client/dist/pwa/assets/permissionModes-Bbl901Hx.js +36 -0
- package/src/client/dist/pwa/assets/{private.use-form-DY1BkePL.js → private.use-form-BcspuzM9.js} +1 -1
- package/src/client/dist/pwa/assets/{project-color-_snXWYUp.js → project-color-gNyhKJlV.js} +1 -1
- package/src/client/dist/pwa/assets/{python-DNAAGBcX.js → python-lhKUZdPj.js} +1 -1
- package/src/client/dist/pwa/assets/{razor-CB3g5p_T.js → razor-Chi44rEL.js} +1 -1
- package/src/client/dist/pwa/assets/reactivity.esm-bundler-Dplx1ILy.js +1 -0
- package/src/client/dist/pwa/assets/render-chat-markdown-C9ihAYBt.js +67 -0
- package/src/client/dist/pwa/assets/runtime-core.esm-bundler-BAUgNzMK.js +1 -0
- package/src/client/dist/pwa/assets/{typescript-0kpz8bqP.js → typescript-CU2TXVm6.js} +1 -1
- package/src/client/dist/pwa/assets/{use-checkbox-v4aAbE6K.js → use-checkbox-DUxgXR4e.js} +1 -1
- package/src/client/dist/pwa/assets/{use-id-BrdYXce0.js → use-id-B7ieAx2m.js} +1 -1
- package/src/client/dist/pwa/assets/use-is-mobile-CHmaewI1.js +1 -0
- package/src/client/dist/pwa/assets/{use-search-index-status-D38yFOD_.js → use-search-index-status-CQ9S05G7.js} +1 -1
- package/src/client/dist/pwa/assets/use-slide-transition-BJh9xGMa.js +1 -0
- package/src/client/dist/pwa/assets/use-tours-BmrZbHjz.js +2 -0
- package/src/client/dist/pwa/assets/use-tours-CU5oA7cz.css +1 -0
- package/src/client/dist/pwa/assets/use-worktree-restore-DcucRlLh.js +1 -0
- package/src/client/dist/pwa/assets/{workspace-templates-D-lPJQ4G.js → workspace-templates-DaG42EEt.js} +1 -1
- package/src/client/dist/pwa/assets/{xml-BbOuqdUe.js → xml-CPO5LI6F.js} +1 -1
- package/src/client/dist/pwa/assets/{yaml-gasFQtfk.js → yaml-CoYs82jI.js} +1 -1
- package/src/client/dist/pwa/index.html +10 -10
- package/src/client/dist/pwa/sw.js +1 -1
- package/src/mcp-server/README.md +18 -6
- package/src/client/dist/pwa/assets/ActivityFeed-D58VS9o2.js +0 -2
- package/src/client/dist/pwa/assets/AutoLoopFinalReviewSettings-CK3r_fVB.js +0 -1
- package/src/client/dist/pwa/assets/AutoLoopFinalReviewSettings-Q-OlSQ1c.css +0 -1
- package/src/client/dist/pwa/assets/CreatePage-DasH1Uk4.js +0 -2
- package/src/client/dist/pwa/assets/CreatePage-DxOes_cF.css +0 -1
- package/src/client/dist/pwa/assets/DiffViewer-CncKlXne.js +0 -8
- package/src/client/dist/pwa/assets/GitPanel-WJlzy2VJ.js +0 -3
- package/src/client/dist/pwa/assets/GitPanel-yHvU38dp.css +0 -1
- package/src/client/dist/pwa/assets/HealthPage-Cnlhrn--.css +0 -1
- package/src/client/dist/pwa/assets/HealthPage-hJY5MurK.js +0 -1
- package/src/client/dist/pwa/assets/MainLayout-DgWElK7w.js +0 -2
- package/src/client/dist/pwa/assets/MemoryProposalList-kgFCm9zz.js +0 -1
- package/src/client/dist/pwa/assets/QBtn-BUSdPaf4.js +0 -1
- package/src/client/dist/pwa/assets/QSelect-DFWyDWCE.js +0 -1
- package/src/client/dist/pwa/assets/SettingsPage-CO3vIpPd.js +0 -9
- package/src/client/dist/pwa/assets/TerminalPanel-BY0lPq6k.js +0 -16
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-B9LE8HtU.css +0 -1
- package/src/client/dist/pwa/assets/WorkspaceAttentionLabels-DiYt3rP3.js +0 -1
- package/src/client/dist/pwa/assets/WorkspacePage-BEBwwr81.css +0 -1
- package/src/client/dist/pwa/assets/WorkspacePage-K-1ce50d.js +0 -4
- package/src/client/dist/pwa/assets/build-path-tree-DEuOdIIk.js +0 -1
- package/src/client/dist/pwa/assets/custom-sounds-Ggw6V9iF.js +0 -1
- package/src/client/dist/pwa/assets/de-Bk3zQrin.js +0 -17
- package/src/client/dist/pwa/assets/detached-fullscreen-Du3TcYdX.js +0 -1
- package/src/client/dist/pwa/assets/dom-BtYTvLeN.js +0 -2
- package/src/client/dist/pwa/assets/ecl-D05T4iGw.js +0 -1
- package/src/client/dist/pwa/assets/editor.worker-BLJF_oQx.js +0 -33
- package/src/client/dist/pwa/assets/efforts-TGacUPcJ.js +0 -9
- package/src/client/dist/pwa/assets/es-f3xuAWA9.js +0 -17
- package/src/client/dist/pwa/assets/expand-template-DM8gq3Mo.js +0 -1
- package/src/client/dist/pwa/assets/fr-B6c21SG3.js +0 -17
- package/src/client/dist/pwa/assets/i18n-WaE4cZK9.js +0 -1
- package/src/client/dist/pwa/assets/index-C8zAZ-k-.css +0 -1
- package/src/client/dist/pwa/assets/index-CpWBGKdM.js +0 -20
- package/src/client/dist/pwa/assets/it-DUstDpC2.js +0 -17
- package/src/client/dist/pwa/assets/monaco-contributions-DHvm-kp5.js +0 -53
- package/src/client/dist/pwa/assets/network-auth-DTZUKbny.js +0 -1
- package/src/client/dist/pwa/assets/notify-theme-FuTL7HuS.js +0 -1
- package/src/client/dist/pwa/assets/permissionModes-D-Nexnoo.js +0 -36
- package/src/client/dist/pwa/assets/reactivity.esm-bundler-DY1JkAEA.js +0 -1
- package/src/client/dist/pwa/assets/render-chat-markdown-CafzCcmu.js +0 -69
- package/src/client/dist/pwa/assets/runtime-core.esm-bundler-Bqg71Vll.js +0 -1
- package/src/client/dist/pwa/assets/use-is-mobile-CDB_rzM9.js +0 -1
- package/src/client/dist/pwa/assets/use-slide-transition-B_Nu6u-t.js +0 -1
- package/src/client/dist/pwa/assets/use-tours-BWkHp34X.js +0 -2
- package/src/client/dist/pwa/assets/use-tours-CTZuBZOi.css +0 -1
- package/src/client/dist/pwa/assets/use-worktree-restore-DUjZr44N.js +0 -1
|
@@ -1019,6 +1019,24 @@ const settingsMigrations = [
|
|
|
1019
1019
|
global.forceImmediateMessages = false;
|
|
1020
1020
|
},
|
|
1021
1021
|
},
|
|
1022
|
+
{
|
|
1023
|
+
version: 68,
|
|
1024
|
+
name: 'mistral-native-defaults',
|
|
1025
|
+
migrate: ({ global }) => {
|
|
1026
|
+
for (const [key, value] of [
|
|
1027
|
+
['defaultModelByEngine', 'auto'],
|
|
1028
|
+
['defaultPermissionModeByEngine', 'interactive'],
|
|
1029
|
+
]) {
|
|
1030
|
+
const map = global[key];
|
|
1031
|
+
// Missing maps inherit the full fresh-install defaults when settings are read.
|
|
1032
|
+
if (map && typeof map === 'object' && !Array.isArray(map)) {
|
|
1033
|
+
const defaults = map;
|
|
1034
|
+
if (typeof defaults['mistral-vibe'] !== 'string')
|
|
1035
|
+
defaults['mistral-vibe'] = value;
|
|
1036
|
+
}
|
|
1037
|
+
}
|
|
1038
|
+
},
|
|
1039
|
+
},
|
|
1022
1040
|
];
|
|
1023
1041
|
/** Current settings schema version — always equals the highest migration version. */
|
|
1024
1042
|
export const SETTINGS_SCHEMA_VERSION = settingsMigrations.length > 0 ? settingsMigrations[settingsMigrations.length - 1].version : 0;
|
|
@@ -1127,7 +1145,7 @@ function defaultSettings() {
|
|
|
1127
1145
|
notionInProgressStatus: '',
|
|
1128
1146
|
notionAssigneeProperty: '',
|
|
1129
1147
|
notionUserId: '',
|
|
1130
|
-
defaultPermissionModeByEngine: { 'claude-code': 'plan', codex: 'plan' },
|
|
1148
|
+
defaultPermissionModeByEngine: { 'claude-code': 'plan', codex: 'plan', 'mistral-vibe': 'interactive' },
|
|
1131
1149
|
notionMcpKey: '',
|
|
1132
1150
|
sentryMcpKey: '',
|
|
1133
1151
|
notionEnabled: false,
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
import { checkoutDecisionError, deriveSteps } from '../../shared/pr-checkout-steps.js';
|
|
2
2
|
import { validateWorkspaceCreationArguments } from '../../shared/workspace-creation-tools.js';
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
3
|
+
import { assertEngineConfigurationSupported } from './agent/engines/configuration.js';
|
|
4
|
+
import { resolveEngine } from './agent/engines/registry.js';
|
|
5
|
+
import { parseFinalReviewConfiguration } from './auto-loop-final-review-service.js';
|
|
6
|
+
import { preflightMistralConfiguration } from './mistral-options-service.js';
|
|
5
7
|
import { rollbackCreatedPrCheckout } from './pr-checkout-rollback-service.js';
|
|
8
|
+
import { getGlobalSettings } from './settings-service.js';
|
|
6
9
|
import { beginWorkspaceCreation } from './update-maintenance-service.js';
|
|
7
10
|
export class WorkspaceCreationMcpError extends Error {
|
|
8
11
|
status;
|
|
@@ -102,13 +105,52 @@ async function executeCreation(name, raw, dispatch) {
|
|
|
102
105
|
catch (error) {
|
|
103
106
|
throw new WorkspaceCreationMcpError(error instanceof Error ? error.message : 'Invalid arguments', 400, 'validate');
|
|
104
107
|
}
|
|
105
|
-
const config = input.auto_loop_final_review;
|
|
106
|
-
if (config) {
|
|
107
|
-
const capabilities = config.engine === 'codex' ? CODEX_CAPABILITIES : CLAUDE_CODE_CAPABILITIES;
|
|
108
|
-
if (!capabilities.effortLevels?.some((effort) => effort.id === config.reasoning_effort))
|
|
109
|
-
throw new WorkspaceCreationMcpError('Unsupported review reasoning effort', 400, 'validate');
|
|
110
|
-
}
|
|
111
108
|
const body = mapInput(input);
|
|
109
|
+
try {
|
|
110
|
+
if (name === 'create_workspace') {
|
|
111
|
+
const engine = resolveEngine(input.engine ?? 'claude-code');
|
|
112
|
+
const savedMode = engine.id === 'mistral-vibe' ? getGlobalSettings().defaultPermissionModeByEngine?.[engine.id] : undefined;
|
|
113
|
+
const defaultMode = savedMode === 'plan' || engine.capabilities.permissionModes.some((mode) => mode === savedMode)
|
|
114
|
+
? savedMode
|
|
115
|
+
: undefined;
|
|
116
|
+
if (engine.id === 'mistral-vibe')
|
|
117
|
+
body.agentPermissionMode = input.agent_permission_mode ?? defaultMode ?? 'interactive';
|
|
118
|
+
assertEngineConfigurationSupported(engine, {
|
|
119
|
+
model: input.model,
|
|
120
|
+
reasoningEffort: input.reasoning_effort,
|
|
121
|
+
agentPermissionMode: body.agentPermissionMode,
|
|
122
|
+
});
|
|
123
|
+
await preflightMistralConfiguration(engine.id, { projectPath: input.project_path }, {
|
|
124
|
+
model: input.model,
|
|
125
|
+
reasoningEffort: input.reasoning_effort,
|
|
126
|
+
agentPermissionMode: body.agentPermissionMode,
|
|
127
|
+
});
|
|
128
|
+
assertEngineConfigurationSupported(engine, {
|
|
129
|
+
model: input.brainstorm_model,
|
|
130
|
+
reasoningEffort: input.brainstorm_reasoning_effort,
|
|
131
|
+
});
|
|
132
|
+
await preflightMistralConfiguration(engine.id, { projectPath: input.project_path }, {
|
|
133
|
+
model: input.brainstorm_model ?? input.model,
|
|
134
|
+
reasoningEffort: input.brainstorm_reasoning_effort ?? input.reasoning_effort,
|
|
135
|
+
agentPermissionMode: body.agentPermissionMode,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
throw new WorkspaceCreationMcpError(error instanceof Error ? error.message : 'Invalid engine configuration', 400, 'validate');
|
|
141
|
+
}
|
|
142
|
+
if (body.autoLoopFinalReview) {
|
|
143
|
+
try {
|
|
144
|
+
const config = parseFinalReviewConfiguration(body.autoLoopFinalReview);
|
|
145
|
+
await preflightMistralConfiguration(config.engine, { projectPath: input.project_path }, {
|
|
146
|
+
...config,
|
|
147
|
+
agentPermissionMode: 'interactive',
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
catch (error) {
|
|
151
|
+
throw new WorkspaceCreationMcpError(error instanceof Error ? error.message : 'Invalid final review configuration', 400, 'validate');
|
|
152
|
+
}
|
|
153
|
+
}
|
|
112
154
|
let resolvedCheckout;
|
|
113
155
|
if (input.pr_url) {
|
|
114
156
|
const supplied = prIdentity(input.pr_url);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { nanoid } from 'nanoid';
|
|
2
|
+
import { parseQuestionSelections } from '../../shared/question-selections.js';
|
|
2
3
|
import { validateDialogueArguments } from '../../shared/workspace-dialogue-tools.js';
|
|
3
4
|
import { parseMessageSource } from '../../shared/workspace-message-types.js';
|
|
4
5
|
import { getDb } from '../db/index.js';
|
|
@@ -79,6 +80,7 @@ export async function executeWorkspaceDialogueTool(name, input, source = createM
|
|
|
79
80
|
throw new Error('The requested question is not the current pending question');
|
|
80
81
|
await answerPendingQuestion(workspaceId, args.answers, args.tool_call_id, {
|
|
81
82
|
source,
|
|
83
|
+
...(args.selections !== undefined ? { selections: parseQuestionSelections(args.selections) } : {}),
|
|
82
84
|
});
|
|
83
85
|
return { accepted: true };
|
|
84
86
|
}
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import { validateMcpAttachments } from '../../shared/mcp-attachments.js';
|
|
2
2
|
import { assertWorkspaceLifecycleAvailable, withWorkspaceLifecycleGuard } from '../utils/workspace-lifecycle-guard.js';
|
|
3
|
-
import {
|
|
3
|
+
import { assertEngineConfigurationSupported } from './agent/engines/configuration.js';
|
|
4
|
+
import { resolveEngine } from './agent/engines/registry.js';
|
|
5
|
+
import { assertImmediateMessageSupported, isAgentUnavailableError, isShuttingDown, sendMessage, startAgent, } from './agent/orchestrator.js';
|
|
4
6
|
import { attachmentReference, removeAttachments, saveAttachments } from './attachment-service.js';
|
|
5
7
|
import { hasLoopMessage } from './auto-loop-message-service.js';
|
|
6
8
|
import * as autoLoop from './auto-loop-service.js';
|
|
7
9
|
import { createChatReceipt } from './chat-receipt-service.js';
|
|
10
|
+
import { preflightMistralConfiguration } from './mistral-options-service.js';
|
|
8
11
|
import { emitEphemeral } from './websocket-service.js';
|
|
9
12
|
import { getActiveSession, getWorkspace, updateWorkspaceStatus } from './workspace-service.js';
|
|
10
13
|
/** Shared delivery for WebSocket chat and external MCP clients. */
|
|
@@ -67,6 +70,21 @@ export async function deliverWorkspaceMessage(workspaceId, message, hooks) {
|
|
|
67
70
|
reason = 'awaiting-user';
|
|
68
71
|
throw new Error('Answer the pending question or permission request before sending a chat message');
|
|
69
72
|
}
|
|
73
|
+
if (workspace.engine === 'mistral-vibe') {
|
|
74
|
+
assertEngineConfigurationSupported(resolveEngine(workspace.engine), {
|
|
75
|
+
model: workspace.model,
|
|
76
|
+
reasoningEffort: workspace.reasoningEffort,
|
|
77
|
+
agentPermissionMode: message.agentPermissionModeOverride ?? workspace.agentPermissionMode,
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
assertImmediateMessageSupported(workspaceId);
|
|
81
|
+
if (workspace.engine === 'mistral-vibe') {
|
|
82
|
+
await preflightMistralConfiguration(workspace.engine, { workspaceId }, {
|
|
83
|
+
model: workspace.model,
|
|
84
|
+
reasoningEffort: workspace.reasoningEffort,
|
|
85
|
+
agentPermissionMode: message.agentPermissionModeOverride ?? workspace.agentPermissionMode,
|
|
86
|
+
}, true);
|
|
87
|
+
}
|
|
70
88
|
if (attachments.length) {
|
|
71
89
|
attachmentWorktree = workspace.worktreePath;
|
|
72
90
|
await withWorkspaceLifecycleGuard(workspaceId, async () => {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { isAbsolute } from 'node:path';
|
|
2
3
|
import { nanoid } from 'nanoid';
|
|
3
4
|
import { getDb } from '../db/index.js';
|
|
4
5
|
const turnRules = new Map();
|
|
@@ -29,6 +30,26 @@ export function permissionFingerprint(payload) {
|
|
|
29
30
|
}
|
|
30
31
|
const CODEX_EDIT_FINGERPRINT_PREFIX = 'codex-edit-v2:';
|
|
31
32
|
function operationFingerprint(request) {
|
|
33
|
+
if (request.engine === 'mistral-vibe') {
|
|
34
|
+
const payload = request.payload;
|
|
35
|
+
const input = payload?.rawInput;
|
|
36
|
+
if (!input || typeof input !== 'object' || Array.isArray(input) || payload?.operationApprovalAvailable === false)
|
|
37
|
+
return null;
|
|
38
|
+
const shell = request.toolName === 'bash' &&
|
|
39
|
+
payload?.effectKind === 'shell' &&
|
|
40
|
+
payload.kind === 'execute' &&
|
|
41
|
+
typeof input.command === 'string' &&
|
|
42
|
+
input.command.trim().length > 0;
|
|
43
|
+
const write = request.toolName === 'write_file' &&
|
|
44
|
+
payload?.effectKind === 'file_write' &&
|
|
45
|
+
payload.kind === 'edit' &&
|
|
46
|
+
typeof input.filePath === 'string' &&
|
|
47
|
+
isAbsolute(input.filePath) &&
|
|
48
|
+
typeof input.content === 'string';
|
|
49
|
+
if (!shell && !write)
|
|
50
|
+
return null;
|
|
51
|
+
return `mistral-vibe-operation-v1:${permissionFingerprint({ rawInput: input, effectKind: payload?.effectKind, kind: payload?.kind })}`;
|
|
52
|
+
}
|
|
32
53
|
if (request.engine !== 'codex' || request.toolName !== 'Edit')
|
|
33
54
|
return permissionFingerprint(request.payload);
|
|
34
55
|
const payload = request.payload;
|
|
@@ -48,6 +69,9 @@ function operationFingerprint(request) {
|
|
|
48
69
|
grantRoot: payload.grantRoot ?? null,
|
|
49
70
|
}));
|
|
50
71
|
}
|
|
72
|
+
export function isOperationApprovalAvailable(request) {
|
|
73
|
+
return operationFingerprint(request) !== null;
|
|
74
|
+
}
|
|
51
75
|
function toRule(row) {
|
|
52
76
|
return {
|
|
53
77
|
active: !(row.scope === 'operation' &&
|
|
@@ -2,7 +2,7 @@ import { execFile, spawn } from 'node:child_process';
|
|
|
2
2
|
import { promisify } from 'node:util';
|
|
3
3
|
const execFileAsync = promisify(execFile);
|
|
4
4
|
/** A zombie cannot mutate a checkout, even before its parent reaps it. */
|
|
5
|
-
async function groupIsLive(pid) {
|
|
5
|
+
export async function groupIsLive(pid) {
|
|
6
6
|
try {
|
|
7
7
|
process.kill(-pid, 0);
|
|
8
8
|
}
|
|
@@ -5,20 +5,29 @@ export function getKoboPromptCapabilities(env) {
|
|
|
5
5
|
handoff: Boolean(env?.KOBO_HANDOFF_ID && env.KOBO_HANDOFF_TOKEN),
|
|
6
6
|
finalReview: Boolean(env?.KOBO_FINAL_REVIEW_SESSION_ID && env.KOBO_FINAL_REVIEW_TOKEN),
|
|
7
7
|
progressReporting: Boolean(env?.KOBO_PROGRESS_SESSION_TOKEN),
|
|
8
|
+
reviewOnly: env?.KOBO_REVIEW_ONLY === '1',
|
|
8
9
|
};
|
|
9
10
|
}
|
|
10
11
|
export function buildKoboLaunchInstructions(context) {
|
|
11
|
-
const restricted = context.readOnly || context.handoff || context.finalReview;
|
|
12
|
+
const restricted = context.readOnly || context.handoff || context.finalReview || context.reviewOnly;
|
|
12
13
|
const canWrite = context.permissionMode !== 'plan' && !restricted;
|
|
13
14
|
const lines = [
|
|
14
|
-
'[Kōbō MCP] Start by consulting the descriptions and schemas of the available tools from the managed `kobo-tasks` server. Prefer relevant Kōbō tools for operations managed by Kōbō (tasks, development services, shared memory, workspace messages and state) over reimplementing them through shell commands or HTTP. Check each tool result before treating an operation as completed. Discover tools as needed; do not call every tool or poll for activity.
|
|
15
|
+
'[Kōbō MCP] Start by consulting the descriptions and schemas of the available tools from the managed `kobo-tasks` server. Prefer relevant Kōbō tools for operations managed by Kōbō (tasks, development services, shared memory, workspace messages and state) over reimplementing them through shell commands or HTTP. Check each tool result before treating an operation as completed. Discover tools as needed; do not call every tool or poll for activity. ' +
|
|
16
|
+
(context.engine === 'mistral-vibe'
|
|
17
|
+
? 'Discover schemas with `search_tool_functions`, then call `tools.mcp_kobo_tasks.<tool>` through `run_typescript`; short names below refer to that server. '
|
|
18
|
+
: 'Exposed names use `mcp__kobo-tasks__<tool>`; short names below refer to that server. ') +
|
|
19
|
+
'Availability does not grant permission.',
|
|
15
20
|
'## Current permissions',
|
|
16
21
|
canWrite
|
|
17
22
|
? `Permission mode: ${context.permissionMode}. Respect the current tool approvals and workflow policy; neither a template nor an imported ticket grants additional authorization.`
|
|
18
|
-
:
|
|
23
|
+
: context.engine === 'mistral-vibe' && restricted
|
|
24
|
+
? `Report-only review under native ${context.permissionMode} permissions, without guaranteed filesystem read-only enforcement. Do not modify, create or delete files, commit, push, or mutate tasks, workspace state, memory or other MCP data. Kōbō tools permit only reads and explicitly scoped reports. Review instructions forbid all modifications even when native permissions allow them. Provide findings and recommended fixes only.`
|
|
25
|
+
: 'Read-only launch. Do not write files or mutate tasks, workspace state, memory, or other MCP data. Approving a plan does not change these permissions; continue only after Kōbō explicitly changes the launch permissions. Provide analysis and plans in the conversation.',
|
|
19
26
|
];
|
|
20
27
|
if (restricted) {
|
|
21
|
-
lines.push(
|
|
28
|
+
lines.push(context.engine === 'mistral-vibe'
|
|
29
|
+
? 'Respect native approval requests and wait for user approval when required; never bypass or auto-approve them. Report missing information and blockers in your final response, then finish.'
|
|
30
|
+
: 'Do not ask the user or wait for input. Report missing information and blockers in your final response, then finish so Kōbō can return to the source session.');
|
|
22
31
|
if (context.handoff)
|
|
23
32
|
lines.push('Submit the handoff report with the available `submit_session_handoff` tool according to its schema, then finish.');
|
|
24
33
|
else if (context.finalReview)
|
|
@@ -36,7 +45,7 @@ export function buildKoboLaunchInstructions(context) {
|
|
|
36
45
|
}
|
|
37
46
|
lines.push('## Development services', 'Kōbō manages the workspace dev server and its Docker services. Before tests or app checks that need those services (backend, frontend, integration or E2E), use `get_dev_server_status` and reuse the existing instance. Missing host dependencies are not a reason to launch another stack. Use the returned URL and container names, not guessed ports or names.', 'Read the project Makefile, scripts and relevant documentation to select the intended test command and runtime. Distinguish the Kōbō agent environment from the project service containers: if tests belong in a project container, run them there under current permissions. A PHP extension or other dependency missing in the agent environment alone is not evidence that the project is misconfigured, nor a reason to install global packages.', canWrite
|
|
38
47
|
? 'When an authorized task needs these services and their status is stopped, use `start_dev_server`. For an explicitly requested stop or a necessary authorized restart, use `stop_dev_server`. Do not run lifecycle commands such as `make dev-docker`, `sh/dev-docker.sh`, `docker compose up/down` or `npm run dev` directly; Kōbō runs the configured commands and tracks their processes.'
|
|
39
|
-
: 'This
|
|
48
|
+
: 'This restricted launch must not start, stop or restart services. Inspect available status/logs and report any unavailable test environment in the final response.', 'Use `get_dev_server_logs` to diagnose startup/runtime failures. If the tools are unavailable, the server is not_configured, or startup fails, report the blocker; do not bypass Kōbō with a shell launch. Test commands inside an existing container remain subject to the current permissions.', 'A running process or container is not proof that the service is ready or that tests passed. Before dependent tests, use the documented health check or a non-mutating request to the appropriate service URL. Bound readiness checks with a timeout and limited retries; if readiness remains unconfirmed, inspect logs and report the blocker rather than restarting repeatedly. Missing application readiness does not invalidate independent unit tests.');
|
|
40
49
|
lines.push('## Delegation and reporting', 'Only one agent edits the worktree at a time. Parallel read-only analysis is allowed; wait for an editing subagent to finish before editing or running tests yourself. Give each delegate its objective, exact worktree path, relevant user constraints, current permissions, intended test runtime and applicable Kōbō tools and reporting rules. Do not assume it inherits this context. A delegate without the required managed tools must ask its parent to coordinate the operation within the same permissions, not bypass Kōbō.');
|
|
41
50
|
if (context.progressReporting)
|
|
42
51
|
lines.push(PROGRESS_BAR_PROMPT);
|
|
@@ -53,9 +62,11 @@ export function buildKoboLaunchInstructions(context) {
|
|
|
53
62
|
else {
|
|
54
63
|
continuation.push('This launch cannot schedule follow-up work. Use available completion notifications for tracked work; report unfinished work or blockers honestly and finish the requested analysis/report.');
|
|
55
64
|
}
|
|
65
|
+
if (context.engine === 'mistral-vibe')
|
|
66
|
+
continuation.push('Use native `tools.process` tracked jobs for long-running commands; do not use raw redirected Bash backgrounding to detach work from native ownership.');
|
|
56
67
|
const continuationText = continuation.join('\n');
|
|
57
|
-
// Claude supports a durable application append;
|
|
58
|
-
if (context.engine
|
|
68
|
+
// Claude supports a durable application append; other engines receive these rules in their input.
|
|
69
|
+
if (context.engine !== 'claude-code')
|
|
59
70
|
lines.push(continuationText);
|
|
60
71
|
return { promptPrefix: lines.join('\n\n'), systemAppend: context.engine === 'claude-code' ? continuationText : '' };
|
|
61
72
|
}
|
package/dist/shared/memory.js
CHANGED
|
@@ -31,7 +31,7 @@ export function deriveMemoryActor(source, _callerActor) {
|
|
|
31
31
|
if (source.kind === 'internal-agent') {
|
|
32
32
|
if (!isNonEmptyString(source.workspaceId) ||
|
|
33
33
|
!isNonEmptyString(source.sessionId) ||
|
|
34
|
-
(source.engine !== 'claude-code' && source.engine !== 'codex')) {
|
|
34
|
+
(source.engine !== 'claude-code' && source.engine !== 'codex' && source.engine !== 'mistral-vibe')) {
|
|
35
35
|
throw new TypeError('Invalid internal memory actor source');
|
|
36
36
|
}
|
|
37
37
|
return Object.freeze({
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** Native multi-select values travel separately from legacy human-readable answers. */
|
|
2
|
+
export function parseQuestionSelections(value) {
|
|
3
|
+
if (value === undefined)
|
|
4
|
+
return undefined;
|
|
5
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
6
|
+
throw new Error('selections must be an object of string arrays');
|
|
7
|
+
const entries = Object.entries(value);
|
|
8
|
+
if (entries.length > 20 ||
|
|
9
|
+
entries.some(([key, values]) => !key ||
|
|
10
|
+
key.length > 200 ||
|
|
11
|
+
!Array.isArray(values) ||
|
|
12
|
+
values.length > 32 ||
|
|
13
|
+
values.some((item) => typeof item !== 'string' || item.length > 2000)))
|
|
14
|
+
throw new Error('selections exceed their field, choice or string limits');
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
@@ -9,8 +9,8 @@ const object = (properties, required = []) => ({
|
|
|
9
9
|
required,
|
|
10
10
|
additionalProperties: false,
|
|
11
11
|
});
|
|
12
|
-
const effort = choice('auto', 'none', 'low', 'medium', 'high', 'xhigh', 'max');
|
|
13
|
-
const engine = choice('claude-code', 'codex');
|
|
12
|
+
const effort = choice('auto', 'off', 'none', 'low', 'medium', 'high', 'xhigh', 'max');
|
|
13
|
+
const engine = choice('claude-code', 'codex', 'mistral-vibe');
|
|
14
14
|
const path = string(4096);
|
|
15
15
|
const url = string(4096);
|
|
16
16
|
const titles = { type: 'array', items: string(20_000), maxItems: 500 };
|
|
@@ -144,6 +144,12 @@ export function validateWorkspaceCreationArguments(name, input) {
|
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
if (name === 'create_workspace') {
|
|
147
|
+
if (value.engine !== 'mistral-vibe' &&
|
|
148
|
+
(value.reasoning_effort === 'off' || value.brainstorm_reasoning_effort === 'off'))
|
|
149
|
+
throw new Error('off is a native Mistral Vibe thinking value');
|
|
150
|
+
const review = value.auto_loop_final_review;
|
|
151
|
+
if (review && review.engine !== 'mistral-vibe' && review.reasoning_effort === 'off')
|
|
152
|
+
throw new Error('off is a native Mistral Vibe thinking value');
|
|
147
153
|
const { attachments: _attachments, ...metadataFields } = value;
|
|
148
154
|
// Keep room for multipart file headers within the downstream 1 MiB allowance.
|
|
149
155
|
if (new TextEncoder().encode(JSON.stringify(metadataFields)).byteLength > 960 * 1024)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { MCP_ATTACHMENTS_SCHEMA, validateMcpAttachments } from './mcp-attachments.js';
|
|
2
|
+
import { parseQuestionSelections } from './question-selections.js';
|
|
2
3
|
const workspace = { type: 'string', minLength: 1, maxLength: 200, description: 'Workspace ID from list_workspaces.' };
|
|
3
4
|
const session = {
|
|
4
5
|
type: 'string',
|
|
@@ -41,10 +42,16 @@ export const WORKSPACE_DIALOGUE_TOOLS = [
|
|
|
41
42
|
},
|
|
42
43
|
}, ['workspace_id'], false),
|
|
43
44
|
tool('get_workspace_questions', 'Read pending questions and whether a human tool approval is blocking the workspace.', { workspace_id: workspace }, ['workspace_id']),
|
|
44
|
-
tool('answer_workspace_question', 'Answer the current pending question using its exact tool_call_id. Answer keys are question IDs for Codex, question text for Claude. Tool permission requests require human approval in Kōbō.', {
|
|
45
|
+
tool('answer_workspace_question', 'Answer the current pending question using its exact tool_call_id. Answer keys are question IDs for Codex/Mistral Vibe, question text for Claude. Native multiple-choice arrays use selections; never split comma-joined display answers. Tool permission requests require human approval in Kōbō.', {
|
|
45
46
|
workspace_id: workspace,
|
|
46
47
|
tool_call_id: { type: 'string', minLength: 1, maxLength: 200 },
|
|
47
|
-
answers: { type: 'object',
|
|
48
|
+
answers: { type: 'object', additionalProperties: { type: 'string' } },
|
|
49
|
+
selections: {
|
|
50
|
+
type: 'object',
|
|
51
|
+
maxProperties: 20,
|
|
52
|
+
propertyNames: { minLength: 1, maxLength: 200 },
|
|
53
|
+
additionalProperties: { type: 'array', maxItems: 32, items: { type: 'string', maxLength: 2000 } },
|
|
54
|
+
},
|
|
48
55
|
}, ['workspace_id', 'tool_call_id', 'answers'], false),
|
|
49
56
|
];
|
|
50
57
|
export const EXTERNAL_MCP_TOOLS = [WORKSPACE_DISCOVERY_TOOL, ...WORKSPACE_DIALOGUE_TOOLS];
|
|
@@ -60,6 +67,8 @@ export function validateDialogueArguments(name, value) {
|
|
|
60
67
|
for (const key of definition.inputSchema.required ?? [])
|
|
61
68
|
if (!Object.hasOwn(args, key))
|
|
62
69
|
throw new Error(`${key} is required`);
|
|
70
|
+
if (name === 'answer_workspace_question')
|
|
71
|
+
parseQuestionSelections(args.selections);
|
|
63
72
|
for (const [key, input] of Object.entries(args)) {
|
|
64
73
|
const property = properties[key];
|
|
65
74
|
if (!Object.hasOwn(properties, key))
|
|
@@ -67,6 +76,9 @@ export function validateDialogueArguments(name, value) {
|
|
|
67
76
|
if (key === 'attachments') {
|
|
68
77
|
validateMcpAttachments(input);
|
|
69
78
|
}
|
|
79
|
+
else if (key === 'selections') {
|
|
80
|
+
// Validated above; native forms may omit all optional fields.
|
|
81
|
+
}
|
|
70
82
|
else if (property.type === 'string') {
|
|
71
83
|
if (typeof input !== 'string' ||
|
|
72
84
|
(property.minLength !== 0 && !input.trim()) ||
|
|
@@ -87,9 +99,8 @@ export function validateDialogueArguments(name, value) {
|
|
|
87
99
|
else if (!input ||
|
|
88
100
|
typeof input !== 'object' ||
|
|
89
101
|
Array.isArray(input) ||
|
|
90
|
-
Object.keys(input).length === 0 ||
|
|
91
102
|
Object.values(input).some((answer) => typeof answer !== 'string' || answer.length > 100_000)) {
|
|
92
|
-
throw new Error(`${key} must be
|
|
103
|
+
throw new Error(`${key} must be an object of string answers`);
|
|
93
104
|
}
|
|
94
105
|
}
|
|
95
106
|
if (name === 'send_workspace_message') {
|
package/docs/deployment-vps.md
CHANGED
|
@@ -97,7 +97,7 @@ these checks.
|
|
|
97
97
|
|
|
98
98
|
After installation, continue with [opening Kōbō](#2-start-and-open-kōbō) and
|
|
99
99
|
[authenticating agent engines](#3-authenticate-and-choose-a-project). The installer
|
|
100
|
-
does not log you into Claude or
|
|
100
|
+
does not log you into Claude Code, Codex or Mistral Vibe. Obtain the Kōbō browser token through the
|
|
101
101
|
existing startup-log command below. For installer-managed deployments, invoke the
|
|
102
102
|
updater as `/opt/kobo/bin/kobo-update --directory /opt/kobo`; the `./kobo-update`
|
|
103
103
|
examples later in this guide describe the manual installation layout.
|
|
@@ -312,6 +312,11 @@ and login requirements can vary; `claude auth login --help` and `codex login --h
|
|
|
312
312
|
show the supported options. You can also configure your own provider API key.
|
|
313
313
|
No paid agent turn is needed for these setup commands.
|
|
314
314
|
|
|
315
|
+
For **Mistral Vibe**, install Vibe separately in the image/container and authenticate
|
|
316
|
+
as the same agent user. The server must be able to run `vibe-acp`. Follow
|
|
317
|
+
[Use Mistral Vibe inside the container](./vps-projects-and-skills.md#use-mistral-vibe-inside-the-container);
|
|
318
|
+
an installation or login on the host is insufficient.
|
|
319
|
+
|
|
315
320
|
For a personal GitHub account, complete the CLI's browser login flow from your PC,
|
|
316
321
|
then connect Git HTTPS credentials to it:
|
|
317
322
|
|
|
@@ -337,7 +342,9 @@ In the first-run form, **Local project directory** means
|
|
|
337
342
|
nor a folder on the PC running the browser. Then follow [your first mission](./getting-started.md#create-a-mission).
|
|
338
343
|
|
|
339
344
|
The named `kobo-home` volume covers `/root`: it preserves Kōbō's database/settings,
|
|
340
|
-
Claude/Codex state and Git/forge configuration
|
|
345
|
+
Claude/Codex state, Vibe state stored under that home, and Git/forge configuration
|
|
346
|
+
across container replacement. A custom `VIBE_HOME` outside the volume needs its own
|
|
347
|
+
persistence.
|
|
341
348
|
Do not run `docker compose down -v`. Authentication performed only on the host is
|
|
342
349
|
not automatically available inside a container. See [Docker volume persistence](https://docs.docker.com/reference/compose-file/volumes/).
|
|
343
350
|
|
|
@@ -616,7 +623,7 @@ the reservation deliberately has no expiry that could reopen the race. Follow
|
|
|
616
623
|
container and confirm its exit before restarting it. Restart clears the in-memory
|
|
617
624
|
reservation. Never release it while a Docker stop could still be in progress.
|
|
618
625
|
|
|
619
|
-
Claude/Codex configuration and credentials, skills/plugins, caches, browser
|
|
626
|
+
Claude Code/Codex/Mistral Vibe configuration and credentials, skills/plugins, caches, browser
|
|
620
627
|
downloads, repositories/worktrees, bind-mounted App keys/scripts and project
|
|
621
628
|
database volumes are **not included** in `kobo.tar.gz`. Files outside the Kōbō
|
|
622
629
|
directory remain in the existing volume; the updater neither archives nor deletes
|
package/docs/getting-started.md
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
# Your first Kōbō workspace
|
|
2
2
|
|
|
3
|
-
Kōbō is a local, single-user application that runs Claude Code
|
|
3
|
+
Kōbō is a local, single-user application that runs Claude Code, OpenAI Codex or Mistral Vibe in Git worktrees. Each user installs their own instance and supplies their own provider account. A shared network token is not a multi-user account system.
|
|
4
4
|
|
|
5
5
|
## Requirements
|
|
6
6
|
|
|
7
|
-
- Node.js
|
|
7
|
+
- Node.js 26.12.1 or later, Git and Bash, with a writable local Git repository containing at least one commit.
|
|
8
|
+
- For Mistral Vibe, install and authenticate Vibe separately as the Kōbō server user; `vibe-acp` must be on its PATH. See [Mistral Vibe setup](../CONFIGURATION.md#mistral-vibe).
|
|
8
9
|
- A working login or API credential for the engine you choose. Kōbō ships neither credentials nor a provider subscription. Provider usage can incur charges.
|
|
9
10
|
- Linux is the locally exercised platform for this readiness change. CI is configured to exercise Linux and macOS; a configured job is not a completed compatibility test. Windows users need a Linux environment such as WSL; native Windows and WSL have not been validated in this release rehearsal.
|
|
10
11
|
|
|
@@ -36,7 +37,7 @@ Open <http://localhost:3000>. The server binds to loopback by default. Do not ex
|
|
|
36
37
|
1. In the first-run panel, choose an engine and the path of your local Git repository.
|
|
37
38
|
2. Run **Check environment**. Resolve missing Git, Bash, runtime, or write access before continuing. Authentication and model availability remain **unverified**: diagnostics do not contact a paid model or read your credentials.
|
|
38
39
|
3. Continue to the creation form. Name the mission and describe a small change, including its acceptance criteria.
|
|
39
|
-
4. Keep **Standard**
|
|
40
|
+
4. Keep **Standard** for a first mission. Use **Plan** with Claude Code/Codex, or **Interactive** with Mistral Vibe. Vibe has no Plan mode: review prompts forbid modifications, but native permissions do not guarantee filesystem read-only access. Standard requires no external skill suite. Plan does not silently become unrestricted when you prepare or enable auto-loop.
|
|
40
41
|
5. Review the plan, explicitly select an execution permission mode when you are ready, and send the implementation instruction. Review the resulting diff before committing or publishing.
|
|
41
42
|
|
|
42
43
|
New installations use manual commit, push and PR/MR publication preferences, disable audio and optional ticket integrations, and admit at most two concurrent unattended starts. Manual sessions can exceed that threshold. Agent workflow preferences are instructions; the engine permission mode supplies the actual sandbox and approval behavior.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -6,11 +6,11 @@ Open the first-run setup from Help and run the check again after changing the se
|
|
|
6
6
|
|
|
7
7
|
| Check | Action |
|
|
8
8
|
|---|---|
|
|
9
|
-
| Node | Use Node
|
|
9
|
+
| Node | Use Node 26.12.1 or later; contributors should use `.nvmrc`. |
|
|
10
10
|
| Git / Bash | Install the missing executable and make it available on the server's `PATH`. |
|
|
11
11
|
| Project | Select a writable Git repository containing at least one commit. |
|
|
12
12
|
| Storage / worktrees | Check permissions on `KOBO_HOME`, the project and configured worktree root. |
|
|
13
|
-
| Engine executable |
|
|
13
|
+
| Engine executable | Check the chosen runtime installation. Claude Code/Codex runtimes come from package dependencies; Mistral Vibe must be installed separately, with `vibe-acp` on the server user’s PATH (inside the container for Docker). See [Vibe setup](../CONFIGURATION.md#mistral-vibe). |
|
|
14
14
|
| Authentication / model: unknown | Authenticate with the selected provider, select a model available to that account, then run a small mission. The diagnostic deliberately makes no provider request. |
|
|
15
15
|
|
|
16
16
|
## Native dependency installation fails
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.30",
|
|
4
4
|
"description": "Kōbō — local multi-workspace orchestrator for Claude Code and OpenAI Codex, with isolated Git worktrees, live review and optional automation.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"quasar"
|
|
62
62
|
],
|
|
63
63
|
"engines": {
|
|
64
|
-
"node": ">=
|
|
64
|
+
"node": ">=26.12.1"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"dev": "KOBO_ENFORCE_LOCAL_HOME=1 KOBO_HOME=./data PORT=3300 KOBO_DEV_CLIENT_ORIGIN=http://localhost:8080 tsx watch src/server/index.ts",
|
|
@@ -88,32 +88,38 @@
|
|
|
88
88
|
"security:scan": "node scripts/scan-secrets.mjs"
|
|
89
89
|
},
|
|
90
90
|
"dependencies": {
|
|
91
|
-
"@
|
|
91
|
+
"@agentclientprotocol/sdk": "2.0.1",
|
|
92
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.308",
|
|
92
93
|
"@emnapi/core": "^1.11.3",
|
|
93
94
|
"@emnapi/runtime": "^1.11.3",
|
|
94
|
-
"@hono/node-server": "^2.1.
|
|
95
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
96
|
-
"@openai/codex": "^0.
|
|
95
|
+
"@hono/node-server": "^2.1.5",
|
|
96
|
+
"@modelcontextprotocol/sdk": "^1.32.1",
|
|
97
|
+
"@openai/codex": "^0.163.0",
|
|
97
98
|
"better-sqlite3": "^13.0.3",
|
|
98
|
-
"cron-parser": "^5.10.
|
|
99
|
-
"hono": "^4.13.
|
|
100
|
-
"nanoid": "^6.0.
|
|
99
|
+
"cron-parser": "^5.10.2",
|
|
100
|
+
"hono": "^4.13.13",
|
|
101
|
+
"nanoid": "^6.0.2",
|
|
101
102
|
"node-pty": "^1.1.0",
|
|
102
103
|
"ws": "^8.22.0"
|
|
103
104
|
},
|
|
104
105
|
"devDependencies": {
|
|
105
106
|
"@biomejs/biome": "2.5.14",
|
|
106
107
|
"@types/better-sqlite3": "^9.6.0",
|
|
107
|
-
"@types/node": "^26.6.
|
|
108
|
+
"@types/node": "^26.6.5",
|
|
108
109
|
"@types/ws": "^8.18.2",
|
|
109
110
|
"@vitest/runner": "^4.1.11",
|
|
110
|
-
"concurrently": "^10.0.
|
|
111
|
+
"concurrently": "^10.0.6",
|
|
111
112
|
"tsx": "^4.23.15",
|
|
112
113
|
"typescript": "^7.0.2",
|
|
113
|
-
"vitest": "^5.0.
|
|
114
|
+
"vitest": "^5.0.5"
|
|
114
115
|
},
|
|
115
116
|
"overrides": {
|
|
116
|
-
"@hono/node-server": "^2.1.
|
|
117
|
-
"shell-quote": "^1.
|
|
117
|
+
"@hono/node-server": "^2.1.5",
|
|
118
|
+
"shell-quote": "^1.12.0"
|
|
119
|
+
},
|
|
120
|
+
"allowScripts": {
|
|
121
|
+
"better-sqlite3@13.0.3": true,
|
|
122
|
+
"esbuild@0.28.2": true,
|
|
123
|
+
"node-pty@1.1.0": true
|
|
118
124
|
}
|
|
119
125
|
}
|