@zerwiz/ymir 0.1.34 → 0.1.35
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/CHANGELOG.md +56 -0
- package/apps/README.md +4 -0
- package/apps/hlidskjalf/README.md +68 -0
- package/apps/hlidskjalf/android/app/build.gradle +73 -0
- package/apps/hlidskjalf/android/app/capacitor.build.gradle +19 -0
- package/apps/hlidskjalf/android/app/proguard-rules.pro +21 -0
- package/apps/hlidskjalf/android/app/src/androidTest/java/com/getcapacitor/myapp/ExampleInstrumentedTest.java +26 -0
- package/apps/hlidskjalf/android/app/src/main/AndroidManifest.xml +41 -0
- package/apps/hlidskjalf/android/app/src/main/java/org/zerwiz/ymir/MainActivity.java +5 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable/ic_launcher_background.xml +170 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-land-hdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-land-mdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-land-xhdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-land-xxhdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-land-xxxhdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-port-hdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-port-mdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-port-xhdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-port-xxhdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-port-xxxhdpi/splash.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/drawable-v24/ic_launcher_foreground.xml +34 -0
- package/apps/hlidskjalf/android/app/src/main/res/layout/activity_main.xml +12 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +5 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +5 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-hdpi/ic_launcher.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-mdpi/ic_launcher.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png +0 -0
- package/apps/hlidskjalf/android/app/src/main/res/values/ic_launcher_background.xml +4 -0
- package/apps/hlidskjalf/android/app/src/main/res/values/strings.xml +7 -0
- package/apps/hlidskjalf/android/app/src/main/res/values/styles.xml +22 -0
- package/apps/hlidskjalf/android/app/src/main/res/xml/file_paths.xml +5 -0
- package/apps/hlidskjalf/android/app/src/test/java/com/getcapacitor/myapp/ExampleUnitTest.java +18 -0
- package/apps/hlidskjalf/android/build.gradle +29 -0
- package/apps/hlidskjalf/android/capacitor.settings.gradle +3 -0
- package/apps/hlidskjalf/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/apps/hlidskjalf/android/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/apps/hlidskjalf/android/gradle.properties +22 -0
- package/apps/hlidskjalf/android/gradlew +248 -0
- package/apps/hlidskjalf/android/gradlew.bat +92 -0
- package/apps/hlidskjalf/android/settings.gradle +5 -0
- package/apps/hlidskjalf/android/variables.gradle +16 -0
- package/apps/hlidskjalf/capacitor.config.ts +26 -0
- package/apps/hlidskjalf/dist/apple-touch-icon.png +0 -0
- package/apps/hlidskjalf/dist/assets/index-BWmNIyaG.css +1 -0
- package/apps/hlidskjalf/dist/assets/index-k7QEfNto.js +88 -0
- package/apps/hlidskjalf/dist/assets/index-k7QEfNto.js.map +1 -0
- package/apps/hlidskjalf/dist/icon.svg +7 -0
- package/apps/hlidskjalf/dist/index.html +64 -0
- package/apps/hlidskjalf/dist/manifest.webmanifest +31 -0
- package/apps/hlidskjalf/dist/og.jpg +0 -0
- package/apps/hlidskjalf/dist/og.png +0 -0
- package/apps/hlidskjalf/dist/og.svg +64 -0
- package/apps/hlidskjalf/dist/sw.js +39 -0
- package/apps/hlidskjalf/dist/ymir-icon.png +0 -0
- package/apps/hlidskjalf/dist/ymir-mark.svg +62 -0
- package/apps/hlidskjalf/electron/icon.png +0 -0
- package/apps/hlidskjalf/electron/main.cjs +236 -0
- package/apps/hlidskjalf/electron/preload.cjs +8 -0
- package/apps/hlidskjalf/electron/smidja-icon.png +0 -0
- package/apps/hlidskjalf/electron/ymir-hlidskjalf.desktop.in +12 -0
- package/apps/hlidskjalf/electron/ymir-smidja.desktop.in +12 -0
- package/apps/hlidskjalf/index.html +63 -0
- package/apps/hlidskjalf/package-lock.json +5398 -0
- package/apps/hlidskjalf/package.json +55 -0
- package/apps/hlidskjalf/public/apple-touch-icon.png +0 -0
- package/apps/hlidskjalf/public/icon.svg +7 -0
- package/apps/hlidskjalf/public/manifest.webmanifest +31 -0
- package/apps/hlidskjalf/public/og.jpg +0 -0
- package/apps/hlidskjalf/public/og.png +0 -0
- package/apps/hlidskjalf/public/og.svg +64 -0
- package/apps/hlidskjalf/public/sw.js +39 -0
- package/apps/hlidskjalf/public/ymir-icon.png +0 -0
- package/apps/hlidskjalf/public/ymir-mark.svg +62 -0
- package/apps/hlidskjalf/server/accounts.ts +159 -0
- package/apps/hlidskjalf/server/index.ts +2045 -0
- package/apps/hlidskjalf/src/app/App.tsx +116 -0
- package/apps/hlidskjalf/src/app/BottomStream.tsx +128 -0
- package/apps/hlidskjalf/src/app/MobileNav.tsx +87 -0
- package/apps/hlidskjalf/src/app/Rail.tsx +106 -0
- package/apps/hlidskjalf/src/app/Shell.tsx +135 -0
- package/apps/hlidskjalf/src/app/Topbar.tsx +130 -0
- package/apps/hlidskjalf/src/components/AccentPicker.tsx +207 -0
- package/apps/hlidskjalf/src/components/AccountMenu.tsx +115 -0
- package/apps/hlidskjalf/src/components/AgentCard.tsx +75 -0
- package/apps/hlidskjalf/src/components/EmberBackground.tsx +36 -0
- package/apps/hlidskjalf/src/components/Emblem.tsx +48 -0
- package/apps/hlidskjalf/src/components/Halls.tsx +155 -0
- package/apps/hlidskjalf/src/components/LoginModal.tsx +329 -0
- package/apps/hlidskjalf/src/components/Markdown.tsx +10 -0
- package/apps/hlidskjalf/src/components/MetricTile.tsx +40 -0
- package/apps/hlidskjalf/src/components/ModelPicker.tsx +100 -0
- package/apps/hlidskjalf/src/components/Overlay.tsx +134 -0
- package/apps/hlidskjalf/src/components/PRCard.tsx +154 -0
- package/apps/hlidskjalf/src/components/RecallPanel.tsx +116 -0
- package/apps/hlidskjalf/src/components/RuneTag.tsx +23 -0
- package/apps/hlidskjalf/src/components/Status.tsx +35 -0
- package/apps/hlidskjalf/src/components/TaskChip.tsx +23 -0
- package/apps/hlidskjalf/src/components/TraceRow.tsx +28 -0
- package/apps/hlidskjalf/src/data/lore.ts +127 -0
- package/apps/hlidskjalf/src/data/metadata.ts +147 -0
- package/apps/hlidskjalf/src/data/mythology.ts +95 -0
- package/apps/hlidskjalf/src/data/realms.ts +167 -0
- package/apps/hlidskjalf/src/gates/Cron.tsx +77 -0
- package/apps/hlidskjalf/src/gates/Decisions.tsx +67 -0
- package/apps/hlidskjalf/src/gates/Files.tsx +138 -0
- package/apps/hlidskjalf/src/gates/Fleet.tsx +184 -0
- package/apps/hlidskjalf/src/gates/Forge.tsx +486 -0
- package/apps/hlidskjalf/src/gates/OmniChat.tsx +217 -0
- package/apps/hlidskjalf/src/gates/Processes.tsx +162 -0
- package/apps/hlidskjalf/src/gates/Profile.tsx +225 -0
- package/apps/hlidskjalf/src/gates/Reviews.tsx +33 -0
- package/apps/hlidskjalf/src/gates/Runes.tsx +116 -0
- package/apps/hlidskjalf/src/gates/Runtime.tsx +106 -0
- package/apps/hlidskjalf/src/gates/Sessions.tsx +109 -0
- package/apps/hlidskjalf/src/gates/Stats.tsx +268 -0
- package/apps/hlidskjalf/src/gates/Tasks.tsx +173 -0
- package/apps/hlidskjalf/src/gates/Trace.tsx +155 -0
- package/apps/hlidskjalf/src/gates/Well.tsx +154 -0
- package/apps/hlidskjalf/src/gates/Worktrees.tsx +48 -0
- package/apps/hlidskjalf/src/hooks/useTenantDef.ts +13 -0
- package/apps/hlidskjalf/src/main.tsx +31 -0
- package/apps/hlidskjalf/src/services/api.ts +404 -0
- package/apps/hlidskjalf/src/services/auth.ts +107 -0
- package/apps/hlidskjalf/src/services/stream.ts +35 -0
- package/apps/hlidskjalf/src/state/store.ts +648 -0
- package/apps/hlidskjalf/src/state/ui.ts +62 -0
- package/apps/hlidskjalf/src/styles/auth.css +485 -0
- package/apps/hlidskjalf/src/styles/components.css +1259 -0
- package/apps/hlidskjalf/src/styles/forge.css +115 -0
- package/apps/hlidskjalf/src/styles/global.css +167 -0
- package/apps/hlidskjalf/src/styles/menus.css +175 -0
- package/apps/hlidskjalf/src/styles/mobile.css +298 -0
- package/apps/hlidskjalf/src/styles/overlays.css +205 -0
- package/apps/hlidskjalf/src/styles/shell.css +641 -0
- package/apps/hlidskjalf/src/types.ts +251 -0
- package/apps/hlidskjalf/src/vite-env.d.ts +9 -0
- package/apps/hlidskjalf/static/landing.md +6 -0
- package/apps/hlidskjalf/tsconfig.json +25 -0
- package/apps/hlidskjalf/vite.config.ts +49 -0
- package/apps/hlidskjalf-mobile/App.tsx +93 -0
- package/apps/hlidskjalf-mobile/app.json +13 -0
- package/apps/hlidskjalf-mobile/index.ts +4 -0
- package/apps/hlidskjalf-mobile/package.json +35 -0
- package/apps/hlidskjalf-mobile/public/icon.svg +7 -0
- package/apps/hlidskjalf-mobile/tsconfig.json +4 -0
- package/apps/odrerir/.astro/content.d.ts +159 -0
- package/apps/odrerir/.astro/dev.json +24 -0
- package/apps/odrerir/.astro/settings.json +5 -0
- package/apps/odrerir/.astro/types.d.ts +2 -0
- package/apps/odrerir/astro.config.mjs +79 -0
- package/apps/odrerir/dist/apple-touch-icon.png +0 -0
- package/apps/odrerir/dist/favicon-192.png +0 -0
- package/apps/odrerir/dist/favicon-32.png +0 -0
- package/apps/odrerir/dist/favicon-512.png +0 -0
- package/apps/odrerir/dist/favicon.svg +53 -0
- package/apps/odrerir/dist/icon.svg +7 -0
- package/apps/odrerir/dist/index.html +837 -0
- package/apps/odrerir/dist/og-square.png +0 -0
- package/apps/odrerir/dist/og-story.png +0 -0
- package/apps/odrerir/dist/og.png +0 -0
- package/apps/odrerir/dist/safari-pinned-tab.svg +7 -0
- package/apps/odrerir/dist/site.webmanifest +16 -0
- package/apps/odrerir/dist/styles/cloth.css +112 -0
- package/apps/odrerir/dist/styles/livehall.css +278 -0
- package/apps/odrerir/electron/icon.png +0 -0
- package/apps/odrerir/electron/main.cjs +183 -0
- package/apps/odrerir/electron/ymir-odrerir.desktop.in +12 -0
- package/apps/odrerir/package-lock.json +4195 -0
- package/apps/odrerir/package.json +30 -0
- package/apps/odrerir/public/apple-touch-icon.png +0 -0
- package/apps/odrerir/public/favicon-192.png +0 -0
- package/apps/odrerir/public/favicon-32.png +0 -0
- package/apps/odrerir/public/favicon-512.png +0 -0
- package/apps/odrerir/public/favicon.svg +53 -0
- package/apps/odrerir/public/icon.svg +7 -0
- package/apps/odrerir/public/og-square.png +0 -0
- package/apps/odrerir/public/og-story.png +0 -0
- package/apps/odrerir/public/og.png +0 -0
- package/apps/odrerir/public/safari-pinned-tab.svg +7 -0
- package/apps/odrerir/public/site.webmanifest +16 -0
- package/apps/odrerir/scripts/extract-cloth.mjs +101 -0
- package/apps/odrerir/src/index.html +837 -0
- package/apps/odrerir/src/styles/cloth.css +112 -0
- package/apps/odrerir/src/styles/livehall.css +278 -0
- package/apps/sessrumnir/.github/ISSUE_TEMPLATE/bug_report.yml +99 -0
- package/apps/sessrumnir/.github/ISSUE_TEMPLATE/config.yml +8 -0
- package/apps/sessrumnir/.github/ISSUE_TEMPLATE/feature_request.yml +46 -0
- package/apps/sessrumnir/.github/PULL_REQUEST_TEMPLATE.md +56 -0
- package/apps/sessrumnir/.github/SUPPORT.md +18 -0
- package/apps/sessrumnir/.github/workflows/build.yml +133 -0
- package/apps/sessrumnir/AGENTS.md +540 -0
- package/apps/sessrumnir/CLA.md +63 -0
- package/apps/sessrumnir/CONTRIBUTING.md +233 -0
- package/apps/sessrumnir/LICENSE +200 -0
- package/apps/sessrumnir/NOTICE +33 -0
- package/apps/sessrumnir/README.md +329 -0
- package/apps/sessrumnir/bin/sessrumnir-web.sh +117 -0
- package/apps/sessrumnir/bin/sessrumnir.js +169 -0
- package/apps/sessrumnir/docs/CNAME +1 -0
- package/apps/sessrumnir/docs/favicon.ico +0 -0
- package/apps/sessrumnir/docs/icon-512.png +0 -0
- package/apps/sessrumnir/docs/index.html +441 -0
- package/apps/sessrumnir/docs/robots.txt +4 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_181929.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182005.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182020.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182039.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182117.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182225.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182248.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182322.png +0 -0
- package/apps/sessrumnir/docs/screenshots/Screenshot_20260824_182340.png +0 -0
- package/apps/sessrumnir/docs/sitemap.xml +9 -0
- package/apps/sessrumnir/electron.vite.config.ts +49 -0
- package/apps/sessrumnir/eslint.config.mjs +75 -0
- package/apps/sessrumnir/i18next.config.ts +33 -0
- package/apps/sessrumnir/install.sh +144 -0
- package/apps/sessrumnir/out/main/index.js +10881 -0
- package/apps/sessrumnir/out/preload/index.js +722 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-400-normal-C8QS47vb.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-400-normal-D3EsxgFc.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-500-normal-B7dJQtg-.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-500-normal-BLlg2W5x.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-600-normal-BcIsDXzC.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-600-normal-CBymlcNF.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-400-normal-Bgrpe4p1.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-400-normal-BlcaxZtM.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-500-normal-CdQuyvtc.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-500-normal-pZw22qtS.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-600-normal-Dr-wLyOm.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-cyrillic-ext-600-normal-dLR2-a_v.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-400-normal-BGH8Vunh.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-400-normal-C3_-2Ua-.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-500-normal-Dj3SQ6fR.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-500-normal-EBdSCOD3.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-600-normal-B254Xisw.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-600-normal-DUW-TI76.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-400-normal-DuQ88yz3.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-400-normal-DuXFa1Dr.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-500-normal-AH9qog1s.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-500-normal-DAuUCO41.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-600-normal-CD-dlDpD.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-latin-ext-600-normal-D3T6BBXG.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-400-normal-C-RiYxEf.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-400-normal-DmUuA7Y2.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-500-normal-DsPuwQHi.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-500-normal-tGBW_mI7.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-600-normal-Dar_cCT6.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/cormorant-vietnamese-600-normal-GIs8CF2x.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-300-normal-Ba-HN6uq.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-300-normal-ByB2hQUF.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-400-normal-BSMlKf0J.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-400-normal-CEL4l2ZJ.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-500-normal-Ael50iVv.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-500-normal-Bq9vWWag.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-300-normal-B8O3uHbr.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-300-normal-BbtBtHoB.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-400-normal-DMdlQ8Kv.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-400-normal-xuaO2J-f.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-500-normal-BIfNGwUT.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-cyrillic-ext-500-normal-BqneJy0T.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-300-normal-BPU54Tw3.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-300-normal-BRS-C4KA.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-400-normal-CvHOgSBP.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-400-normal-DMJ8VG8y.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-500-normal-CB9ihrfo.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-500-normal-DSY6xOcd.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-300-normal-BEtQ2wm2.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-300-normal-CQbCaAQ4.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-400-normal-BmRBH3aV.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-400-normal-D3D2R8hC.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-500-normal-CAhNIIs5.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-latin-ext-500-normal-CZ70TYgx.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-300-normal-B6fSpYYV.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-300-normal-CpdbWO_2.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-400-normal-BulugwFq.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-400-normal-DDuiU_S-.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-500-normal-C8zxqsMH.woff +0 -0
- package/apps/sessrumnir/out/renderer/assets/ibm-plex-mono-vietnamese-500-normal-DZ4AoWbu.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/index-BxqsRq2x.css +4858 -0
- package/apps/sessrumnir/out/renderer/assets/index-TaD69rFk.js +99435 -0
- package/apps/sessrumnir/out/renderer/assets/inter-cyrillic-ext-wght-normal-BOeWTOD4.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/inter-cyrillic-wght-normal-DqGufNeO.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/inter-greek-ext-wght-normal-DlzME5K_.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/inter-greek-wght-normal-CkhJZR-_.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/inter-latin-ext-wght-normal-DO1Apj_S.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/inter-latin-wght-normal-Dx4kXJAl.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/inter-vietnamese-wght-normal-CBcvBZtf.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-cyrillic-wght-normal-D73BlboJ.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-greek-wght-normal-Bw9x6K1M.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-latin-ext-wght-normal-DBQx-q_a.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-latin-wght-normal-B9CIFXIH.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/jetbrains-mono-vietnamese-wght-normal-Bt-aOZkq.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/newsreader-latin-ext-wght-italic-DFS986qL.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/newsreader-latin-ext-wght-normal-C-3rgBeH.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/newsreader-latin-wght-italic-Bxi8ein9.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/newsreader-latin-wght-normal-CCVVNp6i.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/newsreader-vietnamese-wght-italic-xAqemagA.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/newsreader-vietnamese-wght-normal-Czsa-EzN.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/openmoji-color-9qo_2DLG.woff2 +0 -0
- package/apps/sessrumnir/out/renderer/assets/pi-logo-B6SVnhuS.svg +7 -0
- package/apps/sessrumnir/out/renderer/index.html +19 -0
- package/apps/sessrumnir/out/renderer/theme-boot.js +30 -0
- package/apps/sessrumnir/package-lock.json +10636 -0
- package/apps/sessrumnir/package.json +183 -0
- package/apps/sessrumnir/public/apple-touch-icon.png +0 -0
- package/apps/sessrumnir/public/icon.svg +7 -0
- package/apps/sessrumnir/resources/icons/generate_icons.py +38 -0
- package/apps/sessrumnir/resources/icons/icon-128.png +0 -0
- package/apps/sessrumnir/resources/icons/icon-16.png +0 -0
- package/apps/sessrumnir/resources/icons/icon-256.png +0 -0
- package/apps/sessrumnir/resources/icons/icon-32.png +0 -0
- package/apps/sessrumnir/resources/icons/icon-48.png +0 -0
- package/apps/sessrumnir/resources/icons/icon-512.png +0 -0
- package/apps/sessrumnir/resources/icons/icon-64.png +0 -0
- package/apps/sessrumnir/resources/icons/icon.icns +0 -0
- package/apps/sessrumnir/resources/icons/icon.ico +0 -0
- package/apps/sessrumnir/resources/icons/icon.png +0 -0
- package/apps/sessrumnir/resources/icons/icon.svg +7 -0
- package/apps/sessrumnir/resources/linux/after-install.sh +23 -0
- package/apps/sessrumnir/resources/linux/after-remove.sh +18 -0
- package/apps/sessrumnir/resources/locales/en/translation.json +1735 -0
- package/apps/sessrumnir/resources/permission-prompt-text.test.ts +111 -0
- package/apps/sessrumnir/resources/permission-prompt-text.ts +84 -0
- package/apps/sessrumnir/resources/permission-rules.test.ts +351 -0
- package/apps/sessrumnir/resources/permission-rules.ts +293 -0
- package/apps/sessrumnir/resources/pi-desktop-permissions.ts +62 -0
- package/apps/sessrumnir/resources/ymir-sessrumnir.desktop.in +12 -0
- package/apps/sessrumnir/scripts/check-semantic-colors.mjs +57 -0
- package/apps/sessrumnir/src/main/activity-stats.test.ts +240 -0
- package/apps/sessrumnir/src/main/activity-stats.ts +596 -0
- package/apps/sessrumnir/src/main/agent-detection.test.ts +25 -0
- package/apps/sessrumnir/src/main/agent-detection.ts +114 -0
- package/apps/sessrumnir/src/main/app-data-paths.test.ts +90 -0
- package/apps/sessrumnir/src/main/app-data-paths.ts +95 -0
- package/apps/sessrumnir/src/main/app-log.test.ts +114 -0
- package/apps/sessrumnir/src/main/app-log.ts +210 -0
- package/apps/sessrumnir/src/main/archived-sessions.test.ts +50 -0
- package/apps/sessrumnir/src/main/archived-sessions.ts +95 -0
- package/apps/sessrumnir/src/main/attachment-reader.test.ts +56 -0
- package/apps/sessrumnir/src/main/attachment-reader.ts +52 -0
- package/apps/sessrumnir/src/main/auto-tag.test.ts +38 -0
- package/apps/sessrumnir/src/main/auto-tag.ts +75 -0
- package/apps/sessrumnir/src/main/autostart-linux.test.ts +56 -0
- package/apps/sessrumnir/src/main/autostart-linux.ts +58 -0
- package/apps/sessrumnir/src/main/cmd-escape.test.ts +424 -0
- package/apps/sessrumnir/src/main/cmd-escape.ts +186 -0
- package/apps/sessrumnir/src/main/council-manager.test.ts +167 -0
- package/apps/sessrumnir/src/main/council-manager.ts +265 -0
- package/apps/sessrumnir/src/main/diagnostics-report.test.ts +140 -0
- package/apps/sessrumnir/src/main/diagnostics-report.ts +91 -0
- package/apps/sessrumnir/src/main/diagnostics.ts +111 -0
- package/apps/sessrumnir/src/main/editor-guard.test.ts +59 -0
- package/apps/sessrumnir/src/main/editor-guard.ts +50 -0
- package/apps/sessrumnir/src/main/extension-ui-ipc.test.ts +299 -0
- package/apps/sessrumnir/src/main/extension-ui-ipc.ts +117 -0
- package/apps/sessrumnir/src/main/file-service.test.ts +279 -0
- package/apps/sessrumnir/src/main/file-service.ts +652 -0
- package/apps/sessrumnir/src/main/fs-errors.ts +42 -0
- package/apps/sessrumnir/src/main/get-messages-trim.test.ts +77 -0
- package/apps/sessrumnir/src/main/get-messages-trim.ts +97 -0
- package/apps/sessrumnir/src/main/git-conveyor.test.ts +305 -0
- package/apps/sessrumnir/src/main/git-conveyor.ts +338 -0
- package/apps/sessrumnir/src/main/git-worktree.test.ts +101 -0
- package/apps/sessrumnir/src/main/git-worktree.ts +201 -0
- package/apps/sessrumnir/src/main/i18n.ts +31 -0
- package/apps/sessrumnir/src/main/index.ts +619 -0
- package/apps/sessrumnir/src/main/ipc/active-engine.ts +15 -0
- package/apps/sessrumnir/src/main/ipc/context.ts +58 -0
- package/apps/sessrumnir/src/main/ipc/council-handlers.ts +126 -0
- package/apps/sessrumnir/src/main/ipc/diagnostics-handlers.ts +8 -0
- package/apps/sessrumnir/src/main/ipc/file-handlers.ts +96 -0
- package/apps/sessrumnir/src/main/ipc/git-conveyor-handlers.ts +55 -0
- package/apps/sessrumnir/src/main/ipc/model-handlers.ts +33 -0
- package/apps/sessrumnir/src/main/ipc/models-config-handlers.ts +80 -0
- package/apps/sessrumnir/src/main/ipc/notes-handlers.ts +65 -0
- package/apps/sessrumnir/src/main/ipc/package-handlers.ts +330 -0
- package/apps/sessrumnir/src/main/ipc/permission-rules-handlers.ts +223 -0
- package/apps/sessrumnir/src/main/ipc/pi-handlers.ts +136 -0
- package/apps/sessrumnir/src/main/ipc/pi-start-options.ts +150 -0
- package/apps/sessrumnir/src/main/ipc/run-pi-cli.ts +53 -0
- package/apps/sessrumnir/src/main/ipc/session-handlers.ts +491 -0
- package/apps/sessrumnir/src/main/ipc/settings.ts +120 -0
- package/apps/sessrumnir/src/main/ipc/skills-mcp-handlers.ts +192 -0
- package/apps/sessrumnir/src/main/ipc/system-handlers.ts +131 -0
- package/apps/sessrumnir/src/main/ipc/tag-handlers.ts +69 -0
- package/apps/sessrumnir/src/main/ipc/terminal-handlers.ts +41 -0
- package/apps/sessrumnir/src/main/ipc/theme-handlers.ts +131 -0
- package/apps/sessrumnir/src/main/ipc/update-handlers.ts +61 -0
- package/apps/sessrumnir/src/main/ipc/validation.ts +45 -0
- package/apps/sessrumnir/src/main/ipc/workflow-handlers.ts +108 -0
- package/apps/sessrumnir/src/main/ipc/workspace-activity-wiring.ts +179 -0
- package/apps/sessrumnir/src/main/ipc/workspace-handlers.ts +133 -0
- package/apps/sessrumnir/src/main/ipc-handlers.ts +98 -0
- package/apps/sessrumnir/src/main/map-concurrent.test.ts +80 -0
- package/apps/sessrumnir/src/main/map-concurrent.ts +30 -0
- package/apps/sessrumnir/src/main/models-file.test.ts +114 -0
- package/apps/sessrumnir/src/main/models-file.ts +89 -0
- package/apps/sessrumnir/src/main/notes-manager.test.ts +64 -0
- package/apps/sessrumnir/src/main/notes-manager.ts +183 -0
- package/apps/sessrumnir/src/main/notify-decision.test.ts +39 -0
- package/apps/sessrumnir/src/main/notify-decision.ts +25 -0
- package/apps/sessrumnir/src/main/omp-fork-points.test.ts +119 -0
- package/apps/sessrumnir/src/main/omp-fork-points.ts +105 -0
- package/apps/sessrumnir/src/main/omp-plugin-list.test.ts +94 -0
- package/apps/sessrumnir/src/main/omp-plugin-list.ts +103 -0
- package/apps/sessrumnir/src/main/package-catalog.test.ts +157 -0
- package/apps/sessrumnir/src/main/package-catalog.ts +166 -0
- package/apps/sessrumnir/src/main/package-updates.test.ts +149 -0
- package/apps/sessrumnir/src/main/package-updates.ts +185 -0
- package/apps/sessrumnir/src/main/path-authorization.test.ts +64 -0
- package/apps/sessrumnir/src/main/path-authorization.ts +31 -0
- package/apps/sessrumnir/src/main/pi-binary-resolution.test.ts +582 -0
- package/apps/sessrumnir/src/main/pi-binary-resolution.ts +649 -0
- package/apps/sessrumnir/src/main/pi-event-router.test.ts +388 -0
- package/apps/sessrumnir/src/main/pi-event-router.ts +290 -0
- package/apps/sessrumnir/src/main/pi-paths.test.ts +134 -0
- package/apps/sessrumnir/src/main/pi-paths.ts +74 -0
- package/apps/sessrumnir/src/main/pi-rpc-manager.test.ts +467 -0
- package/apps/sessrumnir/src/main/pi-rpc-manager.ts +1319 -0
- package/apps/sessrumnir/src/main/process-tree.test.ts +94 -0
- package/apps/sessrumnir/src/main/renderer-origin.test.ts +33 -0
- package/apps/sessrumnir/src/main/renderer-origin.ts +35 -0
- package/apps/sessrumnir/src/main/session-lineage-reader.test.ts +317 -0
- package/apps/sessrumnir/src/main/session-lineage-reader.ts +111 -0
- package/apps/sessrumnir/src/main/session-metadata.test.ts +508 -0
- package/apps/sessrumnir/src/main/session-metadata.ts +526 -0
- package/apps/sessrumnir/src/main/session-name.test.ts +71 -0
- package/apps/sessrumnir/src/main/session-name.ts +69 -0
- package/apps/sessrumnir/src/main/session-paths.test.ts +110 -0
- package/apps/sessrumnir/src/main/session-paths.ts +88 -0
- package/apps/sessrumnir/src/main/session-tags.test.ts +61 -0
- package/apps/sessrumnir/src/main/session-tags.ts +253 -0
- package/apps/sessrumnir/src/main/session-trash.test.ts +66 -0
- package/apps/sessrumnir/src/main/session-trash.ts +65 -0
- package/apps/sessrumnir/src/main/settings-logic.ts +66 -0
- package/apps/sessrumnir/src/main/skills-discovery.test.ts +149 -0
- package/apps/sessrumnir/src/main/skills-discovery.ts +179 -0
- package/apps/sessrumnir/src/main/startup-launch.ts +63 -0
- package/apps/sessrumnir/src/main/terminal-service.ts +96 -0
- package/apps/sessrumnir/src/main/theme-store.test.ts +440 -0
- package/apps/sessrumnir/src/main/theme-store.ts +495 -0
- package/apps/sessrumnir/src/main/tray-decision.test.ts +46 -0
- package/apps/sessrumnir/src/main/tray-decision.ts +49 -0
- package/apps/sessrumnir/src/main/tray-manager.ts +220 -0
- package/apps/sessrumnir/src/main/tsconfig.json +20 -0
- package/apps/sessrumnir/src/main/window-background.test.ts +29 -0
- package/apps/sessrumnir/src/main/window-background.ts +16 -0
- package/apps/sessrumnir/src/main/workflow-discovery.test.ts +252 -0
- package/apps/sessrumnir/src/main/workflow-monitor.test.ts +371 -0
- package/apps/sessrumnir/src/main/workflow-monitor.ts +1020 -0
- package/apps/sessrumnir/src/main/workspace-activity.test.ts +227 -0
- package/apps/sessrumnir/src/main/workspace-activity.ts +215 -0
- package/apps/sessrumnir/src/main/workspace-manager.test.ts +680 -0
- package/apps/sessrumnir/src/main/workspace-manager.ts +1199 -0
- package/apps/sessrumnir/src/main/workspace-trust.test.ts +78 -0
- package/apps/sessrumnir/src/main/workspace-trust.ts +84 -0
- package/apps/sessrumnir/src/preload/index.ts +358 -0
- package/apps/sessrumnir/src/preload/tsconfig.json +20 -0
- package/apps/sessrumnir/src/renderer/index.html +18 -0
- package/apps/sessrumnir/src/renderer/public/theme-boot.js +30 -0
- package/apps/sessrumnir/src/renderer/src/app.tsx +194 -0
- package/apps/sessrumnir/src/renderer/src/assets/openmoji-color.woff2 +0 -0
- package/apps/sessrumnir/src/renderer/src/assets/pi-logo.svg +7 -0
- package/apps/sessrumnir/src/renderer/src/assets/ymir-mark.svg +55 -0
- package/apps/sessrumnir/src/renderer/src/assets.d.ts +7 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-code-highlight.ts +239 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-file-link.ts +140 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-input.tsx +729 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-panel-widths.test.ts +175 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-panel-widths.ts +100 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-panel.tsx +523 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-project-picker.tsx +193 -0
- package/apps/sessrumnir/src/renderer/src/components/chat-search.tsx +251 -0
- package/apps/sessrumnir/src/renderer/src/components/code-editor-highlight.ts +85 -0
- package/apps/sessrumnir/src/renderer/src/components/code-editor-language.test.ts +19 -0
- package/apps/sessrumnir/src/renderer/src/components/code-editor-language.ts +88 -0
- package/apps/sessrumnir/src/renderer/src/components/code-editor.tsx +128 -0
- package/apps/sessrumnir/src/renderer/src/components/command-palette.tsx +315 -0
- package/apps/sessrumnir/src/renderer/src/components/command-results.tsx +80 -0
- package/apps/sessrumnir/src/renderer/src/components/composer-permission-menu.tsx +91 -0
- package/apps/sessrumnir/src/renderer/src/components/context-menu.tsx +457 -0
- package/apps/sessrumnir/src/renderer/src/components/copy-button.tsx +36 -0
- package/apps/sessrumnir/src/renderer/src/components/council-panels.tsx +193 -0
- package/apps/sessrumnir/src/renderer/src/components/custom-models-editor.tsx +330 -0
- package/apps/sessrumnir/src/renderer/src/components/diagnostics-panel.tsx +380 -0
- package/apps/sessrumnir/src/renderer/src/components/diff-viewer.tsx +318 -0
- package/apps/sessrumnir/src/renderer/src/components/ember-background.tsx +113 -0
- package/apps/sessrumnir/src/renderer/src/components/error-boundary.tsx +38 -0
- package/apps/sessrumnir/src/renderer/src/components/extension-ui-dialog-helpers.test.ts +43 -0
- package/apps/sessrumnir/src/renderer/src/components/extension-ui-dialog-helpers.ts +51 -0
- package/apps/sessrumnir/src/renderer/src/components/extension-ui-dialog.tsx +486 -0
- package/apps/sessrumnir/src/renderer/src/components/file-tree.tsx +784 -0
- package/apps/sessrumnir/src/renderer/src/components/git-conveyor-actions.tsx +246 -0
- package/apps/sessrumnir/src/renderer/src/components/home-screen.tsx +396 -0
- package/apps/sessrumnir/src/renderer/src/components/image-viewer.tsx +100 -0
- package/apps/sessrumnir/src/renderer/src/components/line-numbered-code.tsx +58 -0
- package/apps/sessrumnir/src/renderer/src/components/markdown-renderer.tsx +237 -0
- package/apps/sessrumnir/src/renderer/src/components/message-bubble.tsx +1006 -0
- package/apps/sessrumnir/src/renderer/src/components/mission-control.tsx +341 -0
- package/apps/sessrumnir/src/renderer/src/components/model-selector.tsx +219 -0
- package/apps/sessrumnir/src/renderer/src/components/note-picker.tsx +155 -0
- package/apps/sessrumnir/src/renderer/src/components/notes-panel.tsx +437 -0
- package/apps/sessrumnir/src/renderer/src/components/package-browser.tsx +604 -0
- package/apps/sessrumnir/src/renderer/src/components/permission-mode.test.ts +22 -0
- package/apps/sessrumnir/src/renderer/src/components/permission-mode.ts +49 -0
- package/apps/sessrumnir/src/renderer/src/components/permission-rules-editor-helpers.test.ts +44 -0
- package/apps/sessrumnir/src/renderer/src/components/permission-rules-editor-helpers.ts +35 -0
- package/apps/sessrumnir/src/renderer/src/components/permission-rules-editor.tsx +226 -0
- package/apps/sessrumnir/src/renderer/src/components/permission-selector.tsx +104 -0
- package/apps/sessrumnir/src/renderer/src/components/resize-handle.tsx +51 -0
- package/apps/sessrumnir/src/renderer/src/components/review-rail.tsx +194 -0
- package/apps/sessrumnir/src/renderer/src/components/session-menu-position.test.ts +22 -0
- package/apps/sessrumnir/src/renderer/src/components/session-menu-position.ts +34 -0
- package/apps/sessrumnir/src/renderer/src/components/session-panel.tsx +711 -0
- package/apps/sessrumnir/src/renderer/src/components/session-runtime-indicator.tsx +43 -0
- package/apps/sessrumnir/src/renderer/src/components/settings-panel.tsx +1360 -0
- package/apps/sessrumnir/src/renderer/src/components/sidebar-activity.test.ts +47 -0
- package/apps/sessrumnir/src/renderer/src/components/sidebar-activity.ts +76 -0
- package/apps/sessrumnir/src/renderer/src/components/sidebar-session-labels.test.ts +73 -0
- package/apps/sessrumnir/src/renderer/src/components/sidebar-session-labels.ts +47 -0
- package/apps/sessrumnir/src/renderer/src/components/sidebar.tsx +1045 -0
- package/apps/sessrumnir/src/renderer/src/components/skills-panel.tsx +159 -0
- package/apps/sessrumnir/src/renderer/src/components/stats-panel.tsx +368 -0
- package/apps/sessrumnir/src/renderer/src/components/status-bar.tsx +274 -0
- package/apps/sessrumnir/src/renderer/src/components/status-popover.tsx +481 -0
- package/apps/sessrumnir/src/renderer/src/components/streaming-bubble.tsx +128 -0
- package/apps/sessrumnir/src/renderer/src/components/subagent-progress.tsx +254 -0
- package/apps/sessrumnir/src/renderer/src/components/task-launcher.tsx +168 -0
- package/apps/sessrumnir/src/renderer/src/components/terminal.tsx +203 -0
- package/apps/sessrumnir/src/renderer/src/components/theme-editor-helpers.test.ts +35 -0
- package/apps/sessrumnir/src/renderer/src/components/theme-editor-helpers.ts +35 -0
- package/apps/sessrumnir/src/renderer/src/components/theme-editor.tsx +440 -0
- package/apps/sessrumnir/src/renderer/src/components/theme-gallery.tsx +373 -0
- package/apps/sessrumnir/src/renderer/src/components/thinking-level-selector.tsx +85 -0
- package/apps/sessrumnir/src/renderer/src/components/timeline.tsx +289 -0
- package/apps/sessrumnir/src/renderer/src/components/tool-call-icon.ts +32 -0
- package/apps/sessrumnir/src/renderer/src/components/workflow-navigator.tsx +901 -0
- package/apps/sessrumnir/src/renderer/src/components/workspace-tabs.tsx +241 -0
- package/apps/sessrumnir/src/renderer/src/global.d.ts +8 -0
- package/apps/sessrumnir/src/renderer/src/hooks/use-folder-drop.ts +101 -0
- package/apps/sessrumnir/src/renderer/src/hooks.test.ts +88 -0
- package/apps/sessrumnir/src/renderer/src/hooks.ts +574 -0
- package/apps/sessrumnir/src/renderer/src/i18n.test.ts +54 -0
- package/apps/sessrumnir/src/renderer/src/i18n.ts +89 -0
- package/apps/sessrumnir/src/renderer/src/index.css +425 -0
- package/apps/sessrumnir/src/renderer/src/main.tsx +42 -0
- package/apps/sessrumnir/src/renderer/src/message-grouping.test.ts +422 -0
- package/apps/sessrumnir/src/renderer/src/message-grouping.ts +410 -0
- package/apps/sessrumnir/src/renderer/src/message-parsing.test.ts +86 -0
- package/apps/sessrumnir/src/renderer/src/message-parsing.ts +166 -0
- package/apps/sessrumnir/src/renderer/src/store-external-prompts.test.ts +161 -0
- package/apps/sessrumnir/src/renderer/src/store-session-transitions.test.ts +2090 -0
- package/apps/sessrumnir/src/renderer/src/store-timeline.test.ts +52 -0
- package/apps/sessrumnir/src/renderer/src/store-turn-error.test.ts +136 -0
- package/apps/sessrumnir/src/renderer/src/store.ts +3726 -0
- package/apps/sessrumnir/src/renderer/src/subagent-detection.test.ts +55 -0
- package/apps/sessrumnir/src/renderer/src/theme/engine.test.ts +29 -0
- package/apps/sessrumnir/src/renderer/src/theme/engine.ts +20 -0
- package/apps/sessrumnir/src/renderer/src/themes/breeze-claudius.json +69 -0
- package/apps/sessrumnir/src/renderer/src/themes/breeze-dark.json +69 -0
- package/apps/sessrumnir/src/renderer/src/themes/breeze-light.json +69 -0
- package/apps/sessrumnir/src/renderer/src/themes/builtin-themes.test.ts +95 -0
- package/apps/sessrumnir/src/renderer/src/themes/dark.json +46 -0
- package/apps/sessrumnir/src/renderer/src/themes/fensalir.json +82 -0
- package/apps/sessrumnir/src/renderer/src/themes/gruvbox.json +69 -0
- package/apps/sessrumnir/src/renderer/src/themes/index.ts +60 -0
- package/apps/sessrumnir/src/renderer/src/themes/light.json +46 -0
- package/apps/sessrumnir/src/renderer/src/themes/nord.json +69 -0
- package/apps/sessrumnir/src/renderer/src/themes/sessrumnir.json +82 -0
- package/apps/sessrumnir/src/renderer/src/utils/debounced-buffer.test.ts +81 -0
- package/apps/sessrumnir/src/renderer/src/utils/debounced-buffer.ts +57 -0
- package/apps/sessrumnir/src/renderer/src/utils/format-relative-time.test.ts +62 -0
- package/apps/sessrumnir/src/renderer/src/utils/format-relative-time.ts +28 -0
- package/apps/sessrumnir/src/renderer/src/utils/heatmap-grid.test.ts +57 -0
- package/apps/sessrumnir/src/renderer/src/utils/heatmap-grid.ts +41 -0
- package/apps/sessrumnir/src/renderer/src/utils/ipc-error.test.ts +22 -0
- package/apps/sessrumnir/src/renderer/src/utils/ipc-error.ts +12 -0
- package/apps/sessrumnir/src/renderer/src/utils/model-search.test.ts +63 -0
- package/apps/sessrumnir/src/renderer/src/utils/model-search.ts +20 -0
- package/apps/sessrumnir/src/renderer/src/utils/planning-prompt.test.ts +31 -0
- package/apps/sessrumnir/src/renderer/src/utils/planning-prompt.ts +27 -0
- package/apps/sessrumnir/src/renderer/src/utils/preview-load-error.test.ts +15 -0
- package/apps/sessrumnir/src/renderer/src/utils/preview-load-error.ts +22 -0
- package/apps/sessrumnir/src/renderer/src/utils/process-status-label.test.ts +13 -0
- package/apps/sessrumnir/src/renderer/src/utils/process-status-label.ts +19 -0
- package/apps/sessrumnir/src/renderer/src/utils/quick-switcher.test.ts +68 -0
- package/apps/sessrumnir/src/renderer/src/utils/quick-switcher.ts +52 -0
- package/apps/sessrumnir/src/renderer/src/utils/rank-file-results.test.ts +46 -0
- package/apps/sessrumnir/src/renderer/src/utils/rank-file-results.ts +23 -0
- package/apps/sessrumnir/src/renderer/src/utils/relative-time.tsx +25 -0
- package/apps/sessrumnir/src/renderer/src/utils/session-title.test.ts +98 -0
- package/apps/sessrumnir/src/renderer/src/utils/session-title.ts +58 -0
- package/apps/sessrumnir/src/renderer/src/utils/stale-guard.test.ts +29 -0
- package/apps/sessrumnir/src/renderer/src/utils/stale-guard.ts +20 -0
- package/apps/sessrumnir/src/renderer/src/utils/theme.test.ts +174 -0
- package/apps/sessrumnir/src/renderer/src/utils/theme.ts +159 -0
- package/apps/sessrumnir/src/renderer/src/utils/workflow-runs.test.ts +130 -0
- package/apps/sessrumnir/src/renderer/src/utils/workflow-runs.ts +84 -0
- package/apps/sessrumnir/src/renderer/tsconfig.json +24 -0
- package/apps/sessrumnir/src/shared/agent-engine-label.test.ts +45 -0
- package/apps/sessrumnir/src/shared/agent-engine-label.ts +53 -0
- package/apps/sessrumnir/src/shared/app-settings.test.ts +25 -0
- package/apps/sessrumnir/src/shared/app-settings.ts +23 -0
- package/apps/sessrumnir/src/shared/bridge-http.ts +341 -0
- package/apps/sessrumnir/src/shared/bridge.ts +337 -0
- package/apps/sessrumnir/src/shared/council-config.test.ts +300 -0
- package/apps/sessrumnir/src/shared/council-config.ts +356 -0
- package/apps/sessrumnir/src/shared/default-settings.ts +39 -0
- package/apps/sessrumnir/src/shared/folder-drop.test.ts +118 -0
- package/apps/sessrumnir/src/shared/folder-drop.ts +74 -0
- package/apps/sessrumnir/src/shared/fork-point.test.ts +30 -0
- package/apps/sessrumnir/src/shared/fork-point.ts +24 -0
- package/apps/sessrumnir/src/shared/i18n/i18next.d.ts +10 -0
- package/apps/sessrumnir/src/shared/i18n/index.test.ts +51 -0
- package/apps/sessrumnir/src/shared/i18n/index.ts +50 -0
- package/apps/sessrumnir/src/shared/i18n/languages.ts +12 -0
- package/apps/sessrumnir/src/shared/i18n/locale-checks.ts +98 -0
- package/apps/sessrumnir/src/shared/i18n/locales.test.ts +92 -0
- package/apps/sessrumnir/src/shared/i18n/pseudo.test.ts +39 -0
- package/apps/sessrumnir/src/shared/i18n/pseudo.ts +44 -0
- package/apps/sessrumnir/src/shared/i18n/resolve.test.ts +43 -0
- package/apps/sessrumnir/src/shared/i18n/resolve.ts +41 -0
- package/apps/sessrumnir/src/shared/i18n/resources.ts +11 -0
- package/apps/sessrumnir/src/shared/ipc-contracts.ts +1539 -0
- package/apps/sessrumnir/src/shared/models-config.test.ts +124 -0
- package/apps/sessrumnir/src/shared/models-config.ts +167 -0
- package/apps/sessrumnir/src/shared/package-filter.ts +19 -0
- package/apps/sessrumnir/src/shared/package-spec.test.ts +51 -0
- package/apps/sessrumnir/src/shared/package-spec.ts +25 -0
- package/apps/sessrumnir/src/shared/path-compare.test.ts +38 -0
- package/apps/sessrumnir/src/shared/path-compare.ts +76 -0
- package/apps/sessrumnir/src/shared/permission-mode.ts +8 -0
- package/apps/sessrumnir/src/shared/pi-command.test.ts +165 -0
- package/apps/sessrumnir/src/shared/pi-command.ts +139 -0
- package/apps/sessrumnir/src/shared/product-name.ts +7 -0
- package/apps/sessrumnir/src/shared/session-lineage.test.ts +103 -0
- package/apps/sessrumnir/src/shared/session-lineage.ts +50 -0
- package/apps/sessrumnir/src/shared/session-preview.test.ts +93 -0
- package/apps/sessrumnir/src/shared/session-preview.ts +56 -0
- package/apps/sessrumnir/src/shared/sidebar-width.test.ts +58 -0
- package/apps/sessrumnir/src/shared/sidebar-width.ts +37 -0
- package/apps/sessrumnir/src/shared/theme/builtin-ids.ts +16 -0
- package/apps/sessrumnir/src/shared/theme/resolve.test.ts +66 -0
- package/apps/sessrumnir/src/shared/theme/resolve.ts +29 -0
- package/apps/sessrumnir/src/shared/theme/syntax-defaults.ts +24 -0
- package/apps/sessrumnir/src/shared/theme/theme-file.test.ts +88 -0
- package/apps/sessrumnir/src/shared/theme/theme-file.ts +132 -0
- package/apps/sessrumnir/src/shared/theme/tokens.test.ts +35 -0
- package/apps/sessrumnir/src/shared/theme/tokens.ts +86 -0
- package/apps/sessrumnir/src/shared/tsconfig.json +17 -0
- package/apps/sessrumnir/src/shared/untrusted-data.test.ts +32 -0
- package/apps/sessrumnir/src/shared/untrusted-data.ts +22 -0
- package/apps/sessrumnir/src/shared/version-compare.test.ts +33 -0
- package/apps/sessrumnir/src/shared/version-compare.ts +50 -0
- package/apps/sessrumnir/src/shared/workflow-control.ts +33 -0
- package/apps/sessrumnir/src/web-server.ts +315 -0
- package/apps/sessrumnir/tsconfig.json +26 -0
- package/apps/smidja/smidja_build.py +45 -0
- package/apps/smidja/smidja_build_review.py +76 -0
- package/apps/smidja/smidja_build_test.py +79 -0
- package/apps/smidja/smidja_document.py +76 -0
- package/apps/smidja/smidja_modules/agent_cc.py +15 -0
- package/apps/smidja/smidja_modules/agent_opencode.py +194 -0
- package/apps/smidja/smidja_modules/agent_pi.py +392 -0
- package/apps/smidja/smidja_modules/agents.py +993 -0
- package/apps/smidja/smidja_modules/changes.py +103 -0
- package/apps/smidja/smidja_modules/console.py +131 -0
- package/apps/smidja/smidja_modules/data_types.py +447 -0
- package/apps/smidja/smidja_modules/gates.py +108 -0
- package/apps/smidja/smidja_modules/git_helper.py +120 -0
- package/apps/smidja/smidja_modules/lm_local.py +144 -0
- package/apps/smidja/smidja_modules/permissions.py +194 -0
- package/apps/smidja/smidja_modules/prompts.py +21 -0
- package/apps/smidja/smidja_modules/quality.py +240 -0
- package/apps/smidja/smidja_modules/runner.py +155 -0
- package/apps/smidja/smidja_modules/session.py +50 -0
- package/apps/smidja/smidja_modules/stall_watch.py +149 -0
- package/apps/smidja/smidja_modules/tracer.py +271 -0
- package/apps/smidja/smidja_modules/utils.py +77 -0
- package/apps/smidja/smidja_orchestrate.py +162 -0
- package/apps/smidja/smidja_plan.py +45 -0
- package/apps/smidja/smidja_plan_build.py +55 -0
- package/apps/smidja/smidja_plan_build_test.py +86 -0
- package/apps/smidja/smidja_plan_build_test_quality.py +98 -0
- package/apps/smidja/smidja_prompt.py +44 -0
- package/apps/smidja/smidja_quality.py +49 -0
- package/apps/smidja/smidja_recon_iv.py +202 -0
- package/apps/smidja/smidja_scout.py +45 -0
- package/apps/smidja/smidja_simple_sdlc.py +183 -0
- package/apps/smidja/smidja_smidja_config/smidja.config.yaml +143 -0
- package/apps/smidja-factory/AGENTS.md +165 -0
- package/apps/smidja-factory/README.md +3 -0
- package/apps/smidja-factory/SKILL.md +18 -0
- package/apps/smidja-factory/apps/visualizer/.oxlintrc.json +18 -0
- package/apps/smidja-factory/apps/visualizer/bun.lock +269 -0
- package/apps/smidja-factory/apps/visualizer/desktop/icon.png +0 -0
- package/apps/smidja-factory/apps/visualizer/desktop/main.js +140 -0
- package/apps/smidja-factory/apps/visualizer/desktop/package-lock.json +871 -0
- package/apps/smidja-factory/apps/visualizer/desktop/package.json +18 -0
- package/apps/smidja-factory/apps/visualizer/desktop/preload.js +19 -0
- package/apps/smidja-factory/apps/visualizer/index.html +28 -0
- package/apps/smidja-factory/apps/visualizer/package.json +31 -0
- package/apps/smidja-factory/apps/visualizer/public/icon.svg +7 -0
- package/apps/smidja-factory/apps/visualizer/public/models/claude.png +0 -0
- package/apps/smidja-factory/apps/visualizer/public/models/gemini.png +0 -0
- package/apps/smidja-factory/apps/visualizer/public/models/kimi.png +0 -0
- package/apps/smidja-factory/apps/visualizer/public/models/openai.png +0 -0
- package/apps/smidja-factory/apps/visualizer/public/models/zai.png +0 -0
- package/apps/smidja-factory/apps/visualizer/server/chat.ts +425 -0
- package/apps/smidja-factory/apps/visualizer/server/db.ts +1050 -0
- package/apps/smidja-factory/apps/visualizer/server/index.ts +648 -0
- package/apps/smidja-factory/apps/visualizer/server/model-catalog.ts +90 -0
- package/apps/smidja-factory/apps/visualizer/server/roster-api.ts +75 -0
- package/apps/smidja-factory/apps/visualizer/server/roster_resolve.py +170 -0
- package/apps/smidja-factory/apps/visualizer/server/settings.ts +106 -0
- package/apps/smidja-factory/apps/visualizer/shared/types.ts +630 -0
- package/apps/smidja-factory/apps/visualizer/src/App.vue +379 -0
- package/apps/smidja-factory/apps/visualizer/src/components/ChatInput.vue +155 -0
- package/apps/smidja-factory/apps/visualizer/src/components/ChatThread.vue +219 -0
- package/apps/smidja-factory/apps/visualizer/src/components/ChatView.vue +335 -0
- package/apps/smidja-factory/apps/visualizer/src/components/DecisionsView.vue +177 -0
- package/apps/smidja-factory/apps/visualizer/src/components/DetailSection.vue +76 -0
- package/apps/smidja-factory/apps/visualizer/src/components/MemoryView.vue +397 -0
- package/apps/smidja-factory/apps/visualizer/src/components/PhaseDetail.vue +1354 -0
- package/apps/smidja-factory/apps/visualizer/src/components/PhaseDots.vue +55 -0
- package/apps/smidja-factory/apps/visualizer/src/components/SessionCard.vue +583 -0
- package/apps/smidja-factory/apps/visualizer/src/components/SessionMiniCard.vue +58 -0
- package/apps/smidja-factory/apps/visualizer/src/components/SessionPanel.vue +272 -0
- package/apps/smidja-factory/apps/visualizer/src/components/SessionStartForm.vue +152 -0
- package/apps/smidja-factory/apps/visualizer/src/components/SessionTrace.vue +1157 -0
- package/apps/smidja-factory/apps/visualizer/src/components/SessionsList.vue +96 -0
- package/apps/smidja-factory/apps/visualizer/src/components/SettingsView.vue +152 -0
- package/apps/smidja-factory/apps/visualizer/src/components/StatChip.vue +98 -0
- package/apps/smidja-factory/apps/visualizer/src/components/StatsView.vue +382 -0
- package/apps/smidja-factory/apps/visualizer/src/components/StatusChip.vue +73 -0
- package/apps/smidja-factory/apps/visualizer/src/components/ToolCallCard.vue +156 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/api.ts +177 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/chat-api.ts +95 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/chat-store.ts +351 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/events.ts +131 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/format.ts +92 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/highlight.ts +54 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/markdown.ts +120 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/models.ts +42 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/router.ts +67 -0
- package/apps/smidja-factory/apps/visualizer/src/lib/types.ts +61 -0
- package/apps/smidja-factory/apps/visualizer/src/main.ts +13 -0
- package/apps/smidja-factory/apps/visualizer/src/style.css +592 -0
- package/apps/smidja-factory/apps/visualizer/tsconfig.json +30 -0
- package/apps/smidja-factory/apps/visualizer/vite.config.js +32 -0
- package/apps/smidja-factory/apps/visualizer/vite.config.ts +31 -0
- package/apps/smidja-factory/cookbooks/create_config.md +61 -0
- package/apps/smidja-factory/cookbooks/create_smidja.md +120 -0
- package/apps/smidja-factory/cookbooks/how_to_prompt_for_the_eng.md +110 -0
- package/apps/smidja-factory/cookbooks/install.md +56 -0
- package/apps/smidja-factory/cookbooks/run_smidja.md +122 -0
- package/apps/smidja-factory/cookbooks/smidja_overview.md +88 -0
- package/apps/smidja-factory/cookbooks/update_config.md +103 -0
- package/apps/smidja-factory/cookbooks/update_modules.md +100 -0
- package/apps/smidja-factory/cookbooks/update_smidja.md +90 -0
- package/apps/smidja-factory/docs/enhancement-plan.md +420 -0
- package/apps/smidja-factory/references/config.md +202 -0
- package/apps/smidja-factory/references/handoff.md +161 -0
- package/apps/smidja-factory/references/observability.md +166 -0
- package/apps/smidja-factory/scripts/install.py +113 -0
- package/apps/smidja-factory/scripts/make_config.py +35 -0
- package/apps/smidja-factory/scripts/make_smidja.py +119 -0
- package/apps/smidja-factory/skills/add-or-edit-ai-models/SKILL.md +151 -0
- package/apps/smidja-factory/skills/create-new-agent/SKILL.md +125 -0
- package/apps/smidja-factory/skills/create-new-teams/SKILL.md +151 -0
- package/apps/smidja-factory/skills/git-ops/README.md +25 -0
- package/apps/smidja-factory/skills/git-ops/SKILL.md +18 -0
- package/apps/smidja-factory/skills/git-ops/create_branch.sh +79 -0
- package/apps/smidja-factory/skills/git-ops/safe_commit.sh +82 -0
- package/apps/smidja-factory/skills/git-ops/sync_upstream.sh +94 -0
- package/apps/smidja-factory/skills/how-to-run-agent-teams/SKILL.md +117 -0
- package/apps/smidja-factory/skills/smidja-instructions/SKILL.md +168 -0
- package/apps/smidja-factory/skills/smidja-launcher/SKILL.md +155 -0
- package/apps/smidja-factory/skills/smidja-start/SKILL.md +266 -0
- package/apps/smidja-factory/skills/volundr/SKILL.md +232 -0
- package/apps/smidja-factory/skills/volundr/prompt/dispatch-prompt.md +91 -0
- package/apps/smidja-factory/skills/volundr/prompt/volundr-system.md +63 -0
- package/apps/smidja-factory/skills/volundr/scripts/volundr-observe.py +52 -0
- package/apps/smidja-factory/skills/volundr/scripts/volundr-recall.py +54 -0
- package/apps/smidja-factory/skills/volundr/scripts/volundr-status.py +51 -0
- package/apps/smidja-factory/skills/volundr/scripts/volundr-teach.py +47 -0
- package/apps/smidja-factory/templates/env.sample +28 -0
- package/apps/smidja-factory/templates/harness_engineering/subagents.ts +706 -0
- package/apps/smidja-factory/templates/harness_engineering/themeMap.ts +145 -0
- package/apps/smidja-factory/templates/justfile +89 -0
- package/apps/smidja-factory/templates/prompt_engineering/builder/system.md +13 -0
- package/apps/smidja-factory/templates/prompt_engineering/builder/user.md +34 -0
- package/apps/smidja-factory/templates/prompt_engineering/documenter/system.md +17 -0
- package/apps/smidja-factory/templates/prompt_engineering/documenter/user.md +48 -0
- package/apps/smidja-factory/templates/prompt_engineering/orchestrator/system.md +55 -0
- package/apps/smidja-factory/templates/prompt_engineering/orchestrator/user.md +39 -0
- package/apps/smidja-factory/templates/prompt_engineering/planner/system.md +21 -0
- package/apps/smidja-factory/templates/prompt_engineering/planner/user.md +45 -0
- package/apps/smidja-factory/templates/prompt_engineering/recon_orchestrator/system.md +51 -0
- package/apps/smidja-factory/templates/prompt_engineering/recon_orchestrator/user.md +26 -0
- package/apps/smidja-factory/templates/prompt_engineering/reviewer/system.md +16 -0
- package/apps/smidja-factory/templates/prompt_engineering/reviewer/user.md +44 -0
- package/apps/smidja-factory/templates/prompt_engineering/scout/system.md +32 -0
- package/apps/smidja-factory/templates/prompt_engineering/scout/user.md +34 -0
- package/apps/smidja-factory/templates/smidja/smidja_build.py +45 -0
- package/apps/smidja-factory/templates/smidja/smidja_build_review.py +76 -0
- package/apps/smidja-factory/templates/smidja/smidja_build_test.py +79 -0
- package/apps/smidja-factory/templates/smidja/smidja_document.py +76 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/agent_cc.py +15 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/agent_opencode.py +194 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/agent_pi.py +392 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/agents.py +993 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/changes.py +103 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/console.py +131 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/data_types.py +447 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/gates.py +108 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/git_helper.py +120 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/lm_local.py +144 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/permissions.py +194 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/prompts.py +21 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/quality.py +240 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/runner.py +155 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/session.py +50 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/stall_watch.py +149 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/tracer.py +271 -0
- package/apps/smidja-factory/templates/smidja/smidja_modules/utils.py +77 -0
- package/apps/smidja-factory/templates/smidja/smidja_orchestrate.py +162 -0
- package/apps/smidja-factory/templates/smidja/smidja_plan.py +45 -0
- package/apps/smidja-factory/templates/smidja/smidja_plan_build.py +55 -0
- package/apps/smidja-factory/templates/smidja/smidja_plan_build_test.py +86 -0
- package/apps/smidja-factory/templates/smidja/smidja_plan_build_test_quality.py +98 -0
- package/apps/smidja-factory/templates/smidja/smidja_prompt.py +44 -0
- package/apps/smidja-factory/templates/smidja/smidja_quality.py +49 -0
- package/apps/smidja-factory/templates/smidja/smidja_recon_iv.py +202 -0
- package/apps/smidja-factory/templates/smidja/smidja_scout.py +45 -0
- package/apps/smidja-factory/templates/smidja/smidja_simple_sdlc.py +183 -0
- package/apps/smidja-factory/templates/smidja.config.yaml +143 -0
- package/bin/app-build.sh +36 -0
- package/bin/electron-lib.sh +25 -0
- package/bin/sessrumnir.sh +1 -1
- package/bin/ymir-install.sh +7 -0
- package/package.json +15 -7
- package/scripts/electron.sh +6 -2
- package/.agents/bus/messages.json +0 -1
- package/.agents/config/agents.machine.example.yaml +0 -16
- package/.pi/mcp.json +0 -16
- package/assets/reference/state/.branch-eligible-owner +0 -4
- package/assets/reference/state/.branch-mirror-cursor +0 -1
- package/assets/reference/state/.branch-outcomes-cursor +0 -1
- package/assets/reference/state/.branch-session +0 -1
- package/assets/reference/state/.count-default_wF_p5 +0 -1
- package/assets/reference/state/.count-default_wF_p6 +0 -1
- package/assets/reference/state/.count-default_wR_p2 +0 -1
- package/assets/reference/state/.count-default_wS_p2 +0 -1
- package/assets/reference/state/.count-firstmate_fm-server-knowledge +0 -1
- package/assets/reference/state/.hash-default_wF_p5 +0 -1
- package/assets/reference/state/.hash-default_wF_p6 +0 -1
- package/assets/reference/state/.hash-default_wR_p2 +0 -1
- package/assets/reference/state/.hash-default_wS_p2 +0 -1
- package/assets/reference/state/.hash-firstmate_fm-server-knowledge +0 -1
- package/assets/reference/state/.heartbeat-streak +0 -1
- package/assets/reference/state/.inactive-outcome-reconcile +0 -2
- package/assets/reference/state/.lock +0 -1
- package/assets/reference/state/.pi-branch-extension-loaded +0 -1
- package/assets/reference/state/.pi-turnend-extension-loaded +0 -2
- package/assets/reference/state/.pi-watch-extension-loaded +0 -2
- package/assets/reference/state/.seen-server-knowledge_turn-ended +0 -1
- package/assets/reference/state/.session-start-agents-baseline +0 -2
- package/assets/reference/state/.session-start-complete +0 -1
- package/assets/reference/state/.stale-default_wF_p5 +0 -1
- package/assets/reference/state/.stale-default_wR_p2 +0 -1
- package/assets/reference/state/.stale-firstmate_fm-server-knowledge +0 -1
- package/assets/reference/state/.stale-since-default_wF_p5 +0 -1
- package/assets/reference/state/.stale-since-default_wR_p2 +0 -1
- package/assets/reference/state/.stale-since-firstmate_fm-server-knowledge +0 -1
- package/assets/reference/state/.startup-network.delivered +0 -1
- package/assets/reference/state/.startup-network.report +0 -1
- package/assets/reference/state/.startup-network.status +0 -10
- package/assets/reference/state/.startup-network.timings +0 -6
- package/assets/reference/state/.trace-context-effective +0 -1
- package/assets/reference/state/.wake-queue +0 -0
- package/assets/reference/state/.wake-queue.seq +0 -1
- package/assets/reference/state/.wake-rows.consume.BcqXSq +0 -0
- package/assets/reference/state/.wake-rows.consume.NDZZei +0 -0
- package/assets/reference/state/.wake-rows.consume.VGkhYm +0 -0
- package/assets/reference/state/.wake-rows.consume.tR2rTy +0 -0
- package/assets/reference/state/.watch-arm-output.3581p6 +0 -0
- package/assets/reference/state/.watch-arm-output.3ciDNP +0 -0
- package/assets/reference/state/.watch-arm-output.SksR6k +0 -0
- package/assets/reference/state/.watch-cycle-exits.log +0 -22
- package/assets/reference/state/.watch-deliveries.log +0 -19
- package/assets/reference/state/.watch-triage.log +0 -38
- package/assets/reference/state/.watch.lock/fm-home +0 -1
- package/assets/reference/state/.watch.lock/pid +0 -1
- package/assets/reference/state/.watch.lock/pid-identity +0 -1
- package/assets/reference/state/.watch.lock/watcher-path +0 -1
- package/assets/reference/state/.watch.lock.owner.qqbxmS/fm-home +0 -1
- package/assets/reference/state/.watch.lock.owner.qqbxmS/pid +0 -1
- package/assets/reference/state/.watch.lock.owner.qqbxmS/pid-identity +0 -1
- package/assets/reference/state/.watch.lock.owner.qqbxmS/watcher-path +0 -1
- package/assets/reference/state/.watcher-down +0 -1
- package/assets/reference/state/branch-outcomes.jsonl +0 -1
- package/assets/reference/state/branch-session/2026-09-04T16-49-38-671Z_01a06d53-6b6f-7619-930d-e6dfd9a4a29e.jsonl +0 -211
- package/assets/reference/state/home-summary.json +0 -42
- package/assets/reference/state/server-knowledge.busy-gen +0 -1
- package/assets/reference/state/server-knowledge.busy-state +0 -1
- package/assets/reference/state/server-knowledge.herdr-presentation +0 -12
- package/assets/reference/state/server-knowledge.meta +0 -18
- package/assets/reference/state/server-knowledge.pi-ext.ts +0 -26
- package/assets/reference/state/server-knowledge.turn-ended +0 -0
- /package/{assets/reference/state/.last-check → apps/hlidskjalf/src/app/.gitkeep} +0 -0
- /package/{assets/reference/state/.last-heartbeat → apps/hlidskjalf/src/components/.gitkeep} +0 -0
- /package/{assets/reference/state/.last-watcher-beat → apps/hlidskjalf/src/services/.gitkeep} +0 -0
- /package/{assets/reference/state/.main-eligible-rows.tmp.p2HMKo → apps/smidja/smidja_modules/__init__.py} +0 -0
- /package/{assets/reference/state/.main-eligible-rows.tmp.Exxm82 → apps/smidja-factory/templates/smidja/smidja_modules/__init__.py} +0 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { test } from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import { join } from 'path'
|
|
4
|
+
import {
|
|
5
|
+
engineForBoundSession,
|
|
6
|
+
engineForSessionPath,
|
|
7
|
+
getSessionsRoot,
|
|
8
|
+
getOmpSessionsRoot,
|
|
9
|
+
getSessionRoots,
|
|
10
|
+
isWithinSessionRoots,
|
|
11
|
+
} from './pi-paths'
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Each engine keeps its sessions in its own store, so a session started under
|
|
15
|
+
* OMP never reaches Pi's tree. The index has to read both or those sessions
|
|
16
|
+
* are invisible in the Sessions tab, and it has to remember which store a row
|
|
17
|
+
* came from or the app cannot relaunch the engine that owns it.
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
function withEnv(vars: Record<string, string | undefined>, run: () => void): void {
|
|
21
|
+
const saved = new Map<string, string | undefined>()
|
|
22
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
23
|
+
saved.set(key, process.env[key])
|
|
24
|
+
if (value === undefined) delete process.env[key]
|
|
25
|
+
else process.env[key] = value
|
|
26
|
+
}
|
|
27
|
+
try {
|
|
28
|
+
run()
|
|
29
|
+
} finally {
|
|
30
|
+
for (const [key, value] of saved) {
|
|
31
|
+
if (value === undefined) delete process.env[key]
|
|
32
|
+
else process.env[key] = value
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
test('the two engines resolve to different session stores', () => {
|
|
38
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
39
|
+
assert.equal(getSessionsRoot(), join('/home/tester', '.pi', 'agent', 'sessions'))
|
|
40
|
+
assert.equal(getOmpSessionsRoot(), join('/home/tester', '.omp', 'agent', 'sessions'))
|
|
41
|
+
assert.notEqual(getSessionsRoot(), getOmpSessionsRoot())
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
test('the index reads both stores, Pi first', () => {
|
|
46
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
47
|
+
assert.deepEqual(getSessionRoots(), [getSessionsRoot(), getOmpSessionsRoot()])
|
|
48
|
+
})
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
test('one directory shared by both engines is only listed once', () => {
|
|
52
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: '/shared/agent', OMP_CODING_AGENT_DIR: '/shared/agent' }, () => {
|
|
53
|
+
assert.deepEqual(getSessionRoots(), [join('/shared/agent', 'sessions')])
|
|
54
|
+
})
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
test('a session file is owned by the engine whose store holds it', () => {
|
|
58
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
59
|
+
assert.equal(engineForSessionPath(join(getSessionsRoot(), '--home-tester--', 'a.jsonl')), 'pi')
|
|
60
|
+
assert.equal(engineForSessionPath(join(getOmpSessionsRoot(), '--home-tester--', 'b.jsonl')), 'omp')
|
|
61
|
+
// Nested subagent transcripts belong to the same engine as their parent.
|
|
62
|
+
assert.equal(engineForSessionPath(join(getOmpSessionsRoot(), '--p--', 'run', 'c.jsonl')), 'omp')
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
|
|
66
|
+
test('a session outside every store has no owning engine', () => {
|
|
67
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
68
|
+
assert.equal(engineForSessionPath('/tmp/loose.jsonl'), null)
|
|
69
|
+
assert.equal(engineForSessionPath(join('/home/tester', '.pi', 'agent', 'auth.json')), null)
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test('one directory shared by both engines is owned by Pi', () => {
|
|
74
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: '/shared/agent', OMP_CODING_AGENT_DIR: '/shared/agent' }, () => {
|
|
75
|
+
// Same tie-break as getSessionRoots, so the row's engine matches the root
|
|
76
|
+
// the index listed it from.
|
|
77
|
+
assert.equal(engineForSessionPath(join('/shared/agent', 'sessions', '--p--', 'a.jsonl')), 'pi')
|
|
78
|
+
})
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test('a session created by OMP is authorized, not just a Pi one', () => {
|
|
82
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
83
|
+
const piSession = join(getSessionsRoot(), '--home-tester--', 'a.jsonl')
|
|
84
|
+
const ompSession = join(getOmpSessionsRoot(), '--home-tester--', 'b.jsonl')
|
|
85
|
+
|
|
86
|
+
assert.equal(isWithinSessionRoots(piSession), true)
|
|
87
|
+
// This is the regression: before the index read both stores, resuming or
|
|
88
|
+
// deleting an OMP session was refused as being outside the session root.
|
|
89
|
+
assert.equal(isWithinSessionRoots(ompSession), true)
|
|
90
|
+
})
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test('a path outside every store is still refused', () => {
|
|
94
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
95
|
+
assert.equal(isWithinSessionRoots('/etc/passwd'), false)
|
|
96
|
+
assert.equal(isWithinSessionRoots(join('/home/tester', '.pi', 'agent', 'auth.json')), false)
|
|
97
|
+
// A sibling directory whose name merely starts with the root must not pass.
|
|
98
|
+
assert.equal(isWithinSessionRoots(join('/home/tester', '.omp', 'agent', 'sessions-backup', 'x.jsonl')), false)
|
|
99
|
+
})
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The runtime launcher and the permission-mode options both have to name the
|
|
104
|
+
* same engine for one start. If they disagree, a start runs OMP while being
|
|
105
|
+
* given Pi's plan-mode tool names, so plan mode loses the tools it should allow.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
test('a start bound to an OMP session belongs to OMP', () => {
|
|
109
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
110
|
+
const ompSession = join(getOmpSessionsRoot(), '--p--', 'a.jsonl')
|
|
111
|
+
assert.equal(engineForBoundSession({ sessionPath: ompSession }), 'omp')
|
|
112
|
+
assert.equal(engineForBoundSession({ sessionPath: join(getSessionsRoot(), '--p--', 'a.jsonl') }), 'pi')
|
|
113
|
+
})
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
test('a fork reads its source, so the source engine wins over the new file', () => {
|
|
117
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
118
|
+
assert.equal(
|
|
119
|
+
engineForBoundSession({
|
|
120
|
+
sessionPath: join(getSessionsRoot(), '--p--', 'new.jsonl'),
|
|
121
|
+
forkSessionPath: join(getOmpSessionsRoot(), '--p--', 'source.jsonl'),
|
|
122
|
+
}),
|
|
123
|
+
'omp'
|
|
124
|
+
)
|
|
125
|
+
})
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
test('a start with no session has no owning engine', () => {
|
|
129
|
+
withEnv({ HOME: '/home/tester', PI_CODING_AGENT_DIR: undefined, OMP_CODING_AGENT_DIR: undefined }, () => {
|
|
130
|
+
// A brand-new session is free to use whichever engine is configured.
|
|
131
|
+
assert.equal(engineForBoundSession({}), null)
|
|
132
|
+
assert.equal(engineForBoundSession({ sessionPath: '/tmp/loose.jsonl' }), null)
|
|
133
|
+
})
|
|
134
|
+
})
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { join } from 'path'
|
|
2
|
+
import { isPathWithin } from './path-authorization'
|
|
3
|
+
import type { AgentEngineKind } from '../shared/ipc-contracts'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Absolute path to Pi's on-disk session store (`~/.pi/agent/sessions`).
|
|
7
|
+
* Centralized so session listing, lineage, and activity aggregation agree.
|
|
8
|
+
*/
|
|
9
|
+
export function getSessionsRoot(): string {
|
|
10
|
+
const agentDir = process.env.PI_CODING_AGENT_DIR ||
|
|
11
|
+
join(process.env.HOME ?? process.env.USERPROFILE ?? '', '.pi', 'agent')
|
|
12
|
+
return join(agentDir, 'sessions')
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Absolute path to OMP's session store (`~/.omp/agent/sessions`).
|
|
17
|
+
*
|
|
18
|
+
* Each engine keeps its own sessions: OMP writes here, Pi writes under
|
|
19
|
+
* `~/.pi`, and neither is pointed at the other's tree. Both stores use the
|
|
20
|
+
* same per-project directory naming and the same JSONL record shape, so the
|
|
21
|
+
* index can read them side by side.
|
|
22
|
+
*/
|
|
23
|
+
export function getOmpSessionsRoot(): string {
|
|
24
|
+
const agentDir = process.env.OMP_CODING_AGENT_DIR ||
|
|
25
|
+
join(process.env.HOME ?? process.env.USERPROFILE ?? '', '.omp', 'agent')
|
|
26
|
+
return join(agentDir, 'sessions')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Every store the session index reads, Pi's first so its rows win a tie.
|
|
31
|
+
* Duplicates are dropped so an env var pointing both engines at one directory
|
|
32
|
+
* cannot list the same session twice.
|
|
33
|
+
*/
|
|
34
|
+
export function getSessionRoots(): string[] {
|
|
35
|
+
return [...new Set([getSessionsRoot(), getOmpSessionsRoot()])]
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The engine that owns a session file: the store it lives in. Pi's store is
|
|
40
|
+
* checked first so a directory shared by both engines (one env var pointing at
|
|
41
|
+
* the other's) resolves the way getSessionRoots orders it. Null means the path
|
|
42
|
+
* is in no store at all, which is also what makes it unauthorized.
|
|
43
|
+
*/
|
|
44
|
+
export function engineForSessionPath(candidate: string): AgentEngineKind | null {
|
|
45
|
+
if (isPathWithin(getSessionsRoot(), candidate)) return 'pi'
|
|
46
|
+
if (isPathWithin(getOmpSessionsRoot(), candidate)) return 'omp'
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The engine a start must use, taken from the session file that start is bound
|
|
52
|
+
* to. A fork source outranks a session path because the fork reads the source
|
|
53
|
+
* before it writes anything. Null when the start creates a new session and so
|
|
54
|
+
* has no owner yet, leaving the caller free to use the configured engine.
|
|
55
|
+
*
|
|
56
|
+
* Shared by the runtime launcher and the permission-mode options so both agree
|
|
57
|
+
* on which engine a start belongs to — the tool names differ per engine, so a
|
|
58
|
+
* disagreement sends OMP Pi's tool list.
|
|
59
|
+
*/
|
|
60
|
+
export function engineForBoundSession(
|
|
61
|
+
bound: { sessionPath?: string; forkSessionPath?: string }
|
|
62
|
+
): AgentEngineKind | null {
|
|
63
|
+
const boundSessionPath = bound.forkSessionPath ?? bound.sessionPath
|
|
64
|
+
return boundSessionPath ? engineForSessionPath(boundSessionPath) : null
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Authorization gate for a session path the renderer supplied. A path is
|
|
69
|
+
* acceptable when it sits inside any store the index itself reads; anything
|
|
70
|
+
* else is refused, which is what keeps resume/fork/delete inside the stores.
|
|
71
|
+
*/
|
|
72
|
+
export function isWithinSessionRoots(candidate: string): boolean {
|
|
73
|
+
return engineForSessionPath(candidate) !== null
|
|
74
|
+
}
|
|
@@ -0,0 +1,467 @@
|
|
|
1
|
+
import assert from 'node:assert/strict'
|
|
2
|
+
import { test } from 'node:test'
|
|
3
|
+
import { chmodSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs'
|
|
4
|
+
import { tmpdir } from 'node:os'
|
|
5
|
+
import { join } from 'node:path'
|
|
6
|
+
import {
|
|
7
|
+
buildPiArgs,
|
|
8
|
+
buildPiInvocation,
|
|
9
|
+
detectPiInstallations,
|
|
10
|
+
PiRpcManager,
|
|
11
|
+
RpcTimeoutError,
|
|
12
|
+
resolveStartCli,
|
|
13
|
+
RpcFrameDecoder,
|
|
14
|
+
setPiExecutableOverride,
|
|
15
|
+
type PiCli,
|
|
16
|
+
} from './pi-rpc-manager'
|
|
17
|
+
import { appLog } from './app-log'
|
|
18
|
+
import { i18n } from '../shared/i18n'
|
|
19
|
+
import { PSEUDO_LANGUAGE, SOURCE_LANGUAGE } from '../shared/i18n/languages'
|
|
20
|
+
|
|
21
|
+
/** A pseudo-language string: bracketed and padded with "~" (see pseudo.ts). */
|
|
22
|
+
const PSEUDO_MARKED = /^\[[^]*~+\]$/
|
|
23
|
+
const PREFLIGHT_LOG_MESSAGE = 'Pre-flight failed'
|
|
24
|
+
|
|
25
|
+
/** The sender's chunk size: OMP protocol v2 splits payloads at 256 KiB. */
|
|
26
|
+
const CHUNK_PAYLOAD_BYTES = 256 * 1024
|
|
27
|
+
/** The frame size the decoder used to demand before it would reassemble. */
|
|
28
|
+
const REMOVED_FRAME_FLOOR_BYTES = 1024 * 1024
|
|
29
|
+
const MAX_REASSEMBLED_BYTES = 64 * 1024 * 1024
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* A resolution fixture. `needsShell` is only ever true on Windows for a
|
|
33
|
+
* `.cmd`/`.bat`/`.ps1` shim, and never together with `useNode` — see
|
|
34
|
+
* pi-binary-resolution.finalize.
|
|
35
|
+
*/
|
|
36
|
+
function piCli(overrides: Partial<PiCli> = {}): PiCli {
|
|
37
|
+
return {
|
|
38
|
+
script: '/usr/local/bin/pi',
|
|
39
|
+
node: '/usr/bin/node',
|
|
40
|
+
useNode: false,
|
|
41
|
+
needsShell: false,
|
|
42
|
+
found: true,
|
|
43
|
+
nodeFound: true,
|
|
44
|
+
failureReason: null,
|
|
45
|
+
...overrides,
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** The physical frames a sender emits for one logical frame, in wire order. */
|
|
50
|
+
function chunkFrames(chunkId: string, payload: string): Array<Record<string, unknown>> {
|
|
51
|
+
const bytes = Buffer.from(payload, 'utf8')
|
|
52
|
+
const count = Math.ceil(bytes.length / CHUNK_PAYLOAD_BYTES)
|
|
53
|
+
return Array.from({ length: count }, (_unused, index) => ({
|
|
54
|
+
type: 'rpc_chunk',
|
|
55
|
+
chunkId,
|
|
56
|
+
index,
|
|
57
|
+
count,
|
|
58
|
+
byteLength: bytes.length,
|
|
59
|
+
data: bytes.subarray(index * CHUNK_PAYLOAD_BYTES, (index + 1) * CHUNK_PAYLOAD_BYTES).toString('base64'),
|
|
60
|
+
}))
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function decodeAll(frames: Array<Record<string, unknown>>): object | undefined {
|
|
64
|
+
const decoder = new RpcFrameDecoder()
|
|
65
|
+
let decoded: object | undefined
|
|
66
|
+
for (const frame of frames) {
|
|
67
|
+
const result = decoder.push(frame)
|
|
68
|
+
if (result) decoded = result
|
|
69
|
+
}
|
|
70
|
+
return decoded
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function responsePayload(size: number, filler: string): string {
|
|
74
|
+
return JSON.stringify({ type: 'response', command: 'get_messages', success: true, data: filler.repeat(size) })
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
test('RpcFrameDecoder reassembles a lossless OMP protocol-v2 frame', () => {
|
|
78
|
+
const frames = chunkFrames('rpc-test', responsePayload(1_100_000, 'x'))
|
|
79
|
+
assert.equal((decodeAll(frames) as { data?: string }).data?.length, 1_100_000)
|
|
80
|
+
})
|
|
81
|
+
|
|
82
|
+
test('RpcFrameDecoder reassembles a two-chunk frame smaller than one whole frame', () => {
|
|
83
|
+
// 300 KiB splits into exactly two chunks, and two chunks can never reach the
|
|
84
|
+
// 1 MiB floor the metadata check used to impose — every such sequence was
|
|
85
|
+
// discarded, leaving sendCommand to time out with an empty result.
|
|
86
|
+
const payload = responsePayload(300 * 1024, 'y')
|
|
87
|
+
const frames = chunkFrames('rpc-small', payload)
|
|
88
|
+
assert.equal(frames.length, 2)
|
|
89
|
+
assert.ok(Buffer.byteLength(payload, 'utf8') < REMOVED_FRAME_FLOOR_BYTES)
|
|
90
|
+
|
|
91
|
+
const decoded = decodeAll(frames)
|
|
92
|
+
assert.deepEqual(decoded, JSON.parse(payload))
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
test('RpcFrameDecoder still refuses a declared length above the reassembly limit', () => {
|
|
96
|
+
const decoder = new RpcFrameDecoder()
|
|
97
|
+
const frame = {
|
|
98
|
+
type: 'rpc_chunk',
|
|
99
|
+
chunkId: 'rpc-huge',
|
|
100
|
+
index: 0,
|
|
101
|
+
count: 2,
|
|
102
|
+
byteLength: MAX_REASSEMBLED_BYTES + 1,
|
|
103
|
+
data: Buffer.from('a').toString('base64'),
|
|
104
|
+
}
|
|
105
|
+
assert.throws(() => decoder.push(frame), /invalid rpc chunk metadata/)
|
|
106
|
+
assert.equal(decoder.hasPending(), false)
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
test('RpcFrameDecoder rejects a sequence that does not match its declared length', () => {
|
|
110
|
+
const frames = chunkFrames('rpc-lying', responsePayload(300 * 1024, 'z'))
|
|
111
|
+
const inflated = frames.map((frame) => ({ ...frame, byteLength: (frame.byteLength as number) + 1 }))
|
|
112
|
+
assert.throws(() => decodeAll(inflated), /length mismatch/)
|
|
113
|
+
})
|
|
114
|
+
|
|
115
|
+
test('RpcFrameDecoder can be reset after an interrupted sequence', () => {
|
|
116
|
+
const decoder = new RpcFrameDecoder()
|
|
117
|
+
const first = {
|
|
118
|
+
type: 'rpc_chunk',
|
|
119
|
+
chunkId: 'rpc-a',
|
|
120
|
+
index: 0,
|
|
121
|
+
count: 2,
|
|
122
|
+
byteLength: 2,
|
|
123
|
+
data: Buffer.from('a').toString('base64'),
|
|
124
|
+
}
|
|
125
|
+
decoder.push(first)
|
|
126
|
+
assert.equal(decoder.hasPending(), true)
|
|
127
|
+
assert.throws(() => decoder.push({ ...first, chunkId: 'rpc-b' }), /sequence mismatch/)
|
|
128
|
+
decoder.reset()
|
|
129
|
+
assert.equal(decoder.hasPending(), false)
|
|
130
|
+
})
|
|
131
|
+
|
|
132
|
+
test('no start forces a session directory on the engine', () => {
|
|
133
|
+
// Pointing OMP at Pi's root only moved resumed sessions — OMP ignores the
|
|
134
|
+
// flag for new ones — so one conversation history ended up split across both
|
|
135
|
+
// trees. Each engine now keeps its own store and the index reads both.
|
|
136
|
+
assert.deepEqual(buildPiArgs({ cwd: '/projects/app' }), ['--mode', 'rpc'])
|
|
137
|
+
assert.deepEqual(buildPiArgs({ engine: 'omp', cwd: '/projects/app' }), ['--mode', 'rpc'])
|
|
138
|
+
assert.deepEqual(buildPiArgs({ engine: 'pi', cwd: '/projects/app' }), ['--mode', 'rpc'])
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
test('a caller that asks for a shared session directory still gets one', () => {
|
|
142
|
+
assert.deepEqual(
|
|
143
|
+
buildPiArgs({ engine: 'omp', args: ['--session-dir', '/shared/sessions'] }),
|
|
144
|
+
['--mode', 'rpc', '--session-dir', '/shared/sessions'],
|
|
145
|
+
)
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
test('an explicit session path is passed to the engine that owns it', () => {
|
|
149
|
+
assert.deepEqual(
|
|
150
|
+
buildPiArgs({ engine: 'omp', sessionPath: '/home/u/.omp/agent/sessions/--p--/s.jsonl' }),
|
|
151
|
+
['--mode', 'rpc', '--session', '/home/u/.omp/agent/sessions/--p--/s.jsonl'],
|
|
152
|
+
)
|
|
153
|
+
// --session wins over the resume preference, so opening a session never
|
|
154
|
+
// silently lands on "the most recent session for this cwd" instead.
|
|
155
|
+
assert.deepEqual(
|
|
156
|
+
buildPiArgs({ sessionPath: '/sessions/s.jsonl', continueSession: true }),
|
|
157
|
+
['--mode', 'rpc', '--session', '/sessions/s.jsonl'],
|
|
158
|
+
)
|
|
159
|
+
})
|
|
160
|
+
|
|
161
|
+
test('a start resolves the engine that owns the session, without moving the configured one', () => {
|
|
162
|
+
// Sandbox HOME/PATH so both engines resolve inside the fixture directory and
|
|
163
|
+
// the login-shell probe cannot widen PATH (see detectPiInstallations below).
|
|
164
|
+
const dir = mkdtempSync(join(tmpdir(), 'pi-engine-'))
|
|
165
|
+
const saved = { HOME: process.env.HOME, PATH: process.env.PATH, SHELL: process.env.SHELL }
|
|
166
|
+
try {
|
|
167
|
+
process.env.HOME = dir
|
|
168
|
+
process.env.PATH = dir
|
|
169
|
+
process.env.SHELL = join(dir, 'no-such-shell')
|
|
170
|
+
writeFileSync(join(dir, 'pi'), '')
|
|
171
|
+
writeFileSync(join(dir, 'omp'), '')
|
|
172
|
+
// The user's configured default: Pi for everything.
|
|
173
|
+
setPiExecutableOverride(null, 'pi')
|
|
174
|
+
|
|
175
|
+
assert.deepEqual(
|
|
176
|
+
{ kind: resolveStartCli({ engine: 'omp' }).kind, script: resolveStartCli({ engine: 'omp' }).script },
|
|
177
|
+
{ kind: 'omp', script: join(dir, 'omp') },
|
|
178
|
+
'an OMP session must start OMP even though Pi is the configured engine',
|
|
179
|
+
)
|
|
180
|
+
assert.equal(resolveStartCli({ engine: 'pi' }).script, join(dir, 'pi'))
|
|
181
|
+
assert.equal(resolveStartCli({}).script, join(dir, 'pi'), 'no engine means the configured one')
|
|
182
|
+
// The override is a parameter, never a global the caller flips: two session
|
|
183
|
+
// runtimes start concurrently, so a mutated global would leak one session's
|
|
184
|
+
// engine into another session's spawn.
|
|
185
|
+
assert.equal(resolveStartCli({}).kind, 'pi', 'resolving OMP must not change the configured engine')
|
|
186
|
+
} finally {
|
|
187
|
+
setPiExecutableOverride(null, 'auto')
|
|
188
|
+
process.env.HOME = saved.HOME
|
|
189
|
+
process.env.PATH = saved.PATH
|
|
190
|
+
if (saved.SHELL === undefined) delete process.env.SHELL
|
|
191
|
+
else process.env.SHELL = saved.SHELL
|
|
192
|
+
rmSync(dir, { recursive: true, force: true })
|
|
193
|
+
}
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
test('a session whose engine is not installed still opens under the configured one', () => {
|
|
197
|
+
const dir = mkdtempSync(join(tmpdir(), 'pi-engine-missing-'))
|
|
198
|
+
const saved = { HOME: process.env.HOME, PATH: process.env.PATH, SHELL: process.env.SHELL }
|
|
199
|
+
try {
|
|
200
|
+
process.env.HOME = dir
|
|
201
|
+
process.env.PATH = dir
|
|
202
|
+
process.env.SHELL = join(dir, 'no-such-shell')
|
|
203
|
+
writeFileSync(join(dir, 'pi'), '')
|
|
204
|
+
setPiExecutableOverride(null, 'pi')
|
|
205
|
+
|
|
206
|
+
// No `omp` binary in the sandbox. Both engines write the same JSONL, so
|
|
207
|
+
// opening the conversation beats refusing to open it.
|
|
208
|
+
const cli = resolveStartCli({ engine: 'omp' })
|
|
209
|
+
assert.equal(cli.script, join(dir, 'pi'))
|
|
210
|
+
assert.equal(cli.found, true)
|
|
211
|
+
assert.equal(cli.failureReason, null)
|
|
212
|
+
} finally {
|
|
213
|
+
setPiExecutableOverride(null, 'auto')
|
|
214
|
+
process.env.HOME = saved.HOME
|
|
215
|
+
process.env.PATH = saved.PATH
|
|
216
|
+
if (saved.SHELL === undefined) delete process.env.SHELL
|
|
217
|
+
else process.env.SHELL = saved.SHELL
|
|
218
|
+
rmSync(dir, { recursive: true, force: true })
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
|
|
222
|
+
test('a pre-flight failure shows interface text and logs English', async () => {
|
|
223
|
+
const dir = mkdtempSync(join(tmpdir(), 'pi-preflight-language-'))
|
|
224
|
+
const saved = { HOME: process.env.HOME, PATH: process.env.PATH, SHELL: process.env.SHELL }
|
|
225
|
+
await i18n.changeLanguage(PSEUDO_LANGUAGE)
|
|
226
|
+
try {
|
|
227
|
+
process.env.HOME = dir
|
|
228
|
+
process.env.PATH = dir
|
|
229
|
+
process.env.SHELL = join(dir, 'no-such-shell')
|
|
230
|
+
writeFileSync(join(dir, 'pi'), '')
|
|
231
|
+
setPiExecutableOverride(null, 'pi')
|
|
232
|
+
const missingCwd = join(dir, 'missing')
|
|
233
|
+
|
|
234
|
+
const status = await new PiRpcManager().start({ cwd: missingCwd })
|
|
235
|
+
|
|
236
|
+
assert.equal(status.status, 'error')
|
|
237
|
+
// The UI text is in the interface language; the path inside it is not.
|
|
238
|
+
assert.match(status.error ?? '', PSEUDO_MARKED)
|
|
239
|
+
assert.ok(status.error?.includes(missingCwd))
|
|
240
|
+
// The log feeds the diagnostics report, which stays English.
|
|
241
|
+
const logged = appLog.getRecent().filter((entry) => entry.message === PREFLIGHT_LOG_MESSAGE).at(-1)
|
|
242
|
+
assert.equal(logged?.detail, `Pi working directory does not exist or is not a directory:\n ${missingCwd}`)
|
|
243
|
+
} finally {
|
|
244
|
+
await i18n.changeLanguage(SOURCE_LANGUAGE)
|
|
245
|
+
setPiExecutableOverride(null, 'auto')
|
|
246
|
+
process.env.HOME = saved.HOME
|
|
247
|
+
process.env.PATH = saved.PATH
|
|
248
|
+
if (saved.SHELL === undefined) delete process.env.SHELL
|
|
249
|
+
else process.env.SHELL = saved.SHELL
|
|
250
|
+
rmSync(dir, { recursive: true, force: true })
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
|
|
254
|
+
test('buildPiInvocation escapes the shim path and args for the Windows cmd.exe hop', () => {
|
|
255
|
+
const cli = piCli({ script: String.raw`C:\Program Files\nodejs\pi.cmd`, needsShell: true })
|
|
256
|
+
assert.deepEqual(buildPiInvocation(cli, ['--mode', 'rpc', '--session', 'a&calc']), {
|
|
257
|
+
file: String.raw`"C:\Program Files\nodejs\pi.cmd"`,
|
|
258
|
+
args: ['--mode', 'rpc', '--session', '"a&calc"'],
|
|
259
|
+
})
|
|
260
|
+
})
|
|
261
|
+
|
|
262
|
+
test('buildPiInvocation escapes cmd metacharacters coming from the user profile path', () => {
|
|
263
|
+
const cli = piCli({ script: String.raw`C:\Users\Tom & Jerry\100%\pi.cmd`, needsShell: true })
|
|
264
|
+
assert.equal(
|
|
265
|
+
buildPiInvocation(cli, []).file,
|
|
266
|
+
String.raw`"C:\Users\Tom & Jerry\100"^%"\pi.cmd"`,
|
|
267
|
+
)
|
|
268
|
+
})
|
|
269
|
+
|
|
270
|
+
test('buildPiInvocation leaves the node path byte-identical', () => {
|
|
271
|
+
// useNode implies needsShell false (a .js entry point is launched directly),
|
|
272
|
+
// so nothing may be rewritten even when the paths contain spaces.
|
|
273
|
+
const cli = piCli({
|
|
274
|
+
script: String.raw`C:\Program Files\nodejs\node_modules\pi\cli.js`,
|
|
275
|
+
node: String.raw`C:\Program Files\nodejs\node.exe`,
|
|
276
|
+
useNode: true,
|
|
277
|
+
})
|
|
278
|
+
assert.deepEqual(buildPiInvocation(cli, ['--mode', 'rpc', '--session', 'a&calc']), {
|
|
279
|
+
file: String.raw`C:\Program Files\nodejs\node.exe`,
|
|
280
|
+
args: [
|
|
281
|
+
String.raw`C:\Program Files\nodejs\node_modules\pi\cli.js`,
|
|
282
|
+
'--mode',
|
|
283
|
+
'rpc',
|
|
284
|
+
'--session',
|
|
285
|
+
'a&calc',
|
|
286
|
+
],
|
|
287
|
+
})
|
|
288
|
+
})
|
|
289
|
+
|
|
290
|
+
test('buildPiInvocation leaves a direct POSIX spawn byte-identical', () => {
|
|
291
|
+
const cli = piCli({ script: '/home/tester/my agents/pi' })
|
|
292
|
+
assert.deepEqual(buildPiInvocation(cli, ['--mode', 'rpc', '--session', 'a&calc']), {
|
|
293
|
+
file: '/home/tester/my agents/pi',
|
|
294
|
+
args: ['--mode', 'rpc', '--session', 'a&calc'],
|
|
295
|
+
})
|
|
296
|
+
})
|
|
297
|
+
|
|
298
|
+
test('buildPiInvocation preserves fork startup arguments', () => {
|
|
299
|
+
const cli = piCli()
|
|
300
|
+
assert.deepEqual(buildPiInvocation(cli, ['--mode', 'rpc', '--fork', '/sessions/source.jsonl']), {
|
|
301
|
+
file: '/usr/local/bin/pi',
|
|
302
|
+
args: ['--mode', 'rpc', '--fork', '/sessions/source.jsonl'],
|
|
303
|
+
})
|
|
304
|
+
})
|
|
305
|
+
|
|
306
|
+
test('buildPiInvocation rejects arguments cmd.exe cannot carry', () => {
|
|
307
|
+
const cli = piCli({ script: String.raw`C:\npm\pi.cmd`, needsShell: true })
|
|
308
|
+
assert.throws(
|
|
309
|
+
() => buildPiInvocation(cli, ['--session', 'a\nb']),
|
|
310
|
+
/cannot be passed through cmd\.exe/,
|
|
311
|
+
)
|
|
312
|
+
// Off the cmd path the same value is passed through as-is: spawn hands argv
|
|
313
|
+
// to the OS directly, so there is nothing to truncate a command line.
|
|
314
|
+
assert.deepEqual(buildPiInvocation(piCli(), ['--session', 'a\nb']).args, ['--session', 'a\nb'])
|
|
315
|
+
})
|
|
316
|
+
|
|
317
|
+
// ─── Startup deadline behavior (issue #58) ──────────────────────────────────
|
|
318
|
+
//
|
|
319
|
+
// The engine runs every extension session_start hook before it reads stdin, so
|
|
320
|
+
// a hook that waits on a local model server keeps the readiness probe
|
|
321
|
+
// unanswered for tens of seconds while the process is demonstrably alive.
|
|
322
|
+
// The deadline is therefore two-staged: a short cap while stdout is silent
|
|
323
|
+
// (dead spawn / broken pipe), a long cap once stdout has shown life.
|
|
324
|
+
|
|
325
|
+
/** Fast test caps — real values are 20s / 120s. */
|
|
326
|
+
const TEST_SILENCE_MS = 400
|
|
327
|
+
const TEST_ENGINE_BUSY_MS = 2_000
|
|
328
|
+
/** Probe id the manager correlates on; fixed by the wire protocol. */
|
|
329
|
+
const PROBE_ID = '__startup_probe__'
|
|
330
|
+
/** Fixture heartbeat: proves liveness well within the silence cap. */
|
|
331
|
+
const HEARTBEAT_MS = 100
|
|
332
|
+
/** Late-ready fixture answers between the two caps. */
|
|
333
|
+
const LATE_READY_DELAY_MS = 900
|
|
334
|
+
const SKIP_ON_WINDOWS = { skip: process.platform === 'win32' ? 'POSIX shebang fixture' : false }
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* A stand-in engine. Modes via FAKE_PI_MODE:
|
|
338
|
+
* - 'silent' — stays alive, never writes stdout.
|
|
339
|
+
* - 'late-ready' — emits frames immediately, answers the probe only after
|
|
340
|
+
* FAKE_PI_READY_DELAY_MS.
|
|
341
|
+
* - 'never-ready' — emits frames forever, never answers the probe.
|
|
342
|
+
*/
|
|
343
|
+
const FAKE_ENGINE_SOURCE = `#!/usr/bin/env node
|
|
344
|
+
const mode = process.env.FAKE_PI_MODE || 'silent'
|
|
345
|
+
const readyDelayMs = Number(process.env.FAKE_PI_READY_DELAY_MS || '0')
|
|
346
|
+
const emit = (obj) => process.stdout.write(JSON.stringify(obj) + '\\n')
|
|
347
|
+
if (mode !== 'silent') {
|
|
348
|
+
emit({ type: 'extension_ui_request', id: 'boot', method: 'setStatus', statusKey: 'boot', statusText: 'loading' })
|
|
349
|
+
setInterval(() => emit({ type: 'extension_ui_request', id: 'hb', method: 'setStatus', statusKey: 'hb', statusText: 'busy' }), ${HEARTBEAT_MS})
|
|
350
|
+
if (mode === 'late-ready') {
|
|
351
|
+
setTimeout(() => emit({ id: '${PROBE_ID}', type: 'response', command: 'get_state', success: true }), readyDelayMs)
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
process.stdin.resume()
|
|
355
|
+
`
|
|
356
|
+
|
|
357
|
+
async function withFakeEngine(
|
|
358
|
+
run: (manager: PiRpcManager, startEnv: Record<string, string>) => Promise<void>,
|
|
359
|
+
env: Record<string, string>,
|
|
360
|
+
): Promise<void> {
|
|
361
|
+
const dir = mkdtempSync(join(tmpdir(), 'pi-fake-engine-'))
|
|
362
|
+
const script = join(dir, 'fake-pi')
|
|
363
|
+
writeFileSync(script, FAKE_ENGINE_SOURCE)
|
|
364
|
+
chmodSync(script, 0o755)
|
|
365
|
+
setPiExecutableOverride(script, 'pi')
|
|
366
|
+
const manager = new PiRpcManager({ silenceMs: TEST_SILENCE_MS, engineBusyMs: TEST_ENGINE_BUSY_MS })
|
|
367
|
+
try {
|
|
368
|
+
await run(manager, env)
|
|
369
|
+
} finally {
|
|
370
|
+
manager.stop()
|
|
371
|
+
setPiExecutableOverride(null, 'auto')
|
|
372
|
+
rmSync(dir, { recursive: true, force: true })
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const delay = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms))
|
|
377
|
+
|
|
378
|
+
test('startup keeps waiting past the silence cap while Pi is emitting output', SKIP_ON_WINDOWS, async () => {
|
|
379
|
+
await withFakeEngine(async (manager, env) => {
|
|
380
|
+
const phases: string[] = []
|
|
381
|
+
manager.on('startup-phase', (phase: string) => phases.push(phase))
|
|
382
|
+
|
|
383
|
+
const started = manager.start({ env })
|
|
384
|
+
// Between the caps: the silence deadline has passed, readiness has not
|
|
385
|
+
// arrived, and stdout activity must have switched the manager to waiting.
|
|
386
|
+
await delay(TEST_SILENCE_MS + 200)
|
|
387
|
+
assert.equal(manager.getStatus().status, 'starting', 'still starting between the caps')
|
|
388
|
+
assert.equal(manager.getStatus().startupPhase, 'waiting-on-engine')
|
|
389
|
+
assert.deepEqual(phases, ['waiting-on-engine'], 'the phase flip is announced once')
|
|
390
|
+
|
|
391
|
+
const status = await started
|
|
392
|
+
assert.equal(status.status, 'running', 'a late probe response still means ready')
|
|
393
|
+
assert.equal(status.startupPhase, undefined, 'phase reporting ends with startup')
|
|
394
|
+
}, { FAKE_PI_MODE: 'late-ready', FAKE_PI_READY_DELAY_MS: String(LATE_READY_DELAY_MS) })
|
|
395
|
+
})
|
|
396
|
+
|
|
397
|
+
test('a silent Pi still fails fast at the silence cap', SKIP_ON_WINDOWS, async () => {
|
|
398
|
+
await withFakeEngine(async (manager, env) => {
|
|
399
|
+
const startedAt = Date.now()
|
|
400
|
+
const status = await manager.start({ env })
|
|
401
|
+
assert.equal(status.status, 'error')
|
|
402
|
+
assert.match(status.error ?? '', /produced no output within 0\.4s/)
|
|
403
|
+
// The old message asserted two specific causes that misdiagnosed issue
|
|
404
|
+
// #58 for days; the error must not name them any more.
|
|
405
|
+
assert.doesNotMatch(status.error ?? '', /shell:true|waiting on input/)
|
|
406
|
+
assert.ok(
|
|
407
|
+
Date.now() - startedAt < TEST_ENGINE_BUSY_MS,
|
|
408
|
+
'silence must not inherit the long engine-busy cap',
|
|
409
|
+
)
|
|
410
|
+
}, { FAKE_PI_MODE: 'silent' })
|
|
411
|
+
})
|
|
412
|
+
|
|
413
|
+
test('a chatty but never-ready Pi fails at the engine-busy cap with an engine-busy error', SKIP_ON_WINDOWS, async () => {
|
|
414
|
+
await withFakeEngine(async (manager, env) => {
|
|
415
|
+
const startedAt = Date.now()
|
|
416
|
+
const status = await manager.start({ env })
|
|
417
|
+
assert.equal(status.status, 'error')
|
|
418
|
+
assert.ok(
|
|
419
|
+
Date.now() - startedAt >= TEST_ENGINE_BUSY_MS - HEARTBEAT_MS,
|
|
420
|
+
'the full engine-busy cap is granted before giving up',
|
|
421
|
+
)
|
|
422
|
+
assert.match(status.error ?? '', /did not become ready within 2s/)
|
|
423
|
+
assert.match(status.error ?? '', /model server/, 'the message points at the real cause class')
|
|
424
|
+
assert.equal(status.startupPhase, undefined, 'phase reporting ends with startup')
|
|
425
|
+
}, { FAKE_PI_MODE: 'never-ready' })
|
|
426
|
+
})
|
|
427
|
+
|
|
428
|
+
test('detectPiInstallations serves a cached scan until a rescan forces a fresh one', () => {
|
|
429
|
+
// The resolver reads process.env live, so a sandbox HOME plus a PATH holding
|
|
430
|
+
// only the fixture directory keeps every search branch inside the temp tree.
|
|
431
|
+
// SHELL points at nothing, so the login-shell probe cannot widen that PATH.
|
|
432
|
+
const dir = mkdtempSync(join(tmpdir(), 'pi-detect-'))
|
|
433
|
+
const saved = { HOME: process.env.HOME, PATH: process.env.PATH, SHELL: process.env.SHELL }
|
|
434
|
+
try {
|
|
435
|
+
process.env.HOME = dir
|
|
436
|
+
process.env.PATH = dir
|
|
437
|
+
process.env.SHELL = join(dir, 'no-such-shell')
|
|
438
|
+
writeFileSync(join(dir, 'pi'), '')
|
|
439
|
+
|
|
440
|
+
const initial = detectPiInstallations(true)
|
|
441
|
+
assert.deepEqual(initial, [{ kind: 'pi', path: join(dir, 'pi'), source: 'path' }])
|
|
442
|
+
|
|
443
|
+
// An engine installed after that scan: the cached answer cannot show it.
|
|
444
|
+
writeFileSync(join(dir, 'omp'), '')
|
|
445
|
+
assert.deepEqual(detectPiInstallations(), initial)
|
|
446
|
+
|
|
447
|
+
assert.deepEqual(detectPiInstallations(true), [
|
|
448
|
+
{ kind: 'pi', path: join(dir, 'pi'), source: 'path' },
|
|
449
|
+
{ kind: 'omp', path: join(dir, 'omp'), source: 'omp' },
|
|
450
|
+
])
|
|
451
|
+
} finally {
|
|
452
|
+
process.env.HOME = saved.HOME
|
|
453
|
+
process.env.PATH = saved.PATH
|
|
454
|
+
if (saved.SHELL === undefined) delete process.env.SHELL
|
|
455
|
+
else process.env.SHELL = saved.SHELL
|
|
456
|
+
rmSync(dir, { recursive: true, force: true })
|
|
457
|
+
}
|
|
458
|
+
})
|
|
459
|
+
|
|
460
|
+
test('RpcTimeoutError is identified by class, not by message text', () => {
|
|
461
|
+
const error = new RpcTimeoutError('get_state', 30_000)
|
|
462
|
+
assert.ok(error instanceof RpcTimeoutError)
|
|
463
|
+
assert.ok(error instanceof Error)
|
|
464
|
+
assert.equal(error.name, 'RpcTimeoutError')
|
|
465
|
+
assert.equal(error.commandType, 'get_state')
|
|
466
|
+
assert.equal(error.message, 'Command get_state timed out after 30000ms')
|
|
467
|
+
})
|