refactor!: drop clawdis_ tool prefix
This commit is contained in:
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
### Breaking
|
### Breaking
|
||||||
- Identifiers: rename bundle IDs and internal domains to `com.clawdis.*` (macOS: `com.clawdis.mac`, iOS: `com.clawdis.ios`, Android: `com.clawdis.android`) and update the gateway LaunchAgent label to `com.clawdis.gateway`.
|
- Identifiers: rename bundle IDs and internal domains to `com.clawdis.*` (macOS: `com.clawdis.mac`, iOS: `com.clawdis.ios`, Android: `com.clawdis.android`) and update the gateway LaunchAgent label to `com.clawdis.gateway`.
|
||||||
|
- Agent tools: drop the `clawdis_` prefix (`browser`, `canvas`, `nodes`, `cron`, `gateway`).
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
- Gateway: support `gateway.port` + `CLAWDIS_GATEWAY_PORT` across CLI, TUI, and macOS app.
|
- Gateway: support `gateway.port` + `CLAWDIS_GATEWAY_PORT` across CLI, TUI, and macOS app.
|
||||||
@@ -230,7 +231,7 @@
|
|||||||
- Hook mappings + Gmail Pub/Sub helper (`clawdis hooks gmail setup/run`) with auto-renew + Tailscale Funnel support.
|
- Hook mappings + Gmail Pub/Sub helper (`clawdis hooks gmail setup/run`) with auto-renew + Tailscale Funnel support.
|
||||||
- Command queue modes + per-session overrides (`/queue ...`) and new `agent.maxConcurrent` cap for safe parallelism across sessions.
|
- Command queue modes + per-session overrides (`/queue ...`) and new `agent.maxConcurrent` cap for safe parallelism across sessions.
|
||||||
- Background bash tasks: `bash` auto-yields after 20s (or on demand) with a `process` tool to list/poll/log/write/kill sessions.
|
- Background bash tasks: `bash` auto-yields after 20s (or on demand) with a `process` tool to list/poll/log/write/kill sessions.
|
||||||
- Gateway in-process restart: `clawdis_gateway` tool action triggers a SIGUSR1 restart without needing a supervisor.
|
- Gateway in-process restart: `gateway` tool action triggers a SIGUSR1 restart without needing a supervisor.
|
||||||
|
|
||||||
### Breaking
|
### Breaking
|
||||||
- Config refactor: `inbound.*` removed; use top-level `routing` (allowlists + group rules + transcription), `messages` (prefixes/timestamps), and `session` (scoping/store/mainKey). No legacy keys read.
|
- Config refactor: `inbound.*` removed; use top-level `routing` (allowlists + group rules + transcription), `messages` (prefixes/timestamps), and `session` (scoping/store/mainKey). No legacy keys read.
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ pnpm gateway:watch
|
|||||||
- Pass `--verbose` to mirror debug logging (handshakes, req/res, events) from the log file into stdio when troubleshooting.
|
- Pass `--verbose` to mirror debug logging (handshakes, req/res, events) from the log file into stdio when troubleshooting.
|
||||||
- `--force` uses `lsof` to find listeners on the chosen port, sends SIGTERM, logs what it killed, then starts the gateway (fails fast if `lsof` is missing).
|
- `--force` uses `lsof` to find listeners on the chosen port, sends SIGTERM, logs what it killed, then starts the gateway (fails fast if `lsof` is missing).
|
||||||
- If you run under a supervisor (launchd/systemd/mac app child-process mode), a stop/restart typically sends **SIGTERM**; older builds may surface this as `pnpm` `ELIFECYCLE` exit code **143** (SIGTERM), which is a normal shutdown, not a crash.
|
- If you run under a supervisor (launchd/systemd/mac app child-process mode), a stop/restart typically sends **SIGTERM**; older builds may surface this as `pnpm` `ELIFECYCLE` exit code **143** (SIGTERM), which is a normal shutdown, not a crash.
|
||||||
- **SIGUSR1** triggers an in-process restart (no external supervisor required). This is what the `clawdis_gateway` agent tool uses.
|
- **SIGUSR1** triggers an in-process restart (no external supervisor required). This is what the `gateway` agent tool uses.
|
||||||
- Optional shared secret: pass `--token <value>` or set `CLAWDIS_GATEWAY_TOKEN` to require clients to send `connect.params.auth.token`.
|
- Optional shared secret: pass `--token <value>` or set `CLAWDIS_GATEWAY_TOKEN` to require clients to send `connect.params.auth.token`.
|
||||||
- Port precedence: `--port` > `CLAWDIS_GATEWAY_PORT` > `gateway.port` > default `18789`.
|
- Port precedence: `--port` > `CLAWDIS_GATEWAY_PORT` > `gateway.port` > default `18789`.
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ Notes:
|
|||||||
- `poll` returns new output and exit status when complete.
|
- `poll` returns new output and exit status when complete.
|
||||||
- `log` supports line-based `offset`/`limit` (omit `offset` to grab the last N lines).
|
- `log` supports line-based `offset`/`limit` (omit `offset` to grab the last N lines).
|
||||||
|
|
||||||
### `clawdis_browser`
|
### `browser`
|
||||||
Control the dedicated clawd browser.
|
Control the dedicated clawd browser.
|
||||||
|
|
||||||
Core actions:
|
Core actions:
|
||||||
@@ -56,7 +56,7 @@ Notes:
|
|||||||
- `upload` can optionally pass a `ref` to auto-click after arming.
|
- `upload` can optionally pass a `ref` to auto-click after arming.
|
||||||
- `upload` also supports `inputRef` (aria ref) or `element` (CSS selector) to set `<input type="file">` directly.
|
- `upload` also supports `inputRef` (aria ref) or `element` (CSS selector) to set `<input type="file">` directly.
|
||||||
|
|
||||||
### `clawdis_canvas`
|
### `canvas`
|
||||||
Drive the node Canvas (present, eval, snapshot, A2UI).
|
Drive the node Canvas (present, eval, snapshot, A2UI).
|
||||||
|
|
||||||
Core actions:
|
Core actions:
|
||||||
@@ -70,7 +70,7 @@ Notes:
|
|||||||
- A2UI is v0.8 only (no `createSurface`); the CLI rejects v0.9 JSONL with line errors.
|
- A2UI is v0.8 only (no `createSurface`); the CLI rejects v0.9 JSONL with line errors.
|
||||||
- Quick smoke: `clawdis canvas a2ui push --text "Hello from A2UI"`.
|
- Quick smoke: `clawdis canvas a2ui push --text "Hello from A2UI"`.
|
||||||
|
|
||||||
### `clawdis_nodes`
|
### `nodes`
|
||||||
Discover and target paired nodes; send notifications; capture camera/screen.
|
Discover and target paired nodes; send notifications; capture camera/screen.
|
||||||
|
|
||||||
Core actions:
|
Core actions:
|
||||||
@@ -84,7 +84,7 @@ Notes:
|
|||||||
- Images return image blocks + `MEDIA:<path>`.
|
- Images return image blocks + `MEDIA:<path>`.
|
||||||
- Videos return `FILE:<path>` (mp4).
|
- Videos return `FILE:<path>` (mp4).
|
||||||
|
|
||||||
### `clawdis_cron`
|
### `cron`
|
||||||
Manage Gateway cron jobs and wakeups.
|
Manage Gateway cron jobs and wakeups.
|
||||||
|
|
||||||
Core actions:
|
Core actions:
|
||||||
@@ -96,7 +96,7 @@ Notes:
|
|||||||
- `add` expects a full cron job object (same schema as `cron.add` RPC).
|
- `add` expects a full cron job object (same schema as `cron.add` RPC).
|
||||||
- `update` uses `{ jobId, patch }`.
|
- `update` uses `{ jobId, patch }`.
|
||||||
|
|
||||||
### `clawdis_gateway`
|
### `gateway`
|
||||||
Restart the running Gateway process (in-place).
|
Restart the running Gateway process (in-place).
|
||||||
|
|
||||||
Core actions:
|
Core actions:
|
||||||
@@ -147,7 +147,7 @@ Notes:
|
|||||||
|
|
||||||
## Parameters (common)
|
## Parameters (common)
|
||||||
|
|
||||||
Gateway-backed tools (`clawdis_canvas`, `clawdis_nodes`, `clawdis_cron`):
|
Gateway-backed tools (`canvas`, `nodes`, `cron`):
|
||||||
- `gatewayUrl` (default `ws://127.0.0.1:18789`)
|
- `gatewayUrl` (default `ws://127.0.0.1:18789`)
|
||||||
- `gatewayToken` (if auth enabled)
|
- `gatewayToken` (if auth enabled)
|
||||||
- `timeoutMs`
|
- `timeoutMs`
|
||||||
@@ -158,18 +158,18 @@ Browser tool:
|
|||||||
## Recommended agent flows
|
## Recommended agent flows
|
||||||
|
|
||||||
Browser automation:
|
Browser automation:
|
||||||
1) `clawdis_browser` → `status` / `start`
|
1) `browser` → `status` / `start`
|
||||||
2) `snapshot` (ai or aria)
|
2) `snapshot` (ai or aria)
|
||||||
3) `act` (click/type/press)
|
3) `act` (click/type/press)
|
||||||
4) `screenshot` if you need visual confirmation
|
4) `screenshot` if you need visual confirmation
|
||||||
|
|
||||||
Canvas render:
|
Canvas render:
|
||||||
1) `clawdis_canvas` → `present`
|
1) `canvas` → `present`
|
||||||
2) `a2ui_push` (optional)
|
2) `a2ui_push` (optional)
|
||||||
3) `snapshot`
|
3) `snapshot`
|
||||||
|
|
||||||
Node targeting:
|
Node targeting:
|
||||||
1) `clawdis_nodes` → `status`
|
1) `nodes` → `status`
|
||||||
2) `describe` on the chosen node
|
2) `describe` on the chosen node
|
||||||
3) `notify` / `camera_snap` / `screen_record`
|
3) `notify` / `camera_snap` / `screen_record`
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ import { describe, expect, it, vi } from "vitest";
|
|||||||
|
|
||||||
import { createClawdisTools } from "./clawdis-tools.js";
|
import { createClawdisTools } from "./clawdis-tools.js";
|
||||||
|
|
||||||
describe("clawdis_gateway tool", () => {
|
describe("gateway tool", () => {
|
||||||
it("schedules SIGUSR1 restart", async () => {
|
it("schedules SIGUSR1 restart", async () => {
|
||||||
vi.useFakeTimers();
|
vi.useFakeTimers();
|
||||||
const kill = vi.spyOn(process, "kill").mockImplementation(() => true);
|
const kill = vi.spyOn(process, "kill").mockImplementation(() => true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const tool = createClawdisTools().find(
|
const tool = createClawdisTools().find(
|
||||||
(candidate) => candidate.name === "clawdis_gateway",
|
(candidate) => candidate.name === "gateway",
|
||||||
);
|
);
|
||||||
expect(tool).toBeDefined();
|
expect(tool).toBeDefined();
|
||||||
if (!tool) throw new Error("missing clawdis_gateway tool");
|
if (!tool) throw new Error("missing gateway tool");
|
||||||
|
|
||||||
const result = await tool.execute("call1", {
|
const result = await tool.execute("call1", {
|
||||||
action: "restart",
|
action: "restart",
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ vi.mock("../media/image-ops.js", () => ({
|
|||||||
|
|
||||||
import { createClawdisTools } from "./clawdis-tools.js";
|
import { createClawdisTools } from "./clawdis-tools.js";
|
||||||
|
|
||||||
describe("clawdis_nodes camera_snap", () => {
|
describe("nodes camera_snap", () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
callGateway.mockReset();
|
callGateway.mockReset();
|
||||||
});
|
});
|
||||||
@@ -36,9 +36,9 @@ describe("clawdis_nodes camera_snap", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const tool = createClawdisTools().find(
|
const tool = createClawdisTools().find(
|
||||||
(candidate) => candidate.name === "clawdis_nodes",
|
(candidate) => candidate.name === "nodes",
|
||||||
);
|
);
|
||||||
if (!tool) throw new Error("missing clawdis_nodes tool");
|
if (!tool) throw new Error("missing nodes tool");
|
||||||
|
|
||||||
const result = await tool.execute("call1", {
|
const result = await tool.execute("call1", {
|
||||||
action: "camera_snap",
|
action: "camera_snap",
|
||||||
@@ -76,9 +76,9 @@ describe("clawdis_nodes camera_snap", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const tool = createClawdisTools().find(
|
const tool = createClawdisTools().find(
|
||||||
(candidate) => candidate.name === "clawdis_nodes",
|
(candidate) => candidate.name === "nodes",
|
||||||
);
|
);
|
||||||
if (!tool) throw new Error("missing clawdis_nodes tool");
|
if (!tool) throw new Error("missing nodes tool");
|
||||||
|
|
||||||
await tool.execute("call1", {
|
await tool.execute("call1", {
|
||||||
action: "camera_snap",
|
action: "camera_snap",
|
||||||
|
|||||||
@@ -577,8 +577,8 @@ const BrowserToolSchema = Type.Union([
|
|||||||
|
|
||||||
function createBrowserTool(): AnyAgentTool {
|
function createBrowserTool(): AnyAgentTool {
|
||||||
return {
|
return {
|
||||||
label: "Clawdis Browser",
|
label: "Browser",
|
||||||
name: "clawdis_browser",
|
name: "browser",
|
||||||
description:
|
description:
|
||||||
"Control clawd's dedicated browser (status/start/stop/tabs/open/snapshot/screenshot/actions). Use snapshot+act for UI automation. Avoid act:wait by default; use only in exceptional cases when no reliable UI state exists.",
|
"Control clawd's dedicated browser (status/start/stop/tabs/open/snapshot/screenshot/actions). Use snapshot+act for UI automation. Avoid act:wait by default; use only in exceptional cases when no reliable UI state exists.",
|
||||||
parameters: BrowserToolSchema,
|
parameters: BrowserToolSchema,
|
||||||
@@ -837,8 +837,8 @@ const CanvasToolSchema = Type.Union([
|
|||||||
|
|
||||||
function createCanvasTool(): AnyAgentTool {
|
function createCanvasTool(): AnyAgentTool {
|
||||||
return {
|
return {
|
||||||
label: "Clawdis Canvas",
|
label: "Canvas",
|
||||||
name: "clawdis_canvas",
|
name: "canvas",
|
||||||
description:
|
description:
|
||||||
"Control node canvases (present/hide/navigate/eval/snapshot/A2UI). Use snapshot to capture the rendered UI.",
|
"Control node canvases (present/hide/navigate/eval/snapshot/A2UI). Use snapshot to capture the rendered UI.",
|
||||||
parameters: CanvasToolSchema,
|
parameters: CanvasToolSchema,
|
||||||
@@ -1088,8 +1088,8 @@ const NodesToolSchema = Type.Union([
|
|||||||
|
|
||||||
function createNodesTool(): AnyAgentTool {
|
function createNodesTool(): AnyAgentTool {
|
||||||
return {
|
return {
|
||||||
label: "Clawdis Nodes",
|
label: "Nodes",
|
||||||
name: "clawdis_nodes",
|
name: "nodes",
|
||||||
description:
|
description:
|
||||||
"Discover and control paired nodes (status/describe/pairing/notify/camera/screen).",
|
"Discover and control paired nodes (status/describe/pairing/notify/camera/screen).",
|
||||||
parameters: NodesToolSchema,
|
parameters: NodesToolSchema,
|
||||||
@@ -1454,8 +1454,8 @@ const CronToolSchema = Type.Union([
|
|||||||
|
|
||||||
function createCronTool(): AnyAgentTool {
|
function createCronTool(): AnyAgentTool {
|
||||||
return {
|
return {
|
||||||
label: "Clawdis Cron",
|
label: "Cron",
|
||||||
name: "clawdis_cron",
|
name: "cron",
|
||||||
description:
|
description:
|
||||||
"Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events.",
|
"Manage Gateway cron jobs (status/list/add/update/remove/run/runs) and send wake events.",
|
||||||
parameters: CronToolSchema,
|
parameters: CronToolSchema,
|
||||||
@@ -1736,7 +1736,7 @@ const DiscordToolSchema = Type.Union([
|
|||||||
|
|
||||||
function createDiscordTool(): AnyAgentTool {
|
function createDiscordTool(): AnyAgentTool {
|
||||||
return {
|
return {
|
||||||
label: "Clawdis Discord",
|
label: "Discord",
|
||||||
name: "discord",
|
name: "discord",
|
||||||
description: "Manage Discord messages, reactions, and moderation.",
|
description: "Manage Discord messages, reactions, and moderation.",
|
||||||
parameters: DiscordToolSchema,
|
parameters: DiscordToolSchema,
|
||||||
@@ -2264,8 +2264,8 @@ function createDiscordTool(): AnyAgentTool {
|
|||||||
|
|
||||||
function createGatewayTool(): AnyAgentTool {
|
function createGatewayTool(): AnyAgentTool {
|
||||||
return {
|
return {
|
||||||
label: "Clawdis Gateway",
|
label: "Gateway",
|
||||||
name: "clawdis_gateway",
|
name: "gateway",
|
||||||
description:
|
description:
|
||||||
"Restart the running gateway process in-place (SIGUSR1) without needing an external supervisor. Use delayMs to avoid interrupting an in-flight reply.",
|
"Restart the running gateway process in-place (SIGUSR1) without needing an external supervisor. Use delayMs to avoid interrupting an in-flight reply.",
|
||||||
parameters: GatewayToolSchema,
|
parameters: GatewayToolSchema,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { createClawdisCodingTools } from "./pi-tools.js";
|
|||||||
describe("createClawdisCodingTools", () => {
|
describe("createClawdisCodingTools", () => {
|
||||||
it("merges properties for union tool schemas", () => {
|
it("merges properties for union tool schemas", () => {
|
||||||
const tools = createClawdisCodingTools();
|
const tools = createClawdisCodingTools();
|
||||||
const browser = tools.find((tool) => tool.name === "clawdis_browser");
|
const browser = tools.find((tool) => tool.name === "browser");
|
||||||
expect(browser).toBeDefined();
|
expect(browser).toBeDefined();
|
||||||
const parameters = browser?.parameters as {
|
const parameters = browser?.parameters as {
|
||||||
anyOf?: unknown[];
|
anyOf?: unknown[];
|
||||||
@@ -26,9 +26,7 @@ describe("createClawdisCodingTools", () => {
|
|||||||
|
|
||||||
it("preserves union action values in merged schema", () => {
|
it("preserves union action values in merged schema", () => {
|
||||||
const tools = createClawdisCodingTools();
|
const tools = createClawdisCodingTools();
|
||||||
const toolNames = tools
|
const toolNames = ["browser", "canvas", "nodes", "cron", "gateway"];
|
||||||
.filter((tool) => tool.name.startsWith("clawdis_"))
|
|
||||||
.map((tool) => tool.name);
|
|
||||||
|
|
||||||
for (const name of toolNames) {
|
for (const name of toolNames) {
|
||||||
const tool = tools.find((candidate) => candidate.name === name);
|
const tool = tools.find((candidate) => candidate.name === name);
|
||||||
|
|||||||
@@ -62,10 +62,10 @@ export function buildAgentSystemPromptAppend(params: {
|
|||||||
"- bash: run shell commands (supports background via yieldMs/background)",
|
"- bash: run shell commands (supports background via yieldMs/background)",
|
||||||
"- process: manage background bash sessions",
|
"- process: manage background bash sessions",
|
||||||
"- whatsapp_login: generate a WhatsApp QR code and wait for linking",
|
"- whatsapp_login: generate a WhatsApp QR code and wait for linking",
|
||||||
"- clawdis_browser: control clawd's dedicated browser",
|
"- browser: control clawd's dedicated browser",
|
||||||
"- clawdis_canvas: present/eval/snapshot the Canvas",
|
"- canvas: present/eval/snapshot the Canvas",
|
||||||
"- clawdis_nodes: list/describe/notify/camera/screen on paired nodes",
|
"- nodes: list/describe/notify/camera/screen on paired nodes",
|
||||||
"- clawdis_cron: manage cron jobs and wake events",
|
"- cron: manage cron jobs and wake events",
|
||||||
"TOOLS.md does not control tool availability; it is user guidance for how to use external tools.",
|
"TOOLS.md does not control tool availability; it is user guidance for how to use external tools.",
|
||||||
"",
|
"",
|
||||||
"## Workspace",
|
"## Workspace",
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ describe("tool meta formatting", () => {
|
|||||||
vi.stubEnv("HOME", "/Users/test");
|
vi.stubEnv("HOME", "/Users/test");
|
||||||
expect(shortenMeta("/Users/test/a.txt")).toBe("~/a.txt");
|
expect(shortenMeta("/Users/test/a.txt")).toBe("~/a.txt");
|
||||||
expect(shortenMeta("/Users/test/a.txt:12")).toBe("~/a.txt:12");
|
expect(shortenMeta("/Users/test/a.txt:12")).toBe("~/a.txt:12");
|
||||||
|
expect(shortenMeta("cd /Users/test/dir && ls")).toBe("cd ~/dir && ls");
|
||||||
expect(shortenMeta("")).toBe("");
|
expect(shortenMeta("")).toBe("");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ describe("tool meta formatting", () => {
|
|||||||
"note",
|
"note",
|
||||||
"a→b",
|
"a→b",
|
||||||
]);
|
]);
|
||||||
expect(out).toMatch(/^🛠️ fs/);
|
expect(out).toMatch(/^🧩 fs/);
|
||||||
expect(out).toContain("~/dir/{a.txt, b.txt}");
|
expect(out).toContain("~/dir/{a.txt, b.txt}");
|
||||||
expect(out).toContain("note");
|
expect(out).toContain("note");
|
||||||
expect(out).toContain("a→b");
|
expect(out).toContain("a→b");
|
||||||
@@ -43,8 +44,8 @@ describe("tool meta formatting", () => {
|
|||||||
|
|
||||||
it("formats prefixes with default labels", () => {
|
it("formats prefixes with default labels", () => {
|
||||||
vi.stubEnv("HOME", "/Users/test");
|
vi.stubEnv("HOME", "/Users/test");
|
||||||
expect(formatToolPrefix(undefined, undefined)).toBe("🛠️ tool");
|
expect(formatToolPrefix(undefined, undefined)).toBe("🧩 tool");
|
||||||
expect(formatToolPrefix("x", "/Users/test/a.txt")).toBe("🛠️ x: ~/a.txt");
|
expect(formatToolPrefix("x", "/Users/test/a.txt")).toBe("🧩 x: ~/a.txt");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,17 @@ export const TOOL_RESULT_DEBOUNCE_MS = 500;
|
|||||||
export const TOOL_RESULT_FLUSH_COUNT = 5;
|
export const TOOL_RESULT_FLUSH_COUNT = 5;
|
||||||
|
|
||||||
const TOOL_EMOJI_BY_NAME: Record<string, string> = {
|
const TOOL_EMOJI_BY_NAME: Record<string, string> = {
|
||||||
bash: "💻",
|
bash: "🛠️",
|
||||||
process: "🧰",
|
process: "🧰",
|
||||||
read: "📖",
|
read: "📖",
|
||||||
write: "✍️",
|
write: "✍️",
|
||||||
edit: "📝",
|
edit: "📝",
|
||||||
attach: "📎",
|
attach: "📎",
|
||||||
clawdis_browser: "🌐",
|
browser: "🌐",
|
||||||
clawdis_canvas: "🖼️",
|
canvas: "🖼️",
|
||||||
clawdis_nodes: "📱",
|
nodes: "📱",
|
||||||
clawdis_cron: "⏰",
|
cron: "⏰",
|
||||||
clawdis_gateway: "🔌",
|
gateway: "🔌",
|
||||||
whatsapp_login: "🟢",
|
whatsapp_login: "🟢",
|
||||||
discord: "💬",
|
discord: "💬",
|
||||||
};
|
};
|
||||||
@@ -20,7 +20,13 @@ const TOOL_EMOJI_BY_NAME: Record<string, string> = {
|
|||||||
function resolveToolEmoji(toolName?: string): string {
|
function resolveToolEmoji(toolName?: string): string {
|
||||||
const key = toolName?.trim().toLowerCase();
|
const key = toolName?.trim().toLowerCase();
|
||||||
if (key && TOOL_EMOJI_BY_NAME[key]) return TOOL_EMOJI_BY_NAME[key];
|
if (key && TOOL_EMOJI_BY_NAME[key]) return TOOL_EMOJI_BY_NAME[key];
|
||||||
return "🛠️";
|
return "🧩";
|
||||||
|
}
|
||||||
|
|
||||||
|
function shortenHomeInString(input: string): string {
|
||||||
|
const home = process.env.HOME;
|
||||||
|
if (!home) return input;
|
||||||
|
return input.split(home).join("~");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function shortenPath(p: string): string {
|
export function shortenPath(p: string): string {
|
||||||
@@ -33,10 +39,10 @@ export function shortenPath(p: string): string {
|
|||||||
export function shortenMeta(meta: string): string {
|
export function shortenMeta(meta: string): string {
|
||||||
if (!meta) return meta;
|
if (!meta) return meta;
|
||||||
const colonIdx = meta.indexOf(":");
|
const colonIdx = meta.indexOf(":");
|
||||||
if (colonIdx === -1) return shortenPath(meta);
|
if (colonIdx === -1) return shortenHomeInString(meta);
|
||||||
const base = meta.slice(0, colonIdx);
|
const base = meta.slice(0, colonIdx);
|
||||||
const rest = meta.slice(colonIdx);
|
const rest = meta.slice(colonIdx);
|
||||||
return `${shortenPath(base)}${rest}`;
|
return `${shortenHomeInString(base)}${rest}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function formatToolAggregate(
|
export function formatToolAggregate(
|
||||||
|
|||||||
@@ -1591,8 +1591,8 @@ describe("web auto-reply", () => {
|
|||||||
_ctx,
|
_ctx,
|
||||||
opts?: { onToolResult?: (r: { text: string }) => Promise<void> },
|
opts?: { onToolResult?: (r: { text: string }) => Promise<void> },
|
||||||
) => {
|
) => {
|
||||||
await opts?.onToolResult?.({ text: "🛠️ tool1" });
|
await opts?.onToolResult?.({ text: "🧩 tool1" });
|
||||||
await opts?.onToolResult?.({ text: "🛠️ tool2" });
|
await opts?.onToolResult?.({ text: "🧩 tool2" });
|
||||||
return { text: "final" };
|
return { text: "final" };
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -1611,7 +1611,7 @@ describe("web auto-reply", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const replies = reply.mock.calls.map((call) => call[0]);
|
const replies = reply.mock.calls.map((call) => call[0]);
|
||||||
expect(replies).toEqual(["🦞 🛠️ tool1", "🦞 🛠️ tool2", "🦞 final"]);
|
expect(replies).toEqual(["🦞 🧩 tool1", "🦞 🧩 tool2", "🦞 final"]);
|
||||||
resetLoadConfigMock();
|
resetLoadConfigMock();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user