@loicngr/kobo 1.6.15 → 1.7.0
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/README.md +4 -3
- package/dist/mcp-server/kobo-tasks-server.js +51 -0
- package/dist/server/db/migrations.js +40 -0
- package/dist/server/db/schema.js +7 -5
- package/dist/server/index.js +12 -11
- package/dist/server/routes/workspaces.js +160 -21
- package/dist/server/services/agent/engines/claude-code/capabilities.js +1 -1
- package/dist/server/services/agent/engines/claude-code/engine.js +237 -132
- package/dist/server/services/agent/engines/claude-code/event-mapper.js +234 -0
- package/dist/server/services/agent/engines/claude-code/options-builder.js +68 -0
- package/dist/server/services/agent/engines/claude-code/precompact-hook.js +27 -0
- package/dist/server/services/agent/engines/types.js +1 -0
- package/dist/server/services/agent/orchestrator.js +536 -94
- package/dist/server/services/agent/session-controller.js +14 -43
- package/dist/server/services/auto-loop-service.js +17 -6
- package/dist/server/services/content-migration-service.js +24 -94
- package/dist/server/services/wakeup-service.js +8 -9
- package/dist/server/services/workspace-service.js +40 -36
- package/package.json +2 -1
- package/src/client/dist/spa/assets/ActivityFeed-CIJPN8TH.js +7 -0
- package/src/client/dist/spa/assets/ActivityFeed-LXnbg3ff.css +1 -0
- package/src/client/dist/spa/assets/{ClosePopup-D7BBEcaf.js → ClosePopup-DzB3mDtj.js} +1 -1
- package/src/client/dist/spa/assets/CreatePage-BE3xfQsC.css +1 -0
- package/src/client/dist/spa/assets/CreatePage-U6TtJzNe.js +2 -0
- package/src/client/dist/spa/assets/{DiffViewer-BJZADilo.js → DiffViewer-Di85TBIi.js} +3 -3
- package/src/client/dist/spa/assets/HealthPage-B7aWFxAZ.js +1 -0
- package/src/client/dist/spa/assets/MainLayout-BHBrz4c9.js +37 -0
- package/src/client/dist/spa/assets/MainLayout-Dba6SdpU.css +1 -0
- package/src/client/dist/spa/assets/QCheckbox-CcY7ZSk9.js +1 -0
- package/src/client/dist/spa/assets/{QChip-D905z6BM.js → QChip-BhT0W2Dg.js} +1 -1
- package/src/client/dist/spa/assets/QExpansionItem-VS4b4eY6.js +1 -0
- package/src/client/dist/spa/assets/{QInput-6U0_avSY.js → QInput-D4WJro4e.js} +1 -1
- package/src/client/dist/spa/assets/{QItemSection-Cloi4ErY.js → QItemSection-KFAnxzMK.js} +1 -1
- package/src/client/dist/spa/assets/{QMenu-BPzgTm2k.js → QMenu-CchbRXbp.js} +1 -1
- package/src/client/dist/spa/assets/{QPage-C6h_ah5z.js → QPage-Cu7zkfc6.js} +1 -1
- package/src/client/dist/spa/assets/QRadio-DaZhdLCg.js +1 -0
- package/src/client/dist/spa/assets/{touch-DBLw8vQK.js → QResizeObserver-Cf79V-VZ.js} +1 -1
- package/src/client/dist/spa/assets/QScrollArea-DrVTDLU0.js +1 -0
- package/src/client/dist/spa/assets/QTabPanels-HXz-evuj.js +1 -0
- package/src/client/dist/spa/assets/QToggle-CGpiJLDJ.js +1 -0
- package/src/client/dist/spa/assets/QTooltip-DjJYMTkN.js +1 -0
- package/src/client/dist/spa/assets/SearchPage-CVm-sqxH.js +1 -0
- package/src/client/dist/spa/assets/SettingsPage-ayDKGo9H.js +1 -0
- package/src/client/dist/spa/assets/SettingsPage-wTBCvK6t.css +1 -0
- package/src/client/dist/spa/assets/WorkspacePage-DQxGe62K.css +1 -0
- package/src/client/dist/spa/assets/WorkspacePage-xaVy8s5i.js +4 -0
- package/src/client/dist/spa/assets/build-path-tree-CdY1A6aP.js +1 -0
- package/src/client/dist/spa/assets/{cssMode-QQTtBrD_.js → cssMode-BVNBMOxh.js} +1 -1
- package/src/client/dist/spa/assets/{editor.api-YqpktRoe.js → editor.api-D6Vfp5yv.js} +1 -1
- package/src/client/dist/spa/assets/{editor.main-DDGqfxYm.js → editor.main-CTCYF6V4.js} +3 -3
- package/src/client/dist/spa/assets/expand-template-vHV2iwXf.js +1 -0
- package/src/client/dist/spa/assets/{formatters-DWeOzSfw.js → formatters-ejxELb0M.js} +1 -1
- package/src/client/dist/spa/assets/{freemarker2-BC_Lt7t3.js → freemarker2-nmzwPmzi.js} +1 -1
- package/src/client/dist/spa/assets/{handlebars-BphhRg2c.js → handlebars-CI9lR7Ef.js} +1 -1
- package/src/client/dist/spa/assets/{html-C84Ufc1n.js → html-BQ21REnv.js} +1 -1
- package/src/client/dist/spa/assets/{htmlMode-CIlyKZJ4.js → htmlMode-io5J5Qr1.js} +1 -1
- package/src/client/dist/spa/assets/i18n-Do8Kn8n0.js +1 -0
- package/src/client/dist/spa/assets/index-C_e7KOYh.js +2 -0
- package/src/client/dist/spa/assets/{javascript-D5LTZTWn.js → javascript--u9PDBCv.js} +1 -1
- package/src/client/dist/spa/assets/{jsonMode-YBOBMJNl.js → jsonMode-DBG5llk4.js} +1 -1
- package/src/client/dist/spa/assets/{kobo-commands-DFflpxts.js → kobo-commands-DiUm1Y34.js} +1 -1
- package/src/client/dist/spa/assets/{liquid-UNCP2Jl6.js → liquid-DxAS4nYF.js} +1 -1
- package/src/client/dist/spa/assets/{marked.esm-D7ibHC_y.js → marked.esm-DuOsJx63.js} +1 -1
- package/src/client/dist/spa/assets/{mdx-CsHyBm_B.js → mdx-BNXTiODW.js} +1 -1
- package/src/client/dist/spa/assets/{models-tXWASlTL.js → models-DNYEhFF7.js} +1 -1
- package/src/client/dist/spa/assets/{monaco.contribution-Bv79M2zD.js → monaco.contribution-CT3LAK0J.js} +2 -2
- package/src/client/dist/spa/assets/{python-B3h-WTW0.js → python-DztNww13.js} +1 -1
- package/src/client/dist/spa/assets/{razor-Cs79ULMl.js → razor-Cyr82NZF.js} +1 -1
- package/src/client/dist/spa/assets/{settings-Cw4mtk9x.js → settings-Dbx1_ksA.js} +1 -1
- package/src/client/dist/spa/assets/symbols-BVRrMH2r.js +1 -0
- package/src/client/dist/spa/assets/touch-Co9pfjUU.js +1 -0
- package/src/client/dist/spa/assets/{tsMode-238NR35q.js → tsMode-CbQVgsIP.js} +1 -1
- package/src/client/dist/spa/assets/{typescript-C93UakWa.js → typescript-UHOe4d1S.js} +1 -1
- package/src/client/dist/spa/assets/{use-checkbox-w-raiu10.js → use-checkbox-DzHmcu7s.js} +1 -1
- package/src/client/dist/spa/assets/use-panel-Br8QNRMk.js +1 -0
- package/src/client/dist/spa/assets/{xml-24CcVrVJ.js → xml-DC88eFpV.js} +1 -1
- package/src/client/dist/spa/assets/{yaml-BLhB8_OL.js → yaml-DSTsIRJr.js} +1 -1
- package/src/client/dist/spa/index.html +10 -7
- package/src/mcp-server/kobo-tasks-server.ts +60 -1
- package/dist/server/services/agent/engines/claude-code/args-builder.js +0 -57
- package/dist/server/services/agent/engines/claude-code/mcp-config.js +0 -23
- package/dist/server/services/agent/engines/claude-code/stream-parser.js +0 -386
- package/src/client/dist/spa/assets/ActivityFeed-BHdMJRwS.css +0 -1
- package/src/client/dist/spa/assets/ActivityFeed-D7MF6IK1.js +0 -8
- package/src/client/dist/spa/assets/CreatePage-DJbZH8wp.css +0 -1
- package/src/client/dist/spa/assets/CreatePage-rp-9_jOF.js +0 -2
- package/src/client/dist/spa/assets/HealthPage-CZQB2pvh.js +0 -1
- package/src/client/dist/spa/assets/MainLayout-CFHf3zKv.js +0 -37
- package/src/client/dist/spa/assets/MainLayout-Db3dwSTM.css +0 -1
- package/src/client/dist/spa/assets/QExpansionItem-CUXuOfeR.js +0 -1
- package/src/client/dist/spa/assets/QScrollArea-N10UpHIf.js +0 -1
- package/src/client/dist/spa/assets/QSlideTransition-BMX92yUu.js +0 -1
- package/src/client/dist/spa/assets/QTabPanels-PPompnxw.js +0 -1
- package/src/client/dist/spa/assets/QTooltip-DLT8jCHz.js +0 -1
- package/src/client/dist/spa/assets/SearchPage-CfYy4vGJ.js +0 -1
- package/src/client/dist/spa/assets/SettingsPage-B8DhSZw7.css +0 -1
- package/src/client/dist/spa/assets/SettingsPage-ONWYC-Bn.js +0 -1
- package/src/client/dist/spa/assets/WorkspacePage-B2VAbf6l.js +0 -4
- package/src/client/dist/spa/assets/WorkspacePage-k2pgeRoy.css +0 -1
- package/src/client/dist/spa/assets/build-path-tree-DETFP2lL.js +0 -1
- package/src/client/dist/spa/assets/expand-template-CZkefibF.js +0 -1
- package/src/client/dist/spa/assets/i18n-CNdSgNP6.js +0 -1
- package/src/client/dist/spa/assets/index-pGAaG7Rh.js +0 -2
- package/src/client/dist/spa/assets/stats-BrLStQKj.js +0 -1
- package/src/client/dist/spa/assets/symbols-TAFELniU.js +0 -1
- /package/src/client/dist/spa/assets/{QBadge-BUkmTO0P.js → QBadge-fsQ2AokU.js} +0 -0
- /package/src/client/dist/spa/assets/{QBtn-CyzfM9-_.js → QBtn-DHwAb18J.js} +0 -0
- /package/src/client/dist/spa/assets/{QItemLabel-DwnV_S8y.js → QItemLabel-DWwenW2S.js} +0 -0
- /package/src/client/dist/spa/assets/{QList-DZfpUv3n.js → QList-NmIE6Rd9.js} +0 -0
- /package/src/client/dist/spa/assets/{QSpace-PlDK6Fg3.js → QSpace-COlmM_4F.js} +0 -0
- /package/src/client/dist/spa/assets/{QSpinnerDots-D7bo_KgI.js → QSpinnerDots-DwtnRN2r.js} +0 -0
- /package/src/client/dist/spa/assets/{_plugin-vue_export-helper-CpNzZuug.js → _plugin-vue_export-helper-B8bB5DBd.js} +0 -0
- /package/src/client/dist/spa/assets/{abap-DrZwwXZX.js → abap-DzK-OTGh.js} +0 -0
- /package/src/client/dist/spa/assets/{apex-CrCz0btt.js → apex-Bj60_dRt.js} +0 -0
- /package/src/client/dist/spa/assets/{azcli-BapzKHay.js → azcli-B6NwaBAZ.js} +0 -0
- /package/src/client/dist/spa/assets/{bat-C_NRAiA1.js → bat-bf7wXV68.js} +0 -0
- /package/src/client/dist/spa/assets/{bicep-C7pp2CNk.js → bicep-C_bg8UgA.js} +0 -0
- /package/src/client/dist/spa/assets/{cameligo-BhhK9vxZ.js → cameligo-CTWw4D4B.js} +0 -0
- /package/src/client/dist/spa/assets/{clojure-D0ujmUyE.js → clojure-CgdPoH0r.js} +0 -0
- /package/src/client/dist/spa/assets/{coffee-DHEl7Jbb.js → coffee-gHQfdA5M.js} +0 -0
- /package/src/client/dist/spa/assets/{cpp-Iil-3nzZ.js → cpp-BM4Jj4aW.js} +0 -0
- /package/src/client/dist/spa/assets/{csharp-Dh0Ee7SY.js → csharp-D8-bh4Cd.js} +0 -0
- /package/src/client/dist/spa/assets/{csp-mwzjw0JL.js → csp-CXBxRx0n.js} +0 -0
- /package/src/client/dist/spa/assets/{css-COIa8ZTR.js → css-DKjIxrmY.js} +0 -0
- /package/src/client/dist/spa/assets/{cypher-GVc17FC4.js → cypher-C5e5inIh.js} +0 -0
- /package/src/client/dist/spa/assets/{dart-phiCaE7_.js → dart-BhRHHm4x.js} +0 -0
- /package/src/client/dist/spa/assets/{dockerfile-BMaDhdim.js → dockerfile-DW5REF8E.js} +0 -0
- /package/src/client/dist/spa/assets/{documents-BMdAS6h8.js → documents-D6A3wRry.js} +0 -0
- /package/src/client/dist/spa/assets/{ecl-Cj47kvqp.js → ecl-Bw4Hg3n_.js} +0 -0
- /package/src/client/dist/spa/assets/{elixir-DBbstcE1.js → elixir-DHmoBvpZ.js} +0 -0
- /package/src/client/dist/spa/assets/{flow9-ChHb1adO.js → flow9-BsFExz3v.js} +0 -0
- /package/src/client/dist/spa/assets/{fsharp-CDI_AxQw.js → fsharp-BaeLhgfq.js} +0 -0
- /package/src/client/dist/spa/assets/{go-DmsC2k-Y.js → go-Bd-NFKIC.js} +0 -0
- /package/src/client/dist/spa/assets/{graphql-C8hjT6Ki.js → graphql-DZVerJfy.js} +0 -0
- /package/src/client/dist/spa/assets/{hcl-C15cAQOZ.js → hcl-CAVzrZfH.js} +0 -0
- /package/src/client/dist/spa/assets/{ini-CKrAe0ag.js → ini-CyXdX58t.js} +0 -0
- /package/src/client/dist/spa/assets/{java-BVhjILyl.js → java-B5pNgvhy.js} +0 -0
- /package/src/client/dist/spa/assets/{julia-BzPDHDOG.js → julia-XRhmV3AN.js} +0 -0
- /package/src/client/dist/spa/assets/{kotlin-DQMAn-b6.js → kotlin-DOd3J5vr.js} +0 -0
- /package/src/client/dist/spa/assets/{less-428mfr1h.js → less-veZSnyw6.js} +0 -0
- /package/src/client/dist/spa/assets/{lexon-B09dCO6A.js → lexon-QWGkuK0H.js} +0 -0
- /package/src/client/dist/spa/assets/{lua-CVQ0BJif.js → lua-CYGpjuO5.js} +0 -0
- /package/src/client/dist/spa/assets/{m3-CiPQ1ljw.js → m3-yNnrZkdc.js} +0 -0
- /package/src/client/dist/spa/assets/{markdown--G0dqL-7.js → markdown-BCSWEPSX.js} +0 -0
- /package/src/client/dist/spa/assets/{mips-BaboCM3T.js → mips-OpYmcC30.js} +0 -0
- /package/src/client/dist/spa/assets/{msdax-DUaqkqre.js → msdax-2oxoTO9Z.js} +0 -0
- /package/src/client/dist/spa/assets/{mysql-CUE6XF4r.js → mysql-5KlC-K_9.js} +0 -0
- /package/src/client/dist/spa/assets/{objective-c-C4MUnzeT.js → objective-c-CcDCgtLx.js} +0 -0
- /package/src/client/dist/spa/assets/{pascal-CWMUMx__.js → pascal-BZGsbaEV.js} +0 -0
- /package/src/client/dist/spa/assets/{pascaligo-DLCVutek.js → pascaligo-DtD5qU3G.js} +0 -0
- /package/src/client/dist/spa/assets/{perl-JYoirQpx.js → perl-C1jNNS3E.js} +0 -0
- /package/src/client/dist/spa/assets/{pgsql-BqOy7sqx.js → pgsql-CT0fhiZa.js} +0 -0
- /package/src/client/dist/spa/assets/{php-PZqsysO1.js → php-D6DrXoPM.js} +0 -0
- /package/src/client/dist/spa/assets/{pla-BiwqVlg6.js → pla-b3-HN2pF.js} +0 -0
- /package/src/client/dist/spa/assets/{postiats-COxQtXCD.js → postiats-Bin2ApVS.js} +0 -0
- /package/src/client/dist/spa/assets/{powerquery-DdXUmaWa.js → powerquery-7ASnn-ZG.js} +0 -0
- /package/src/client/dist/spa/assets/{powershell-D05yu9sz.js → powershell-t4p7sU1H.js} +0 -0
- /package/src/client/dist/spa/assets/{protobuf-BDsm0ZB_.js → protobuf-BUGeWa_j.js} +0 -0
- /package/src/client/dist/spa/assets/{pug-3CmTiGoi.js → pug-BuKcgC9s.js} +0 -0
- /package/src/client/dist/spa/assets/{qsharp-C4eHfCpJ.js → qsharp-DSMtI_O7.js} +0 -0
- /package/src/client/dist/spa/assets/{r-Decg_RIU.js → r-DMlFgn7A.js} +0 -0
- /package/src/client/dist/spa/assets/{redis-Cl3EBA4R.js → redis-cXItkC5u.js} +0 -0
- /package/src/client/dist/spa/assets/{redshift-5ZsNLhOp.js → redshift-BZVbW7HE.js} +0 -0
- /package/src/client/dist/spa/assets/{restructuredtext-BulNNF_e.js → restructuredtext-BzjxwS8h.js} +0 -0
- /package/src/client/dist/spa/assets/{ruby-D3Axi_9w.js → ruby-C5nyLV4l.js} +0 -0
- /package/src/client/dist/spa/assets/{rust-Csys1Tos.js → rust-BcmMsHdf.js} +0 -0
- /package/src/client/dist/spa/assets/{sb-C_iBPphi.js → sb-Dnb1iy6B.js} +0 -0
- /package/src/client/dist/spa/assets/{scala-Cg4p-EZ2.js → scala-anMIFYpA.js} +0 -0
- /package/src/client/dist/spa/assets/{scheme-BlVnEL_j.js → scheme-BItQTe08.js} +0 -0
- /package/src/client/dist/spa/assets/{scss-CmLW8ojr.js → scss-BOv51BJ5.js} +0 -0
- /package/src/client/dist/spa/assets/{shell-B1DV_gpl.js → shell-BsRYRTNN.js} +0 -0
- /package/src/client/dist/spa/assets/{solidity-glFpNhe3.js → solidity-BtuLgGDx.js} +0 -0
- /package/src/client/dist/spa/assets/{sophia-D9j4cFkA.js → sophia-B0Vkc5MF.js} +0 -0
- /package/src/client/dist/spa/assets/{sparql-DV5Ux9cO.js → sparql-B7lvkZQM.js} +0 -0
- /package/src/client/dist/spa/assets/{sql-K8tNKFcf.js → sql-DvP5MpA3.js} +0 -0
- /package/src/client/dist/spa/assets/{st-BhIdE2hj.js → st-GVUeyB3U.js} +0 -0
- /package/src/client/dist/spa/assets/{swift-B0pzSmmx.js → swift-DSPIoCjm.js} +0 -0
- /package/src/client/dist/spa/assets/{systemverilog-CeBgixbN.js → systemverilog-Icj2-k23.js} +0 -0
- /package/src/client/dist/spa/assets/{tcl-B0Ji3IbZ.js → tcl-Cd8KQcm-.js} +0 -0
- /package/src/client/dist/spa/assets/{twig-KUgPCP41.js → twig-CBHmt8z3.js} +0 -0
- /package/src/client/dist/spa/assets/{typespec-ryrhjid6.js → typespec-Ckc037mq.js} +0 -0
- /package/src/client/dist/spa/assets/{use-quasar-Clv5nVxk.js → use-quasar-Cc4smfg5.js} +0 -0
- /package/src/client/dist/spa/assets/{vb-Z68-YtMY.js → vb-B97GW9Wb.js} +0 -0
- /package/src/client/dist/spa/assets/{vue-i18n-BVrBmgZa.js → vue-i18n-eUDnMrPl.js} +0 -0
- /package/src/client/dist/spa/assets/{wgsl-bH-W-d_T.js → wgsl-DIKmb3YH.js} +0 -0
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { getWorkspace, listTasks } from '../workspace-service.js';
|
|
2
1
|
export class SessionController {
|
|
3
2
|
workspaceId;
|
|
4
3
|
agentSessionId;
|
|
5
4
|
engine;
|
|
6
5
|
onEvent;
|
|
7
|
-
|
|
6
|
+
_engineProcess;
|
|
8
7
|
_status = 'running';
|
|
8
|
+
get engineProcess() {
|
|
9
|
+
return this._engineProcess;
|
|
10
|
+
}
|
|
9
11
|
constructor(workspaceId, agentSessionId, engine, onEvent) {
|
|
10
12
|
this.workspaceId = workspaceId;
|
|
11
13
|
this.agentSessionId = agentSessionId;
|
|
@@ -13,67 +15,36 @@ export class SessionController {
|
|
|
13
15
|
this.onEvent = onEvent;
|
|
14
16
|
}
|
|
15
17
|
async start(options) {
|
|
16
|
-
if (this.
|
|
18
|
+
if (this._engineProcess)
|
|
17
19
|
throw new Error('SessionController already started');
|
|
18
|
-
this.
|
|
20
|
+
this._engineProcess = await this.engine.start(options, (ev) => this.handle(ev));
|
|
19
21
|
this._status = 'running';
|
|
20
22
|
}
|
|
21
23
|
sendMessage(content) {
|
|
22
|
-
if (!this.
|
|
24
|
+
if (!this._engineProcess)
|
|
23
25
|
throw new Error('SessionController not started');
|
|
24
|
-
this.
|
|
26
|
+
this._engineProcess.sendMessage(content);
|
|
25
27
|
}
|
|
26
28
|
interrupt() {
|
|
27
|
-
if (!this.
|
|
29
|
+
if (!this._engineProcess)
|
|
28
30
|
throw new Error('SessionController not started');
|
|
29
|
-
this.
|
|
31
|
+
this._engineProcess.interrupt();
|
|
30
32
|
}
|
|
31
33
|
async stop() {
|
|
32
34
|
this._status = 'stopping';
|
|
33
|
-
if (this.
|
|
34
|
-
await this.
|
|
35
|
+
if (this._engineProcess)
|
|
36
|
+
await this._engineProcess.stop();
|
|
35
37
|
}
|
|
36
38
|
get status() {
|
|
37
39
|
return this._status;
|
|
38
40
|
}
|
|
39
41
|
get pid() {
|
|
40
|
-
return this.
|
|
42
|
+
return this._engineProcess?.pid;
|
|
41
43
|
}
|
|
42
44
|
get engineSessionId() {
|
|
43
|
-
return this.
|
|
45
|
+
return this._engineProcess?.engineSessionId;
|
|
44
46
|
}
|
|
45
47
|
handle(ev) {
|
|
46
|
-
if (ev.kind === 'session:compacted') {
|
|
47
|
-
try {
|
|
48
|
-
this.injectPostCompactReminder();
|
|
49
|
-
}
|
|
50
|
-
catch (err) {
|
|
51
|
-
console.error('[session-controller] post-compact reminder failed:', err);
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
48
|
this.onEvent(ev);
|
|
55
49
|
}
|
|
56
|
-
injectPostCompactReminder() {
|
|
57
|
-
if (!this.engineProcess)
|
|
58
|
-
return;
|
|
59
|
-
const ws = getWorkspace(this.workspaceId);
|
|
60
|
-
const tasks = listTasks(this.workspaceId);
|
|
61
|
-
const criteria = tasks.filter((t) => t.isAcceptanceCriterion);
|
|
62
|
-
const todos = tasks.filter((t) => !t.isAcceptanceCriterion);
|
|
63
|
-
if (criteria.length === 0 && todos.length === 0)
|
|
64
|
-
return;
|
|
65
|
-
let reminder = `\n--- Context reminder after compaction ---\n`;
|
|
66
|
-
reminder += `Task: ${ws?.name ?? this.workspaceId}\n`;
|
|
67
|
-
if (todos.length > 0) {
|
|
68
|
-
reminder += `\nTasks:\n${todos.map((t) => `- [${t.status === 'done' ? 'x' : ' '}] ${t.title}`).join('\n')}\n`;
|
|
69
|
-
}
|
|
70
|
-
if (criteria.length > 0) {
|
|
71
|
-
reminder += `\nAcceptance criteria:\n${criteria
|
|
72
|
-
.map((t) => `- [${t.status === 'done' ? 'x' : ' '}] ${t.title}`)
|
|
73
|
-
.join('\n')}\n`;
|
|
74
|
-
reminder += `\nWhen you complete a criterion, tell me which one so I can mark it as done.\n`;
|
|
75
|
-
}
|
|
76
|
-
reminder += `--- End of reminder ---\n`;
|
|
77
|
-
this.engineProcess.sendMessage(reminder);
|
|
78
|
-
}
|
|
79
50
|
}
|
|
@@ -10,7 +10,7 @@ const NO_PROGRESS_STALL_THRESHOLD = 3;
|
|
|
10
10
|
function getRow(workspaceId) {
|
|
11
11
|
const db = getDb();
|
|
12
12
|
const row = db
|
|
13
|
-
.prepare(`SELECT id, project_path, working_branch, worktree_path, model, permission_mode, reasoning_effort,
|
|
13
|
+
.prepare(`SELECT id, project_path, working_branch, worktree_path, model, permission_mode, agent_permission_mode, reasoning_effort,
|
|
14
14
|
status, auto_loop, auto_loop_ready, no_progress_streak, archived_at
|
|
15
15
|
FROM workspaces WHERE id = ?`)
|
|
16
16
|
.get(workspaceId);
|
|
@@ -97,6 +97,10 @@ export function onSessionEnded(workspaceId, reason, tasksDoneDelta) {
|
|
|
97
97
|
// timer), let that timer own the next spawn so the backoff delay is respected.
|
|
98
98
|
if (row.status === 'quota')
|
|
99
99
|
return;
|
|
100
|
+
// Don't spawn a competing session while paused on canUseTool — the user
|
|
101
|
+
// will resume the deferred turn explicitly.
|
|
102
|
+
if (row.status === 'awaiting-user')
|
|
103
|
+
return;
|
|
100
104
|
if (reason === 'error' || reason === 'killed') {
|
|
101
105
|
disable(workspaceId, 'error');
|
|
102
106
|
return;
|
|
@@ -219,6 +223,9 @@ function spawnNextIteration(workspaceId, opts = {}) {
|
|
|
219
223
|
const row = getRow(workspaceId);
|
|
220
224
|
if (!row)
|
|
221
225
|
return;
|
|
226
|
+
// Same guard as onSessionEnded — never race a deferred-resume start.
|
|
227
|
+
if (row.status === 'awaiting-user')
|
|
228
|
+
return;
|
|
222
229
|
const task = pickNextTask(workspaceId);
|
|
223
230
|
if (!task) {
|
|
224
231
|
disable(workspaceId, 'completed');
|
|
@@ -246,10 +253,14 @@ function spawnNextIteration(workspaceId, opts = {}) {
|
|
|
246
253
|
.replaceAll('{isAcceptanceCriterion}', String(task.isAcceptanceCriterion))
|
|
247
254
|
.replaceAll('{overrideBlock}', overrideBlock);
|
|
248
255
|
const worktreePath = row.worktree_path ?? path.join(row.project_path, '.worktrees', row.working_branch);
|
|
249
|
-
//
|
|
250
|
-
//
|
|
251
|
-
|
|
252
|
-
const
|
|
256
|
+
// Plan mode would deadlock the loop (blocks MCP + edits) — promote to bypass.
|
|
257
|
+
// Other modes (bypass/strict/interactive) are honored.
|
|
258
|
+
const stored = (row.agent_permission_mode ?? 'bypass');
|
|
259
|
+
const agentPermissionMode = stored === 'plan' ? 'bypass' : stored;
|
|
260
|
+
if (stored === 'plan') {
|
|
261
|
+
console.warn(`[auto-loop-service] Promoting plan → bypass for workspace ${workspaceId} — auto-loop cannot run in plan mode`);
|
|
262
|
+
emitEphemeral(workspaceId, 'autoloop:permission-overridden', { from: 'plan', to: 'bypass' });
|
|
263
|
+
}
|
|
253
264
|
// Pre-check: if the worktree directory is gone (user `rm -rf`-ed it),
|
|
254
265
|
// fail loudly rather than letting startAgent throw a deep engine error.
|
|
255
266
|
if (!fs.existsSync(worktreePath)) {
|
|
@@ -263,7 +274,7 @@ function spawnNextIteration(workspaceId, opts = {}) {
|
|
|
263
274
|
let agentSessionId;
|
|
264
275
|
try {
|
|
265
276
|
const agent = orchestrator.startAgent(workspaceId, worktreePath, prompt, row.model, false, // resume=false — fresh context for each iteration
|
|
266
|
-
|
|
277
|
+
agentPermissionMode, undefined, row.reasoning_effort);
|
|
267
278
|
agentSessionId = agent.agentSessionId;
|
|
268
279
|
}
|
|
269
280
|
catch (err) {
|
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
import { nanoid } from 'nanoid';
|
|
2
|
-
import { createParserState, parseClaudeLine } from './agent/engines/claude-code/stream-parser.js';
|
|
3
|
-
import { createPreMigrationBackup } from './db-backup-service.js';
|
|
4
|
-
import { broadcastAll } from './websocket-service.js';
|
|
5
1
|
const internal = { state: 'idle', total: 0, processed: 0 };
|
|
6
2
|
let isRunning = false;
|
|
7
3
|
function snapshot() {
|
|
@@ -41,105 +37,39 @@ function snapshot() {
|
|
|
41
37
|
export function getContentMigrationStatus() {
|
|
42
38
|
return snapshot();
|
|
43
39
|
}
|
|
44
|
-
|
|
40
|
+
/**
|
|
41
|
+
* Legacy ws_events content migration.
|
|
42
|
+
*
|
|
43
|
+
* Historical context: earlier versions of Kōbō persisted Claude Code stdout as
|
|
44
|
+
* `agent:output` / `agent:stderr` / `agent:status` rows. The migration to the
|
|
45
|
+
* unified `agent:event` shape was completed in v10. As of the Claude Agent SDK
|
|
46
|
+
* cutover, the stream-parser used to reconstruct AgentEvents from those legacy
|
|
47
|
+
* rows has been removed.
|
|
48
|
+
*
|
|
49
|
+
* All production databases have been migrated. This function is now a no-op
|
|
50
|
+
* kept for API compatibility — it always reports `idle`. Should any rare,
|
|
51
|
+
* unmigrated row remain, it is left untouched in `ws_events` (and ignored by
|
|
52
|
+
* the new replay path which only reads `agent:event`).
|
|
53
|
+
*/
|
|
54
|
+
export async function runContentMigrationIfNeeded(_db, _dbPath) {
|
|
45
55
|
if (isRunning)
|
|
46
56
|
return;
|
|
47
57
|
isRunning = true;
|
|
48
58
|
try {
|
|
49
|
-
|
|
50
|
-
.prepare("SELECT COUNT(*) AS c FROM ws_events WHERE type IN ('agent:output', 'agent:stderr', 'agent:status')")
|
|
51
|
-
.get();
|
|
52
|
-
if (row.c === 0) {
|
|
53
|
-
internal.state = 'idle';
|
|
54
|
-
isRunning = false;
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
internal.state = 'backing-up';
|
|
58
|
-
internal.startedAt = new Date().toISOString();
|
|
59
|
-
broadcastStatus();
|
|
60
|
-
const backup = await createPreMigrationBackup(db, dbPath, 'v10');
|
|
61
|
-
internal.backupPath = backup.created ?? undefined;
|
|
62
|
-
internal.state = 'running';
|
|
63
|
-
internal.total = row.c;
|
|
64
|
-
internal.processed = 0;
|
|
65
|
-
broadcastStatus();
|
|
66
|
-
await processLoop(db);
|
|
67
|
-
internal.state = 'done';
|
|
68
|
-
internal.finishedAt = new Date().toISOString();
|
|
69
|
-
broadcastStatus();
|
|
70
|
-
}
|
|
71
|
-
catch (err) {
|
|
72
|
-
internal.state = 'error';
|
|
73
|
-
internal.errorMessage = err instanceof Error ? err.message : String(err);
|
|
74
|
-
broadcastStatus();
|
|
75
|
-
throw err;
|
|
59
|
+
internal.state = 'idle';
|
|
76
60
|
}
|
|
77
61
|
finally {
|
|
78
62
|
isRunning = false;
|
|
79
63
|
}
|
|
80
64
|
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
const insertStmt = db.prepare('INSERT INTO ws_events (id, workspace_id, type, payload, session_id, created_at) VALUES (?, ?, ?, ?, ?, ?)');
|
|
90
|
-
const deleteStmt = db.prepare('DELETE FROM ws_events WHERE id = ?');
|
|
91
|
-
while (true) {
|
|
92
|
-
const rows = selectStmt.all(batchSize);
|
|
93
|
-
if (rows.length === 0)
|
|
94
|
-
break;
|
|
95
|
-
db.transaction(() => {
|
|
96
|
-
for (const r of rows) {
|
|
97
|
-
const events = convertRow(r.type, r.payload, { workspaceId: r.workspace_id });
|
|
98
|
-
for (const ev of events) {
|
|
99
|
-
insertStmt.run(nanoid(), r.workspace_id, 'agent:event', JSON.stringify(ev), r.session_id, r.created_at);
|
|
100
|
-
}
|
|
101
|
-
deleteStmt.run(r.id);
|
|
102
|
-
}
|
|
103
|
-
})();
|
|
104
|
-
internal.processed += rows.length;
|
|
105
|
-
broadcastStatus();
|
|
106
|
-
// Yield to the event loop
|
|
107
|
-
await new Promise((resolve) => setImmediate(resolve));
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
export function convertRow(type, payload, context) {
|
|
111
|
-
if (type === 'agent:status')
|
|
112
|
-
return []; // redundant — re-derivable from session events
|
|
113
|
-
if (type === 'agent:stderr') {
|
|
114
|
-
// Drop: the new engine only logs non-quota stderr via console.warn and
|
|
115
|
-
// does not persist it. Converting legacy stderr rows to error events
|
|
116
|
-
// would surface every historical Claude CLI warning ("no stdin data in
|
|
117
|
-
// 3s…", debug lines) as a UI-blocking banner. Quota-bearing stderr is
|
|
118
|
-
// handled live by the engine's backoff path, not via replay.
|
|
119
|
-
return [];
|
|
120
|
-
}
|
|
121
|
-
if (type === 'agent:output') {
|
|
122
|
-
try {
|
|
123
|
-
const parsed = JSON.parse(payload);
|
|
124
|
-
// The legacy payload may be either the raw Claude NDJSON already-parsed object,
|
|
125
|
-
// or a wrapper { type: 'raw', content: '...' } for non-JSON output. Handle both.
|
|
126
|
-
if (parsed && typeof parsed === 'object' && parsed.type === 'raw') {
|
|
127
|
-
return [{ kind: 'message:raw', content: String(parsed.content ?? '') }];
|
|
128
|
-
}
|
|
129
|
-
const state = createParserState();
|
|
130
|
-
const { events } = parseClaudeLine(JSON.stringify(parsed), state);
|
|
131
|
-
return events;
|
|
132
|
-
}
|
|
133
|
-
catch {
|
|
134
|
-
// Log enough to debug (first 200 chars of the bad payload + the owning
|
|
135
|
-
// workspace id when the caller passed one). We intentionally do not log
|
|
136
|
-
// the full payload to keep the console readable on noisy migrations.
|
|
137
|
-
const preview = payload.length > 200 ? `${payload.slice(0, 200)}…` : payload;
|
|
138
|
-
const ctx = context?.workspaceId ? ` (workspace=${context.workspaceId})` : '';
|
|
139
|
-
console.warn(`[content-migration] Could not parse agent:output payload${ctx}, falling back to message:raw. Preview: ${preview}`);
|
|
140
|
-
return [{ kind: 'message:raw', content: payload }];
|
|
141
|
-
}
|
|
142
|
-
}
|
|
65
|
+
/**
|
|
66
|
+
* Convert a legacy ws_events row into AgentEvents.
|
|
67
|
+
*
|
|
68
|
+
* The stream-parser has been removed; this function now skips every legacy
|
|
69
|
+
* type and returns an empty array. It is preserved as an export for API
|
|
70
|
+
* compatibility with old call sites and tests.
|
|
71
|
+
*/
|
|
72
|
+
export function convertRow(_type, _payload, _context) {
|
|
143
73
|
return [];
|
|
144
74
|
}
|
|
145
75
|
/** Test-only. */
|
|
@@ -18,7 +18,7 @@ function rowToPending(row) {
|
|
|
18
18
|
return { targetAt: row.target_at, reason: row.reason ?? undefined };
|
|
19
19
|
}
|
|
20
20
|
/** Schedule a wakeup for the given workspace. Replaces any existing pending wakeup. */
|
|
21
|
-
export function schedule(workspaceId, delaySeconds, prompt, reason) {
|
|
21
|
+
export function schedule(workspaceId, delaySeconds, prompt, reason, agentSessionId) {
|
|
22
22
|
try {
|
|
23
23
|
const clampedSeconds = clamp(Math.floor(delaySeconds), MIN_DELAY_SECONDS, MAX_DELAY_SECONDS);
|
|
24
24
|
const effectivePrompt = prompt === AUTONOMOUS_LOOP_SENTINEL ? AUTONOMOUS_LOOP_FALLBACK_PROMPT : prompt;
|
|
@@ -28,8 +28,8 @@ export function schedule(workspaceId, delaySeconds, prompt, reason) {
|
|
|
28
28
|
clearTimeout(existing);
|
|
29
29
|
const db = getDb();
|
|
30
30
|
db.prepare(`INSERT OR REPLACE INTO pending_wakeups
|
|
31
|
-
(workspace_id, target_at, prompt, reason, created_at)
|
|
32
|
-
VALUES (?, ?, ?, ?, ?)`).run(workspaceId, targetAtIso, effectivePrompt, reason ?? null, new Date().toISOString());
|
|
31
|
+
(workspace_id, target_at, prompt, reason, created_at, agent_session_id)
|
|
32
|
+
VALUES (?, ?, ?, ?, ?, ?)`).run(workspaceId, targetAtIso, effectivePrompt, reason ?? null, new Date().toISOString(), agentSessionId ?? null);
|
|
33
33
|
const timeout = setTimeout(() => fire(workspaceId), clampedSeconds * 1000);
|
|
34
34
|
timeout.unref?.();
|
|
35
35
|
timers.set(workspaceId, timeout);
|
|
@@ -125,7 +125,7 @@ function fire(workspaceId) {
|
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
const wsRow = db
|
|
128
|
-
.prepare(`SELECT project_path, working_branch, worktree_path, model,
|
|
128
|
+
.prepare(`SELECT project_path, working_branch, worktree_path, model, agent_permission_mode, reasoning_effort
|
|
129
129
|
FROM workspaces WHERE id = ?`)
|
|
130
130
|
.get(workspaceId);
|
|
131
131
|
if (!wsRow) {
|
|
@@ -133,12 +133,11 @@ function fire(workspaceId) {
|
|
|
133
133
|
return;
|
|
134
134
|
}
|
|
135
135
|
const worktreePath = wsRow.worktree_path ?? path.join(wsRow.project_path, '.worktrees', wsRow.working_branch);
|
|
136
|
-
//
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
const permissionMode = wsRow.permission_mode === 'plan' ? 'plan' : 'auto-accept';
|
|
136
|
+
// Narrow against the four known values; unknowns → 'bypass'.
|
|
137
|
+
const stored = wsRow.agent_permission_mode;
|
|
138
|
+
const agentPermissionMode = stored === 'plan' || stored === 'strict' || stored === 'interactive' ? stored : 'bypass';
|
|
140
139
|
try {
|
|
141
|
-
orchestrator.startAgent(workspaceId, worktreePath, row.prompt, wsRow.model, true,
|
|
140
|
+
orchestrator.startAgent(workspaceId, worktreePath, row.prompt, wsRow.model, true, agentPermissionMode, row.agent_session_id ?? undefined, wsRow.reasoning_effort);
|
|
142
141
|
emitEphemeral(workspaceId, 'wakeup:fired', {});
|
|
143
142
|
}
|
|
144
143
|
catch (err) {
|
|
@@ -6,9 +6,10 @@ import * as wakeupService from './wakeup-service.js';
|
|
|
6
6
|
/** Allowed status transitions per current status. Enforced by updateWorkspaceStatus. */
|
|
7
7
|
const VALID_TRANSITIONS = {
|
|
8
8
|
created: ['extracting', 'brainstorming', 'idle', 'error'],
|
|
9
|
-
extracting: ['extracting', 'brainstorming', 'idle', 'error'],
|
|
10
|
-
brainstorming: ['executing', 'completed', 'idle', 'error'],
|
|
11
|
-
executing: ['completed', 'idle', 'error', 'quota'],
|
|
9
|
+
extracting: ['extracting', 'brainstorming', 'idle', 'error', 'awaiting-user'],
|
|
10
|
+
brainstorming: ['executing', 'completed', 'idle', 'error', 'awaiting-user'],
|
|
11
|
+
executing: ['completed', 'idle', 'error', 'quota', 'awaiting-user'],
|
|
12
|
+
'awaiting-user': ['executing', 'brainstorming', 'extracting', 'idle', 'error', 'completed', 'quota'],
|
|
12
13
|
completed: ['idle', 'executing'],
|
|
13
14
|
idle: ['executing', 'brainstorming', 'extracting', 'error'],
|
|
14
15
|
error: ['idle', 'executing', 'brainstorming', 'extracting'],
|
|
@@ -19,6 +20,17 @@ const VALID_TRANSITIONS = {
|
|
|
19
20
|
// is untyped, so we intentionally do not narrow here — validation against
|
|
20
21
|
// `listEngines()` is expected to happen at workspace creation (see the
|
|
21
22
|
// routes/engines handler) and when resolving an engine at agent-start time.
|
|
23
|
+
/**
|
|
24
|
+
* Coerce a raw `agent_permission_mode` cell into the typed union.
|
|
25
|
+
* Falls back to `bypass` for unknown / null values — guarantees callers
|
|
26
|
+
* always get a valid SDK-mappable mode regardless of legacy or corrupted rows.
|
|
27
|
+
*/
|
|
28
|
+
function coerceAgentPermissionMode(raw) {
|
|
29
|
+
if (raw === 'plan' || raw === 'bypass' || raw === 'strict' || raw === 'interactive') {
|
|
30
|
+
return raw;
|
|
31
|
+
}
|
|
32
|
+
return 'bypass';
|
|
33
|
+
}
|
|
22
34
|
function mapWorkspace(row) {
|
|
23
35
|
return {
|
|
24
36
|
id: row.id,
|
|
@@ -32,7 +44,7 @@ function mapWorkspace(row) {
|
|
|
32
44
|
sentryUrl: row.sentry_url,
|
|
33
45
|
model: row.model,
|
|
34
46
|
reasoningEffort: row.reasoning_effort ?? 'auto',
|
|
35
|
-
|
|
47
|
+
agentPermissionMode: coerceAgentPermissionMode(row.agent_permission_mode),
|
|
36
48
|
devServerStatus: row.dev_server_status,
|
|
37
49
|
hasUnread: row.has_unread === 1,
|
|
38
50
|
archivedAt: row.archived_at,
|
|
@@ -42,7 +54,6 @@ function mapWorkspace(row) {
|
|
|
42
54
|
autoLoop: row.auto_loop === 1,
|
|
43
55
|
autoLoopReady: row.auto_loop_ready === 1,
|
|
44
56
|
noProgressStreak: row.no_progress_streak ?? 0,
|
|
45
|
-
permissionProfile: (row.permission_profile ?? 'bypass'),
|
|
46
57
|
worktreePath: row.worktree_path ?? '',
|
|
47
58
|
worktreeOwned: row.worktree_owned === 1,
|
|
48
59
|
createdAt: row.created_at,
|
|
@@ -82,13 +93,18 @@ export function createWorkspace(data) {
|
|
|
82
93
|
const id = nanoid();
|
|
83
94
|
const computedWorktreePath = data.worktreePath ?? `${data.projectPath}/.worktrees/${data.workingBranch}`;
|
|
84
95
|
const owned = data.worktreeOwned ?? true;
|
|
96
|
+
// Mirror the unified mode into the legacy columns so older readers (in-flight
|
|
97
|
+
// requests during deploy, external scripts) still see a sane value.
|
|
98
|
+
const unifiedMode = data.agentPermissionMode ?? 'bypass';
|
|
99
|
+
const legacyMode = unifiedMode === 'plan' ? 'plan' : 'auto-accept';
|
|
100
|
+
const legacyProfile = unifiedMode === 'plan' ? 'bypass' : unifiedMode;
|
|
85
101
|
db.prepare(`
|
|
86
102
|
INSERT INTO workspaces (
|
|
87
103
|
id, name, project_path, source_branch, working_branch, status,
|
|
88
104
|
notion_url, notion_page_id, sentry_url, worktree_path, worktree_owned,
|
|
89
|
-
model, reasoning_effort, permission_mode, engine, created_at, updated_at
|
|
90
|
-
) VALUES (?, ?, ?, ?, ?, 'created', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
91
|
-
`).run(id, data.name, data.projectPath, data.sourceBranch, data.workingBranch, data.notionUrl ?? null, data.notionPageId ?? null, data.sentryUrl ?? null, computedWorktreePath, owned ? 1 : 0, data.model ?? 'claude-opus-4-7', data.reasoningEffort ?? 'auto',
|
|
105
|
+
model, reasoning_effort, permission_mode, permission_profile, agent_permission_mode, engine, created_at, updated_at
|
|
106
|
+
) VALUES (?, ?, ?, ?, ?, 'created', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
107
|
+
`).run(id, data.name, data.projectPath, data.sourceBranch, data.workingBranch, data.notionUrl ?? null, data.notionPageId ?? null, data.sentryUrl ?? null, computedWorktreePath, owned ? 1 : 0, data.model ?? 'claude-opus-4-7', data.reasoningEffort ?? 'auto', legacyMode, legacyProfile, unifiedMode, data.engine ?? 'claude-code', now, now);
|
|
92
108
|
return getWorkspace(id);
|
|
93
109
|
}
|
|
94
110
|
/** Fetch a single workspace by ID, or null if not found. */
|
|
@@ -212,13 +228,21 @@ export function updateWorktreePath(id, newPath) {
|
|
|
212
228
|
}
|
|
213
229
|
return getWorkspace(id);
|
|
214
230
|
}
|
|
215
|
-
/**
|
|
216
|
-
|
|
231
|
+
/**
|
|
232
|
+
* Update the agent's unified permission mode (plan | bypass | strict | interactive).
|
|
233
|
+
*
|
|
234
|
+
* Also writes the legacy `permission_mode` and `permission_profile` columns to
|
|
235
|
+
* keep them coherent with the new value — they remain readable by legacy code
|
|
236
|
+
* paths during deploy. The unified column is the source of truth.
|
|
237
|
+
*/
|
|
238
|
+
export function updateAgentPermissionMode(id, mode) {
|
|
217
239
|
const db = getDb();
|
|
218
240
|
const now = new Date().toISOString();
|
|
241
|
+
const legacyMode = mode === 'plan' ? 'plan' : 'auto-accept';
|
|
242
|
+
const legacyProfile = mode === 'plan' ? 'bypass' : mode;
|
|
219
243
|
const result = db
|
|
220
|
-
.prepare('UPDATE workspaces SET permission_mode = ?, updated_at = ? WHERE id = ?')
|
|
221
|
-
.run(
|
|
244
|
+
.prepare('UPDATE workspaces SET agent_permission_mode = ?, permission_mode = ?, permission_profile = ?, updated_at = ? WHERE id = ?')
|
|
245
|
+
.run(mode, legacyMode, legacyProfile, now, id);
|
|
222
246
|
if (result.changes === 0) {
|
|
223
247
|
throw new Error(`Workspace '${id}' not found`);
|
|
224
248
|
}
|
|
@@ -249,6 +273,10 @@ export function deleteWorkspace(id) {
|
|
|
249
273
|
// churn. The Map has no FK to clean up for it automatically.
|
|
250
274
|
orchestrator.forgetRateLimitInfo(id);
|
|
251
275
|
orchestrator.forgetTasksDoneSnapshot(id);
|
|
276
|
+
orchestrator.forgetResumeFailed(id);
|
|
277
|
+
orchestrator.forgetPendingQueue(id);
|
|
278
|
+
orchestrator.forgetPreAwaitStatus(id);
|
|
279
|
+
orchestrator.forgetSessionId(id);
|
|
252
280
|
autoLoopService.forgetAutoLoopState(id);
|
|
253
281
|
const db = getDb();
|
|
254
282
|
db.prepare('DELETE FROM workspaces WHERE id = ?').run(id);
|
|
@@ -373,30 +401,6 @@ export function setAutoLoopReady(id, ready) {
|
|
|
373
401
|
db.prepare('UPDATE workspaces SET auto_loop_ready = ? WHERE id = ?').run(ready ? 1 : 0, id);
|
|
374
402
|
return getWorkspace(id);
|
|
375
403
|
}
|
|
376
|
-
/**
|
|
377
|
-
* Set the permission profile for a workspace.
|
|
378
|
-
*
|
|
379
|
-
* - `bypass` (default): Kōbō passes `--dangerously-skip-permissions` — no
|
|
380
|
-
* prompts, but the CLI hard-denies writes under `.claude/**` and
|
|
381
|
-
* `.github/workflows/**` regardless of the project's settings.json.
|
|
382
|
-
* - `strict`: Kōbō passes `--permission-mode acceptEdits` — the CLI respects
|
|
383
|
-
* the project's `.claude/settings.json` allow/deny lists. Enables writes
|
|
384
|
-
* under `.claude/**` / `.github/workflows/**` when the user has explicitly
|
|
385
|
-
* allowed them, at the cost of potential prompts on un-allow-listed Bash
|
|
386
|
-
* or MCP calls.
|
|
387
|
-
*
|
|
388
|
-
* Takes effect on the next session spawn — running sessions keep whichever
|
|
389
|
-
* flag they were started with.
|
|
390
|
-
*/
|
|
391
|
-
export function setPermissionProfile(id, profile) {
|
|
392
|
-
const workspace = getWorkspace(id);
|
|
393
|
-
if (!workspace)
|
|
394
|
-
throw new Error(`Workspace '${id}' not found`);
|
|
395
|
-
const db = getDb();
|
|
396
|
-
const now = new Date().toISOString();
|
|
397
|
-
db.prepare('UPDATE workspaces SET permission_profile = ?, updated_at = ? WHERE id = ?').run(profile, now, id);
|
|
398
|
-
return getWorkspace(id);
|
|
399
|
-
}
|
|
400
404
|
/** Remove a workspace from favorites. Idempotent: safe to call on a non-favorite, though `updated_at` still refreshes. */
|
|
401
405
|
export function unsetFavorite(id) {
|
|
402
406
|
const db = getDb();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.7.0",
|
|
4
4
|
"description": "Kōbō — multi-workspace agent manager for Claude Code. Orchestrates isolated git worktrees with dev servers, Notion integration, and MCP tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
"prepublishOnly": "npm run build"
|
|
67
67
|
},
|
|
68
68
|
"dependencies": {
|
|
69
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.126",
|
|
69
70
|
"@hono/node-server": "^1.19.13",
|
|
70
71
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
71
72
|
"better-sqlite3": "^12.8.0",
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import{E as e,F as t,H as n,L as r,M as i,Q as a,U as o,_t as s,bt as c,d as l,f as u,g as d,h as f,l as p,p as m,r as h,rt as g,u as _,v,yt as y}from"./runtime-core.esm-bundler-C3IgBgY5.js";import{L as b,l as x,t as S}from"./QIcon-B0-pH3Qs.js";import{t as C}from"./settings-Dbx1_ksA.js";import{t as w}from"./QBtn-DHwAb18J.js";import{n as T}from"./vue-i18n-eUDnMrPl.js";import{d as E,g as D,l as O,p as k}from"./index-C_e7KOYh.js";import{t as A}from"./QSpinnerDots-DwtnRN2r.js";import{t as j}from"./QTooltip-DjJYMTkN.js";import{t as M}from"./QExpansionItem-VS4b4eY6.js";import{t as N}from"./QScrollArea-DrVTDLU0.js";import{n as P,t as F}from"./marked.esm-DuOsJx63.js";import{t as I}from"./documents-D6A3wRry.js";import{t as L}from"./_plugin-vue_export-helper-B8bB5DBd.js";function ee(e,t,n=!0){let r=[],i=new Map,a=new Map;for(let n=0;n<e.length;n++){let o=e[n],s=t?.[n];switch(o.kind){case`message:text`:{let e=i.get(o.messageId);if(e)e.text+=o.text,e.streaming=o.streaming;else{let e={type:`text`,messageId:o.messageId,text:o.text,streaming:o.streaming,ts:s};i.set(o.messageId,e),r.push(e)}break}case`message:end`:{let e=i.get(o.messageId);e&&(e.streaming=!1);break}case`message:thinking`:r.push({type:`thinking`,messageId:o.messageId,text:o.text,ts:s});break;case`tool:call`:{let e={type:`tool`,toolCallId:o.toolCallId,name:o.name,input:o.input,ts:s};a.set(o.toolCallId,e),r.push(e);break}case`tool:result`:{let e=a.get(o.toolCallId);e&&(e.result={output:o.output,isError:o.isError});break}case`session:started`:r.push({type:`session`,kind:`started`,detail:{engineSessionId:o.engineSessionId,model:o.model},ts:s});break;case`session:ended`:r.push({type:`session`,kind:`ended`,detail:{reason:o.reason,exitCode:o.exitCode},ts:s});break;case`session:compacted`:r.push({type:`session`,kind:`compacted`,ts:s});break;case`session:brainstorm-complete`:case`session:user-input-requested`:case`message:raw`:case`skills:discovered`:case`usage`:case`rate_limit`:case`subagent:progress`:case`error`:break;default:}}let o=null;for(let e of r)e.type===`text`&&e.streaming&&(o&&(o.streaming=!1),o=e);return o&&!n&&(o.streaming=!1),r}function te(e,t){if(t.length===0)return e;let n=t.map(e=>({type:`user`,content:e.content,sender:e.sender,ts:e.ts})),r=[...e,...n];r.sort((e,t)=>{let n=e.ts??``,r=t.ts??``;return n===r?0:n?r?n<r?-1:1:-1:1});let i;for(let e of r)e.type===`user`&&e.sender!==`system-prompt`&&e.ts&&(!i||e.ts>i)&&(i=e.ts);if(i)for(let e of r)e.type===`text`&&e.streaming&&(!e.ts||e.ts<i)&&(e.streaming=!1);return r}function R(e){switch(e.type){case`user`:return e.sender===`system-prompt`?`system-prompt`:`user`;case`session`:return`session`;default:return`agent`}}function ne(e){let t=[],n=null;for(let r of e){let e=R(r),i=e===`session`||e===`system-prompt`;!n||n.speaker!==e||i?(n={speaker:e,ts:r.ts,items:[r]},t.push(n),i&&(n=null)):n.items.push(r)}return t}var z={class:`text-caption text-grey-6`},B=v({__name:`SessionEventItem`,props:{item:{}},setup(e){let n=e,r=p(()=>{switch(n.item.kind){case`started`:return`session.started`;case`ended`:return`session.ended`;case`compacted`:return`session.compacted`;default:return`session.started`}});return(e,n)=>(t(),m(`span`,z,c(e.$t(r.value)),1))}});function V(e,t){if(t.length===0||e.length===0)return e;let n=[...t].sort((e,t)=>t.length-e.length),r=new DOMParser().parseFromString(`<div>${e}</div>`,`text/html`),i=r.body.firstChild;if(!i)return e;function a(e){if(e.nodeType===Node.TEXT_NODE){H(e,n,r);return}if(e.nodeName===`A`)return;let t=Array.from(e.childNodes);for(let e of t)a(e)}return a(i),i.innerHTML}function H(e,t,n){let r=e.textContent??``;if(!t.some(e=>r.includes(e)))return;let i=n.createDocumentFragment(),a=0;for(;a<r.length;){let e=U(r,a,t);if(!e){i.appendChild(n.createTextNode(r.slice(a)));break}e.index>a&&i.appendChild(n.createTextNode(r.slice(a,e.index)));let o=n.createElement(`a`);o.className=`document-link`,o.setAttribute(`data-document-path`,e.path),o.setAttribute(`href`,`#`),o.textContent=e.path,i.appendChild(o),a=e.index+e.path.length}e.parentNode?.replaceChild(i,e)}function U(e,t,n){let r=null;for(let i of n){let n=e.indexOf(i,t);n<0||(!r||n<r.index||n===r.index&&i.length>r.path.length)&&(r={index:n,path:i})}return r}var re=[`innerHTML`],W=L(v({__name:`TextMessageItem`,props:{item:{}},setup(e){let n=e,r=I(),i=O(),a=p(()=>{let e=i.selectedWorkspaceId;return e?r.documentsFor(e).map(e=>e.path):[]}),o=p(()=>{let e=V(F.parse(n.item.text,{async:!1,breaks:!0,gfm:!0}),a.value);return P.sanitize(e,{ADD_ATTR:[`data-document-path`]})});function s(e){let t=e.target?.closest(`.document-link`);if(!t)return;e.preventDefault();let n=t.getAttribute(`data-document-path`),a=i.selectedWorkspaceId;!n||!a||r.openDocumentByPath(a,n)}return(n,r)=>(t(),m(`div`,{class:`markdown-message`,onClick:s},[_(`div`,{innerHTML:o.value},null,8,re),e.item.streaming?(t(),l(x,{key:0,size:`xs`,class:`q-ml-xs`})):u(``,!0)]))}}),[[`__scopeId`,`data-v-e9f9bd11`]]),ie={key:0,class:`text-caption text-grey-5`,style:{"font-style":`italic`}},G=[`innerHTML`],ae={key:1,style:{"white-space":`pre-wrap`}},oe=L(v({__name:`ThinkingItem`,props:{item:{}},setup(e){let n=e,r=p(()=>n.item.text.trim().slice(0,100)),i=p(()=>n.item.text.trim().length>0),a=p(()=>n.item.text.trim().length>100),s=p(()=>{let e=F.parse(n.item.text,{async:!1,breaks:!0,gfm:!0});return P.sanitize(e)});return(n,d)=>i.value?(t(),m(`div`,ie,[a.value?(t(),l(M,{key:0,dense:``,"dense-toggle":``,label:r.value,"header-class":`text-grey-5 text-caption`,style:{"font-style":`italic`}},{default:o(()=>[_(`div`,{class:`q-py-xs markdown-thinking`,innerHTML:s.value},null,8,G)]),_:1},8,[`label`])):(t(),m(`span`,ae,c(e.item.text),1))])):u(``,!0)}}),[[`__scopeId`,`data-v-4e64694c`]]);function K(e,t){let n=e.split(`
|
|
2
|
+
`),r=t.split(`
|
|
3
|
+
`),i=n.length,a=r.length,o=Array.from({length:i+1},()=>Array(a+1).fill(0));for(let e=i-1;e>=0;e--)for(let t=a-1;t>=0;t--)n[e]===r[t]?o[e][t]=o[e+1][t+1]+1:o[e][t]=Math.max(o[e+1][t],o[e][t+1]);let s=[],c=0,l=0;for(;c<i&&l<a;)n[c]===r[l]?(s.push({type:`context`,content:n[c]}),c++,l++):o[c+1][l]>=o[c][l+1]?(s.push({type:`del`,content:n[c]}),c++):(s.push({type:`add`,content:r[l]}),l++);for(;c<i;)s.push({type:`del`,content:n[c++]});for(;l<a;)s.push({type:`add`,content:r[l++]});return s}function se(e,t){if(!t||typeof t!=`object`)return null;let n=t;if(e===`Edit`){let e=n.file_path;if(!e)return null;let t=n.old_string??``,r=n.new_string??``;return{toolName:`Edit`,filePath:e,oldString:t,newString:r,replaceAll:n.replace_all??!1,additions:r?r.split(`
|
|
4
|
+
`).length:0,deletions:t?t.split(`
|
|
5
|
+
`).length:0}}if(e===`Write`){let e=n.file_path;if(!e)return null;let t=n.content??``;return{toolName:`Write`,filePath:e,content:t,additions:t?t.split(`
|
|
6
|
+
`).length:0,deletions:0}}if(e===`Bash`){let e=(n.command??``).match(/^\s*rm\s+(?:-[a-zA-Z]*\s+)*(.+)/);if(e)return{toolName:`Bash:rm`,filePath:e[1].trim().replace(/["']/g,``),additions:0,deletions:1}}return null}function q(e,t){if(!e||!t?.projectPath)return e;let n=J(e,`${t.projectPath}/.worktrees/${t.workingBranch}`);return n===e&&(n=J(e,t.projectPath)),n}function J(e,t){if(!t)return e;let n=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return e.replace(RegExp(`${n}/`,`g`),``).replace(RegExp(`${n}(?=\\s|$|["'\`])`,`g`),`.`)}var ce={class:`tool-name`},le=[`title`],ue={key:0,class:`tool-stat-add`},Y={key:1,class:`tool-stat-del`},X={class:`diff-sign`},de={class:`tool-name`},fe=[`title`],Z=L(v({__name:`ToolCallItem`,props:{item:{}},setup(e){let i=e,o=a(!1),g=O(),v=p(()=>se(i.item.name,i.item.input)),y=p(()=>v.value?q(v.value.filePath,g.selectedWorkspace):``),x={Bash:`terminal`,Read:`description`,Edit:`edit`,Write:`edit_note`,MultiEdit:`edit`,Glob:`folder_open`,Grep:`manage_search`,LS:`list`,Skill:`auto_awesome`,Task:`hub`,Agent:`hub`,TodoWrite:`checklist`,TodoRead:`checklist`,ToolSearch:`search`,WebFetch:`public`,WebSearch:`travel_explore`,NotebookRead:`book`,NotebookEdit:`edit_note`,SendMessage:`send`,ExitPlanMode:`check_circle_outline`,KillShell:`stop_circle`,BashOutput:`terminal`},C=p(()=>x[i.item.name]??`build`),w=p(()=>{if(v.value)return``;let e=i.item.input,t=T(e);return t?q(t,g.selectedWorkspace):``});function T(e){if(!e||typeof e!=`object`)return typeof e==`string`?e:``;let t=e;for(let e of[`file_path`,`path`,`command`,`pattern`,`query`,`url`,`skill`,`description`,`subject`,`prompt`]){let n=t[e];if(typeof n==`string`&&n.length>0)return n}for(let e of Object.values(t))if(typeof e==`string`&&e.length>0)return e;return``}let E=p(()=>{let e=v.value;return e?e.toolName===`Edit`&&e.oldString!==void 0&&e.newString!==void 0?K(e.oldString,e.newString):e.toolName===`Write`&&e.content!==void 0?e.content.split(`
|
|
7
|
+
`).map(e=>({type:`add`,content:e})):e.toolName===`Bash:rm`?[{type:`del`,content:`File deleted`}]:null:null}),D=p(()=>{let e=i.item.result;if(!e)return``;if(typeof e.output==`string`)return e.output;try{return JSON.stringify(e.output)}catch{return String(e.output)}}),k=new Set([`Read`]),A=p(()=>!!(i.item.result&&D.value)&&(!k.has(i.item.name)||i.item.result?.isError===!0));function j(){o.value=!o.value}return n(()=>i.item.result?.isError===!0,e=>{e&&(o.value=!0)},{immediate:!0}),(n,i)=>v.value?(t(),m(`div`,{key:0,class:s([`tool-row`,{"tool-row-expanded":o.value}])},[_(`div`,{class:`tool-header`,onClick:j},[d(S,{name:C.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),_(`span`,ce,c(v.value.toolName===`Bash:rm`?`Bash`:v.value.toolName),1),_(`span`,{class:`tool-path`,title:v.value.filePath},c(y.value),9,le),v.value.additions>0?(t(),m(`span`,ue,`+`+c(v.value.additions),1)):u(``,!0),v.value.deletions>0?(t(),m(`span`,Y,`-`+c(v.value.deletions),1)):u(``,!0),e.item.result?.isError?(t(),l(S,{key:2,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-xs`})):e.item.result?(t(),l(S,{key:3,name:`check`,color:`positive`,size:`xs`,class:`q-ml-xs`})):u(``,!0),d(S,{name:o.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-auto text-grey-6`},null,8,[`name`])]),o.value&&E.value?(t(),m(`div`,{key:0,class:`tool-diff`,onClick:i[0]||=b(()=>{},[`stop`])},[(t(!0),m(h,null,r(E.value,(e,n)=>(t(),m(`div`,{key:n,class:s([`diff-line`,{"diff-del":e.type===`del`,"diff-add":e.type===`add`,"diff-context":e.type===`context`}])},[_(`span`,X,c(e.type===`del`?`-`:e.type===`add`?`+`:` `),1),f(c(e.content),1)],2))),128))])):u(``,!0)],2)):(t(),m(`div`,{key:1,class:s([`tool-row tool-row-generic`,{"tool-row-expanded":o.value,"tool-row--toggleable":A.value}])},[_(`div`,{class:`tool-header`,onClick:i[1]||=e=>A.value&&j()},[d(S,{name:C.value,size:`14px`,class:`tool-icon`},null,8,[`name`]),_(`span`,de,c(e.item.name),1),w.value?(t(),m(`span`,{key:0,class:`tool-arg`,title:T(e.item.input)||w.value},c(w.value),9,fe)):u(``,!0),e.item.result?.isError?(t(),l(S,{key:1,name:`error_outline`,color:`negative`,size:`xs`,class:`q-ml-auto`})):e.item.result?(t(),l(S,{key:2,name:`check`,color:`positive`,size:`xs`,class:`q-ml-auto`})):u(``,!0),A.value?(t(),l(S,{key:3,name:o.value?`expand_less`:`expand_more`,size:`xs`,class:`q-ml-xs text-grey-6`},null,8,[`name`])):u(``,!0)]),o.value&&A.value?(t(),m(`div`,{key:0,class:`tool-output`,onClick:i[2]||=b(()=>{},[`stop`])},c(D.value),1)):u(``,!0)],2))}}),[[`__scopeId`,`data-v-b1fcd20d`]]);function Q(e,t){return t?e.replace(/\[image:\s+([^\]]+)\]/g,(e,n)=>{let r=String(n).trim();return/^(\.ai\/images\/|images\/)/.test(r)?`}/images/file?path=${encodeURIComponent(r)}`})`:e}):e}var $=[`innerHTML`],pe=[`innerHTML`],me=[`src`],he=L(v({__name:`UserMessageItem`,props:{item:{}},setup(e){let n=e,r=O(),i=p(()=>n.item.sender===`system-prompt`),s=p(()=>{let e=Q(n.item.content,r.selectedWorkspaceId??``),t=F.parse(e,{async:!1,breaks:!0,gfm:!0});return P.sanitize(t)}),c=a(null),f=a(!1);function g(e){let t=e.target;if(t?.tagName!==`IMG`)return;let n=t;n.src&&(c.value=n.src,f.value=!0)}return(e,n)=>(t(),m(h,null,[i.value?(t(),l(M,{key:0,dense:``,"dense-toggle":``,label:e.$t(`chat.systemPrompt`),"header-class":`text-grey-5 text-caption`},{default:o(()=>[_(`div`,{class:`q-py-xs markdown-user-prompt`,innerHTML:s.value},null,8,$)]),_:1},8,[`label`])):(t(),m(`div`,{key:1,class:`markdown-message`,onClick:g},[_(`div`,{innerHTML:s.value},null,8,pe)])),d(D,{modelValue:f.value,"onUpdate:modelValue":n[1]||=e=>f.value=e},{default:o(()=>[c.value?(t(),m(`img`,{key:0,src:c.value,alt:``,class:`image-lightbox-img`,onClick:n[0]||=e=>f.value=!1},null,8,me)):u(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-c2e7c407`]]),ge={class:`turn-header`},_e={key:0,class:`turn-time`},ve={class:`turn-time turn-time-updated`},ye={key:2,class:`turn-actions`},be={class:`turn-body`},xe={key:0,class:`turn-scroll-top`},Se=L(v({__name:`TurnCard`,props:{turn:{}},emits:[`scrollTo`],setup(e,{emit:n}){let i=e,v=n,{t:b}=T(),x=a(null);function C(){let e=x.value;if(!e)return;let t=e.closest(`.q-scrollarea`)?.querySelector(`.q-scrollarea__content`);if(!t){e.scrollIntoView({behavior:`smooth`,block:`start`});return}let n=e.getBoundingClientRect().top-t.getBoundingClientRect().top;v(`scrollTo`,Math.max(0,n-8))}let E=p(()=>{switch(i.turn.speaker){case`user`:return{label:b(`chat.you`),accent:`#ce93d8`,badgeClass:`turn-badge-user`};case`agent`:return{label:b(`chat.agent`),accent:`#7986cb`,badgeClass:`turn-badge-agent`};case`system-prompt`:return{label:b(`chat.systemPrompt`),accent:`#757575`,badgeClass:`turn-badge-system`};case`session`:return{label:b(`chat.session`),accent:`#616161`,badgeClass:`turn-badge-session`}}});function D(e,t=!1){if(!e)return``;let n=new Date(e);return Number.isNaN(n.getTime())?``:n.toLocaleTimeString(void 0,t?{hour:`2-digit`,minute:`2-digit`,second:`2-digit`}:{hour:`2-digit`,minute:`2-digit`})}let O=p(()=>D(i.turn.ts)),k=p(()=>{let e=i.turn.items;if(e.length===0)return null;for(let t=e.length-1;t>=0;t--){let n=e[t].ts;if(n)return n}return null}),A=p(()=>{let e=i.turn.ts,t=k.value;if(!t||!e||t===e)return``;let n=new Date(e).getTime(),r=new Date(t).getTime();return Number.isNaN(n)||Number.isNaN(r)||r<=n?``:D(t,r-n<6e4)}),M=p(()=>A.value!==``),N=p(()=>i.turn.items.filter(e=>e.type===`tool`).length);return(n,i)=>(t(),m(`div`,{ref_key:`cardEl`,ref:x,class:s([`turn-card`,{"turn-card--user":e.turn.speaker===`user`}]),style:y({"--turn-accent":E.value.accent})},[_(`div`,ge,[_(`span`,{class:s([`turn-badge`,E.value.badgeClass])},c(E.value.label),3),O.value?(t(),m(`span`,_e,c(O.value),1)):u(``,!0),M.value?(t(),m(h,{key:1},[d(S,{name:`arrow_forward`,size:`10px`,color:`grey-7`,class:`turn-time-arrow`}),_(`span`,ve,[f(c(A.value)+` `,1),d(j,null,{default:o(()=>[f(c(g(b)(`chat.lastUpdatedAt`,{time:A.value})),1)]),_:1})])],64)):u(``,!0),N.value>0?(t(),m(`span`,ye,` · `+c(g(b)(`chat.nActions`,{n:N.value})),1)):u(``,!0)]),_(`div`,be,[(t(!0),m(h,null,r(e.turn.items,(e,n)=>(t(),m(h,{key:n},[e.type===`text`?(t(),l(W,{key:0,item:e},null,8,[`item`])):e.type===`thinking`?(t(),l(oe,{key:1,item:e},null,8,[`item`])):e.type===`tool`?(t(),l(Z,{key:2,item:e},null,8,[`item`])):e.type===`user`?(t(),l(he,{key:3,item:e},null,8,[`item`])):e.type===`session`?(t(),l(B,{key:4,item:e},null,8,[`item`])):u(``,!0)],64))),128))]),e.turn.items.length>4?(t(),m(`div`,xe,[d(w,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`grey-6`,class:`turn-scroll-top-btn`,onClick:C},{default:o(()=>[d(j,null,{default:o(()=>[f(c(g(b)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):u(``,!0)],6))}}),[[`__scopeId`,`data-v-4729e0cc`]]),Ce={key:0,class:`activity-feed-switching`},we={key:1,class:`activity-feed-wrap`},Te={key:0,class:`text-center q-py-sm text-caption text-grey-6`},Ee={class:`q-pa-md`},De={key:1,class:`q-px-md q-pb-md`},Oe={class:`activity-feed-nav-cluster`},ke=60,Ae=200,je=200,Me=400,Ne=200,Pe=L(v({__name:`ActivityFeed`,props:{workspaceId:{}},setup(s){let g=s,v=k(),y=C(),b=O(),S=p(()=>b.selectedSessionId),T=p(()=>b.sessions.find(e=>e.id===S.value)?.engineSessionId??null),D=p(()=>{let e=b.sessions;return e.length===0?!1:S.value===e[e.length-1].id});function j(e){return S.value?e?e===S.value||e===T.value:D.value:!0}let P=p(()=>(b.activityFeeds[g.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&j(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,ts:e.timestamp,sessionId:e.sessionId}))),F=p(()=>E(b.workspaces.find(e=>e.id===g.workspaceId)?.status)),I=p(()=>{let e=v.eventsFor(g.workspaceId),t=v.timestampsFor(g.workspaceId),n=v.sessionIdsFor(g.workspaceId),r=[],i=[];for(let a=0;a<e.length;a++)j(n[a])&&(r.push(e[a]),i.push(t[a]));let a=te(ee(r,i,F.value),P.value);return ne(y.showVerboseSystemMessages?a:a.filter(e=>e.type!==`session`))}),L=p(()=>y.showVerboseSystemMessages?v.eventsFor(g.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),R=a(null),z=a(!0),B=a(!1),V=!1,H=a(!0),U=a(new Map);function re(e){z.value=e.verticalSize-e.verticalPosition-e.verticalContainerSize<=ke,V&&e.verticalPosition<=Ae&&!B.value&&ie()&&oe()}function W(e,t){return`${e}:${t}`}function ie(){let e=S.value;return e?U.value.get(W(g.workspaceId,e))??!0:v.hasMoreOlderFor(g.workspaceId)}function G(e,t,n){U.value.set(W(e,t),n)}function ae(e){if(!S.value)return v.oldestIdFor(e);let t=v.eventIdsFor(e),n=v.sessionIdsFor(e);for(let e=0;e<t.length;e++){if(!j(n[e]))continue;let r=t[e];if(r)return r}}async function oe(){let t=g.workspaceId,n=S.value,r=ae(t);if(!r)return;B.value=!0;let i=Date.now();try{let i=R.value,a=i?.getScroll().verticalSize??0,o=i?.getScroll().verticalPosition??0,s=new URLSearchParams({before:r,limit:`200`});n&&s.set(`session`,n);let c=fetch(`/api/workspaces/${t}/events?${s.toString()}`),l=new Promise(e=>setTimeout(e,je)),[u]=await Promise.all([c,l]);if(!u.ok){n?G(t,n,!1):v.prepend(t,[],[],{oldestId:r,hasMoreOlder:!1});return}let d=await u.json(),f=d.events??[],p=f.filter(e=>e.type===`agent:event`&&e.workspaceId===t),m=f.filter(e=>e.type===`user:message`&&e.workspaceId===t),h=p.map(e=>e.payload),g=p.map(e=>e.createdAt),_=p.map(e=>e.sessionId??null),y=p.map(e=>e.id),x=f.length>0?f[0].id:r;n&&G(t,n,d.hasMore),v.prepend(t,h,g,{oldestId:x,hasMoreOlder:n?v.hasMoreOlderFor(t):d.hasMore,sessionIds:_,eventIds:y});for(let e of m){let n=e.payload;typeof n.content==`string`&&b.addActivityItem(t,{id:e.id,type:`text`,content:n.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:n.sender??`user`}})}if(await e(),i){let e=i.getScroll().verticalSize-a,t=Math.max(o+e,Ae+50);i.setScrollPosition(`vertical`,t,0)}}catch(e){console.error(`[ActivityFeed] failed to load older events:`,e)}finally{let e=Date.now()-i,t=Math.max(0,je-e);await new Promise(e=>setTimeout(e,t+Me)),B.value=!1}}async function K(t=0){await e();let n=R.value;if(!n)return;let r=n.getScroll();n.setScrollPosition(`vertical`,r.verticalSize,t)}function se(e){let t=R.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}let q=a([]),J=a(null);function ce(){let e=I.value,t=q.value,n=[];if(t.length===e.length){for(let r=0;r<e.length;r++){if(e[r].speaker!==`user`)continue;let i=t[r]?.$el;i&&n.push(i)}if(n.length>0)return n}let r=J.value?.parentElement;if(r){let e=r.querySelectorAll(`.turn-card--user`);for(let t of e)n.push(t)}return n}function le(){let e=R.value;if(!e)return null;let t=J.value;if(!t)return null;let n=e.getScroll().verticalPosition,r=t.getBoundingClientRect().top,i=null;for(let e of ce()){let t=e.getBoundingClientRect().top-r;if(t<n-40)i=t;else break}return i}async function ue(){let t=R.value;if(!t)return;let n=le();if(n===null)for(let t=0;t<15&&ie();t++){for(;B.value;)await new Promise(e=>setTimeout(e,50));if(await oe(),await e(),n=le(),n!==null)break}n!==null&&t.setScrollPosition(`vertical`,Math.max(0,n-12),250)}async function Y(){V=!1,await e(),await K(0),requestAnimationFrame(()=>{requestAnimationFrame(()=>{V=!0})})}let X=p(()=>{let e=v.sessionIdsFor(g.workspaceId);if(!S.value)return e.length;let t=0;for(let n of e)j(n)&&t++;return t}),de=p(()=>v.eventsFor(g.workspaceId).length);async function fe(){H.value=!0;let e=Date.now();await new Promise(e=>setTimeout(e,Ne));let t=e+5e3;for(;de.value===0&&Date.now()<t;)await new Promise(e=>setTimeout(e,50));H.value=!1}n(H,async e=>{!e&&X.value>0&&await Y(),!e&&X.value===0&&S.value&&$()}),i(()=>{fe(),X.value>0&&Y(),S.value&&$()});let Z=!1;n(X,async(e,t)=>{if(!Z&&e>0){Z=!0,await Y();return}e>t&&z.value&&!B.value&&await K(180)}),n(()=>g.workspaceId,()=>{z.value=!0,Z=!1,V=!1,fe(),X.value>0&&Y()}),n(()=>b.selectedSessionId,async()=>{z.value=!0,V=!1,await Y(),$()});let Q=new Set;async function $(){let t=S.value;if(!t||X.value>0)return;let n=W(g.workspaceId,t);if(!Q.has(n)){Q.add(n);try{let n=await fetch(`/api/workspaces/${g.workspaceId}/events?session=${encodeURIComponent(t)}&limit=500`);if(!n.ok)return;let r=await n.json(),i=r.events??[];if(i.length===0)return;let a=i.filter(e=>e.type===`agent:event`&&e.workspaceId===g.workspaceId),o=i.filter(e=>e.type===`user:message`&&e.workspaceId===g.workspaceId),s=a.map(e=>e.payload),c=a.map(e=>e.createdAt),l=a.map(e=>e.sessionId??null),u=a.map(e=>e.id);G(g.workspaceId,t,r.hasMore),s.length>0&&v.prepend(g.workspaceId,s,c,{oldestId:i[0].id,hasMoreOlder:v.hasMoreOlderFor(g.workspaceId),sessionIds:l,eventIds:u});for(let e of o){let t=e.payload;typeof t.content==`string`&&b.addActivityItem(g.workspaceId,{id:e.id,type:`text`,content:t.content,timestamp:e.createdAt,sessionId:e.sessionId??void 0,meta:{sender:t.sender??`user`}})}await e(),await K(0)}catch(e){console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Q.delete(n)}}}n(p(()=>P.value.filter(e=>e.sender!==`system-prompt`).length),async(e,t)=>{e>t&&(z.value=!0,await K(180))});async function pe(){z.value=!0,await K(250)}return(e,n)=>H.value?(t(),m(`div`,Ce,[d(A,{size:`40px`,color:`indigo-4`})])):(t(),m(`div`,we,[d(N,{ref_key:`scrollRef`,ref:R,class:`activity-feed-scroll`,onScroll:re},{default:o(()=>[_(`div`,{ref_key:`contentOriginRef`,ref:J,class:`content-origin-marker`},null,512),B.value?(t(),m(`div`,Te,[d(x,{size:`sm`}),f(` `+c(e.$t(`activity.loading_older`)),1)])):u(``,!0),_(`div`,Ee,[(t(!0),m(h,null,r(I.value,(e,n)=>(t(),l(Se,{key:n,ref_for:!0,ref_key:`turnRefs`,ref:q,turn:e,onScrollTo:se},null,8,[`turn`]))),128))]),L.value.length?(t(),m(`div`,De,[d(M,{label:e.$t(`activity.raw_lines`,{n:L.value.length}),dense:``},{default:o(()=>[(t(!0),m(h,null,r(L.value,(e,n)=>(t(),m(`div`,{key:n,class:`text-caption text-grey q-pa-xs`},c(e),1))),128))]),_:1},8,[`label`])])):u(``,!0)]),_:1},512),_(`div`,Oe,[z.value?u(``,!0):(t(),l(w,{key:0,round:``,dense:``,unelevated:``,color:`grey-9`,"text-color":`grey-3`,icon:`arrow_downward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.scroll_to_bottom`),onClick:pe},null,8,[`title`])),d(w,{round:``,dense:``,unelevated:``,color:`grey-9`,"text-color":`grey-3`,icon:`arrow_upward`,size:`sm`,class:`activity-feed-nav-btn`,title:e.$t(`activity.prev_user_message`),onClick:ue},null,8,[`title`])])]))}}),[[`__scopeId`,`data-v-890bdcbd`]]);export{Pe as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.markdown-message[data-v-e9f9bd11]{color:#e0e0e0;word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-e9f9bd11] *{max-width:100%}.markdown-message[data-v-e9f9bd11] p{margin:0 0 .5em}.markdown-message[data-v-e9f9bd11] p:last-child{margin-bottom:0}.markdown-message[data-v-e9f9bd11] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-e9f9bd11] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-e9f9bd11] pre code{background:0 0;padding:0}.markdown-message[data-v-e9f9bd11] ul,.markdown-message[data-v-e9f9bd11] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-e9f9bd11] li{margin:.15em 0}.markdown-message[data-v-e9f9bd11] a{color:#7986cb;text-decoration:underline}.markdown-message[data-v-e9f9bd11] .document-link{color:#9fa8da;cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-e9f9bd11] .document-link:hover{color:#c5cae9;-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-e9f9bd11] h1,.markdown-message[data-v-e9f9bd11] h2,.markdown-message[data-v-e9f9bd11] h3,.markdown-message[data-v-e9f9bd11] h4,.markdown-message[data-v-e9f9bd11] h5,.markdown-message[data-v-e9f9bd11] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-e9f9bd11] h1{font-size:1.25em}.markdown-message[data-v-e9f9bd11] h2{font-size:1.15em}.markdown-message[data-v-e9f9bd11] h3{font-size:1.08em}.markdown-message[data-v-e9f9bd11] h4,.markdown-message[data-v-e9f9bd11] h5,.markdown-message[data-v-e9f9bd11] h6{font-size:1em}.markdown-message[data-v-e9f9bd11] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-e9f9bd11] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-e9f9bd11] th,.markdown-message[data-v-e9f9bd11] td{border:1px solid #ffffff26;padding:.25em .5em}.markdown-thinking[data-v-4e64694c] p{margin:0 0 .4em}.markdown-thinking[data-v-4e64694c] p:last-child{margin-bottom:0}.markdown-thinking[data-v-4e64694c] code{background:#ffffff14;border-radius:3px;padding:.1em .3em}.tool-row[data-v-b1fcd20d]{border-radius:4px;margin:0;font-size:12px}.tool-header[data-v-b1fcd20d]{color:#bbb;cursor:default;align-items:center;gap:10px;min-width:0;padding:5px 10px;display:flex}.tool-row:not(.tool-row-generic) .tool-header[data-v-b1fcd20d],.tool-row--toggleable .tool-header[data-v-b1fcd20d]{cursor:pointer}.tool-row:has(.tool-diff) .tool-header[data-v-b1fcd20d]{cursor:pointer}.tool-row:not(.tool-row-generic) .tool-header[data-v-b1fcd20d]:hover,.tool-row--toggleable .tool-header[data-v-b1fcd20d]:hover{background:#ffffff08}.tool-icon[data-v-b1fcd20d]{color:#9fbce0;flex-shrink:0}.tool-name[data-v-b1fcd20d]{color:#d0d0d0;flex-shrink:0;font-weight:600}.tool-arg[data-v-b1fcd20d],.tool-path[data-v-b1fcd20d]{color:#999;text-overflow:ellipsis;white-space:nowrap;min-width:0;max-width:100%;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11.5px;overflow:hidden}.tool-path[data-v-b1fcd20d],.tool-arg[data-v-b1fcd20d]{flex:1}.tool-stat-add[data-v-b1fcd20d]{color:#66bb6a;flex-shrink:0;font-size:11px;font-weight:600}.tool-stat-del[data-v-b1fcd20d]{color:#ef5350;flex-shrink:0;font-size:11px;font-weight:600}.tool-diff[data-v-b1fcd20d]{background:#0003;border-radius:4px;max-height:400px;margin-top:4px;padding:8px 0;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px;line-height:1.5;overflow:auto}.diff-line[data-v-b1fcd20d]{white-space:pre;color:#bbb;padding:0 12px}.diff-sign[data-v-b1fcd20d]{color:#555;-webkit-user-select:none;user-select:none;width:14px;display:inline-block}.diff-add[data-v-b1fcd20d]{color:#c8e6c9;background:#66bb6a1a}.diff-add .diff-sign[data-v-b1fcd20d]{color:#66bb6a}.diff-del[data-v-b1fcd20d]{color:#ffcdd2;background:#ef53501a}.diff-del .diff-sign[data-v-b1fcd20d]{color:#ef5350}.tool-output[data-v-b1fcd20d]{color:#aaa;white-space:pre-wrap;background:#00000026;border-radius:4px;max-height:8em;margin-top:4px;padding:6px 10px;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px;overflow:auto}.markdown-message[data-v-c2e7c407]{color:#e0e0e0;word-break:break-word;overflow-wrap:anywhere;min-width:0;max-width:100%;font-size:13px;line-height:1.55}.markdown-message[data-v-c2e7c407] *{max-width:100%}.markdown-message[data-v-c2e7c407] img{-o-object-fit:contain;object-fit:contain;cursor:zoom-in;background:#0003;border-radius:4px;max-width:180px;max-height:100px;margin:.3em 0;display:block}.markdown-message[data-v-c2e7c407] code{word-break:break-all}.markdown-message[data-v-c2e7c407] p{margin:0 0 .4em}.markdown-message[data-v-c2e7c407] p:last-child{margin-bottom:0}.markdown-message[data-v-c2e7c407] code{background:#00000040;border-radius:3px;padding:.1em .3em}.markdown-message[data-v-c2e7c407] h1,.markdown-message[data-v-c2e7c407] h2,.markdown-message[data-v-c2e7c407] h3,.markdown-message[data-v-c2e7c407] h4,.markdown-message[data-v-c2e7c407] h5,.markdown-message[data-v-c2e7c407] h6{margin:.4em 0 .25em;font-weight:600;line-height:1.3}.markdown-message[data-v-c2e7c407] h1{font-size:1.25em}.markdown-message[data-v-c2e7c407] h2{font-size:1.15em}.markdown-message[data-v-c2e7c407] h3{font-size:1.08em}.markdown-message[data-v-c2e7c407] h4,.markdown-message[data-v-c2e7c407] h5,.markdown-message[data-v-c2e7c407] h6{font-size:1em}.markdown-user-prompt[data-v-c2e7c407]{color:#aaa;font-size:12px;font-style:italic}.markdown-user-prompt[data-v-c2e7c407] p{margin:0 0 .4em}.markdown-user-prompt[data-v-c2e7c407] code{background:#ffffff14;border-radius:3px;padding:.1em .3em;font-style:normal}.image-lightbox-img{-o-object-fit:contain;object-fit:contain;cursor:zoom-out;background:#0000004d;border-radius:4px;max-width:92vw;max-height:92vh;display:block}.turn-card[data-v-4729e0cc]{border:1px solid #ffffff14;border-left:3px solid var(--turn-accent);background:#ffffff05;border-radius:6px;min-width:0;max-width:100%;margin:14px 0;overflow:hidden}.turn-header[data-v-4729e0cc]{color:#888;background:#ffffff08;border-bottom:1px solid #ffffff0d;align-items:center;gap:8px;padding:8px 14px;font-size:11px;display:flex}.turn-badge[data-v-4729e0cc]{letter-spacing:.3px;border-radius:3px;padding:2px 8px;font-size:11px;font-weight:700}.turn-badge-user[data-v-4729e0cc]{color:#ce93d8;background:#ce93d826}.turn-badge-agent[data-v-4729e0cc]{color:#7986cb;background:#7986cb26}.turn-badge-system[data-v-4729e0cc]{color:#bdbdbd;background:#75757533;font-style:italic}.turn-badge-session[data-v-4729e0cc]{color:#9e9e9e;background:#61616133}.turn-time[data-v-4729e0cc]{color:#666;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px}.turn-time-arrow[data-v-4729e0cc]{opacity:.7;margin:0 -2px}.turn-time-updated[data-v-4729e0cc]{color:#8891a3}.turn-actions[data-v-4729e0cc]{color:#777;font-size:11px}.turn-body[data-v-4729e0cc]{flex-direction:column;gap:12px;min-width:0;padding:14px 18px;display:flex}.turn-body[data-v-4729e0cc]>*{min-width:0;max-width:100%}.turn-body[data-v-4729e0cc] .tool-row+.tool-row{margin-top:-8px}.turn-scroll-top[data-v-4729e0cc]{justify-content:flex-start;padding:0 8px 6px;display:flex}.turn-scroll-top-btn[data-v-4729e0cc]{opacity:.5;transition:opacity .15s}.turn-scroll-top-btn[data-v-4729e0cc]:hover{opacity:1}.activity-feed-wrap[data-v-890bdcbd]{width:100%;height:100%;position:relative}.activity-feed-scroll[data-v-890bdcbd]{width:100%;height:100%}.activity-feed-nav-cluster[data-v-890bdcbd]{z-index:2;align-items:center;gap:8px;display:flex;position:absolute;bottom:14px;right:14px}.activity-feed-nav-btn[data-v-890bdcbd]{opacity:.8;transition:opacity .12s}.activity-feed-nav-btn[data-v-890bdcbd]:hover{opacity:1}.content-origin-marker[data-v-890bdcbd]{pointer-events:none;width:0;height:0;margin:0;padding:0}.activity-feed-scroll[data-v-890bdcbd] .q-scrollarea__content{max-width:100%;overflow-x:hidden}.activity-feed-switching[data-v-890bdcbd]{justify-content:center;align-items:center;width:100%;height:100%;display:flex}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{k as e,m as t}from"./QIcon-B0-pH3Qs.js";import{_ as n,g as r}from"./settings-
|
|
1
|
+
import{k as e,m as t}from"./QIcon-B0-pH3Qs.js";import{_ as n,g as r}from"./settings-Dbx1_ksA.js";function i(e){if(e===!1)return 0;if(e===!0||e===void 0)return 1;let t=parseInt(e,10);return isNaN(t)?0:t}var a=e({name:`close-popup`,beforeMount(e,{value:a}){let o={depth:i(a),handler(t){o.depth!==0&&setTimeout(()=>{let i=n(e);i!==void 0&&r(i,t,o.depth)})},handlerKey(e){t(e,13)===!0&&o.handler(e)}};e.__qclosepopup=o,e.addEventListener(`click`,o.handler),e.addEventListener(`keyup`,o.handlerKey)},updated(e,{value:t,oldValue:n}){t!==n&&(e.__qclosepopup.depth=i(t))},beforeUnmount(e){let t=e.__qclosepopup;e.removeEventListener(`click`,t.handler),e.removeEventListener(`keyup`,t.handlerKey),delete e.__qclosepopup}});export{a as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.create-page[data-v-56d6cf98]{background-color:#1a1a2e;min-height:100%;padding:48px 24px}.create-inner[data-v-56d6cf98]{width:100%;max-width:700px}.create-title[data-v-56d6cf98]{font-size:24px;line-height:1.3}.create-card[data-v-56d6cf98]{background:#224;border:1px solid #444;overflow:hidden}.card-top-bar[data-v-56d6cf98]{background:#1e1e3a;min-height:36px}.card-name-wrap[data-v-56d6cf98]{background:#224;padding:8px 16px 4px}.card-name-wrap[data-v-56d6cf98] .q-field__control{height:32px;min-height:32px;padding:0}.card-name-wrap[data-v-56d6cf98] input{color:#e0e0e0;font-size:15px;font-weight:500}.card-name-wrap[data-v-56d6cf98] input::placeholder{color:#555}.card-textarea-wrap[data-v-56d6cf98]{background:#224;position:relative}.create-slash-popup[data-v-56d6cf98]{z-index:9999;position:absolute;top:calc(100% + 4px);left:12px;right:12px}.repo-select[data-v-56d6cf98]{min-width:160px;max-width:260px}.repo-select[data-v-56d6cf98] .q-field__prepend{align-items:center;height:auto;padding-top:0}.create-textarea[data-v-56d6cf98]{color:#d0d0d0;width:100%;padding:12px 16px 4px}.create-textarea[data-v-56d6cf98] .q-field__control{padding:0}.create-textarea[data-v-56d6cf98] textarea{color:#d0d0d0;resize:none;min-height:100px;font-size:14px;line-height:1.6}.create-textarea[data-v-56d6cf98] textarea::placeholder{color:#666}.notion-toggle-btn[data-v-56d6cf98]{background:#333;padding:2px 10px}.notion-url-wrap[data-v-56d6cf98]{background:#1e1e3a;padding:8px 0 0}.notion-url-input[data-v-56d6cf98]{padding:0 12px}.notion-url-input[data-v-56d6cf98] .q-field__control{height:36px;min-height:36px;padding:0}.notion-url-input[data-v-56d6cf98] input{color:#d0d0d0;font-size:13px}.notion-url-input[data-v-56d6cf98] input::placeholder{color:#555;font-size:12px}.notion-error[data-v-56d6cf98],.notion-valid[data-v-56d6cf98]{padding-bottom:6px}.notion-peek-choice[data-v-56d6cf98]{padding-top:4px}.peek-card[data-v-56d6cf98]{cursor:pointer;text-align:left;color:#e0e0e0;font-family:inherit;font-size:inherit;background:#ffffff08;border:1px solid #ffffff14;border-radius:8px;align-items:center;gap:10px;padding:10px 12px;transition:background .15s,border-color .15s,transform .1s;display:flex;position:relative}.peek-card[data-v-56d6cf98]:hover{background:#ffffff0f;border-color:#6c63ff66}.peek-card[data-v-56d6cf98]:active{transform:scale(.99)}.peek-card--active[data-v-56d6cf98]{background:#6c63ff1f;border-color:#6c63ffd9;box-shadow:0 0 0 1px #6c63ff66}.peek-card--active .peek-card-icon[data-v-56d6cf98]{color:#8a82ff}.peek-card--active .peek-card-title[data-v-56d6cf98]{color:#fff}.peek-card-icon[data-v-56d6cf98]{color:#999;flex-shrink:0}.peek-card-text[data-v-56d6cf98]{flex:1;min-width:0;line-height:1.25}.peek-card-title[data-v-56d6cf98]{color:#d0d0d0;font-size:12px;font-weight:600}.peek-card-desc[data-v-56d6cf98]{color:#888;margin-top:2px;font-size:10.5px}.peek-card-check[data-v-56d6cf98]{flex-shrink:0}.sentry-toggle-btn[data-v-56d6cf98]{background:#333;padding:2px 10px}.sentry-url-wrap[data-v-56d6cf98]{background:#1e1e3a;padding:8px 0 0}.sentry-url-input[data-v-56d6cf98]{padding:0 12px}.sentry-url-input[data-v-56d6cf98] .q-field__control{height:36px;min-height:36px;padding:0}.sentry-url-input[data-v-56d6cf98] input{color:#d0d0d0;font-size:13px}.sentry-url-input[data-v-56d6cf98] input::placeholder{color:#555;font-size:12px}.sentry-error[data-v-56d6cf98],.sentry-valid[data-v-56d6cf98]{padding-bottom:6px}.slide-enter-active[data-v-56d6cf98],.slide-leave-active[data-v-56d6cf98]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-56d6cf98],.slide-leave-to[data-v-56d6cf98]{opacity:0;max-height:0}.slide-enter-to[data-v-56d6cf98],.slide-leave-from[data-v-56d6cf98]{opacity:1;max-height:120px}.card-bottom-bar[data-v-56d6cf98]{background:#1e1e3a}.skip-setup-btn[data-v-56d6cf98]{min-height:28px;padding:2px 10px;font-size:11px}.skip-setup-btn[data-v-56d6cf98] .q-btn__content{gap:4px}.skip-setup-btn[data-v-56d6cf98] .q-icon{font-size:14px}.bottom-row-git .bottom-select-label[data-v-56d6cf98]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bottom-row-git .bottom-select.repo-select[data-v-56d6cf98] input{color:#bbb;padding:0 4px;font-size:11px}.bottom-row-git .bottom-select.repo-select[data-v-56d6cf98] input::placeholder{color:#666;font-style:italic}.bottom-select[data-v-56d6cf98]{background:#333;height:28px;padding:0 6px}.bottom-select[data-v-56d6cf98] .q-field__control{height:28px;min-height:28px;padding:0}.bottom-select[data-v-56d6cf98] .q-field__native{min-height:unset;padding:0}.bottom-select-label[data-v-56d6cf98]{color:#bbb;gap:2px;font-size:11px}.bottom-sep[data-v-56d6cf98]{color:#555;padding:0 2px;font-size:12px;line-height:1}.repo-path-wrap[data-v-56d6cf98]{background:#333;border-radius:6px;height:28px;padding:0 8px}.repo-input[data-v-56d6cf98]{min-width:140px}.repo-input[data-v-56d6cf98] .q-field__control{height:28px;min-height:28px;padding:0}.repo-input[data-v-56d6cf98] input{color:#bbb;font-size:11px}.repo-input[data-v-56d6cf98] input::placeholder{color:#666;font-size:11px}.branch-select[data-v-56d6cf98]{min-width:80px}.create-btn[data-v-56d6cf98]{color:#fff;background:#4f46e5;min-width:220px;height:32px;padding:0 32px;font-size:13px}.create-btn[data-v-56d6cf98] .q-btn__content{height:32px}.create-hint[data-v-56d6cf98]{line-height:1.5}.fade-enter-active[data-v-56d6cf98],.fade-leave-active[data-v-56d6cf98]{transition:opacity .2s}.fade-enter-from[data-v-56d6cf98],.fade-leave-to[data-v-56d6cf98]{opacity:0}.manual-hint[data-v-56d6cf98]{background:#1e1e3a;line-height:1.4}.manual-expansion[data-v-56d6cf98]{background:#1e1e3a;border:1px solid #333;border-radius:4px;margin-top:6px;overflow:hidden}.manual-expansion[data-v-56d6cf98] .manual-expansion-header{min-height:32px;padding:4px 10px;font-size:12px}.manual-expansion[data-v-56d6cf98] .q-expansion-item__content,.manual-section-body[data-v-56d6cf98]{background:#1a1a2e}.manual-input[data-v-56d6cf98] .q-field__control{height:26px;min-height:26px;padding:0}.manual-input[data-v-56d6cf98] input{color:#e0e0e0;font-size:12px}.manual-input[data-v-56d6cf98] input::placeholder{color:#555}.manual-item[data-v-56d6cf98]{border-top:1px solid #ffffff0a}.manual-item[data-v-56d6cf98]:first-child{border-top:none}
|