@agent-native/core 0.171.3 → 0.172.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/agent/actions/set-tool-approval-policy.d.ts +8 -0
- package/dist/agent/actions/set-tool-approval-policy.js +26 -0
- package/dist/agent/harness/migrations.js +8 -0
- package/dist/agent/harness/runner.js +114 -33
- package/dist/agent/harness/store.d.ts +9 -0
- package/dist/agent/harness/store.js +87 -23
- package/dist/agent/production-agent.d.ts +3 -0
- package/dist/agent/production-agent.js +23 -1
- package/dist/agent/run-manager.js +40 -9
- package/dist/agent/tool-approval-migrations.d.ts +21 -0
- package/dist/agent/tool-approval-migrations.js +32 -0
- package/dist/agent/tool-approval-store.d.ts +11 -0
- package/dist/agent/tool-approval-store.js +76 -1
- package/dist/agent-web/generator.d.ts +44 -10
- package/dist/agent-web/generator.js +38 -0
- package/dist/agent-web/index.d.ts +1 -1
- package/dist/cli/code-agent-executor.js +20 -3
- package/dist/client/AgentPanel.d.ts +4 -1
- package/dist/client/AgentPanel.js +11 -3
- package/dist/client/AssistantChat.d.ts +5 -5
- package/dist/client/AssistantChat.js +24 -11
- package/dist/client/chat/tool-call-display.d.ts +5 -5
- package/dist/client/chat/tool-call-display.js +27 -11
- package/dist/client/resources/McpIntegrationDialog.js +5 -5
- package/dist/client/resources/mcp-integration-catalog.js +1 -1
- package/dist/coding-tools/index.d.ts +31 -0
- package/dist/coding-tools/index.js +139 -3
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/localization/core-messages/ar-SA.js +3 -0
- package/dist/localization/core-messages/de-DE.js +3 -0
- package/dist/localization/core-messages/en-US.d.ts +3 -0
- package/dist/localization/core-messages/en-US.js +3 -0
- package/dist/localization/core-messages/es-ES.js +3 -0
- package/dist/localization/core-messages/fr-FR.js +3 -0
- package/dist/localization/core-messages/hi-IN.js +3 -0
- package/dist/localization/core-messages/ja-JP.js +3 -0
- package/dist/localization/core-messages/ko-KR.js +3 -0
- package/dist/localization/core-messages/pt-BR.js +3 -0
- package/dist/localization/core-messages/zh-CN.js +3 -0
- package/dist/localization/core-messages/zh-TW.js +3 -0
- package/dist/localization/core-messages.d.ts +3 -0
- package/dist/localization/default-messages.d.ts +1 -0
- package/dist/localization/default-messages.js +7 -6
- package/dist/observability/routes.d.ts +3 -3
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/actions/custom-provider-registration.d.ts +7 -7
- package/dist/provider-api/actions/provider-api.d.ts +11 -11
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/action-discovery.js +5 -0
- package/dist/server/agent-chat/prompt-resources.d.ts +9 -0
- package/dist/server/agent-chat/prompt-resources.js +12 -2
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/release-schema.js +4 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/triggers/dispatcher.d.ts +24 -0
- package/dist/triggers/dispatcher.js +76 -18
- package/dist/vite/action-types-plugin.js +4 -0
- package/dist/vite/agent-web-plugin.d.ts +4 -6
- package/dist/vite/agent-web-plugin.js +2 -0
- package/package.json +2 -1
|
@@ -35,6 +35,27 @@ export declare const AGENT_TOOL_APPROVAL_TABLE_SQL: {
|
|
|
35
35
|
export declare const AGENT_TOOL_APPROVAL_INDEX_SQL = "CREATE INDEX IF NOT EXISTS idx_agent_tool_approvals_binding\n ON agent_tool_approvals(owner_email, org_id, thread_id, tool_name, call_id, status)";
|
|
36
36
|
export declare const AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL = "CREATE INDEX IF NOT EXISTS idx_agent_tool_approvals_logical\n ON agent_tool_approvals(owner_email, org_id, thread_id, turn_id, tool_name, approval_key_hash, status)";
|
|
37
37
|
export declare const AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL = "CREATE INDEX IF NOT EXISTS idx_agent_tool_approvals_recovery\n ON agent_tool_approvals(owner_email, org_id, thread_id, approval_key_hash, status, turn_id)";
|
|
38
|
+
export declare const AGENT_TOOL_APPROVAL_POLICY_TABLE_SQL: {
|
|
39
|
+
readonly postgres: `CREATE TABLE IF NOT EXISTS agent_tool_approval_policies (
|
|
40
|
+
id TEXT PRIMARY KEY,
|
|
41
|
+
owner_email TEXT NOT NULL,
|
|
42
|
+
org_id TEXT,
|
|
43
|
+
tool_name TEXT NOT NULL,
|
|
44
|
+
enabled BOOLEAN NOT NULL,
|
|
45
|
+
created_at BIGINT NOT NULL,
|
|
46
|
+
updated_at BIGINT NOT NULL
|
|
47
|
+
)`;
|
|
48
|
+
readonly sqlite: `CREATE TABLE IF NOT EXISTS agent_tool_approval_policies (
|
|
49
|
+
id TEXT PRIMARY KEY,
|
|
50
|
+
owner_email TEXT NOT NULL,
|
|
51
|
+
org_id TEXT,
|
|
52
|
+
tool_name TEXT NOT NULL,
|
|
53
|
+
enabled INTEGER NOT NULL,
|
|
54
|
+
created_at INTEGER NOT NULL,
|
|
55
|
+
updated_at INTEGER NOT NULL
|
|
56
|
+
)`;
|
|
57
|
+
};
|
|
58
|
+
export declare const AGENT_TOOL_APPROVAL_POLICY_INDEX_SQL = "CREATE INDEX IF NOT EXISTS idx_agent_tool_approval_policies_scope\n ON agent_tool_approval_policies(owner_email, org_id, tool_name, enabled)";
|
|
38
59
|
/**
|
|
39
60
|
* Durable approval grants are created and consumed on request paths, but their
|
|
40
61
|
* schema belongs to the release migration boundary in production.
|
|
@@ -37,6 +37,28 @@ export const AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL = `CREATE INDEX IF NOT EXISTS
|
|
|
37
37
|
ON agent_tool_approvals(owner_email, org_id, thread_id, turn_id, tool_name, approval_key_hash, status)`;
|
|
38
38
|
export const AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL = `CREATE INDEX IF NOT EXISTS idx_agent_tool_approvals_recovery
|
|
39
39
|
ON agent_tool_approvals(owner_email, org_id, thread_id, approval_key_hash, status, turn_id)`;
|
|
40
|
+
export const AGENT_TOOL_APPROVAL_POLICY_TABLE_SQL = {
|
|
41
|
+
postgres: `CREATE TABLE IF NOT EXISTS agent_tool_approval_policies (
|
|
42
|
+
id TEXT PRIMARY KEY,
|
|
43
|
+
owner_email TEXT NOT NULL,
|
|
44
|
+
org_id TEXT,
|
|
45
|
+
tool_name TEXT NOT NULL,
|
|
46
|
+
enabled BOOLEAN NOT NULL,
|
|
47
|
+
created_at BIGINT NOT NULL,
|
|
48
|
+
updated_at BIGINT NOT NULL
|
|
49
|
+
)`,
|
|
50
|
+
sqlite: `CREATE TABLE IF NOT EXISTS agent_tool_approval_policies (
|
|
51
|
+
id TEXT PRIMARY KEY,
|
|
52
|
+
owner_email TEXT NOT NULL,
|
|
53
|
+
org_id TEXT,
|
|
54
|
+
tool_name TEXT NOT NULL,
|
|
55
|
+
enabled INTEGER NOT NULL,
|
|
56
|
+
created_at INTEGER NOT NULL,
|
|
57
|
+
updated_at INTEGER NOT NULL
|
|
58
|
+
)`,
|
|
59
|
+
};
|
|
60
|
+
export const AGENT_TOOL_APPROVAL_POLICY_INDEX_SQL = `CREATE INDEX IF NOT EXISTS idx_agent_tool_approval_policies_scope
|
|
61
|
+
ON agent_tool_approval_policies(owner_email, org_id, tool_name, enabled)`;
|
|
40
62
|
/**
|
|
41
63
|
* Durable approval grants are created and consumed on request paths, but their
|
|
42
64
|
* schema belongs to the release migration boundary in production.
|
|
@@ -68,4 +90,14 @@ ${AGENT_TOOL_APPROVAL_INDEX_SQL}`,
|
|
|
68
90
|
sqlite: AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL,
|
|
69
91
|
},
|
|
70
92
|
},
|
|
93
|
+
{
|
|
94
|
+
version: 4,
|
|
95
|
+
name: "agent-tool-approval-policies-table-and-index",
|
|
96
|
+
sql: {
|
|
97
|
+
postgres: `${AGENT_TOOL_APPROVAL_POLICY_TABLE_SQL.postgres};
|
|
98
|
+
${AGENT_TOOL_APPROVAL_POLICY_INDEX_SQL}`,
|
|
99
|
+
sqlite: `${AGENT_TOOL_APPROVAL_POLICY_TABLE_SQL.sqlite};
|
|
100
|
+
${AGENT_TOOL_APPROVAL_POLICY_INDEX_SQL}`,
|
|
101
|
+
},
|
|
102
|
+
},
|
|
71
103
|
];
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export declare function ensureAgentToolApprovalTable(): Promise<void>;
|
|
2
|
+
export declare function ensureAgentToolApprovalPolicyTable(): Promise<void>;
|
|
2
3
|
export interface AgentToolApprovalBinding {
|
|
3
4
|
ownerEmail: string;
|
|
4
5
|
orgId?: string | null;
|
|
@@ -10,6 +11,16 @@ export interface AgentToolApprovalBinding {
|
|
|
10
11
|
expiresAt?: number;
|
|
11
12
|
}
|
|
12
13
|
export declare function hashAgentToolApprovalKey(approvalKey: string): string;
|
|
14
|
+
export interface AgentToolApprovalPolicyBinding {
|
|
15
|
+
ownerEmail: string;
|
|
16
|
+
orgId?: string | null;
|
|
17
|
+
toolName: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function setAgentToolApprovalPolicy(input: {
|
|
20
|
+
binding: AgentToolApprovalPolicyBinding;
|
|
21
|
+
enabled: boolean;
|
|
22
|
+
}): Promise<void>;
|
|
23
|
+
export declare function isAgentToolAlwaysAllowed(input: AgentToolApprovalPolicyBinding): Promise<boolean>;
|
|
13
24
|
/**
|
|
14
25
|
* Recover the durable scope for an approval continuation when a transport
|
|
15
26
|
* drops the original turn id. A single pending logical turn is safe to
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { getDbExec, isPostgres, retryOnDdlRace } from "../db/client.js";
|
|
3
3
|
import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
|
|
4
|
-
import { AGENT_TOOL_APPROVAL_INDEX_SQL, AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL, AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL, AGENT_TOOL_APPROVAL_TABLE_SQL, } from "./tool-approval-migrations.js";
|
|
4
|
+
import { AGENT_TOOL_APPROVAL_INDEX_SQL, AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL, AGENT_TOOL_APPROVAL_POLICY_INDEX_SQL, AGENT_TOOL_APPROVAL_POLICY_TABLE_SQL, AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL, AGENT_TOOL_APPROVAL_TABLE_SQL, } from "./tool-approval-migrations.js";
|
|
5
5
|
// 15 minutes was too short in practice: a user who steps away mid-approval
|
|
6
6
|
// (switching tabs to update their client, checking something else) comes back
|
|
7
7
|
// to a silently expired grant with no visible error — clicking Approve just
|
|
@@ -11,6 +11,7 @@ import { AGENT_TOOL_APPROVAL_INDEX_SQL, AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL, A
|
|
|
11
11
|
const APPROVAL_TTL_MS = 60 * 60_000;
|
|
12
12
|
const APPROVAL_CLEANUP_AGE_MS = 24 * 60 * 60_000;
|
|
13
13
|
let initPromise;
|
|
14
|
+
let policyInitPromise;
|
|
14
15
|
export async function ensureAgentToolApprovalTable() {
|
|
15
16
|
if (!initPromise) {
|
|
16
17
|
initPromise = (async () => {
|
|
@@ -34,9 +35,83 @@ export async function ensureAgentToolApprovalTable() {
|
|
|
34
35
|
}
|
|
35
36
|
return initPromise;
|
|
36
37
|
}
|
|
38
|
+
export async function ensureAgentToolApprovalPolicyTable() {
|
|
39
|
+
if (!policyInitPromise) {
|
|
40
|
+
policyInitPromise = (async () => {
|
|
41
|
+
const createSql = AGENT_TOOL_APPROVAL_POLICY_TABLE_SQL[isPostgres() ? "postgres" : "sqlite"];
|
|
42
|
+
if (isPostgres()) {
|
|
43
|
+
await ensureTableExists("agent_tool_approval_policies", createSql);
|
|
44
|
+
await ensureIndexExists("idx_agent_tool_approval_policies_scope", AGENT_TOOL_APPROVAL_POLICY_INDEX_SQL);
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
const client = getDbExec();
|
|
48
|
+
await retryOnDdlRace(() => client.execute(createSql));
|
|
49
|
+
await retryOnDdlRace(() => client.execute(AGENT_TOOL_APPROVAL_POLICY_INDEX_SQL));
|
|
50
|
+
})().catch((error) => {
|
|
51
|
+
policyInitPromise = undefined;
|
|
52
|
+
throw error;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
return policyInitPromise;
|
|
56
|
+
}
|
|
37
57
|
export function hashAgentToolApprovalKey(approvalKey) {
|
|
38
58
|
return createHash("sha256").update(approvalKey).digest("hex");
|
|
39
59
|
}
|
|
60
|
+
function normalizeApprovalPolicyBinding(binding) {
|
|
61
|
+
const ownerEmail = binding.ownerEmail.trim().toLowerCase();
|
|
62
|
+
const toolName = binding.toolName.trim();
|
|
63
|
+
if (!ownerEmail)
|
|
64
|
+
throw new Error("Approval policy owner is required.");
|
|
65
|
+
if (!toolName)
|
|
66
|
+
throw new Error("Approval policy tool name is required.");
|
|
67
|
+
return {
|
|
68
|
+
ownerEmail,
|
|
69
|
+
orgId: binding.orgId?.trim() || null,
|
|
70
|
+
toolName,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
function approvalPolicyId(binding) {
|
|
74
|
+
return `agent-tool-approval-policy-${createHash("sha256")
|
|
75
|
+
.update(`${binding.ownerEmail}\u0000${binding.orgId ?? ""}\u0000${binding.toolName}`)
|
|
76
|
+
.digest("hex")}`;
|
|
77
|
+
}
|
|
78
|
+
export async function setAgentToolApprovalPolicy(input) {
|
|
79
|
+
const binding = normalizeApprovalPolicyBinding(input.binding);
|
|
80
|
+
await ensureAgentToolApprovalPolicyTable();
|
|
81
|
+
const now = Date.now();
|
|
82
|
+
const id = approvalPolicyId(binding);
|
|
83
|
+
await getDbExec().execute({
|
|
84
|
+
sql: `INSERT INTO agent_tool_approval_policies
|
|
85
|
+
(id, owner_email, org_id, tool_name, enabled, created_at, updated_at)
|
|
86
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
87
|
+
ON CONFLICT(id) DO UPDATE SET
|
|
88
|
+
enabled = excluded.enabled,
|
|
89
|
+
updated_at = excluded.updated_at`,
|
|
90
|
+
args: [
|
|
91
|
+
id,
|
|
92
|
+
binding.ownerEmail,
|
|
93
|
+
binding.orgId,
|
|
94
|
+
binding.toolName,
|
|
95
|
+
input.enabled,
|
|
96
|
+
now,
|
|
97
|
+
now,
|
|
98
|
+
],
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
export async function isAgentToolAlwaysAllowed(input) {
|
|
102
|
+
const binding = normalizeApprovalPolicyBinding(input);
|
|
103
|
+
await ensureAgentToolApprovalPolicyTable();
|
|
104
|
+
const result = await getDbExec().execute({
|
|
105
|
+
sql: `SELECT 1 FROM agent_tool_approval_policies
|
|
106
|
+
WHERE owner_email = ?
|
|
107
|
+
AND ((org_id IS NULL AND CAST(? AS TEXT) IS NULL) OR org_id = ?)
|
|
108
|
+
AND tool_name = ?
|
|
109
|
+
AND enabled = TRUE
|
|
110
|
+
LIMIT 1`,
|
|
111
|
+
args: [binding.ownerEmail, binding.orgId, binding.orgId, binding.toolName],
|
|
112
|
+
});
|
|
113
|
+
return (result.rows ?? []).length > 0;
|
|
114
|
+
}
|
|
40
115
|
/**
|
|
41
116
|
* Recover the durable scope for an approval continuation when a transport
|
|
42
117
|
* drops the original turn id. A single pending logical turn is safe to
|
|
@@ -7,17 +7,40 @@ export interface AgentWebPage {
|
|
|
7
7
|
markdownPath?: string;
|
|
8
8
|
lastmod?: string | Date;
|
|
9
9
|
}
|
|
10
|
+
export interface AgentWebResource {
|
|
11
|
+
title: string;
|
|
12
|
+
url: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
}
|
|
15
|
+
export interface AgentWebOrganization {
|
|
16
|
+
name: string;
|
|
17
|
+
url?: string;
|
|
18
|
+
sameAs?: string[];
|
|
19
|
+
contactPoint?: {
|
|
20
|
+
"@type": "ContactPoint";
|
|
21
|
+
contactType: string;
|
|
22
|
+
email?: string;
|
|
23
|
+
telephone?: string;
|
|
24
|
+
url?: string;
|
|
25
|
+
};
|
|
26
|
+
address?: {
|
|
27
|
+
"@type": "PostalAddress";
|
|
28
|
+
streetAddress?: string;
|
|
29
|
+
addressLocality?: string;
|
|
30
|
+
addressRegion?: string;
|
|
31
|
+
postalCode?: string;
|
|
32
|
+
addressCountry?: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
10
35
|
export interface BuildAgentWebStaticFilesOptions {
|
|
11
36
|
siteName: string;
|
|
12
37
|
siteUrl: string;
|
|
13
38
|
description?: string;
|
|
14
39
|
pages: AgentWebPage[];
|
|
15
40
|
config: AgentWebConfig;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
sameAs?: string[];
|
|
20
|
-
};
|
|
41
|
+
developerResources?: AgentWebResource[];
|
|
42
|
+
whenToUse?: string[];
|
|
43
|
+
organization?: AgentWebOrganization;
|
|
21
44
|
}
|
|
22
45
|
export interface AgentWebStaticFile {
|
|
23
46
|
path: string;
|
|
@@ -43,17 +66,28 @@ export declare function buildBaseJsonLd(options: {
|
|
|
43
66
|
siteName: string;
|
|
44
67
|
siteUrl: string;
|
|
45
68
|
description?: string;
|
|
46
|
-
organization?:
|
|
47
|
-
name: string;
|
|
48
|
-
url?: string;
|
|
49
|
-
sameAs?: string[];
|
|
50
|
-
};
|
|
69
|
+
organization?: AgentWebOrganization;
|
|
51
70
|
}): ({
|
|
52
71
|
"@context": string;
|
|
53
72
|
"@type": string;
|
|
54
73
|
name: string;
|
|
55
74
|
url: string;
|
|
56
75
|
sameAs?: string[] | undefined;
|
|
76
|
+
contactPoint?: {
|
|
77
|
+
"@type": "ContactPoint";
|
|
78
|
+
contactType: string;
|
|
79
|
+
email?: string;
|
|
80
|
+
telephone?: string;
|
|
81
|
+
url?: string;
|
|
82
|
+
} | undefined;
|
|
83
|
+
address?: {
|
|
84
|
+
"@type": "PostalAddress";
|
|
85
|
+
streetAddress?: string;
|
|
86
|
+
addressLocality?: string;
|
|
87
|
+
addressRegion?: string;
|
|
88
|
+
postalCode?: string;
|
|
89
|
+
addressCountry?: string;
|
|
90
|
+
} | undefined;
|
|
57
91
|
} | {
|
|
58
92
|
"@context": string;
|
|
59
93
|
"@type": string;
|
|
@@ -91,11 +91,24 @@ ${entries}
|
|
|
91
91
|
`;
|
|
92
92
|
}
|
|
93
93
|
export function buildLlmsTxt(options) {
|
|
94
|
+
const developerResources = options.developerResources ?? [];
|
|
95
|
+
const whenToUse = options.whenToUse ?? [];
|
|
94
96
|
const lines = [
|
|
95
97
|
`# ${options.siteName}`,
|
|
96
98
|
"",
|
|
97
99
|
options.description ? `> ${options.description}` : undefined,
|
|
98
100
|
options.description ? "" : undefined,
|
|
101
|
+
whenToUse.length ? "## When to use this" : undefined,
|
|
102
|
+
...whenToUse.map((instruction) => `- ${instruction}`),
|
|
103
|
+
whenToUse.length ? "" : undefined,
|
|
104
|
+
developerResources.length ? "## Developer resources" : undefined,
|
|
105
|
+
...developerResources.map((resource) => {
|
|
106
|
+
const description = resource.description
|
|
107
|
+
? `: ${resource.description}`
|
|
108
|
+
: "";
|
|
109
|
+
return `- [${resource.title}](${absoluteResourceUrl(options.siteUrl, resource.url)})${description}`;
|
|
110
|
+
}),
|
|
111
|
+
developerResources.length ? "" : undefined,
|
|
99
112
|
"## Pages",
|
|
100
113
|
...options.pages.map((page) => {
|
|
101
114
|
const description = page.description ? `: ${page.description}` : "";
|
|
@@ -110,11 +123,24 @@ export function buildLlmsTxt(options) {
|
|
|
110
123
|
return `${lines.join("\n")}\n`;
|
|
111
124
|
}
|
|
112
125
|
export function buildLlmsFullTxt(options) {
|
|
126
|
+
const developerResources = options.developerResources ?? [];
|
|
127
|
+
const whenToUse = options.whenToUse ?? [];
|
|
113
128
|
const lines = [
|
|
114
129
|
`# ${options.siteName}`,
|
|
115
130
|
"",
|
|
116
131
|
options.description ?? "",
|
|
117
132
|
"",
|
|
133
|
+
whenToUse.length ? "## When to use this" : undefined,
|
|
134
|
+
...whenToUse.map((instruction) => `- ${instruction}`),
|
|
135
|
+
whenToUse.length ? "" : undefined,
|
|
136
|
+
developerResources.length ? "## Developer resources" : undefined,
|
|
137
|
+
...developerResources.map((resource) => {
|
|
138
|
+
const description = resource.description
|
|
139
|
+
? `: ${resource.description}`
|
|
140
|
+
: "";
|
|
141
|
+
return `- [${resource.title}](${absoluteResourceUrl(options.siteUrl, resource.url)})${description}`;
|
|
142
|
+
}),
|
|
143
|
+
developerResources.length ? "" : undefined,
|
|
118
144
|
...options.pages.flatMap((page) => [
|
|
119
145
|
`## ${page.title}`,
|
|
120
146
|
"",
|
|
@@ -141,6 +167,12 @@ export function buildBaseJsonLd(options) {
|
|
|
141
167
|
...(options.organization?.sameAs?.length
|
|
142
168
|
? { sameAs: options.organization.sameAs }
|
|
143
169
|
: {}),
|
|
170
|
+
...(options.organization?.contactPoint
|
|
171
|
+
? { contactPoint: options.organization.contactPoint }
|
|
172
|
+
: {}),
|
|
173
|
+
...(options.organization?.address
|
|
174
|
+
? { address: options.organization.address }
|
|
175
|
+
: {}),
|
|
144
176
|
},
|
|
145
177
|
{
|
|
146
178
|
"@context": "https://schema.org",
|
|
@@ -188,6 +220,7 @@ export function buildMarkdownResponseHeaders(options) {
|
|
|
188
220
|
return {
|
|
189
221
|
"content-type": "text/markdown; charset=utf-8",
|
|
190
222
|
"x-markdown-tokens": String(estimateMarkdownTokens(options.markdown)),
|
|
223
|
+
vary: "Accept, Accept-Encoding",
|
|
191
224
|
link: `<${absoluteUrl(options.siteUrl, "/llms.txt")}>; rel="llms-txt", <${absoluteUrl(options.siteUrl, markdownUrlForPage(options.pagePath, options.markdownPath))}>; rel="alternate"; type="text/markdown"`,
|
|
192
225
|
};
|
|
193
226
|
}
|
|
@@ -213,6 +246,11 @@ export function absoluteUrl(siteUrl, pagePath) {
|
|
|
213
246
|
const path = normalizePagePath(pagePath);
|
|
214
247
|
return `${base}${path}`;
|
|
215
248
|
}
|
|
249
|
+
function absoluteResourceUrl(siteUrl, resourceUrl) {
|
|
250
|
+
return /^https?:\/\//i.test(resourceUrl)
|
|
251
|
+
? resourceUrl
|
|
252
|
+
: absoluteUrl(siteUrl, resourceUrl);
|
|
253
|
+
}
|
|
216
254
|
function normalizePagePath(pagePath) {
|
|
217
255
|
const withSlash = pagePath.startsWith("/") ? pagePath : `/${pagePath}`;
|
|
218
256
|
if (withSlash.length > 1 && withSlash.endsWith("/")) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export { AGENT_WEB_CRAWLER_CATEGORIES, DEFAULT_AGENT_WEB_CRAWLER_POLICY, agentWebConfigFromPackageJson, deriveAgentWebPublicRoutes, normalizeAgentWebConfig, pathPatternMatches, resolveAgentWebCrawlerPolicy, type AgentWebConfig, type AgentWebCrawlerCategory, type AgentWebCrawlerDecision, type AgentWebCrawlerOverrides, type AgentWebCrawlerPolicy, type AgentWebInputConfig, type DeriveAgentWebPublicRoutesOptions, } from "./config.js";
|
|
2
|
-
export { AGENT_WEB_CRAWLER_USER_AGENTS, absoluteUrl, buildAgentWebStaticFiles, buildBaseJsonLd, buildLlmsFullTxt, buildLlmsTxt, buildMarkdownResponseHeaders, buildPageJsonLd, buildRobotsTxt, buildSitemapXml, estimateMarkdownTokens, markdownFilePathForPage, markdownUrlForPage, type AgentWebPage, type AgentWebStaticFile, type BuildAgentWebStaticFilesOptions, type MarkdownResponseHeadersOptions, } from "./generator.js";
|
|
2
|
+
export { AGENT_WEB_CRAWLER_USER_AGENTS, absoluteUrl, buildAgentWebStaticFiles, buildBaseJsonLd, buildLlmsFullTxt, buildLlmsTxt, buildMarkdownResponseHeaders, buildPageJsonLd, buildRobotsTxt, buildSitemapXml, estimateMarkdownTokens, markdownFilePathForPage, markdownUrlForPage, type AgentWebPage, type AgentWebOrganization, type AgentWebResource, type AgentWebStaticFile, type BuildAgentWebStaticFilesOptions, type MarkdownResponseHeadersOptions, } from "./generator.js";
|
|
@@ -9,7 +9,7 @@ import { actionsToEngineTools, runAgentLoop, } from "../agent/production-agent.j
|
|
|
9
9
|
import { createToolSearchEntry, TOOL_SEARCH_ACTION_NAME, } from "../agent/tool-search.js";
|
|
10
10
|
import { getAppConfig } from "../app-config/index.js";
|
|
11
11
|
import { formatPromptWithAttachments, } from "../code-agents/prompt-attachments.js";
|
|
12
|
-
import { createCodingToolRegistry, isReadOnlyShellCommand, runCodingCommand, truncateBashOutput, truncateCodingOutput, } from "../coding-tools/index.js";
|
|
12
|
+
import { createCodingToolRegistry, canonicalizeShellCommand, isReadOnlyShellCommand, runCodingCommand, truncateBashOutput, truncateCodingOutput, } from "../coding-tools/index.js";
|
|
13
13
|
import { buildMergedConfig, McpClientManager, mcpToolsToActionEntries, } from "../mcp-client/index.js";
|
|
14
14
|
import { readAgentsBundleFromFs, generateDevelopmentSkillsPromptBlock, } from "../server/agents-bundle.js";
|
|
15
15
|
import { getAmbientOrgId, getAmbientUserEmail, runWithRequestContext, } from "../server/request-context.js";
|
|
@@ -2303,6 +2303,13 @@ export function classifyCodeAgentCommandPermission(command) {
|
|
|
2303
2303
|
const normalized = command.trim().toLowerCase();
|
|
2304
2304
|
if (!normalized)
|
|
2305
2305
|
return { kind: "read" };
|
|
2306
|
+
// Match every rule below against the quote-stripped form as well as the raw
|
|
2307
|
+
// one. The shell removes quoting before the command word exists, so
|
|
2308
|
+
// `git 'checkout' main` runs the branch operation these rules forbid while
|
|
2309
|
+
// matching none of them verbatim.
|
|
2310
|
+
const { canonical, unanalyzable } = canonicalizeShellCommand(command);
|
|
2311
|
+
const canonicalized = canonical.trim().toLowerCase();
|
|
2312
|
+
const matches = (pattern) => pattern.test(normalized) || pattern.test(canonicalized);
|
|
2306
2313
|
const blockedPatterns = [
|
|
2307
2314
|
[
|
|
2308
2315
|
/\bgit\s+(checkout|switch|reset|rebase|stash|clean|worktree)\b/,
|
|
@@ -2315,7 +2322,7 @@ export function classifyCodeAgentCommandPermission(command) {
|
|
|
2315
2322
|
[/\bdrizzle-kit\s+push\b/, "drizzle-kit push is not allowed"],
|
|
2316
2323
|
];
|
|
2317
2324
|
for (const [pattern, reason] of blockedPatterns) {
|
|
2318
|
-
if (pattern
|
|
2325
|
+
if (matches(pattern))
|
|
2319
2326
|
return { kind: "forbidden", reason };
|
|
2320
2327
|
}
|
|
2321
2328
|
const approvalPatterns = [
|
|
@@ -2331,10 +2338,20 @@ export function classifyCodeAgentCommandPermission(command) {
|
|
|
2331
2338
|
[/\bdelete\s+from\b(?![\s\S]*\bwhere\b)/, "unscoped delete command"],
|
|
2332
2339
|
];
|
|
2333
2340
|
for (const [pattern, reason] of approvalPatterns) {
|
|
2334
|
-
if (pattern
|
|
2341
|
+
if (matches(pattern)) {
|
|
2335
2342
|
return { kind: "approval-required", reason };
|
|
2336
2343
|
}
|
|
2337
2344
|
}
|
|
2345
|
+
// A command whose real text this pass cannot recover is not a command we can
|
|
2346
|
+
// clear. `$(printf git) $(printf checkout) main` runs the forbidden operation
|
|
2347
|
+
// while containing neither token, so a rule that did not match proves nothing.
|
|
2348
|
+
// Ask rather than fall through to `write` on a guess.
|
|
2349
|
+
if (unanalyzable) {
|
|
2350
|
+
return {
|
|
2351
|
+
kind: "approval-required",
|
|
2352
|
+
reason: "command builds its text at runtime (command substitution or $'…' escaping), so policy matching cannot see what will run",
|
|
2353
|
+
};
|
|
2354
|
+
}
|
|
2338
2355
|
if (isReadOnlyShellCommand(command)) {
|
|
2339
2356
|
return { kind: "read" };
|
|
2340
2357
|
}
|
|
@@ -26,6 +26,7 @@ export declare function preloadAgentChatSurface(): Promise<void>;
|
|
|
26
26
|
import type { AgentChatSurfaceKind } from "./agent-chat-adapter.js";
|
|
27
27
|
import type { AssistantChatProps } from "./AssistantChat.js";
|
|
28
28
|
import type { MultiTabAssistantChatHeaderProps, MultiTabAssistantChatProps } from "./MultiTabAssistantChat.js";
|
|
29
|
+
export declare function shouldHandleAgentSidebarToggle(event: Event, toggleScopeId?: string | null): boolean;
|
|
29
30
|
type PanelMode = "chat" | "cli" | "resources" | "settings";
|
|
30
31
|
export declare function normalizeAgentPanelModeForSurface(mode: PanelMode, allowSettingsMode: boolean, chatOnly?: boolean): PanelMode;
|
|
31
32
|
export declare function deferAgentPanelOverlayOpen(event: {
|
|
@@ -249,6 +250,8 @@ export interface AgentSidebarProps {
|
|
|
249
250
|
onFullscreenRequest?: () => void;
|
|
250
251
|
/** Ambient resource context rendered as a composer chip. */
|
|
251
252
|
scope?: import("./use-chat-threads.js").ChatThreadScope | null;
|
|
253
|
+
/** Identity used to route host-scoped sidebar toggle events. */
|
|
254
|
+
toggleScopeId?: string;
|
|
252
255
|
/** Keep app-owned chat history isolated to the supplied scope. */
|
|
253
256
|
isolateHistoryByScope?: boolean;
|
|
254
257
|
/** @deprecated Scope context now appears inside the composer. */
|
|
@@ -266,7 +269,7 @@ export interface AgentSidebarProps {
|
|
|
266
269
|
* Wraps app content with a toggleable agent sidebar.
|
|
267
270
|
* Use AgentToggleButton in your header to open/close it.
|
|
268
271
|
*/
|
|
269
|
-
export declare function AgentSidebar({ children, enabled, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, onConnectProvider, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openStorageKey, restoreActiveThread, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning, onFullscreenRequest, scope, isolateHistoryByScope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
|
|
272
|
+
export declare function AgentSidebar({ children, enabled, emptyStateText, suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, onConnectProvider, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position, defaultOpen, animateMobile, animateDesktop, chatViewTransition, chatViewTransitionHandoff, storageKey, openStorageKey, restoreActiveThread, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning, onFullscreenRequest, scope, toggleScopeId, isolateHistoryByScope, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding, }: AgentSidebarProps): React.JSX.Element;
|
|
270
273
|
/**
|
|
271
274
|
* Focus the agent chat composer input.
|
|
272
275
|
* Opens the sidebar if closed, then focuses the text input.
|
|
@@ -74,6 +74,12 @@ const AgentTerminal = lazy(() => import("./terminal/index.js").then((m) => ({ de
|
|
|
74
74
|
const AGENT_PANEL_PREPARE_EVENT = "agent-panel:prepare";
|
|
75
75
|
const AGENT_PANEL_SET_MODE_EVENT = "agent-panel:set-mode";
|
|
76
76
|
const AGENT_PANEL_OPEN_SETTINGS_EVENT = "agent-panel:open-settings";
|
|
77
|
+
export function shouldHandleAgentSidebarToggle(event, toggleScopeId) {
|
|
78
|
+
const detail = event.detail;
|
|
79
|
+
if (!detail || detail.scopeId === undefined)
|
|
80
|
+
return true;
|
|
81
|
+
return typeof detail.scopeId === "string" && detail.scopeId === toggleScopeId;
|
|
82
|
+
}
|
|
77
83
|
function postPerAppChatSidebarStateToEmbeddedFrames(open) {
|
|
78
84
|
const message = buildAppChatSidebarStateMessage(open);
|
|
79
85
|
for (const frame of document.querySelectorAll("iframe")) {
|
|
@@ -1423,7 +1429,7 @@ export function AgentChatSurface({ mode = "panel", className, defaultMode = "cha
|
|
|
1423
1429
|
* Wraps app content with a toggleable agent sidebar.
|
|
1424
1430
|
* Use AgentToggleButton in your header to open/close it.
|
|
1425
1431
|
*/
|
|
1426
|
-
export function AgentSidebar({ children, enabled = true, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, onConnectProvider, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, restoreActiveThread = true, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, isolateHistoryByScope = false, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
|
|
1432
|
+
export function AgentSidebar({ children, enabled = true, emptyStateText = "How can I help you?", suggestions, dynamicSuggestions, composerToolbarSlot, composerSlot, onComposerTextChange, imageModelMenu, availableAgents, availableModels, modelListLoading, selectedAgent, onAgentChange, onConnectLocalRuntime, onConnectProvider, runtime, adapterReloadKey, threadFooterSlot, defaultSidebarWidth, sidebarWidth, position = "right", defaultOpen = false, animateMobile = true, animateDesktop = true, chatViewTransition = false, chatViewTransitionHandoff = false, storageKey, openStorageKey, restoreActiveThread = true, apiUrl, agentChatSurface, desktopIdentityUnauthenticated, desktopIdentityAuthenticated, showTabBar = true, suppressInlineOpenApp, composerPlaceholder, openOnChatRunning = false, onFullscreenRequest, scope, toggleScopeId, isolateHistoryByScope = false, showScopeBadge, browserTabId, threadUrlSync, agentPageHref, suppressFirstRunOnboarding = false, }) {
|
|
1427
1433
|
const staticHostedHarnessEnabled = isHostedHarnessConfigured(injectedAgentNativeConfig().harness);
|
|
1428
1434
|
const hostedHarnessQuery = useActionQuery("get-hosted-harness-config", undefined, { enabled: staticHostedHarnessEnabled });
|
|
1429
1435
|
const hostedHarnessStatus = hostedHarnessQuery.data;
|
|
@@ -1729,7 +1735,9 @@ export function AgentSidebar({ children, enabled = true, emptyStateText = "How c
|
|
|
1729
1735
|
};
|
|
1730
1736
|
}, [setOpenPersisted]);
|
|
1731
1737
|
useEffect(() => {
|
|
1732
|
-
const toggleHandler = () => {
|
|
1738
|
+
const toggleHandler = (event) => {
|
|
1739
|
+
if (!shouldHandleAgentSidebarToggle(event, toggleScopeId))
|
|
1740
|
+
return;
|
|
1733
1741
|
if (isPerAppChatHosted) {
|
|
1734
1742
|
requestPerAppChatCommand("toggle");
|
|
1735
1743
|
return;
|
|
@@ -1774,7 +1782,7 @@ export function AgentSidebar({ children, enabled = true, emptyStateText = "How c
|
|
|
1774
1782
|
window.removeEventListener("agent-panel:open", openHandler);
|
|
1775
1783
|
window.removeEventListener("agent-panel:close", closeHandler);
|
|
1776
1784
|
};
|
|
1777
|
-
}, [setOpenPersisted, frameCodeMode, isPerAppChatHosted]);
|
|
1785
|
+
}, [setOpenPersisted, frameCodeMode, isPerAppChatHosted, toggleScopeId]);
|
|
1778
1786
|
// Listen for sidebar mode commands from the frame parent.
|
|
1779
1787
|
// When frame is in "code" mode, hide the app sidebar.
|
|
1780
1788
|
// When frame is in "app" mode, show the app sidebar, sync width and panel mode.
|
|
@@ -438,14 +438,14 @@ export interface AssistantChatProps {
|
|
|
438
438
|
externalStreaming?: boolean;
|
|
439
439
|
/**
|
|
440
440
|
* Optional host hooks for the inline `needsApproval` affordance beyond the
|
|
441
|
-
* built-in Approve
|
|
442
|
-
*
|
|
443
|
-
*
|
|
444
|
-
* standalone approval banner already uses (see CodeAgentsApp).
|
|
441
|
+
* built-in Approve and action-type policy. Code sessions pass their
|
|
442
|
+
* exact-command callback through for the standalone banner, but suppress the
|
|
443
|
+
* shared action-type menu (see CodeAgentsApp).
|
|
445
444
|
*/
|
|
446
445
|
approvalActions?: {
|
|
447
446
|
onDeny?: (approvalKey: string) => void;
|
|
448
|
-
onAlwaysAllow?: (approvalKey: string) => void
|
|
447
|
+
onAlwaysAllow?: (approvalKey: string, toolName: string) => void | Promise<void>;
|
|
448
|
+
alwaysAllowScope?: "action" | "exact-command";
|
|
449
449
|
};
|
|
450
450
|
}
|
|
451
451
|
export declare function shouldShowAssistantChatModelSelector(showModelSelector: boolean | undefined): boolean;
|
|
@@ -38,6 +38,7 @@ import { addMcpConnectionCompleteListener, consumeMcpConnectionResume, } from ".
|
|
|
38
38
|
import { McpConnectionSuggestion } from "./resources/McpConnectionSuggestion.js";
|
|
39
39
|
import { claimRunStream, createRunStreamToken, ownsRunStream, releaseRunStream, } from "./run-stream-ownership.js";
|
|
40
40
|
import { AgentAutoContinueSignal, readSSEStreamRaw, settleInterruptedToolCalls, } from "./sse-event-processor.js";
|
|
41
|
+
import { callAction } from "./use-action.js";
|
|
41
42
|
import { useAgentEngineConfigured } from "./use-agent-engine-configured.js";
|
|
42
43
|
import { appendChatThreadScopeParams, } from "./use-chat-threads.js";
|
|
43
44
|
import { useDevMode } from "./use-dev-mode.js";
|
|
@@ -4268,24 +4269,36 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
|
|
|
4268
4269
|
// tool call, re-issue the turn carrying the call's approval key so the server
|
|
4269
4270
|
// gate lets that specific call run. Reuses the same append path as recovery /
|
|
4270
4271
|
// queued messages (no hand-written fetch).
|
|
4272
|
+
const approveToolCall = useCallback((approvalKey) => {
|
|
4273
|
+
void addToQueue("Approved. Go ahead and run the requested action.", // i18n-ignore -- stable hidden agent instruction, not UI copy.
|
|
4274
|
+
undefined, undefined, undefined, undefined, "queued", undefined, false, false, false, true, // hideUserMessage: this is a protocol continuation, not a new prompt
|
|
4275
|
+
undefined, [approvalKey]);
|
|
4276
|
+
}, [addToQueue]);
|
|
4277
|
+
const alwaysAllowToolCall = useCallback((approvalKey, toolName) => {
|
|
4278
|
+
if (approvalActions?.onAlwaysAllow) {
|
|
4279
|
+
return approvalActions.onAlwaysAllow(approvalKey, toolName);
|
|
4280
|
+
}
|
|
4281
|
+
return callAction("set-tool-approval-policy", {
|
|
4282
|
+
toolName,
|
|
4283
|
+
enabled: true,
|
|
4284
|
+
}).then(() => approveToolCall(approvalKey));
|
|
4285
|
+
}, [approvalActions, approveToolCall]);
|
|
4286
|
+
const showActionTypeApprovalPolicy = approvalActions?.alwaysAllowScope !== "exact-command";
|
|
4271
4287
|
const approvalCtx = useMemo(() => ({
|
|
4272
4288
|
getApprovalResolution,
|
|
4273
4289
|
onApprovalResolved: recordApprovalResolution,
|
|
4274
|
-
onApprove:
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
undefined, [approvalKey]);
|
|
4278
|
-
},
|
|
4279
|
-
...(approvalActions?.onDeny ? { onDeny: approvalActions.onDeny } : {}),
|
|
4280
|
-
...(approvalActions?.onAlwaysAllow
|
|
4281
|
-
? { onAlwaysAllow: approvalActions.onAlwaysAllow }
|
|
4290
|
+
onApprove: approveToolCall,
|
|
4291
|
+
...(showActionTypeApprovalPolicy
|
|
4292
|
+
? { onAlwaysAllow: alwaysAllowToolCall }
|
|
4282
4293
|
: {}),
|
|
4294
|
+
...(approvalActions?.onDeny ? { onDeny: approvalActions.onDeny } : {}),
|
|
4283
4295
|
}), [
|
|
4284
|
-
|
|
4285
|
-
execMode,
|
|
4286
|
-
getApprovalResolution,
|
|
4296
|
+
alwaysAllowToolCall,
|
|
4287
4297
|
approvalActions,
|
|
4298
|
+
approveToolCall,
|
|
4299
|
+
getApprovalResolution,
|
|
4288
4300
|
recordApprovalResolution,
|
|
4301
|
+
showActionTypeApprovalPolicy,
|
|
4289
4302
|
]);
|
|
4290
4303
|
return (_jsx(SuppressInlineOpenAppContext.Provider, { value: suppressInlineOpenApp, children: _jsx(CheckpointContext.Provider, { value: checkpointCtx, children: _jsx(MessageActionsContext.Provider, { value: messageActionsCtx, children: _jsx(ApprovalContext.Provider, { value: approvalCtx, children: _jsx(ChatRunDurationContext.Provider, { value: lastChatRunDurationMs, children: _jsx(ServerRunActiveContext.Provider, { value: serverRunActive, children: _jsx(ChatRunningRunIdContext.Provider, { value: activeChatRunId, children: _jsx(ChatRunningTurnIdContext.Provider, { value: activeChatTurnId, children: _jsx(ChatRunningContext.Provider
|
|
4291
4304
|
// Keep the current message in a non-complete state while
|
|
@@ -23,8 +23,8 @@ export declare function ToolCallStackMotion({ children, className, }: {
|
|
|
23
23
|
* re-issues the turn approving a specific paused tool call (opt-in
|
|
24
24
|
* `needsApproval` actions). When null, the Approve button is not rendered.
|
|
25
25
|
* Deny defaults to local-only (the action stays un-run) unless `onDeny` is
|
|
26
|
-
* provided
|
|
27
|
-
*
|
|
26
|
+
* provided. The chevron menu persists an action-type policy before approving
|
|
27
|
+
* the current call.
|
|
28
28
|
*/
|
|
29
29
|
export type ApprovalResolution = "approved" | "denied";
|
|
30
30
|
export type ApprovalContextValue = {
|
|
@@ -51,10 +51,10 @@ export type ApprovalContextValue = {
|
|
|
51
51
|
*/
|
|
52
52
|
onDeny?: (approvalKey: string) => void;
|
|
53
53
|
/**
|
|
54
|
-
* Optional host hook that persists this
|
|
55
|
-
*
|
|
54
|
+
* Optional host hook that persists this action type and resolves the current
|
|
55
|
+
* call. The default AssistantChat implementation uses the shared policy.
|
|
56
56
|
*/
|
|
57
|
-
onAlwaysAllow?: (approvalKey: string) => void
|
|
57
|
+
onAlwaysAllow?: (approvalKey: string, toolName: string) => void | Promise<void>;
|
|
58
58
|
};
|
|
59
59
|
export declare const ApprovalContext: React.Context<ApprovalContextValue | null>;
|
|
60
60
|
/** Pending human-in-the-loop gate still waiting for Approve/Deny. */
|