@slock-ai/daemon 0.55.0 → 0.55.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/{chunk-6Q3U5STT.js → chunk-QQRU3GA6.js} +186 -27
- package/dist/cli/index.js +1160 -480
- package/dist/core.js +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
|
@@ -1061,13 +1061,14 @@ Use the \`slock\` CLI for chat / task / attachment operations. The daemon inject
|
|
|
1061
1061
|
19. **\`slock profile update\`** \u2014 Update your own profile. Supports \`--avatar-file <path>\`, \`--avatar-url pixel:random:<seed>\`, \`--display-name <name>\`, and \`--description <text>\`. Use \`--avatar-url pixel:random:<seed>\` when you want a new pixel avatar but do not have a local image file. Values must be non-empty. Provide at least one flag per call; multiple flags can be combined.
|
|
1062
1062
|
20. **\`slock integration list\`** \u2014 List registered third-party services and this agent's active Slock Agent Logins.
|
|
1063
1063
|
21. **\`slock integration login\`** \u2014 Provision or reuse this agent's login for a registered third-party service.
|
|
1064
|
-
22. **\`slock
|
|
1065
|
-
23. **\`slock reminder
|
|
1066
|
-
24. **\`slock reminder
|
|
1067
|
-
25. **\`slock reminder
|
|
1068
|
-
26. **\`slock reminder
|
|
1069
|
-
27. **\`slock reminder
|
|
1070
|
-
28. **\`slock
|
|
1064
|
+
22. **\`slock integration env\`** \u2014 Print per-agent local CLI environment for a manifest-backed service that requires isolated HOME/XDG state.
|
|
1065
|
+
23. **\`slock reminder schedule\`** \u2014 Schedule a reminder for yourself later, at a specific time, or on a recurring cadence.
|
|
1066
|
+
24. **\`slock reminder list\`** \u2014 List your reminders, including lifecycle history for each reminder.
|
|
1067
|
+
25. **\`slock reminder snooze\`** \u2014 Push a reminder later without replacing it.
|
|
1068
|
+
26. **\`slock reminder update\`** \u2014 Change a reminder's title, schedule, or recurrence without creating a new reminder.
|
|
1069
|
+
27. **\`slock reminder cancel\`** \u2014 Cancel one of your reminders by ID.
|
|
1070
|
+
28. **\`slock reminder log\`** \u2014 Show the event log for a reminder, including fires, dismissals, and reschedules.
|
|
1071
|
+
29. **\`slock action prepare\`** \u2014 Prepare an action card for a human to commit (B-mode quick-commit shortcut). Posts a card the human can click to execute the action under their own identity. Pass \`--target <ch>\` and pipe the action JSON on stdin (variants: \`channel:create\`, \`agent:create\`).
|
|
1071
1072
|
|
|
1072
1073
|
The CLI prints human-readable canonical text on success (matching the format you see in received messages and history). On failure it prints JSON to stderr:
|
|
1073
1074
|
- failure \u2192 stderr \`{"ok":false,"code":"...","message":"..."}\` with non-zero exit
|
|
@@ -1173,7 +1174,7 @@ Each channel has a **name** and optionally a **description** that define its pur
|
|
|
1173
1174
|
- If unsure where something belongs, call ${serverInfoCmd} to review channel descriptions.`;
|
|
1174
1175
|
const thirdPartyIntegrationsSection = isCli ? `### Third-party integrations
|
|
1175
1176
|
|
|
1176
|
-
If a registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app, first run \`slock integration list\` and match the app to a registered service before browsing the app. Use \`slock integration login --service <service>\` to provision or reuse your agent login for that service. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. When the command returns \`Agent login ready\` or \`Already logged in\`, the agent-side login is ready. If the output includes an app URL, open that URL as the service-provided third-party app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes, call internal Slock integration endpoints directly, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`slock profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the registered service / Slock Agent Login path.` : `### Third-party integrations
|
|
1177
|
+
If a registered third-party service requires login, use Slock Agent Login through the CLI instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app, first run \`slock integration list\` and match the app to a registered service before browsing the app. Use \`slock integration login --service <service>\` to provision or reuse your agent login for that service. If the service exposes an agent behavior manifest and you need to run its local CLI, run \`slock integration env --service <service>\` before invoking that CLI; if it prints exports, apply them first so service credentials stay under a per-agent profile HOME/XDG tree instead of the host user's global HOME. If it reports that no local env is required, do not invent HOME/XDG overrides. If it fails, do not run that local CLI with the host user's HOME; report that the service manifest is unsupported. Slock does not execute commands from remote manifests automatically. If the CLI reports that the \`integration\` command is unknown, the local daemon/CLI is too old for Slock Agent Login; report that the machine must be upgraded/restarted instead of calling internal HTTP endpoints yourself. When the command returns \`Agent login ready\` or \`Already logged in\`, the agent-side login is ready. If the output includes an app URL, open that URL as the service-provided third-party app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow, use internal request IDs as OAuth callback codes, call internal Slock integration endpoints directly, or call third-party exchange endpoints unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use \`slock profile show\`. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the registered service / Slock Agent Login path.` : `### Third-party integrations
|
|
1177
1178
|
|
|
1178
1179
|
If a registered third-party service requires login, use Slock Agent Login through the available registered-service interface instead of asking the human to copy tokens or complete human OAuth for you. If a human asks you to sign into, open, use, or fetch identity from a third-party app, first inspect the registered-service interface and match the app to a registered service before browsing the app. Once the registered-service interface reports the agent login is ready, the agent-side login is ready. If that interface provides an app URL, use it as the service-provided third-party app surface; it should look like the service's normal Login with Slock callback and not require you to understand Slock's internal grant/request protocol. Do not crawl third-party routes looking for a session before trying the registered-service login path. Do not open the human \`Login with Slock\` browser flow or treat internal request IDs as OAuth callback codes unless a human explicitly asks you to debug that server-to-server protocol. If the service or human asks for your Slock Agent identity card, use your Slock profile view. Third-party pages may show \`Login with Slock\`; for agent-facing access, prefer the registered service / Slock Agent Login path.`;
|
|
1179
1180
|
const readingHistorySection = isCli ? `### Reading history
|
|
@@ -1548,6 +1549,17 @@ var proxyServerState = null;
|
|
|
1548
1549
|
var proxyServerStartPromise = null;
|
|
1549
1550
|
var proxyServerFactory = createProxyServer;
|
|
1550
1551
|
var DECODED_RESPONSE_HEADERS = /* @__PURE__ */ new Set(["content-encoding", "content-length", "transfer-encoding"]);
|
|
1552
|
+
var HOP_BY_HOP_REQUEST_HEADERS = /* @__PURE__ */ new Set([
|
|
1553
|
+
"connection",
|
|
1554
|
+
"keep-alive",
|
|
1555
|
+
"proxy-authenticate",
|
|
1556
|
+
"proxy-authorization",
|
|
1557
|
+
"proxy-connection",
|
|
1558
|
+
"te",
|
|
1559
|
+
"trailer",
|
|
1560
|
+
"transfer-encoding",
|
|
1561
|
+
"upgrade"
|
|
1562
|
+
]);
|
|
1551
1563
|
var LOCAL_HELD_CONTEXT_LIMIT = 3;
|
|
1552
1564
|
var AGENT_CREDENTIAL_PROXY_HOST = "127.0.0.1";
|
|
1553
1565
|
var AGENT_CREDENTIAL_PROXY_BIND_MAX_ATTEMPTS = 3;
|
|
@@ -1647,9 +1659,12 @@ async function handleProxyRequest(req, res) {
|
|
|
1647
1659
|
target = new URL2(req.url ?? "/", registration.serverUrl);
|
|
1648
1660
|
const headers = new Headers();
|
|
1649
1661
|
for (const [name, value] of Object.entries(req.headers)) {
|
|
1662
|
+
const normalizedName = name.toLowerCase();
|
|
1650
1663
|
if (value === void 0) continue;
|
|
1651
|
-
if (
|
|
1652
|
-
if (
|
|
1664
|
+
if (normalizedName === "host") continue;
|
|
1665
|
+
if (normalizedName === "authorization") continue;
|
|
1666
|
+
if (normalizedName === "content-length") continue;
|
|
1667
|
+
if (HOP_BY_HOP_REQUEST_HEADERS.has(normalizedName)) continue;
|
|
1653
1668
|
if (Array.isArray(value)) {
|
|
1654
1669
|
for (const item of value) headers.append(name, item);
|
|
1655
1670
|
} else {
|
|
@@ -1660,7 +1675,15 @@ async function handleProxyRequest(req, res) {
|
|
|
1660
1675
|
headers.set("X-Agent-Id", registration.agentId);
|
|
1661
1676
|
headers.set("X-Slock-Client", "cli");
|
|
1662
1677
|
headers.set("X-Slock-Agent-Active-Capabilities", registration.activeCapabilities);
|
|
1663
|
-
let body
|
|
1678
|
+
let body;
|
|
1679
|
+
let rawBodyBuffer;
|
|
1680
|
+
if (method !== "GET" && method !== "HEAD") {
|
|
1681
|
+
rawBodyBuffer = await readRequestBody(req);
|
|
1682
|
+
const bodyBuffer = new ArrayBuffer(rawBodyBuffer.byteLength);
|
|
1683
|
+
new Uint8Array(bodyBuffer).set(rawBodyBuffer);
|
|
1684
|
+
body = bodyBuffer;
|
|
1685
|
+
headers.set("content-length", String(rawBodyBuffer.byteLength));
|
|
1686
|
+
}
|
|
1664
1687
|
let sendTarget;
|
|
1665
1688
|
const sideEffectAction = agentApiSideEffectAction(target.pathname);
|
|
1666
1689
|
if (method === "GET" && target.pathname === "/internal/agent-api/events") {
|
|
@@ -1672,7 +1695,7 @@ async function handleProxyRequest(req, res) {
|
|
|
1672
1695
|
}
|
|
1673
1696
|
}
|
|
1674
1697
|
if (method === "POST" && sideEffectAction) {
|
|
1675
|
-
const rawBody =
|
|
1698
|
+
const rawBody = rawBodyBuffer?.toString("utf8") ?? "";
|
|
1676
1699
|
const prepared = await prepareAgentApiSideEffectForward(registration, headers, rawBody, sideEffectAction);
|
|
1677
1700
|
if (prepared.localResponse) {
|
|
1678
1701
|
const responseText = JSON.stringify(prepared.localResponse);
|
|
@@ -1688,10 +1711,13 @@ async function handleProxyRequest(req, res) {
|
|
|
1688
1711
|
const upstream = await daemonFetch(target, {
|
|
1689
1712
|
method,
|
|
1690
1713
|
headers,
|
|
1691
|
-
body
|
|
1692
|
-
// Required by undici when forwarding a Node stream.
|
|
1693
|
-
duplex: body ? "half" : void 0
|
|
1714
|
+
body
|
|
1694
1715
|
});
|
|
1716
|
+
if (upstream.status >= 500) {
|
|
1717
|
+
registration.inboxCoordinator?.recordTransportNormalizedError?.(
|
|
1718
|
+
transportNormalizedErrorForHttpStatus(target, upstream.status, registration.launchId)
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1695
1721
|
if (shouldBufferJsonResponse(upstream, target.pathname, registration)) {
|
|
1696
1722
|
const responseText = await upstream.text();
|
|
1697
1723
|
consumeVisibleResponse(registration, target, sendTarget, responseText);
|
|
@@ -1714,9 +1740,12 @@ async function handleProxyRequest(req, res) {
|
|
|
1714
1740
|
} catch (err) {
|
|
1715
1741
|
const failure = proxyFailureForError(method, target, err);
|
|
1716
1742
|
logger.warn(
|
|
1717
|
-
`[Agent Credential Proxy] request failed (agent=${registration.agentId}, launch=${registration.launchId ?? "none"}, method=${failure.method}, path=${failure.pathname}, query_keys=${failure.queryKeys.join(",") || "none"}): ${failure.errorName}: ${failure.errorMessage}`
|
|
1743
|
+
`[Agent Credential Proxy] request failed (agent=${registration.agentId}, launch=${registration.launchId ?? "none"}, method=${failure.method}, path=${failure.pathname}, query_keys=${failure.queryKeys.join(",") || "none"}): ${failure.errorName}: ${failure.errorMessage}${failure.errorCause ? ` (cause=${failure.errorCause})` : ""}`
|
|
1718
1744
|
);
|
|
1719
1745
|
registration.inboxCoordinator?.recordProxyFailure?.(failure);
|
|
1746
|
+
registration.inboxCoordinator?.recordTransportNormalizedError?.(
|
|
1747
|
+
transportNormalizedErrorForError(target, err, registration.launchId)
|
|
1748
|
+
);
|
|
1720
1749
|
writeProxyFailureResponse(res, failure);
|
|
1721
1750
|
}
|
|
1722
1751
|
}
|
|
@@ -1735,25 +1764,125 @@ function writeProxyFailureResponse(res, failure) {
|
|
|
1735
1764
|
}
|
|
1736
1765
|
function proxyFailureForError(method, target, err) {
|
|
1737
1766
|
const queryKeys = target ? [.../* @__PURE__ */ new Set([...target.searchParams.keys()])].sort() : [];
|
|
1738
|
-
|
|
1767
|
+
const cause = err instanceof Error ? err.cause : void 0;
|
|
1768
|
+
const failure = {
|
|
1739
1769
|
method,
|
|
1740
1770
|
pathname: target?.pathname ?? "unknown",
|
|
1741
1771
|
queryKeys,
|
|
1742
1772
|
errorName: err instanceof Error ? err.name : typeof err,
|
|
1743
1773
|
errorMessage: truncateProxyErrorMessage(err instanceof Error ? err.message : String(err))
|
|
1744
1774
|
};
|
|
1775
|
+
const errorCause = describeProxyErrorCause(cause);
|
|
1776
|
+
if (errorCause) failure.errorCause = errorCause;
|
|
1777
|
+
return failure;
|
|
1778
|
+
}
|
|
1779
|
+
function describeProxyErrorCause(cause) {
|
|
1780
|
+
if (!cause) return void 0;
|
|
1781
|
+
if (cause instanceof Error) {
|
|
1782
|
+
const errorWithCode = cause;
|
|
1783
|
+
const code = typeof errorWithCode.code === "string" ? errorWithCode.code : void 0;
|
|
1784
|
+
return truncateProxyErrorMessage([code, cause.message].filter(Boolean).join(" "));
|
|
1785
|
+
}
|
|
1786
|
+
if (typeof cause === "object") {
|
|
1787
|
+
const causeObject = cause;
|
|
1788
|
+
const code = typeof causeObject.code === "string" ? causeObject.code : void 0;
|
|
1789
|
+
const message = typeof causeObject.message === "string" ? causeObject.message : void 0;
|
|
1790
|
+
const detail = [code, message].filter(Boolean).join(" ");
|
|
1791
|
+
if (detail) return truncateProxyErrorMessage(detail);
|
|
1792
|
+
}
|
|
1793
|
+
return truncateProxyErrorMessage(String(cause));
|
|
1745
1794
|
}
|
|
1746
1795
|
function truncateProxyErrorMessage(message) {
|
|
1747
1796
|
const normalized = message.replace(/\s+/g, " ").trim();
|
|
1748
1797
|
return normalized.length > 500 ? `${normalized.slice(0, 497)}...` : normalized;
|
|
1749
1798
|
}
|
|
1799
|
+
function transportNormalizedErrorForHttpStatus(target, status, launchId) {
|
|
1800
|
+
return {
|
|
1801
|
+
normalizedCode: "server_5xx",
|
|
1802
|
+
routeFamily: routeFamilyForPath(target.pathname),
|
|
1803
|
+
responseStarted: true,
|
|
1804
|
+
upstreamLayer: "http_status",
|
|
1805
|
+
upstreamStatus: status,
|
|
1806
|
+
launchId,
|
|
1807
|
+
targetHostClass: daemonUpstreamTargetHostClass(target),
|
|
1808
|
+
// Today the local credential proxy is only used by CLI wrappers. If runtime
|
|
1809
|
+
// or daemon-internal callers use it later, plumb the caller identity here.
|
|
1810
|
+
downstreamCaller: "cli",
|
|
1811
|
+
upstream: "server"
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
function transportNormalizedErrorForError(target, err, launchId) {
|
|
1815
|
+
return {
|
|
1816
|
+
normalizedCode: "transport_failure",
|
|
1817
|
+
routeFamily: routeFamilyForPath(target?.pathname ?? "unknown"),
|
|
1818
|
+
responseStarted: false,
|
|
1819
|
+
upstreamLayer: target ? upstreamLayerForProxyError(err) : "unknown",
|
|
1820
|
+
originalMessage: sanitizeTransportOriginalMessage(err instanceof Error ? err.message : String(err)),
|
|
1821
|
+
launchId,
|
|
1822
|
+
targetHostClass: target ? daemonUpstreamTargetHostClass(target) : "custom_server",
|
|
1823
|
+
// Today the local credential proxy is only used by CLI wrappers. If runtime
|
|
1824
|
+
// or daemon-internal callers use it later, plumb the caller identity here.
|
|
1825
|
+
downstreamCaller: "cli",
|
|
1826
|
+
upstream: "server"
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
function routeFamilyForPath(pathname) {
|
|
1830
|
+
if (pathname === "/internal/agent-api/send") return "agent-api/send";
|
|
1831
|
+
if (pathname === "/internal/agent-api/events") return "agent-api/events";
|
|
1832
|
+
if (pathname === "/internal/agent-api/receive-ack") return "agent-api/events";
|
|
1833
|
+
if (pathname === "/internal/agent-api/tasks/claim") return "tasks/claim";
|
|
1834
|
+
if (pathname === "/internal/agent-api/tasks/update-status") return "tasks/update";
|
|
1835
|
+
if (pathname === "/internal/agent-api/tasks" || pathname.startsWith("/internal/agent-api/tasks/")) return "tasks";
|
|
1836
|
+
if (pathname.startsWith("/internal/agent-api/attachments/")) return "agent-api/attachments";
|
|
1837
|
+
if (/^\/internal\/agent-api\/messages\/[^/]+\/reactions$/.test(pathname)) return "agent-api/messages/reactions";
|
|
1838
|
+
if (pathname === "/internal/agent-api/server") return "server";
|
|
1839
|
+
if (pathname.startsWith("/internal/agent-api/history")) return "agent-api/events";
|
|
1840
|
+
if (pathname.startsWith("/internal/agent-api/search")) return "agent-api/events";
|
|
1841
|
+
if (pathname.startsWith("/internal/agent-api/channel-members")) return "channel-members";
|
|
1842
|
+
if (pathname.startsWith("/internal/agent-api/knowledge")) return "knowledge";
|
|
1843
|
+
if (pathname === "/internal/agent-api/profile" || pathname.startsWith("/internal/agent-api/profile/")) return "profile";
|
|
1844
|
+
if (pathname === "/internal/agent-api/integrations" || pathname.startsWith("/internal/agent-api/integrations/")) return "integrations";
|
|
1845
|
+
if (pathname === "/internal/agent-api/upload") return "attachments/upload";
|
|
1846
|
+
if (pathname === "/internal/agent-api/resolve-channel") return "resolve-channel";
|
|
1847
|
+
if (pathname === "/internal/agent-api/threads/unfollow") return "threads/unfollow";
|
|
1848
|
+
if (pathname === "/internal/agent-api/prepare-action") return "action/prepare";
|
|
1849
|
+
if (pathname === "/internal/agent-api/reminders" || pathname.startsWith("/internal/agent-api/reminders/")) return "reminders";
|
|
1850
|
+
if (/^\/internal\/agent-api\/channels\/[^/]+\/join$/.test(pathname)) return "channels/join";
|
|
1851
|
+
if (/^\/internal\/agent-api\/channels\/[^/]+\/leave$/.test(pathname)) return "channels/leave";
|
|
1852
|
+
return "unknown";
|
|
1853
|
+
}
|
|
1854
|
+
function daemonUpstreamTargetHostClass(url) {
|
|
1855
|
+
const hostname = url.hostname.toLowerCase();
|
|
1856
|
+
if (hostname === "api.slock.ai") return "api.slock.ai";
|
|
1857
|
+
return "custom_server";
|
|
1858
|
+
}
|
|
1859
|
+
function upstreamLayerForProxyError(err) {
|
|
1860
|
+
const code = errorCode(err).toUpperCase();
|
|
1861
|
+
const message = (err instanceof Error ? err.message : String(err)).toLowerCase();
|
|
1862
|
+
if (code === "ENOTFOUND" || code === "EAI_AGAIN" || message.includes("dns")) return "dns";
|
|
1863
|
+
if (code === "ECONNREFUSED" || code === "ECONNRESET" || code === "EPIPE" || code === "UND_ERR_SOCKET" || message.includes("socket")) return "tcp";
|
|
1864
|
+
if (code.includes("TLS") || message.includes("certificate") || message.includes("tls")) return "tls";
|
|
1865
|
+
if (code === "UND_ERR_HEADERS_TIMEOUT" || code === "UND_ERR_BODY_TIMEOUT" || message.includes("timeout")) return "read_timeout";
|
|
1866
|
+
if (message.includes("proxy")) return "proxy_connect";
|
|
1867
|
+
if (message.includes("fly")) return "fly_edge";
|
|
1868
|
+
return "unknown";
|
|
1869
|
+
}
|
|
1870
|
+
function errorCode(err) {
|
|
1871
|
+
if (typeof err === "object" && err && "code" in err && typeof err.code === "string") {
|
|
1872
|
+
return err.code;
|
|
1873
|
+
}
|
|
1874
|
+
if (typeof err === "object" && err && "cause" in err) return errorCode(err.cause);
|
|
1875
|
+
return "";
|
|
1876
|
+
}
|
|
1877
|
+
function sanitizeTransportOriginalMessage(message) {
|
|
1878
|
+
return truncateProxyErrorMessage(message).replace(/sk_(?:agent|machine|computer)_[A-Za-z0-9_-]+/g, "sk_[redacted]").replace(/sap_[A-Za-z0-9_-]+/g, "sap_[redacted]").replace(/https?:\/\/\S+/g, "[url]");
|
|
1879
|
+
}
|
|
1750
1880
|
async function readRequestBody(req) {
|
|
1751
|
-
|
|
1752
|
-
req.setEncoding("utf8");
|
|
1881
|
+
const chunks = [];
|
|
1753
1882
|
for await (const chunk of req) {
|
|
1754
|
-
|
|
1883
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
1755
1884
|
}
|
|
1756
|
-
return
|
|
1885
|
+
return Buffer.concat(chunks);
|
|
1757
1886
|
}
|
|
1758
1887
|
function messageSeq(message) {
|
|
1759
1888
|
return Number(message.seq ?? 0);
|
|
@@ -1928,7 +2057,7 @@ async function loadRecentTargetMessages(registration, headers, target) {
|
|
|
1928
2057
|
const historyHeaders = new Headers(headers);
|
|
1929
2058
|
historyHeaders.delete("content-length");
|
|
1930
2059
|
historyHeaders.delete("content-type");
|
|
1931
|
-
const res = await
|
|
2060
|
+
const res = await fetch(historyUrl, { method: "GET", headers: historyHeaders });
|
|
1932
2061
|
if (!res.ok) return [];
|
|
1933
2062
|
const parsed = await res.json().catch(() => null);
|
|
1934
2063
|
return Array.isArray(parsed?.messages) ? normalizeVisibleMessages(parsed.messages, target) : [];
|
|
@@ -2131,6 +2260,7 @@ var shellSingleQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
|
|
|
2131
2260
|
var powershellSingleQuote = (value) => `'${value.replace(/'/g, "''")}'`;
|
|
2132
2261
|
var DEFAULT_ACTIVE_CAPABILITIES = "send,read,mentions,tasks,reactions,server,channels,knowledge";
|
|
2133
2262
|
var LOOPBACK_NO_PROXY = "127.0.0.1,localhost";
|
|
2263
|
+
var CLI_TRANSPORT_TRACE_DIR_ENV = "SLOCK_CLI_TRANSPORT_TRACE_DIR";
|
|
2134
2264
|
var safePathPart = (value) => value.replace(/[^a-zA-Z0-9_.-]/g, "_");
|
|
2135
2265
|
var RAW_CREDENTIAL_ENV_DENYLIST = [
|
|
2136
2266
|
"SLOCK_AGENT_CREDENTIAL_KEY"
|
|
@@ -2343,6 +2473,7 @@ exec ${shellSingleQuote(process.execPath)} ${shellSingleQuote(opencliBinPath)} "
|
|
|
2343
2473
|
[SLOCK_HOME_ENV]: slockHome,
|
|
2344
2474
|
SLOCK_AGENT_ID: ctx.agentId,
|
|
2345
2475
|
...ctx.launchId ? { SLOCK_AGENT_LAUNCH_ID: ctx.launchId } : {},
|
|
2476
|
+
...ctx.cliTransportTraceDir ? { [CLI_TRANSPORT_TRACE_DIR_ENV]: ctx.cliTransportTraceDir } : {},
|
|
2346
2477
|
SLOCK_SERVER_URL: ctx.config.serverUrl,
|
|
2347
2478
|
...agentCredentialProxy ? {} : { SLOCK_AGENT_TOKEN_FILE: tokenFile },
|
|
2348
2479
|
PATH: `${slockDir}${path2.delimiter}${process.env.PATH ?? ""}`
|
|
@@ -6617,6 +6748,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6617
6748
|
driverResolver;
|
|
6618
6749
|
defaultAgentEnvVarsProvider;
|
|
6619
6750
|
tracer;
|
|
6751
|
+
cliTransportTraceDir = null;
|
|
6620
6752
|
deliveryTraceContexts = /* @__PURE__ */ new WeakMap();
|
|
6621
6753
|
processExitTraceAttrs = /* @__PURE__ */ new WeakMap();
|
|
6622
6754
|
agentVisibleBoundaries = /* @__PURE__ */ new Map();
|
|
@@ -6647,6 +6779,9 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6647
6779
|
setTracer(tracer) {
|
|
6648
6780
|
this.tracer = tracer;
|
|
6649
6781
|
}
|
|
6782
|
+
setCliTransportTraceDir(traceDir) {
|
|
6783
|
+
this.cliTransportTraceDir = traceDir;
|
|
6784
|
+
}
|
|
6650
6785
|
visibleBoundaryMap(agentId) {
|
|
6651
6786
|
let map = this.agentVisibleBoundaries.get(agentId);
|
|
6652
6787
|
if (!map) {
|
|
@@ -6751,6 +6886,7 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6751
6886
|
});
|
|
6752
6887
|
},
|
|
6753
6888
|
recordProxyFailure: (input) => this.recordAgentProxyFailure(agentId, input),
|
|
6889
|
+
recordTransportNormalizedError: (input) => this.recordAgentProxyTransportNormalizedError(agentId, input),
|
|
6754
6890
|
recordFreshnessDecision: (input) => {
|
|
6755
6891
|
this.recordDaemonTrace("daemon.agent.inbox.freshness_decision", {
|
|
6756
6892
|
agentId,
|
|
@@ -6779,6 +6915,22 @@ var AgentProcessManager = class _AgentProcessManager {
|
|
|
6779
6915
|
error_message: input.errorMessage
|
|
6780
6916
|
}, "error");
|
|
6781
6917
|
}
|
|
6918
|
+
recordAgentProxyTransportNormalizedError(agentId, input) {
|
|
6919
|
+
this.recordDaemonTrace("daemon.transport.normalized_error", {
|
|
6920
|
+
producer: "daemon",
|
|
6921
|
+
agentId,
|
|
6922
|
+
normalized_code: input.normalizedCode,
|
|
6923
|
+
route_family: input.routeFamily,
|
|
6924
|
+
response_started: input.responseStarted,
|
|
6925
|
+
upstream_layer: input.upstreamLayer,
|
|
6926
|
+
...typeof input.upstreamStatus === "number" ? { upstream_status: input.upstreamStatus } : {},
|
|
6927
|
+
...input.originalMessage ? { original_message: input.originalMessage } : {},
|
|
6928
|
+
launchId: input.launchId,
|
|
6929
|
+
target_host_class: input.targetHostClass,
|
|
6930
|
+
downstream_caller: input.downstreamCaller,
|
|
6931
|
+
upstream: input.upstream
|
|
6932
|
+
}, "error");
|
|
6933
|
+
}
|
|
6782
6934
|
recordFreshnessDecisionActivity(agentId, input) {
|
|
6783
6935
|
if (input.decision !== "local_hold" && input.decision !== "syncing_hold") return;
|
|
6784
6936
|
const ap = this.agents.get(agentId);
|
|
@@ -7178,7 +7330,8 @@ Use ${communicationCommand(driver, "read_history")} to catch up on the channels
|
|
|
7178
7330
|
slockCliPath: this.slockCliPath,
|
|
7179
7331
|
daemonApiKey: this.daemonApiKey,
|
|
7180
7332
|
launchId: launchId || null,
|
|
7181
|
-
agentCredentialProxyInboxCoordinator: this.createAgentProxyInboxCoordinator(agentId)
|
|
7333
|
+
agentCredentialProxyInboxCoordinator: this.createAgentProxyInboxCoordinator(agentId),
|
|
7334
|
+
cliTransportTraceDir: this.cliTransportTraceDir
|
|
7182
7335
|
});
|
|
7183
7336
|
this.recordDaemonTrace("daemon.agent.spawn.created", {
|
|
7184
7337
|
...this.startQueueTraceAttrs(agentId, effectiveConfig, wakeMessage, unreadSummary, resumePrompt, launchId),
|
|
@@ -9880,7 +10033,8 @@ var DIAGNOSTIC_ERROR_ATTRS = /* @__PURE__ */ new Set([
|
|
|
9880
10033
|
"runtime_error_message_present",
|
|
9881
10034
|
"runtime_error_message_length_bucket",
|
|
9882
10035
|
"runtime_error_message_truncated",
|
|
9883
|
-
"runtime_error_message_excerpt"
|
|
10036
|
+
"runtime_error_message_excerpt",
|
|
10037
|
+
"original_message"
|
|
9884
10038
|
]);
|
|
9885
10039
|
var LocalRotatingTraceSink = class {
|
|
9886
10040
|
traceDir;
|
|
@@ -9974,14 +10128,13 @@ function sanitizeAttrs(attrs) {
|
|
|
9974
10128
|
if (!attrs) return void 0;
|
|
9975
10129
|
const sanitized = {};
|
|
9976
10130
|
for (const [key, value] of Object.entries(attrs)) {
|
|
10131
|
+
if (value === null || value === void 0 || value === "") continue;
|
|
9977
10132
|
if (isDiagnosticIdAttr(key)) {
|
|
9978
|
-
if (value === null || value === void 0 || value === "") continue;
|
|
9979
10133
|
sanitized[key] = sanitizeValue(value);
|
|
9980
10134
|
continue;
|
|
9981
10135
|
}
|
|
9982
10136
|
if (isDiagnosticErrorAttr(key)) {
|
|
9983
|
-
|
|
9984
|
-
sanitized[key] = sanitizeValue(value);
|
|
10137
|
+
sanitized[key] = sanitizeDiagnosticErrorValue(key, value);
|
|
9985
10138
|
continue;
|
|
9986
10139
|
}
|
|
9987
10140
|
if (shouldDropAttr(key)) continue;
|
|
@@ -10001,6 +10154,11 @@ function sanitizeValue(value) {
|
|
|
10001
10154
|
}
|
|
10002
10155
|
return String(value);
|
|
10003
10156
|
}
|
|
10157
|
+
function sanitizeDiagnosticErrorValue(key, value) {
|
|
10158
|
+
if (key !== "original_message" || typeof value !== "string") return sanitizeValue(value);
|
|
10159
|
+
const normalized = value.replace(/sk_(?:agent|machine|computer)_[A-Za-z0-9_-]+/g, "sk_[redacted]").replace(/sap_[A-Za-z0-9_-]+/g, "sap_[redacted]").replace(/https?:\/\/\S+/g, "[url]").replace(/\s+/g, " ").trim();
|
|
10160
|
+
return normalized.length > 240 ? `${normalized.slice(0, 237)}...` : normalized;
|
|
10161
|
+
}
|
|
10004
10162
|
function shouldDropAttr(key) {
|
|
10005
10163
|
const normalized = key.replace(/([a-z0-9])([A-Z])/g, "$1_$2").toLowerCase();
|
|
10006
10164
|
if (/(^|_)(api_key|auth_token|token|secret|password|cookie|credential)(_|$)/i.test(normalized)) {
|
|
@@ -10648,6 +10806,7 @@ var DaemonCore = class {
|
|
|
10648
10806
|
sink: this.localTraceSink
|
|
10649
10807
|
});
|
|
10650
10808
|
this.agentManager.setTracer(this.tracer);
|
|
10809
|
+
this.agentManager.setCliTransportTraceDir(path16.join(machineDir, "traces"));
|
|
10651
10810
|
}
|
|
10652
10811
|
installTraceBundleUploader(machineDir) {
|
|
10653
10812
|
if (!this.shouldEnableLocalTrace()) return;
|