@turmind/halo 1.4.6 → 1.5.1-alpha
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/README.md +0 -1
- package/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/160.c52d3d6cf7bc8286.js +1 -0
- package/admin-out/_next/static/chunks/220.e250bbbf65d24094.js +1 -0
- package/admin-out/_next/static/chunks/362.a0c58d3bf9b1300b.js +1 -0
- package/admin-out/_next/static/chunks/449.c4b881b9ebdc556e.js +1 -0
- package/admin-out/_next/static/chunks/613.fb09e55e0a61d3fe.js +1 -0
- package/admin-out/_next/static/chunks/73.05abce37d312e880.js +1 -0
- package/admin-out/_next/static/chunks/803-7128009ee0e1c10e.js +1 -0
- package/admin-out/_next/static/chunks/839.a2729fd33013d763.js +1 -0
- package/admin-out/_next/static/chunks/868.bbb91afd48c9eb58.js +1 -0
- package/admin-out/_next/static/chunks/892.a35118e09d8d8efd.js +1 -0
- package/admin-out/_next/static/chunks/989-7420ee650083df43.js +1 -0
- package/admin-out/_next/static/chunks/app/page-fa5e935dbaa74165.js +1 -0
- package/admin-out/_next/static/chunks/webpack-1a264efd965db7ab.js +1 -0
- package/admin-out/_next/static/css/b8ffb5202b5a6619.css +3 -0
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +5 -5
- package/bundled-docs/design/agent.md +8 -7
- package/bundled-docs/design/architecture.md +9 -5
- package/bundled-docs/design/canvas-extensions.md +183 -0
- package/bundled-docs/design/cron.md +1 -1
- package/bundled-docs/design/express-self.md +9 -7
- package/bundled-docs/design/feishu.md +3 -1
- package/bundled-docs/design/observability.md +2 -0
- package/bundled-docs/design/prompt-system.md +6 -10
- package/bundled-docs/design/relay.md +22 -16
- package/bundled-docs/design/session.md +38 -26
- package/bundled-docs/design/slack.md +2 -2
- package/bundled-docs/design/storage.md +5 -5
- package/bundled-docs/design/telegram.md +4 -2
- package/bundled-docs/design/wechat.md +7 -5
- package/bundled-docs/design/wecom.md +2 -2
- package/bundled-docs/design/ws.md +29 -22
- package/bundled-docs/dev/add-model-provider.md +21 -18
- package/bundled-docs/dev/api.md +25 -24
- package/bundled-docs/dev/deploy.md +39 -9
- package/bundled-docs/dev/desktop-packaging.md +18 -8
- package/bundled-docs/dev/env.md +2 -3
- package/bundled-docs/dev/previews.md +9 -1
- package/bundled-docs/dev/tools.md +17 -82
- package/bundled-docs/guide/channels/wechat.md +1 -1
- package/bundled-docs/guide/chat.md +4 -2
- package/bundled-docs/guide/cli.md +0 -1
- package/bundled-docs/guide/delegation-and-access.md +1 -2
- package/bundled-docs/guide/workspace.md +11 -0
- package/bundled-docs/requirements/chat.md +11 -8
- package/bundled-docs/requirements/command.md +1 -12
- package/bundled-docs/requirements/editor.md +10 -0
- package/bundled-docs/requirements/settings.md +9 -0
- package/dist/index.js +2168 -1199
- package/package.json +2 -2
- package/templates/agents/deep-executor/agent.yaml +0 -3
- package/templates/agents/default/AGENT.md +0 -17
- package/templates/agents/default/agent.yaml +0 -1
- package/templates/agents/executor/agent.yaml +1 -1
- package/templates/models/aws-bedrock-claude-invoke.yaml +31 -0
- package/templates/models/aws-bedrock-mantle.yaml +42 -7
- package/templates/models/aws-bedrock-openai.yaml +53 -17
- package/templates/prompts/root/DELEGATION.md +58 -0
- package/templates/skills/extension/SKILL.md +70 -0
- package/templates/skills/extension/templates/ext.sh +112 -0
- package/templates/skills/halo/SKILL.md +3 -0
- package/templates/skills/send-file/SKILL.md +1 -1
- package/admin-out/_next/static/chunks/220.1ed70c874686122f.js +0 -1
- package/admin-out/_next/static/chunks/23-092ac3901411582e.js +0 -1
- package/admin-out/_next/static/chunks/362.5970ef15ec3d7b15.js +0 -1
- package/admin-out/_next/static/chunks/449.a403f7ad18054e3f.js +0 -1
- package/admin-out/_next/static/chunks/613.f314fc12e05a566c.js +0 -1
- package/admin-out/_next/static/chunks/73.a4617a551a8e176c.js +0 -1
- package/admin-out/_next/static/chunks/767.16a0b33b6f5e7965.js +0 -1
- package/admin-out/_next/static/chunks/839.e381287756453ffe.js +0 -1
- package/admin-out/_next/static/chunks/868.cc7fd84c9f2fd711.js +0 -1
- package/admin-out/_next/static/chunks/892.92b2ed455683b49a.js +0 -1
- package/admin-out/_next/static/chunks/989-6a0ec35b8ae2cb39.js +0 -1
- package/admin-out/_next/static/chunks/app/page-bf9c0b21ae431c92.js +0 -1
- package/admin-out/_next/static/chunks/webpack-ca926228f8cba1ff.js +0 -1
- package/admin-out/_next/static/css/c0ea31cd787f7aa7.css +0 -3
- package/bundled-docs/design/goal-mode.md +0 -144
- /package/admin-out/_next/static/{qYSILjqBjfgTggO0T8E7T → gRsZxPP4kTOmCtkHhJIZB}/_buildManifest.js +0 -0
- /package/admin-out/_next/static/{qYSILjqBjfgTggO0T8E7T → gRsZxPP4kTOmCtkHhJIZB}/_ssgManifest.js +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@turmind/halo",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.1-alpha",
|
|
4
4
|
"description": "Halo — multi-agent collaborative workspace. CLI + TUI + HTTP/WS server in one package.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"@aws-crypto/sha256-js": "^5.2.0",
|
|
21
|
-
"@aws-sdk/client-bedrock-runtime": "^3.
|
|
21
|
+
"@aws-sdk/client-bedrock-runtime": "^3.1142.0",
|
|
22
22
|
"@aws-sdk/credential-provider-node": "^3.972.30",
|
|
23
23
|
"@hono/node-server": "^1.19.17",
|
|
24
24
|
"@larksuiteoapi/node-sdk": "^1.65.0",
|
|
@@ -13,9 +13,6 @@ context:
|
|
|
13
13
|
compressAt: 0.8
|
|
14
14
|
priority: 40
|
|
15
15
|
tools:
|
|
16
|
-
# `draft` matches this agent's draft-critique-revise persona (AGENT.md
|
|
17
|
-
# "What deep means here") — deliberate, unlike executor which omits it.
|
|
18
|
-
- draft
|
|
19
16
|
- file_read
|
|
20
17
|
- file_write
|
|
21
18
|
- file_edit
|
|
@@ -23,23 +23,6 @@ useful. Don't reply off the cuff on questions that deserve care.
|
|
|
23
23
|
one.) The agents you can reach are exactly the ones in the team roster
|
|
24
24
|
in your system prompt.
|
|
25
25
|
|
|
26
|
-
## Briefing sub-agents
|
|
27
|
-
|
|
28
|
-
A sub-agent starts from zero context — your brief is all it knows, and
|
|
29
|
-
executors don't ask follow-up questions: under-specified corners become
|
|
30
|
-
their best guess. A good brief names:
|
|
31
|
-
|
|
32
|
-
- The deliverable and where it lives (paths, format), and what "done"
|
|
33
|
-
looks like — build passes? tests green? which ones?
|
|
34
|
-
- Boundaries, whenever they matter: files/dirs NOT to touch, whether
|
|
35
|
-
committing / pushing / installing / running builds is allowed, and any
|
|
36
|
-
in-flight work (yours or a parallel session's) it must not disturb.
|
|
37
|
-
- When fanning out in parallel, partition the file set — two sessions
|
|
38
|
-
editing the same files corrupt each other's work.
|
|
39
|
-
|
|
40
|
-
One task per session. Bundling unrelated asks into one brief gets you a
|
|
41
|
-
muddled summary and no way to retry one part alone.
|
|
42
|
-
|
|
43
26
|
## Talking to sub-agents
|
|
44
27
|
|
|
45
28
|
When you start a sub-session, one sentence — "Asked X to do Y" — usually
|
|
@@ -2,7 +2,7 @@ name: Executor
|
|
|
2
2
|
description: Workhorse for self-contained, well-specified tasks that would otherwise eat the parent's context — multi-file edits with a clear spec, batch shell chains, build/test loops, research across many web fetches. Takes a brief, executes end-to-end, returns a summary. Does not delegate further. Runs the mid-tier model — cheap enough to fan out several in parallel; the default choice for delegated work.
|
|
3
3
|
model:
|
|
4
4
|
provider: aws-bedrock-claude-invoke
|
|
5
|
-
id: global.anthropic.claude-sonnet-5
|
|
5
|
+
id: global.anthropic.claude-sonnet-5-5
|
|
6
6
|
endpoint: https://bedrock-runtime.us-east-1.amazonaws.com
|
|
7
7
|
promptCaching: 1h
|
|
8
8
|
thinking:
|
|
@@ -145,6 +145,37 @@ models:
|
|
|
145
145
|
- { value: xhigh, label: XHigh }
|
|
146
146
|
- { value: max, label: Max }
|
|
147
147
|
|
|
148
|
+
- id: global.anthropic.claude-sonnet-5-5
|
|
149
|
+
displayName: Claude Sonnet 5.5
|
|
150
|
+
maxOutputTokens: 64000
|
|
151
|
+
contextWindow: 1000000
|
|
152
|
+
capabilities:
|
|
153
|
+
image: true
|
|
154
|
+
video: false
|
|
155
|
+
audio: false
|
|
156
|
+
promptCaching:
|
|
157
|
+
default: 1h
|
|
158
|
+
ttlPresets:
|
|
159
|
+
- { value: 5m, label: 5min }
|
|
160
|
+
- { value: 1h, label: 1hour }
|
|
161
|
+
thinking:
|
|
162
|
+
# Sonnet 5.5 (Bedrock GA 2026-09-28; global profile only, no us.).
|
|
163
|
+
# Live-probed 2026-09-29 on invoke: invalid-value probe lists
|
|
164
|
+
# low / medium / high / xhigh / max; max_tokens ceiling 128000
|
|
165
|
+
# (maxOutputTokens kept at Sonnet 5's 64000); smoke call (xhigh,
|
|
166
|
+
# tool_use round trip) returned normally. Adaptive thinking
|
|
167
|
+
# always-on (type disabled / enabled both rejected); image input
|
|
168
|
+
# verified. Model card: 1M context.
|
|
169
|
+
mode: adaptive
|
|
170
|
+
defaultEnabled: true
|
|
171
|
+
default: high
|
|
172
|
+
effortPresets:
|
|
173
|
+
- { value: low, label: Low }
|
|
174
|
+
- { value: medium, label: Medium }
|
|
175
|
+
- { value: high, label: High }
|
|
176
|
+
- { value: xhigh, label: XHigh }
|
|
177
|
+
- { value: max, label: Max }
|
|
178
|
+
|
|
148
179
|
- id: global.anthropic.claude-opus-4-6-v1
|
|
149
180
|
displayName: Claude Opus 4.6
|
|
150
181
|
maxOutputTokens: 128000
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
id: aws-bedrock-mantle
|
|
2
|
-
displayName: AWS Bedrock Mantle (OpenAI GPT-6 / 5.6)
|
|
3
|
-
displayName_zh: AWS Bedrock Mantle(OpenAI GPT-6 / 5.6)
|
|
4
|
-
description: OpenAI GPT-6 (Astra / Sol / Luna) and GPT-5.6 (Sol / Terra / Luna) on Amazon Bedrock via the bedrock-mantle endpoint (OpenAI Responses API only — not Converse/InvokeModel). Region-split — GPT-6 Sol / Luna are on us-east-1 only, Astra on us-west-2 only.
|
|
5
|
-
description_zh: 通过 Bedrock Mantle 端点调用 OpenAI GPT-6(Astra / Sol / Luna)与 GPT-5.6(Sol / Terra / Luna)(仅 OpenAI Responses API,不支持 Converse/InvokeModel)。按区域分布:GPT-6 Sol / Luna 仅 us-east-1,Astra 仅 us-west-2。
|
|
2
|
+
displayName: AWS Bedrock Mantle (OpenAI GPT-6.1 / 6 / 5.6)
|
|
3
|
+
displayName_zh: AWS Bedrock Mantle(OpenAI GPT-6.1 / 6 / 5.6)
|
|
4
|
+
description: OpenAI GPT-6.1 Sol, GPT-6 (Astra / Sol / Luna) and GPT-5.6 (Sol / Terra / Luna) on Amazon Bedrock via the bedrock-mantle endpoint (OpenAI Responses API only — not Converse/InvokeModel). Region-split — GPT-6.1 Sol and GPT-6 Sol / Luna are on us-east-1 only, Astra on us-west-2 only.
|
|
5
|
+
description_zh: 通过 Bedrock Mantle 端点调用 OpenAI GPT-6.1 Sol、GPT-6(Astra / Sol / Luna)与 GPT-5.6(Sol / Terra / Luna)(仅 OpenAI Responses API,不支持 Converse/InvokeModel)。按区域分布:GPT-6.1 Sol 与 GPT-6 Sol / Luna 仅 us-east-1,Astra 仅 us-west-2。
|
|
6
6
|
# Mantle is a distinct endpoint from bedrock-runtime; the OpenAI surface lives
|
|
7
|
-
# under /openai/v1. Region split (live-probed 2026-09-24,
|
|
8
|
-
# endpoint):
|
|
7
|
+
# under /openai/v1. Region split (live-probed 2026-09-24, gpt-6.1-sol
|
|
8
|
+
# 2026-09-30; 404 on the wrong endpoint):
|
|
9
9
|
#
|
|
10
10
|
# us-east-1 us-east-2 us-west-2
|
|
11
11
|
# gpt-6-astra - - ✓
|
|
12
12
|
# gpt-6-sol ✓ - -
|
|
13
13
|
# gpt-6-luna ✓ - -
|
|
14
|
+
# gpt-6.1-sol ✓ - -
|
|
14
15
|
# gpt-5.6-sol ✓ ✓ -
|
|
15
16
|
# gpt-5.6-terra ✓ ✓ ✓
|
|
16
17
|
# gpt-5.6-luna ✓ ✓ ✓
|
|
@@ -19,7 +20,7 @@ description_zh: 通过 Bedrock Mantle 端点调用 OpenAI GPT-6(Astra / Sol /
|
|
|
19
20
|
# us-east-2 configs (5.6-era) keep working; Astra users pick us-west-2 in the
|
|
20
21
|
# agent form. The endpoint is a per-agent pick.
|
|
21
22
|
#
|
|
22
|
-
# The same
|
|
23
|
+
# The same seven models are also in aws-bedrock-openai.yaml (bedrock-runtime
|
|
23
24
|
# host, `global.openai.*` ids, no region split) — AWS's recommended endpoint
|
|
24
25
|
# for new agents. Stay here only for Mantle-only features (server-side
|
|
25
26
|
# web_search, background inference), which the web-search skill relies on.
|
|
@@ -138,6 +139,40 @@ models:
|
|
|
138
139
|
- { value: medium, label: Medium }
|
|
139
140
|
- { value: high, label: High }
|
|
140
141
|
|
|
142
|
+
# GPT-6.1 Sol (Bedrock GA 2026-09-29) — us-east-1 endpoint ONLY (404 on
|
|
143
|
+
# us-east-2 / us-west-2, live-probed 2026-09-30). reasoning.effort accepts
|
|
144
|
+
# low/medium/high/xhigh/max — `none` 400s, unlike GPT-6 Sol, so no "none"
|
|
145
|
+
# preset; text.verbosity low/medium/high; image input OK; 1,050,000 /
|
|
146
|
+
# 128,000 per the OpenAI model page.
|
|
147
|
+
- id: openai.gpt-6.1-sol
|
|
148
|
+
displayName: GPT-6.1 Sol
|
|
149
|
+
maxOutputTokens: 128000
|
|
150
|
+
contextWindow: 1050000
|
|
151
|
+
capabilities:
|
|
152
|
+
image: true
|
|
153
|
+
video: false
|
|
154
|
+
audio: false
|
|
155
|
+
promptCaching:
|
|
156
|
+
default: 5m
|
|
157
|
+
ttlPresets:
|
|
158
|
+
- { value: 5m, label: 5min }
|
|
159
|
+
thinking:
|
|
160
|
+
mode: adaptive
|
|
161
|
+
defaultEnabled: true
|
|
162
|
+
default: medium
|
|
163
|
+
effortPresets:
|
|
164
|
+
- { value: low, label: Low }
|
|
165
|
+
- { value: medium, label: Medium }
|
|
166
|
+
- { value: high, label: High }
|
|
167
|
+
- { value: xhigh, label: XHigh }
|
|
168
|
+
- { value: max, label: Max }
|
|
169
|
+
verbosity:
|
|
170
|
+
default: low
|
|
171
|
+
presets:
|
|
172
|
+
- { value: low, label: Low }
|
|
173
|
+
- { value: medium, label: Medium }
|
|
174
|
+
- { value: high, label: High }
|
|
175
|
+
|
|
141
176
|
- id: openai.gpt-6-luna
|
|
142
177
|
displayName: GPT-6 Luna
|
|
143
178
|
maxOutputTokens: 128000
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
id: aws-bedrock-openai
|
|
2
|
-
displayName: AWS Bedrock OpenAI-compatible (GPT-6 / 5.6 · Grok 4.6 · Kimi K3)
|
|
3
|
-
displayName_zh: AWS Bedrock OpenAI 兼容接口(GPT-6 / 5.6 · Grok 4.6 · Kimi K3)
|
|
4
|
-
description: Frontier models on Amazon Bedrock via the bedrock-runtime endpoint's OpenAI Responses API (/openai/v1) — OpenAI GPT-6 (Astra / Sol / Luna) and GPT-5.6 (Sol / Terra / Luna), xAI Grok 4.6, Moonshot Kimi K3. Cross-Region inference profiles (global.*) only — every region serves every model, no region split. No server-side web_search (that is Mantle-only).
|
|
5
|
-
description_zh: 通过 bedrock-runtime 端点的 OpenAI Responses API(/openai/v1)调用 Bedrock 上的前沿模型——OpenAI GPT-6(Astra / Sol / Luna)与 GPT-5.6(Sol / Terra / Luna)、xAI Grok 4.6、月之暗面 Kimi K3。仅支持跨区域推理 profile(global.*)——每个区域都能调所有模型,无区域分裂。不支持服务端 web_search(那是 Mantle 独有)。
|
|
2
|
+
displayName: AWS Bedrock OpenAI-compatible (GPT-6.1 / 6 / 5.6 · Grok 4.6 · Kimi K3)
|
|
3
|
+
displayName_zh: AWS Bedrock OpenAI 兼容接口(GPT-6.1 / 6 / 5.6 · Grok 4.6 · Kimi K3)
|
|
4
|
+
description: Frontier models on Amazon Bedrock via the bedrock-runtime endpoint's OpenAI Responses API (/openai/v1) — OpenAI GPT-6.1 Sol, GPT-6 (Astra / Sol / Luna) and GPT-5.6 (Sol / Terra / Luna), xAI Grok 4.6, Moonshot Kimi K3. Cross-Region inference profiles (global.*) only — every region serves every model, no region split. No server-side web_search (that is Mantle-only).
|
|
5
|
+
description_zh: 通过 bedrock-runtime 端点的 OpenAI Responses API(/openai/v1)调用 Bedrock 上的前沿模型——OpenAI GPT-6.1 Sol、GPT-6(Astra / Sol / Luna)与 GPT-5.6(Sol / Terra / Luna)、xAI Grok 4.6、月之暗面 Kimi K3。仅支持跨区域推理 profile(global.*)——每个区域都能调所有模型,无区域分裂。不支持服务端 web_search(那是 Mantle 独有)。
|
|
6
6
|
# Why a second Bedrock/OpenAI provider next to aws-bedrock-mantle: this is the
|
|
7
7
|
# bedrock-runtime host (https://bedrock-runtime.<region>.amazonaws.com/openai/v1),
|
|
8
8
|
# which AWS now recommends for new applications; bedrock-mantle is the legacy
|
|
@@ -12,10 +12,10 @@ description_zh: 通过 bedrock-runtime 端点的 OpenAI Responses API(/openai/
|
|
|
12
12
|
# the bare foundation-model id 400s with "on-demand throughput isn't
|
|
13
13
|
# supported". Kimi K3 isn't on Mantle at all; Grok 4.6 is Mantle us-west-2
|
|
14
14
|
# only — here everything is reachable from any region.
|
|
15
|
-
# - live-probed 2026-09-24 with SigV4: all
|
|
16
|
-
# 200 in us-east-1 / us-west-2 /
|
|
17
|
-
# endpoint is purely a latency /
|
|
18
|
-
# per-region GPT matrix.
|
|
15
|
+
# - live-probed 2026-09-24 with SigV4: all nine global.* ids below return
|
|
16
|
+
# 200 (gpt-6.1-sol probed 2026-09-30) in us-east-1 / us-west-2 /
|
|
17
|
+
# eu-west-1 / ap-northeast-1 alike, so the endpoint is purely a latency /
|
|
18
|
+
# data-residency pick — unlike Mantle's per-region GPT matrix.
|
|
19
19
|
# - requests are always synchronous and there are NO server-side tools:
|
|
20
20
|
# `tools:[{type:'web_search'}]` → 400 "web search is not supported for
|
|
21
21
|
# this request" (verified). MantleAgent never sends those, but the
|
|
@@ -51,18 +51,20 @@ secrets:
|
|
|
51
51
|
# which MantleAgent doesn't send) — the single 5m preset is a form hint only.
|
|
52
52
|
# - thinking: reasoning.effort. Turning Thinking off in the form omits the
|
|
53
53
|
# field (model default) — it does not send `none`. Good thing too: on this
|
|
54
|
-
# host GPT-6 Astra
|
|
54
|
+
# host GPT-6 Astra and GPT-6.1 Sol 400 on `none` while every other GPT
|
|
55
|
+
# accepts it.
|
|
55
56
|
# - Reasoning summaries are never surfaced (output[].reasoning.summary
|
|
56
57
|
# empty) — same as GPT on Mantle; reasoning_tokens > 0 proves it ran.
|
|
57
58
|
models:
|
|
58
|
-
# OpenAI GPT-6 / GPT-5.6 — the same
|
|
59
|
-
# (see that file for the per-model background:
|
|
60
|
-
# 272,000 / 64,000 for 5.6, 2x input price
|
|
61
|
-
# 2026-09-24 on this host with invalid-value
|
|
62
|
-
#
|
|
63
|
-
#
|
|
64
|
-
#
|
|
65
|
-
#
|
|
59
|
+
# OpenAI GPT-6.1 / GPT-6 / GPT-5.6 — the same seven models as
|
|
60
|
+
# aws-bedrock-mantle.yaml (see that file for the per-model background:
|
|
61
|
+
# 1,050,000 / 128,000 for GPT-6, 272,000 / 64,000 for 5.6, 2x input price
|
|
62
|
+
# past 272K). Live-probed 2026-09-24 on this host with invalid-value
|
|
63
|
+
# requests: every one (except GPT-6.1 Sol, below) lists reasoning.effort
|
|
64
|
+
# none/low/medium/high/xhigh/max in its own validation error and accepts
|
|
65
|
+
# text.verbosity low/medium/high — identical surface, so presets are copied
|
|
66
|
+
# verbatim. Pick these over the Mantle entries unless you need Mantle-only
|
|
67
|
+
# features (server-side web_search, background inference).
|
|
66
68
|
- id: global.openai.gpt-6-sol
|
|
67
69
|
displayName: GPT-6 Sol
|
|
68
70
|
maxOutputTokens: 128000
|
|
@@ -92,6 +94,40 @@ models:
|
|
|
92
94
|
- { value: medium, label: Medium }
|
|
93
95
|
- { value: high, label: High }
|
|
94
96
|
|
|
97
|
+
# GPT-6.1 Sol (Bedrock GA 2026-09-29). Live-probed 2026-09-30 on this host
|
|
98
|
+
# with SigV4: 200 from all four endpoint presets like the other global.* ids.
|
|
99
|
+
# reasoning.effort accepts low/medium/high/xhigh/max — `none` 400s, unlike
|
|
100
|
+
# GPT-6 Sol, so no "none" preset; text.verbosity low/medium/high; image input
|
|
101
|
+
# OK; 1,050,000 / 128,000 per the OpenAI model page.
|
|
102
|
+
- id: global.openai.gpt-6.1-sol
|
|
103
|
+
displayName: GPT-6.1 Sol
|
|
104
|
+
maxOutputTokens: 128000
|
|
105
|
+
contextWindow: 1050000
|
|
106
|
+
capabilities:
|
|
107
|
+
image: true
|
|
108
|
+
video: false
|
|
109
|
+
audio: false
|
|
110
|
+
promptCaching:
|
|
111
|
+
default: 5m
|
|
112
|
+
ttlPresets:
|
|
113
|
+
- { value: 5m, label: 5min }
|
|
114
|
+
thinking:
|
|
115
|
+
mode: adaptive
|
|
116
|
+
defaultEnabled: true
|
|
117
|
+
default: medium
|
|
118
|
+
effortPresets:
|
|
119
|
+
- { value: low, label: Low }
|
|
120
|
+
- { value: medium, label: Medium }
|
|
121
|
+
- { value: high, label: High }
|
|
122
|
+
- { value: xhigh, label: XHigh }
|
|
123
|
+
- { value: max, label: Max }
|
|
124
|
+
verbosity:
|
|
125
|
+
default: low
|
|
126
|
+
presets:
|
|
127
|
+
- { value: low, label: Low }
|
|
128
|
+
- { value: medium, label: Medium }
|
|
129
|
+
- { value: high, label: High }
|
|
130
|
+
|
|
95
131
|
- id: global.openai.gpt-6-astra
|
|
96
132
|
displayName: GPT-6 Astra
|
|
97
133
|
maxOutputTokens: 128000
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
## Delegation
|
|
2
|
+
|
|
3
|
+
This applies when your tools include `start_session`. The agents you can hand
|
|
4
|
+
work to are listed under "Your Team". Routing and size thresholds for this
|
|
5
|
+
workspace are in its INSTRUCTIONS; this section is what holds in any workspace.
|
|
6
|
+
|
|
7
|
+
A sub-session runs in parallel with your conversation and reports back when it
|
|
8
|
+
finishes. While you run tools, the user's messages can only be answered between
|
|
9
|
+
calls. Both choices cost something: a sub-session you didn't need costs a
|
|
10
|
+
brief to write and a report to read; work you kept costs the user's ability to
|
|
11
|
+
talk to you while you're busy, and fills your context with intermediate output.
|
|
12
|
+
|
|
13
|
+
### What tends to fit a sub-session
|
|
14
|
+
|
|
15
|
+
- The piece stands alone: it can be stated as a task with a checkable result.
|
|
16
|
+
- It can run alongside other pieces, or alongside your conversation with the user.
|
|
17
|
+
- Its working output (grep hits, file dumps, build logs) is large compared with
|
|
18
|
+
the answer you need back.
|
|
19
|
+
- It needs an edit → build/test → fix loop that you don't need to watch.
|
|
20
|
+
- A roster agent is set up for exactly this kind of work.
|
|
21
|
+
|
|
22
|
+
### What tends to fit doing it yourself
|
|
23
|
+
|
|
24
|
+
- It leans on this conversation: decisions the user made, options they ruled
|
|
25
|
+
out, constraints they mentioned in passing — and restating those in a brief
|
|
26
|
+
would take about as long as the work.
|
|
27
|
+
- It is small and its cause is already known.
|
|
28
|
+
- The user is waiting on an answer, or wants to steer step by step.
|
|
29
|
+
- Your next step depends on the result and there is nothing else to do meanwhile.
|
|
30
|
+
|
|
31
|
+
### Three checks before `start_session`
|
|
32
|
+
|
|
33
|
+
1. Could someone with no access to this chat do the task from the brief alone?
|
|
34
|
+
If the missing part can't be written in a few lines, do it yourself or ask
|
|
35
|
+
the user.
|
|
36
|
+
2. Does it need more than one edit-and-verify round, or more than a handful of
|
|
37
|
+
tool calls? If not, doing it yourself is usually cheaper.
|
|
38
|
+
3. Will the user want to talk to you in the meantime? If so, hand off the long
|
|
39
|
+
part and stay reachable.
|
|
40
|
+
|
|
41
|
+
### What a brief contains
|
|
42
|
+
|
|
43
|
+
The worker starts with only the brief and does not ask follow-ups. What the
|
|
44
|
+
brief leaves out, it explores or guesses.
|
|
45
|
+
|
|
46
|
+
- **Goal and deliverable**: what to produce, where it lives, what "done" means.
|
|
47
|
+
- **Decisions already made in this conversation**: the user's choices, rejected
|
|
48
|
+
options, and constraints. Quote the user's wording when it matters.
|
|
49
|
+
- **What you already know**: paths, line numbers, snippets, the pattern to copy.
|
|
50
|
+
Findings, not pointers.
|
|
51
|
+
- **Boundaries**: files not to touch; whether commit / push / build / deploy is
|
|
52
|
+
allowed; in-flight work it must not disturb.
|
|
53
|
+
- **Verification**: the exact commands, scoped to what changed.
|
|
54
|
+
- **What it need not read or redo.**
|
|
55
|
+
|
|
56
|
+
One task per session. When fanning out, partition by file so parallel sessions
|
|
57
|
+
don't edit the same ones. For a follow-up or a fix from the same worker,
|
|
58
|
+
`query_session` continues it with its context intact.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: extension
|
|
3
|
+
description: Install / list / remove admin preview extensions (`~/.halo/global/extensions/<id>/`) — static viewers the admin editor loads for file types it has no built-in preview for (e.g. `.glb`). `/extension install <id|zip|url>` pulls the latest `<id>-v*` release from turmind/halo-hub by default. Activate when the user wants to preview a file type the editor can't open, or asks to install / update / remove an extension.
|
|
4
|
+
command: /extension
|
|
5
|
+
requiresAccess: full
|
|
6
|
+
verbs:
|
|
7
|
+
- { name: install, desc: "Install or upgrade an extension from halo-hub (by id), a local zip path, or a zip URL" }
|
|
8
|
+
- { name: list, desc: List installed extensions with version and status }
|
|
9
|
+
- { name: remove, desc: Remove an installed extension by id }
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# extension
|
|
13
|
+
|
|
14
|
+
The requested action is **`$1`**; the rest of the line is the payload. With
|
|
15
|
+
natural language ("install the glb viewer"), infer both.
|
|
16
|
+
|
|
17
|
+
Preview extensions are static bundles the admin editor loads in a sandboxed
|
|
18
|
+
iframe to preview file types it has no built-in viewer for (e.g. `.glb`).
|
|
19
|
+
Installing = putting a validated directory under `~/.halo/global/extensions/<id>/`;
|
|
20
|
+
the server watches that directory and pushes the change to every open admin —
|
|
21
|
+
**no restart, no page reload**.
|
|
22
|
+
|
|
23
|
+
The helper is `templates/ext.sh` in this skill's directory — the workspace copy
|
|
24
|
+
wins if it exists, else the global one:
|
|
25
|
+
|
|
26
|
+
- `<workspace>/.halo/skills/extension/templates/ext.sh`
|
|
27
|
+
- `~/.halo/global/skills/extension/templates/ext.sh`
|
|
28
|
+
|
|
29
|
+
Pick EXT = the first that exists, then:
|
|
30
|
+
|
|
31
|
+
## install
|
|
32
|
+
|
|
33
|
+
`bash EXT install <source>` where `<source>` is one of:
|
|
34
|
+
- an extension id (e.g. `glb`) → downloads the newest `glb-v*` release asset
|
|
35
|
+
(`glb-<version>.zip`) from https://github.com/turmind/halo-hub/releases;
|
|
36
|
+
- a local `.zip` path;
|
|
37
|
+
- an `https://…zip` URL.
|
|
38
|
+
|
|
39
|
+
The script unpacks to a temp dir, pre-checks `halo-extension.json` (id matches,
|
|
40
|
+
entry exists), then atomically replaces `~/.halo/global/extensions/<id>/`.
|
|
41
|
+
Reinstalling the same id upgrades (or downgrades) it. Relay the script's last
|
|
42
|
+
line to the user (`installed glb 1.0.0` / the error). Never edit files inside an
|
|
43
|
+
installed extension — reinstall instead.
|
|
44
|
+
|
|
45
|
+
If the download fails with "no release for <id>" the GitHub API may be
|
|
46
|
+
rate-limited (60 unauthenticated requests/hour) or the id may not exist: point
|
|
47
|
+
the user at https://github.com/turmind/halo-hub/releases to download the zip by
|
|
48
|
+
hand, then `install <path>`. Setting `GITHUB_TOKEN` in the environment lifts
|
|
49
|
+
the limit.
|
|
50
|
+
|
|
51
|
+
## list
|
|
52
|
+
|
|
53
|
+
`bash EXT list` → one line per extension: `<id>\t<version>\t<name>` or
|
|
54
|
+
`<id>\tERROR\t<reason>` for directories the server would reject. Relay as a
|
|
55
|
+
short `-` list; `(none)` when empty.
|
|
56
|
+
|
|
57
|
+
## remove
|
|
58
|
+
|
|
59
|
+
`bash EXT remove <id>` → deletes `~/.halo/global/extensions/<id>/`. Confirm with
|
|
60
|
+
the user first if they didn't name the id explicitly.
|
|
61
|
+
|
|
62
|
+
## Notes
|
|
63
|
+
|
|
64
|
+
- Extensions are global (all workspaces on this server). Say so if the user
|
|
65
|
+
asks "install it for this project".
|
|
66
|
+
- To find what's available, point the user at https://github.com/turmind/halo-hub
|
|
67
|
+
(the `extensions/` directory); do not scrape it.
|
|
68
|
+
- The script only pre-checks the required fields; the server's scanner is the
|
|
69
|
+
authority. A package it rejects shows up in `list` (and the admin) as
|
|
70
|
+
`ERROR` with the reason.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Install / list / remove admin preview extensions under ~/.halo/global/extensions/.
|
|
3
|
+
# The directory IS the install: the server watches the root and pushes changes
|
|
4
|
+
# to every open admin, so nothing here talks to the server. Validation
|
|
5
|
+
# authority is the server's scanner; this script only pre-checks the required
|
|
6
|
+
# fields so a broken package never replaces a working install.
|
|
7
|
+
#
|
|
8
|
+
# ext.sh install <id | path/to.zip | https://…zip>
|
|
9
|
+
# ext.sh list
|
|
10
|
+
# ext.sh remove <id>
|
|
11
|
+
#
|
|
12
|
+
# Needs curl + unzip + node. No `gh`: releases are read through the public API
|
|
13
|
+
# (GITHUB_TOKEN, if set, is sent to lift the 60 req/h anonymous limit).
|
|
14
|
+
set -euo pipefail
|
|
15
|
+
|
|
16
|
+
ROOT="$HOME/.halo/global/extensions"
|
|
17
|
+
REPO="turmind/halo-hub"
|
|
18
|
+
ID_RE='^[a-z0-9][a-z0-9_-]{0,63}$' # keep in sync with server extensions/registry.ts ID_RE
|
|
19
|
+
|
|
20
|
+
cmd=${1:?usage: ext.sh install <id|zip|url> | list | remove <id>}
|
|
21
|
+
shift || true
|
|
22
|
+
|
|
23
|
+
# Print `<id> <version> <name>` for the extension dir $1, or fail with the
|
|
24
|
+
# reason. $2 (optional) = the id the directory / request claims.
|
|
25
|
+
precheck() {
|
|
26
|
+
node -e '
|
|
27
|
+
const fs = require("fs"), dir = process.argv[1], expect = process.argv[2] || ""
|
|
28
|
+
const fail = (msg) => { console.log(msg); process.exit(1) }
|
|
29
|
+
let m
|
|
30
|
+
try { m = JSON.parse(fs.readFileSync(dir + "/halo-extension.json", "utf8")) } catch (e) { fail("halo-extension.json missing or invalid: " + e.message) }
|
|
31
|
+
for (const k of ["id", "name", "version", "extensions", "entry"]) if (!m[k]) fail("missing " + k)
|
|
32
|
+
if (!/^[a-z0-9][a-z0-9_-]{0,63}$/.test(m.id)) fail("bad id: " + m.id)
|
|
33
|
+
if (expect && m.id !== expect) fail("manifest id \"" + m.id + "\" != \"" + expect + "\"")
|
|
34
|
+
let isFile = false
|
|
35
|
+
try { isFile = fs.statSync(dir + "/" + m.entry).isFile() } catch {}
|
|
36
|
+
if (!isFile) fail("entry not found: " + m.entry)
|
|
37
|
+
console.log(m.id + " " + m.version + " " + m.name)
|
|
38
|
+
' "$1" "${2:-}"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# Echo the path of a local zip for source $1 (path, https URL, or hub id).
|
|
42
|
+
resolve_source() {
|
|
43
|
+
local src=$1 url
|
|
44
|
+
if [[ -f $src ]]; then echo "$src"; return; fi
|
|
45
|
+
if [[ $src =~ ^https?:// ]]; then curl -fsSL "$src" -o "$TMP/pkg.zip"; echo "$TMP/pkg.zip"; return; fi
|
|
46
|
+
[[ $src =~ $ID_RE ]] || { echo "invalid id or missing file: $src" >&2; exit 1; }
|
|
47
|
+
# Newest non-draft, non-prerelease release tagged "<id>-v*" (API is newest-first).
|
|
48
|
+
url=$(curl -fsSL ${GITHUB_TOKEN:+-H "Authorization: Bearer $GITHUB_TOKEN"} \
|
|
49
|
+
"https://api.github.com/repos/$REPO/releases?per_page=100" \
|
|
50
|
+
| node -e '
|
|
51
|
+
let s = ""; process.stdin.on("data", (d) => s += d).on("end", () => {
|
|
52
|
+
const id = process.argv[1]
|
|
53
|
+
const r = JSON.parse(s).find((r) => r.tag_name.startsWith(id + "-v") && !r.draft && !r.prerelease)
|
|
54
|
+
const a = r && r.assets.find((a) => a.name.endsWith(".zip"))
|
|
55
|
+
if (!a) process.exit(2)
|
|
56
|
+
console.log(a.browser_download_url)
|
|
57
|
+
})' "$src") \
|
|
58
|
+
|| { echo "no release for $src in $REPO — download the zip from https://github.com/$REPO/releases and run: install <path>" >&2; exit 1; }
|
|
59
|
+
curl -fsSL "$url" -o "$TMP/pkg.zip"
|
|
60
|
+
echo "$TMP/pkg.zip"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
case $cmd in
|
|
64
|
+
install)
|
|
65
|
+
src=${1:?usage: ext.sh install <id|zip|url>}
|
|
66
|
+
TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT
|
|
67
|
+
zip=$(resolve_source "$src")
|
|
68
|
+
# Same refusals as the server's zip installer: no `..`, no absolute paths,
|
|
69
|
+
# no symlinks (zipinfo mode column starts with `l`).
|
|
70
|
+
if unzip -Z1 "$zip" | grep -Eq '(^|/)\.\.(/|$)|^/'; then echo "zip contains ../ or absolute entries" >&2; exit 1; fi
|
|
71
|
+
if unzip -Z "$zip" | grep -q '^l'; then echo "zip contains symlinks" >&2; exit 1; fi
|
|
72
|
+
mkdir -p "$TMP/x"
|
|
73
|
+
unzip -q "$zip" -d "$TMP/x"
|
|
74
|
+
# `zip -r glb.zip glb/` wraps everything in one directory — descend into it.
|
|
75
|
+
dir="$TMP/x"
|
|
76
|
+
if [[ ! -f $dir/halo-extension.json ]]; then
|
|
77
|
+
only=$(find "$dir" -mindepth 1 -maxdepth 1 | head -2)
|
|
78
|
+
if [[ $(printf '%s\n' "$only" | wc -l) -eq 1 && -f $only/halo-extension.json ]]; then dir=$only; fi
|
|
79
|
+
fi
|
|
80
|
+
expect=""
|
|
81
|
+
if [[ $src =~ $ID_RE && ! -f $src ]]; then expect=$src; fi
|
|
82
|
+
if ! out=$(precheck "$dir" "$expect"); then echo "invalid extension: $out" >&2; exit 1; fi
|
|
83
|
+
read -r id ver _ <<<"$out"
|
|
84
|
+
mkdir -p "$ROOT"
|
|
85
|
+
stage="$ROOT/.tmp-$id-$RANDOM$RANDOM"
|
|
86
|
+
mv "$dir" "$stage"
|
|
87
|
+
old=""
|
|
88
|
+
if [[ -d $ROOT/$id ]]; then old="$ROOT/.old-$id-$RANDOM$RANDOM"; mv "$ROOT/$id" "$old"; fi
|
|
89
|
+
mv "$stage" "$ROOT/$id" || { [[ -n $old ]] && mv "$old" "$ROOT/$id"; rm -rf "$stage"; exit 1; }
|
|
90
|
+
if [[ -n $old ]]; then rm -rf "$old"; fi
|
|
91
|
+
echo "installed $id $ver" ;;
|
|
92
|
+
list)
|
|
93
|
+
shopt -s nullglob
|
|
94
|
+
n=0
|
|
95
|
+
for d in "$ROOT"/*/; do
|
|
96
|
+
d=${d%/}; id=$(basename "$d"); n=$((n + 1))
|
|
97
|
+
if out=$(precheck "$d" "$id"); then
|
|
98
|
+
read -r _ ver name <<<"$out"; printf '%s\t%s\t%s\n' "$id" "$ver" "$name"
|
|
99
|
+
else
|
|
100
|
+
printf '%s\tERROR\t%s\n' "$id" "$(printf '%s' "$out" | head -1)"
|
|
101
|
+
fi
|
|
102
|
+
done
|
|
103
|
+
if [[ $n -eq 0 ]]; then echo "(none)"; fi ;;
|
|
104
|
+
remove)
|
|
105
|
+
id=${1:?usage: ext.sh remove <id>}
|
|
106
|
+
[[ $id =~ $ID_RE ]] || { echo "invalid id: $id" >&2; exit 1; }
|
|
107
|
+
[[ -d $ROOT/$id ]] || { echo "not installed: $id" >&2; exit 1; }
|
|
108
|
+
rm -rf "$ROOT/$id"
|
|
109
|
+
echo "removed $id" ;;
|
|
110
|
+
*)
|
|
111
|
+
echo "unknown command: $cmd (install | list | remove)" >&2; exit 1 ;;
|
|
112
|
+
esac
|
|
@@ -13,6 +13,7 @@ You are running inside **Halo**, a multi-agent collaboration workspace.
|
|
|
13
13
|
| Location | Scope | Purpose |
|
|
14
14
|
|----------|-------|---------|
|
|
15
15
|
| `~/.halo/global/` | Global (all projects) | User profile, global instructions, global agents & skills, system prompts, bundled docs |
|
|
16
|
+
| `~/.halo/global/extensions/<id>/` | Global (all projects) | Installed admin preview extensions (static viewers for file types the editor can't open, e.g. `.glb`); managed with the `extension` skill (`/extension install|list|remove`) |
|
|
16
17
|
| `<workspace>/.halo/` | Per-project | Project instructions, knowledge index, project agents & skills |
|
|
17
18
|
|
|
18
19
|
`.halo/` is excluded from `grep` and `glob`. Use `file_read` with the exact path to access files inside.
|
|
@@ -97,3 +98,5 @@ Questions outside these rows aren't in the bundled docs (backend internals, REST
|
|
|
97
98
|
## Skills
|
|
98
99
|
|
|
99
100
|
Skills are referenced by id from an agent's `agent.yaml`. The system prompt shows each skill's name + description; the full body is loaded on demand via `activate_skill`.
|
|
101
|
+
|
|
102
|
+
Admin preview extensions (`.glb` and other file types the editor has no built-in viewer for) are not skills — they are static bundles under `~/.halo/global/extensions/`; the `extension` skill installs / lists / removes them.
|
|
@@ -13,7 +13,7 @@ Multiple `MEDIA:` lines in one reply = multiple attachments.
|
|
|
13
13
|
|
|
14
14
|
- Marker must be alone on a line. No leading spaces, no inline text.
|
|
15
15
|
- Path must be absolute and the file must exist. Verify with `file_list` if unsure.
|
|
16
|
-
-
|
|
16
|
+
- Where the file may live depends on the channel account's access level. A full-access account may send any readable absolute path. A workspace / readonly account is limited to the current workspace directory or the OS temp dir (`/tmp` on Linux/macOS); any other path — including another workspace on the same server — is not sent, and the user sees a "⚠️ 文件上传失败 / delivery failed" message naming the file. If you are not full-access, copy the file into the workspace (e.g. `.halo/tmp/`) or `/tmp` first, then reference the copy.
|
|
17
17
|
- Write normal text around `MEDIA:` lines for context.
|
|
18
18
|
|
|
19
19
|
## Example
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[220],{10912:(e,t,n)=>{function r(e,t){let n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:"font-family:sans-serif;padding:40px;max-width:800px;margin:0 auto",r=window.open("","_blank");r&&(r.document.write("<!DOCTYPE html><html><head><title>".concat(e.replace(/[&<>"']/g,e=>({"&":"&","<":"<",">":">",'"':""","'":"'"})[e]),"</title><style>body{").concat(n,"}img{max-width:100%}</style></head><body>").concat(t,"</body></html>")),r.document.close(),r.onload=()=>{r.print()})}n.d(t,{H:()=>r})},37050:(e,t,n)=>{n.d(t,{I:()=>o,n:()=>s});var r=n(41440),l=n(48434),a=n(90302),i=n(17119);function s(e){let{name:t,downloadUrl:n,onOpenAsText:s,extraToolbar:c,loading:d,error:u,children:x}=e,h=(0,i.kj)();return(0,r.jsxs)("div",{className:"flex h-full flex-col bg-[var(--background)]",children:[(0,r.jsxs)("div",{className:"flex h-8 shrink-0 items-center gap-2 border-b border-[var(--border)] bg-[var(--card)] px-3",children:[(0,r.jsx)("span",{className:"truncate text-xs text-[var(--muted-foreground)]",children:t}),(0,r.jsx)("div",{className:"flex-1"}),c,s&&(0,r.jsxs)(o,{onClick:s,title:h("editor.openAsText"),children:[(0,r.jsx)(l.A,{className:"h-3 w-3"}),(0,r.jsx)("span",{children:h("editor.openAsText")})]}),(0,r.jsxs)("a",{href:n,download:!0,className:"flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium text-[var(--muted-foreground)] transition-colors hover:bg-[var(--secondary)] hover:text-[var(--foreground)]",title:h("editor.download"),children:[(0,r.jsx)(a.A,{className:"h-3 w-3"}),(0,r.jsx)("span",{children:h("editor.download")})]})]}),(0,r.jsx)("div",{className:"relative min-h-0 flex-1",children:u?(0,r.jsx)("div",{className:"flex h-full items-center justify-center text-sm text-red-400",children:u}):(0,r.jsxs)(r.Fragment,{children:[x,d&&(0,r.jsx)("div",{className:"absolute inset-0 flex items-center justify-center bg-[var(--background)]/80 text-sm text-[var(--muted-foreground)]",children:"Loading preview..."})]})})]})}function o(e){let{onClick:t,title:n,children:l}=e;return(0,r.jsx)("button",{onClick:t,title:n,className:"flex items-center gap-1 rounded px-2 py-1 text-[10px] font-medium text-[var(--muted-foreground)] transition-colors hover:bg-[var(--secondary)] hover:text-[var(--foreground)]",children:l})}},39250:(e,t,n)=>{n.d(t,{A:()=>r});let r=(0,n(79020).A)("Printer",[["path",{d:"M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2",key:"143wyd"}],["path",{d:"M6 9V3a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1v6",key:"1itne7"}],["rect",{x:"6",y:"14",width:"12",height:"8",rx:"1",key:"1ue0tg"}]])},48434:(e,t,n)=>{n.d(t,{A:()=>r});let r=(0,n(79020).A)("ArrowRightLeft",[["path",{d:"m16 3 4 4-4 4",key:"1x1c3m"}],["path",{d:"M20 7H4",key:"zbl0bi"}],["path",{d:"m8 21-4-4 4-4",key:"h9nckh"}],["path",{d:"M4 17h16",key:"g4d7ey"}]])},62839:(e,t,n)=>{n.r(t),n.d(t,{MediaPreview:()=>m});var r=n(41440),l=n(54604),a=n(79020);let i=(0,a.A)("ZoomOut",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]),s=(0,a.A)("ZoomIn",[["circle",{cx:"11",cy:"11",r:"8",key:"4ej97u"}],["line",{x1:"21",x2:"16.65",y1:"21",y2:"16.65",key:"13gj7c"}],["line",{x1:"11",x2:"11",y1:"8",y2:"14",key:"1vmskp"}],["line",{x1:"8",x2:"14",y1:"11",y2:"11",key:"durymu"}]]);var o=n(23715),c=n(39250),d=n(37050),u=n(10912),x=n(27173),h=n(17119);function m(e){let{name:t,viewUrl:n,downloadUrl:a,onOpenAsText:m}=e,f=(0,h.kj)(),g=function(e){var t,n;let r=null!=(n=null==(t=e.split(".").pop())?void 0:t.toLowerCase())?n:"";return x.dj.includes(r)?"image":x.Tv.includes(r)?"video":x._H.includes(r)?"audio":null}(t),p=function(){let e=(0,l.useRef)(null),[t,n]=(0,l.useState)(1),[r,a]=(0,l.useState)({x:0,y:0}),i=(0,l.useRef)(null),[s,o]=(0,l.useState)(!1),c=(0,l.useCallback)(()=>{n(1),a({x:0,y:0})},[]),d=(0,l.useCallback)((e,t,r)=>{n(n=>{let l=Math.min(20,Math.max(.1,n*r)),i=l/n;return a(n=>({x:e-i*(e-n.x),y:t-i*(t-n.y)})),l})},[]),u=(0,l.useCallback)(t=>{let n=e.current;n&&d(n.clientWidth/2,n.clientHeight/2,t)},[d]),x=(0,l.useCallback)(t=>{var n;t.preventDefault();let r=null==(n=e.current)?void 0:n.getBoundingClientRect();r&&d(t.clientX-r.left,t.clientY-r.top,t.deltaY<0?1.15:.8695652173913044)},[d]),h=(0,l.useCallback)(e=>{0===e.button&&(e.preventDefault(),e.target.setPointerCapture(e.pointerId),i.current={startX:e.clientX,startY:e.clientY,origX:r.x,origY:r.y},o(!0))},[r]),m=(0,l.useCallback)(e=>{i.current&&a({x:i.current.origX+(e.clientX-i.current.startX),y:i.current.origY+(e.clientY-i.current.startY)})},[]),f=(0,l.useCallback)(()=>{i.current=null,o(!1)},[]);return(0,l.useEffect)(()=>{let t=e.current;if(!t)return;let n=e=>e.preventDefault();return t.addEventListener("wheel",n,{passive:!1}),()=>t.removeEventListener("wheel",n)},[]),{containerRef:e,scale:t,translate:r,dragging:s,reset:c,zoomCenter:u,onWheel:x,onPointerDown:h,onPointerMove:m,onPointerUp:f}}(),v="image"===g?(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(d.I,{onClick:()=>p.zoomCenter(.8695652173913044),title:f("editor.zoomOut"),children:(0,r.jsx)(i,{className:"h-3 w-3"})}),(0,r.jsxs)("span",{className:"min-w-[3ch] text-center text-[10px] text-[var(--muted-foreground)]",children:[Math.round(100*p.scale),"%"]}),(0,r.jsx)(d.I,{onClick:()=>p.zoomCenter(1.15),title:f("editor.zoomIn"),children:(0,r.jsx)(s,{className:"h-3 w-3"})}),(0,r.jsx)(d.I,{onClick:p.reset,title:f("editor.resetZoom"),children:(0,r.jsx)(o.A,{className:"h-3 w-3"})}),(0,r.jsxs)(d.I,{onClick:()=>(0,u.H)(t,'<img src="'.concat(n,'" />'),"margin:0;display:flex;justify-content:center;align-items:center;min-height:100vh;background:#fff"),title:f("editor.print"),children:[(0,r.jsx)(c.A,{className:"h-3 w-3"}),(0,r.jsx)("span",{children:f("editor.print")})]})]}):null;return(0,r.jsxs)(d.n,{name:t,downloadUrl:a,onOpenAsText:m,extraToolbar:v,children:["image"===g&&(0,r.jsx)("div",{ref:p.containerRef,className:"h-full w-full overflow-hidden bg-[#1a1a1a]",style:{cursor:p.dragging?"grabbing":"grab"},onWheel:p.onWheel,onPointerDown:p.onPointerDown,onPointerMove:p.onPointerMove,onPointerUp:p.onPointerUp,onPointerCancel:p.onPointerUp,children:(0,r.jsx)("img",{src:n,alt:t,draggable:!1,style:{transformOrigin:"0 0",transform:"translate(".concat(p.translate.x,"px, ").concat(p.translate.y,"px) scale(").concat(p.scale,")")}})}),"video"===g&&(0,r.jsx)("div",{className:"flex h-full items-center justify-center bg-black p-4",children:(0,r.jsx)("video",{src:n,controls:!0,className:"max-h-full max-w-full",children:(0,r.jsx)("track",{kind:"captions"})})}),"audio"===g&&(0,r.jsx)("div",{className:"flex h-full flex-col items-center justify-center gap-4 bg-[var(--background)]",children:(0,r.jsx)("audio",{src:n,controls:!0,className:"w-full max-w-md"})})]})}}}]);
|