@dotobokuri/fleet-console 1.70.0 → 1.71.1
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/dist/cli.mjs +78 -14
- package/dist/client/assets/{_baseUniq-81Y5kFtp.js → _baseUniq-Bhd1wyKE.js} +1 -1
- package/dist/client/assets/{arc-d96Fgk-5.js → arc-Cu9FOmUr.js} +1 -1
- package/dist/client/assets/{architectureDiagram-Q4EWVU46-BBgIklLp.js → architectureDiagram-Q4EWVU46-Dq9FA5I3.js} +1 -1
- package/dist/client/assets/{blockDiagram-DXYQGD6D-BCjY9dJk.js → blockDiagram-DXYQGD6D-BDZkCLI1.js} +1 -1
- package/dist/client/assets/{c4Diagram-AHTNJAMY-BVJRdf8q.js → c4Diagram-AHTNJAMY-XBPYwanu.js} +1 -1
- package/dist/client/assets/channel-BTX-SvBb.js +1 -0
- package/dist/client/assets/{chunk-4BX2VUAB-CT7BCzBg.js → chunk-4BX2VUAB-BbTQSLs0.js} +1 -1
- package/dist/client/assets/{chunk-4TB4RGXK-DUbDaHiY.js → chunk-4TB4RGXK-DukpmkUz.js} +1 -1
- package/dist/client/assets/{chunk-55IACEB6-C7HDwq0R.js → chunk-55IACEB6-BFyIa1Ge.js} +1 -1
- package/dist/client/assets/{chunk-EDXVE4YY-Mh16Bf7t.js → chunk-EDXVE4YY-D7RHsfQm.js} +1 -1
- package/dist/client/assets/{chunk-FMBD7UC4-D3BjqAun.js → chunk-FMBD7UC4-Co64dt-k.js} +1 -1
- package/dist/client/assets/{chunk-OYMX7WX6-DmzxPT1k.js → chunk-OYMX7WX6-CdycD6Yh.js} +1 -1
- package/dist/client/assets/{chunk-QZHKN3VN-CaZdQK6Z.js → chunk-QZHKN3VN-CNvTB1xu.js} +1 -1
- package/dist/client/assets/{chunk-YZCP3GAM-Q2hrlgLY.js → chunk-YZCP3GAM-CY1_pTO2.js} +1 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-CixB9uB6.js +1 -0
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-CixB9uB6.js +1 -0
- package/dist/client/assets/clone-DuMuKBBB.js +1 -0
- package/dist/client/assets/{cose-bilkent-S5V4N54A-CPdIsNiQ.js → cose-bilkent-S5V4N54A-PLhfHDPQ.js} +1 -1
- package/dist/client/assets/{dagre-KV5264BT-BYWdUXO0.js → dagre-KV5264BT-gJnGByq0.js} +1 -1
- package/dist/client/assets/{diagram-5BDNPKRD-BC8rqmOK.js → diagram-5BDNPKRD-y48OdlFp.js} +1 -1
- package/dist/client/assets/{diagram-G4DWMVQ6-CES6iBQQ.js → diagram-G4DWMVQ6-DSLYc2V1.js} +1 -1
- package/dist/client/assets/{diagram-MMDJMWI5-BfhQrSaN.js → diagram-MMDJMWI5-DWgtcwcn.js} +1 -1
- package/dist/client/assets/{diagram-TYMM5635-C2FgHNxP.js → diagram-TYMM5635-CLd83m-G.js} +1 -1
- package/dist/client/assets/{erDiagram-SMLLAGMA-KQgKZTcf.js → erDiagram-SMLLAGMA-CGP2g7Ug.js} +1 -1
- package/dist/client/assets/{flowDiagram-DWJPFMVM-7Ytk1sX_.js → flowDiagram-DWJPFMVM-BhKzXbma.js} +1 -1
- package/dist/client/assets/{ganttDiagram-T4ZO3ILL-C4yl6vGV.js → ganttDiagram-T4ZO3ILL-BdpBmhZF.js} +1 -1
- package/dist/client/assets/{gitGraphDiagram-UUTBAWPF-DyN7iLk4.js → gitGraphDiagram-UUTBAWPF-IylczS5r.js} +1 -1
- package/dist/client/assets/{graph-BsOHL3Ty.js → graph-xlKIIKKy.js} +1 -1
- package/dist/client/assets/index-DH7xHFza.js +467 -0
- package/dist/client/assets/index-DKMT7UVt.css +1 -0
- package/dist/client/assets/{infoDiagram-42DDH7IO-BIOEjyDP.js → infoDiagram-42DDH7IO-Dm9-Iqxb.js} +1 -1
- package/dist/client/assets/{ishikawaDiagram-UXIWVN3A-C18t-DEH.js → ishikawaDiagram-UXIWVN3A-0tPrKKU3.js} +1 -1
- package/dist/client/assets/{journeyDiagram-VCZTEJTY-BysZXCkq.js → journeyDiagram-VCZTEJTY-3wTioYxO.js} +1 -1
- package/dist/client/assets/{kanban-definition-6JOO6SKY-Zdulrt1W.js → kanban-definition-6JOO6SKY-DjVcpuse.js} +1 -1
- package/dist/client/assets/{layout-DhT9CiMw.js → layout-BZ0nnXEn.js} +1 -1
- package/dist/client/assets/{linear-DQna1rOZ.js → linear-DNdW4gLV.js} +1 -1
- package/dist/client/assets/{mermaid.core-C0sjt4NJ.js → mermaid.core-DpO6yFcA.js} +4 -4
- package/dist/client/assets/{min-Dyx0ykEh.js → min-xMtTJxkM.js} +1 -1
- package/dist/client/assets/{mindmap-definition-QFDTVHPH-BzEvAUNd.js → mindmap-definition-QFDTVHPH-8tcRIKM5.js} +1 -1
- package/dist/client/assets/{pieDiagram-DEJITSTG-Cd4ORVnw.js → pieDiagram-DEJITSTG-DOuWZGrv.js} +1 -1
- package/dist/client/assets/{quadrantDiagram-34T5L4WZ-CvNxhBIm.js → quadrantDiagram-34T5L4WZ-BWPtgVdA.js} +1 -1
- package/dist/client/assets/{requirementDiagram-MS252O5E-CuGuie-o.js → requirementDiagram-MS252O5E-CkNpSYqR.js} +1 -1
- package/dist/client/assets/{sankeyDiagram-XADWPNL6-zn7buHsU.js → sankeyDiagram-XADWPNL6-DUPS39lN.js} +1 -1
- package/dist/client/assets/{sequenceDiagram-FGHM5R23-BxDReh8o.js → sequenceDiagram-FGHM5R23-B4n7l5jw.js} +1 -1
- package/dist/client/assets/{stateDiagram-FHFEXIEX-DtZ0UE1G.js → stateDiagram-FHFEXIEX-DBHsG7yj.js} +1 -1
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2--18aeGq2.js +1 -0
- package/dist/client/assets/{timeline-definition-GMOUNBTQ-DfKveVha.js → timeline-definition-GMOUNBTQ-BLxUyg3R.js} +1 -1
- package/dist/client/assets/{vennDiagram-DHZGUBPP-CZe6StT_.js → vennDiagram-DHZGUBPP-27NkxCen.js} +1 -1
- package/dist/client/assets/{wardley-RL74JXVD-B10WfMsc.js → wardley-RL74JXVD-VNgEaZlH.js} +1 -1
- package/dist/client/assets/{wardleyDiagram-NUSXRM2D-DzN04fy9.js → wardleyDiagram-NUSXRM2D-byIhDvPD.js} +1 -1
- package/dist/client/assets/{xychartDiagram-5P7HB3ND-CIgNRRNp.js → xychartDiagram-5P7HB3ND-D0amCilL.js} +1 -1
- package/dist/client/index.html +2 -2
- package/dist/fleet-plugins/file-explorer/routes.mjs +138 -96
- package/dist/fleet-plugins/ledger/routes.mjs +73 -12
- package/dist/fleet-plugins/quota/routes.mjs +73 -12
- package/dist/fleet-plugins/scuttlebutt/routes.mjs +74 -12
- package/dist/fleet-plugins/skills/routes.mjs +126 -60
- package/dist/fleet-plugins/terminal/routes.mjs +482 -69
- package/dist/fleet.mjs +479 -67
- package/package.json +1 -1
- package/dist/client/assets/channel-CiSQi5S5.js +0 -1
- package/dist/client/assets/classDiagram-6PBFFD2Q-Cy-ZC6xF.js +0 -1
- package/dist/client/assets/classDiagram-v2-HSJHXN6E-Cy-ZC6xF.js +0 -1
- package/dist/client/assets/clone-BAhE6Fq8.js +0 -1
- package/dist/client/assets/index-2049WCXu.css +0 -1
- package/dist/client/assets/index-DJcpFTNB.js +0 -466
- package/dist/client/assets/stateDiagram-v2-QKLJ7IA2-aYct9Owm.js +0 -1
|
@@ -17709,7 +17709,7 @@ var benchmarks_default = {
|
|
|
17709
17709
|
};
|
|
17710
17710
|
var models_default = {
|
|
17711
17711
|
version: 1,
|
|
17712
|
-
updatedAt: "2026-08-
|
|
17712
|
+
updatedAt: "2026-08-22T00:00:00Z",
|
|
17713
17713
|
providers: {
|
|
17714
17714
|
codex: {
|
|
17715
17715
|
name: "Codex",
|
|
@@ -18120,7 +18120,7 @@ var models_default = {
|
|
|
18120
18120
|
{
|
|
18121
18121
|
modelId: "composer-2.5",
|
|
18122
18122
|
name: "Composer-2.5",
|
|
18123
|
-
capabilityClass: "
|
|
18123
|
+
capabilityClass: "standard",
|
|
18124
18124
|
quotaScope: "auto",
|
|
18125
18125
|
contextWindow: 2e5,
|
|
18126
18126
|
benchmarkKey: "composer-2.5"
|
|
@@ -18128,9 +18128,11 @@ var models_default = {
|
|
|
18128
18128
|
{
|
|
18129
18129
|
modelId: "composer-2.5-fast",
|
|
18130
18130
|
name: "Composer-2.5-Fast",
|
|
18131
|
-
capabilityClass: "
|
|
18131
|
+
capabilityClass: "standard",
|
|
18132
|
+
variantOf: "composer-2.5",
|
|
18132
18133
|
quotaScope: "auto",
|
|
18133
|
-
contextWindow: 2e5
|
|
18134
|
+
contextWindow: 2e5,
|
|
18135
|
+
benchmarkKey: "composer-2.5"
|
|
18134
18136
|
},
|
|
18135
18137
|
{
|
|
18136
18138
|
modelId: "grok-4.5",
|
|
@@ -18152,7 +18154,8 @@ var models_default = {
|
|
|
18152
18154
|
{
|
|
18153
18155
|
modelId: "grok-4.5-fast",
|
|
18154
18156
|
name: "Grok-4.5-Fast",
|
|
18155
|
-
capabilityClass: "
|
|
18157
|
+
capabilityClass: "flagship",
|
|
18158
|
+
variantOf: "grok-4.5",
|
|
18156
18159
|
quotaScope: "auto",
|
|
18157
18160
|
contextWindow: 256e3,
|
|
18158
18161
|
effort: {
|
|
@@ -18163,7 +18166,8 @@ var models_default = {
|
|
|
18163
18166
|
"high"
|
|
18164
18167
|
],
|
|
18165
18168
|
upstreamModelIdTemplate: "cursor-grok-4.5-{effort}-fast"
|
|
18166
|
-
}
|
|
18169
|
+
},
|
|
18170
|
+
benchmarkKey: "grok-4.5"
|
|
18167
18171
|
},
|
|
18168
18172
|
{
|
|
18169
18173
|
modelId: "grok-4.6",
|
|
@@ -18186,7 +18190,8 @@ var models_default = {
|
|
|
18186
18190
|
{
|
|
18187
18191
|
modelId: "grok-4.6-fast",
|
|
18188
18192
|
name: "Grok-4.6-Fast",
|
|
18189
|
-
capabilityClass: "
|
|
18193
|
+
capabilityClass: "flagship",
|
|
18194
|
+
variantOf: "grok-4.6",
|
|
18190
18195
|
quotaScope: "auto",
|
|
18191
18196
|
contextWindow: 256e3,
|
|
18192
18197
|
effort: {
|
|
@@ -18198,7 +18203,8 @@ var models_default = {
|
|
|
18198
18203
|
"xhigh"
|
|
18199
18204
|
],
|
|
18200
18205
|
upstreamModelIdTemplate: "cursor-grok-4.6-{effort}-fast"
|
|
18201
|
-
}
|
|
18206
|
+
},
|
|
18207
|
+
benchmarkKey: "grok-4.6"
|
|
18202
18208
|
},
|
|
18203
18209
|
{
|
|
18204
18210
|
modelId: "claude-opus-5",
|
|
@@ -18426,7 +18432,7 @@ var models_default = {
|
|
|
18426
18432
|
opencode: {
|
|
18427
18433
|
name: "OpenCode",
|
|
18428
18434
|
defaultModel: "minimax-m3",
|
|
18429
|
-
source: "live GET https://opencode.ai/zen/go/v1/models + per-model wire probes on /messages, /responses, /chat/completions (2026-08-03); contextWindow cross-checked against models.dev api.json opencode-go entries and oh-my-pi packages/catalog/src/models.json (2026-08-03, both agree). Excluded: mimo-v2-pro/mimo-v2-omni (upstream server_error), hy3-preview (listed but Router.ModelNotFound); superseded generations removed 2026-08-08 \u2014 the catalog keeps each lineup's current generation only",
|
|
18435
|
+
source: "live GET https://opencode.ai/zen/go/v1/models + per-model wire probes on /messages, /responses, /chat/completions (2026-08-03); contextWindow cross-checked against models.dev api.json opencode-go entries and oh-my-pi packages/catalog/src/models.json (2026-08-03, both agree). Excluded: mimo-v2-pro/mimo-v2-omni (upstream server_error), hy3-preview (listed but Router.ModelNotFound); superseded generations removed 2026-08-08 \u2014 the catalog keeps each lineup's current generation only; ox-alpha-free and muse-spark-1.2-contributor added 2026-08-21 from the same live list, each wire chosen by a streaming probe on that date (ox-alpha-free frames natively on /chat/completions and returns reasoning_content deltas; muse-spark-1.2-contributor frames natively on /responses and echoes its own reasoning block) and each effort ladder taken from the upstream's own rejection message (ox-alpha-free: low/high/max; muse-spark-1.2-contributor: none/minimal/low/medium/high/xhigh, so max is refused); their contextWindow comes from models.dev api.json opencode-go entries (2026-08-21). muse-spark-1.2-contributor's Responses backend accepts only tool_choice auto: named function choices, required, and none are refused with a 400 (2026-08-21), so a caller that forces a tool cannot use it",
|
|
18430
18436
|
models: [
|
|
18431
18437
|
{
|
|
18432
18438
|
modelId: "minimax-m3",
|
|
@@ -18474,6 +18480,22 @@ var models_default = {
|
|
|
18474
18480
|
},
|
|
18475
18481
|
benchmarkKey: "grok-4.5"
|
|
18476
18482
|
},
|
|
18483
|
+
{
|
|
18484
|
+
modelId: "muse-spark-1.2-contributor",
|
|
18485
|
+
name: "Muse-Spark-1.2-Contributor",
|
|
18486
|
+
capabilityClass: "flagship",
|
|
18487
|
+
wire: "responses",
|
|
18488
|
+
contextWindow: 1048576,
|
|
18489
|
+
effort: {
|
|
18490
|
+
supported: true,
|
|
18491
|
+
levels: [
|
|
18492
|
+
"low",
|
|
18493
|
+
"medium",
|
|
18494
|
+
"high",
|
|
18495
|
+
"xhigh"
|
|
18496
|
+
]
|
|
18497
|
+
}
|
|
18498
|
+
},
|
|
18477
18499
|
{
|
|
18478
18500
|
modelId: "deepseek-v4-flash",
|
|
18479
18501
|
name: "DeepSeek-V4-Flash",
|
|
@@ -18524,6 +18546,21 @@ var models_default = {
|
|
|
18524
18546
|
capabilityClass: "flagship",
|
|
18525
18547
|
wire: "chat-completions",
|
|
18526
18548
|
contextWindow: 256e3
|
|
18549
|
+
},
|
|
18550
|
+
{
|
|
18551
|
+
modelId: "ox-alpha-free",
|
|
18552
|
+
name: "Ox-Alpha-Free",
|
|
18553
|
+
capabilityClass: "flagship",
|
|
18554
|
+
wire: "chat-completions",
|
|
18555
|
+
contextWindow: 1e6,
|
|
18556
|
+
effort: {
|
|
18557
|
+
supported: true,
|
|
18558
|
+
levels: [
|
|
18559
|
+
"low",
|
|
18560
|
+
"high",
|
|
18561
|
+
"max"
|
|
18562
|
+
]
|
|
18563
|
+
}
|
|
18527
18564
|
}
|
|
18528
18565
|
]
|
|
18529
18566
|
},
|
|
@@ -18552,7 +18589,7 @@ var models_default = {
|
|
|
18552
18589
|
{
|
|
18553
18590
|
modelId: "grok-composer-2.5-fast",
|
|
18554
18591
|
name: "Grok-Composer-2.5-Fast",
|
|
18555
|
-
capabilityClass: "
|
|
18592
|
+
capabilityClass: "standard",
|
|
18556
18593
|
wire: "responses",
|
|
18557
18594
|
contextWindow: 2e5
|
|
18558
18595
|
}
|
|
@@ -18747,6 +18784,14 @@ var GatewayModelEntrySchema = external_exports.object({
|
|
|
18747
18784
|
benchmarkKey: external_exports.string().min(1).optional(),
|
|
18748
18785
|
description: external_exports.string().min(1).optional(),
|
|
18749
18786
|
providerModelId: external_exports.string().min(1).optional(),
|
|
18787
|
+
/**
|
|
18788
|
+
* The catalog entry this one is a serving variant of, when the provider gives
|
|
18789
|
+
* the variant its own wire id and `providerModelId` is therefore unavailable
|
|
18790
|
+
* as the lineage link. Pure provenance: it names a sibling `modelId` in the
|
|
18791
|
+
* same provider and never reaches a request, so the variant keeps sending its
|
|
18792
|
+
* own upstream id while inheriting the base's class and benchmark evidence.
|
|
18793
|
+
*/
|
|
18794
|
+
variantOf: external_exports.string().min(1).optional(),
|
|
18750
18795
|
serviceTier: external_exports.literal("priority").optional(),
|
|
18751
18796
|
cursorMaxMode: external_exports.literal(true).optional(),
|
|
18752
18797
|
quotaScope: external_exports.enum(GATEWAY_QUOTA_SCOPES).optional(),
|
|
@@ -18984,8 +19029,24 @@ function validateRegistry(value) {
|
|
|
18984
19029
|
if (!isRoutingAlias && !model.capabilityClass) {
|
|
18985
19030
|
throw new Error(`Gateway model is missing a capability class: ${provider}/${model.modelId}`);
|
|
18986
19031
|
}
|
|
18987
|
-
|
|
18988
|
-
|
|
19032
|
+
const catalogEntry = (modelId) => modelId === void 0 ? void 0 : definition.models.find((candidate) => candidate.modelId === modelId);
|
|
19033
|
+
const providerLinkedBase = isRoutingAlias ? void 0 : catalogEntry(model.providerModelId);
|
|
19034
|
+
if (model.variantOf && providerLinkedBase && model.providerModelId !== model.variantOf) {
|
|
19035
|
+
throw new Error(`Gateway service-tier sibling names two different bases: ${provider}/${model.modelId}`);
|
|
19036
|
+
}
|
|
19037
|
+
if (model.variantOf === model.modelId) {
|
|
19038
|
+
throw new Error(`Gateway service-tier sibling names itself as its base: ${provider}/${model.modelId}`);
|
|
19039
|
+
}
|
|
19040
|
+
const baseModelId = isRoutingAlias ? void 0 : model.variantOf ?? model.providerModelId;
|
|
19041
|
+
if (baseModelId) {
|
|
19042
|
+
const base = catalogEntry(baseModelId);
|
|
19043
|
+
if (model.variantOf && !base) {
|
|
19044
|
+
throw new Error(`Gateway service-tier sibling names an unknown base: ${provider}/${model.modelId} -> ${model.variantOf}`);
|
|
19045
|
+
}
|
|
19046
|
+
const baseLink = base && base.modelId !== base.providerModelId ? base.variantOf ?? base.providerModelId : base?.variantOf;
|
|
19047
|
+
if (base && catalogEntry(baseLink)) {
|
|
19048
|
+
throw new Error(`Gateway service-tier sibling names another sibling as its base: ${provider}/${model.modelId}`);
|
|
19049
|
+
}
|
|
18989
19050
|
if (base && base.capabilityClass !== model.capabilityClass) {
|
|
18990
19051
|
throw new Error(`Gateway service-tier sibling class differs from its base: ${provider}/${model.modelId}`);
|
|
18991
19052
|
}
|
|
@@ -20028,6 +20089,7 @@ function claudeGatewayLaunchEnv(inherited, options) {
|
|
|
20028
20089
|
env.CLAUDE_CODE_ENABLE_GATEWAY_MODEL_DISCOVERY = "1";
|
|
20029
20090
|
env.ENABLE_TOOL_SEARCH = "true";
|
|
20030
20091
|
env.CLAUDE_CODE_AUTO_COMPACT_WINDOW ??= "1000000";
|
|
20092
|
+
env.CLAUDE_CODE_MAX_SUBAGENT_SPAWN_DEPTH ??= "1";
|
|
20031
20093
|
delete env.ANTHROPIC_AUTH_TOKEN;
|
|
20032
20094
|
delete env.ANTHROPIC_API_KEY;
|
|
20033
20095
|
delete env.ANTHROPIC_MODEL;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { execFile } from 'node:child_process';
|
|
4
|
-
import
|
|
4
|
+
import fs4 from 'node:fs/promises';
|
|
5
5
|
import os2 from 'node:os';
|
|
6
6
|
import { existsSync, accessSync, constants } from 'node:fs';
|
|
7
7
|
import crypto from 'node:crypto';
|
|
@@ -10,16 +10,16 @@ import crypto from 'node:crypto';
|
|
|
10
10
|
function definePlugin(definition) {
|
|
11
11
|
return definition;
|
|
12
12
|
}
|
|
13
|
-
function registerRouter(ctx,
|
|
13
|
+
function registerRouter(ctx, path7, handler, catalog) {
|
|
14
14
|
if (catalog) {
|
|
15
|
-
ctx.registerRouter(normalizePath(
|
|
15
|
+
ctx.registerRouter(normalizePath(path7), handler, catalog);
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
|
-
ctx.registerRouter(normalizePath(
|
|
18
|
+
ctx.registerRouter(normalizePath(path7), handler);
|
|
19
19
|
}
|
|
20
|
-
function normalizePath(
|
|
21
|
-
if (
|
|
22
|
-
return
|
|
20
|
+
function normalizePath(path7) {
|
|
21
|
+
if (path7.length === 0 || path7 === "/") return "/";
|
|
22
|
+
return path7;
|
|
23
23
|
}
|
|
24
24
|
var DEFAULT_WINDOWS_PATHEXT = ".COM;.EXE;.BAT;.CMD";
|
|
25
25
|
var WINDOWS_PATH_SEPARATOR = ";";
|
|
@@ -161,14 +161,14 @@ async function ensureCliMjs(cliHome, onBootstrap) {
|
|
|
161
161
|
const pkgPath = path.join(cliHome, "node_modules", SKILLS_PACKAGE, "package.json");
|
|
162
162
|
let needsInstall = true;
|
|
163
163
|
try {
|
|
164
|
-
const raw = await
|
|
164
|
+
const raw = await fs4.readFile(pkgPath, "utf-8");
|
|
165
165
|
const pkg = JSON.parse(raw);
|
|
166
166
|
if (pkg.version === SKILLS_VERSION) needsInstall = false;
|
|
167
167
|
} catch {
|
|
168
168
|
}
|
|
169
169
|
if (needsInstall) {
|
|
170
170
|
onBootstrap?.(WARMUP_LINE);
|
|
171
|
-
await
|
|
171
|
+
await fs4.mkdir(cliHome, { recursive: true });
|
|
172
172
|
await runNpmInstall(cliHome);
|
|
173
173
|
}
|
|
174
174
|
_cliMjsPath = mjsPath;
|
|
@@ -293,6 +293,55 @@ function getJobResult(id, cursor) {
|
|
|
293
293
|
exitCode: job.exitCode
|
|
294
294
|
};
|
|
295
295
|
}
|
|
296
|
+
var HEAD_BYTES = 8192;
|
|
297
|
+
var MAX_DESCRIPTION = 500;
|
|
298
|
+
function parseSkillDescription(head) {
|
|
299
|
+
const text = head.charCodeAt(0) === 65279 ? head.slice(1) : head;
|
|
300
|
+
if (!/^---\r?\n/.test(text)) return void 0;
|
|
301
|
+
const body = text.slice(text.indexOf("\n") + 1);
|
|
302
|
+
const endIndex = body.search(/^---\s*$/m);
|
|
303
|
+
if (endIndex === -1) return void 0;
|
|
304
|
+
const lines = body.slice(0, endIndex).split(/\r?\n/);
|
|
305
|
+
const startLine = lines.findIndex((line) => /^description\s*:/.test(line));
|
|
306
|
+
if (startLine === -1) return void 0;
|
|
307
|
+
const first = (lines[startLine] ?? "").replace(/^description\s*:\s*/, "");
|
|
308
|
+
if (/^[>|]/.test(first.trim())) return void 0;
|
|
309
|
+
const parts = [first.trim()];
|
|
310
|
+
for (let i = startLine + 1; i < lines.length; i += 1) {
|
|
311
|
+
const line = lines[i] ?? "";
|
|
312
|
+
if (!/^\s+\S/.test(line)) break;
|
|
313
|
+
parts.push(line.trim());
|
|
314
|
+
}
|
|
315
|
+
let value = parts.filter(Boolean).join(" ").trim();
|
|
316
|
+
if (value.startsWith('"') && value.endsWith('"') && value.length > 1 || value.startsWith("'") && value.endsWith("'") && value.length > 1) {
|
|
317
|
+
value = value.slice(1, -1).trim();
|
|
318
|
+
}
|
|
319
|
+
if (!value) return void 0;
|
|
320
|
+
return value.length > MAX_DESCRIPTION ? value.slice(0, MAX_DESCRIPTION) : value;
|
|
321
|
+
}
|
|
322
|
+
async function readSkillDescription(skillRoot, allowedRoot) {
|
|
323
|
+
let handle;
|
|
324
|
+
try {
|
|
325
|
+
const [realAllowedRoot, realRoot] = await Promise.all([
|
|
326
|
+
fs4.realpath(allowedRoot),
|
|
327
|
+
fs4.realpath(skillRoot)
|
|
328
|
+
]);
|
|
329
|
+
if (realRoot !== realAllowedRoot && !realRoot.startsWith(realAllowedRoot + path.sep)) {
|
|
330
|
+
return void 0;
|
|
331
|
+
}
|
|
332
|
+
const realMd = await fs4.realpath(path.join(realRoot, "SKILL.md"));
|
|
333
|
+
if (!realMd.startsWith(realRoot + path.sep)) return void 0;
|
|
334
|
+
handle = await fs4.open(realMd, "r");
|
|
335
|
+
const buffer = Buffer.alloc(HEAD_BYTES);
|
|
336
|
+
const { bytesRead } = await handle.read(buffer, 0, HEAD_BYTES, 0);
|
|
337
|
+
return parseSkillDescription(buffer.subarray(0, bytesRead).toString("utf-8"));
|
|
338
|
+
} catch {
|
|
339
|
+
return void 0;
|
|
340
|
+
} finally {
|
|
341
|
+
await handle?.close().catch(() => {
|
|
342
|
+
});
|
|
343
|
+
}
|
|
344
|
+
}
|
|
296
345
|
var ProjectPathError = class extends Error {
|
|
297
346
|
code;
|
|
298
347
|
constructor(code) {
|
|
@@ -305,12 +354,12 @@ async function resolveProjectCwd(theaterRoot) {
|
|
|
305
354
|
const lexicalRoot = path.resolve(theaterRoot);
|
|
306
355
|
let realRoot;
|
|
307
356
|
try {
|
|
308
|
-
realRoot = await
|
|
357
|
+
realRoot = await fs4.realpath(lexicalRoot);
|
|
309
358
|
} catch (error) {
|
|
310
359
|
throw mapFilesystemError(error);
|
|
311
360
|
}
|
|
312
361
|
try {
|
|
313
|
-
if (!(await
|
|
362
|
+
if (!(await fs4.stat(realRoot)).isDirectory()) {
|
|
314
363
|
throw new ProjectPathError("invalid_path");
|
|
315
364
|
}
|
|
316
365
|
} catch (error) {
|
|
@@ -402,30 +451,47 @@ var CLI_TIMEOUT_MS = 12e4;
|
|
|
402
451
|
var USERINFO_URL_RE = /\b[a-z][a-z0-9+.-]*:\/\/[^\s/@]+@[^\s]+/gi;
|
|
403
452
|
var TOKEN_URL_PARAM_RE = /([?&](?:access_?token|token|api_?key|apikey|auth(?:orization)?|password|secret|credential)=)[^&#\s]*/gi;
|
|
404
453
|
var installedSkillsByTheater = /* @__PURE__ */ new Map();
|
|
454
|
+
function isRecord(value) {
|
|
455
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
456
|
+
}
|
|
457
|
+
function hasSourceEntry(table) {
|
|
458
|
+
return Object.values(table).some((entry) => isRecord(entry) && typeof entry["source"] === "string");
|
|
459
|
+
}
|
|
460
|
+
function isLockShape(parsed) {
|
|
461
|
+
if (!isRecord(parsed)) return false;
|
|
462
|
+
if ("skills" in parsed) return isRecord(parsed["skills"]);
|
|
463
|
+
return hasSourceEntry(parsed);
|
|
464
|
+
}
|
|
465
|
+
function collectLockSources(lock, sources) {
|
|
466
|
+
const table = isRecord(lock.skills) ? lock.skills : lock;
|
|
467
|
+
for (const [name, entry] of Object.entries(table)) {
|
|
468
|
+
if (isRecord(entry) && typeof entry["source"] === "string") {
|
|
469
|
+
sources.set(name, entry["source"]);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
}
|
|
405
473
|
async function readSkillSources(cwd) {
|
|
406
474
|
const sources = /* @__PURE__ */ new Map();
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
475
|
+
for (const candidate of [
|
|
476
|
+
path.join(cwd, "skills-lock.json"),
|
|
477
|
+
path.join(cwd, ".agents", ".skill-lock.json")
|
|
478
|
+
]) {
|
|
479
|
+
let raw;
|
|
480
|
+
try {
|
|
481
|
+
raw = await fs4.readFile(candidate, "utf-8");
|
|
482
|
+
} catch {
|
|
483
|
+
continue;
|
|
415
484
|
}
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
if (typeof parsed === "object" && parsed !== null) {
|
|
422
|
-
for (const [name, entry] of Object.entries(parsed)) {
|
|
423
|
-
if (entry && typeof entry.source === "string") sources.set(name, entry.source);
|
|
485
|
+
try {
|
|
486
|
+
const parsed = JSON.parse(raw);
|
|
487
|
+
if (isLockShape(parsed)) {
|
|
488
|
+
collectLockSources(parsed, sources);
|
|
489
|
+
return { sources, lockRead: true };
|
|
424
490
|
}
|
|
491
|
+
} catch {
|
|
425
492
|
}
|
|
426
|
-
} catch {
|
|
427
493
|
}
|
|
428
|
-
return sources;
|
|
494
|
+
return { sources, lockRead: false };
|
|
429
495
|
}
|
|
430
496
|
async function runListCommand(args, cwd, executor) {
|
|
431
497
|
const result = await executor(args, { cwd, timeout: CLI_TIMEOUT_MS });
|
|
@@ -488,42 +554,42 @@ function spawnJobAsync(jobId, args, cwd, redactionPaths, executor) {
|
|
|
488
554
|
}).then((result) => finishJob(jobId, result.exitCode)).catch(() => finishJob(jobId, 1));
|
|
489
555
|
});
|
|
490
556
|
}
|
|
557
|
+
async function toListItems(raw, scope, lock, allowedRoot) {
|
|
558
|
+
return Promise.all(raw.map(async (entry) => {
|
|
559
|
+
const description = entry.path ? await readSkillDescription(entry.path, allowedRoot) : void 0;
|
|
560
|
+
const source = lock.sources.get(entry.name);
|
|
561
|
+
const unmanaged = !source && lock.lockRead;
|
|
562
|
+
return {
|
|
563
|
+
name: entry.name,
|
|
564
|
+
scope,
|
|
565
|
+
agents: entry.agents,
|
|
566
|
+
...source ? { source } : {},
|
|
567
|
+
...unmanaged ? { unmanaged: true } : {},
|
|
568
|
+
...description ? { description } : {},
|
|
569
|
+
displayPath: buildDisplayPath(scope, entry.name)
|
|
570
|
+
};
|
|
571
|
+
}));
|
|
572
|
+
}
|
|
491
573
|
async function listInstalledSkills(projectCwd, executor) {
|
|
574
|
+
const homeDir = os2.homedir();
|
|
492
575
|
if (projectCwd) {
|
|
493
576
|
const [projectRaw, globalRaw2, projectSources, globalSources2] = await Promise.all([
|
|
494
577
|
runListCommand(["list", "--json"], projectCwd, executor),
|
|
495
|
-
runListCommand(["list", "-g", "--json"],
|
|
578
|
+
runListCommand(["list", "-g", "--json"], homeDir, executor),
|
|
496
579
|
readSkillSources(projectCwd),
|
|
497
|
-
readSkillSources(
|
|
580
|
+
readSkillSources(homeDir)
|
|
581
|
+
]);
|
|
582
|
+
const [projectItems, globalItems] = await Promise.all([
|
|
583
|
+
toListItems(projectRaw, "project", projectSources, projectCwd),
|
|
584
|
+
toListItems(globalRaw2, "global", globalSources2, homeDir)
|
|
498
585
|
]);
|
|
499
|
-
return [
|
|
500
|
-
...projectRaw.map((entry) => ({
|
|
501
|
-
name: entry.name,
|
|
502
|
-
scope: "project",
|
|
503
|
-
agents: entry.agents,
|
|
504
|
-
source: projectSources.get(entry.name),
|
|
505
|
-
displayPath: buildDisplayPath("project", entry.name)
|
|
506
|
-
})),
|
|
507
|
-
...globalRaw2.map((entry) => ({
|
|
508
|
-
name: entry.name,
|
|
509
|
-
scope: "global",
|
|
510
|
-
agents: entry.agents,
|
|
511
|
-
source: globalSources2.get(entry.name),
|
|
512
|
-
displayPath: buildDisplayPath("global", entry.name)
|
|
513
|
-
}))
|
|
514
|
-
];
|
|
586
|
+
return [...projectItems, ...globalItems];
|
|
515
587
|
}
|
|
516
588
|
const [globalRaw, globalSources] = await Promise.all([
|
|
517
|
-
runListCommand(["list", "-g", "--json"],
|
|
518
|
-
readSkillSources(
|
|
589
|
+
runListCommand(["list", "-g", "--json"], homeDir, executor),
|
|
590
|
+
readSkillSources(homeDir)
|
|
519
591
|
]);
|
|
520
|
-
return globalRaw
|
|
521
|
-
name: entry.name,
|
|
522
|
-
scope: "global",
|
|
523
|
-
agents: entry.agents,
|
|
524
|
-
source: globalSources.get(entry.name),
|
|
525
|
-
displayPath: buildDisplayPath("global", entry.name)
|
|
526
|
-
}));
|
|
592
|
+
return toListItems(globalRaw, "global", globalSources, homeDir);
|
|
527
593
|
}
|
|
528
594
|
async function handleList(req, res, ctx, executor) {
|
|
529
595
|
if (req.method !== "GET") {
|
|
@@ -900,9 +966,9 @@ async function handleInstalledFile(req, res, ctx, executor) {
|
|
|
900
966
|
// CLI가 보고한 skillRoot 자체도 신뢰하지 않는다 — scope의 정당한 상위 경계
|
|
901
967
|
// (project=theater 루트, global=홈)를 벗어나면 읽지 않는다. `.agents/skills`로
|
|
902
968
|
// 고정하지 않는 이유: claude 단독 설치는 `.claude/skills` 아래에 놓인다.
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
969
|
+
fs4.realpath(cwd),
|
|
970
|
+
fs4.realpath(skillRoot),
|
|
971
|
+
fs4.realpath(skillMdPath).catch(() => null)
|
|
906
972
|
]);
|
|
907
973
|
if (!realMd) {
|
|
908
974
|
ctx.host.http.writeJson(res, 404, { error: "skill_not_found" });
|
|
@@ -916,7 +982,7 @@ async function handleInstalledFile(req, res, ctx, executor) {
|
|
|
916
982
|
ctx.host.http.writeJson(res, 403, { error: "path_outside_theater" });
|
|
917
983
|
return;
|
|
918
984
|
}
|
|
919
|
-
const markdown = await
|
|
985
|
+
const markdown = await fs4.readFile(realMd, "utf-8");
|
|
920
986
|
ctx.host.http.writeJson(res, 200, { markdown });
|
|
921
987
|
} catch {
|
|
922
988
|
ctx.host.http.writeJson(res, 502, { error: "read_failed" });
|