failproofai 1.0.4-beta.1 → 1.0.4-beta.2
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/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/build-manifest.json +5 -5
- package/.next/standalone/.next/prerender-manifest.json +5 -5
- package/.next/standalone/.next/required-server-files.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_global-error/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_global-error.html +1 -1
- package/.next/standalone/.next/server/app/_global-error.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +6 -6
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +7 -7
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/api/audit/invite/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/invite/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route.js +4 -4
- package/.next/standalone/.next/server/app/api/audit/run/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/run/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/audit/status/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-request/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/login-verify/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/logout/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/auth/status/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/download/[project]/[session]/route_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/audit/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/audit/page/server-reference-manifest.json +37 -4
- package/.next/standalone/.next/server/app/audit/page.js +2 -2
- package/.next/standalone/.next/server/app/audit/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/audit/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +14 -14
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +15 -15
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/policies/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/policies/page/server-reference-manifest.json +14 -14
- package/.next/standalone/.next/server/app/policies/page.js +1 -1
- package/.next/standalone/.next/server/app/policies/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/policies/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page.js +3 -3
- package/.next/standalone/.next/server/app/project/[name]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page/server-reference-manifest.json +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js +2 -2
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/project/[name]/session/[sessionId]/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/projects/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/projects/page/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/server/app/projects/page.js +1 -1
- package/.next/standalone/.next/server/app/projects/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/projects/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/settings/page/build-manifest.json +2 -2
- package/.next/standalone/.next/server/app/settings/page/server-reference-manifest.json +4 -4
- package/.next/standalone/.next/server/app/settings/page.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__1zndo1i._.js → [externals]__1lh7m5d._.js} +1 -1
- package/.next/standalone/.next/server/chunks/{[externals]__0_gzk8q._.js → [externals]__1rqkg_y._.js} +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__08dchfu._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0cuho4x._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0o07qi9._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1adacul._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1le9jqc._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1p-qi2t._.js +5 -0
- package/.next/standalone/.next/server/chunks/_08w6xzm._.js +3 -0
- package/.next/standalone/.next/server/chunks/_09dz7xv._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0tovk6q._.js +1 -1
- package/.next/standalone/.next/server/chunks/_0trp3yc._.js +1 -1
- package/.next/standalone/.next/server/chunks/_1ek68ln._.js +14 -21
- package/.next/standalone/.next/server/chunks/lib_telemetry_ts_0dctyyw._.js +1 -1
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_01r25oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/node_modules_posthog-node_dist_entrypoints_index_node_mjs_09z9-p7._.js +2 -2
- package/.next/standalone/.next/server/chunks/package_json_[json]_cjs_1nxcc4v._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_0iu54mz._.js +1 -1
- package/.next/standalone/.next/server/chunks/src_hooks_fp-home_ts_09kv0bn._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__00-s7h8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__013jr2b._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__01wy8d-._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__02npjtd._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0da85px._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0ftmoxc._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/{[root-of-the-server]__0wvusu0._.js → [root-of-the-server]__0n_lxhg._.js} +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0oa1lav._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0p-5p8u._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0rgu2r3._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s740oi._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__190won8._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1ctpynv._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1p2otjt._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1qapotl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1sc84bb._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1zl_r0t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0-oij9d._.js +23 -0
- package/.next/standalone/.next/server/chunks/ssr/_0-yi74u._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_08x1r5t._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_0l2hi_d._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0oq1dh6._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/_0wso5d3._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1es2j7i._.js +48 -168
- package/.next/standalone/.next/server/chunks/ssr/{_08f0jd2._.js → _1if9ixi._.js} +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_1u8-lu2._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_next-internal_server_app_policies_page_actions_1sp2-yo.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_audit-dashboard_tsx_0p9ud47._.js +1 -69
- package/.next/standalone/.next/server/chunks/ssr/app_audit__components_rerun-button_tsx_0blihgw._.js +3 -0
- package/.next/standalone/.next/server/chunks/ssr/app_global-error_tsx_1kp6l3x._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_policies_hooks-client_tsx_19dqvpc._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/app_settings_settings-client_tsx_20lq-mq._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_13n822a._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_posthog-node_dist_entrypoints_index_node_mjs_11bnuzn._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_builtin-policies_ts_09j2ndl._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-config_ts_04t589g._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/src_hooks_fp-home_ts_0je3xkv._.js +1 -1
- package/.next/standalone/.next/server/middleware-build-manifest.js +5 -5
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +54 -21
- package/.next/standalone/.next/static/chunks/{1_bxotmf9qngs.js → 010bv1w6j171t.js} +1 -1
- package/.next/standalone/.next/static/chunks/04r6ch8uf_n8m.js +1 -0
- package/.next/standalone/.next/static/chunks/{29-iqnp9v_axt.css → 0o-hh5_turzlz.css} +1 -1
- package/.next/standalone/.next/static/chunks/0qmsunv04x4na.css +2 -0
- package/.next/standalone/.next/static/chunks/{00gv0v91mycm-.js → 0wz8yftk18ts2.js} +1 -1
- package/.next/standalone/.next/static/chunks/0zebh1n9jkfbt.js +1 -0
- package/.next/standalone/.next/static/chunks/{0qn9khv0oo9ex.js → 1pb1oztsbwcss.js} +1 -1
- package/.next/standalone/.next/static/chunks/2aquitk72k2op.js +1 -0
- package/.next/standalone/.next/static/chunks/2bi_1y0a_smt7.js +6 -0
- package/.next/standalone/.next/static/chunks/{1po3lirgk2riw.js → 2ej3b8gk5ittu.js} +1 -1
- package/.next/standalone/.next/static/chunks/{01hvwwrhvbzyh.js → 2zafgs90r_leq.js} +1 -1
- package/.next/standalone/.next/static/chunks/{1_2jsatfuthrw.js → 32spub4wqjem-.js} +1 -1
- package/.next/standalone/.next/static/chunks/{3_--3ibia6ba1.js → 3l36d73kj18zw.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2bvwsyu6x__ia.js → 3m4upvybtrexd.js} +1 -1
- package/.next/standalone/.next/static/chunks/{2k9f4tyv04809.css → 3uyhmm01g64k4.css} +1 -0
- package/.next/standalone/.next/static/chunks/{2bnf_4pgyk1rq.js → 40lpt2o2b283e.js} +1 -1
- package/.next/standalone/.next/static/chunks/{turbopack-18qf4jodtft6b.js → turbopack-3s3c-u_u_l0u9.js} +1 -1
- package/.next/standalone/.opencode/plugins/failproofai.mjs +51 -27
- package/.next/standalone/app/actions/get-leaks.ts +100 -0
- package/.next/standalone/app/audit/_components/audit-dashboard.tsx +112 -33
- package/.next/standalone/app/audit/_components/audit-poster.tsx +29 -10
- package/.next/standalone/app/audit/_components/come-back-better-section.tsx +6 -1
- package/.next/standalone/app/audit/_components/empty-state.tsx +4 -1
- package/.next/standalone/app/audit/_components/how-to-improve-section.tsx +19 -5
- package/.next/standalone/app/audit/_components/leak-section.tsx +179 -0
- package/.next/standalone/app/audit/_components/share-templates.ts +110 -44
- package/.next/standalone/app/audit/audit-styles.css +114 -1
- package/.next/standalone/app/project/[name]/page.tsx +4 -24
- package/.next/standalone/fp-cloud-cli/CHANGELOG.md +26 -3
- package/.next/standalone/fp-cloud-cli/fp_cli/_click_compat.py +31 -8
- package/.next/standalone/fp-cloud-cli/fp_cli/permissions.py +1 -0
- package/.next/standalone/fp-cloud-cli/pyproject.toml +9 -2
- package/.next/standalone/fp-cloud-cli/tests/test_click_compat.py +54 -0
- package/.next/standalone/fp-cloud-cli/uv.lock +9 -12
- package/.next/standalone/lib/auth/api-server-client.ts +28 -0
- package/.next/standalone/lib/claude-sessions.ts +101 -27
- package/.next/standalone/lib/cli-registry.ts +1 -33
- package/.next/standalone/lib/download-session.ts +0 -37
- package/.next/standalone/lib/projects.ts +3 -27
- package/.next/standalone/node_modules/@next/env/package.json +1 -1
- package/.next/standalone/node_modules/next/dist/build/swc/index.js +1 -1
- package/.next/standalone/node_modules/next/dist/compiled/next-server/pages-turbo.runtime.prod.js +1 -1
- package/.next/standalone/node_modules/next/dist/experimental/testmode/fetch.js +10 -2
- package/.next/standalone/node_modules/next/dist/lib/patch-incorrect-lockfile.js +3 -3
- package/.next/standalone/node_modules/next/dist/lib/typescript/runTypeScriptCli.js +2 -2
- package/.next/standalone/node_modules/next/dist/lib/verify-typescript-setup.js +3 -1
- package/.next/standalone/node_modules/next/dist/server/config.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-turbopack.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/dev/hot-reloader-webpack.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/image-optimizer.js +2 -2
- package/.next/standalone/node_modules/next/dist/server/lib/app-info-log.js +1 -1
- package/.next/standalone/node_modules/next/dist/server/lib/start-server.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/anonymous-meta.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/swc-load-failure.js +1 -1
- package/.next/standalone/node_modules/next/dist/telemetry/events/version.js +2 -2
- package/.next/standalone/node_modules/next/package.json +11 -11
- package/.next/standalone/package.json +15 -14
- package/.next/standalone/sdk/python/CHANGELOG.md +155 -0
- package/.next/standalone/sdk/python/README.md +8 -0
- package/.next/standalone/sdk/python/examples/evaluator_worker.py +121 -0
- package/.next/standalone/sdk/python/failproofai_sdk/_version.py +1 -1
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__init__.py +101 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/__main__.py +49 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/_sandbox_runner.py +63 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/authoring.py +404 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/client.py +299 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/protocol.py +754 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/runtime.py +936 -0
- package/.next/standalone/sdk/python/failproofai_sdk/evaluator/source.py +684 -0
- package/.next/standalone/sdk/python/tests/fixtures/evaluator_v2/README.md +28 -0
- package/.next/standalone/sdk/python/tests/fixtures/evaluator_v2/contract.json +252 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_authoring.py +124 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_client.py +253 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_example.py +35 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_http_e2e.py +636 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_main.py +47 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_protocol.py +246 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_review_fixes.py +164 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_runtime.py +1103 -0
- package/.next/standalone/sdk/python/tests/test_evaluator_source.py +430 -0
- package/.next/standalone/sdk/python/tests/test_zero_dependencies.py +17 -0
- package/.next/standalone/sdk/python/uv.lock +18 -18
- package/.next/standalone/server.js +1 -1
- package/README.md +19 -95
- package/bin/failproofai.mjs +7 -24
- package/dist/cli.mjs +19910 -25855
- package/dist/worker.mjs +4818 -6344
- package/lib/auth/api-server-client.ts +28 -0
- package/lib/claude-sessions.ts +101 -27
- package/lib/cli-registry.ts +1 -33
- package/lib/download-session.ts +0 -37
- package/lib/projects.ts +3 -27
- package/package.json +15 -14
- package/pi-extension/index.ts +42 -4
- package/scripts/changelog-open.py +115 -0
- package/src/audit/cli-adapters/index.ts +0 -24
- package/src/audit/cli.ts +134 -0
- package/src/audit/desktop-notify.ts +420 -0
- package/src/audit/harm-report.ts +101 -0
- package/src/audit/index.ts +141 -13
- package/src/audit/leak-fingerprint.ts +200 -0
- package/src/audit/leak-notice.ts +161 -0
- package/src/audit/leak-record.ts +232 -0
- package/src/audit/leak-scan.ts +292 -0
- package/src/audit/leak-store.ts +217 -0
- package/src/audit/macos-notifier.ts +310 -0
- package/src/audit/redact-example.ts +266 -14
- package/src/audit/report-harm.ts +12 -1
- package/src/audit/report.ts +6 -3
- package/src/audit/schedule-cli.ts +37 -0
- package/src/audit/scoring.ts +49 -0
- package/src/audit/types.ts +41 -0
- package/src/hooks/builtin-policies.ts +71 -8
- package/src/hooks/configure-wizard.ts +20 -0
- package/src/hooks/enforcement-capability.ts +0 -97
- package/src/hooks/fp-config.ts +71 -11
- package/src/hooks/fp-home.ts +27 -0
- package/src/hooks/handler.ts +64 -62
- package/src/hooks/harness-cli.ts +1 -3
- package/src/hooks/integrations.ts +49 -769
- package/src/hooks/normalize-cli-payload.ts +0 -126
- package/src/hooks/notice.ts +155 -0
- package/src/hooks/policy-evaluator.ts +6 -297
- package/src/hooks/resolve-transcript-path.ts +0 -10
- package/src/hooks/tool-name-canonicalize.ts +0 -64
- package/src/hooks/types.ts +2 -533
- package/src/hooks/uninstall-cli.ts +15 -0
- package/.next/standalone/.grok/hooks/failproofai.json +0 -172
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__07hor7h._.js +0 -5
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0elsuli._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0gnj_qa._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0ljuzm_._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0w23bpg._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0x5c7sh._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__0yik9_w._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1jg6s9m._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1s6qci9._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1xfm05z._.js +0 -3
- package/.next/standalone/.next/server/chunks/_0tdy_6l._.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_grok-projects_ts_1i2epl_._.js +0 -3
- package/.next/standalone/.next/server/chunks/lib_qwen-projects_ts_0wu_a8e._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0_4gcz8._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0d--wmy._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0qqrlf_._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__0s11fx1._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__16gamwq._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1bbk-si._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1c3ybxr._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__1izi7zn._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/[root-of-the-server]__21bj7uw._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_00z5uuq._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1byck5v._.js +0 -23
- package/.next/standalone/.next/server/chunks/ssr/_1ylae7o._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/_1zopuov._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_cline-projects_ts_13_hbdd._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_grok-projects_ts_0rc-d0o._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_ori-projects_ts_04tofqo._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/lib_qwen-projects_ts_0w3i9o7._.js +0 -3
- package/.next/standalone/.next/server/chunks/ssr/node_modules_html-to-image_es_index_1ao30b1.js +0 -3
- package/.next/standalone/.next/static/chunks/0hzmxwb2pvk5p.js +0 -6
- package/.next/standalone/.next/static/chunks/0j884dwnwtyrt.js +0 -1
- package/.next/standalone/.next/static/chunks/0mr9dg3bnloa1.js +0 -1
- package/.next/standalone/.next/static/chunks/0u64yey446k4f.css +0 -1
- package/.next/standalone/.next/static/chunks/3gf1jg-5m-u1t.css +0 -2
- package/.next/standalone/.next/static/chunks/3qfoeqhy5l10x.js +0 -1
- package/.next/standalone/.next/static/chunks/3ws7eljkq25wg.js +0 -69
- package/.next/standalone/.next/static/chunks/3zkg2s2vzxc3d.js +0 -1
- package/.next/standalone/.qwen/settings.json +0 -251
- package/.next/standalone/assets/logos/cline.png +0 -0
- package/.next/standalone/assets/logos/grok-dark.svg +0 -1
- package/.next/standalone/assets/logos/grok-light.svg +0 -1
- package/.next/standalone/assets/logos/ori-dark.svg +0 -1
- package/.next/standalone/assets/logos/ori-light.svg +0 -1
- package/.next/standalone/assets/logos/qwen.svg +0 -1
- package/.next/standalone/lib/cline-projects.ts +0 -155
- package/.next/standalone/lib/cline-sessions.ts +0 -268
- package/.next/standalone/lib/grok-projects.ts +0 -123
- package/.next/standalone/lib/grok-sessions.ts +0 -355
- package/.next/standalone/lib/ori-projects.ts +0 -141
- package/.next/standalone/lib/ori-sessions.ts +0 -221
- package/.next/standalone/lib/qwen-projects.ts +0 -106
- package/.next/standalone/lib/qwen-sessions.ts +0 -313
- package/lib/cline-projects.ts +0 -155
- package/lib/cline-sessions.ts +0 -268
- package/lib/grok-projects.ts +0 -123
- package/lib/grok-sessions.ts +0 -355
- package/lib/ori-projects.ts +0 -141
- package/lib/ori-sessions.ts +0 -221
- package/lib/qwen-projects.ts +0 -106
- package/lib/qwen-sessions.ts +0 -313
- package/src/audit/cli-adapters/cline.ts +0 -50
- package/src/audit/cli-adapters/grok.ts +0 -70
- package/src/audit/cli-adapters/ori.ts +0 -55
- package/src/audit/cli-adapters/qwen.ts +0 -71
- package/src/hooks/batch-expand.ts +0 -380
- package/src/hooks/batch-fanout.ts +0 -142
- package/src/hooks/risk-patterns.ts +0 -26
- /package/.next/standalone/.next/static/{qJx3mbOQV-5ElrcRb4Sp7 → aKNv4Kmv98Xpwns0Xa-C-}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{qJx3mbOQV-5ElrcRb4Sp7 → aKNv4Kmv98Xpwns0Xa-C-}/_clientMiddlewareManifest.js +0 -0
- /package/.next/standalone/.next/static/{qJx3mbOQV-5ElrcRb4Sp7 → aKNv4Kmv98Xpwns0Xa-C-}/_ssgManifest.js +0 -0
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cline session transcript loader + parser.
|
|
3
|
-
*
|
|
4
|
-
* AUDIT-ONLY (Pillar 2). Cline is the easiest transcript of any integration we
|
|
5
|
-
* support, because it already speaks CLAUDE'S OWN content-block schema. Each
|
|
6
|
-
* session is a directory under `~/.cline/data/sessions/<epochMs>_<suffix>/`
|
|
7
|
-
* holding exactly two files:
|
|
8
|
-
*
|
|
9
|
-
* <id>.json session metadata: {session_id, source, pid, started_at,
|
|
10
|
-
* ended_at, exit_code, status, interactive, provider,
|
|
11
|
-
* model, cwd, workspace_root, prompt}
|
|
12
|
-
* <id>.messages.json {version, updated_at, agent, sessionId, origin,
|
|
13
|
-
* system_prompt, messages}
|
|
14
|
-
*
|
|
15
|
-
* and `messages[].content` is an array of the very blocks lib/log-entries.ts
|
|
16
|
-
* already models: `{type:"thinking"}`, `{type:"text"}`,
|
|
17
|
-
* `{type:"tool_use", id, name, input}`, `{type:"tool_result", tool_use_id,
|
|
18
|
-
* name, content}`. So there is no dialect to translate — only tool_result
|
|
19
|
-
* pairing, which `clineMessagesToLogEntries` does by `tool_use_id`.
|
|
20
|
-
*
|
|
21
|
-
* Two things that are NOT free, recorded so nobody assumes otherwise:
|
|
22
|
-
* • Cline stores NO per-message timestamp. Every entry in a session therefore
|
|
23
|
-
* carries the session's own time, so ordering within a session is array
|
|
24
|
-
* order and per-message timing is unrecoverable. (Same limitation as ori.)
|
|
25
|
-
* • Tool RESULTS arrive in `role:"user"` messages, Claude-style. A user
|
|
26
|
-
* message whose content is entirely tool_result blocks is NOT user prose
|
|
27
|
-
* and must not be emitted as one, or every tool call produces a phantom
|
|
28
|
-
* user turn in the audit.
|
|
29
|
-
*
|
|
30
|
-
* Home override: `CLINE_HOME` (the dir containing `data/sessions`, used by
|
|
31
|
-
* tests); otherwise `$CLINE_DIR` — which cline itself honours — then `~/.cline`.
|
|
32
|
-
*/
|
|
33
|
-
import { readFile, readdir } from "node:fs/promises";
|
|
34
|
-
import { homedir } from "node:os";
|
|
35
|
-
import { join } from "node:path";
|
|
36
|
-
import { runtimeCache } from "./runtime-cache";
|
|
37
|
-
import {
|
|
38
|
-
baseEntry,
|
|
39
|
-
formatTimestamp,
|
|
40
|
-
type LogEntry,
|
|
41
|
-
type UserEntry,
|
|
42
|
-
type AssistantEntry,
|
|
43
|
-
type ContentBlock,
|
|
44
|
-
type ToolUseBlock,
|
|
45
|
-
type LogSource,
|
|
46
|
-
} from "./log-entries";
|
|
47
|
-
import { formatDuration } from "./format-duration";
|
|
48
|
-
|
|
49
|
-
/** Absolute path to cline's home (override with CLINE_HOME, then CLINE_DIR). */
|
|
50
|
-
export function clineHome(): string {
|
|
51
|
-
return process.env.CLINE_HOME || process.env.CLINE_DIR || join(homedir(), ".cline");
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/** Absolute path to the directory holding one folder per session. */
|
|
55
|
-
export function clineSessionsDir(): string {
|
|
56
|
-
return join(clineHome(), "data", "sessions");
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/** Session directories are `<epochMs>_<suffix>`, e.g. `1788253271772_bn188`. */
|
|
60
|
-
export const CLINE_SESSION_DIR_RE = /^(\d{10,})_([A-Za-z0-9]+)$/;
|
|
61
|
-
|
|
62
|
-
export function clineTimestampToMs(value: string | null | undefined): number {
|
|
63
|
-
if (!value) return 0;
|
|
64
|
-
const ms = Date.parse(value);
|
|
65
|
-
return Number.isNaN(ms) ? 0 : ms;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export interface ClineSessionMeta {
|
|
69
|
-
session_id?: string;
|
|
70
|
-
status?: string;
|
|
71
|
-
provider?: string;
|
|
72
|
-
model?: string;
|
|
73
|
-
cwd?: string;
|
|
74
|
-
workspace_root?: string;
|
|
75
|
-
prompt?: string;
|
|
76
|
-
started_at?: string;
|
|
77
|
-
ended_at?: string;
|
|
78
|
-
source?: string;
|
|
79
|
-
interactive?: boolean;
|
|
80
|
-
exit_code?: number;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
interface ClineBlock {
|
|
84
|
-
type?: string;
|
|
85
|
-
text?: string;
|
|
86
|
-
thinking?: string;
|
|
87
|
-
id?: string;
|
|
88
|
-
name?: string;
|
|
89
|
-
input?: Record<string, unknown>;
|
|
90
|
-
tool_use_id?: string;
|
|
91
|
-
content?: unknown;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
interface ClineMessage {
|
|
95
|
-
role?: string;
|
|
96
|
-
content?: string | ClineBlock[];
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
/** Flatten a tool_result's `content` into display text. Cline uses an array of
|
|
100
|
-
* `{query, result}`-ish objects or plain text blocks depending on the tool, so
|
|
101
|
-
* fall back to JSON rather than dropping the result entirely. */
|
|
102
|
-
function toolResultText(content: unknown): string {
|
|
103
|
-
if (typeof content === "string") return content;
|
|
104
|
-
if (Array.isArray(content)) {
|
|
105
|
-
const parts = content.map((c) => {
|
|
106
|
-
if (typeof c === "string") return c;
|
|
107
|
-
if (c && typeof c === "object") {
|
|
108
|
-
const o = c as Record<string, unknown>;
|
|
109
|
-
if (typeof o.text === "string") return o.text;
|
|
110
|
-
if (typeof o.result === "string") return o.result;
|
|
111
|
-
return JSON.stringify(o);
|
|
112
|
-
}
|
|
113
|
-
return "";
|
|
114
|
-
});
|
|
115
|
-
return parts.filter((p) => p.length > 0).join("\n");
|
|
116
|
-
}
|
|
117
|
-
if (content && typeof content === "object") return JSON.stringify(content);
|
|
118
|
-
return "";
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* Parse cline's message array into the shared LogEntry[] shape.
|
|
123
|
-
*
|
|
124
|
-
* PURE — takes already-parsed JSON, so tests need no fixture directory.
|
|
125
|
-
*/
|
|
126
|
-
export function clineMessagesToLogEntries(
|
|
127
|
-
messages: ClineMessage[],
|
|
128
|
-
sessionId: string,
|
|
129
|
-
timestampMs: number,
|
|
130
|
-
source: LogSource = "session",
|
|
131
|
-
): LogEntry[] {
|
|
132
|
-
const date = new Date(timestampMs);
|
|
133
|
-
const timestamp = date.toISOString();
|
|
134
|
-
const entries: LogEntry[] = [];
|
|
135
|
-
// tool_use id → the block awaiting its result, so a later user-role
|
|
136
|
-
// tool_result attaches onto the assistant turn that made the call.
|
|
137
|
-
const pending = new Map<string, ToolUseBlock>();
|
|
138
|
-
|
|
139
|
-
messages.forEach((msg, i) => {
|
|
140
|
-
const role = msg.role;
|
|
141
|
-
const raw = { uuid: `${sessionId}:${i}`, parentUuid: null } as Record<string, unknown>;
|
|
142
|
-
const base = baseEntry(raw, timestamp, date, source);
|
|
143
|
-
const blocks: ClineBlock[] = Array.isArray(msg.content) ? msg.content : [];
|
|
144
|
-
|
|
145
|
-
if (role === "user") {
|
|
146
|
-
// Attach any tool results this message carries…
|
|
147
|
-
let attached = 0;
|
|
148
|
-
for (const b of blocks) {
|
|
149
|
-
if (b.type !== "tool_result" || typeof b.tool_use_id !== "string") continue;
|
|
150
|
-
attached++;
|
|
151
|
-
const target = pending.get(b.tool_use_id);
|
|
152
|
-
if (!target) continue;
|
|
153
|
-
// No per-message timestamp exists, so duration is unknowable — 0 rather
|
|
154
|
-
// than a fabricated span.
|
|
155
|
-
target.result = {
|
|
156
|
-
timestamp,
|
|
157
|
-
timestampFormatted: formatTimestamp(date),
|
|
158
|
-
content: toolResultText(b.content),
|
|
159
|
-
durationMs: 0,
|
|
160
|
-
durationFormatted: formatDuration(0),
|
|
161
|
-
};
|
|
162
|
-
pending.delete(b.tool_use_id);
|
|
163
|
-
}
|
|
164
|
-
// …and only emit a user turn if there was real prose. A message that is
|
|
165
|
-
// nothing but tool results is the tool-result carrier, not a user turn.
|
|
166
|
-
const text =
|
|
167
|
-
typeof msg.content === "string"
|
|
168
|
-
? msg.content
|
|
169
|
-
: blocks
|
|
170
|
-
.filter((b) => b.type === "text" && typeof b.text === "string")
|
|
171
|
-
.map((b) => b.text as string)
|
|
172
|
-
.join("");
|
|
173
|
-
if (text.trim().length > 0) {
|
|
174
|
-
entries.push({ ...base, type: "user", message: { role: "user", content: text } } as UserEntry);
|
|
175
|
-
} else if (attached === 0 && typeof msg.content === "string") {
|
|
176
|
-
entries.push({ ...base, type: "user", message: { role: "user", content: msg.content } } as UserEntry);
|
|
177
|
-
}
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
if (role === "assistant") {
|
|
182
|
-
const out: ContentBlock[] = [];
|
|
183
|
-
for (const b of blocks) {
|
|
184
|
-
if (b.type === "thinking" && typeof b.thinking === "string") {
|
|
185
|
-
out.push({ type: "thinking", thinking: b.thinking });
|
|
186
|
-
} else if (b.type === "text" && typeof b.text === "string") {
|
|
187
|
-
out.push({ type: "text", text: b.text });
|
|
188
|
-
} else if (b.type === "tool_use" && typeof b.id === "string") {
|
|
189
|
-
const block: ToolUseBlock = {
|
|
190
|
-
type: "tool_use",
|
|
191
|
-
id: b.id,
|
|
192
|
-
name: b.name ?? "",
|
|
193
|
-
input: b.input ?? {},
|
|
194
|
-
};
|
|
195
|
-
pending.set(b.id, block);
|
|
196
|
-
out.push(block);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
if (out.length > 0) {
|
|
200
|
-
entries.push({
|
|
201
|
-
...base,
|
|
202
|
-
type: "assistant",
|
|
203
|
-
message: { role: "assistant", content: out },
|
|
204
|
-
} as AssistantEntry);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
});
|
|
208
|
-
|
|
209
|
-
return entries;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export interface ClineSessionLog {
|
|
213
|
-
entries: LogEntry[];
|
|
214
|
-
cwd?: string;
|
|
215
|
-
meta?: ClineSessionMeta;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
/** Read a session's metadata sidecar. Returns undefined when absent/unreadable. */
|
|
219
|
-
export async function readClineSessionMeta(
|
|
220
|
-
dir: string,
|
|
221
|
-
sessionId: string,
|
|
222
|
-
): Promise<ClineSessionMeta | undefined> {
|
|
223
|
-
try {
|
|
224
|
-
return JSON.parse(await readFile(join(dir, `${sessionId}.json`), "utf8")) as ClineSessionMeta;
|
|
225
|
-
} catch {
|
|
226
|
-
return undefined;
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/** Load and parse one cline session. Returns null when absent or unreadable. */
|
|
231
|
-
export async function getClineSessionLog(sessionId: string): Promise<ClineSessionLog | null> {
|
|
232
|
-
const root = clineSessionsDir();
|
|
233
|
-
let dirs: string[];
|
|
234
|
-
try {
|
|
235
|
-
dirs = await readdir(root);
|
|
236
|
-
} catch {
|
|
237
|
-
return null;
|
|
238
|
-
}
|
|
239
|
-
// The directory is `<epochMs>_<suffix>` and the files inside are named for
|
|
240
|
-
// the FULL directory name, which is also the session id.
|
|
241
|
-
const dirName = dirs.find((d) => d === sessionId);
|
|
242
|
-
if (!dirName) return null;
|
|
243
|
-
const dir = join(root, dirName);
|
|
244
|
-
|
|
245
|
-
let parsed: { messages?: ClineMessage[]; updated_at?: string };
|
|
246
|
-
try {
|
|
247
|
-
parsed = JSON.parse(await readFile(join(dir, `${sessionId}.messages.json`), "utf8")) as {
|
|
248
|
-
messages?: ClineMessage[];
|
|
249
|
-
updated_at?: string;
|
|
250
|
-
};
|
|
251
|
-
} catch {
|
|
252
|
-
return null;
|
|
253
|
-
}
|
|
254
|
-
const meta = await readClineSessionMeta(dir, sessionId);
|
|
255
|
-
const ms =
|
|
256
|
-
clineTimestampToMs(meta?.started_at) ||
|
|
257
|
-
clineTimestampToMs(parsed.updated_at) ||
|
|
258
|
-
Number(sessionId.split("_")[0]) ||
|
|
259
|
-
0;
|
|
260
|
-
|
|
261
|
-
return {
|
|
262
|
-
entries: clineMessagesToLogEntries(parsed.messages ?? [], sessionId, ms),
|
|
263
|
-
cwd: meta?.cwd ?? meta?.workspace_root,
|
|
264
|
-
meta,
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
export const getCachedClineSessionLog = runtimeCache(getClineSessionLog, 2);
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* grok CLI project discovery.
|
|
3
|
-
*
|
|
4
|
-
* grok stores transcripts at
|
|
5
|
-
* `~/.grok/sessions/<percent-encoded-cwd>/<uuid>/chat_history.jsonl`.
|
|
6
|
-
*
|
|
7
|
-
* NOTE the folder encoding differs from every other JSONL store we read: grok
|
|
8
|
-
* percent-encodes the cwd (`%2Fhome%2Fuser%2Frepo`) where Claude, Factory and
|
|
9
|
-
* Qwen dash-encode it (`-home-user-repo`).
|
|
10
|
-
*
|
|
11
|
-
* So the on-disk folder name is deliberately NOT used as the project `name`.
|
|
12
|
-
* Two reasons, and the first is a hard bug: `name` becomes the URL slug for
|
|
13
|
-
* `/project/[name]`, and a percent-encoded name re-encodes to `%252F…` in the
|
|
14
|
-
* link, which the route cannot resolve — every grok project 404'd. Second, a
|
|
15
|
-
* name no other CLI can produce merges with nothing, so a cwd driven by both
|
|
16
|
-
* grok and Claude showed up as two unrelated rows.
|
|
17
|
-
*
|
|
18
|
-
* Re-encoding the decoded cwd with `encodeFolderName` fixes both at once: the
|
|
19
|
-
* slug is URL-safe, and it is byte-identical to the one Claude/Factory/Qwen
|
|
20
|
-
* derive for the same cwd, so those rows merge as they should.
|
|
21
|
-
*/
|
|
22
|
-
import { encodeFolderName, decodeFolderName } from "./paths";
|
|
23
|
-
import { listGrokTranscripts, getGrokSessionLog } from "./grok-sessions";
|
|
24
|
-
import type { ProjectFolder, SessionFile } from "./projects";
|
|
25
|
-
import { runtimeCache } from "./runtime-cache";
|
|
26
|
-
import { formatDate } from "./format-date";
|
|
27
|
-
import { logWarn } from "./logger";
|
|
28
|
-
|
|
29
|
-
/** Returns one ProjectFolder per percent-encoded cwd folder discovered under
|
|
30
|
-
* ~/.grok/sessions/. */
|
|
31
|
-
export async function getGrokProjects(): Promise<ProjectFolder[]> {
|
|
32
|
-
let transcripts;
|
|
33
|
-
try {
|
|
34
|
-
transcripts = listGrokTranscripts();
|
|
35
|
-
} catch (error) {
|
|
36
|
-
logWarn("Failed to scan grok sessions:", error);
|
|
37
|
-
return [];
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
const byName = new Map<string, { latest: number; cwd: string; name: string }>();
|
|
41
|
-
for (const t of transcripts) {
|
|
42
|
-
// The URL slug is derived from the real cwd, never from grok's
|
|
43
|
-
// percent-encoded folder — see the module header.
|
|
44
|
-
const name = encodeFolderName(t.cwd);
|
|
45
|
-
const existing = byName.get(name);
|
|
46
|
-
if (!existing || t.mtimeMs > existing.latest) {
|
|
47
|
-
byName.set(name, { latest: t.mtimeMs, cwd: t.cwd, name });
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const folders: ProjectFolder[] = [];
|
|
52
|
-
for (const { name, cwd, latest } of byName.values()) {
|
|
53
|
-
const lastModified = new Date(latest);
|
|
54
|
-
folders.push({
|
|
55
|
-
name,
|
|
56
|
-
path: cwd,
|
|
57
|
-
isDirectory: true,
|
|
58
|
-
lastModified,
|
|
59
|
-
lastModifiedFormatted: formatDate(lastModified),
|
|
60
|
-
cli: ["grok"],
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
folders.sort((a, b) => b.lastModified.getTime() - a.lastModified.getTime());
|
|
64
|
-
return folders;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export interface GrokProjectByName {
|
|
68
|
-
/** Canonical cwd, taken from a session's summary.json `info.cwd`. Null when
|
|
69
|
-
* no session could be read. */
|
|
70
|
-
cwd: string | null;
|
|
71
|
-
sessions: SessionFile[];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Look up grok sessions for a project URL slug (the percent-encoded cwd folder
|
|
76
|
-
* name). The canonical cwd comes from summary.json; the percent-decode is the
|
|
77
|
-
* fallback.
|
|
78
|
-
*/
|
|
79
|
-
export async function getGrokSessionsByEncodedName(name: string): Promise<GrokProjectByName> {
|
|
80
|
-
let transcripts;
|
|
81
|
-
try {
|
|
82
|
-
// Match on the derived slug, since that is what the link carried.
|
|
83
|
-
transcripts = listGrokTranscripts().filter((t) => encodeFolderName(t.cwd) === name);
|
|
84
|
-
} catch (error) {
|
|
85
|
-
logWarn("Failed to scan grok sessions:", error);
|
|
86
|
-
return { cwd: null, sessions: [] };
|
|
87
|
-
}
|
|
88
|
-
if (transcripts.length === 0) return { cwd: null, sessions: [] };
|
|
89
|
-
|
|
90
|
-
const sorted = [...transcripts].sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
91
|
-
|
|
92
|
-
let cwd: string | null = sorted[0].cwd || null;
|
|
93
|
-
if (!cwd) {
|
|
94
|
-
try {
|
|
95
|
-
const log = await getGrokSessionLog(sorted[0].sessionId);
|
|
96
|
-
cwd = log?.cwd ?? null;
|
|
97
|
-
} catch {
|
|
98
|
-
// best-effort — fall back to the decode below
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// `name` is a dash-encoded cwd here, so the shared decoder is the right one.
|
|
102
|
-
if (!cwd) cwd = decodeFolderName(name);
|
|
103
|
-
|
|
104
|
-
const sessions: SessionFile[] = sorted.map((t) => {
|
|
105
|
-
const lastModified = new Date(t.mtimeMs);
|
|
106
|
-
return {
|
|
107
|
-
name: t.sessionId,
|
|
108
|
-
path: t.transcriptPath,
|
|
109
|
-
lastModified,
|
|
110
|
-
lastModifiedFormatted: formatDate(lastModified),
|
|
111
|
-
sessionId: t.sessionId,
|
|
112
|
-
cli: "grok" as const,
|
|
113
|
-
};
|
|
114
|
-
});
|
|
115
|
-
return { cwd, sessions };
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export const getCachedGrokProjects = runtimeCache(getGrokProjects, 30);
|
|
119
|
-
export const getCachedGrokSessionsByEncodedName = runtimeCache(
|
|
120
|
-
(name: string) => getGrokSessionsByEncodedName(name),
|
|
121
|
-
30,
|
|
122
|
-
{ maxSize: 50 },
|
|
123
|
-
);
|