hoomanjs 1.37.0 → 1.37.2
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/acp/acp-agent.js +128 -2
- package/dist/acp/acp-agent.js.map +1 -1
- package/dist/acp/commands.js +5 -0
- package/dist/acp/commands.js.map +1 -1
- package/dist/acp/session-config.d.ts +2 -0
- package/dist/acp/session-config.js +27 -0
- package/dist/acp/session-config.js.map +1 -1
- package/dist/chat/app.js +71 -58
- package/dist/chat/app.js.map +1 -1
- package/dist/chat/components/BottomChrome.d.ts +2 -1
- package/dist/chat/components/BottomChrome.js +2 -2
- package/dist/chat/components/BottomChrome.js.map +1 -1
- package/dist/chat/components/ChromePicker.d.ts +3 -2
- package/dist/chat/components/ChromePicker.js +15 -1
- package/dist/chat/components/ChromePicker.js.map +1 -1
- package/dist/chat/steering.d.ts +1 -20
- package/dist/chat/steering.js +3 -66
- package/dist/chat/steering.js.map +1 -1
- package/dist/core/agent/index.js +3 -2
- package/dist/core/agent/index.js.map +1 -1
- package/dist/core/agent/turn-steering.d.ts +39 -0
- package/dist/core/agent/turn-steering.js +80 -0
- package/dist/core/agent/turn-steering.js.map +1 -0
- package/dist/core/approvals/channel-ask.d.ts +27 -0
- package/dist/core/approvals/channel-ask.js +104 -0
- package/dist/core/approvals/channel-ask.js.map +1 -0
- package/dist/core/models/reasoning-effort.d.ts +55 -0
- package/dist/core/models/reasoning-effort.js +91 -0
- package/dist/core/models/reasoning-effort.js.map +1 -0
- package/dist/core/prompts/harness/execution.md +1 -0
- package/dist/core/sessions/tolerant-file-storage.d.ts +24 -0
- package/dist/core/sessions/tolerant-file-storage.js +81 -0
- package/dist/core/sessions/tolerant-file-storage.js.map +1 -0
- package/dist/daemon/approvals.js +2 -90
- package/dist/daemon/approvals.js.map +1 -1
- package/dist/index.d.ts +17 -2
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"turn-steering.js","sourceRoot":"","sources":["../../../src/core/agent/turn-steering.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Manager as McpManager } from "../mcp/index.js";
|
|
2
|
+
import type { ToolApprovalAsk } from "./intervention.js";
|
|
3
|
+
/** Metadata a channel-driven job (daemon, bot, etc.) stashes on `appState.origin`. */
|
|
4
|
+
export type ChannelOrigin = {
|
|
5
|
+
server?: string;
|
|
6
|
+
source?: string;
|
|
7
|
+
user?: string;
|
|
8
|
+
session?: string;
|
|
9
|
+
thread?: string;
|
|
10
|
+
};
|
|
11
|
+
/** Reads the `origin` an {@link McpManager}-backed channel job stashes on `appState`. */
|
|
12
|
+
export declare function readChannelOrigin(rawAgent: {
|
|
13
|
+
appState: {
|
|
14
|
+
get(key: string): unknown;
|
|
15
|
+
};
|
|
16
|
+
}): ChannelOrigin | null;
|
|
17
|
+
/**
|
|
18
|
+
* Builds a {@link ToolApprovalAsk} that resolves tool approvals over
|
|
19
|
+
* `hooman/channel/permission` — the remote-approval capability MCP servers
|
|
20
|
+
* advertise for channel-driven jobs (daemon mode, chat bots, etc.) that have
|
|
21
|
+
* no local human to prompt. Pair with {@link HoomanToolApprovalIntervention}.
|
|
22
|
+
*
|
|
23
|
+
* Requires the job's `appState.origin` to carry the originating channel
|
|
24
|
+
* server name (see {@link readChannelOrigin}); jobs without one, or servers
|
|
25
|
+
* that don't support the capability, are rejected.
|
|
26
|
+
*/
|
|
27
|
+
export declare function createChannelPermissionAsk(manager: McpManager): ToolApprovalAsk;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const TOOL_DESCRIPTION_PREVIEW_LIMIT = 50;
|
|
2
|
+
const TOOL_ARGS_PREVIEW_LIMIT = 50;
|
|
3
|
+
function randomRequestId() {
|
|
4
|
+
return crypto.randomUUID();
|
|
5
|
+
}
|
|
6
|
+
function truncateWithEllipsis(text, max) {
|
|
7
|
+
return text.length > max ? `${text.slice(0, max)}…` : text;
|
|
8
|
+
}
|
|
9
|
+
function truncateWithHiddenCharCount(text, max) {
|
|
10
|
+
if (text.length <= max) {
|
|
11
|
+
return text;
|
|
12
|
+
}
|
|
13
|
+
const hidden = text.length - max;
|
|
14
|
+
return `${text.slice(0, max)}…(${hidden} chars)`;
|
|
15
|
+
}
|
|
16
|
+
function inputPreview(input) {
|
|
17
|
+
try {
|
|
18
|
+
const text = JSON.stringify(input) ?? "null";
|
|
19
|
+
return truncateWithHiddenCharCount(text, TOOL_ARGS_PREVIEW_LIMIT);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return truncateWithHiddenCharCount(String(input), TOOL_ARGS_PREVIEW_LIMIT);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** Reads the `origin` an {@link McpManager}-backed channel job stashes on `appState`. */
|
|
26
|
+
export function readChannelOrigin(rawAgent) {
|
|
27
|
+
const raw = rawAgent.appState.get("origin");
|
|
28
|
+
if (!raw || typeof raw !== "object") {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const entry = raw;
|
|
32
|
+
const text = (value) => {
|
|
33
|
+
if (typeof value !== "string") {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
const trimmed = value.trim();
|
|
37
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
38
|
+
};
|
|
39
|
+
return {
|
|
40
|
+
server: text(entry.server),
|
|
41
|
+
source: text(entry.source),
|
|
42
|
+
user: text(entry.user),
|
|
43
|
+
session: text(entry.session),
|
|
44
|
+
thread: text(entry.thread),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Builds a {@link ToolApprovalAsk} that resolves tool approvals over
|
|
49
|
+
* `hooman/channel/permission` — the remote-approval capability MCP servers
|
|
50
|
+
* advertise for channel-driven jobs (daemon mode, chat bots, etc.) that have
|
|
51
|
+
* no local human to prompt. Pair with {@link HoomanToolApprovalIntervention}.
|
|
52
|
+
*
|
|
53
|
+
* Requires the job's `appState.origin` to carry the originating channel
|
|
54
|
+
* server name (see {@link readChannelOrigin}); jobs without one, or servers
|
|
55
|
+
* that don't support the capability, are rejected.
|
|
56
|
+
*/
|
|
57
|
+
export function createChannelPermissionAsk(manager) {
|
|
58
|
+
return async (request, event) => {
|
|
59
|
+
const origin = readChannelOrigin(event.agent);
|
|
60
|
+
if (!origin?.server) {
|
|
61
|
+
return {
|
|
62
|
+
decision: "reject",
|
|
63
|
+
reason: `Tool "${request.toolName}" was denied: missing channel origin context.`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
const supported = await manager.supportsChannelPermission(origin.server);
|
|
67
|
+
if (!supported) {
|
|
68
|
+
return {
|
|
69
|
+
decision: "reject",
|
|
70
|
+
reason: `Tool "${request.toolName}" was denied: MCP server "${origin.server}" does not support hooman/channel/permission.`,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const behavior = await manager.requestChannelPermission(origin.server, {
|
|
75
|
+
requestId: randomRequestId(),
|
|
76
|
+
tool: request.toolName,
|
|
77
|
+
description: truncateWithEllipsis(request.description?.trim() ??
|
|
78
|
+
`Run tool "${request.toolName}" via channel.`, TOOL_DESCRIPTION_PREVIEW_LIMIT),
|
|
79
|
+
preview: inputPreview(request.input),
|
|
80
|
+
source: origin.source,
|
|
81
|
+
user: origin.user,
|
|
82
|
+
session: origin.session,
|
|
83
|
+
thread: origin.thread,
|
|
84
|
+
});
|
|
85
|
+
if (behavior === "allow_once") {
|
|
86
|
+
return "allow";
|
|
87
|
+
}
|
|
88
|
+
if (behavior === "allow_always") {
|
|
89
|
+
return "always";
|
|
90
|
+
}
|
|
91
|
+
return {
|
|
92
|
+
decision: "reject",
|
|
93
|
+
reason: `Tool "${request.toolName}" was rejected by remote approval.`,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
return {
|
|
98
|
+
decision: "reject",
|
|
99
|
+
reason: `Tool "${request.toolName}" was denied: failed to request permission (${error instanceof Error ? error.message : String(error)}).`,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=channel-ask.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel-ask.js","sourceRoot":"","sources":["../../../src/core/approvals/channel-ask.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { Config } from "../config.js";
|
|
2
|
+
/**
|
|
3
|
+
* Shared reasoning-effort helpers used by both the chat TUI and the ACP agent
|
|
4
|
+
* so the two front-ends cycle/set/persist effort identically.
|
|
5
|
+
*
|
|
6
|
+
* Effort is stored under a provider's `options.reasoning.effort`. Its presence
|
|
7
|
+
* enables thinking; the level is forwarded where the backend supports it. The
|
|
8
|
+
* `undefined` rung means "off" (no reasoning), so a single control can also
|
|
9
|
+
* disable thinking.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Ordered effort rungs cycled by the chat Shift+Tab shortcut and `/effort`.
|
|
13
|
+
* `undefined` is the "off" (no reasoning) rung.
|
|
14
|
+
*/
|
|
15
|
+
export declare const REASONING_EFFORT_CYCLE: readonly [undefined, "minimal", "low", "medium", "high"];
|
|
16
|
+
/** Selectable effort levels (the {@link REASONING_EFFORT_CYCLE} minus "off"). */
|
|
17
|
+
export declare const REASONING_EFFORT_LEVELS: readonly ["minimal", "low", "medium", "high"];
|
|
18
|
+
/** Sentinel value used to represent the "off" rung in pickers/config options. */
|
|
19
|
+
export declare const REASONING_EFFORT_OFF = "off";
|
|
20
|
+
/** Advance one rung through {@link REASONING_EFFORT_CYCLE}, wrapping around. */
|
|
21
|
+
export declare function nextReasoningEffort(current: string | undefined, direction: 1 | -1): string | undefined;
|
|
22
|
+
/**
|
|
23
|
+
* Returns provider options with `reasoning.effort` set to `nextEffort`,
|
|
24
|
+
* preserving sibling reasoning keys and collapsing to `undefined` when the
|
|
25
|
+
* reasoning object would end up empty (so we never persist `"reasoning": {}`).
|
|
26
|
+
*/
|
|
27
|
+
export declare function withReasoningEffort(options: unknown, nextEffort: string | undefined): Record<string, unknown>;
|
|
28
|
+
/** Read `reasoning.effort` out of a provider's raw options object. */
|
|
29
|
+
export declare function readProviderEffort(options: unknown): string | undefined;
|
|
30
|
+
/** The active (default) named LLM, falling back to the first configured one. */
|
|
31
|
+
export declare function activeLlm(config: Config): {
|
|
32
|
+
name: string;
|
|
33
|
+
provider: string;
|
|
34
|
+
options: {
|
|
35
|
+
model: string;
|
|
36
|
+
temperature?: number | undefined;
|
|
37
|
+
maxTokens?: number | undefined;
|
|
38
|
+
};
|
|
39
|
+
default: boolean;
|
|
40
|
+
} | undefined;
|
|
41
|
+
/** Provider name backing the active LLM, if any is configured. */
|
|
42
|
+
export declare function activeProviderName(config: Config): string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* The effort currently applied to the active model, read from the fully
|
|
45
|
+
* resolved provider options (so overlay/session values are reflected).
|
|
46
|
+
*/
|
|
47
|
+
export declare function currentReasoningEffort(config: Config): string | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* Parse a user-typed effort argument. Recognizes the four levels plus a set of
|
|
50
|
+
* "off" aliases (mapped to `undefined`). Returns `null` for unrecognized input.
|
|
51
|
+
* Callers should handle the empty-argument case before calling this.
|
|
52
|
+
*/
|
|
53
|
+
export declare function parseReasoningEffortArg(raw: string): {
|
|
54
|
+
value: string | undefined;
|
|
55
|
+
} | null;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared reasoning-effort helpers used by both the chat TUI and the ACP agent
|
|
3
|
+
* so the two front-ends cycle/set/persist effort identically.
|
|
4
|
+
*
|
|
5
|
+
* Effort is stored under a provider's `options.reasoning.effort`. Its presence
|
|
6
|
+
* enables thinking; the level is forwarded where the backend supports it. The
|
|
7
|
+
* `undefined` rung means "off" (no reasoning), so a single control can also
|
|
8
|
+
* disable thinking.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Ordered effort rungs cycled by the chat Shift+Tab shortcut and `/effort`.
|
|
12
|
+
* `undefined` is the "off" (no reasoning) rung.
|
|
13
|
+
*/
|
|
14
|
+
export const REASONING_EFFORT_CYCLE = [
|
|
15
|
+
undefined,
|
|
16
|
+
"minimal",
|
|
17
|
+
"low",
|
|
18
|
+
"medium",
|
|
19
|
+
"high",
|
|
20
|
+
];
|
|
21
|
+
/** Selectable effort levels (the {@link REASONING_EFFORT_CYCLE} minus "off"). */
|
|
22
|
+
export const REASONING_EFFORT_LEVELS = [
|
|
23
|
+
"minimal",
|
|
24
|
+
"low",
|
|
25
|
+
"medium",
|
|
26
|
+
"high",
|
|
27
|
+
];
|
|
28
|
+
/** Sentinel value used to represent the "off" rung in pickers/config options. */
|
|
29
|
+
export const REASONING_EFFORT_OFF = "off";
|
|
30
|
+
/** Advance one rung through {@link REASONING_EFFORT_CYCLE}, wrapping around. */
|
|
31
|
+
export function nextReasoningEffort(current, direction) {
|
|
32
|
+
const currentIndex = REASONING_EFFORT_CYCLE.indexOf((current ?? undefined));
|
|
33
|
+
const from = currentIndex === -1 ? 0 : currentIndex;
|
|
34
|
+
const length = REASONING_EFFORT_CYCLE.length;
|
|
35
|
+
const nextIndex = (from + direction + length) % length;
|
|
36
|
+
return REASONING_EFFORT_CYCLE[nextIndex];
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Returns provider options with `reasoning.effort` set to `nextEffort`,
|
|
40
|
+
* preserving sibling reasoning keys and collapsing to `undefined` when the
|
|
41
|
+
* reasoning object would end up empty (so we never persist `"reasoning": {}`).
|
|
42
|
+
*/
|
|
43
|
+
export function withReasoningEffort(options, nextEffort) {
|
|
44
|
+
const base = (options ?? {});
|
|
45
|
+
const reasoning = base.reasoning;
|
|
46
|
+
const merged = { ...(reasoning ?? {}), effort: nextEffort };
|
|
47
|
+
const hasValues = Object.values(merged).some((value) => value !== undefined);
|
|
48
|
+
return { ...base, reasoning: hasValues ? merged : undefined };
|
|
49
|
+
}
|
|
50
|
+
/** Read `reasoning.effort` out of a provider's raw options object. */
|
|
51
|
+
export function readProviderEffort(options) {
|
|
52
|
+
const reasoning = options
|
|
53
|
+
?.reasoning;
|
|
54
|
+
return reasoning?.effort;
|
|
55
|
+
}
|
|
56
|
+
/** The active (default) named LLM, falling back to the first configured one. */
|
|
57
|
+
export function activeLlm(config) {
|
|
58
|
+
return config.llms.find((entry) => entry.default) ?? config.llms[0];
|
|
59
|
+
}
|
|
60
|
+
/** Provider name backing the active LLM, if any is configured. */
|
|
61
|
+
export function activeProviderName(config) {
|
|
62
|
+
return activeLlm(config)?.provider;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* The effort currently applied to the active model, read from the fully
|
|
66
|
+
* resolved provider options (so overlay/session values are reflected).
|
|
67
|
+
*/
|
|
68
|
+
export function currentReasoningEffort(config) {
|
|
69
|
+
const active = activeLlm(config);
|
|
70
|
+
if (!active) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
const resolved = config.resolveLlm(active.name);
|
|
74
|
+
return readProviderEffort(resolved?.providerOptions);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parse a user-typed effort argument. Recognizes the four levels plus a set of
|
|
78
|
+
* "off" aliases (mapped to `undefined`). Returns `null` for unrecognized input.
|
|
79
|
+
* Callers should handle the empty-argument case before calling this.
|
|
80
|
+
*/
|
|
81
|
+
export function parseReasoningEffortArg(raw) {
|
|
82
|
+
const t = raw.trim().toLowerCase();
|
|
83
|
+
if (["off", "none", "disable", "disabled", "0"].includes(t)) {
|
|
84
|
+
return { value: undefined };
|
|
85
|
+
}
|
|
86
|
+
if (REASONING_EFFORT_LEVELS.includes(t)) {
|
|
87
|
+
return { value: t };
|
|
88
|
+
}
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=reasoning-effort.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reasoning-effort.js","sourceRoot":"","sources":["../../../src/core/models/reasoning-effort.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG;IACpC,SAAS;IACT,SAAS;IACT,KAAK;IACL,QAAQ;IACR,MAAM;CACE,CAAC;AAEX,iFAAiF;AACjF,MAAM,CAAC,MAAM,uBAAuB,GAAG;IACrC,SAAS;IACT,KAAK;IACL,QAAQ;IACR,MAAM;CACE,CAAC;AAEX,iFAAiF;AACjF,MAAM,CAAC,MAAM,oBAAoB,GAAG,KAAK,CAAC;AAE1C,gFAAgF;AAChF,MAAM,UAAU,mBAAmB,CACjC,OAA2B,EAC3B,SAAiB;IAEjB,MAAM,YAAY,GAAG,sBAAsB,CAAC,OAAO,CACjD,CAAC,OAAO,IAAI,SAAS,CAA4C,CAClE,CAAC;IACF,MAAM,IAAI,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IACpD,MAAM,MAAM,GAAG,sBAAsB,CAAC,MAAM,CAAC;IAC7C,MAAM,SAAS,GAAG,CAAC,IAAI,GAAG,SAAS,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;IACvD,OAAO,sBAAsB,CAAC,SAAS,CAAC,CAAC;AAC3C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CACjC,OAAgB,EAChB,UAA8B;IAE9B,MAAM,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAA4B,CAAC;IACxD,MAAM,SAAS,GAAG,IAAI,CAAC,SAAgD,CAAC;IACxE,MAAM,MAAM,GAAG,EAAE,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IAC5D,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;IAC7E,OAAO,EAAE,GAAG,IAAI,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC;AAChE,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,kBAAkB,CAAC,OAAgB;IACjD,MAAM,SAAS,GAAI,OAA2D;QAC5E,EAAE,SAAS,CAAC;IACd,OAAO,SAAS,EAAE,MAAM,CAAC;AAC3B,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,SAAS,CAAC,MAAc;IACtC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,kBAAkB,CAAC,MAAc;IAC/C,OAAO,SAAS,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IACjC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,kBAAkB,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,uBAAuB,CACrC,GAAW;IAEX,MAAM,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACnC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5D,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC9B,CAAC;IACD,IAAK,uBAA6C,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/D,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;IACtB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -10,6 +10,7 @@ Use a simple execution loop for non-trivial tasks: understand the request, gathe
|
|
|
10
10
|
- Batch independent inspections when supported; keep dependent steps sequential.
|
|
11
11
|
- Keep raw output small with scoped reads, bounded searches, and concise command output.
|
|
12
12
|
- If a tool fails, inspect the error and adjust instead of retrying blindly.
|
|
13
|
+
- When a tool result was offloaded to external storage, pass the reference back to the retrieval tool exactly as given — copy the full reference verbatim (including any path and file extension); do not shorten, rename, or reconstruct it.
|
|
13
14
|
- Avoid destructive or broad actions when a focused inspection or edit is enough.
|
|
14
15
|
- Verify important claims with available evidence before presenting them as facts.
|
|
15
16
|
- Final replies should state the outcome, verification performed, and any remaining blocker or risk.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type Storage } from "@strands-agents/sdk/vended-plugins/context-offloader";
|
|
2
|
+
/**
|
|
3
|
+
* Host-filesystem offload storage that tolerates slightly-mangled references.
|
|
4
|
+
*
|
|
5
|
+
* The vended `FileStorage.retrieve` resolves the reference to an exact file
|
|
6
|
+
* path, so a model that copies the reference imperfectly — most commonly by
|
|
7
|
+
* dropping the content-type extension (`…_0.json` -> `…_0`) or the directory
|
|
8
|
+
* prefix — gets an unhelpful "reference not found" even though the artifact is
|
|
9
|
+
* on disk. This wrapper first tries the exact lookup, then falls back to a
|
|
10
|
+
* basename / extension-insensitive match within the artifact directory.
|
|
11
|
+
*
|
|
12
|
+
* It implements {@link Storage} directly (rather than extending `FileStorage`)
|
|
13
|
+
* so the `ContextOffloader` treats it as an opaque backend and uses it as-is
|
|
14
|
+
* (no per-agent sandbox rebinding), keeping retrieval on the host-fs path.
|
|
15
|
+
*/
|
|
16
|
+
export declare class TolerantFileStorage implements Storage {
|
|
17
|
+
#private;
|
|
18
|
+
constructor(artifactDir: string);
|
|
19
|
+
store(key: string, content: Uint8Array, contentType?: string): Promise<string>;
|
|
20
|
+
retrieve(reference: string): Promise<{
|
|
21
|
+
content: Uint8Array;
|
|
22
|
+
contentType: string;
|
|
23
|
+
}>;
|
|
24
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { basename, extname, join } from "node:path";
|
|
2
|
+
import { readdir } from "node:fs/promises";
|
|
3
|
+
import { FileStorage, } from "@strands-agents/sdk/vended-plugins/context-offloader";
|
|
4
|
+
/** Sidecar file the vended {@link FileStorage} writes; never a real reference. */
|
|
5
|
+
const METADATA_FILE = ".metadata.json";
|
|
6
|
+
/**
|
|
7
|
+
* Host-filesystem offload storage that tolerates slightly-mangled references.
|
|
8
|
+
*
|
|
9
|
+
* The vended `FileStorage.retrieve` resolves the reference to an exact file
|
|
10
|
+
* path, so a model that copies the reference imperfectly — most commonly by
|
|
11
|
+
* dropping the content-type extension (`…_0.json` -> `…_0`) or the directory
|
|
12
|
+
* prefix — gets an unhelpful "reference not found" even though the artifact is
|
|
13
|
+
* on disk. This wrapper first tries the exact lookup, then falls back to a
|
|
14
|
+
* basename / extension-insensitive match within the artifact directory.
|
|
15
|
+
*
|
|
16
|
+
* It implements {@link Storage} directly (rather than extending `FileStorage`)
|
|
17
|
+
* so the `ContextOffloader` treats it as an opaque backend and uses it as-is
|
|
18
|
+
* (no per-agent sandbox rebinding), keeping retrieval on the host-fs path.
|
|
19
|
+
*/
|
|
20
|
+
export class TolerantFileStorage {
|
|
21
|
+
#artifactDir;
|
|
22
|
+
#inner;
|
|
23
|
+
constructor(artifactDir) {
|
|
24
|
+
this.#artifactDir = artifactDir;
|
|
25
|
+
this.#inner = new FileStorage(artifactDir);
|
|
26
|
+
}
|
|
27
|
+
store(key, content, contentType) {
|
|
28
|
+
return this.#inner.store(key, content, contentType);
|
|
29
|
+
}
|
|
30
|
+
async retrieve(reference) {
|
|
31
|
+
try {
|
|
32
|
+
return await this.#inner.retrieve(reference);
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
const resolved = await this.#resolveReference(reference);
|
|
36
|
+
if (resolved && resolved !== reference) {
|
|
37
|
+
return this.#inner.retrieve(resolved);
|
|
38
|
+
}
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Best-effort match of a mangled reference to an on-disk artifact filename.
|
|
44
|
+
* Returns the resolved filename (relative to the artifact dir) or `null`.
|
|
45
|
+
*/
|
|
46
|
+
async #resolveReference(reference) {
|
|
47
|
+
let entries;
|
|
48
|
+
try {
|
|
49
|
+
entries = await readdir(this.#artifactDir);
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const candidates = entries.filter((entry) => entry !== METADATA_FILE);
|
|
55
|
+
const wanted = basename(reference.trim());
|
|
56
|
+
if (!wanted) {
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
// Exact filename (reference had the right name but a wrong/absent dir).
|
|
60
|
+
if (candidates.includes(wanted)) {
|
|
61
|
+
return join(this.#artifactDir, wanted);
|
|
62
|
+
}
|
|
63
|
+
// Extension dropped: match on the filename stem (e.g. `…_0` -> `…_0.json`).
|
|
64
|
+
const stemMatches = candidates.filter((entry) => stripExt(entry) === wanted);
|
|
65
|
+
if (stemMatches.length === 1) {
|
|
66
|
+
return join(this.#artifactDir, stemMatches[0]);
|
|
67
|
+
}
|
|
68
|
+
// Reference itself carried an extension the model altered; match by stem.
|
|
69
|
+
const wantedStem = stripExt(wanted);
|
|
70
|
+
const bothStemMatches = candidates.filter((entry) => stripExt(entry) === wantedStem);
|
|
71
|
+
if (bothStemMatches.length === 1) {
|
|
72
|
+
return join(this.#artifactDir, bothStemMatches[0]);
|
|
73
|
+
}
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function stripExt(filename) {
|
|
78
|
+
const ext = extname(filename);
|
|
79
|
+
return ext ? filename.slice(0, -ext.length) : filename;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=tolerant-file-storage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tolerant-file-storage.js","sourceRoot":"","sources":["../../../src/core/sessions/tolerant-file-storage.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon/approvals.js
CHANGED
|
@@ -1,96 +1,8 @@
|
|
|
1
|
+
import { createChannelPermissionAsk } from "../core/approvals/channel-ask.js";
|
|
1
2
|
import { HoomanToolApprovalIntervention } from "../core/approvals/intervention.js";
|
|
2
|
-
const TOOL_DESCRIPTION_PREVIEW_LIMIT = 50;
|
|
3
|
-
const TOOL_ARGS_PREVIEW_LIMIT = 50;
|
|
4
|
-
function randomRequestId() {
|
|
5
|
-
return crypto.randomUUID();
|
|
6
|
-
}
|
|
7
|
-
function truncateWithEllipsis(text, max) {
|
|
8
|
-
return text.length > max ? `${text.slice(0, max)}…` : text;
|
|
9
|
-
}
|
|
10
|
-
function truncateWithHiddenCharCount(text, max) {
|
|
11
|
-
if (text.length <= max) {
|
|
12
|
-
return text;
|
|
13
|
-
}
|
|
14
|
-
const hidden = text.length - max;
|
|
15
|
-
return `${text.slice(0, max)}…(${hidden} chars)`;
|
|
16
|
-
}
|
|
17
|
-
function inputPreview(input) {
|
|
18
|
-
try {
|
|
19
|
-
const text = JSON.stringify(input) ?? "null";
|
|
20
|
-
return truncateWithHiddenCharCount(text, TOOL_ARGS_PREVIEW_LIMIT);
|
|
21
|
-
}
|
|
22
|
-
catch {
|
|
23
|
-
return truncateWithHiddenCharCount(String(input), TOOL_ARGS_PREVIEW_LIMIT);
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function readOrigin(rawAgent) {
|
|
27
|
-
const raw = rawAgent.appState.get("origin");
|
|
28
|
-
if (!raw || typeof raw !== "object") {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
const entry = raw;
|
|
32
|
-
const text = (value) => {
|
|
33
|
-
if (typeof value !== "string") {
|
|
34
|
-
return undefined;
|
|
35
|
-
}
|
|
36
|
-
const trimmed = value.trim();
|
|
37
|
-
return trimmed.length > 0 ? trimmed : undefined;
|
|
38
|
-
};
|
|
39
|
-
return {
|
|
40
|
-
server: text(entry.server),
|
|
41
|
-
source: text(entry.source),
|
|
42
|
-
user: text(entry.user),
|
|
43
|
-
session: text(entry.session),
|
|
44
|
-
thread: text(entry.thread),
|
|
45
|
-
};
|
|
46
|
-
}
|
|
47
3
|
export function createDaemonApprovalIntervention(manager) {
|
|
48
4
|
return new HoomanToolApprovalIntervention({
|
|
49
|
-
ask:
|
|
50
|
-
const origin = readOrigin(event.agent);
|
|
51
|
-
if (!origin?.server) {
|
|
52
|
-
return {
|
|
53
|
-
decision: "reject",
|
|
54
|
-
reason: `Tool "${request.toolName}" was denied: missing daemon origin context.`,
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
const supported = await manager.supportsChannelPermission(origin.server);
|
|
58
|
-
if (!supported) {
|
|
59
|
-
return {
|
|
60
|
-
decision: "reject",
|
|
61
|
-
reason: `Tool "${request.toolName}" was denied: MCP server "${origin.server}" does not support hooman/channel/permission.`,
|
|
62
|
-
};
|
|
63
|
-
}
|
|
64
|
-
try {
|
|
65
|
-
const behavior = await manager.requestChannelPermission(origin.server, {
|
|
66
|
-
requestId: randomRequestId(),
|
|
67
|
-
tool: request.toolName,
|
|
68
|
-
description: truncateWithEllipsis(request.description?.trim() ??
|
|
69
|
-
`Run tool "${request.toolName}" in daemon mode.`, TOOL_DESCRIPTION_PREVIEW_LIMIT),
|
|
70
|
-
preview: inputPreview(request.input),
|
|
71
|
-
source: origin.source,
|
|
72
|
-
user: origin.user,
|
|
73
|
-
session: origin.session,
|
|
74
|
-
thread: origin.thread,
|
|
75
|
-
});
|
|
76
|
-
if (behavior === "allow_once") {
|
|
77
|
-
return "allow";
|
|
78
|
-
}
|
|
79
|
-
if (behavior === "allow_always") {
|
|
80
|
-
return "always";
|
|
81
|
-
}
|
|
82
|
-
return {
|
|
83
|
-
decision: "reject",
|
|
84
|
-
reason: `Tool "${request.toolName}" was rejected by remote approval.`,
|
|
85
|
-
};
|
|
86
|
-
}
|
|
87
|
-
catch (error) {
|
|
88
|
-
return {
|
|
89
|
-
decision: "reject",
|
|
90
|
-
reason: `Tool "${request.toolName}" was denied: failed to request permission (${error instanceof Error ? error.message : String(error)}).`,
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
},
|
|
5
|
+
ask: createChannelPermissionAsk(manager),
|
|
94
6
|
});
|
|
95
7
|
}
|
|
96
8
|
//# sourceMappingURL=approvals.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/daemon/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../../src/daemon/approvals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,8BAA8B,EAAE,MAAM,mCAAmC,CAAC;AAGnF,MAAM,UAAU,gCAAgC,CAAC,OAAmB;IAClE,OAAO,IAAI,8BAA8B,CAAC;QACxC,GAAG,EAAE,0BAA0B,CAAC,OAAO,CAAC;KACzC,CAAC,CAAC;AACL,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { bootstrap } from "./core/index.js";
|
|
2
2
|
export type { AcpMeta, BootstrapMeta, BootstrapMode } from "./core/index.js";
|
|
3
3
|
export { Config as HoomanConfig, LlmProvider } from "./core/config.js";
|
|
4
|
-
export type { CompactionConfig, ConfigData, LlmConfig, NamedLlmConfig, NamedProviderConfig, PromptsConfig, ProviderConfig, ResolvedNamedLlmConfig, SearchConfig, ToolsConfig, } from "./core/config.js";
|
|
4
|
+
export type { CompactionConfig, ConfigData, ConfigOptions, LlmConfig, NamedLlmConfig, NamedProviderConfig, PromptsConfig, ProviderConfig, ResolvedNamedLlmConfig, SearchConfig, ToolsConfig, } from "./core/config.js";
|
|
5
|
+
export { createRuntimeConfig, createRuntimeMcpConfig, runtimeConfigOptions, runtimeConfigSources, } from "./core/runtime-config.js";
|
|
6
|
+
export type { RuntimeConfigSources } from "./core/runtime-config.js";
|
|
5
7
|
export { attachmentsPath, basePath, configJsonPath, instructionsMdPath, mcpJsonPath, mcpOauthJsonPath, sessionsPath, skillsPath, } from "./core/utils/paths.js";
|
|
6
8
|
export { openBrowser } from "./core/utils/browser.js";
|
|
7
9
|
export { attachmentDiagnosticBlock, attachmentPathsToPromptBlocks, normalizeAttachmentPaths, readAttachmentAsBlocksOrBase64, } from "./core/utils/attachments.js";
|
|
@@ -9,8 +11,10 @@ export type { AttachmentBinaryFallback, AttachmentMediaBlocks, AttachmentReadRes
|
|
|
9
11
|
export { detectDocumentFormat, detectImageFormat, detectVideoFormat, } from "./core/utils/file-formats.js";
|
|
10
12
|
export { getCwd, runWithCwd } from "./core/utils/cwd-context.js";
|
|
11
13
|
export { isResolvedPathInsideDir, normalizeUserPath, } from "./core/utils/normalize-user-path.js";
|
|
14
|
+
export { candidateWalkUpPaths, discoverWalkUpFiles, findGitRoot, } from "./core/utils/discover-files.js";
|
|
12
15
|
export { create as createAgent } from "./core/agent/index.js";
|
|
13
16
|
export { applySessionMode } from "./core/agent/sync-tool-registry-mode.js";
|
|
17
|
+
export { ModeAwareToolRegistry } from "./core/agent/mode-aware-tool-registry.js";
|
|
14
18
|
export { HOOMAN_CHANNEL, HOOMAN_CHANNEL_PERMISSION, Manager as McpManager, createMcpConfig, createMcpManager, createMcpOAuthService, createMcpOAuthStore, } from "./core/mcp/index.js";
|
|
15
19
|
export type { ChannelMessage, ChannelPermissionBehavior, ChannelSubscription, ChannelSubscriptionHandle, NamedMcpTransport, ServerAuthStatus, } from "./core/mcp/index.js";
|
|
16
20
|
export { Config as McpConfig, type McpServersFile } from "./core/mcp/config.js";
|
|
@@ -21,6 +25,8 @@ export type { McpTransport, Sse, Stdio, StreamableHttp, } from "./core/mcp/types
|
|
|
21
25
|
export { PrefixedMcpTool } from "./core/mcp/prefixed-mcp-tool.js";
|
|
22
26
|
export { createByeTools, createFetchTools, createFilesystemTools, createGrepTools, createShellTools, createSleepTools, createThinkingTools, createTimeTools, createTodoTools, createWebSearchTools, } from "./core/tools/index.js";
|
|
23
27
|
export { UPDATE_TODOS_TOOL_NAME } from "./core/tools/todo.js";
|
|
28
|
+
export { getTerminalBackend, setTerminalBackend, type TerminalBackend, type TerminalRunRequest, type TerminalRunResult, } from "./core/tools/terminal-backend.js";
|
|
29
|
+
export { getTextFsBackend, setTextFsBackend, type TextFsBackend, type TextFsReadOptions, } from "./core/tools/text-fs-backend.js";
|
|
24
30
|
export { AGENT_SKILLS_STATE_KEY, Registry as SkillsRegistry, builtInSkillsPath, clearAgentSkillsPromptInjectionState, createAgentSkillsPlugin, createAgentSkillSources, createSkillsRegistry, } from "./core/skills/index.js";
|
|
25
31
|
export type { SkillListEntry, SkillSearchResult, } from "./core/skills/registry.js";
|
|
26
32
|
export { System as SystemPrompt, system as createSystemPrompt, } from "./core/prompts/index.js";
|
|
@@ -43,13 +49,22 @@ export { StrandsOllamaModel, type OllamaModelConfig, } from "./core/models/ollam
|
|
|
43
49
|
export { createContext } from "./core/agent/index.js";
|
|
44
50
|
export { FlatFileStorage } from "./core/sessions/flat-file-storage.js";
|
|
45
51
|
export { LazySessionManager, type LazySessionManagerConfig, } from "./core/sessions/lazy-session-manager.js";
|
|
52
|
+
export { TolerantFileStorage } from "./core/sessions/tolerant-file-storage.js";
|
|
53
|
+
export { latestCliSessionForCwd, listCliSessions, type CliSessionSummary, } from "./core/sessions/list-cli-sessions.js";
|
|
46
54
|
export { SUBAGENT_TOOL_NAME_PREFIX, createSubagentTools, loadSubagentRegistry, } from "./core/subagents/index.js";
|
|
47
55
|
export type { SubagentKindConfig, SubagentKindDefinition, SubagentRegistry, } from "./core/subagents/index.js";
|
|
48
56
|
export { EXIT_REQUESTED_CODE, EXIT_REQUESTED_STATE_KEY, consumeExitRequest, isExitRequested, requestExit, } from "./core/state/exit-request.js";
|
|
49
|
-
export { INTERNAL_ALWAYS_ALLOWED as TOOL_APPROVAL_INTERNAL_ALWAYS_ALLOWED, isImplicitlyAllowed, planModeWriteEditRejectionMessage, } from "./core/state/tool-approvals.js";
|
|
57
|
+
export { INTERNAL_ALWAYS_ALLOWED as TOOL_APPROVAL_INTERNAL_ALWAYS_ALLOWED, isImplicitlyAllowed, isToolVisible, planModeWriteEditRejectionMessage, } from "./core/state/tool-approvals.js";
|
|
50
58
|
export { Allowlist, getAllowlist, type AllowlistOptions, type AllowlistRule, } from "./core/approvals/allowlist.js";
|
|
59
|
+
export { arityPrefix, splitCommands, tokenize, } from "./core/approvals/bash-arity.js";
|
|
60
|
+
export { matchWildcard } from "./core/approvals/wildcard.js";
|
|
61
|
+
export { HoomanToolApprovalIntervention, type HoomanToolApprovalInterventionConfig, type ToolApprovalAsk, type ToolApprovalDecision, type ToolApprovalRequest, type ToolApprovalResult, } from "./core/approvals/intervention.js";
|
|
62
|
+
export { createChannelPermissionAsk, readChannelOrigin, type ChannelOrigin as ToolApprovalChannelOrigin, } from "./core/approvals/channel-ask.js";
|
|
63
|
+
export { ChatTurnSteeringController, ChatTurnSteeringIntervention, createChatTurnSteeringIntervention, type QueuedSteeringPrompt, } from "./core/agent/turn-steering.js";
|
|
51
64
|
export { YOLO_STATE_KEY, isYoloEnabled, setYoloEnabled, } from "./core/state/yolo.js";
|
|
52
65
|
export { MODE_STATE_KEY, getModeState, setSessionMode, type SessionMode, } from "./core/state/session-mode.js";
|
|
66
|
+
export { DEFAULT_SESSION_MODE, MODE_DEFINITIONS, MODE_IDS, formatModeNames, getModeDefinition, getModeIds, getModeOptions, getModeTools, isKnownSessionMode, isModeDefinition, loadModeDefinitions, type KnownSessionMode, type ModeDefinition, } from "./core/modes/index.js";
|
|
67
|
+
export type { LoadedModeDefinition } from "./core/modes/registry.js";
|
|
53
68
|
export { TODO_ITEMS_STATE_KEY, TODO_VISIBLE_STATE_KEY, TodoItemSchema, TodoStatusSchema, clearTodoState, getTodoViewState, setTodoState, summarizeTodos, } from "./core/state/todos.js";
|
|
54
69
|
export type { TodoItem, TodoStatus, TodoViewState, } from "./core/state/todos.js";
|
|
55
70
|
export { readThinkingState, writeThinkingState, } from "./core/state/thought-process.js";
|