@witty-ai/skill-insight 0.5.0-beta → 0.6.0-beta
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/.env.example +5 -0
- package/.next/standalone/.next/BUILD_ID +1 -1
- package/.next/standalone/.next/app-path-routes-manifest.json +4 -0
- package/.next/standalone/.next/build-manifest.json +2 -2
- package/.next/standalone/.next/prerender-manifest.json +3 -3
- package/.next/standalone/.next/routes-manifest.json +24 -0
- package/.next/standalone/.next/server/app/_global-error.html +2 -2
- package/.next/standalone/.next/server/app/_global-error.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.html +1 -1
- package/.next/standalone/.next/server/app/_not-found.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/api/config/route.js +3 -3
- package/.next/standalone/.next/server/app/api/config/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/data/route.js +3 -3
- package/.next/standalone/.next/server/app/api/data/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/otel/v1/logs/route.js +3 -3
- package/.next/standalone/.next/server/app/api/otel/v1/logs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/otel/v1/traces/route.js +1 -1
- package/.next/standalone/.next/server/app/api/otel/v1/traces/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/proxy/[taskId]/end/route.js +4 -4
- package/.next/standalone/.next/server/app/api/proxy/[taskId]/end/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/rejudge/route.js +3 -3
- package/.next/standalone/.next/server/app/api/rejudge/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/session/route.js +1 -1
- package/.next/standalone/.next/server/app/api/session/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/setup/opencode-commands/si-optimizer/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-commands/si-optimizer/route/build-manifest.json +11 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-commands/si-optimizer/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-commands/si-optimizer/route.js +6 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-commands/si-optimizer/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-commands/si-optimizer/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-commands/si-optimizer/route_client-reference-manifest.js +2 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-tui/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-tui/route/build-manifest.json +11 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-tui/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-tui/route.js +6 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-tui/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-tui/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/setup/opencode-tui/route_client-reference-manifest.js +2 -0
- package/.next/standalone/.next/server/app/api/skills/[id]/versions/[version]/download/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/skills/[id]/versions/[version]/route.js +3 -2
- package/.next/standalone/.next/server/app/api/skills/[id]/versions/[version]/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/skills/automation/import/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/skills/logs/route.js +2 -2
- package/.next/standalone/.next/server/app/api/skills/logs/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/skills/route.js +3 -2
- package/.next/standalone/.next/server/app/api/skills/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route/build-manifest.json +11 -0
- package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route.js +8 -0
- package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/skills/sync-enterprise/route_client-reference-manifest.js +2 -0
- package/.next/standalone/.next/server/app/api/task-stats/route/app-paths-manifest.json +3 -0
- package/.next/standalone/.next/server/app/api/task-stats/route/build-manifest.json +11 -0
- package/.next/standalone/.next/server/app/api/task-stats/route/server-reference-manifest.json +4 -0
- package/.next/standalone/.next/server/app/api/task-stats/route.js +11 -0
- package/.next/standalone/.next/server/app/api/task-stats/route.js.map +5 -0
- package/.next/standalone/.next/server/app/api/task-stats/route.js.nft.json +1 -0
- package/.next/standalone/.next/server/app/api/task-stats/route_client-reference-manifest.js +2 -0
- package/.next/standalone/.next/server/app/api/upload/route.js +1 -1
- package/.next/standalone/.next/server/app/api/upload/route.js.nft.json +1 -1
- package/.next/standalone/.next/server/app/details/page/react-loadable-manifest.json +2 -2
- package/.next/standalone/.next/server/app/details/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/details.html +1 -1
- package/.next/standalone/.next/server/app/details.rsc +2 -2
- package/.next/standalone/.next/server/app/details.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/details.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/details.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/details.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/details.segments/details/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/details.segments/details.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.html +1 -1
- package/.next/standalone/.next/server/app/index.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_full.segment.rsc +2 -2
- package/.next/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.html +1 -1
- package/.next/standalone/.next/server/app/login.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/login.segments/login.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/page_client-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/app/skills.html +1 -1
- package/.next/standalone/.next/server/app/skills.rsc +1 -1
- package/.next/standalone/.next/server/app/skills.segments/_full.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/skills.segments/_head.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/skills.segments/_index.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/skills.segments/_tree.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/skills.segments/skills/__PAGE__.segment.rsc +1 -1
- package/.next/standalone/.next/server/app/skills.segments/skills.segment.rsc +1 -1
- package/.next/standalone/.next/server/app-paths-manifest.json +4 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__15dbd1f2._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__1ce5e3b8._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__53775b48._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__6923eecf._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__6d8053e2._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__8402dfd1._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__863cf6de._.js +1 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__89404730._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__aa5c8858._.js +2 -2
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__c20da96a._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__ddf63a21._.js +3 -0
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__f9e66e02._.js +3 -0
- package/.next/standalone/.next/server/chunks/_3e8b4d8c._.js +1 -1
- package/.next/standalone/.next/server/chunks/_41a98bd8._.js +1 -1
- package/.next/standalone/.next/server/chunks/_4c806e26._.js +3 -0
- package/.next/standalone/.next/server/chunks/_cd3d20ca._.js +1 -1
- package/.next/standalone/.next/server/chunks/_ddffef3e._.js +1 -1
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_setup_opencode-tui_route_actions_fc8ae29f.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_skills_sync-enterprise_route_actions_0ca45899.js +3 -0
- package/.next/standalone/.next/server/chunks/_next-internal_server_app_api_task-stats_route_actions_983505cd.js +3 -0
- package/.next/standalone/.next/server/chunks/ce889_server_app_api_setup_opencode-commands_si-optimizer_route_actions_fcde30ef.js +3 -0
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_c33286ed.js +47 -4
- package/.next/standalone/.next/server/chunks/node_modules_next_dist_esm_build_templates_app-route_f42faeee.js +1 -1
- package/.next/standalone/.next/server/chunks/src_98433cb8._.js +175 -0
- package/.next/standalone/.next/server/chunks/src_lib_12408140._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/_c8c8c083._.js +2 -2
- package/.next/standalone/.next/server/chunks/ssr/_fd46f439._.js +2 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_dagre-d3-es_src_dagre_index_3582f3d0.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_lodash-es_a1341fea._.js +1 -1
- package/.next/standalone/.next/server/chunks/ssr/node_modules_lodash-es_e1de6ed8._.js +1 -1
- package/.next/standalone/.next/server/pages/404.html +1 -1
- package/.next/standalone/.next/server/pages/500.html +2 -2
- package/.next/standalone/.next/server/server-reference-manifest.js +1 -1
- package/.next/standalone/.next/server/server-reference-manifest.json +1 -1
- package/.next/standalone/.next/static/chunks/{01eddf501c574a44.js → 4ee8dc41c9f15b7b.js} +1 -1
- package/.next/standalone/.next/static/chunks/{737b8cff3c6a4e30.js → 9445b2873a413c58.js} +1 -1
- package/.next/standalone/.next/static/chunks/94dfb15df65ef720.js +2 -0
- package/.next/standalone/.next/static/chunks/9d1c5c3494fa53de.js +109 -0
- package/.next/standalone/.next/static/chunks/{e09d9ee16fe90255.js → cd0fde15dc0dfcca.js} +1 -1
- package/.next/standalone/.next/static/chunks/{ff6357067630b168.js → e13d208072a48316.js} +1 -1
- package/.next/standalone/node_modules/.prisma/client/edge.js +6 -3
- package/.next/standalone/node_modules/.prisma/client/index-browser.js +3 -0
- package/.next/standalone/node_modules/.prisma/client/index.js +6 -3
- package/.next/standalone/node_modules/.prisma/client/package.json +1 -1
- package/.next/standalone/node_modules/.prisma/client/schema.prisma +12 -9
- package/.next/standalone/node_modules/.prisma/client/wasm.js +3 -0
- package/.next/standalone/node_modules/adm-zip/util/constants.js +142 -0
- package/.next/standalone/node_modules/adm-zip/util/decoder.js +5 -0
- package/.next/standalone/node_modules/adm-zip/util/errors.js +63 -0
- package/.next/standalone/node_modules/adm-zip/util/fattr.js +76 -0
- package/.next/standalone/node_modules/adm-zip/util/index.js +5 -0
- package/.next/standalone/node_modules/adm-zip/util/utils.js +339 -0
- package/.next/standalone/package.json +6 -2
- package/.next/standalone/prisma/schema.prisma +3 -0
- package/.next/standalone/scripts/opencode_plugin.ts +23 -5
- package/.next/standalone/scripts/opencode_tui_plugin.tsx +308 -0
- package/.next/standalone/scripts/si-optimizer.md +5 -0
- package/.next/static/chunks/{01eddf501c574a44.js → 4ee8dc41c9f15b7b.js} +1 -1
- package/.next/static/chunks/{737b8cff3c6a4e30.js → 9445b2873a413c58.js} +1 -1
- package/.next/static/chunks/94dfb15df65ef720.js +2 -0
- package/.next/static/chunks/9d1c5c3494fa53de.js +109 -0
- package/.next/static/chunks/{e09d9ee16fe90255.js → cd0fde15dc0dfcca.js} +1 -1
- package/.next/static/chunks/{ff6357067630b168.js → e13d208072a48316.js} +1 -1
- package/package.json +6 -2
- package/prisma/schema.prisma +3 -0
- package/scripts/activate_telemetry.sh +44 -1
- package/scripts/opencode_plugin.ts +23 -5
- package/scripts/opencode_tui_plugin.tsx +308 -0
- package/scripts/si-optimizer.md +5 -0
- package/scripts/utils.js +0 -1
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__e2f0baee._.js +0 -3
- package/.next/standalone/.next/server/chunks/[root-of-the-server]__fc05579d._.js +0 -3
- package/.next/standalone/.next/server/chunks/src_497d2ad2._.js +0 -175
- package/.next/standalone/.next/static/chunks/4071dbec4cf7e72e.js +0 -109
- package/.next/standalone/.next/static/chunks/a87b5e84254095a5.js +0 -1
- package/.next/standalone/LICENSE +0 -21
- package/.next/standalone/bin/cli.js +0 -106
- package/.next/standalone/custom-models.example.json +0 -21
- package/.next/standalone/eslint.config.mjs +0 -18
- package/.next/standalone/features/feature-skill-used-jump-link/design/2026-03-18-skill-used-jump-link-design.md +0 -126
- package/.next/standalone/features/feature-skill-used-jump-link/feature.json +0 -32
- package/.next/standalone/features/feature-skill-used-jump-link/issue.md +0 -32
- package/.next/standalone/features/feature-skill-used-jump-link/plans/2026-03-18-skill-used-jump-link.md +0 -528
- package/.next/standalone/next.config.ts +0 -41
- package/.next/standalone/scripts/activate_telemetry.sh +0 -159
- package/.next/standalone/scripts/create_migration_package.sh +0 -124
- package/.next/standalone/scripts/fix_models.js +0 -66
- package/.next/standalone/scripts/init_opengauss.py +0 -284
- package/.next/standalone/scripts/install.js +0 -273
- package/.next/standalone/scripts/logs.js +0 -38
- package/.next/standalone/scripts/otel_data/logs.jsonl +0 -12
- package/.next/standalone/scripts/otel_data/metrics.jsonl +0 -21
- package/.next/standalone/scripts/otel_data/raw_requests.jsonl +0 -8
- package/.next/standalone/scripts/otel_data/raw_requests.jsonl.bak +0 -6
- package/.next/standalone/scripts/otel_receiver.py +0 -580
- package/.next/standalone/scripts/postinstall.js +0 -192
- package/.next/standalone/scripts/publish-npm.js +0 -401
- package/.next/standalone/scripts/restart.js +0 -26
- package/.next/standalone/scripts/restart.sh +0 -138
- package/.next/standalone/scripts/restart_dev.sh +0 -132
- package/.next/standalone/scripts/start.js +0 -291
- package/.next/standalone/scripts/status.js +0 -41
- package/.next/standalone/scripts/stop.js +0 -90
- package/.next/standalone/scripts/sync_skills.js +0 -216
- package/.next/standalone/scripts/utils.js +0 -235
- package/.next/standalone/tests/setup_skill_optimizer.sh +0 -118
- package/.next/standalone/tsconfig.json +0 -34
- package/.next/static/chunks/4071dbec4cf7e72e.js +0 -109
- package/.next/static/chunks/a87b5e84254095a5.js +0 -1
- /package/.next/standalone/.next/static/{H581Rok68JtPV4bAVVH3l → 0uvhCJooDO_gMNlKOaHwB}/_buildManifest.js +0 -0
- /package/.next/standalone/.next/static/{H581Rok68JtPV4bAVVH3l → 0uvhCJooDO_gMNlKOaHwB}/_clientMiddlewareManifest.json +0 -0
- /package/.next/standalone/.next/static/{H581Rok68JtPV4bAVVH3l → 0uvhCJooDO_gMNlKOaHwB}/_ssgManifest.js +0 -0
- /package/.next/static/{H581Rok68JtPV4bAVVH3l → 0uvhCJooDO_gMNlKOaHwB}/_buildManifest.js +0 -0
- /package/.next/static/{H581Rok68JtPV4bAVVH3l → 0uvhCJooDO_gMNlKOaHwB}/_clientMiddlewareManifest.json +0 -0
- /package/.next/static/{H581Rok68JtPV4bAVVH3l → 0uvhCJooDO_gMNlKOaHwB}/_ssgManifest.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@witty-ai/skill-insight",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0-beta",
|
|
4
4
|
"description": "Agent Skill 评估与观测平台 — 量化评估 Skills 在 Agent 上的实际运行效果",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"private": false,
|
|
@@ -21,12 +21,14 @@
|
|
|
21
21
|
"dev": "next dev",
|
|
22
22
|
"build": "next build",
|
|
23
23
|
"start": "next start",
|
|
24
|
-
"lint": "eslint"
|
|
24
|
+
"lint": "eslint",
|
|
25
|
+
"test": "node --import tsx --test \"test/**/*.test.ts\""
|
|
25
26
|
},
|
|
26
27
|
"dependencies": {
|
|
27
28
|
"@prisma/client": "5.22.0",
|
|
28
29
|
"@types/archiver": "^7.0.0",
|
|
29
30
|
"@types/uuid": "^11.0.0",
|
|
31
|
+
"adm-zip": "^0.5.10",
|
|
30
32
|
"archiver": "7.0.1",
|
|
31
33
|
"chokidar": "^5.0.0",
|
|
32
34
|
"dotenv": "^17.3.1",
|
|
@@ -49,12 +51,14 @@
|
|
|
49
51
|
"xlsx": "^0.18.5"
|
|
50
52
|
},
|
|
51
53
|
"devDependencies": {
|
|
54
|
+
"@types/adm-zip": "^0.5.8",
|
|
52
55
|
"@types/node": "^20",
|
|
53
56
|
"@types/pg": "^8.18.0",
|
|
54
57
|
"@types/react": "^19",
|
|
55
58
|
"@types/react-dom": "^19",
|
|
56
59
|
"eslint": "^9",
|
|
57
60
|
"eslint-config-next": "16.1.4",
|
|
61
|
+
"tsx": "^4.20.5",
|
|
58
62
|
"typescript": "^5"
|
|
59
63
|
}
|
|
60
64
|
}
|
package/prisma/schema.prisma
CHANGED
|
@@ -34,6 +34,8 @@ model SkillVersion {
|
|
|
34
34
|
id String @id @default(cuid())
|
|
35
35
|
skillId String
|
|
36
36
|
version Int
|
|
37
|
+
semanticVersion String? // 语义化版本号,用于企业同步
|
|
38
|
+
enterpriseSkillId Int? // 企业skill的id,用于删除同步
|
|
37
39
|
content String
|
|
38
40
|
assetPath String?
|
|
39
41
|
files String?
|
|
@@ -68,6 +70,7 @@ model Execution {
|
|
|
68
70
|
cacheReadInputTokens Int?
|
|
69
71
|
cacheCreationInputTokens Int?
|
|
70
72
|
maxSingleCallTokens Int?
|
|
73
|
+
reasoningTokens Int?
|
|
71
74
|
timestamp DateTime @default(now())
|
|
72
75
|
model String?
|
|
73
76
|
finalResult String?
|
|
@@ -30,14 +30,49 @@ fi
|
|
|
30
30
|
# --- 2. Setup OpenCode Plugin (Priority) ---
|
|
31
31
|
OPENCODE_PLUGIN_SRC="$SCRIPTS_DIR/opencode_plugin.ts"
|
|
32
32
|
OPENCODE_PLUGIN_DEST="$HOME/.opencode/plugins/Witty-Skill-Insight.ts"
|
|
33
|
+
OPENCODE_TUI_PLUGIN_SRC="$SCRIPTS_DIR/opencode_tui_plugin.tsx"
|
|
34
|
+
OPENCODE_TUI_PLUGIN_DEST="$HOME/.opencode/plugins/Witty-Skill-Insight.tui.tsx"
|
|
35
|
+
OPENCODE_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/opencode"
|
|
36
|
+
OPENCODE_CONFIG_PLUGIN_DIR="$OPENCODE_CONFIG_DIR/plugins"
|
|
33
37
|
|
|
34
38
|
if [ -f "$OPENCODE_PLUGIN_SRC" ]; then
|
|
35
39
|
echo "🛠️ Syncing OpenCode Plugin..."
|
|
36
40
|
|
|
37
41
|
# Create plugin directory
|
|
38
42
|
mkdir -p "$HOME/.opencode/plugins"
|
|
43
|
+
mkdir -p "$OPENCODE_CONFIG_PLUGIN_DIR"
|
|
39
44
|
cp "$OPENCODE_PLUGIN_SRC" "$OPENCODE_PLUGIN_DEST"
|
|
45
|
+
cp "$OPENCODE_PLUGIN_SRC" "$OPENCODE_CONFIG_PLUGIN_DIR/Witty-Skill-Insight.ts"
|
|
40
46
|
echo "✅ OpenCode Plugin installed to $OPENCODE_PLUGIN_DEST"
|
|
47
|
+
|
|
48
|
+
if [ -f "$OPENCODE_TUI_PLUGIN_SRC" ]; then
|
|
49
|
+
cp "$OPENCODE_TUI_PLUGIN_SRC" "$OPENCODE_TUI_PLUGIN_DEST"
|
|
50
|
+
cp "$OPENCODE_TUI_PLUGIN_SRC" "$OPENCODE_CONFIG_PLUGIN_DIR/Witty-Skill-Insight.tui.tsx"
|
|
51
|
+
echo "✅ OpenCode TUI Plugin installed to $OPENCODE_TUI_PLUGIN_DEST"
|
|
52
|
+
if command -v node &> /dev/null; then
|
|
53
|
+
export TUI_PLUGIN_PATH="$OPENCODE_CONFIG_PLUGIN_DIR/Witty-Skill-Insight.tui.tsx"
|
|
54
|
+
export TUI_CONFIG_FILE="$OPENCODE_CONFIG_DIR/tui.json"
|
|
55
|
+
node - <<'NODE'
|
|
56
|
+
const fs = require("fs");
|
|
57
|
+
const path = require("path");
|
|
58
|
+
const file = process.env.TUI_CONFIG_FILE;
|
|
59
|
+
const pluginPath = process.env.TUI_PLUGIN_PATH;
|
|
60
|
+
let data = {};
|
|
61
|
+
try {
|
|
62
|
+
if (fs.existsSync(file)) {
|
|
63
|
+
const text = fs.readFileSync(file, "utf8");
|
|
64
|
+
data = text && text.trim() ? JSON.parse(text) : {};
|
|
65
|
+
}
|
|
66
|
+
} catch {}
|
|
67
|
+
if (!data || typeof data !== "object") data = {};
|
|
68
|
+
const list = Array.isArray(data.plugin) ? data.plugin.slice() : [];
|
|
69
|
+
if (pluginPath && !list.includes(pluginPath)) list.push(pluginPath);
|
|
70
|
+
data.plugin = list;
|
|
71
|
+
fs.mkdirSync(path.dirname(file), { recursive: true });
|
|
72
|
+
fs.writeFileSync(file, JSON.stringify(data, null, 2));
|
|
73
|
+
NODE
|
|
74
|
+
fi
|
|
75
|
+
fi
|
|
41
76
|
|
|
42
77
|
# --- 2.1 Setup Skill-Insight Config (~/.skill-insight/.env) ---
|
|
43
78
|
SKILL_INSIGHT_CONFIG_DIR="$HOME/.skill-insight"
|
|
@@ -46,10 +81,12 @@ if [ -f "$OPENCODE_PLUGIN_SRC" ]; then
|
|
|
46
81
|
|
|
47
82
|
EXISTING_KEY=""
|
|
48
83
|
EXISTING_HOST=""
|
|
84
|
+
EXISTING_SHOW_TASK_STATS=""
|
|
49
85
|
if [ -f "$SKILL_INSIGHT_CONFIG_FILE" ]; then
|
|
50
86
|
# match only UNCOMMENTED lines
|
|
51
87
|
EXISTING_KEY=$(grep '^SKILL_INSIGHT_API_KEY=' "$SKILL_INSIGHT_CONFIG_FILE" | head -n 1 | cut -d'=' -f2-)
|
|
52
88
|
EXISTING_HOST=$(grep '^SKILL_INSIGHT_HOST=' "$SKILL_INSIGHT_CONFIG_FILE" | head -n 1 | cut -d'=' -f2-)
|
|
89
|
+
EXISTING_SHOW_TASK_STATS=$(grep '^SKILL_INSIGHT_SHOW_TASK_STATS=' "$SKILL_INSIGHT_CONFIG_FILE" | head -n 1 | cut -d'=' -f2-)
|
|
53
90
|
fi
|
|
54
91
|
|
|
55
92
|
# API Key Selection Logic
|
|
@@ -89,13 +126,19 @@ if [ -f "$OPENCODE_PLUGIN_SRC" ]; then
|
|
|
89
126
|
if [ -z "$API_KEY" ]; then
|
|
90
127
|
echo "⚠️ Warning: No API Key provided. Data reporting will fail."
|
|
91
128
|
fi
|
|
129
|
+
|
|
130
|
+
FINAL_SHOW_TASK_STATS="$EXISTING_SHOW_TASK_STATS"
|
|
131
|
+
if [ -z "$FINAL_SHOW_TASK_STATS" ]; then
|
|
132
|
+
FINAL_SHOW_TASK_STATS="true"
|
|
133
|
+
fi
|
|
92
134
|
|
|
93
135
|
echo "⚙️ Syncing configuration to $SKILL_INSIGHT_CONFIG_FILE..."
|
|
94
136
|
touch "$SKILL_INSIGHT_CONFIG_FILE"
|
|
95
137
|
cp "$SKILL_INSIGHT_CONFIG_FILE" "${SKILL_INSIGHT_CONFIG_FILE}.bak"
|
|
96
|
-
grep -v "^SKILL_INSIGHT_API_KEY=" "${SKILL_INSIGHT_CONFIG_FILE}.bak" | grep -v "^SKILL_INSIGHT_HOST=" > "$SKILL_INSIGHT_CONFIG_FILE"
|
|
138
|
+
grep -v "^SKILL_INSIGHT_API_KEY=" "${SKILL_INSIGHT_CONFIG_FILE}.bak" | grep -v "^SKILL_INSIGHT_HOST=" | grep -v "^SKILL_INSIGHT_SHOW_TASK_STATS=" > "$SKILL_INSIGHT_CONFIG_FILE"
|
|
97
139
|
echo "SKILL_INSIGHT_API_KEY=$API_KEY" >> "$SKILL_INSIGHT_CONFIG_FILE"
|
|
98
140
|
echo "SKILL_INSIGHT_HOST=$FINAL_HOST" >> "$SKILL_INSIGHT_CONFIG_FILE"
|
|
141
|
+
echo "SKILL_INSIGHT_SHOW_TASK_STATS=$FINAL_SHOW_TASK_STATS" >> "$SKILL_INSIGHT_CONFIG_FILE"
|
|
99
142
|
rm "${SKILL_INSIGHT_CONFIG_FILE}.bak"
|
|
100
143
|
echo "✅ Configuration updated (Other settings preserved)."
|
|
101
144
|
|
|
@@ -399,9 +399,10 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
399
399
|
|
|
400
400
|
// logDebug(`Event: ${event.type}`);
|
|
401
401
|
|
|
402
|
-
|
|
402
|
+
try {
|
|
403
403
|
// Attempt to find session ID in various places
|
|
404
|
-
|
|
404
|
+
let sessionId = event.session_id || event.properties?.sessionID || event.payload?.session_id;
|
|
405
|
+
let eagerFlush = false;
|
|
405
406
|
|
|
406
407
|
// 1. Accumulate Message Metadata
|
|
407
408
|
if (event.type === 'message.created' || event.type === 'message.updated') {
|
|
@@ -416,11 +417,16 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
416
417
|
});
|
|
417
418
|
}
|
|
418
419
|
const entry = sessionStore.get(msgId);
|
|
420
|
+
if (!sessionId) sessionId = info.sessionID || info.sessionId || entry.info?.sessionID;
|
|
419
421
|
if (sessionId) entry.info.sessionID = sessionId;
|
|
420
422
|
// Merge info
|
|
421
423
|
Object.assign(entry.info, info);
|
|
422
424
|
if (info.tool_calls || info.toolCalls) entry.info.tool_calls = info.tool_calls || info.toolCalls;
|
|
423
425
|
if (info.function_call || info.functionCall) entry.info.function_call = info.function_call || info.functionCall;
|
|
426
|
+
|
|
427
|
+
if (entry.info?.role === 'assistant' && (entry.info.finish || entry.info.time?.completed != null)) {
|
|
428
|
+
eagerFlush = true;
|
|
429
|
+
}
|
|
424
430
|
}
|
|
425
431
|
}
|
|
426
432
|
|
|
@@ -441,6 +447,7 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
441
447
|
});
|
|
442
448
|
}
|
|
443
449
|
const entry = sessionStore.get(msgId);
|
|
450
|
+
if (!sessionId) sessionId = entry.info?.sessionID || part.sessionID || part.session_id;
|
|
444
451
|
if (!(entry.parts instanceof Map)) entry.parts = new Map(Array.isArray(entry.parts) ? entry.parts : []);
|
|
445
452
|
if (entry.toolParts && !(entry.toolParts instanceof Map)) entry.toolParts = new Map(Array.isArray(entry.toolParts) ? entry.toolParts : []);
|
|
446
453
|
|
|
@@ -566,6 +573,7 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
566
573
|
}
|
|
567
574
|
|
|
568
575
|
const entry = sessionStore.get(msgId);
|
|
576
|
+
if (!sessionId) sessionId = entry.info?.sessionID;
|
|
569
577
|
if (!(entry.parts instanceof Map)) entry.parts = new Map(Array.isArray(entry.parts) ? entry.parts : []);
|
|
570
578
|
|
|
571
579
|
const dedupeKey = `${msgId}:${partId}:${field}`;
|
|
@@ -606,7 +614,7 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
606
614
|
}
|
|
607
615
|
|
|
608
616
|
// 3. Upload on Session Idle
|
|
609
|
-
if (event.type === "session.idle") {
|
|
617
|
+
if (event.type === "session.idle" || eagerFlush) {
|
|
610
618
|
if (!sessionId || !sessionId.startsWith("ses")) return;
|
|
611
619
|
|
|
612
620
|
// Reload store from disk to pick up any data written by
|
|
@@ -688,6 +696,7 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
688
696
|
let totalOutputTokens = 0;
|
|
689
697
|
let totalCacheReadInputTokens = 0;
|
|
690
698
|
let totalCacheCreationInputTokens = 0;
|
|
699
|
+
let totalReasoningTokens = 0;
|
|
691
700
|
let llmCallCount = 0;
|
|
692
701
|
let toolCallCount = 0;
|
|
693
702
|
let toolCallErrorCount = 0;
|
|
@@ -717,11 +726,18 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
717
726
|
const cacheReadToks = Number(u.cache?.read || u.cache_read_input_tokens || 0);
|
|
718
727
|
const cacheCreateToks = Number(u.cache?.write || u.cache_creation_input_tokens || 0);
|
|
719
728
|
const inputToks = Number(u.input_tokens || u.input || 0); // base input only (excludes cache)
|
|
720
|
-
const
|
|
729
|
+
const rawOutputToks = Number(u.output_tokens || u.output || 0);
|
|
730
|
+
const reasoningToks = Number(u.reasoning || u.reasoning_tokens || u.completion_tokens_details?.reasoning_tokens || 0);
|
|
731
|
+
// OpenCode reports reasoning separately from output; DeepSeek API includes it in output.
|
|
732
|
+
// Normalize: output_tokens should always include reasoning tokens.
|
|
733
|
+
const outputToks = (u.reasoning !== undefined && reasoningToks > 0 && rawOutputToks < reasoningToks)
|
|
734
|
+
? rawOutputToks + reasoningToks
|
|
735
|
+
: rawOutputToks;
|
|
721
736
|
totalInputTokens += inputToks;
|
|
722
737
|
totalOutputTokens += outputToks;
|
|
723
738
|
totalCacheReadInputTokens += cacheReadToks;
|
|
724
739
|
totalCacheCreationInputTokens += cacheCreateToks;
|
|
740
|
+
totalReasoningTokens += reasoningToks;
|
|
725
741
|
const callTotal = inputToks + cacheReadToks + cacheCreateToks + outputToks;
|
|
726
742
|
if (callTotal > maxSingleCallTokens) maxSingleCallTokens = callTotal;
|
|
727
743
|
}
|
|
@@ -767,6 +783,7 @@ export default async function WittySkillInsightPlugin(input) {
|
|
|
767
783
|
cache_read_input_tokens: totalCacheReadInputTokens,
|
|
768
784
|
cache_creation_input_tokens: totalCacheCreationInputTokens,
|
|
769
785
|
max_single_call_tokens: maxSingleCallTokens,
|
|
786
|
+
reasoning_tokens: totalReasoningTokens,
|
|
770
787
|
final_result: lastAssistantContent,
|
|
771
788
|
interactions: messages.map(m => ({
|
|
772
789
|
role: m.role,
|
|
@@ -911,8 +928,9 @@ try {
|
|
|
911
928
|
}
|
|
912
929
|
} catch (err) {
|
|
913
930
|
logDebug(`Plugin Exception: ${err.message}`);
|
|
931
|
+
} finally {
|
|
932
|
+
saveStore();
|
|
914
933
|
}
|
|
915
|
-
saveStore();
|
|
916
934
|
}
|
|
917
935
|
};
|
|
918
936
|
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// @ts-nocheck
|
|
2
|
+
/** @jsxImportSource @opentui/solid */
|
|
3
|
+
import { Show, createEffect, createMemo, createSignal } from "solid-js"
|
|
4
|
+
import fs from "fs"
|
|
5
|
+
import os from "os"
|
|
6
|
+
import path from "path"
|
|
7
|
+
import { spawn } from "child_process"
|
|
8
|
+
|
|
9
|
+
function parseBool(input: unknown, defaultValue: boolean) {
|
|
10
|
+
if (input === undefined || input === null) return defaultValue
|
|
11
|
+
const value = String(input).trim().toLowerCase()
|
|
12
|
+
if (!value) return defaultValue
|
|
13
|
+
if (value === "1" || value === "true" || value === "yes" || value === "y" || value === "on") return true
|
|
14
|
+
if (value === "0" || value === "false" || value === "no" || value === "n" || value === "off") return false
|
|
15
|
+
return defaultValue
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function loadSkillInsightConfig() {
|
|
19
|
+
const config: Record<string, string> = {}
|
|
20
|
+
try {
|
|
21
|
+
const envPath = path.join(os.homedir(), ".skill-insight", ".env")
|
|
22
|
+
if (fs.existsSync(envPath)) {
|
|
23
|
+
const content = fs.readFileSync(envPath, "utf8")
|
|
24
|
+
for (const line of content.split("\n")) {
|
|
25
|
+
const match = line.match(/^\s*([\w_]+)\s*=\s*(.*)?\s*$/)
|
|
26
|
+
if (!match) continue
|
|
27
|
+
const key = match[1]
|
|
28
|
+
const raw = (match[2] || "").trim()
|
|
29
|
+
const value = raw.replace(/^['"](.*)['"]$/, "$1")
|
|
30
|
+
config[key] = value
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
} catch {}
|
|
34
|
+
|
|
35
|
+
const apiKey = config["SKILL_INSIGHT_API_KEY"] || process.env.SKILL_INSIGHT_API_KEY
|
|
36
|
+
const host = config["SKILL_INSIGHT_HOST"] || process.env.SKILL_INSIGHT_HOST
|
|
37
|
+
const showTaskStats = parseBool(
|
|
38
|
+
config["SKILL_INSIGHT_SHOW_TASK_STATS"] ?? process.env.SKILL_INSIGHT_SHOW_TASK_STATS,
|
|
39
|
+
true,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
return { apiKey, host, showTaskStats }
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function normalizeHost(host: string) {
|
|
46
|
+
const raw = host.trim()
|
|
47
|
+
if (!raw) return null
|
|
48
|
+
try {
|
|
49
|
+
const urlStr = raw.match(/^https?:\/\//) ? raw : `http://${raw}`
|
|
50
|
+
const u = new URL(urlStr)
|
|
51
|
+
return u
|
|
52
|
+
} catch {
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function formatLatencySeconds(input: unknown) {
|
|
58
|
+
const n = typeof input === "number" ? input : Number(input)
|
|
59
|
+
if (!Number.isFinite(n) || n < 0) return "-"
|
|
60
|
+
if (n < 10) return `${n.toFixed(2)}s`
|
|
61
|
+
if (n < 60) return `${n.toFixed(1)}s`
|
|
62
|
+
return `${Math.round(n)}s`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function formatNumber(input: unknown) {
|
|
66
|
+
const n = typeof input === "number" ? input : Number(input)
|
|
67
|
+
if (!Number.isFinite(n)) return "-"
|
|
68
|
+
return new Intl.NumberFormat("en-US").format(n)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function sleep(ms: number) {
|
|
72
|
+
await new Promise((r) => setTimeout(r, ms))
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
async function fetchTaskStats(base: URL, taskId: string, apiKey?: string) {
|
|
76
|
+
const url = new URL("/api/task-stats", base)
|
|
77
|
+
url.searchParams.set("taskId", taskId)
|
|
78
|
+
url.searchParams.set("framework", "opencode")
|
|
79
|
+
const headers: Record<string, string> = {}
|
|
80
|
+
if (apiKey) headers["x-witty-api-key"] = apiKey
|
|
81
|
+
|
|
82
|
+
const res = await fetch(url, { headers })
|
|
83
|
+
if (!res.ok) return null
|
|
84
|
+
const json = (await res.json()) as any
|
|
85
|
+
if (!json || json.found !== true) return null
|
|
86
|
+
return json
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function buildDetailsUrl(base: URL, taskId: string) {
|
|
90
|
+
const u = new URL("/details", base)
|
|
91
|
+
u.searchParams.set("framework", "opencode")
|
|
92
|
+
u.searchParams.set("expandTaskId", taskId)
|
|
93
|
+
return u.toString()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function openUrl(url: string) {
|
|
97
|
+
try {
|
|
98
|
+
if (process.platform === "darwin") {
|
|
99
|
+
spawn("open", [url], { stdio: "ignore", detached: true }).unref()
|
|
100
|
+
return true
|
|
101
|
+
}
|
|
102
|
+
if (process.platform === "win32") {
|
|
103
|
+
spawn("cmd", ["/c", "start", "", url], { stdio: "ignore", detached: true, windowsHide: true }).unref()
|
|
104
|
+
return true
|
|
105
|
+
}
|
|
106
|
+
spawn("xdg-open", [url], { stdio: "ignore", detached: true }).unref()
|
|
107
|
+
return true
|
|
108
|
+
} catch {
|
|
109
|
+
return false
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function formatStatsMessage(stats: any, detailsUrl: string) {
|
|
114
|
+
const latency = formatLatencySeconds(stats?.latency)
|
|
115
|
+
const tokens = formatNumber(stats?.tokens)
|
|
116
|
+
const inputTokens = formatNumber(stats?.input_tokens)
|
|
117
|
+
const outputTokens = formatNumber(stats?.output_tokens)
|
|
118
|
+
const toolCalls = formatNumber(stats?.tool_call_count)
|
|
119
|
+
const llmCalls = formatNumber(stats?.llm_call_count)
|
|
120
|
+
return [
|
|
121
|
+
`时延: ${latency}`,
|
|
122
|
+
`Token: ${tokens} (入: ${inputTokens}, 出: ${outputTokens})`,
|
|
123
|
+
`LLM: ${llmCalls} | 工具: ${toolCalls}`,
|
|
124
|
+
`详情: ${detailsUrl}`,
|
|
125
|
+
].join("\n")
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function StatsFooter(props: {
|
|
129
|
+
api: any
|
|
130
|
+
sessionId: string
|
|
131
|
+
getEntry: (sid: string) => any
|
|
132
|
+
ensure: (sid: string) => void
|
|
133
|
+
config: { host?: string; apiKey?: string }
|
|
134
|
+
}) {
|
|
135
|
+
const theme = () => props.api.theme.current
|
|
136
|
+
|
|
137
|
+
createEffect(() => {
|
|
138
|
+
if (!props.sessionId) return
|
|
139
|
+
props.ensure(props.sessionId)
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
const entry = createMemo(() => {
|
|
143
|
+
if (!props.sessionId) return null
|
|
144
|
+
return props.getEntry(props.sessionId)
|
|
145
|
+
})
|
|
146
|
+
|
|
147
|
+
const title = createMemo(() => {
|
|
148
|
+
return "Skill Insight"
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<box gap={1}>
|
|
153
|
+
<Show when={!props.config.host}>
|
|
154
|
+
<box
|
|
155
|
+
backgroundColor={theme().backgroundElement}
|
|
156
|
+
paddingTop={1}
|
|
157
|
+
paddingBottom={1}
|
|
158
|
+
paddingLeft={2}
|
|
159
|
+
paddingRight={2}
|
|
160
|
+
flexDirection="column"
|
|
161
|
+
gap={0}
|
|
162
|
+
>
|
|
163
|
+
<text fg={theme().text}>
|
|
164
|
+
<b>Skill Insight</b>
|
|
165
|
+
</text>
|
|
166
|
+
<text fg={theme().textMuted}>未配置 SKILL_INSIGHT_HOST</text>
|
|
167
|
+
<text fg={theme().textMuted}>请在 ~/.skill-insight/.env 设置 SKILL_INSIGHT_HOST</text>
|
|
168
|
+
</box>
|
|
169
|
+
</Show>
|
|
170
|
+
<Show when={entry()}>
|
|
171
|
+
{(x: any) => (
|
|
172
|
+
<box
|
|
173
|
+
backgroundColor={theme().backgroundElement}
|
|
174
|
+
paddingTop={1}
|
|
175
|
+
paddingBottom={1}
|
|
176
|
+
paddingLeft={2}
|
|
177
|
+
paddingRight={2}
|
|
178
|
+
flexDirection="column"
|
|
179
|
+
gap={0}
|
|
180
|
+
>
|
|
181
|
+
<box flexDirection="row" justifyContent="space-between">
|
|
182
|
+
<text fg={theme().text}>
|
|
183
|
+
<b>{title()}</b>
|
|
184
|
+
</text>
|
|
185
|
+
</box>
|
|
186
|
+
<Show when={x().state === "loading"}>
|
|
187
|
+
<text fg={theme().textMuted}>等待任务执行完毕</text>
|
|
188
|
+
</Show>
|
|
189
|
+
<Show when={x().state === "error"}>
|
|
190
|
+
<text fg={theme().textMuted}>统计暂不可用</text>
|
|
191
|
+
</Show>
|
|
192
|
+
<Show when={x().state === "ready"}>
|
|
193
|
+
<text fg={theme().textMuted}>时延: {formatLatencySeconds(x().stats?.latency)}</text>
|
|
194
|
+
<text fg={theme().textMuted}>
|
|
195
|
+
Token: {formatNumber(x().stats?.tokens)} (入: {formatNumber(x().stats?.input_tokens)}, 出:{" "}
|
|
196
|
+
{formatNumber(x().stats?.output_tokens)})
|
|
197
|
+
</text>
|
|
198
|
+
<text fg={theme().textMuted}>
|
|
199
|
+
LLM: {formatNumber(x().stats?.llm_call_count)} | 工具: {formatNumber(x().stats?.tool_call_count)}
|
|
200
|
+
</text>
|
|
201
|
+
<text
|
|
202
|
+
fg={theme().primary}
|
|
203
|
+
onMouseDown={() => {
|
|
204
|
+
const ok = openUrl(x().detailsUrl)
|
|
205
|
+
if (!ok) props.api.ui.toast({ message: "打开失败(可复制链接到浏览器)", variant: "error" })
|
|
206
|
+
}}
|
|
207
|
+
>
|
|
208
|
+
<b>查看详情 ↗</b> <span style={{ fg: theme().textMuted }}>(点击打开)</span>
|
|
209
|
+
</text>
|
|
210
|
+
</Show>
|
|
211
|
+
</box>
|
|
212
|
+
)}
|
|
213
|
+
</Show>
|
|
214
|
+
<Show when={!entry()}>
|
|
215
|
+
<text fg={theme().textMuted}>Skill Insight:暂无任务统计</text>
|
|
216
|
+
</Show>
|
|
217
|
+
</box>
|
|
218
|
+
)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
const tui = async (api: any) => {
|
|
222
|
+
const [entries, setEntries] = createSignal({})
|
|
223
|
+
|
|
224
|
+
const getEntry = (sid: string) => entries()[sid]
|
|
225
|
+
const setEntry = (sid: string, value: any) => {
|
|
226
|
+
const prev = entries()
|
|
227
|
+
setEntries({ ...prev, [sid]: value })
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const ensure = async (sessionId: string, opts?: { force?: boolean }) => {
|
|
231
|
+
const existing = getEntry(sessionId)
|
|
232
|
+
if (existing?.state === "loading") return
|
|
233
|
+
if (!opts?.force && existing?.state === "ready") return
|
|
234
|
+
|
|
235
|
+
const cfg = loadSkillInsightConfig()
|
|
236
|
+
if (!cfg.showTaskStats) return
|
|
237
|
+
if (!cfg.host) return
|
|
238
|
+
const base = normalizeHost(cfg.host)
|
|
239
|
+
if (!base) return
|
|
240
|
+
|
|
241
|
+
const detailsUrl = buildDetailsUrl(base, sessionId)
|
|
242
|
+
setEntry(sessionId, {
|
|
243
|
+
sessionId,
|
|
244
|
+
state: "loading",
|
|
245
|
+
detailsUrl,
|
|
246
|
+
updatedAt: Date.now(),
|
|
247
|
+
prevTimestamp: existing?.stats?.timestamp,
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
let stats: any = null
|
|
251
|
+
const maxAttempts = 8
|
|
252
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
253
|
+
stats = await fetchTaskStats(base, sessionId, cfg.apiKey)
|
|
254
|
+
if (stats) {
|
|
255
|
+
if (opts?.force && existing?.stats?.timestamp && stats.timestamp) {
|
|
256
|
+
const prevMs = Date.parse(existing.stats.timestamp)
|
|
257
|
+
const curMs = Date.parse(stats.timestamp)
|
|
258
|
+
if (Number.isFinite(prevMs) && Number.isFinite(curMs) && curMs <= prevMs) {
|
|
259
|
+
stats = null
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (stats) break
|
|
264
|
+
await sleep(i < 2 ? 800 : 1200)
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
if (!stats) {
|
|
268
|
+
setEntry(sessionId, { sessionId, state: "error", detailsUrl, updatedAt: Date.now() })
|
|
269
|
+
return
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
setEntry(sessionId, { sessionId, state: "ready", detailsUrl, stats, updatedAt: Date.now() })
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
api.slots.register({
|
|
276
|
+
order: 80,
|
|
277
|
+
slots: {
|
|
278
|
+
sidebar_content(_ctx: any, props: any) {
|
|
279
|
+
const cfg = loadSkillInsightConfig()
|
|
280
|
+
if (!cfg.showTaskStats) return null
|
|
281
|
+
const sid = props?.session_id
|
|
282
|
+
if (!sid || typeof sid !== "string") return null
|
|
283
|
+
return <StatsFooter api={api} sessionId={sid} getEntry={getEntry} ensure={ensure} config={cfg} />
|
|
284
|
+
},
|
|
285
|
+
},
|
|
286
|
+
})
|
|
287
|
+
|
|
288
|
+
api.event.on("session.idle", async (evt: any) => {
|
|
289
|
+
const sessionId =
|
|
290
|
+
evt?.properties?.sessionId ||
|
|
291
|
+
evt?.properties?.sessionID ||
|
|
292
|
+
evt?.properties?.session_id ||
|
|
293
|
+
evt?.session_id ||
|
|
294
|
+
evt?.payload?.session_id
|
|
295
|
+
|
|
296
|
+
if (!sessionId || typeof sessionId !== "string") return
|
|
297
|
+
if (!sessionId.startsWith("ses")) return
|
|
298
|
+
api.kv.set("skill_insight_latest_session_id", sessionId)
|
|
299
|
+
ensure(sessionId, { force: true })
|
|
300
|
+
})
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
const plugin = {
|
|
304
|
+
id: "witty-skill-insight-task-stats",
|
|
305
|
+
tui,
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export default plugin
|
package/scripts/utils.js
CHANGED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[46786,(e,t,r)=>{t.exports=e.x("os",()=>require("os"))},14747,(e,t,r)=>{t.exports=e.x("path",()=>require("path"))},54799,(e,t,r)=>{t.exports=e.x("crypto",()=>require("crypto"))},93695,(e,t,r)=>{t.exports=e.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},70406,(e,t,r)=>{t.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},18622,(e,t,r)=>{t.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},24725,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},22734,(e,t,r)=>{t.exports=e.x("fs",()=>require("fs"))},66680,(e,t,r)=>{t.exports=e.x("node:crypto",()=>require("node:crypto"))},98043,e=>e.a(async(t,r)=>{try{let l;var n,a=e.i(97289),s=e.i(63021),i=e.i(86414),o=t([i]);[i]=o.then?(await o)():o,(0,a.config)();let d=e.g.prisma||new s.PrismaClient,u=(0,i.getDatabaseAdapter)(),c=process.env.DB_HOST?(l=(n=u).getClient())instanceof s.PrismaClient?l:{user:{findUnique:async e=>e.where?.apiKey?n.findUserByApiKey(e.where.apiKey):e.where?.username?n.findUserByUsername(e.where.username):null,findFirst:async e=>e.where?.username?n.findUserByUsername(e.where.username):null},skill:{findFirst:async e=>{let t=e.where?.name,r=e.where?.OR?.[0]?.user??e.where?.OR?.[1]?.user;return n.findSkill(t,r)},findMany:async e=>n.findSkills(e.where||{}),findUnique:async e=>n.findSkill(e.where?.name,e.where?.user),delete:async e=>(console.warn("[OpenGaussAdapter] skill.delete not fully implemented"),null)},skillVersion:{findFirst:async e=>e.where?.skillId?n.findLatestSkillVersion(e.where.skillId):null},config:{findMany:async e=>n.findConfigs(e.where||{})},session:{findUnique:async e=>e.where?.taskId?n.findSessionByTaskId(e.where.taskId):null,update:async e=>e.where?.id?n.updateSession(e.where.id,e.data):null,upsert:async e=>{let t=e.where?.taskId;return t?n.upsertSession(t,e.create,e.update):null}},execution:{findUnique:async e=>e.where?.id?n.findExecutionById(e.where.id):null,upsert:async e=>n.upsertExecution(e),findMany:async e=>n.findExecutions(e.where,e.orderBy)}}:d;e.s(["db",0,u,"prisma",0,c]),r()}catch(e){r(e)}},!1),79832,e=>e.a(async(t,r)=>{try{var n=e.i(98043),a=t([n]);async function s(e,t){if(t)return{username:t,apiKey:null};let r=e.headers.get("x-witty-api-key");if(r)return{username:await i(r),apiKey:r};let n=new URL(e.url).searchParams.get("apiKey");return n?{username:await i(n),apiKey:n}:{username:null,apiKey:null}}async function i(e){try{let t=await n.db.findUserByApiKey(e);return t?.username||null}catch(e){return console.error("[Auth] Failed to lookup user by API Key:",e),null}}async function o(e,t){let r=await n.db.findSkillById(e);return r?"public"!==r.visibility&&r.user&&(!t||r.user!==t)&&t?{allowed:!1,skill:r}:{allowed:!0,skill:r}:{allowed:!1,skill:null}}[n]=a.then?(await a)():a,e.s(["canAccessSkill",()=>o,"resolveUser",()=>s]),r()}catch(e){r(e)}},!1),56042,e=>e.a(async(t,r)=>{try{var n=e.i(79832),a=e.i(98043),s=e.i(22734),i=e.i(89171),o=e.i(14747),l=t([n,a]);async function d(e){try{let t=e.nextUrl.searchParams,r=t.get("query"),s=t.get("category"),o=t.get("user"),{username:l}=await (0,n.resolveUser)(e,o),d={};if(l&&(d.OR=[{user:l},{user:null},{visibility:"public"}]),r){let e={OR:[{name:{contains:r}},{description:{contains:r}}]};d.OR?(d.AND=[{OR:d.OR},e],delete d.OR):d.OR=e.OR}s&&"全部"!==s&&(d.category=s);let u=await a.db.findSkills(d);u.sort((e,t)=>{let r=e.versions?.find(e=>0===e.version),n=t.versions?.find(e=>0===e.version),a=r?new Date(r.createdAt).getTime():0;return(n?new Date(n.createdAt).getTime():0)-a});let c=u.map(e=>{let t=e.versions?.find(t=>t.version===(e.activeVersion||0)),r=t?.changeLog||e.description,n=t?.createdAt?new Date(t.createdAt).toISOString():e.updatedAt.toISOString();return{id:e.id,name:e.name,description:r,category:e.category,tags:e.tags?JSON.parse(e.tags):[],author:e.author,updatedAt:n,version:e.activeVersion||0,activeVersion:e.activeVersion||0,visibility:e.visibility,qualityScore:0,usageCount:0,successRate:0,isUploaded:e.isUploaded,versions:e.versions?.map(e=>({version:e.version,createdAt:e.createdAt?new Date(e.createdAt).toISOString():"",changeLog:e.changeLog}))||[]}});return i.NextResponse.json(c)}catch(e){return console.error("Fetch Skills Error:",e),i.NextResponse.json({error:"Failed to fetch skills"},{status:500})}}async function u(e){let t=e.nextUrl.searchParams,r=t.get("id"),l=t.get("user");if(!r)return i.NextResponse.json({error:"ID required"},{status:400});try{let{username:t}=await (0,n.resolveUser)(e,l),d=await a.db.findSkillById(r);if(!d)return i.NextResponse.json({error:"Skill not found"},{status:404});if(t&&d.user&&d.user!==t)return i.NextResponse.json({error:"Unauthorized delete"},{status:403});let u=o.default.join(process.cwd(),"data","storage","skills",r);return s.default.existsSync(u)&&s.default.rmSync(u,{recursive:!0,force:!0}),await a.db.deleteSkill(r),i.NextResponse.json({success:!0})}catch(e){return console.error("Delete Skill Error:",e),i.NextResponse.json({error:e.message},{status:500})}}[n,a]=l.then?(await l)():l,e.s(["DELETE",()=>u,"GET",()=>d,"dynamic",0,"force-dynamic"]),r()}catch(e){r(e)}},!1),87542,e=>e.a(async(t,r)=>{try{var n=e.i(47909),a=e.i(74017),s=e.i(60476),i=e.i(59756),o=e.i(61916),l=e.i(74677),d=e.i(69741),u=e.i(16795),c=e.i(87718),p=e.i(95169),h=e.i(47587),y=e.i(66012),f=e.i(70101),x=e.i(26937),w=e.i(10372),g=e.i(93695);e.i(52474);var v=e.i(220),m=e.i(56042),R=t([m]);[m]=R.then?(await R)():R;let A=new n.AppRouteRouteModule({definition:{kind:a.RouteKind.APP_ROUTE,page:"/api/skills/route",pathname:"/api/skills",filename:"route",bundlePath:""},distDir:".next",relativeProjectDir:"",resolvedPagePath:"[project]/src/app/api/skills/route.ts",nextConfigOutput:"standalone",userland:m}),{workAsyncStorage:S,workUnitAsyncStorage:b,serverHooks:C}=A;function k(){return(0,s.patchFetch)({workAsyncStorage:S,workUnitAsyncStorage:b})}async function E(e,t,r){A.isDev&&(0,i.addRequestMeta)(e,"devRequestTimingInternalsEnd",process.hrtime.bigint());let n="/api/skills/route";n=n.replace(/\/index$/,"")||"/";let s=await A.prepare(e,t,{srcPage:n,multiZoneDraftMode:!1});if(!s)return t.statusCode=400,t.end("Bad Request"),null==r.waitUntil||r.waitUntil.call(r,Promise.resolve()),null;let{buildId:m,params:R,nextConfig:k,parsedUrl:E,isDraftMode:S,prerenderManifest:b,routerServerContext:C,isOnDemandRevalidate:O,revalidateOnlyGenerated:U,resolvedPathname:q,clientReferenceManifest:N,serverActionsManifest:T}=s,I=(0,d.normalizeAppPath)(n),P=!!(b.dynamicRoutes[I]||b.routes[q]),j=async()=>((null==C?void 0:C.render404)?await C.render404(e,t,E,!1):t.end("This page could not be found"),null);if(P&&!S){let e=!!b.routes[q],t=b.dynamicRoutes[I];if(t&&!1===t.fallback&&!e){if(k.experimental.adapterPath)return await j();throw new g.NoFallbackError}}let D=null;!P||A.isDev||S||(D=q,D="/index"===D?"/":D);let _=!0===A.isDev||!P,H=P&&!_;T&&N&&(0,l.setManifestsSingleton)({page:n,clientReferenceManifest:N,serverActionsManifest:T});let K=e.method||"GET",B=(0,o.getTracer)(),M=B.getActiveScopeSpan(),F={params:R,prerenderManifest:b,renderOpts:{experimental:{authInterrupts:!!k.experimental.authInterrupts},cacheComponents:!!k.cacheComponents,supportsDynamicResponse:_,incrementalCache:(0,i.getRequestMeta)(e,"incrementalCache"),cacheLifeProfiles:k.cacheLife,waitUntil:r.waitUntil,onClose:e=>{t.on("close",e)},onAfterTaskError:void 0,onInstrumentationRequestError:(t,r,n,a)=>A.onRequestError(e,t,n,a,C)},sharedContext:{buildId:m}},L=new u.NodeNextRequest(e),V=new u.NodeNextResponse(t),$=c.NextRequestAdapter.fromNodeNextRequest(L,(0,c.signalFromNodeResponse)(t));try{let s=async e=>A.handle($,F).finally(()=>{if(!e)return;e.setAttributes({"http.status_code":t.statusCode,"next.rsc":!1});let r=B.getRootSpanAttributes();if(!r)return;if(r.get("next.span_type")!==p.BaseServerSpan.handleRequest)return void console.warn(`Unexpected root span type '${r.get("next.span_type")}'. Please report this Next.js issue https://github.com/vercel/next.js`);let a=r.get("next.route");if(a){let t=`${K} ${a}`;e.setAttributes({"next.route":a,"http.route":a,"next.span_name":t}),e.updateName(t)}else e.updateName(`${K} ${n}`)}),l=!!(0,i.getRequestMeta)(e,"minimalMode"),d=async i=>{var o,d;let u=async({previousCacheEntry:a})=>{try{if(!l&&O&&U&&!a)return t.statusCode=404,t.setHeader("x-nextjs-cache","REVALIDATED"),t.end("This page could not be found"),null;let n=await s(i);e.fetchMetrics=F.renderOpts.fetchMetrics;let o=F.renderOpts.pendingWaitUntil;o&&r.waitUntil&&(r.waitUntil(o),o=void 0);let d=F.renderOpts.collectedTags;if(!P)return await (0,y.sendResponse)(L,V,n,F.renderOpts.pendingWaitUntil),null;{let e=await n.blob(),t=(0,f.toNodeOutgoingHttpHeaders)(n.headers);d&&(t[w.NEXT_CACHE_TAGS_HEADER]=d),!t["content-type"]&&e.type&&(t["content-type"]=e.type);let r=void 0!==F.renderOpts.collectedRevalidate&&!(F.renderOpts.collectedRevalidate>=w.INFINITE_CACHE)&&F.renderOpts.collectedRevalidate,a=void 0===F.renderOpts.collectedExpire||F.renderOpts.collectedExpire>=w.INFINITE_CACHE?void 0:F.renderOpts.collectedExpire;return{value:{kind:v.CachedRouteKind.APP_ROUTE,status:n.status,body:Buffer.from(await e.arrayBuffer()),headers:t},cacheControl:{revalidate:r,expire:a}}}}catch(t){throw(null==a?void 0:a.isStale)&&await A.onRequestError(e,t,{routerKind:"App Router",routePath:n,routeType:"route",revalidateReason:(0,h.getRevalidateReason)({isStaticGeneration:H,isOnDemandRevalidate:O})},!1,C),t}},c=await A.handleResponse({req:e,nextConfig:k,cacheKey:D,routeKind:a.RouteKind.APP_ROUTE,isFallback:!1,prerenderManifest:b,isRoutePPREnabled:!1,isOnDemandRevalidate:O,revalidateOnlyGenerated:U,responseGenerator:u,waitUntil:r.waitUntil,isMinimalMode:l});if(!P)return null;if((null==c||null==(o=c.value)?void 0:o.kind)!==v.CachedRouteKind.APP_ROUTE)throw Object.defineProperty(Error(`Invariant: app-route received invalid cache entry ${null==c||null==(d=c.value)?void 0:d.kind}`),"__NEXT_ERROR_CODE",{value:"E701",enumerable:!1,configurable:!0});l||t.setHeader("x-nextjs-cache",O?"REVALIDATED":c.isMiss?"MISS":c.isStale?"STALE":"HIT"),S&&t.setHeader("Cache-Control","private, no-cache, no-store, max-age=0, must-revalidate");let p=(0,f.fromNodeOutgoingHttpHeaders)(c.value.headers);return l&&P||p.delete(w.NEXT_CACHE_TAGS_HEADER),!c.cacheControl||t.getHeader("Cache-Control")||p.get("Cache-Control")||p.set("Cache-Control",(0,x.getCacheControlHeader)(c.cacheControl)),await (0,y.sendResponse)(L,V,new Response(c.value.body,{headers:p,status:c.value.status||200})),null};M?await d(M):await B.withPropagatedContext(e.headers,()=>B.trace(p.BaseServerSpan.handleRequest,{spanName:`${K} ${n}`,kind:o.SpanKind.SERVER,attributes:{"http.method":K,"http.target":e.url}},d))}catch(t){if(t instanceof g.NoFallbackError||await A.onRequestError(e,t,{routerKind:"App Router",routePath:I,routeType:"route",revalidateReason:(0,h.getRevalidateReason)({isStaticGeneration:H,isOnDemandRevalidate:O})},!1,C),P)throw t;return await (0,y.sendResponse)(L,V,new Response(null,{status:500})),null}}e.s(["handler",()=>E,"patchFetch",()=>k,"routeModule",()=>A,"serverHooks",()=>C,"workAsyncStorage",()=>S,"workUnitAsyncStorage",()=>b]),r()}catch(e){r(e)}},!1)];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__e2f0baee._.js.map
|
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
module.exports=[46786,(e,t,r)=>{t.exports=e.x("os",()=>require("os"))},14747,(e,t,r)=>{t.exports=e.x("path",()=>require("path"))},54799,(e,t,r)=>{t.exports=e.x("crypto",()=>require("crypto"))},93695,(e,t,r)=>{t.exports=e.x("next/dist/shared/lib/no-fallback-error.external.js",()=>require("next/dist/shared/lib/no-fallback-error.external.js"))},70406,(e,t,r)=>{t.exports=e.x("next/dist/compiled/@opentelemetry/api",()=>require("next/dist/compiled/@opentelemetry/api"))},18622,(e,t,r)=>{t.exports=e.x("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js",()=>require("next/dist/compiled/next-server/app-page-turbo.runtime.prod.js"))},56704,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-async-storage.external.js",()=>require("next/dist/server/app-render/work-async-storage.external.js"))},32319,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/work-unit-async-storage.external.js",()=>require("next/dist/server/app-render/work-unit-async-storage.external.js"))},24725,(e,t,r)=>{t.exports=e.x("next/dist/server/app-render/after-task-async-storage.external.js",()=>require("next/dist/server/app-render/after-task-async-storage.external.js"))},22734,(e,t,r)=>{t.exports=e.x("fs",()=>require("fs"))},66680,(e,t,r)=>{t.exports=e.x("node:crypto",()=>require("node:crypto"))},98043,e=>e.a(async(t,r)=>{try{let l;var n,s=e.i(97289),a=e.i(63021),i=e.i(86414),o=t([i]);[i]=o.then?(await o)():o,(0,s.config)();let u=e.g.prisma||new a.PrismaClient,d=(0,i.getDatabaseAdapter)(),c=process.env.DB_HOST?(l=(n=d).getClient())instanceof a.PrismaClient?l:{user:{findUnique:async e=>e.where?.apiKey?n.findUserByApiKey(e.where.apiKey):e.where?.username?n.findUserByUsername(e.where.username):null,findFirst:async e=>e.where?.username?n.findUserByUsername(e.where.username):null},skill:{findFirst:async e=>{let t=e.where?.name,r=e.where?.OR?.[0]?.user??e.where?.OR?.[1]?.user;return n.findSkill(t,r)},findMany:async e=>n.findSkills(e.where||{}),findUnique:async e=>n.findSkill(e.where?.name,e.where?.user),delete:async e=>(console.warn("[OpenGaussAdapter] skill.delete not fully implemented"),null)},skillVersion:{findFirst:async e=>e.where?.skillId?n.findLatestSkillVersion(e.where.skillId):null},config:{findMany:async e=>n.findConfigs(e.where||{})},session:{findUnique:async e=>e.where?.taskId?n.findSessionByTaskId(e.where.taskId):null,update:async e=>e.where?.id?n.updateSession(e.where.id,e.data):null,upsert:async e=>{let t=e.where?.taskId;return t?n.upsertSession(t,e.create,e.update):null}},execution:{findUnique:async e=>e.where?.id?n.findExecutionById(e.where.id):null,upsert:async e=>n.upsertExecution(e),findMany:async e=>n.findExecutions(e.where,e.orderBy)}}:u;e.s(["db",0,d,"prisma",0,c]),r()}catch(e){r(e)}},!1),79832,e=>e.a(async(t,r)=>{try{var n=e.i(98043),s=t([n]);async function a(e,t){if(t)return{username:t,apiKey:null};let r=e.headers.get("x-witty-api-key");if(r)return{username:await i(r),apiKey:r};let n=new URL(e.url).searchParams.get("apiKey");return n?{username:await i(n),apiKey:n}:{username:null,apiKey:null}}async function i(e){try{let t=await n.db.findUserByApiKey(e);return t?.username||null}catch(e){return console.error("[Auth] Failed to lookup user by API Key:",e),null}}async function o(e,t){let r=await n.db.findSkillById(e);return r?"public"!==r.visibility&&r.user&&(!t||r.user!==t)&&t?{allowed:!1,skill:r}:{allowed:!0,skill:r}:{allowed:!1,skill:null}}[n]=s.then?(await s)():s,e.s(["canAccessSkill",()=>o,"resolveUser",()=>a]),r()}catch(e){r(e)}},!1),44076,e=>e.a(async(t,r)=>{try{var n=e.i(79832),s=e.i(98043),a=e.i(89171),i=t([n,s]);async function o(e,{params:t}){try{let{id:r,version:i}=await t,o=parseInt(i,10);if(isNaN(o))return a.NextResponse.json({error:"Invalid version number"},{status:400});let{username:l}=await (0,n.resolveUser)(e),{allowed:u,skill:d}=await (0,n.canAccessSkill)(r,l);if(!d)return a.NextResponse.json({error:"Skill not found"},{status:404});if(!u)return a.NextResponse.json({error:"Unauthorized: You do not own this skill"},{status:403});if(!await s.db.findSkillVersion(r,o))return a.NextResponse.json({error:`Version ${o} not found`},{status:404});if(d.versions&&1===d.versions.length)return a.NextResponse.json({error:"Cannot delete the last version. Delete the skill instead."},{status:400});if(await s.db.deleteSkillVersion(r,o),d.activeVersion===o){let e=(d.versions||[]).filter(e=>e.version!==o);if(e.length>0){let t=e[0].version;await s.db.updateSkill(r,{activeVersion:t}),console.log(`[Delete Version] Updated activeVersion from ${o} to ${t}`)}}return a.NextResponse.json({success:!0,message:`Version ${o} deleted successfully`,previousActiveVersion:d.activeVersion})}catch(e){return console.error("Delete Version Error:",e),a.NextResponse.json({error:e.message},{status:500})}}async function l(e,{params:t}){try{let{id:e,version:r}=await t,n=parseInt(r,10);if(isNaN(n))return a.NextResponse.json({error:"Invalid version number"},{status:400});let i=await s.db.findSkillVersion(e,n);if(!i)return a.NextResponse.json({error:`Version ${n} not found`},{status:404});return a.NextResponse.json(i)}catch(e){return console.error("Get Version Error:",e),a.NextResponse.json({error:e.message},{status:500})}}[n,s]=i.then?(await i)():i,e.s(["DELETE",()=>o,"GET",()=>l]),r()}catch(e){r(e)}},!1),97739,e=>e.a(async(t,r)=>{try{var n=e.i(47909),s=e.i(74017),a=e.i(60476),i=e.i(59756),o=e.i(61916),l=e.i(74677),u=e.i(69741),d=e.i(16795),c=e.i(87718),p=e.i(95169),h=e.i(47587),f=e.i(66012),y=e.i(70101),x=e.i(26937),w=e.i(10372),v=e.i(93695);e.i(52474);var R=e.i(220),m=e.i(44076),g=t([m]);[m]=g.then?(await g)():g;let b=new n.AppRouteRouteModule({definition:{kind:s.RouteKind.APP_ROUTE,page:"/api/skills/[id]/versions/[version]/route",pathname:"/api/skills/[id]/versions/[version]",filename:"route",bundlePath:""},distDir:".next",relativeProjectDir:"",resolvedPagePath:"[project]/src/app/api/skills/[id]/versions/[version]/route.ts",nextConfigOutput:"standalone",userland:m}),{workAsyncStorage:C,workUnitAsyncStorage:A,serverHooks:N}=b;function k(){return(0,a.patchFetch)({workAsyncStorage:C,workUnitAsyncStorage:A})}async function E(e,t,r){b.isDev&&(0,i.addRequestMeta)(e,"devRequestTimingInternalsEnd",process.hrtime.bigint());let n="/api/skills/[id]/versions/[version]/route";n=n.replace(/\/index$/,"")||"/";let a=await b.prepare(e,t,{srcPage:n,multiZoneDraftMode:!1});if(!a)return t.statusCode=400,t.end("Bad Request"),null==r.waitUntil||r.waitUntil.call(r,Promise.resolve()),null;let{buildId:m,params:g,nextConfig:k,parsedUrl:E,isDraftMode:C,prerenderManifest:A,routerServerContext:N,isOnDemandRevalidate:S,revalidateOnlyGenerated:U,resolvedPathname:q,clientReferenceManifest:j,serverActionsManifest:I}=a,T=(0,u.normalizeAppPath)(n),P=!!(A.dynamicRoutes[T]||A.routes[q]),O=async()=>((null==N?void 0:N.render404)?await N.render404(e,t,E,!1):t.end("This page could not be found"),null);if(P&&!C){let e=!!A.routes[q],t=A.dynamicRoutes[T];if(t&&!1===t.fallback&&!e){if(k.experimental.adapterPath)return await O();throw new v.NoFallbackError}}let _=null;!P||b.isDev||C||(_=q,_="/index"===_?"/":_);let D=!0===b.isDev||!P,V=P&&!D;I&&j&&(0,l.setManifestsSingleton)({page:n,clientReferenceManifest:j,serverActionsManifest:I});let H=e.method||"GET",K=(0,o.getTracer)(),M=K.getActiveScopeSpan(),B={params:g,prerenderManifest:A,renderOpts:{experimental:{authInterrupts:!!k.experimental.authInterrupts},cacheComponents:!!k.cacheComponents,supportsDynamicResponse:D,incrementalCache:(0,i.getRequestMeta)(e,"incrementalCache"),cacheLifeProfiles:k.cacheLife,waitUntil:r.waitUntil,onClose:e=>{t.on("close",e)},onAfterTaskError:void 0,onInstrumentationRequestError:(t,r,n,s)=>b.onRequestError(e,t,n,s,N)},sharedContext:{buildId:m}},$=new d.NodeNextRequest(e),F=new d.NodeNextResponse(t),L=c.NextRequestAdapter.fromNodeNextRequest($,(0,c.signalFromNodeResponse)(t));try{let a=async e=>b.handle(L,B).finally(()=>{if(!e)return;e.setAttributes({"http.status_code":t.statusCode,"next.rsc":!1});let r=K.getRootSpanAttributes();if(!r)return;if(r.get("next.span_type")!==p.BaseServerSpan.handleRequest)return void console.warn(`Unexpected root span type '${r.get("next.span_type")}'. Please report this Next.js issue https://github.com/vercel/next.js`);let s=r.get("next.route");if(s){let t=`${H} ${s}`;e.setAttributes({"next.route":s,"http.route":s,"next.span_name":t}),e.updateName(t)}else e.updateName(`${H} ${n}`)}),l=!!(0,i.getRequestMeta)(e,"minimalMode"),u=async i=>{var o,u;let d=async({previousCacheEntry:s})=>{try{if(!l&&S&&U&&!s)return t.statusCode=404,t.setHeader("x-nextjs-cache","REVALIDATED"),t.end("This page could not be found"),null;let n=await a(i);e.fetchMetrics=B.renderOpts.fetchMetrics;let o=B.renderOpts.pendingWaitUntil;o&&r.waitUntil&&(r.waitUntil(o),o=void 0);let u=B.renderOpts.collectedTags;if(!P)return await (0,f.sendResponse)($,F,n,B.renderOpts.pendingWaitUntil),null;{let e=await n.blob(),t=(0,y.toNodeOutgoingHttpHeaders)(n.headers);u&&(t[w.NEXT_CACHE_TAGS_HEADER]=u),!t["content-type"]&&e.type&&(t["content-type"]=e.type);let r=void 0!==B.renderOpts.collectedRevalidate&&!(B.renderOpts.collectedRevalidate>=w.INFINITE_CACHE)&&B.renderOpts.collectedRevalidate,s=void 0===B.renderOpts.collectedExpire||B.renderOpts.collectedExpire>=w.INFINITE_CACHE?void 0:B.renderOpts.collectedExpire;return{value:{kind:R.CachedRouteKind.APP_ROUTE,status:n.status,body:Buffer.from(await e.arrayBuffer()),headers:t},cacheControl:{revalidate:r,expire:s}}}}catch(t){throw(null==s?void 0:s.isStale)&&await b.onRequestError(e,t,{routerKind:"App Router",routePath:n,routeType:"route",revalidateReason:(0,h.getRevalidateReason)({isStaticGeneration:V,isOnDemandRevalidate:S})},!1,N),t}},c=await b.handleResponse({req:e,nextConfig:k,cacheKey:_,routeKind:s.RouteKind.APP_ROUTE,isFallback:!1,prerenderManifest:A,isRoutePPREnabled:!1,isOnDemandRevalidate:S,revalidateOnlyGenerated:U,responseGenerator:d,waitUntil:r.waitUntil,isMinimalMode:l});if(!P)return null;if((null==c||null==(o=c.value)?void 0:o.kind)!==R.CachedRouteKind.APP_ROUTE)throw Object.defineProperty(Error(`Invariant: app-route received invalid cache entry ${null==c||null==(u=c.value)?void 0:u.kind}`),"__NEXT_ERROR_CODE",{value:"E701",enumerable:!1,configurable:!0});l||t.setHeader("x-nextjs-cache",S?"REVALIDATED":c.isMiss?"MISS":c.isStale?"STALE":"HIT"),C&&t.setHeader("Cache-Control","private, no-cache, no-store, max-age=0, must-revalidate");let p=(0,y.fromNodeOutgoingHttpHeaders)(c.value.headers);return l&&P||p.delete(w.NEXT_CACHE_TAGS_HEADER),!c.cacheControl||t.getHeader("Cache-Control")||p.get("Cache-Control")||p.set("Cache-Control",(0,x.getCacheControlHeader)(c.cacheControl)),await (0,f.sendResponse)($,F,new Response(c.value.body,{headers:p,status:c.value.status||200})),null};M?await u(M):await K.withPropagatedContext(e.headers,()=>K.trace(p.BaseServerSpan.handleRequest,{spanName:`${H} ${n}`,kind:o.SpanKind.SERVER,attributes:{"http.method":H,"http.target":e.url}},u))}catch(t){if(t instanceof v.NoFallbackError||await b.onRequestError(e,t,{routerKind:"App Router",routePath:T,routeType:"route",revalidateReason:(0,h.getRevalidateReason)({isStaticGeneration:V,isOnDemandRevalidate:S})},!1,N),P)throw t;return await (0,f.sendResponse)($,F,new Response(null,{status:500})),null}}e.s(["handler",()=>E,"patchFetch",()=>k,"routeModule",()=>b,"serverHooks",()=>N,"workAsyncStorage",()=>C,"workUnitAsyncStorage",()=>A]),r()}catch(e){r(e)}},!1)];
|
|
2
|
-
|
|
3
|
-
//# sourceMappingURL=%5Broot-of-the-server%5D__fc05579d._.js.map
|