@turmind/halo 1.5.10 → 1.6.0
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 +2 -2
- package/admin-out/404.html +1 -1
- package/admin-out/_next/static/chunks/{388-d5950f264d91625a.js → 147-d4200c70445aabb6.js} +1 -1
- package/admin-out/_next/static/chunks/989-a7f752480eaaa2dc.js +1 -0
- package/admin-out/_next/static/chunks/app/{layout-5ec6c5f713a8562b.js → layout-ea161287d934ba96.js} +1 -1
- package/admin-out/_next/static/chunks/app/page-8173112f256bc483.js +1 -0
- package/admin-out/_next/static/chunks/{webpack-efd27999305b080a.js → webpack-dc73047e0279979b.js} +1 -1
- package/admin-out/_next/static/css/7b736202f0b1dbfd.css +1 -0
- package/admin-out/_next/static/css/981c9e5610ce535a.css +1 -0
- package/admin-out/index.html +1 -1
- package/admin-out/index.txt +6 -5
- package/bundled-docs/design/a2a.md +286 -0
- package/bundled-docs/design/agent.md +7 -5
- package/bundled-docs/design/agentcore.md +194 -122
- package/bundled-docs/design/architecture.md +2 -2
- package/bundled-docs/design/canvas-extensions.md +30 -9
- package/bundled-docs/design/halo-city.md +6 -0
- package/bundled-docs/design/observability.md +12 -4
- package/bundled-docs/design/prompt-system.md +1 -1
- package/bundled-docs/design/relay.md +6 -6
- package/bundled-docs/design/session.md +15 -12
- package/bundled-docs/design/storage.md +9 -2
- package/bundled-docs/design/web.md +36 -59
- package/bundled-docs/dev/acp-adapter.md +59 -175
- package/bundled-docs/dev/api.md +75 -6
- package/bundled-docs/dev/deploy.md +3 -2
- package/bundled-docs/dev/desktop-packaging.md +14 -0
- package/bundled-docs/dev/env.md +10 -6
- package/bundled-docs/dev/tools.md +101 -11
- package/bundled-docs/guide/README.md +1 -1
- package/bundled-docs/guide/channels/README.md +3 -3
- package/bundled-docs/guide/channels/acp.md +67 -42
- package/bundled-docs/guide/channels/feishu.md +1 -1
- package/bundled-docs/guide/channels/slack.md +1 -1
- package/bundled-docs/guide/channels/telegram.md +1 -1
- package/bundled-docs/guide/channels/web.md +10 -34
- package/bundled-docs/guide/channels/wechat.md +1 -1
- package/bundled-docs/guide/channels/wecom.md +1 -1
- package/bundled-docs/guide/chat.md +0 -1
- package/bundled-docs/guide/cli.md +41 -6
- package/bundled-docs/guide/delegation-and-access.md +3 -2
- package/bundled-docs/guide/getting-started.md +1 -1
- package/bundled-docs/guide/skills.md +2 -3
- package/bundled-docs/requirements/agent.md +1 -1
- package/bundled-docs/requirements/chat.md +17 -1
- package/bundled-docs/requirements/command.md +1 -2
- package/bundled-docs/requirements/editor.md +9 -3
- package/bundled-docs/requirements/explorer.md +1 -0
- package/bundled-docs/requirements/terminal.md +15 -0
- package/bundled-docs/requirements/workspace.md +6 -0
- package/dist/index.js +5392 -2786
- package/package.json +1 -1
- package/templates/agents/__score__/AGENT.md +1 -1
- package/templates/agents/default/agent.yaml +0 -1
- package/templates/models/aws-bedrock-claude-invoke.yaml +40 -1
- package/templates/models/aws-bedrock-openai.yaml +100 -6
- package/templates/prompts/all/RUNTIME.md +2 -1
- package/templates/prompts/all/TOOL_SHELL.windows.md +2 -1
- package/templates/skills/send-file/SKILL.md +1 -1
- package/templates/skills/send-file/a2a.md +13 -0
- package/templates/skills/skill/SKILL.md +1 -1
- package/templates/skills/workspace/stage.py +1 -1
- package/admin-out/_next/static/chunks/989-1797287c46139412.js +0 -1
- package/admin-out/_next/static/chunks/app/page-44ab337b2f071e4d.js +0 -1
- package/admin-out/_next/static/css/d53aa54212002364.css +0 -3
- package/templates/skills/acp/SKILL.md +0 -243
- package/templates/skills/acp/templates/SKILL.md.tmpl +0 -75
- package/templates/skills/acp/templates/ask.py +0 -177
- package/templates/skills/acp/templates/config.yaml.tmpl +0 -38
- /package/admin-out/_next/static/{A-Rjx2yltZDKaSO1qVv7K → _F_Fkyh9PainUNY82EEjY}/_buildManifest.js +0 -0
- /package/admin-out/_next/static/{A-Rjx2yltZDKaSO1qVv7K → _F_Fkyh9PainUNY82EEjY}/_ssgManifest.js +0 -0
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""ask.py — call an agent over ACP: remote halo server, local Claude Code, or local Kiro. See SKILL.md."""
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import argparse
|
|
6
|
-
import json
|
|
7
|
-
import os
|
|
8
|
-
import shutil
|
|
9
|
-
import subprocess
|
|
10
|
-
import sys
|
|
11
|
-
import threading
|
|
12
|
-
import time
|
|
13
|
-
from typing import Any
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def fail(msg: str, code: int = 1) -> None:
|
|
17
|
-
sys.stderr.write(f"[ask-acp-agent] {msg}\n")
|
|
18
|
-
sys.exit(code)
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
def main() -> None:
|
|
22
|
-
p = argparse.ArgumentParser(prog="ask.py", description="Ask a remote agent over ACP.")
|
|
23
|
-
p.add_argument("question")
|
|
24
|
-
p.add_argument("--kind", default="halo", choices=["halo", "claude", "kiro"],
|
|
25
|
-
help="halo: remote halo server via `halo acp`; claude: local Claude Code via `claude-agent-acp`; kiro: local Kiro via `kiro-cli acp`.")
|
|
26
|
-
p.add_argument("--host")
|
|
27
|
-
p.add_argument("--port")
|
|
28
|
-
p.add_argument("--scheme", default="http")
|
|
29
|
-
p.add_argument("--token")
|
|
30
|
-
p.add_argument("--workspace")
|
|
31
|
-
p.add_argument("--cwd", default=None, help="claude kind: working directory for the session (defaults to CWD).")
|
|
32
|
-
p.add_argument("--agent-id", default=None)
|
|
33
|
-
p.add_argument("--session-id", default=None)
|
|
34
|
-
p.add_argument("--timeout", type=int, default=600)
|
|
35
|
-
p.add_argument("--halo-bin", default=None)
|
|
36
|
-
p.add_argument("--claude-bin", default=None)
|
|
37
|
-
p.add_argument("--kiro-bin", default=None)
|
|
38
|
-
args = p.parse_args()
|
|
39
|
-
|
|
40
|
-
if args.kind == "claude":
|
|
41
|
-
bin_ = args.claude_bin or os.environ.get("CLAUDE_ACP_BIN") or "claude-agent-acp"
|
|
42
|
-
if shutil.which(bin_) is None and not os.path.isabs(bin_):
|
|
43
|
-
fail(f"`{bin_}` not found in PATH. npm install -g @agentclientprotocol/claude-agent-acp, or set --claude-bin.", 2)
|
|
44
|
-
cmd = [bin_]
|
|
45
|
-
elif args.kind == "kiro":
|
|
46
|
-
bin_ = args.kiro_bin or os.environ.get("KIRO_ACP_BIN") or "kiro-cli"
|
|
47
|
-
if shutil.which(bin_) is None and not os.path.isabs(bin_):
|
|
48
|
-
fail(f"`{bin_}` not found in PATH. Install Kiro CLI, or set --kiro-bin.", 2)
|
|
49
|
-
# --trust-all-tools: the binding is a headless relay; there's no human
|
|
50
|
-
# at this end to answer kiro's per-tool permission prompts.
|
|
51
|
-
cmd = [bin_, "acp", "--trust-all-tools"]
|
|
52
|
-
if args.agent_id and not args.agent_id.startswith("{{"):
|
|
53
|
-
cmd += ["--agent", args.agent_id]
|
|
54
|
-
else:
|
|
55
|
-
for k in ("host", "port", "token", "workspace"):
|
|
56
|
-
if not getattr(args, k):
|
|
57
|
-
fail(f"--{k} is required for --kind halo", 2)
|
|
58
|
-
halo = args.halo_bin or os.environ.get("HALO_BIN") or "halo"
|
|
59
|
-
if shutil.which(halo) is None and not os.path.isabs(halo):
|
|
60
|
-
fail(f"`{halo}` not found in PATH. Install @turmind/halo or set --halo-bin.", 2)
|
|
61
|
-
cmd = [halo, "acp", "--host", args.host, "--port", str(args.port),
|
|
62
|
-
"--scheme", args.scheme, "--token", args.token, "--workspace", args.workspace]
|
|
63
|
-
# Drop `--agent-id` when blank OR an unsubstituted `{{...}}` literal.
|
|
64
|
-
# Both mean "user hasn't configured this optional field" — the first
|
|
65
|
-
# because settings.yaml has `agent_id: ""`, the second because the
|
|
66
|
-
# key isn't in settings.yaml at all and halo's shell_exec
|
|
67
|
-
# substitute leaves the placeholder verbatim (its "fail loud"
|
|
68
|
-
# contract for required params). For an optional flag like this, we
|
|
69
|
-
# want graceful degrade, not a literal-as-value going to acp.
|
|
70
|
-
aid = (args.agent_id or "").strip()
|
|
71
|
-
if aid and not (aid.startswith("{{") and aid.endswith("}}")):
|
|
72
|
-
cmd += ["--agent-id", aid]
|
|
73
|
-
|
|
74
|
-
proc = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
|
|
75
|
-
stderr=subprocess.PIPE, text=True, bufsize=1)
|
|
76
|
-
assert proc.stdin and proc.stdout and proc.stderr
|
|
77
|
-
|
|
78
|
-
def _drain_stderr() -> None:
|
|
79
|
-
for line in proc.stderr:
|
|
80
|
-
sys.stderr.write(line)
|
|
81
|
-
threading.Thread(target=_drain_stderr, daemon=True).start()
|
|
82
|
-
|
|
83
|
-
next_id = 1
|
|
84
|
-
pending: dict[int, dict[str, Any]] = {}
|
|
85
|
-
chunks: list[str] = []
|
|
86
|
-
|
|
87
|
-
def send(method: str, params: dict[str, Any] | None = None) -> int:
|
|
88
|
-
nonlocal next_id
|
|
89
|
-
rid = next_id
|
|
90
|
-
next_id += 1
|
|
91
|
-
msg = {"jsonrpc": "2.0", "id": rid, "method": method}
|
|
92
|
-
if params is not None:
|
|
93
|
-
msg["params"] = params
|
|
94
|
-
proc.stdin.write(json.dumps(msg) + "\n")
|
|
95
|
-
proc.stdin.flush()
|
|
96
|
-
return rid
|
|
97
|
-
|
|
98
|
-
def wait_for(rid: int, deadline: float) -> dict[str, Any]:
|
|
99
|
-
while True:
|
|
100
|
-
if rid in pending:
|
|
101
|
-
return pending.pop(rid)
|
|
102
|
-
if time.time() > deadline:
|
|
103
|
-
proc.kill()
|
|
104
|
-
fail(f"timeout waiting for response to request {rid}", 124)
|
|
105
|
-
line = proc.stdout.readline()
|
|
106
|
-
if line == "":
|
|
107
|
-
rc = proc.wait(timeout=1)
|
|
108
|
-
fail(f"adapter exited prematurely (rc={rc})", rc or 1)
|
|
109
|
-
line = line.strip()
|
|
110
|
-
if not line:
|
|
111
|
-
continue
|
|
112
|
-
try:
|
|
113
|
-
msg = json.loads(line)
|
|
114
|
-
except json.JSONDecodeError:
|
|
115
|
-
sys.stderr.write(f"[ask-acp-agent] non-JSON: {line[:200]}\n")
|
|
116
|
-
continue
|
|
117
|
-
if "id" in msg and ("result" in msg or "error" in msg):
|
|
118
|
-
pending[msg["id"]] = msg
|
|
119
|
-
continue
|
|
120
|
-
method = msg.get("method")
|
|
121
|
-
if method == "session/update":
|
|
122
|
-
update = (msg.get("params") or {}).get("update") or {}
|
|
123
|
-
if update.get("sessionUpdate") == "agent_message_chunk":
|
|
124
|
-
text = (update.get("content") or {}).get("text", "")
|
|
125
|
-
if text:
|
|
126
|
-
chunks.append(text)
|
|
127
|
-
|
|
128
|
-
deadline = time.time() + args.timeout
|
|
129
|
-
try:
|
|
130
|
-
rid = send("initialize", {"protocolVersion": 1, "clientCapabilities": {}})
|
|
131
|
-
resp = wait_for(rid, deadline)
|
|
132
|
-
if "error" in resp:
|
|
133
|
-
fail(f"initialize failed: {resp['error']}")
|
|
134
|
-
|
|
135
|
-
if args.session_id:
|
|
136
|
-
# ACP session/load requires cwd + mcpServers (same as session/new);
|
|
137
|
-
# kiro-cli exits silently if they're missing.
|
|
138
|
-
load_params: dict[str, Any] = {"sessionId": args.session_id}
|
|
139
|
-
if args.kind in ("claude", "kiro"):
|
|
140
|
-
load_params["cwd"] = args.cwd or os.getcwd()
|
|
141
|
-
load_params["mcpServers"] = []
|
|
142
|
-
rid = send("session/load", load_params)
|
|
143
|
-
resp = wait_for(rid, deadline)
|
|
144
|
-
if "error" in resp:
|
|
145
|
-
fail(f"session/load failed: {resp['error']}")
|
|
146
|
-
session_id = args.session_id
|
|
147
|
-
else:
|
|
148
|
-
new_params = {"cwd": args.cwd or os.getcwd(), "mcpServers": []} if args.kind in ("claude", "kiro") else {}
|
|
149
|
-
rid = send("session/new", new_params)
|
|
150
|
-
resp = wait_for(rid, deadline)
|
|
151
|
-
if "error" in resp:
|
|
152
|
-
fail(f"session/new failed: {resp['error']}")
|
|
153
|
-
session_id = resp["result"]["sessionId"]
|
|
154
|
-
|
|
155
|
-
rid = send("session/prompt", {
|
|
156
|
-
"sessionId": session_id,
|
|
157
|
-
"prompt": [{"type": "text", "text": args.question}],
|
|
158
|
-
})
|
|
159
|
-
resp = wait_for(rid, deadline)
|
|
160
|
-
if "error" in resp:
|
|
161
|
-
fail(f"session/prompt failed: {resp['error']}")
|
|
162
|
-
stop_reason = resp["result"].get("stopReason", "unknown")
|
|
163
|
-
|
|
164
|
-
sys.stdout.write(f"SESSION: {session_id}\n---\n")
|
|
165
|
-
sys.stdout.write("".join(chunks).rstrip() + "\n")
|
|
166
|
-
|
|
167
|
-
if stop_reason != "end_turn":
|
|
168
|
-
sys.stderr.write(f"[ask-acp-agent] stopReason={stop_reason}\n")
|
|
169
|
-
finally:
|
|
170
|
-
try: proc.stdin.close()
|
|
171
|
-
except Exception: pass
|
|
172
|
-
try: proc.wait(timeout=5)
|
|
173
|
-
except subprocess.TimeoutExpired: proc.kill()
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if __name__ == "__main__":
|
|
177
|
-
main()
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
displayName: Ask {{LABEL_DISPLAY}}
|
|
2
|
-
description: Forward a question to the {{LABEL_DISPLAY}} halo agent over ACP.
|
|
3
|
-
|
|
4
|
-
params:
|
|
5
|
-
- key: host
|
|
6
|
-
description: Remote halo server hostname or IP.
|
|
7
|
-
description_zh: 远端 halo server 主机名 / IP。
|
|
8
|
-
default: "{{HOST}}"
|
|
9
|
-
|
|
10
|
-
- key: port
|
|
11
|
-
description: Remote halo server port.
|
|
12
|
-
description_zh: 远端 halo server 端口。
|
|
13
|
-
default: "{{PORT}}"
|
|
14
|
-
|
|
15
|
-
- key: scheme
|
|
16
|
-
description: URL scheme to reach the remote halo server — http or https.
|
|
17
|
-
description_zh: 连接远端 halo server 的协议 — http 或 https。
|
|
18
|
-
default: "{{SCHEME}}"
|
|
19
|
-
|
|
20
|
-
- key: workspace
|
|
21
|
-
description: Absolute path of the remote workspace to drive.
|
|
22
|
-
description_zh: 要驱动的远端 workspace 绝对路径。
|
|
23
|
-
default: "{{WORKSPACE}}"
|
|
24
|
-
|
|
25
|
-
- key: label
|
|
26
|
-
description: Friendly name for the remote, shown when reporting back to the user.
|
|
27
|
-
description_zh: 报告给用户时使用的称呼。
|
|
28
|
-
default: "{{LABEL_DISPLAY}}"
|
|
29
|
-
|
|
30
|
-
- key: agent_id
|
|
31
|
-
description: Optional remote agent profile id. Blank = remote 'default'.
|
|
32
|
-
description_zh: 可选的远端 agent id,留空则用远端 default。
|
|
33
|
-
default: ""
|
|
34
|
-
|
|
35
|
-
- key: token
|
|
36
|
-
description: Web-channel token from the remote halo admin. Must be a full-access token if cross-workspace addressing is needed.
|
|
37
|
-
description_zh: 远端 halo 后台 Web channel token。若需跨 workspace 调用必须是 full 权限。
|
|
38
|
-
secret: true
|
/package/admin-out/_next/static/{A-Rjx2yltZDKaSO1qVv7K → _F_Fkyh9PainUNY82EEjY}/_buildManifest.js
RENAMED
|
File without changes
|
/package/admin-out/_next/static/{A-Rjx2yltZDKaSO1qVv7K → _F_Fkyh9PainUNY82EEjY}/_ssgManifest.js
RENAMED
|
File without changes
|