thinkpool-pair 0.7.364 → 0.7.365
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/LICENSE +18 -0
- package/README.md +20 -0
- package/abort-turn-barrier.mjs +1 -23
- package/account.mjs +1 -1437
- package/acp-client.mjs +1 -140
- package/agent-detect.mjs +1 -28
- package/agent-notify.mjs +1 -142
- package/agent-visibility.mjs +1 -67
- package/auth-store.mjs +1 -120
- package/bridge.mjs +1 -6266
- package/byok-detect.mjs +1 -126
- package/claude-command-catalog.mjs +1 -91
- package/claude-session.mjs +1 -1519
- package/code-event-contract.mjs +1 -118
- package/codex-app-server.mjs +1 -340
- package/codex-commands.mjs +1 -83
- package/codex-event-mapper.mjs +1 -232
- package/codex-images.mjs +1 -69
- package/codex-mcp-http.mjs +1 -131
- package/codex-session.mjs +1 -1295
- package/command-catalog.mjs +1 -118
- package/command-guidance.mjs +1 -8
- package/context-contract.mjs +1 -95
- package/context-windows.mjs +1 -107
- package/cross-terminal.mjs +1 -789
- package/cumulative-event-relay.mjs +1 -53
- package/design-edit.mjs +1 -424
- package/design-source-contract.mjs +1 -4
- package/direct-pair-room.mjs +1 -57
- package/dispatch-lease.mjs +1 -37
- package/dispatch-permission-cleanup.mjs +1 -86
- package/edit-diff.mjs +1 -136
- package/error-recovery.mjs +1 -50
- package/event-bounds.mjs +1 -121
- package/event-delivery-queue.mjs +1 -60
- package/event-id.mjs +1 -549
- package/evidence-citations.mjs +1 -50
- package/evidence-compact.mjs +1 -11
- package/flow-assembly.mjs +1 -196
- package/flow-budget.mjs +1 -84
- package/flow-conductor.mjs +1 -259
- package/flow-context-store.mjs +1 -387
- package/flow-host-revert.mjs +1 -42
- package/flow-models.mjs +1 -139
- package/flow-preview.mjs +1 -148
- package/flow-receipt.mjs +1 -122
- package/flow-redispatch.mjs +1 -72
- package/flow-review-gate.mjs +1 -402
- package/flow-review-reflect.mjs +1 -115
- package/flow-review.mjs +1 -152
- package/flow-scope-evidence.mjs +1 -117
- package/flow-skill-registry.mjs +1 -140
- package/flow-task-graph.mjs +1 -562
- package/flow-worktree.mjs +1 -71
- package/git-diff-report.mjs +1 -121
- package/hermes-delegation-guard.mjs +1 -14
- package/hermes-event-mapper.mjs +1 -194
- package/hermes-isolation.mjs +1 -61
- package/hermes-model-cache.mjs +1 -54
- package/hermes-policy.mjs +1 -92
- package/hermes-probe.mjs +1 -57
- package/hermes-session.mjs +1 -683
- package/hermes-setup.mjs +1 -167
- package/host-memory.mjs +1 -116
- package/interrupted-resume.mjs +1 -95
- package/keep-awake.mjs +1 -148
- package/key-shape.mjs +1 -49
- package/lane-continuation.mjs +1 -83
- package/lane-lifecycle.mjs +1 -189
- package/lane-worktree.mjs +1 -77
- package/launcher.mjs +1 -354
- package/mcp-flight-recorder.mjs +1 -79
- package/mockup-delivery.mjs +1 -57
- package/model-prices.mjs +1 -113
- package/package.json +13 -4
- package/pair-bus.mjs +1 -98
- package/pair-control-authority.mjs +1 -89
- package/past-work-search.mjs +1 -105
- package/plan-meters.mjs +1 -144
- package/presence.mjs +1 -191
- package/privacy-report.mjs +1 -108
- package/provider-resilience.mjs +1 -356
- package/provider.mjs +1 -133
- package/providers.mjs +1 -491
- package/publish-guard.mjs +2 -0
- package/publish-manifest.json +129 -0
- package/question-response.mjs +1 -58
- package/reap-terminal.mjs +1 -68
- package/recap.mjs +1 -297
- package/replay-transport.mjs +1 -64
- package/repo-search.mjs +1 -190
- package/review-check.mjs +1 -182
- package/runtime-contract.mjs +1 -93
- package/runtime-registry.mjs +1 -64
- package/runtime-session.mjs +1 -20
- package/scheduled-run-admission.mjs +1 -364
- package/scheduled-runs.mjs +1 -268
- package/sdk-admission.mjs +1 -9
- package/sdk-smoke.mjs +1 -61
- package/serve-consent.mjs +1 -118
- package/serve-dir.mjs +1 -40
- package/service.mjs +1 -877
- package/session-store.mjs +1 -484
- package/side-lane.mjs +1 -63
- package/supabase-key.mjs +1 -176
- package/supervisor-ready.mjs +1 -57
- package/switch-provider.mjs +1 -84
- package/terminal-name.mjs +1 -359
- package/terminal-row-reconcile.mjs +1 -70
- package/thinkpool-prompt-contracts.mjs +1 -85
- package/thinkpool-room-prompt.mjs +1 -187
- package/transcript-sanitize.mjs +1 -332
- package/turn-stall.mjs +1 -61
- package/update-gate.mjs +1 -53
- package/viewport.mjs +1 -810
- package/worker-completion.mjs +1 -57
package/byok-detect.mjs
CHANGED
|
@@ -1,126 +1 @@
|
|
|
1
|
-
|
|
2
|
-
byok-detect — "paste a key → pick a model" for the bridge menu.
|
|
3
|
-
ThinkPool Code is structured-only (Anthropic Messages API). That format
|
|
4
|
-
has become the de-facto standard for agentic coding: Anthropic, Z.ai/GLM,
|
|
5
|
-
DeepSeek, Moonshot/Kimi and MiniMax all serve it natively (each base
|
|
6
|
-
below live-probed 2026-07-10: POST <base>/v1/messages → 401 auth error,
|
|
7
|
-
i.e. the path exists), and LM Studio / llama.cpp serve it on localhost.
|
|
8
|
-
The holdouts are OpenAI + Google — those need a translation gateway
|
|
9
|
-
(LiteLLM etc.). NOTE OpenRouter's native /v1/messages serves ANTHROPIC
|
|
10
|
-
MODELS ONLY (live-probed 2026-07-09, see src/lib/providers.js) — it is
|
|
11
|
-
not a GPT/Gemini path, despite what this file used to claim.
|
|
12
|
-
A bare OpenAI/Gemini/Groq key is DETECTED so we can guide the user to
|
|
13
|
-
a gateway instead of failing silently.
|
|
14
|
-
Spec: docs/specs/2026-06-28-byok-only-two-tier-pivot.md (addendum)
|
|
15
|
-
───────────────────────────────────────────────────────────── */
|
|
16
|
-
|
|
17
|
-
// Providers whose endpoint speaks the Anthropic Messages API → usable directly
|
|
18
|
-
// in structured mode. `base` is what we set as ANTHROPIC_BASE_URL; `models` is
|
|
19
|
-
// the model-list endpoint; `auth` is how the model-list call authenticates.
|
|
20
|
-
// A wrong/moved `models` URL degrades gracefully — fetchModels() returns []
|
|
21
|
-
// and the menu falls back to a free-text model prompt.
|
|
22
|
-
export const ANTHROPIC_COMPATIBLE = {
|
|
23
|
-
anthropic: {
|
|
24
|
-
name: 'Anthropic',
|
|
25
|
-
base: 'https://api.anthropic.com',
|
|
26
|
-
models: 'https://api.anthropic.com/v1/models',
|
|
27
|
-
auth: 'x-api-key',
|
|
28
|
-
},
|
|
29
|
-
openrouter: {
|
|
30
|
-
name: 'OpenRouter (Anthropic models)',
|
|
31
|
-
base: 'https://openrouter.ai/api',
|
|
32
|
-
models: 'https://openrouter.ai/api/v1/models',
|
|
33
|
-
auth: 'bearer',
|
|
34
|
-
},
|
|
35
|
-
zai: {
|
|
36
|
-
name: 'Z.ai — GLM',
|
|
37
|
-
base: 'https://api.z.ai/api/anthropic',
|
|
38
|
-
models: 'https://api.z.ai/api/paas/v4/models',
|
|
39
|
-
auth: 'bearer',
|
|
40
|
-
},
|
|
41
|
-
deepseek: {
|
|
42
|
-
name: 'DeepSeek',
|
|
43
|
-
base: 'https://api.deepseek.com/anthropic',
|
|
44
|
-
models: 'https://api.deepseek.com/models',
|
|
45
|
-
auth: 'bearer',
|
|
46
|
-
},
|
|
47
|
-
moonshot: {
|
|
48
|
-
name: 'Moonshot — Kimi',
|
|
49
|
-
base: 'https://api.moonshot.ai/anthropic',
|
|
50
|
-
models: 'https://api.moonshot.ai/v1/models',
|
|
51
|
-
auth: 'bearer',
|
|
52
|
-
},
|
|
53
|
-
minimax: {
|
|
54
|
-
name: 'MiniMax',
|
|
55
|
-
base: 'https://api.minimax.io/anthropic',
|
|
56
|
-
models: 'https://api.minimax.io/v1/models',
|
|
57
|
-
auth: 'bearer',
|
|
58
|
-
},
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Key-prefix → provider. `compatible: true` means it works directly; false
|
|
62
|
-
// means we detected it but it needs a gateway (different wire format).
|
|
63
|
-
// Keep the most specific prefixes first (sk-ant- / sk-or- before sk-).
|
|
64
|
-
// Undetectable-by-prefix but directly compatible: DeepSeek + Moonshot keys are
|
|
65
|
-
// bare `sk-…` (indistinguishable from OpenAI — gatewayHint names the escape),
|
|
66
|
-
// Z.ai keys are `<hex>.<secret>` with no stable prefix. Those route via the
|
|
67
|
-
// dashboard's provider presets (src/lib/providers.js BRIDGE_PROVIDER_PRESETS)
|
|
68
|
-
// or the manual-endpoint path instead.
|
|
69
|
-
const PREFIXES = [
|
|
70
|
-
['sk-ant-', 'anthropic', true, 'Anthropic'],
|
|
71
|
-
['sk-or-', 'openrouter', true, 'OpenRouter'],
|
|
72
|
-
['AIza', 'google', false, 'Google Gemini'],
|
|
73
|
-
['gsk_', 'groq', false, 'Groq'],
|
|
74
|
-
['pplx-', 'perplexity', false, 'Perplexity'],
|
|
75
|
-
['xai-', 'xai', false, 'xAI (Grok)'],
|
|
76
|
-
['fw_', 'fireworks', false, 'Fireworks'],
|
|
77
|
-
['sk-', 'openai', false, 'OpenAI'], // generic sk- LAST (after sk-ant-/sk-or-)
|
|
78
|
-
]
|
|
79
|
-
|
|
80
|
-
// Detect the provider from a pasted key. Returns { id, name, compatible }.
|
|
81
|
-
export function detectProvider(key) {
|
|
82
|
-
const k = String(key || '').trim()
|
|
83
|
-
if (!k) return { id: 'unknown', name: 'unknown', compatible: false }
|
|
84
|
-
for (const [prefix, id, compatible, name] of PREFIXES) {
|
|
85
|
-
if (k.startsWith(prefix)) return { id, name, compatible }
|
|
86
|
-
}
|
|
87
|
-
return { id: 'unknown', name: 'unknown', compatible: false }
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Fetch the model-id list for an Anthropic-compatible provider. Handles both
|
|
91
|
-
// OpenAI-shape ({ data: [{ id }] }) and Google-shape ({ models: [{ name }] }).
|
|
92
|
-
// Returns [] on any failure (caller falls back to a free-text model prompt).
|
|
93
|
-
export async function fetchModels({ modelsUrl, key, auth }) {
|
|
94
|
-
const headers = auth === 'x-api-key'
|
|
95
|
-
? { 'x-api-key': key, 'anthropic-version': '2023-06-01' }
|
|
96
|
-
: { Authorization: `Bearer ${key}` }
|
|
97
|
-
const ctrl = new AbortController()
|
|
98
|
-
const timer = setTimeout(() => ctrl.abort(), 12_000)
|
|
99
|
-
try {
|
|
100
|
-
const r = await fetch(modelsUrl, { headers, signal: ctrl.signal, redirect: 'error' })
|
|
101
|
-
if (!r.ok) return []
|
|
102
|
-
const data = await r.json()
|
|
103
|
-
const raw = Array.isArray(data?.data) ? data.data
|
|
104
|
-
: Array.isArray(data?.models) ? data.models
|
|
105
|
-
: []
|
|
106
|
-
return raw
|
|
107
|
-
.map((m) => String(m.id || m.name || '').replace(/^models\//, ''))
|
|
108
|
-
.filter(Boolean)
|
|
109
|
-
} catch {
|
|
110
|
-
return []
|
|
111
|
-
} finally {
|
|
112
|
-
clearTimeout(timer)
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// The friendly message shown when a detected key isn't directly usable.
|
|
117
|
-
// Honest scope (2026-07-10): OpenRouter's native /v1/messages is Anthropic-
|
|
118
|
-
// models-only, so it is NOT the "any model" escape hatch for a GPT/Gemini key —
|
|
119
|
-
// a translation gateway is. And a bare sk- key might not be OpenAI at all:
|
|
120
|
-
// DeepSeek and Moonshot/Kimi keys share the prefix and DO work directly.
|
|
121
|
-
export function gatewayHint(name) {
|
|
122
|
-
const skAmbiguity = name === 'OpenAI'
|
|
123
|
-
? ' (If that key is actually DeepSeek or Moonshot/Kimi — they also start with sk- — it works directly: pick that provider in the dashboard’s LLM providers panel instead.)'
|
|
124
|
-
: ''
|
|
125
|
-
return `That key looks like ${name}. ThinkPool Code runs on the Anthropic Messages API — the format Claude, GLM, DeepSeek, Kimi, MiniMax and local models (LM Studio, llama.cpp) all speak natively — but that provider doesn't, so the key can't be used directly. Route it through your own gateway (e.g. LiteLLM) instead.${skAmbiguity}`
|
|
126
|
-
}
|
|
1
|
+
export const ANTHROPIC_COMPATIBLE={anthropic:{name:"Anthropic",base:"https://api.anthropic.com",models:"https://api.anthropic.com/v1/models",auth:"x-api-key"},openrouter:{name:"OpenRouter (Anthropic models)",base:"https://openrouter.ai/api",models:"https://openrouter.ai/api/v1/models",auth:"bearer"},zai:{name:"Z.ai — GLM",base:"https://api.z.ai/api/anthropic",models:"https://api.z.ai/api/paas/v4/models",auth:"bearer"},deepseek:{name:"DeepSeek",base:"https://api.deepseek.com/anthropic",models:"https://api.deepseek.com/models",auth:"bearer"},moonshot:{name:"Moonshot — Kimi",base:"https://api.moonshot.ai/anthropic",models:"https://api.moonshot.ai/v1/models",auth:"bearer"},minimax:{name:"MiniMax",base:"https://api.minimax.io/anthropic",models:"https://api.minimax.io/v1/models",auth:"bearer"}};const e=[["sk-ant-","anthropic",!0,"Anthropic"],["sk-or-","openrouter",!0,"OpenRouter"],["AIza","google",!1,"Google Gemini"],["gsk_","groq",!1,"Groq"],["pplx-","perplexity",!1,"Perplexity"],["xai-","xai",!1,"xAI (Grok)"],["fw_","fireworks",!1,"Fireworks"],["sk-","openai",!1,"OpenAI"]];export function detectProvider(t){const o=String(t||"").trim();if(!o)return{id:"unknown",name:"unknown",compatible:!1};for(const[t,a,i,r]of e)if(o.startsWith(t))return{id:a,name:r,compatible:i};return{id:"unknown",name:"unknown",compatible:!1}}export async function fetchModels({modelsUrl:e,key:t,auth:o}){const a="x-api-key"===o?{"x-api-key":t,"anthropic-version":"2023-06-01"}:{Authorization:`Bearer ${t}`},i=new AbortController,r=setTimeout(()=>i.abort(),12e3);try{const t=await fetch(e,{headers:a,signal:i.signal,redirect:"error"});if(!t.ok)return[];const o=await t.json();return(Array.isArray(o?.data)?o.data:Array.isArray(o?.models)?o.models:[]).map(e=>String(e.id||e.name||"").replace(/^models\//,"")).filter(Boolean)}catch{return[]}finally{clearTimeout(r)}}export function gatewayHint(e){return`That key looks like ${e}. ThinkPool Code runs on the Anthropic Messages API — the format Claude, GLM, DeepSeek, Kimi, MiniMax and local models (LM Studio, llama.cpp) all speak natively — but that provider doesn't, so the key can't be used directly. Route it through your own gateway (e.g. LiteLLM) instead.${"OpenAI"===e?" (If that key is actually DeepSeek or Moonshot/Kimi — they also start with sk- — it works directly: pick that provider in the dashboard’s LLM providers panel instead.)":""}`}
|
|
@@ -1,91 +1 @@
|
|
|
1
|
-
|
|
2
|
-
// contract. In particular, 2.1.206 advertises TUI/profile commands (`/agents`,
|
|
3
|
-
// `/config`, `/doctor`, …) which are not safe or meaningful in a shared room.
|
|
4
|
-
// Keep the room catalog deliberately small and evidence-based:
|
|
5
|
-
//
|
|
6
|
-
// 1. bridge-owned controls work through the existing room controls;
|
|
7
|
-
// 2. `/compact` is the one native lifecycle command proven on the streaming
|
|
8
|
-
// Agent SDK path; and
|
|
9
|
-
// 3. a discovered slash name is exposed only when the same init event calls it
|
|
10
|
-
// an installed Skill. Skills are structured prompt invocations, unlike
|
|
11
|
-
// Claude Code's interactive/profile command palette.
|
|
12
|
-
//
|
|
13
|
-
// This is also an explicit command matrix for the 2.1.206 probe. Everything
|
|
14
|
-
// outside the allow path is intentionally omitted; `CLAUDE_COMMAND_EXCLUSIONS`
|
|
15
|
-
// records the high-risk/interactive families so a later SDK change cannot turn
|
|
16
|
-
// discovery into accidental exposure.
|
|
17
|
-
|
|
18
|
-
const cleanName = (value) => {
|
|
19
|
-
const name = String(typeof value === 'object' ? value?.name : value || '')
|
|
20
|
-
.trim()
|
|
21
|
-
.replace(/^\/+/, '')
|
|
22
|
-
return /^[A-Za-z0-9][A-Za-z0-9:_-]*$/.test(name) ? name : ''
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const stringMeta = (value) => {
|
|
26
|
-
if (!value || typeof value !== 'object') return {}
|
|
27
|
-
const description = String(value.description || '').trim()
|
|
28
|
-
const inputHint = String(value.inputHint || value.input_hint || value.input?.hint || '').trim()
|
|
29
|
-
return {
|
|
30
|
-
...(description ? { description } : {}),
|
|
31
|
-
...(inputHint ? { inputHint } : {}),
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const CLAUDE_COMMAND_MATRIX = Object.freeze({
|
|
36
|
-
'/clear': Object.freeze({ description: 'clear context · confirms', owner: 'bridge-control' }),
|
|
37
|
-
'/compact': Object.freeze({ description: 'compact context', owner: 'sdk-lifecycle' }),
|
|
38
|
-
'/model': Object.freeze({ description: 'pick model — opens selector', owner: 'bridge-control' }),
|
|
39
|
-
'/usage': Object.freeze({ description: 'session usage and provider limits', owner: 'bridge-control' }),
|
|
40
|
-
'<installed-skill>': Object.freeze({ description: 'run an installed Claude skill', owner: 'sdk-skill' }),
|
|
41
|
-
})
|
|
42
|
-
|
|
43
|
-
// Exclusions are grouped by why the room cannot safely implement them. This
|
|
44
|
-
// is intentionally a deny-list *and* a default-deny catalog: unknown future
|
|
45
|
-
// slash names stay hidden until they have an explicit structured contract.
|
|
46
|
-
export const CLAUDE_COMMAND_EXCLUSIONS = Object.freeze({
|
|
47
|
-
profileOrIdentity: Object.freeze(['agents', 'color', 'config', 'rename', 'team-onboarding']),
|
|
48
|
-
credentialsOrUpdates: Object.freeze(['claude-api', 'mcp', 'update-config']),
|
|
49
|
-
diagnosticsOrUpload: Object.freeze(['debug', 'doctor', 'heapdump', 'insights']),
|
|
50
|
-
hiddenAgentOrAutomation: Object.freeze(['__remote-workflow', 'batch', 'code-review', 'loop', 'review', 'schedule', 'security-review']),
|
|
51
|
-
unsafeInteractive: Object.freeze(['design', 'design-consent', 'design-revoke', 'fast', 'fewer-permission-prompts', 'goal', 'init', 'recap', 'reload-skills', 'run']),
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
const EXCLUDED = new Set(Object.values(CLAUDE_COMMAND_EXCLUSIONS).flat())
|
|
55
|
-
const BRIDGE_CONTROLS = new Set(['clear', 'compact', 'model', 'usage'])
|
|
56
|
-
|
|
57
|
-
// Convert Claude's string-only 2.1.206 payload (and a future object-shaped
|
|
58
|
-
// payload) into the metadata contract shared by all structured runtimes. An
|
|
59
|
-
// argument-bearing future skill retains its description and input hint; no
|
|
60
|
-
// argument command is silently advertised as a one-tap action.
|
|
61
|
-
export function normalizeClaudeCommandCatalog({ slashCommands, skills } = {}) {
|
|
62
|
-
const advertised = Array.isArray(slashCommands) ? slashCommands : []
|
|
63
|
-
const installedSkills = new Set((Array.isArray(skills) ? skills : []).map(cleanName).filter(Boolean))
|
|
64
|
-
const byName = new Map()
|
|
65
|
-
|
|
66
|
-
for (const command of advertised) {
|
|
67
|
-
const name = cleanName(command)
|
|
68
|
-
if (!name || EXCLUDED.has(name)) continue
|
|
69
|
-
const allowed = BRIDGE_CONTROLS.has(name) || installedSkills.has(name)
|
|
70
|
-
if (!allowed || byName.has(name)) continue
|
|
71
|
-
const canonical = CLAUDE_COMMAND_MATRIX[`/${name}`]
|
|
72
|
-
const supplied = stringMeta(command)
|
|
73
|
-
byName.set(name, {
|
|
74
|
-
name: `/${name}`,
|
|
75
|
-
description: supplied.description || canonical?.description || `Run installed Claude skill: /${name}`,
|
|
76
|
-
...(supplied.inputHint ? { inputHint: supplied.inputHint } : {}),
|
|
77
|
-
})
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// Room controls remain available on older SDK init shapes that omit the raw
|
|
81
|
-
// slash list. They are ordered first because they have bridge support.
|
|
82
|
-
const controls = ['clear', 'compact', 'model', 'usage'].map((name) => byName.get(name) || ({
|
|
83
|
-
name: `/${name}`,
|
|
84
|
-
description: CLAUDE_COMMAND_MATRIX[`/${name}`].description,
|
|
85
|
-
}))
|
|
86
|
-
const skillsOnly = [...byName.entries()]
|
|
87
|
-
.filter(([name]) => !BRIDGE_CONTROLS.has(name))
|
|
88
|
-
.sort(([a], [b]) => a.localeCompare(b))
|
|
89
|
-
.map(([, command]) => command)
|
|
90
|
-
return [...controls, ...skillsOnly]
|
|
91
|
-
}
|
|
1
|
+
const e=e=>{const t=String("object"==typeof e?e?.name:e||"").trim().replace(/^\/+/,"");return/^[A-Za-z0-9][A-Za-z0-9:_-]*$/.test(t)?t:""},t=e=>{if(!e||"object"!=typeof e)return{};const t=String(e.description||"").trim(),n=String(e.inputHint||e.input_hint||e.input?.hint||"").trim();return{...t?{description:t}:{},...n?{inputHint:n}:{}}};export const CLAUDE_COMMAND_MATRIX=Object.freeze({"/clear":Object.freeze({description:"clear context · confirms",owner:"bridge-control"}),"/compact":Object.freeze({description:"compact context",owner:"sdk-lifecycle"}),"/model":Object.freeze({description:"pick model — opens selector",owner:"bridge-control"}),"/usage":Object.freeze({description:"session usage and provider limits",owner:"bridge-control"}),"<installed-skill>":Object.freeze({description:"run an installed Claude skill",owner:"sdk-skill"})});export const CLAUDE_COMMAND_EXCLUSIONS=Object.freeze({profileOrIdentity:Object.freeze(["agents","color","config","rename","team-onboarding"]),credentialsOrUpdates:Object.freeze(["claude-api","mcp","update-config"]),diagnosticsOrUpload:Object.freeze(["debug","doctor","heapdump","insights"]),hiddenAgentOrAutomation:Object.freeze(["__remote-workflow","batch","code-review","loop","review","schedule","security-review"]),unsafeInteractive:Object.freeze(["design","design-consent","design-revoke","fast","fewer-permission-prompts","goal","init","recap","reload-skills","run"])});const n=new Set(Object.values(CLAUDE_COMMAND_EXCLUSIONS).flat()),r=new Set(["clear","compact","model","usage"]);export function normalizeClaudeCommandCatalog({slashCommands:i,skills:o}={}){const c=Array.isArray(i)?i:[],s=new Set((Array.isArray(o)?o:[]).map(e).filter(Boolean)),a=new Map;for(const i of c){const o=e(i);if(!o||n.has(o))continue;if(!r.has(o)&&!s.has(o)||a.has(o))continue;const c=CLAUDE_COMMAND_MATRIX[`/${o}`],l=t(i);a.set(o,{name:`/${o}`,description:l.description||c?.description||`Run installed Claude skill: /${o}`,...l.inputHint?{inputHint:l.inputHint}:{}})}return[...["clear","compact","model","usage"].map(e=>a.get(e)||{name:`/${e}`,description:CLAUDE_COMMAND_MATRIX[`/${e}`].description}),...[...a.entries()].filter(([e])=>!r.has(e)).sort(([e],[t])=>e.localeCompare(t)).map(([,e])=>e)]}
|