@loicngr/kobo 1.6.13 → 1.6.15
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 +1 -0
- package/dist/server/routes/workspaces.js +51 -7
- package/dist/server/services/auto-loop-service.js +16 -9
- package/dist/server/services/settings-service.js +39 -2
- package/dist/server/services/usage/poller.js +4 -1
- package/dist/server/utils/git-ops.js +67 -5
- package/dist/shared/auto-loop-prompts.js +19 -7
- package/package.json +1 -1
- package/src/client/dist/spa/assets/ActivityFeed-BHdMJRwS.css +1 -0
- package/src/client/dist/spa/assets/ActivityFeed-D7MF6IK1.js +8 -0
- package/src/client/dist/spa/assets/ClosePopup-D7BBEcaf.js +1 -0
- package/src/client/dist/spa/assets/CreatePage-DJbZH8wp.css +1 -0
- package/src/client/dist/spa/assets/{CreatePage-Cdhkkx-X.js → CreatePage-rp-9_jOF.js} +2 -2
- package/src/client/dist/spa/assets/DiffViewer-BJZADilo.js +7 -0
- package/src/client/dist/spa/assets/DiffViewer-D1Sdu307.css +1 -0
- package/src/client/dist/spa/assets/HealthPage-CZQB2pvh.js +1 -0
- package/src/client/dist/spa/assets/MainLayout-CFHf3zKv.js +37 -0
- package/src/client/dist/spa/assets/MainLayout-Db3dwSTM.css +1 -0
- package/src/client/dist/spa/assets/QChip-D905z6BM.js +1 -0
- package/src/client/dist/spa/assets/QExpansionItem-CUXuOfeR.js +1 -0
- package/src/client/dist/spa/assets/QInput-6U0_avSY.js +1 -0
- package/src/client/dist/spa/assets/{QItemSection-CiY_LK5Y.js → QItemSection-Cloi4ErY.js} +1 -1
- package/src/client/dist/spa/assets/QMenu-BPzgTm2k.js +1 -0
- package/src/client/dist/spa/assets/{QPage-yqdKDG7-.js → QPage-C6h_ah5z.js} +1 -1
- package/src/client/dist/spa/assets/{QScrollArea-DpCqRRE0.js → QScrollArea-N10UpHIf.js} +1 -1
- package/src/client/dist/spa/assets/QTabPanels-PPompnxw.js +1 -0
- package/src/client/dist/spa/assets/QTooltip-DLT8jCHz.js +1 -0
- package/src/client/dist/spa/assets/SearchPage-CfYy4vGJ.js +1 -0
- package/src/client/dist/spa/assets/SearchPage-cVwt0DaQ.css +1 -0
- package/src/client/dist/spa/assets/SettingsPage-B8DhSZw7.css +1 -0
- package/src/client/dist/spa/assets/SettingsPage-ONWYC-Bn.js +1 -0
- package/src/client/dist/spa/assets/WorkspacePage-B2VAbf6l.js +4 -0
- package/src/client/dist/spa/assets/WorkspacePage-k2pgeRoy.css +1 -0
- package/src/client/dist/spa/assets/{build-path-tree-D-2LpB2J.js → build-path-tree-DETFP2lL.js} +1 -1
- package/src/client/dist/spa/assets/{cssMode-DVBmJp-B.js → cssMode-QQTtBrD_.js} +1 -1
- package/src/client/dist/spa/assets/documents-BMdAS6h8.js +1 -0
- package/src/client/dist/spa/assets/{editor.api-DgbPJaK4.js → editor.api-YqpktRoe.js} +1 -1
- package/src/client/dist/spa/assets/{editor.main-BqqoRfAU.js → editor.main-DDGqfxYm.js} +3 -3
- package/src/client/dist/spa/assets/expand-template-CZkefibF.js +1 -0
- package/src/client/dist/spa/assets/expand-template-D2yUa54D.css +1 -0
- package/src/client/dist/spa/assets/{formatters-CX2gvLFv.js → formatters-DWeOzSfw.js} +1 -1
- package/src/client/dist/spa/assets/{freemarker2-CgaW0Q0y.js → freemarker2-BC_Lt7t3.js} +1 -1
- package/src/client/dist/spa/assets/{handlebars-BSs5PdXe.js → handlebars-BphhRg2c.js} +1 -1
- package/src/client/dist/spa/assets/{html-C9wlJaMs.js → html-C84Ufc1n.js} +1 -1
- package/src/client/dist/spa/assets/{htmlMode-DaRssGJk.js → htmlMode-CIlyKZJ4.js} +1 -1
- package/src/client/dist/spa/assets/i18n-CNdSgNP6.js +1 -0
- package/src/client/dist/spa/assets/index-pGAaG7Rh.js +2 -0
- package/src/client/dist/spa/assets/{javascript-D0VYhsc-.js → javascript-D5LTZTWn.js} +1 -1
- package/src/client/dist/spa/assets/{jsonMode-B57EaUNS.js → jsonMode-YBOBMJNl.js} +1 -1
- package/src/client/dist/spa/assets/kobo-commands-DFflpxts.js +11 -0
- package/src/client/dist/spa/assets/{liquid-gP2gg7sw.js → liquid-UNCP2Jl6.js} +1 -1
- package/src/client/dist/spa/assets/marked.esm-D7ibHC_y.js +60 -0
- package/src/client/dist/spa/assets/{mdx-HhXcZn_S.js → mdx-CsHyBm_B.js} +1 -1
- package/src/client/dist/spa/assets/models-tXWASlTL.js +1 -0
- package/src/client/dist/spa/assets/{monaco.contribution-ChJg8bwd.js → monaco.contribution-Bv79M2zD.js} +2 -2
- package/src/client/dist/spa/assets/{python-DM6FfMV3.js → python-B3h-WTW0.js} +1 -1
- package/src/client/dist/spa/assets/{razor-XifsxhTG.js → razor-Cs79ULMl.js} +1 -1
- package/src/client/dist/spa/assets/settings-Cw4mtk9x.js +1 -0
- package/src/client/dist/spa/assets/{stats-C3n1k51k.js → stats-BrLStQKj.js} +1 -1
- package/src/client/dist/spa/assets/touch-DBLw8vQK.js +1 -0
- package/src/client/dist/spa/assets/{tsMode-B8gurPqG.js → tsMode-238NR35q.js} +1 -1
- package/src/client/dist/spa/assets/{typescript-CZKTCOjl.js → typescript-C93UakWa.js} +1 -1
- package/src/client/dist/spa/assets/use-checkbox-w-raiu10.js +1 -0
- package/src/client/dist/spa/assets/use-id-CDuXkR0Z.js +1 -0
- package/src/client/dist/spa/assets/{xml-CtZPkb7Q.js → xml-24CcVrVJ.js} +1 -1
- package/src/client/dist/spa/assets/{yaml-D5IEE5M-.js → yaml-BLhB8_OL.js} +1 -1
- package/src/client/dist/spa/index.html +9 -11
- package/src/client/dist/spa/assets/ActivityFeed-BHDJ5lUn.css +0 -1
- package/src/client/dist/spa/assets/ActivityFeed-BsY3-q5d.js +0 -8
- package/src/client/dist/spa/assets/ClosePopup-DkLittac.js +0 -1
- package/src/client/dist/spa/assets/CreatePage-PRvhol1N.css +0 -1
- package/src/client/dist/spa/assets/DiffViewer-BC81-2me.css +0 -1
- package/src/client/dist/spa/assets/DiffViewer-DXcoEtVq.js +0 -2
- package/src/client/dist/spa/assets/HealthPage-BSyGqDRu.js +0 -1
- package/src/client/dist/spa/assets/MainLayout-D2SfvksB.css +0 -1
- package/src/client/dist/spa/assets/MainLayout-EYaLqjJx.js +0 -37
- package/src/client/dist/spa/assets/QChip-bl3YRhax.js +0 -1
- package/src/client/dist/spa/assets/QExpansionItem-CWw6ZujM.js +0 -1
- package/src/client/dist/spa/assets/QSeparator-DNSiXYrN.js +0 -1
- package/src/client/dist/spa/assets/QTabPanels-C4bZGqml.js +0 -1
- package/src/client/dist/spa/assets/QTooltip-BIDjo2hJ.js +0 -1
- package/src/client/dist/spa/assets/SearchPage-Bgx02GOH.js +0 -1
- package/src/client/dist/spa/assets/SearchPage-DWglAeQv.css +0 -1
- package/src/client/dist/spa/assets/SettingsPage-BTSOovDV.js +0 -1
- package/src/client/dist/spa/assets/SettingsPage-CwLELxfl.css +0 -1
- package/src/client/dist/spa/assets/TouchPan-vsl78kxF.js +0 -1
- package/src/client/dist/spa/assets/WorkspacePage-C5MZx1sZ.css +0 -1
- package/src/client/dist/spa/assets/WorkspacePage-C8dJWu-n.js +0 -4
- package/src/client/dist/spa/assets/documents-Ck8VwvpQ.js +0 -60
- package/src/client/dist/spa/assets/expand-template-bkCTc78P.js +0 -1
- package/src/client/dist/spa/assets/expand-template-hbnn7St6.css +0 -1
- package/src/client/dist/spa/assets/i18n-BSNIShFg.js +0 -1
- package/src/client/dist/spa/assets/index-odgA9x8A.js +0 -2
- package/src/client/dist/spa/assets/kobo-commands-D-9dbM70.js +0 -11
- package/src/client/dist/spa/assets/models-CJC61gWE.js +0 -1
- package/src/client/dist/spa/assets/private.use-form-Dlb0iQZh.js +0 -1
- package/src/client/dist/spa/assets/scroll-CYWyxBdv.js +0 -1
- package/src/client/dist/spa/assets/settings-CAILUJXO.js +0 -1
- package/src/client/dist/spa/assets/touch-Bj_Fr4kC.js +0 -1
- package/src/client/dist/spa/assets/use-checkbox-B_o-iLG2.js +0 -1
- package/src/client/dist/spa/assets/use-id-C93QQwrt.js +0 -1
- /package/src/client/dist/spa/assets/{QBadge-DqtcDv8D.js → QBadge-BUkmTO0P.js} +0 -0
- /package/src/client/dist/spa/assets/{QBtn-DHwAb18J.js → QBtn-CyzfM9-_.js} +0 -0
- /package/src/client/dist/spa/assets/{QItemLabel-Codqjisk.js → QItemLabel-DwnV_S8y.js} +0 -0
- /package/src/client/dist/spa/assets/{QList-Bl9824vi.js → QList-DZfpUv3n.js} +0 -0
- /package/src/client/dist/spa/assets/{QSlideTransition-BQxI8l5r.js → QSlideTransition-BMX92yUu.js} +0 -0
- /package/src/client/dist/spa/assets/{QSpace-BNr0AftG.js → QSpace-PlDK6Fg3.js} +0 -0
- /package/src/client/dist/spa/assets/{QSpinnerDots-DEiRooBD.js → QSpinnerDots-D7bo_KgI.js} +0 -0
- /package/src/client/dist/spa/assets/{_plugin-vue_export-helper-r4mAJOHR.js → _plugin-vue_export-helper-CpNzZuug.js} +0 -0
- /package/src/client/dist/spa/assets/{abap-Bgec7Keq.js → abap-DrZwwXZX.js} +0 -0
- /package/src/client/dist/spa/assets/{apex-VBlPwEoQ.js → apex-CrCz0btt.js} +0 -0
- /package/src/client/dist/spa/assets/{azcli-DKqrEFBx.js → azcli-BapzKHay.js} +0 -0
- /package/src/client/dist/spa/assets/{bat-DdgQWy_0.js → bat-C_NRAiA1.js} +0 -0
- /package/src/client/dist/spa/assets/{bicep-CRMM43EB.js → bicep-C7pp2CNk.js} +0 -0
- /package/src/client/dist/spa/assets/{cameligo-UatALtML.js → cameligo-BhhK9vxZ.js} +0 -0
- /package/src/client/dist/spa/assets/{clojure-D8JU08RA.js → clojure-D0ujmUyE.js} +0 -0
- /package/src/client/dist/spa/assets/{coffee-C56wu358.js → coffee-DHEl7Jbb.js} +0 -0
- /package/src/client/dist/spa/assets/{cpp-CyZLvhJG.js → cpp-Iil-3nzZ.js} +0 -0
- /package/src/client/dist/spa/assets/{csharp-BJl3ixva.js → csharp-Dh0Ee7SY.js} +0 -0
- /package/src/client/dist/spa/assets/{csp-CxEKxmO-.js → csp-mwzjw0JL.js} +0 -0
- /package/src/client/dist/spa/assets/{css-B0t_muXd.js → css-COIa8ZTR.js} +0 -0
- /package/src/client/dist/spa/assets/{cypher-D1hqiMFD.js → cypher-GVc17FC4.js} +0 -0
- /package/src/client/dist/spa/assets/{dart-Bz550Pyv.js → dart-phiCaE7_.js} +0 -0
- /package/src/client/dist/spa/assets/{dockerfile-CIXgVAuA.js → dockerfile-BMaDhdim.js} +0 -0
- /package/src/client/dist/spa/assets/{ecl-D9qbvZoA.js → ecl-Cj47kvqp.js} +0 -0
- /package/src/client/dist/spa/assets/{elixir-b2M38fAy.js → elixir-DBbstcE1.js} +0 -0
- /package/src/client/dist/spa/assets/{flow9-Dq1UYMkt.js → flow9-ChHb1adO.js} +0 -0
- /package/src/client/dist/spa/assets/{fsharp-CFNadkg7.js → fsharp-CDI_AxQw.js} +0 -0
- /package/src/client/dist/spa/assets/{go-dSur1iB2.js → go-DmsC2k-Y.js} +0 -0
- /package/src/client/dist/spa/assets/{graphql-qyhAo11d.js → graphql-C8hjT6Ki.js} +0 -0
- /package/src/client/dist/spa/assets/{hcl-DFzjMyzm.js → hcl-C15cAQOZ.js} +0 -0
- /package/src/client/dist/spa/assets/{ini-TdzA8TIl.js → ini-CKrAe0ag.js} +0 -0
- /package/src/client/dist/spa/assets/{is-DUKatk8N.js → is-BbsvEMaT.js} +0 -0
- /package/src/client/dist/spa/assets/{java-CSGA9pkE.js → java-BVhjILyl.js} +0 -0
- /package/src/client/dist/spa/assets/{julia-9izz5OsY.js → julia-BzPDHDOG.js} +0 -0
- /package/src/client/dist/spa/assets/{kotlin-DuPK7AtF.js → kotlin-DQMAn-b6.js} +0 -0
- /package/src/client/dist/spa/assets/{less-B8d93iCg.js → less-428mfr1h.js} +0 -0
- /package/src/client/dist/spa/assets/{lexon-DWtEIyu7.js → lexon-B09dCO6A.js} +0 -0
- /package/src/client/dist/spa/assets/{lua-Ciq0OGgt.js → lua-CVQ0BJif.js} +0 -0
- /package/src/client/dist/spa/assets/{m3-Cki6JWj_.js → m3-CiPQ1ljw.js} +0 -0
- /package/src/client/dist/spa/assets/{markdown-Cu47xwU0.js → markdown--G0dqL-7.js} +0 -0
- /package/src/client/dist/spa/assets/{mips-BM8ui995.js → mips-BaboCM3T.js} +0 -0
- /package/src/client/dist/spa/assets/{msdax-DqLio0_c.js → msdax-DUaqkqre.js} +0 -0
- /package/src/client/dist/spa/assets/{mysql-v1wbjJOq.js → mysql-CUE6XF4r.js} +0 -0
- /package/src/client/dist/spa/assets/{objective-c-CQl3PGSB.js → objective-c-C4MUnzeT.js} +0 -0
- /package/src/client/dist/spa/assets/{pascal-D4iW0ZtD.js → pascal-CWMUMx__.js} +0 -0
- /package/src/client/dist/spa/assets/{pascaligo-BdC9CZdj.js → pascaligo-DLCVutek.js} +0 -0
- /package/src/client/dist/spa/assets/{perl-BL10m4XD.js → perl-JYoirQpx.js} +0 -0
- /package/src/client/dist/spa/assets/{pgsql-Be_oqVo3.js → pgsql-BqOy7sqx.js} +0 -0
- /package/src/client/dist/spa/assets/{php-BtvXSFRI.js → php-PZqsysO1.js} +0 -0
- /package/src/client/dist/spa/assets/{pla-B2vUy15C.js → pla-BiwqVlg6.js} +0 -0
- /package/src/client/dist/spa/assets/{postiats-CbmTTfXr.js → postiats-COxQtXCD.js} +0 -0
- /package/src/client/dist/spa/assets/{powerquery-DszLhJGx.js → powerquery-DdXUmaWa.js} +0 -0
- /package/src/client/dist/spa/assets/{powershell-B0dYktF6.js → powershell-D05yu9sz.js} +0 -0
- /package/src/client/dist/spa/assets/{protobuf-CZvaj1VX.js → protobuf-BDsm0ZB_.js} +0 -0
- /package/src/client/dist/spa/assets/{pug-CPDx1B3S.js → pug-3CmTiGoi.js} +0 -0
- /package/src/client/dist/spa/assets/{qsharp-CDP9TFLl.js → qsharp-C4eHfCpJ.js} +0 -0
- /package/src/client/dist/spa/assets/{r-8DbbFX2l.js → r-Decg_RIU.js} +0 -0
- /package/src/client/dist/spa/assets/{redis-DRWj9MtJ.js → redis-Cl3EBA4R.js} +0 -0
- /package/src/client/dist/spa/assets/{redshift-C6cElE_5.js → redshift-5ZsNLhOp.js} +0 -0
- /package/src/client/dist/spa/assets/{restructuredtext-W9pS9n3m.js → restructuredtext-BulNNF_e.js} +0 -0
- /package/src/client/dist/spa/assets/{ruby-BKnzWnk-.js → ruby-D3Axi_9w.js} +0 -0
- /package/src/client/dist/spa/assets/{rust-YPCclWwe.js → rust-Csys1Tos.js} +0 -0
- /package/src/client/dist/spa/assets/{sb-BgM4DTFb.js → sb-C_iBPphi.js} +0 -0
- /package/src/client/dist/spa/assets/{scala-fz1OPLMl.js → scala-Cg4p-EZ2.js} +0 -0
- /package/src/client/dist/spa/assets/{scheme-8Uz1RIbu.js → scheme-BlVnEL_j.js} +0 -0
- /package/src/client/dist/spa/assets/{scss-Djo3IYXr.js → scss-CmLW8ojr.js} +0 -0
- /package/src/client/dist/spa/assets/{shell-CINF5Tx_.js → shell-B1DV_gpl.js} +0 -0
- /package/src/client/dist/spa/assets/{solidity-GgiNEuUm.js → solidity-glFpNhe3.js} +0 -0
- /package/src/client/dist/spa/assets/{sophia-Culj97P9.js → sophia-D9j4cFkA.js} +0 -0
- /package/src/client/dist/spa/assets/{sparql-C2ZlpxOY.js → sparql-DV5Ux9cO.js} +0 -0
- /package/src/client/dist/spa/assets/{sql-BEf5Pg7Y.js → sql-K8tNKFcf.js} +0 -0
- /package/src/client/dist/spa/assets/{st-CT6UUoeH.js → st-BhIdE2hj.js} +0 -0
- /package/src/client/dist/spa/assets/{swift-B5g0xTG3.js → swift-B0pzSmmx.js} +0 -0
- /package/src/client/dist/spa/assets/{symbols-DCYodwb2.js → symbols-TAFELniU.js} +0 -0
- /package/src/client/dist/spa/assets/{systemverilog-CEgQz9DR.js → systemverilog-CeBgixbN.js} +0 -0
- /package/src/client/dist/spa/assets/{tcl-D0qL2L0I.js → tcl-B0Ji3IbZ.js} +0 -0
- /package/src/client/dist/spa/assets/{twig-BFUAVf1E.js → twig-KUgPCP41.js} +0 -0
- /package/src/client/dist/spa/assets/{typespec-CjVVcNKm.js → typespec-ryrhjid6.js} +0 -0
- /package/src/client/dist/spa/assets/{use-quasar-Cc4smfg5.js → use-quasar-Clv5nVxk.js} +0 -0
- /package/src/client/dist/spa/assets/{vb-CZJr-DQz.js → vb-Z68-YtMY.js} +0 -0
- /package/src/client/dist/spa/assets/{vue-i18n-BJlZEYnA.js → vue-i18n-BVrBmgZa.js} +0 -0
- /package/src/client/dist/spa/assets/{wgsl-ivoXUo2e.js → wgsl-bH-W-d_T.js} +0 -0
package/README.md
CHANGED
|
@@ -275,6 +275,7 @@ Kōbō reads settings from `~/.config/kobo/settings.json` (or falls back to defa
|
|
|
275
275
|
- `gitConventions` — markdown-formatted git conventions written to `.ai/.git-conventions.md` in every workspace so the agent follows them when committing
|
|
276
276
|
- `devServer` — per-project `startCommand` / `stopCommand` for launching workspace-scoped dev servers
|
|
277
277
|
- `e2e` — per-project E2E test framework (`cypress`, `playwright`, `jest`, `vitest`, `other`, or none) plus an optional skill name and prompt; consumed by the auto-loop grooming step to inject `[E2E] ` test sub-tasks alongside parent tasks
|
|
278
|
+
- `finalization` — per-project free-form prompt that runs as the very last auto-loop iteration. The grooming step injects a `[FINAL]`-prefixed task at the end of the list whose iteration block is replaced by this prompt. Default content asks the agent to run linters, type-checkers, and tests. Empty string disables the feature.
|
|
278
279
|
|
|
279
280
|
## Contributing
|
|
280
281
|
|
|
@@ -197,9 +197,12 @@ app.post('/', migrationGuard, async (c) => {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
// Update workspace name with Sentry issue title if the user did not provide
|
|
200
|
-
// a custom name and Notion hasn't already filled it.
|
|
200
|
+
// a custom name and Notion hasn't already filled it. Prefix with the Sentry
|
|
201
|
+
// short-id (e.g. "SEKUR-IOS-9 | TypeError: …") so the workspace stays
|
|
202
|
+
// identifiable in the sidebar without opening the panel.
|
|
201
203
|
if (sentryContent?.title && !notionContent?.title && workspace.name === 'workspace') {
|
|
202
|
-
|
|
204
|
+
const prefix = sentryContent.issueId ? `${sentryContent.issueId} | ` : '';
|
|
205
|
+
workspace = workspaceService.updateWorkspaceName(workspace.id, `${prefix}${sentryContent.title}`);
|
|
203
206
|
}
|
|
204
207
|
// Create tasks from extracted Notion data
|
|
205
208
|
if (notionContent) {
|
|
@@ -218,9 +221,13 @@ app.post('/', migrationGuard, async (c) => {
|
|
|
218
221
|
sortOrder: sortOrder++,
|
|
219
222
|
});
|
|
220
223
|
}
|
|
221
|
-
// Update workspace name with Notion page title only if user didn't
|
|
224
|
+
// Update workspace name with Notion page title only if user didn't
|
|
225
|
+
// provide a custom name. Prefix with the Notion unique-id (e.g.
|
|
226
|
+
// "TK-123 | …") when the page has one — it makes the workspace
|
|
227
|
+
// immediately scannable in the sidebar.
|
|
222
228
|
if (notionContent.title && workspace.name === 'workspace') {
|
|
223
|
-
|
|
229
|
+
const prefix = notionContent.ticketId ? `${notionContent.ticketId} | ` : '';
|
|
230
|
+
workspace = workspaceService.updateWorkspaceName(workspace.id, `${prefix}${notionContent.title}`);
|
|
224
231
|
}
|
|
225
232
|
}
|
|
226
233
|
// Create manual tasks/criteria if no Notion content was extracted
|
|
@@ -522,11 +529,12 @@ app.post('/', migrationGuard, async (c) => {
|
|
|
522
529
|
// been registered yet, the empty default below is correct.
|
|
523
530
|
const projectSettingsForE2e = settingsService.getProjectSettings(body.projectPath);
|
|
524
531
|
const e2eSettings = projectSettingsForE2e?.e2e ?? { framework: '', skill: '', prompt: '' };
|
|
532
|
+
const finalizationSettings = projectSettingsForE2e?.finalization ?? { prompt: '' };
|
|
525
533
|
brainstormPrompt += `\n\nThen brainstorm the implementation approach. Explore the codebase to understand the existing structure. Ask clarifying questions if needed. When you have a clear plan, create a plan file.
|
|
526
534
|
|
|
527
535
|
Auto-loop mode is active for this workspace. After the plan is ready, DO NOT implement anything. Instead:
|
|
528
536
|
|
|
529
|
-
${buildAutoLoopGroomingSteps(e2eSettings)}
|
|
537
|
+
${buildAutoLoopGroomingSteps(e2eSettings, finalizationSettings)}
|
|
530
538
|
|
|
531
539
|
When the steps above are complete, output [BRAINSTORM_COMPLETE] on its own line and end your turn cleanly.
|
|
532
540
|
|
|
@@ -983,9 +991,10 @@ app.get('/:id/prep-autoloop-prompt', (c) => {
|
|
|
983
991
|
return c.json({ error: `Workspace '${id}' not found` }, 404);
|
|
984
992
|
const projectSettings = settingsService.getProjectSettings(workspace.projectPath);
|
|
985
993
|
const e2eSettings = projectSettings?.e2e ?? { framework: '', skill: '', prompt: '' };
|
|
994
|
+
const finalizationSettings = projectSettings?.finalization ?? { prompt: '' };
|
|
986
995
|
const prompt = `${PREP_AUTOLOOP_INTRO}
|
|
987
996
|
|
|
988
|
-
${buildAutoLoopGroomingSteps(e2eSettings)}
|
|
997
|
+
${buildAutoLoopGroomingSteps(e2eSettings, finalizationSettings)}
|
|
989
998
|
|
|
990
999
|
${AUTO_LOOP_HARD_RULES}`;
|
|
991
1000
|
return c.json({ prompt });
|
|
@@ -1439,6 +1448,9 @@ app.get('/:id/diff', (c) => {
|
|
|
1439
1448
|
try {
|
|
1440
1449
|
const id = c.req.param('id');
|
|
1441
1450
|
const mode = c.req.query('mode') === 'unpushed' ? 'unpushed' : 'branch';
|
|
1451
|
+
// Opt-in flag from the diff viewer toggle. Only meaningful in `branch`
|
|
1452
|
+
// mode — `unpushed` is committed-only by definition.
|
|
1453
|
+
const includeUntracked = c.req.query('includeUntracked') === '1';
|
|
1442
1454
|
const workspace = workspaceService.getWorkspace(id);
|
|
1443
1455
|
if (!workspace) {
|
|
1444
1456
|
return c.json({ error: `Workspace '${id}' not found` }, 404);
|
|
@@ -1446,7 +1458,7 @@ app.get('/:id/diff', (c) => {
|
|
|
1446
1458
|
const worktreePath = workspace.worktreePath;
|
|
1447
1459
|
const files = mode === 'unpushed'
|
|
1448
1460
|
? gitOps.getUnpushedChangedFiles(worktreePath, workspace.workingBranch)
|
|
1449
|
-
: gitOps.getChangedFiles(worktreePath, workspace.sourceBranch);
|
|
1461
|
+
: gitOps.getChangedFiles(worktreePath, workspace.sourceBranch, includeUntracked);
|
|
1450
1462
|
c.header('Cache-Control', 'no-store');
|
|
1451
1463
|
return c.json({
|
|
1452
1464
|
files,
|
|
@@ -1489,6 +1501,38 @@ app.get('/:id/diff-file', (c) => {
|
|
|
1489
1501
|
return c.json({ error: message }, 500);
|
|
1490
1502
|
}
|
|
1491
1503
|
});
|
|
1504
|
+
// POST /api/workspaces/:id/rollback-file { path }
|
|
1505
|
+
// Reset a single file to its `origin/<workingBranch>` version (overwrites
|
|
1506
|
+
// working tree + index). Used by the right-click menu in the diff viewer.
|
|
1507
|
+
// Returns 422 when the branch has never been pushed (no remote ref to
|
|
1508
|
+
// rollback to) so the UI can disable the action gracefully.
|
|
1509
|
+
app.post('/:id/rollback-file', async (c) => {
|
|
1510
|
+
try {
|
|
1511
|
+
const id = c.req.param('id');
|
|
1512
|
+
const workspace = workspaceService.getWorkspace(id);
|
|
1513
|
+
if (!workspace) {
|
|
1514
|
+
return c.json({ error: `Workspace '${id}' not found` }, 404);
|
|
1515
|
+
}
|
|
1516
|
+
const body = await c.req.json();
|
|
1517
|
+
const filePath = typeof body?.path === 'string' ? body.path.trim() : '';
|
|
1518
|
+
if (!filePath) {
|
|
1519
|
+
return c.json({ error: 'Missing or invalid `path` field' }, 400);
|
|
1520
|
+
}
|
|
1521
|
+
let target;
|
|
1522
|
+
try {
|
|
1523
|
+
target = gitOps.rollbackFile(workspace.worktreePath, workspace.workingBranch, filePath);
|
|
1524
|
+
}
|
|
1525
|
+
catch (err) {
|
|
1526
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1527
|
+
return c.json({ error: message }, 422);
|
|
1528
|
+
}
|
|
1529
|
+
return c.json({ ok: true, path: filePath, target });
|
|
1530
|
+
}
|
|
1531
|
+
catch (err) {
|
|
1532
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1533
|
+
return c.json({ error: message }, 500);
|
|
1534
|
+
}
|
|
1535
|
+
});
|
|
1492
1536
|
// GET /api/workspaces/:id/commits?limit=50 — list commits between sourceBranch
|
|
1493
1537
|
// and HEAD, each tagged with whether it's already pushed to origin/<branch>.
|
|
1494
1538
|
app.get('/:id/commits', (c) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import { buildE2eIterationBlock } from '../../shared/auto-loop-prompts.js';
|
|
3
|
+
import { buildE2eIterationBlock, buildFinalizationIterationBlock } from '../../shared/auto-loop-prompts.js';
|
|
4
4
|
import { getDb } from '../db/index.js';
|
|
5
5
|
import * as orchestrator from './agent/orchestrator.js';
|
|
6
6
|
import * as settingsService from './settings-service.js';
|
|
@@ -172,7 +172,7 @@ Current pending task (highest priority, non-acceptance-criterion first):
|
|
|
172
172
|
- Task ID: {taskId}
|
|
173
173
|
- Title: {taskTitle}
|
|
174
174
|
- Is acceptance criterion: {isAcceptanceCriterion}
|
|
175
|
-
{
|
|
175
|
+
{overrideBlock}
|
|
176
176
|
Your job this iteration:
|
|
177
177
|
1. Read \`kobo__list_tasks\` to see all tasks and the big picture.
|
|
178
178
|
2. Implement the SINGLE task above and nothing else. Do not pick a different task.
|
|
@@ -225,19 +225,26 @@ function spawnNextIteration(workspaceId, opts = {}) {
|
|
|
225
225
|
return;
|
|
226
226
|
}
|
|
227
227
|
const iterationNumber = computeIterationNumber(workspaceId);
|
|
228
|
-
//
|
|
229
|
-
//
|
|
230
|
-
//
|
|
231
|
-
//
|
|
228
|
+
// Override block: replaces the standard iteration prompt body when the task
|
|
229
|
+
// title carries a recognized prefix (case-sensitive, trailing space required).
|
|
230
|
+
// Empty string otherwise so the placeholder collapses cleanly in PROMPT_TEMPLATE.
|
|
231
|
+
// A title cannot literally start with both prefixes, so the order of these
|
|
232
|
+
// branches is purely cosmetic.
|
|
232
233
|
const projectSettings = settingsService.getProjectSettings(row.project_path);
|
|
233
234
|
const e2eSettings = projectSettings?.e2e ?? { framework: '', skill: '', prompt: '' };
|
|
234
|
-
const
|
|
235
|
-
|
|
235
|
+
const finalizationSettings = projectSettings?.finalization ?? { prompt: '' };
|
|
236
|
+
let overrideBlock = '';
|
|
237
|
+
if (task.title.startsWith('[FINAL] ')) {
|
|
238
|
+
overrideBlock = buildFinalizationIterationBlock(finalizationSettings);
|
|
239
|
+
}
|
|
240
|
+
else if (task.title.startsWith('[E2E] ') && e2eSettings.framework) {
|
|
241
|
+
overrideBlock = buildE2eIterationBlock(e2eSettings);
|
|
242
|
+
}
|
|
236
243
|
const prompt = PROMPT_TEMPLATE.replaceAll('{n}', String(iterationNumber))
|
|
237
244
|
.replaceAll('{taskId}', task.id)
|
|
238
245
|
.replaceAll('{taskTitle}', task.title)
|
|
239
246
|
.replaceAll('{isAcceptanceCriterion}', String(task.isAcceptanceCriterion))
|
|
240
|
-
.replaceAll('{
|
|
247
|
+
.replaceAll('{overrideBlock}', overrideBlock);
|
|
241
248
|
const worktreePath = row.worktree_path ?? path.join(row.project_path, '.worktrees', row.working_branch);
|
|
242
249
|
// Auto-loop iterations always run in auto-accept mode. Plan mode blocks MCP
|
|
243
250
|
// tools (kobo__mark_task_done, etc.) and Edit/Write/Bash — everything the
|
|
@@ -53,6 +53,12 @@ Please:
|
|
|
53
53
|
3. Post a comment on the PR summarizing what was done and any follow-up items
|
|
54
54
|
4. Do NOT add a "Generated with Claude Code" footer or any AI attribution to the PR description
|
|
55
55
|
`;
|
|
56
|
+
export const DEFAULT_FINALIZATION_PROMPT = `Run final quality checks before closing the workspace:
|
|
57
|
+
|
|
58
|
+
1. Verify all other tasks are marked \`done\`. If any remain \`pending\`, stop and report.
|
|
59
|
+
2. Run the project's linters, type-checkers, and tests (see CLAUDE.md or package.json scripts).
|
|
60
|
+
3. If any check fails, create a new regular task at the end of the list with a title like \`Fix lint failure in X\` (NO \`[FINAL]\` or \`[E2E]\` prefix — it must use the default iteration prompt) and mark this \`[FINAL]\` task as \`done\`. The auto-loop will pick up the fix on the next iteration. The finalization mechanism is single-shot per grooming pass; if you want quality checks to re-run after the fix, mark the fix task \`done\` and re-trigger grooming manually.
|
|
61
|
+
4. If everything passes, mark this task as \`done\`.`;
|
|
56
62
|
/** Default workspace tags seeded on fresh install and on settings upgrade. */
|
|
57
63
|
export const DEFAULT_WORKSPACE_TAGS = [
|
|
58
64
|
'bug',
|
|
@@ -170,6 +176,21 @@ const settingsMigrations = [
|
|
|
170
176
|
}
|
|
171
177
|
},
|
|
172
178
|
},
|
|
179
|
+
{
|
|
180
|
+
version: 10,
|
|
181
|
+
name: 'add-project-finalization',
|
|
182
|
+
migrate({ projects }) {
|
|
183
|
+
for (const p of projects) {
|
|
184
|
+
if (!p.finalization || typeof p.finalization !== 'object') {
|
|
185
|
+
p.finalization = { prompt: DEFAULT_FINALIZATION_PROMPT };
|
|
186
|
+
}
|
|
187
|
+
else if (typeof p.finalization.prompt !== 'string') {
|
|
188
|
+
;
|
|
189
|
+
p.finalization.prompt = DEFAULT_FINALIZATION_PROMPT;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
},
|
|
173
194
|
];
|
|
174
195
|
/** Current settings schema version — always equals the highest migration version. */
|
|
175
196
|
export const SETTINGS_SCHEMA_VERSION = settingsMigrations.length > 0 ? settingsMigrations[settingsMigrations.length - 1].version : 0;
|
|
@@ -233,6 +254,9 @@ function defaultProjectSettings(projectPath) {
|
|
|
233
254
|
skill: '',
|
|
234
255
|
prompt: '',
|
|
235
256
|
},
|
|
257
|
+
finalization: {
|
|
258
|
+
prompt: DEFAULT_FINALIZATION_PROMPT,
|
|
259
|
+
},
|
|
236
260
|
};
|
|
237
261
|
}
|
|
238
262
|
function pickKnownKeys(data, allowedKeys) {
|
|
@@ -439,7 +463,7 @@ export function updateGlobalSettings(data) {
|
|
|
439
463
|
writeSettings(settings, { backup: true });
|
|
440
464
|
return settings.global;
|
|
441
465
|
}
|
|
442
|
-
/** Create or update project-specific settings. Merges devServer and
|
|
466
|
+
/** Create or update project-specific settings. Merges devServer, e2e, and finalization fields on update. */
|
|
443
467
|
export function upsertProject(projectPath, data) {
|
|
444
468
|
const allowedProjectKeys = [
|
|
445
469
|
'displayName',
|
|
@@ -451,9 +475,11 @@ export function upsertProject(projectPath, data) {
|
|
|
451
475
|
'setupScript',
|
|
452
476
|
'devServer',
|
|
453
477
|
'e2e',
|
|
478
|
+
'finalization',
|
|
454
479
|
];
|
|
455
480
|
const allowedDevServerKeys = ['startCommand', 'stopCommand'];
|
|
456
481
|
const allowedE2eKeys = ['framework', 'skill', 'prompt'];
|
|
482
|
+
const allowedFinalizationKeys = ['prompt'];
|
|
457
483
|
const filtered = pickKnownKeys(data, allowedProjectKeys);
|
|
458
484
|
if (filtered.devServer) {
|
|
459
485
|
filtered.devServer = pickKnownKeys(filtered.devServer, allowedDevServerKeys);
|
|
@@ -461,20 +487,28 @@ export function upsertProject(projectPath, data) {
|
|
|
461
487
|
if (filtered.e2e) {
|
|
462
488
|
filtered.e2e = pickKnownKeys(filtered.e2e, allowedE2eKeys);
|
|
463
489
|
}
|
|
490
|
+
if (filtered.finalization) {
|
|
491
|
+
filtered.finalization = pickKnownKeys(filtered.finalization, allowedFinalizationKeys);
|
|
492
|
+
}
|
|
464
493
|
const settings = readSettings();
|
|
465
494
|
const idx = settings.projects.findIndex((p) => p.path === projectPath);
|
|
466
495
|
if (idx >= 0) {
|
|
467
|
-
// Update existing project — merge devServer and
|
|
496
|
+
// Update existing project — merge devServer, e2e, and finalization separately to allow partial updates
|
|
468
497
|
const existing = settings.projects[idx];
|
|
469
498
|
const updatedDevServer = filtered.devServer ? { ...existing.devServer, ...filtered.devServer } : existing.devServer;
|
|
470
499
|
const existingE2e = existing.e2e ?? defaultProjectSettings(projectPath).e2e;
|
|
471
500
|
const updatedE2e = filtered.e2e ? { ...existingE2e, ...filtered.e2e } : existingE2e;
|
|
501
|
+
const existingFinalization = existing.finalization ?? defaultProjectSettings(projectPath).finalization;
|
|
502
|
+
const updatedFinalization = filtered.finalization
|
|
503
|
+
? { ...existingFinalization, ...filtered.finalization }
|
|
504
|
+
: existingFinalization;
|
|
472
505
|
settings.projects[idx] = {
|
|
473
506
|
...existing,
|
|
474
507
|
...filtered,
|
|
475
508
|
path: projectPath,
|
|
476
509
|
devServer: updatedDevServer,
|
|
477
510
|
e2e: updatedE2e,
|
|
511
|
+
finalization: updatedFinalization,
|
|
478
512
|
};
|
|
479
513
|
}
|
|
480
514
|
else {
|
|
@@ -490,6 +524,9 @@ export function upsertProject(projectPath, data) {
|
|
|
490
524
|
if (filtered.e2e) {
|
|
491
525
|
newProject.e2e = { ...defaultProjectSettings(projectPath).e2e, ...filtered.e2e };
|
|
492
526
|
}
|
|
527
|
+
if (filtered.finalization) {
|
|
528
|
+
newProject.finalization = { ...defaultProjectSettings(projectPath).finalization, ...filtered.finalization };
|
|
529
|
+
}
|
|
493
530
|
settings.projects.push(newProject);
|
|
494
531
|
}
|
|
495
532
|
writeSettings(settings, { backup: true });
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import { broadcastAll } from '../websocket-service.js';
|
|
2
2
|
import { upsertUsageSnapshot } from './db.js';
|
|
3
3
|
import { createClaudeCodeProvider } from './providers/claude-code.js';
|
|
4
|
-
|
|
4
|
+
// 5 minutes — the Anthropic `five_hour` / `seven_day` buckets are slow-moving
|
|
5
|
+
// so a tighter cadence just burns rate limit (429s) without surfacing fresher
|
|
6
|
+
// data to the UI. The user can still trigger a manual refresh via `refreshNow`.
|
|
7
|
+
export const POLL_INTERVAL_MS = 5 * 60_000;
|
|
5
8
|
const DEFAULT_PROVIDERS = [createClaudeCodeProvider()];
|
|
6
9
|
let providers = DEFAULT_PROVIDERS;
|
|
7
10
|
let intervalHandle = null;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFile as execFileCb, execFileSync } from 'node:child_process';
|
|
2
|
-
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { existsSync, readFileSync, rmSync } from 'node:fs';
|
|
3
3
|
import { join } from 'node:path';
|
|
4
4
|
import { promisify } from 'node:util';
|
|
5
5
|
const execFileAsync = promisify(execFileCb);
|
|
@@ -410,7 +410,7 @@ export function moveWorktree(projectPath, oldPath, newPath) {
|
|
|
410
410
|
git(projectPath, ['worktree', 'move', oldPath, newPath]);
|
|
411
411
|
}
|
|
412
412
|
/** List files changed between base and HEAD (committed), plus working tree changes. */
|
|
413
|
-
export function getChangedFiles(repoPath, base) {
|
|
413
|
+
export function getChangedFiles(repoPath, base, includeUntracked = false) {
|
|
414
414
|
const ref = resolveBase(repoPath, base);
|
|
415
415
|
const files = [];
|
|
416
416
|
const seen = new Set();
|
|
@@ -443,9 +443,14 @@ export function getChangedFiles(repoPath, base) {
|
|
|
443
443
|
catch {
|
|
444
444
|
// No commits yet
|
|
445
445
|
}
|
|
446
|
-
// Working tree changes (uncommitted)
|
|
446
|
+
// Working tree changes (uncommitted). Default to `-uno` to skip pure
|
|
447
|
+
// untracked files: they have never been `git add`-ed and won't ship in
|
|
448
|
+
// the next commit/PR, so showing them in the diff viewer is misleading.
|
|
449
|
+
// When `includeUntracked` is true (user opt-in via the diff viewer toggle)
|
|
450
|
+
// we use `-uall` and surface them with status='added'.
|
|
447
451
|
try {
|
|
448
|
-
const
|
|
452
|
+
const flag = includeUntracked ? '-uall' : '-uno';
|
|
453
|
+
const output = git(repoPath, ['status', '--porcelain', flag]);
|
|
449
454
|
for (const line of output.split('\n')) {
|
|
450
455
|
if (!line)
|
|
451
456
|
continue;
|
|
@@ -456,7 +461,7 @@ export function getChangedFiles(repoPath, base) {
|
|
|
456
461
|
const y = line[1];
|
|
457
462
|
let status = 'modified';
|
|
458
463
|
if (x === '?' && y === '?')
|
|
459
|
-
status = '
|
|
464
|
+
status = 'untracked';
|
|
460
465
|
else if (x === 'A' || y === 'A')
|
|
461
466
|
status = 'added';
|
|
462
467
|
else if (x === 'D' || y === 'D')
|
|
@@ -523,6 +528,63 @@ export function getFileAtRef(repoPath, ref, filePath) {
|
|
|
523
528
|
return null;
|
|
524
529
|
}
|
|
525
530
|
}
|
|
531
|
+
/**
|
|
532
|
+
* Reset a single file in the worktree to a sensible baseline. Cascade:
|
|
533
|
+
* 1. `origin/<branchName>` if the remote ref AND the file exist there
|
|
534
|
+
* (typical: branch is pushed, user wants to undo all local changes).
|
|
535
|
+
* 2. `HEAD` if the file exists at the last local commit (typical: branch
|
|
536
|
+
* not yet pushed, or file was added in commits that aren't on remote
|
|
537
|
+
* yet — discards just the uncommitted edits, keeps the commits).
|
|
538
|
+
* 3. **Delete** the file from disk when it's untracked (not on remote AND
|
|
539
|
+
* not in HEAD): there's nothing to "rollback to", so the only sensible
|
|
540
|
+
* undo is to remove the local-only file. Caller MUST surface this to
|
|
541
|
+
* the user with an explicit confirmation message — the action is
|
|
542
|
+
* permanent.
|
|
543
|
+
*
|
|
544
|
+
* Throws on filesystem errors (permission denied, etc.). Returns the
|
|
545
|
+
* target that was actually used so the caller can surface the right
|
|
546
|
+
* feedback in the UI.
|
|
547
|
+
*/
|
|
548
|
+
export function rollbackFile(repoPath, branchName, filePath, remote = 'origin') {
|
|
549
|
+
const remoteRef = `${remote}/${branchName}`;
|
|
550
|
+
let remoteRefExists = false;
|
|
551
|
+
try {
|
|
552
|
+
git(repoPath, ['rev-parse', '--verify', remoteRef]);
|
|
553
|
+
remoteRefExists = true;
|
|
554
|
+
}
|
|
555
|
+
catch {
|
|
556
|
+
// Branch never pushed — fall through to HEAD.
|
|
557
|
+
}
|
|
558
|
+
if (remoteRefExists) {
|
|
559
|
+
try {
|
|
560
|
+
git(repoPath, ['cat-file', '-e', `${remoteRef}:${filePath}`]);
|
|
561
|
+
git(repoPath, ['checkout', remoteRef, '--', filePath]);
|
|
562
|
+
return 'remote';
|
|
563
|
+
}
|
|
564
|
+
catch {
|
|
565
|
+
// File doesn't exist at origin/<branch> (added locally) — fall through.
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
try {
|
|
569
|
+
git(repoPath, ['cat-file', '-e', `HEAD:${filePath}`]);
|
|
570
|
+
git(repoPath, ['checkout', 'HEAD', '--', filePath]);
|
|
571
|
+
return 'head';
|
|
572
|
+
}
|
|
573
|
+
catch {
|
|
574
|
+
// File is untracked OR has already been rolled back — delete it from
|
|
575
|
+
// disk if still present. Idempotent: if the file is already gone (race
|
|
576
|
+
// with a previous rollback, stale UI list, manual rm), we still return
|
|
577
|
+
// 'deleted' since the end state matches the user's intent. `rmSync`
|
|
578
|
+
// over `git clean -f` keeps the action narrow to one file.
|
|
579
|
+
const absPath = join(repoPath, filePath);
|
|
580
|
+
if (existsSync(absPath)) {
|
|
581
|
+
rmSync(absPath, { force: true });
|
|
582
|
+
}
|
|
583
|
+
return 'deleted';
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
/** @deprecated kept for backwards-compat with older imports — use `rollbackFile`. */
|
|
587
|
+
export const rollbackFileToRemote = rollbackFile;
|
|
526
588
|
/** Get the current content of a file in the worktree. Returns null if the file doesn't exist. */
|
|
527
589
|
export function getFileContent(repoPath, filePath) {
|
|
528
590
|
try {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* `AUTO_LOOP_HARD_RULES` is the trailing hard-rules block, same for both.
|
|
18
18
|
*/
|
|
19
19
|
export const PREP_AUTOLOOP_INTRO = `You are preparing this workspace for Kōbō auto-loop mode. This is a GROOMING session only — DO NOT implement anything, DO NOT write or edit code, DO NOT run tests or builds, DO NOT invoke \`superpowers:executing-plans\` or any implementation skill. Your ONLY job is to curate the Kōbō task list via MCP tools.`;
|
|
20
|
-
export function buildAutoLoopGroomingSteps(e2e) {
|
|
20
|
+
export function buildAutoLoopGroomingSteps(e2e, finalization) {
|
|
21
21
|
const steps = [
|
|
22
22
|
`1. Call \`kobo__list_tasks\` FIRST to inspect any pre-existing tasks (they may have been seeded from Notion, a template, or the CreatePage form).`,
|
|
23
23
|
`2. If tasks already exist: DO NOT delete or recreate them from scratch. Read each one, judge whether it is atomic and implementable in one session with clear completion criteria. Improve them in place:
|
|
@@ -29,19 +29,31 @@ export function buildAutoLoopGroomingSteps(e2e) {
|
|
|
29
29
|
- If no plan exists, ask the user what the workspace goal is and propose tasks accordingly.
|
|
30
30
|
- Create the tasks via \`kobo__create_task\`. For each task, decide \`is_acceptance_criterion\` appropriately.`,
|
|
31
31
|
];
|
|
32
|
+
let nextNum = 4;
|
|
32
33
|
if (e2e.framework) {
|
|
33
34
|
const skillHint = e2e.skill ? `Use the \`${e2e.skill}\` skill for this task. ` : '';
|
|
34
35
|
const promptHint = e2e.prompt ? `Additional guidance: ${e2e.prompt}` : '';
|
|
35
|
-
steps.push(
|
|
36
|
-
|
|
36
|
+
steps.push(`${nextNum}. **E2E review**: walk the task list and identify which tasks produce user-visible behavior (UI flows, form submissions, page renders, etc.). For each one that warrants regression coverage, INSERT a follow-up sub-task with title prefixed \`[E2E] \` describing the test to write. Place it in \`sort_order\` directly after the parent task. Skip tasks that don't produce user-visible behavior (refactors, infra, internal services) and briefly justify your choices in chat. The project uses \`${e2e.framework}\`. ${skillHint}${promptHint}`.trim());
|
|
37
|
+
nextNum++;
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
-
steps.push(
|
|
39
|
+
if (finalization.prompt) {
|
|
40
|
+
steps.push(`${nextNum}. **Finalization task**: create ONE task with title prefixed \`[FINAL] <descriptive title>\`. Place it at the END of the task list (sort_order = max + 1, AFTER any [E2E] tasks). The agent will execute this task using the project's finalization prompt — do NOT inline the prompt content into the task title or description.`);
|
|
41
|
+
nextNum++;
|
|
40
42
|
}
|
|
43
|
+
steps.push(`${nextNum}. Call \`kobo__mark_auto_loop_ready\`. This will automatically start the auto-loop, which will pick up the tasks one by one in fresh sessions.`);
|
|
41
44
|
return steps.join('\n');
|
|
42
45
|
}
|
|
43
|
-
/** @deprecated Use buildAutoLoopGroomingSteps({ framework: '', skill: '', prompt: '' }) instead. */
|
|
44
|
-
export const AUTO_LOOP_GROOMING_STEPS = buildAutoLoopGroomingSteps({ framework: '', skill: '', prompt: '' });
|
|
46
|
+
/** @deprecated Use buildAutoLoopGroomingSteps({ framework: '', skill: '', prompt: '' }, { prompt: '' }) instead. */
|
|
47
|
+
export const AUTO_LOOP_GROOMING_STEPS = buildAutoLoopGroomingSteps({ framework: '', skill: '', prompt: '' }, { prompt: '' });
|
|
48
|
+
export function buildFinalizationIterationBlock(finalization) {
|
|
49
|
+
if (!finalization.prompt)
|
|
50
|
+
return '';
|
|
51
|
+
return `
|
|
52
|
+
This is the **finalization task**. Follow this prompt instead of the standard 8 steps below:
|
|
53
|
+
|
|
54
|
+
${finalization.prompt}
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
45
57
|
export function buildE2eIterationBlock(e2e) {
|
|
46
58
|
if (!e2e.framework)
|
|
47
59
|
return '';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.15",
|
|
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",
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
.message-choices[data-v-29c0dc7a]{flex-wrap:wrap;align-items:stretch;display:flex}.message-choice-btn[data-v-29c0dc7a]{background:#818cf814;border:1px solid #818cf859;border-radius:6px;max-width:360px;font-size:12px}.message-choice-btn[data-v-29c0dc7a] .q-btn__content{flex-wrap:nowrap;justify-content:flex-start}.message-choice-btn[data-v-29c0dc7a]:hover{background:#818cf82e}.choice-label[data-v-29c0dc7a]{text-overflow:ellipsis;white-space:nowrap;max-width:320px;overflow:hidden}.markdown-message[data-v-8382750f]{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-8382750f] *{max-width:100%}.markdown-message[data-v-8382750f] p{margin:0 0 .5em}.markdown-message[data-v-8382750f] p:last-child{margin-bottom:0}.markdown-message[data-v-8382750f] pre{background:#00000059;border-radius:4px;margin:.5em 0;padding:.5em .75em;overflow-x:auto}.markdown-message[data-v-8382750f] code{word-break:break-all;background:#0000004d;border-radius:3px;padding:.1em .3em;font-size:.9em}.markdown-message[data-v-8382750f] pre code{background:0 0;padding:0}.markdown-message[data-v-8382750f] ul,.markdown-message[data-v-8382750f] ol{margin:.25em 0 .5em;padding-left:1.5em}.markdown-message[data-v-8382750f] li{margin:.15em 0}.markdown-message[data-v-8382750f] a{color:#7986cb;text-decoration:underline}.markdown-message[data-v-8382750f] .document-link{color:#9fa8da;cursor:pointer;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}.markdown-message[data-v-8382750f] .document-link:hover{color:#c5cae9;-webkit-text-decoration:underline;text-decoration:underline}.markdown-message[data-v-8382750f] h1,.markdown-message[data-v-8382750f] h2,.markdown-message[data-v-8382750f] h3,.markdown-message[data-v-8382750f] h4,.markdown-message[data-v-8382750f] h5,.markdown-message[data-v-8382750f] h6{margin:.5em 0 .3em;font-weight:600;line-height:1.3}.markdown-message[data-v-8382750f] h1{font-size:1.25em}.markdown-message[data-v-8382750f] h2{font-size:1.15em}.markdown-message[data-v-8382750f] h3{font-size:1.08em}.markdown-message[data-v-8382750f] h4,.markdown-message[data-v-8382750f] h5,.markdown-message[data-v-8382750f] h6{font-size:1em}.markdown-message[data-v-8382750f] blockquote{color:#ffffffb3;border-left:3px solid #fff3;margin:.5em 0;padding-left:.75em}.markdown-message[data-v-8382750f] table{border-collapse:collapse;margin:.5em 0}.markdown-message[data-v-8382750f] th,.markdown-message[data-v-8382750f] 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-813aff2b]{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-813aff2b]{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-813aff2b]{letter-spacing:.3px;border-radius:3px;padding:2px 8px;font-size:11px;font-weight:700}.turn-badge-user[data-v-813aff2b]{color:#ce93d8;background:#ce93d826}.turn-badge-agent[data-v-813aff2b]{color:#7986cb;background:#7986cb26}.turn-badge-system[data-v-813aff2b]{color:#bdbdbd;background:#75757533;font-style:italic}.turn-badge-session[data-v-813aff2b]{color:#9e9e9e;background:#61616133}.turn-time[data-v-813aff2b]{color:#666;font-family:SF Mono,Menlo,Consolas,monospace;font-size:11px}.turn-time-arrow[data-v-813aff2b]{opacity:.7;margin:0 -2px}.turn-time-updated[data-v-813aff2b]{color:#8891a3}.turn-actions[data-v-813aff2b]{color:#777;font-size:11px}.turn-body[data-v-813aff2b]{flex-direction:column;gap:12px;min-width:0;padding:14px 18px;display:flex}.turn-body[data-v-813aff2b]>*{min-width:0;max-width:100%}.turn-body[data-v-813aff2b] .tool-row+.tool-row{margin-top:-8px}.turn-scroll-top[data-v-813aff2b]{justify-content:flex-start;padding:0 8px 6px;display:flex}.turn-scroll-top-btn[data-v-813aff2b]{opacity:.5;transition:opacity .15s}.turn-scroll-top-btn[data-v-813aff2b]:hover{opacity:1}.activity-feed-wrap[data-v-989e89a0]{width:100%;height:100%;position:relative}.activity-feed-scroll[data-v-989e89a0]{width:100%;height:100%}.activity-feed-nav-cluster[data-v-989e89a0]{z-index:2;align-items:center;gap:8px;display:flex;position:absolute;bottom:14px;right:14px}.activity-feed-nav-btn[data-v-989e89a0]{opacity:.8;transition:opacity .12s}.activity-feed-nav-btn[data-v-989e89a0]:hover{opacity:1}.content-origin-marker[data-v-989e89a0]{pointer-events:none;width:0;height:0;margin:0;padding:0}.activity-feed-scroll[data-v-989e89a0] .q-scrollarea__content{max-width:100%;overflow-x:hidden}.activity-feed-switching[data-v-989e89a0]{justify-content:center;align-items:center;width:100%;height:100%;display:flex}
|
|
@@ -0,0 +1,8 @@
|
|
|
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-Cw4mtk9x.js";import{t as w}from"./QBtn-CyzfM9-_.js";import{n as T}from"./vue-i18n-BVrBmgZa.js";import{d as E,h as D,l as O,p as k,v as A}from"./index-pGAaG7Rh.js";import{t as j}from"./QSpinnerDots-D7bo_KgI.js";import{t as M}from"./QExpansionItem-CUXuOfeR.js";import{t as ee}from"./QScrollArea-N10UpHIf.js";import{n as N,t as P}from"./marked.esm-D7ibHC_y.js";import{t as F}from"./QTooltip-DLT8jCHz.js";import{t as I}from"./_plugin-vue_export-helper-CpNzZuug.js";import{t as L}from"./documents-BMdAS6h8.js";function te(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`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 ne(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 re(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))}}),V={key:0,class:`message-choices q-mt-sm`},ie={class:`choice-key text-weight-medium`},ae={class:`choice-label q-ml-xs ellipsis`},H=I(v({__name:`MessageChoices`,props:{choices:{},active:{type:Boolean}},setup(e){let n=e,i=O(),a=E();function s(e){if(!n.active)return;let t=a.selectedWorkspaceId;if(!t)return;let r=`${e.key}. ${e.label}`,o=a.selectedSessionId??void 0;i.sendChatMessage(t,r,o),a.addActivityItem(t,{id:`user-${Date.now()}`,type:`text`,content:r,timestamp:new Date().toISOString(),sessionId:o,meta:{sender:`user`,pending:!0}})}return(n,i)=>e.choices.length>0&&e.active?(t(),m(`div`,V,[(t(!0),m(h,null,r(e.choices,e=>(t(),l(w,{key:e.key,flat:``,dense:``,"no-caps":``,size:`sm`,color:`indigo-3`,class:`message-choice-btn q-mr-xs q-mb-xs`,onClick:t=>s(e)},{default:o(()=>[_(`span`,ie,c(e.key)+`.`,1),_(`span`,ae,c(e.label),1)]),_:2},1032,[`onClick`]))),128))])):u(``,!0)}}),[[`__scopeId`,`data-v-29c0dc7a`]]),oe=5,U=/^\s*(?:[-*]|\d+\.)\s+(?:\*\*([A-Za-z0-9])\.?\*\*|([A-Za-z])\.)\s+(.+?)\s*$/;function se(e){if(!e)return null;let t=e.split(`
|
|
2
|
+
`),n=0;for(;n<t.length;){let e=t[n].match(U);if(!e){n++;continue}let r=n,i=[{key:e[1]??e[2],label:e[3]}],a=n+1;for(;a<t.length;){let e=t[a];if(e.trim()===``){if(a+1<t.length&&t[a+1].trim()===``)break;a++;continue}let n=e.match(U);if(!n)break;i.push({key:n[1]??n[2],label:n[3]}),a++}if(i.length>=2){let e=Math.max(0,r-oe);if(t.slice(e,r).join(` `).includes(`?`))return{choices:i}}n=a}return null}function ce(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){W(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 W(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=le(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 le(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 G=[`innerHTML`],K=I(v({__name:`TextMessageItem`,props:{item:{},isLatestTurn:{type:Boolean}},setup(e){let n=e,r=L(),i=E(),a=p(()=>{let e=i.selectedWorkspaceId;return e?r.documentsFor(e).map(e=>e.path):[]}),o=p(()=>{let e=ce(P.parse(n.item.text,{async:!1,breaks:!0,gfm:!0}),a.value);return N.sanitize(e,{ADD_ATTR:[`data-document-path`]})}),s=p(()=>se(n.item.text));function c(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:c},[_(`div`,{innerHTML:o.value},null,8,G),e.item.streaming?(t(),l(x,{key:0,size:`xs`,class:`q-ml-xs`})):u(``,!0),s.value?(t(),l(H,{key:1,choices:s.value.choices,active:!!e.isLatestTurn&&!e.item.streaming},null,8,[`choices`,`active`])):u(``,!0)]))}}),[[`__scopeId`,`data-v-8382750f`]]),ue={key:0,class:`text-caption text-grey-5`,style:{"font-style":`italic`}},q=[`innerHTML`],de={key:1,style:{"white-space":`pre-wrap`}},J=I(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=P.parse(n.item.text,{async:!1,breaks:!0,gfm:!0});return N.sanitize(e)});return(n,d)=>i.value?(t(),m(`div`,ue,[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,q)]),_:1},8,[`label`])):(t(),m(`span`,de,c(e.item.text),1))])):u(``,!0)}}),[[`__scopeId`,`data-v-4e64694c`]]);function Y(e,t){let n=e.split(`
|
|
3
|
+
`),r=t.split(`
|
|
4
|
+
`),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 fe(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(`
|
|
5
|
+
`).length:0,deletions:t?t.split(`
|
|
6
|
+
`).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(`
|
|
7
|
+
`).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 X(e,t){if(!e||!t?.projectPath)return e;let n=Z(e,`${t.projectPath}/.worktrees/${t.workingBranch}`);return n===e&&(n=Z(e,t.projectPath)),n}function Z(e,t){if(!t)return e;let n=t.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return e.replace(RegExp(`${n}/`,`g`),``).replace(RegExp(`${n}(?=\\s|$|["'\`])`,`g`),`.`)}var Q={class:`tool-name`},$=[`title`],pe={key:0,class:`tool-stat-add`},me={key:1,class:`tool-stat-del`},he={class:`diff-sign`},ge={class:`tool-name`},_e=[`title`],ve=I(v({__name:`ToolCallItem`,props:{item:{}},setup(e){let i=e,o=a(!1),g=E(),v=p(()=>fe(i.item.name,i.item.input)),y=p(()=>v.value?X(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?X(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 D=p(()=>{let e=v.value;return e?e.toolName===`Edit`&&e.oldString!==void 0&&e.newString!==void 0?Y(e.oldString,e.newString):e.toolName===`Write`&&e.content!==void 0?e.content.split(`
|
|
8
|
+
`).map(e=>({type:`add`,content:e})):e.toolName===`Bash:rm`?[{type:`del`,content:`File deleted`}]:null:null}),O=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&&O.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`,Q,c(v.value.toolName===`Bash:rm`?`Bash`:v.value.toolName),1),_(`span`,{class:`tool-path`,title:v.value.filePath},c(y.value),9,$),v.value.additions>0?(t(),m(`span`,pe,`+`+c(v.value.additions),1)):u(``,!0),v.value.deletions>0?(t(),m(`span`,me,`-`+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&&D.value?(t(),m(`div`,{key:0,class:`tool-diff`,onClick:i[0]||=b(()=>{},[`stop`])},[(t(!0),m(h,null,r(D.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`,he,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`,ge,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,_e)):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(O.value),1)):u(``,!0)],2))}}),[[`__scopeId`,`data-v-b1fcd20d`]]);function ye(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 be=[`innerHTML`],xe=[`innerHTML`],Se=[`src`],Ce=I(v({__name:`UserMessageItem`,props:{item:{}},setup(e){let n=e,r=E(),i=p(()=>n.item.sender===`system-prompt`),s=p(()=>{let e=ye(n.item.content,r.selectedWorkspaceId??``),t=P.parse(e,{async:!1,breaks:!0,gfm:!0});return N.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,be)]),_:1},8,[`label`])):(t(),m(`div`,{key:1,class:`markdown-message`,onClick:g},[_(`div`,{innerHTML:s.value},null,8,xe)])),d(A,{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,Se)):u(``,!0)]),_:1},8,[`modelValue`])],64))}}),[[`__scopeId`,`data-v-c2e7c407`]]),we={class:`turn-header`},Te={key:0,class:`turn-time`},Ee={class:`turn-time turn-time-updated`},De={key:2,class:`turn-actions`},Oe={class:`turn-body`},ke={key:0,class:`turn-scroll-top`},Ae=I(v({__name:`TurnCard`,props:{turn:{},isLatestTurn:{type:Boolean}},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)}),j=p(()=>A.value!==``),M=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`,we,[_(`span`,{class:s([`turn-badge`,E.value.badgeClass])},c(E.value.label),3),O.value?(t(),m(`span`,Te,c(O.value),1)):u(``,!0),j.value?(t(),m(h,{key:1},[d(S,{name:`arrow_forward`,size:`10px`,color:`grey-7`,class:`turn-time-arrow`}),_(`span`,Ee,[f(c(A.value)+` `,1),d(F,null,{default:o(()=>[f(c(g(b)(`chat.lastUpdatedAt`,{time:A.value})),1)]),_:1})])],64)):u(``,!0),M.value>0?(t(),m(`span`,De,` · `+c(g(b)(`chat.nActions`,{n:M.value})),1)):u(``,!0)]),_(`div`,Oe,[(t(!0),m(h,null,r(e.turn.items,(n,r)=>(t(),m(h,{key:r},[n.type===`text`?(t(),l(K,{key:0,item:n,"is-latest-turn":e.isLatestTurn},null,8,[`item`,`is-latest-turn`])):n.type===`thinking`?(t(),l(J,{key:1,item:n},null,8,[`item`])):n.type===`tool`?(t(),l(ve,{key:2,item:n},null,8,[`item`])):n.type===`user`?(t(),l(Ce,{key:3,item:n},null,8,[`item`])):n.type===`session`?(t(),l(B,{key:4,item:n},null,8,[`item`])):u(``,!0)],64))),128))]),e.turn.items.length>4?(t(),m(`div`,ke,[d(w,{flat:``,round:``,dense:``,size:`xs`,icon:`arrow_upward`,color:`grey-6`,class:`turn-scroll-top-btn`,onClick:C},{default:o(()=>[d(F,null,{default:o(()=>[f(c(g(b)(`chat.scrollToTurnTop`)),1)]),_:1})]),_:1})])):u(``,!0)],6))}}),[[`__scopeId`,`data-v-813aff2b`]]),je={key:0,class:`activity-feed-switching`},Me={key:1,class:`activity-feed-wrap`},Ne={key:0,class:`text-center q-py-sm text-caption text-grey-6`},Pe={class:`q-pa-md`},Fe={key:1,class:`q-px-md q-pb-md`},Ie={class:`activity-feed-nav-cluster`},Le=60,Re=200,ze=200,Be=400,Ve=200,He=I(v({__name:`ActivityFeed`,props:{workspaceId:{}},setup(s){let g=s,v=D(),y=C(),b=E(),S=p(()=>b.selectedSessionId),T=p(()=>b.sessions.find(e=>e.id===S.value)?.engineSessionId??null),O=p(()=>{let e=b.sessions;return e.length===0?!1:S.value===e[e.length-1].id});function A(e){return S.value?e?e===S.value||e===T.value:O.value:!0}let N=p(()=>(b.activityFeeds[g.workspaceId]??[]).filter(e=>e.type===`text`&&typeof e.content==`string`&&A(e.sessionId)).map(e=>({content:e.content,sender:e.meta?.sender??`user`,ts:e.timestamp,sessionId:e.sessionId}))),P=p(()=>k(b.workspaces.find(e=>e.id===g.workspaceId)?.status)),F=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++)A(n[a])&&(r.push(e[a]),i.push(t[a]));let a=ne(te(r,i,P.value),N.value);return re(y.showVerboseSystemMessages?a:a.filter(e=>e.type!==`session`))}),I=p(()=>y.showVerboseSystemMessages?v.eventsFor(g.workspaceId).filter(e=>e.kind===`message:raw`).map(e=>e.content):[]),L=a(null),R=a(!0),z=a(!1),B=!1,V=a(!0),ie=a(new Map);function ae(e){R.value=e.verticalSize-e.verticalPosition-e.verticalContainerSize<=Le,B&&e.verticalPosition<=Re&&!z.value&&oe()&&ce()}function H(e,t){return`${e}:${t}`}function oe(){let e=S.value;return e?ie.value.get(H(g.workspaceId,e))??!0:v.hasMoreOlderFor(g.workspaceId)}function U(e,t,n){ie.value.set(H(e,t),n)}function se(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(!A(n[e]))continue;let r=t[e];if(r)return r}}async function ce(){let t=g.workspaceId,n=S.value,r=se(t);if(!r)return;z.value=!0;let i=Date.now();try{let i=L.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,ze)),[u]=await Promise.all([c,l]);if(!u.ok){n?U(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&&U(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,Re+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,ze-e);await new Promise(e=>setTimeout(e,t+Be)),z.value=!1}}async function W(t=0){await e();let n=L.value;if(!n)return;let r=n.getScroll();n.setScrollPosition(`vertical`,r.verticalSize,t)}function le(e){let t=L.value;t&&t.setScrollPosition(`vertical`,Math.max(0,e),250)}let G=a([]),K=a(null);function ue(){let e=F.value,t=G.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=K.value?.parentElement;if(r){let e=r.querySelectorAll(`.turn-card--user`);for(let t of e)n.push(t)}return n}function q(){let e=L.value;if(!e)return null;let t=K.value;if(!t)return null;let n=e.getScroll().verticalPosition,r=t.getBoundingClientRect().top,i=null;for(let e of ue()){let t=e.getBoundingClientRect().top-r;if(t<n-40)i=t;else break}return i}async function de(){let t=L.value;if(!t)return;let n=q();if(n===null)for(let t=0;t<15&&oe();t++){for(;z.value;)await new Promise(e=>setTimeout(e,50));if(await ce(),await e(),n=q(),n!==null)break}n!==null&&t.setScrollPosition(`vertical`,Math.max(0,n-12),250)}async function J(){B=!1,await e(),await W(0),requestAnimationFrame(()=>{requestAnimationFrame(()=>{B=!0})})}let Y=p(()=>{let e=v.sessionIdsFor(g.workspaceId);if(!S.value)return e.length;let t=0;for(let n of e)A(n)&&t++;return t}),fe=p(()=>v.eventsFor(g.workspaceId).length);async function X(){V.value=!0;let e=Date.now();await new Promise(e=>setTimeout(e,Ve));let t=e+5e3;for(;fe.value===0&&Date.now()<t;)await new Promise(e=>setTimeout(e,50));V.value=!1}n(V,async e=>{!e&&Y.value>0&&await J(),!e&&Y.value===0&&S.value&&$()}),i(()=>{X(),Y.value>0&&J(),S.value&&$()});let Z=!1;n(Y,async(e,t)=>{if(!Z&&e>0){Z=!0,await J();return}e>t&&R.value&&!z.value&&await W(180)}),n(()=>g.workspaceId,()=>{R.value=!0,Z=!1,B=!1,X(),Y.value>0&&J()}),n(()=>b.selectedSessionId,async()=>{R.value=!0,B=!1,await J(),$()});let Q=new Set;async function $(){let t=S.value;if(!t||Y.value>0)return;let n=H(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);U(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 W(0)}catch(e){console.error(`[ActivityFeed] fetchSessionIfMissing failed:`,e),Q.delete(n)}}}n(p(()=>N.value.filter(e=>e.sender!==`system-prompt`).length),async(e,t)=>{e>t&&(R.value=!0,await W(180))});async function pe(){R.value=!0,await W(250)}return(e,n)=>V.value?(t(),m(`div`,je,[d(j,{size:`40px`,color:`indigo-4`})])):(t(),m(`div`,Me,[d(ee,{ref_key:`scrollRef`,ref:L,class:`activity-feed-scroll`,onScroll:ae},{default:o(()=>[_(`div`,{ref_key:`contentOriginRef`,ref:K,class:`content-origin-marker`},null,512),z.value?(t(),m(`div`,Ne,[d(x,{size:`sm`}),f(` `+c(e.$t(`activity.loading_older`)),1)])):u(``,!0),_(`div`,Pe,[(t(!0),m(h,null,r(F.value,(e,n)=>(t(),l(Ae,{key:n,ref_for:!0,ref_key:`turnRefs`,ref:G,turn:e,"is-latest-turn":n===F.value.length-1,onScrollTo:le},null,8,[`turn`,`is-latest-turn`]))),128))]),I.value.length?(t(),m(`div`,Fe,[d(M,{label:e.$t(`activity.raw_lines`,{n:I.value.length}),dense:``},{default:o(()=>[(t(!0),m(h,null,r(I.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`,Ie,[R.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:de},null,8,[`title`])])]))}}),[[`__scopeId`,`data-v-989e89a0`]]);export{He as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{k as e,m as t}from"./QIcon-B0-pH3Qs.js";import{_ as n,g as r}from"./settings-Cw4mtk9x.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-f098e4b1]{background-color:#1a1a2e;min-height:100%;padding:48px 24px}.create-inner[data-v-f098e4b1]{width:100%;max-width:700px}.create-title[data-v-f098e4b1]{font-size:24px;line-height:1.3}.create-card[data-v-f098e4b1]{background:#224;border:1px solid #444;overflow:hidden}.card-top-bar[data-v-f098e4b1]{background:#1e1e3a;min-height:36px}.card-name-wrap[data-v-f098e4b1]{background:#224;padding:8px 16px 4px}.card-name-wrap[data-v-f098e4b1] .q-field__control{height:32px;min-height:32px;padding:0}.card-name-wrap[data-v-f098e4b1] input{color:#e0e0e0;font-size:15px;font-weight:500}.card-name-wrap[data-v-f098e4b1] input::placeholder{color:#555}.card-textarea-wrap[data-v-f098e4b1]{background:#224;position:relative}.create-slash-popup[data-v-f098e4b1]{z-index:9999;position:absolute;top:calc(100% + 4px);left:12px;right:12px}.repo-select[data-v-f098e4b1]{min-width:160px;max-width:260px}.repo-select[data-v-f098e4b1] .q-field__prepend{align-items:center;height:auto;padding-top:0}.create-textarea[data-v-f098e4b1]{color:#d0d0d0;width:100%;padding:12px 16px 4px}.create-textarea[data-v-f098e4b1] .q-field__control{padding:0}.create-textarea[data-v-f098e4b1] textarea{color:#d0d0d0;resize:none;min-height:100px;font-size:14px;line-height:1.6}.create-textarea[data-v-f098e4b1] textarea::placeholder{color:#666}.notion-toggle-btn[data-v-f098e4b1]{background:#333;padding:2px 10px}.notion-url-wrap[data-v-f098e4b1]{background:#1e1e3a;padding:8px 0 0}.notion-url-input[data-v-f098e4b1]{padding:0 12px}.notion-url-input[data-v-f098e4b1] .q-field__control{height:36px;min-height:36px;padding:0}.notion-url-input[data-v-f098e4b1] input{color:#d0d0d0;font-size:13px}.notion-url-input[data-v-f098e4b1] input::placeholder{color:#555;font-size:12px}.notion-error[data-v-f098e4b1],.notion-valid[data-v-f098e4b1]{padding-bottom:6px}.notion-peek-choice[data-v-f098e4b1]{padding-top:4px}.peek-card[data-v-f098e4b1]{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-f098e4b1]:hover{background:#ffffff0f;border-color:#6c63ff66}.peek-card[data-v-f098e4b1]:active{transform:scale(.99)}.peek-card--active[data-v-f098e4b1]{background:#6c63ff1f;border-color:#6c63ffd9;box-shadow:0 0 0 1px #6c63ff66}.peek-card--active .peek-card-icon[data-v-f098e4b1]{color:#8a82ff}.peek-card--active .peek-card-title[data-v-f098e4b1]{color:#fff}.peek-card-icon[data-v-f098e4b1]{color:#999;flex-shrink:0}.peek-card-text[data-v-f098e4b1]{flex:1;min-width:0;line-height:1.25}.peek-card-title[data-v-f098e4b1]{color:#d0d0d0;font-size:12px;font-weight:600}.peek-card-desc[data-v-f098e4b1]{color:#888;margin-top:2px;font-size:10.5px}.peek-card-check[data-v-f098e4b1]{flex-shrink:0}.sentry-toggle-btn[data-v-f098e4b1]{background:#333;padding:2px 10px}.sentry-url-wrap[data-v-f098e4b1]{background:#1e1e3a;padding:8px 0 0}.sentry-url-input[data-v-f098e4b1]{padding:0 12px}.sentry-url-input[data-v-f098e4b1] .q-field__control{height:36px;min-height:36px;padding:0}.sentry-url-input[data-v-f098e4b1] input{color:#d0d0d0;font-size:13px}.sentry-url-input[data-v-f098e4b1] input::placeholder{color:#555;font-size:12px}.sentry-error[data-v-f098e4b1],.sentry-valid[data-v-f098e4b1]{padding-bottom:6px}.slide-enter-active[data-v-f098e4b1],.slide-leave-active[data-v-f098e4b1]{transition:all .2s;overflow:hidden}.slide-enter-from[data-v-f098e4b1],.slide-leave-to[data-v-f098e4b1]{opacity:0;max-height:0}.slide-enter-to[data-v-f098e4b1],.slide-leave-from[data-v-f098e4b1]{opacity:1;max-height:120px}.card-bottom-bar[data-v-f098e4b1]{background:#1e1e3a}.skip-setup-btn[data-v-f098e4b1]{min-height:28px;padding:2px 10px;font-size:11px}.skip-setup-btn[data-v-f098e4b1] .q-btn__content{gap:4px}.skip-setup-btn[data-v-f098e4b1] .q-icon{font-size:14px}.bottom-row-git .bottom-select-label[data-v-f098e4b1]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.bottom-row-git .bottom-select.repo-select[data-v-f098e4b1] input{color:#bbb;padding:0 4px;font-size:11px}.bottom-row-git .bottom-select.repo-select[data-v-f098e4b1] input::placeholder{color:#666;font-style:italic}.bottom-select[data-v-f098e4b1]{background:#333;height:28px;padding:0 6px}.bottom-select[data-v-f098e4b1] .q-field__control{height:28px;min-height:28px;padding:0}.bottom-select[data-v-f098e4b1] .q-field__native{min-height:unset;padding:0}.bottom-select-label[data-v-f098e4b1]{color:#bbb;gap:2px;font-size:11px}.bottom-sep[data-v-f098e4b1]{color:#555;padding:0 2px;font-size:12px;line-height:1}.repo-path-wrap[data-v-f098e4b1]{background:#333;border-radius:6px;height:28px;padding:0 8px}.repo-input[data-v-f098e4b1]{min-width:140px}.repo-input[data-v-f098e4b1] .q-field__control{height:28px;min-height:28px;padding:0}.repo-input[data-v-f098e4b1] input{color:#bbb;font-size:11px}.repo-input[data-v-f098e4b1] input::placeholder{color:#666;font-size:11px}.branch-select[data-v-f098e4b1]{min-width:80px}.create-btn[data-v-f098e4b1]{color:#fff;background:#4f46e5;min-width:220px;height:32px;padding:0 32px;font-size:13px}.create-btn[data-v-f098e4b1] .q-btn__content{height:32px}.create-hint[data-v-f098e4b1]{line-height:1.5}.fade-enter-active[data-v-f098e4b1],.fade-leave-active[data-v-f098e4b1]{transition:opacity .2s}.fade-enter-from[data-v-f098e4b1],.fade-leave-to[data-v-f098e4b1]{opacity:0}.manual-hint[data-v-f098e4b1]{background:#1e1e3a;line-height:1.4}.manual-expansion[data-v-f098e4b1]{background:#1e1e3a;border:1px solid #333;border-radius:4px;margin-top:6px;overflow:hidden}.manual-expansion[data-v-f098e4b1] .manual-expansion-header{min-height:32px;padding:4px 10px;font-size:12px}.manual-expansion[data-v-f098e4b1] .q-expansion-item__content,.manual-section-body[data-v-f098e4b1]{background:#1a1a2e}.manual-input[data-v-f098e4b1] .q-field__control{height:26px;min-height:26px;padding:0}.manual-input[data-v-f098e4b1] input{color:#e0e0e0;font-size:12px}.manual-input[data-v-f098e4b1] input::placeholder{color:#555}.manual-item[data-v-f098e4b1]{border-top:1px solid #ffffff0a}.manual-item[data-v-f098e4b1]:first-child{border-top:none}
|