@termhub/agent 0.6.0 → 0.7.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.js +56 -3
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -85,6 +85,12 @@ var RPC = {
|
|
|
85
85
|
recursive: z.boolean().optional()
|
|
86
86
|
}), z.object({ stdout: z.string() })),
|
|
87
87
|
"ai.credential": def(z.object({ provider: aiProvider, config_dir: machinePath.nullable() }), z.object({ stdout: z.string() }), 1e4),
|
|
88
|
+
/** Symlinks a Claude Code transcript into another account's config dir so `claude --resume` finds it there (since agent 0.7.0). */
|
|
89
|
+
"claude.linkSession": def(z.object({
|
|
90
|
+
transcript_path: machinePath,
|
|
91
|
+
session_id: z.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/),
|
|
92
|
+
config_dir: machinePath.nullable()
|
|
93
|
+
}), z.object({ status: z.enum(["linked", "same_account", "no_transcript", "no_config_dir", "conflict"]) }), 1e4),
|
|
88
94
|
"file.paste": def(z.object({ name: pasteName, data_b64: z.string().min(1).max(28 * 1024 * 1024) }), z.object({ path: z.string() }), 6e4),
|
|
89
95
|
/** Monitor hooks (see @termhub/machine-ops hooks.ts): the agent writes the script, env and config entries under its own $HOME. */
|
|
90
96
|
/** `claude_dirs`: Claude config dirs besides ~/.claude (accounts with CLAUDE_CONFIG_DIR), hooked when they exist; since agent 0.1.5. */
|
|
@@ -664,7 +670,7 @@ function claudeConfigDirs(accountDirs) {
|
|
|
664
670
|
function expandHome(dir, home) {
|
|
665
671
|
return dir.startsWith("~/") ? `${home}/${dir.slice(2)}` : dir;
|
|
666
672
|
}
|
|
667
|
-
var CLAUDE_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PermissionRequest", "Notification", "Stop", "SessionEnd"];
|
|
673
|
+
var CLAUDE_HOOK_EVENTS = ["SessionStart", "UserPromptSubmit", "PreToolUse", "PermissionRequest", "Notification", "Stop", "StopFailure", "SessionEnd"];
|
|
668
674
|
var CLAUDE_TOOL_EVENTS = /* @__PURE__ */ new Set(["PreToolUse", "PermissionRequest"]);
|
|
669
675
|
var CURSOR_HOOK_EVENTS = ["sessionStart", "beforeSubmitPrompt", "afterAgentResponse", "stop", "sessionEnd"];
|
|
670
676
|
var HOOK_SCRIPT = `#!/bin/sh
|
|
@@ -909,6 +915,32 @@ function stripCursorHooks(current) {
|
|
|
909
915
|
`;
|
|
910
916
|
}
|
|
911
917
|
|
|
918
|
+
// ../../packages/machine-ops/dist/claude-session.js
|
|
919
|
+
var CLAUDE_LINK_STATUSES = ["linked", "same_account", "no_transcript", "no_config_dir", "conflict"];
|
|
920
|
+
function claudeLinkScript(transcriptPath, sessionId, configDir) {
|
|
921
|
+
return [
|
|
922
|
+
configDirPrefix(configDir, ".claude"),
|
|
923
|
+
`SRC=${shellQuote(transcriptPath)}; SID=${shellQuote(sessionId)}`,
|
|
924
|
+
'[ -f "$SRC" ] || { echo no_transcript; exit 0; }',
|
|
925
|
+
'SLUGDIR=$(dirname "$SRC"); SLUG=$(basename "$SLUGDIR"); SRCROOT=$(dirname "$(dirname "$SLUGDIR")")',
|
|
926
|
+
'[ -d "$D" ] || { echo no_config_dir; exit 0; }',
|
|
927
|
+
'if [ "$(cd "$SRCROOT" && pwd -P)" = "$(cd "$D" && pwd -P)" ]; then echo same_account; exit 0; fi',
|
|
928
|
+
'mkdir -p "$D/projects/$SLUG" 2>/dev/null || { echo no_config_dir; exit 0; }',
|
|
929
|
+
'T="$D/projects/$SLUG/$SID.jsonl"',
|
|
930
|
+
'if [ -e "$T" ] || [ -L "$T" ]; then [ "$T" -ef "$SRC" ] || { echo conflict; exit 0; }; else ln -s "$SRC" "$T" 2>/dev/null || { echo conflict; exit 0; }; fi',
|
|
931
|
+
'if [ -d "$SLUGDIR/$SID" ] && [ ! -e "$D/projects/$SLUG/$SID" ] && [ ! -L "$D/projects/$SLUG/$SID" ]; then ln -s "$SLUGDIR/$SID" "$D/projects/$SLUG/$SID" 2>/dev/null; fi',
|
|
932
|
+
"echo linked"
|
|
933
|
+
].join("\n");
|
|
934
|
+
}
|
|
935
|
+
function parseClaudeLinkStatus(stdout) {
|
|
936
|
+
const words = stdout.split(/\s+/).filter(Boolean);
|
|
937
|
+
for (let i = words.length - 1; i >= 0; i--) {
|
|
938
|
+
if (CLAUDE_LINK_STATUSES.includes(words[i]))
|
|
939
|
+
return words[i];
|
|
940
|
+
}
|
|
941
|
+
return null;
|
|
942
|
+
}
|
|
943
|
+
|
|
912
944
|
// ../../packages/machine-ops/dist/discover.js
|
|
913
945
|
var CLAUDE_MARKERS = ["settings.json", "projects", ".credentials.json"];
|
|
914
946
|
var CLAUDE_DIR_NAME = /^\.claude[A-Za-z0-9._-]*$/;
|
|
@@ -1305,7 +1337,8 @@ async function uninstall(params, home = os3.homedir()) {
|
|
|
1305
1337
|
}
|
|
1306
1338
|
|
|
1307
1339
|
// ../../packages/claude-cli/dist/index.js
|
|
1308
|
-
var
|
|
1340
|
+
var CONCIERGE_TOOLS = "Agent";
|
|
1341
|
+
var DISALLOWED_TOOLS = "Bash,PowerShell,Monitor,Read,Write,Edit,NotebookEdit,Glob,Grep,EnterWorktree,WebFetch,WebSearch,RemoteTrigger";
|
|
1309
1342
|
var BACKGROUND_AGENT_HOOK = `input=$(cat); case "$input" in *'"agent_id"'*) exit 0;; esac; printf '%s' "$input" | grep -Eq '"run_in_background"[[:space:]]*:[[:space:]]*true' && exit 0; echo 'No chat do termhub todo subagente roda em segundo plano: repita esta chamada do Agent com run_in_background: true.' >&2; exit 2`;
|
|
1310
1343
|
var CONCIERGE_SETTINGS = JSON.stringify({
|
|
1311
1344
|
hooks: { PreToolUse: [{ matcher: "Agent|Task", hooks: [{ type: "command", command: BACKGROUND_AGENT_HOOK }] }] }
|
|
@@ -1332,6 +1365,8 @@ function buildClaudeArgs(spec) {
|
|
|
1332
1365
|
"mcp__termhub__*",
|
|
1333
1366
|
"--disallowed-tools",
|
|
1334
1367
|
DISALLOWED_TOOLS,
|
|
1368
|
+
"--tools",
|
|
1369
|
+
CONCIERGE_TOOLS,
|
|
1335
1370
|
...spec.stream_input ? ["--input-format", "stream-json", "--replay-user-messages", "--settings", CONCIERGE_SETTINGS] : [],
|
|
1336
1371
|
...spec.model ? ["--model", spec.model] : [],
|
|
1337
1372
|
// Last, and only when set: the account-wide chat's argv stays exactly what it was. It is our own
|
|
@@ -1348,6 +1383,8 @@ function classifyFailure(stderr) {
|
|
|
1348
1383
|
return "missing_session";
|
|
1349
1384
|
if (/^Error: --/m.test(stderr))
|
|
1350
1385
|
return "cli_rejected";
|
|
1386
|
+
if (/^error: unknown option/m.test(stderr))
|
|
1387
|
+
return "cli_rejected";
|
|
1351
1388
|
return "run_failed";
|
|
1352
1389
|
}
|
|
1353
1390
|
|
|
@@ -2001,6 +2038,21 @@ async function credential(params) {
|
|
|
2001
2038
|
return { stdout: r.stdout };
|
|
2002
2039
|
}
|
|
2003
2040
|
|
|
2041
|
+
// src/rpc/claude.ts
|
|
2042
|
+
async function linkSession(params) {
|
|
2043
|
+
let script;
|
|
2044
|
+
try {
|
|
2045
|
+
script = claudeLinkScript(params.transcript_path, params.session_id, params.config_dir);
|
|
2046
|
+
} catch (err) {
|
|
2047
|
+
throw new RpcFailure("invalid", err instanceof Error ? err.message : "invalid config dir");
|
|
2048
|
+
}
|
|
2049
|
+
const r = await sh(script);
|
|
2050
|
+
if (r.timedOut) throw new RpcFailure("timeout", "claude.linkSession timed out");
|
|
2051
|
+
const status4 = parseClaudeLinkStatus(r.stdout);
|
|
2052
|
+
if (r.code !== 0 || !status4) throw new RpcFailure("internal", `claude.linkSession exited with code ${r.code}`);
|
|
2053
|
+
return { status: status4 };
|
|
2054
|
+
}
|
|
2055
|
+
|
|
2004
2056
|
// src/rpc/fs.ts
|
|
2005
2057
|
function processFailure(method, r) {
|
|
2006
2058
|
if (r.timedOut) return new RpcFailure("timeout", `${method} timed out`);
|
|
@@ -2384,7 +2436,7 @@ async function status3() {
|
|
|
2384
2436
|
}
|
|
2385
2437
|
|
|
2386
2438
|
// src/version.ts
|
|
2387
|
-
var AGENT_VERSION = "0.
|
|
2439
|
+
var AGENT_VERSION = "0.7.1";
|
|
2388
2440
|
|
|
2389
2441
|
// src/rpc/update.ts
|
|
2390
2442
|
var PACKAGE = "@termhub/agent";
|
|
@@ -2504,6 +2556,7 @@ var handlers = {
|
|
|
2504
2556
|
"fs.list": list,
|
|
2505
2557
|
"fs.mkdir": mkdir2,
|
|
2506
2558
|
"ai.credential": credential,
|
|
2559
|
+
"claude.linkSession": linkSession,
|
|
2507
2560
|
"file.paste": pasteFile,
|
|
2508
2561
|
"hooks.install": install,
|
|
2509
2562
|
"hooks.uninstall": uninstall,
|
package/package.json
CHANGED