@dexto/tui 1.13.5 → 1.14.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-backend.cjs +2 -0
- package/dist/agent-backend.d.ts +2 -0
- package/dist/agent-backend.d.ts.map +1 -1
- package/dist/agent-backend.js +2 -0
- package/dist/components/ApprovalPrompt.cjs +19 -17
- package/dist/components/ApprovalPrompt.d.ts +2 -1
- package/dist/components/ApprovalPrompt.d.ts.map +1 -1
- package/dist/components/ApprovalPrompt.js +19 -17
- package/dist/components/ApprovalPrompt.test.cjs +119 -0
- package/dist/components/ApprovalPrompt.test.d.ts +2 -0
- package/dist/components/ApprovalPrompt.test.d.ts.map +1 -0
- package/dist/components/ApprovalPrompt.test.js +120 -0
- package/dist/components/Footer.cjs +5 -1
- package/dist/components/Footer.d.ts.map +1 -1
- package/dist/components/Footer.js +5 -1
- package/dist/components/Footer.test.cjs +47 -0
- package/dist/components/Footer.test.d.ts +2 -0
- package/dist/components/Footer.test.d.ts.map +1 -0
- package/dist/components/Footer.test.js +46 -0
- package/dist/components/modes/AlternateBufferCLI.cjs +3 -1
- package/dist/components/modes/AlternateBufferCLI.d.ts.map +1 -1
- package/dist/components/modes/AlternateBufferCLI.js +3 -1
- package/dist/components/modes/StaticCLI.cjs +3 -1
- package/dist/components/modes/StaticCLI.d.ts.map +1 -1
- package/dist/components/modes/StaticCLI.js +3 -1
- package/dist/components/overlays/PermissionsSelector.cjs +139 -0
- package/dist/components/overlays/PermissionsSelector.d.ts +16 -0
- package/dist/components/overlays/PermissionsSelector.d.ts.map +1 -0
- package/dist/components/overlays/PermissionsSelector.js +115 -0
- package/dist/components/overlays/PermissionsSelector.test.cjs +105 -0
- package/dist/components/overlays/PermissionsSelector.test.d.ts +2 -0
- package/dist/components/overlays/PermissionsSelector.test.d.ts.map +1 -0
- package/dist/components/overlays/PermissionsSelector.test.js +104 -0
- package/dist/containers/InputContainer.cjs +108 -28
- package/dist/containers/InputContainer.d.ts +1 -0
- package/dist/containers/InputContainer.d.ts.map +1 -1
- package/dist/containers/InputContainer.js +108 -28
- package/dist/containers/OverlayContainer.cjs +15 -0
- package/dist/containers/OverlayContainer.d.ts.map +1 -1
- package/dist/containers/OverlayContainer.js +17 -0
- package/dist/hooks/useAgentEvents.cjs +6 -3
- package/dist/hooks/useAgentEvents.d.ts.map +1 -1
- package/dist/hooks/useAgentEvents.js +6 -3
- package/dist/hooks/useCLIState.cjs +28 -8
- package/dist/hooks/useCLIState.d.ts +1 -0
- package/dist/hooks/useCLIState.d.ts.map +1 -1
- package/dist/hooks/useCLIState.js +28 -8
- package/dist/hooks/useCLIState.test.cjs +583 -0
- package/dist/hooks/useCLIState.test.d.ts +2 -0
- package/dist/hooks/useCLIState.test.d.ts.map +1 -0
- package/dist/hooks/useCLIState.test.js +582 -0
- package/dist/index.d.cts +2 -0
- package/dist/interactive-commands/commands.test.cjs +6 -0
- package/dist/interactive-commands/commands.test.js +6 -0
- package/dist/interactive-commands/tool-commands.cjs +7 -0
- package/dist/interactive-commands/tool-commands.d.ts.map +1 -1
- package/dist/interactive-commands/tool-commands.js +7 -0
- package/dist/services/processStream.cjs +4 -2
- package/dist/services/processStream.d.ts.map +1 -1
- package/dist/services/processStream.js +4 -2
- package/dist/services/processStream.test.cjs +63 -0
- package/dist/services/processStream.test.js +63 -0
- package/dist/state/types.d.ts +1 -1
- package/dist/state/types.d.ts.map +1 -1
- package/dist/utils/approvalScope.cjs +35 -0
- package/dist/utils/approvalScope.d.ts +3 -0
- package/dist/utils/approvalScope.d.ts.map +1 -0
- package/dist/utils/approvalScope.js +11 -0
- package/dist/utils/commandOverlays.cjs +1 -0
- package/dist/utils/commandOverlays.d.ts.map +1 -1
- package/dist/utils/commandOverlays.js +1 -0
- package/package.json +5 -5
package/dist/agent-backend.cjs
CHANGED
|
@@ -75,6 +75,8 @@ function getTuiCapabilities(agent) {
|
|
|
75
75
|
}
|
|
76
76
|
function isCommandSupported(agent, command, definition) {
|
|
77
77
|
const capabilities = getTuiCapabilities(agent);
|
|
78
|
+
if (normalizeCommandName(command) === "permissions" && (!agent.getSessionApprovals || !agent.revokeSessionApproval))
|
|
79
|
+
return false;
|
|
78
80
|
const supportedCommands = capabilities.supportedCommands;
|
|
79
81
|
const candidates = /* @__PURE__ */ new Set([normalizeCommandName(command)]);
|
|
80
82
|
if (definition?.name) {
|
package/dist/agent-backend.d.ts
CHANGED
|
@@ -35,6 +35,8 @@ export interface TuiEffectiveConfig {
|
|
|
35
35
|
[key: string]: unknown;
|
|
36
36
|
}
|
|
37
37
|
export interface TuiAgentBackend extends Pick<DextoAgent, 'stream' | 'stop' | 'run' | 'listSessions' | 'getSessionMetadata' | 'getSessionHistory' | 'getSessionTitle' | 'setSessionTitle' | 'generateSessionTitle' | 'forkSession' | 'getCurrentLLMConfig' | 'hasSessionLLMOverride' | 'switchLLM' | 'getSupportedProviders' | 'getSupportedModels' | 'getContextStats' | 'clearContext' | 'compactContext' | 'steer' | 'followUp' | 'getSteerMessages' | 'getFollowUpMessages' | 'removeSteerMessage' | 'removeFollowUpMessage' | 'clearSteerQueue' | 'clearFollowUpQueue' | 'cancel' | 'searchMessages' | 'listPrompts' | 'refreshPrompts' | 'resolvePrompt' | 'getSystemPrompt' | 'loadToolkits' | 'listResources' | 'setLogLevel' | 'getAllTools' | 'getEnabledTools' | 'getAllMcpTools' | 'setGlobalDisabledTools' | 'setSessionDisabledTools' | 'setSessionAutoApproveTools' | 'getSessionAutoApproveTools' | 'getMcpServersWithStatus' | 'addMcpServer' | 'enableMcpServer' | 'disableMcpServer' | 'removeMcpServer' | 'restartMcpServer' | 'getMcpClients' | 'getMcpFailedConnections'> {
|
|
38
|
+
getSessionApprovals?: DextoAgent['getSessionApprovals'];
|
|
39
|
+
revokeSessionApproval?: DextoAgent['revokeSessionApproval'];
|
|
38
40
|
createSession: (sessionId?: string) => Promise<{
|
|
39
41
|
id: string;
|
|
40
42
|
logger: Pick<RootLogger, 'getLevel' | 'getLogFilePath'>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent-backend.d.ts","sourceRoot":"","sources":["../src/agent-backend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,aAAa,EACb,UAAU,EACV,SAAS,EACT,aAAa,EACb,eAAe,EACf,MAAM,EACT,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAElF,MAAM,WAAW,oBAAoB;IACjC,iBAAiB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,KAAK,UAAU,GAAG,IAAI,CAClB,UAAU,CAAC,QAAQ,CAAC,EACpB,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,UAAU,GAAG,gBAAgB,CACtE,CAAC;AAEF,UAAU,eAAe;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IAC/B,GAAG,EAAE;QACD,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;QAC5C,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;KAC3C,CAAC;IACF,WAAW,EAAE;QACT,IAAI,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,QAAQ,CAAC,EACH;QACI,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;KACnC,GACD,SAAS,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACjD,OAAO,CAAC,EAAE,OAAO,EAAE,GAAG,SAAS,CAAC;IAChC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CAC1B;AAED,MAAM,WAAW,eACb,SAAQ,IAAI,CACR,UAAU,EACR,QAAQ,GACR,MAAM,GACN,KAAK,GACL,cAAc,GACd,oBAAoB,GACpB,mBAAmB,GACnB,iBAAiB,GACjB,iBAAiB,GACjB,sBAAsB,GACtB,aAAa,GACb,qBAAqB,GACrB,uBAAuB,GACvB,WAAW,GACX,uBAAuB,GACvB,oBAAoB,GACpB,iBAAiB,GACjB,cAAc,GACd,gBAAgB,GAChB,OAAO,GACP,UAAU,GACV,kBAAkB,GAClB,qBAAqB,GACrB,oBAAoB,GACpB,uBAAuB,GACvB,iBAAiB,GACjB,oBAAoB,GACpB,QAAQ,GACR,gBAAgB,GAChB,aAAa,GACb,gBAAgB,GAChB,eAAe,GACf,iBAAiB,GACjB,cAAc,GACd,eAAe,GACf,aAAa,GACb,aAAa,GACb,iBAAiB,GACjB,gBAAgB,GAChB,wBAAwB,GACxB,yBAAyB,GACzB,4BAA4B,GAC5B,4BAA4B,GAC5B,yBAAyB,GACzB,cAAc,GACd,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,kBAAkB,GAClB,eAAe,GACf,yBAAyB,CAC9B;IACD,aAAa,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;QAC3C,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAAC,CAAC;KAC3D,CAAC,CAAC;IACH,UAAU,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CACpC;QACI,EAAE,EAAE,MAAM,CAAC;QACX,MAAM,EAAE,IAAI,CAAC,UAAU,EAAE,UAAU,GAAG,gBAAgB,CAAC,CAAC;KAC3D,GACD,SAAS,CACd,CAAC;IACF,kBAAkB,EAAE,CAAC,SAAS,CAAC,EAAE,MAAM,KAAK,kBAAkB,CAAC;IAC/D,EAAE,EAAE,CAAC,CAAC,SAAS,MAAM,aAAa,EAC9B,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EACzC,OAAO,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,WAAW,CAAA;KAAE,KACjC,IAAI,CAAC;IACV,IAAI,EAAE,CAAC,CAAC,SAAS,MAAM,aAAa,EAChC,KAAK,EAAE,CAAC,EACR,GAAG,IAAI,EAAE,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KACnC,OAAO,CAAC;IACb,MAAM,EAAE,UAAU,CAAC;IACnB,MAAM,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;KACnB,CAAC;IACF,cAAc,EAAE;QACZ,kBAAkB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC,CAAC;QAChF,eAAe,EAAE,MAAM,OAAO,CAAC,eAAe,CAAC,CAAC;KACnD,CAAC;IACF,UAAU,EAAE;QACR,UAAU,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACvC,oBAAoB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACvD,CAAC;IACF,WAAW,EAAE;QACT,0BAA0B,EAAE,CACxB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,MAAM,EAAE,KAClB,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;KAC7B,CAAC;IACF,QAAQ,EAAE;QACN,WAAW,EAAE;YACT,YAAY,EAAE,MAAM,MAAM,EAAE,CAAC;SAChC,CAAC;KACL,CAAC;IACF,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,YAAY,CAAC,EAAE,oBAAoB,CAAC;CACvC;AAsCD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,eAAe,GAAG,oBAAoB,CAe/E;AAED,wBAAgB,kBAAkB,CAC9B,KAAK,EAAE,eAAe,EACtB,OAAO,EAAE,MAAM,EACf,UAAU,CAAC,EAAE,IAAI,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC,GACzD,OAAO,
|
|
1
|
+
{"version":3,"file":"agent-backend.d.ts","sourceRoot":"","sources":["../src/agent-backend.ts"],"names":[],"mappings":"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"}
|
package/dist/agent-backend.js
CHANGED
|
@@ -43,6 +43,8 @@ function getTuiCapabilities(agent) {
|
|
|
43
43
|
}
|
|
44
44
|
function isCommandSupported(agent, command, definition) {
|
|
45
45
|
const capabilities = getTuiCapabilities(agent);
|
|
46
|
+
if (normalizeCommandName(command) === "permissions" && (!agent.getSessionApprovals || !agent.revokeSessionApproval))
|
|
47
|
+
return false;
|
|
46
48
|
const supportedCommands = capabilities.supportedCommands;
|
|
47
49
|
const candidates = /* @__PURE__ */ new Set([normalizeCommandName(command)]);
|
|
48
50
|
if (definition?.name) {
|
|
@@ -28,6 +28,7 @@ var import_core = require("@dexto/core");
|
|
|
28
28
|
var import_ElicitationForm = require("./ElicitationForm.js");
|
|
29
29
|
var import_renderers = require("./renderers/index.js");
|
|
30
30
|
var import_toolUtils = require("../utils/toolUtils.js");
|
|
31
|
+
var import_approvalScope = require("../utils/approvalScope.js");
|
|
31
32
|
var import_messageFormatting = require("../utils/messageFormatting.js");
|
|
32
33
|
const ApprovalPrompt = (0, import_react.forwardRef)(
|
|
33
34
|
({ approval, onApprove, onDeny, onCancel }, ref) => {
|
|
@@ -36,7 +37,10 @@ const ApprovalPrompt = (0, import_react.forwardRef)(
|
|
|
36
37
|
const toolName = approval.metadata.toolName;
|
|
37
38
|
const toolArgs = approval.metadata.args || {};
|
|
38
39
|
const approvalKey = typeof approval.metadata.approvalKey === "string" ? approval.metadata.approvalKey : void 0;
|
|
39
|
-
const
|
|
40
|
+
const canRemember = approval.type === import_core.ApprovalType.TOOL_APPROVAL && approval.sessionId !== void 0 && approval.autoApproval !== "disallowed";
|
|
41
|
+
const rememberedScope = (0, import_approvalScope.formatApprovalScope)(
|
|
42
|
+
approvalKey !== void 0 ? { kind: "action", value: approvalKey } : { kind: "tool", value: toolName ?? "unknown" }
|
|
43
|
+
);
|
|
40
44
|
const callDescriptionRaw = typeof approval.metadata.description === "string" ? approval.metadata.description : void 0;
|
|
41
45
|
const callDescription = (0, import_react.useMemo)(() => {
|
|
42
46
|
if (!callDescriptionRaw) return null;
|
|
@@ -48,6 +52,7 @@ const ApprovalPrompt = (0, import_react.forwardRef)(
|
|
|
48
52
|
}, [callDescriptionRaw]);
|
|
49
53
|
const isPlanReview = toolName === "plan_review";
|
|
50
54
|
const isEditOrWriteTool = (0, import_toolUtils.isEditWriteTool)(toolName);
|
|
55
|
+
const canAcceptEdits = canRemember && isEditOrWriteTool && approvalKey === void 0;
|
|
51
56
|
const presentationSnapshot = (0, import_react.useMemo)(() => {
|
|
52
57
|
const raw = approval.metadata["presentationSnapshot"];
|
|
53
58
|
return (0, import_core.isToolPresentationSnapshotV1)(raw) ? raw : void 0;
|
|
@@ -69,21 +74,18 @@ const ApprovalPrompt = (0, import_react.forwardRef)(
|
|
|
69
74
|
if (isPlanReview) {
|
|
70
75
|
options.push({ id: "plan-approve", label: "Approve" });
|
|
71
76
|
options.push({ id: "plan-approve-accept-edits", label: "Approve + Accept All Edits" });
|
|
72
|
-
} else if (isCommandApproval) {
|
|
73
|
-
options.push({ id: "yes", label: "Yes" });
|
|
74
|
-
options.push({ id: "no", label: "No" });
|
|
75
|
-
} else if (hasApprovalKey) {
|
|
76
|
-
options.push({ id: "yes", label: "Yes (once)" });
|
|
77
|
-
options.push({ id: "yes-session", label: "Yes, remember this approval" });
|
|
78
|
-
options.push({ id: "no", label: "No" });
|
|
79
|
-
} else if (isEditOrWriteTool) {
|
|
80
|
-
options.push({ id: "yes", label: "Yes" });
|
|
81
|
-
options.push({ id: "yes-accept-edits", label: "Yes, and accept all edits" });
|
|
82
|
-
options.push({ id: "no", label: "No" });
|
|
83
77
|
} else {
|
|
84
|
-
options.push({ id: "yes", label: "
|
|
85
|
-
|
|
86
|
-
|
|
78
|
+
options.push({ id: "yes", label: "Allow once" });
|
|
79
|
+
if (canRemember) {
|
|
80
|
+
options.push({
|
|
81
|
+
id: "yes-session",
|
|
82
|
+
label: `Allow ${rememberedScope} for this session`
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (canAcceptEdits) {
|
|
86
|
+
options.push({ id: "yes-accept-edits", label: "Allow all edits for this session" });
|
|
87
|
+
}
|
|
88
|
+
options.push({ id: "no", label: "Reject" });
|
|
87
89
|
}
|
|
88
90
|
(0, import_react.useEffect)(() => {
|
|
89
91
|
selectedIndexRef.current = selectedIndex;
|
|
@@ -147,7 +149,7 @@ const ApprovalPrompt = (0, import_react.forwardRef)(
|
|
|
147
149
|
onDeny();
|
|
148
150
|
}
|
|
149
151
|
return true;
|
|
150
|
-
} else if (key.shift && key.tab &&
|
|
152
|
+
} else if (key.shift && key.tab && canAcceptEdits) {
|
|
151
153
|
onApprove({ enableAcceptEditsMode: true });
|
|
152
154
|
return true;
|
|
153
155
|
} else if (key.escape) {
|
|
@@ -159,7 +161,7 @@ const ApprovalPrompt = (0, import_react.forwardRef)(
|
|
|
159
161
|
}),
|
|
160
162
|
[
|
|
161
163
|
isElicitation,
|
|
162
|
-
|
|
164
|
+
canAcceptEdits,
|
|
163
165
|
isPlanReview,
|
|
164
166
|
options,
|
|
165
167
|
onApprove,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type { HostRuntimeContext } from '@dexto/core';
|
|
2
|
+
import type { HostRuntimeContext, ApprovalAutoApprovalPolicy } from '@dexto/core';
|
|
3
3
|
import type { Key } from '../hooks/useInputOrchestrator.js';
|
|
4
4
|
export interface ApprovalRequest {
|
|
5
5
|
approvalId: string;
|
|
6
|
+
autoApproval?: ApprovalAutoApprovalPolicy;
|
|
6
7
|
type: string;
|
|
7
8
|
sessionId?: string;
|
|
8
9
|
hostRuntime?: HostRuntimeContext;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ApprovalPrompt.d.ts","sourceRoot":"","sources":["../../src/components/ApprovalPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"ApprovalPrompt.d.ts","sourceRoot":"","sources":["../../src/components/ApprovalPrompt.tsx"],"names":[],"mappings":"AAAA,OAAO,KAON,MAAM,OAAO,CAAC;AAEf,OAAO,KAAK,EACR,kBAAkB,EAGlB,0BAA0B,EAC7B,MAAM,aAAa,CAAC;AAErB,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kCAAkC,CAAC;AAO5D,MAAM,WAAW,eAAe;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,oBAAoB;IACjC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC;CACrD;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,mDAAmD;IACnD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,yCAAyC;IACzC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,gFAAgF;IAChF,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACnC;AAED,UAAU,mBAAmB;IACzB,QAAQ,EAAE,eAAe,CAAC;IAC1B,SAAS,EAAE,CAAC,OAAO,EAAE,eAAe,KAAK,IAAI,CAAC;IAC9C,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpC,QAAQ,EAAE,MAAM,IAAI,CAAC;CACxB;AAYD;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,kGAsY1B,CAAC"}
|
|
@@ -12,6 +12,7 @@ import { ApprovalType, isToolPresentationSnapshotV1 } from "@dexto/core";
|
|
|
12
12
|
import { ElicitationForm } from "./ElicitationForm.js";
|
|
13
13
|
import { DiffPreview, CreateFilePreview } from "./renderers/index.js";
|
|
14
14
|
import { isEditWriteTool } from "../utils/toolUtils.js";
|
|
15
|
+
import { formatApprovalScope } from "../utils/approvalScope.js";
|
|
15
16
|
import { formatToolHeader } from "../utils/messageFormatting.js";
|
|
16
17
|
const ApprovalPrompt = forwardRef(
|
|
17
18
|
({ approval, onApprove, onDeny, onCancel }, ref) => {
|
|
@@ -20,7 +21,10 @@ const ApprovalPrompt = forwardRef(
|
|
|
20
21
|
const toolName = approval.metadata.toolName;
|
|
21
22
|
const toolArgs = approval.metadata.args || {};
|
|
22
23
|
const approvalKey = typeof approval.metadata.approvalKey === "string" ? approval.metadata.approvalKey : void 0;
|
|
23
|
-
const
|
|
24
|
+
const canRemember = approval.type === ApprovalType.TOOL_APPROVAL && approval.sessionId !== void 0 && approval.autoApproval !== "disallowed";
|
|
25
|
+
const rememberedScope = formatApprovalScope(
|
|
26
|
+
approvalKey !== void 0 ? { kind: "action", value: approvalKey } : { kind: "tool", value: toolName ?? "unknown" }
|
|
27
|
+
);
|
|
24
28
|
const callDescriptionRaw = typeof approval.metadata.description === "string" ? approval.metadata.description : void 0;
|
|
25
29
|
const callDescription = useMemo(() => {
|
|
26
30
|
if (!callDescriptionRaw) return null;
|
|
@@ -32,6 +36,7 @@ const ApprovalPrompt = forwardRef(
|
|
|
32
36
|
}, [callDescriptionRaw]);
|
|
33
37
|
const isPlanReview = toolName === "plan_review";
|
|
34
38
|
const isEditOrWriteTool = isEditWriteTool(toolName);
|
|
39
|
+
const canAcceptEdits = canRemember && isEditOrWriteTool && approvalKey === void 0;
|
|
35
40
|
const presentationSnapshot = useMemo(() => {
|
|
36
41
|
const raw = approval.metadata["presentationSnapshot"];
|
|
37
42
|
return isToolPresentationSnapshotV1(raw) ? raw : void 0;
|
|
@@ -53,21 +58,18 @@ const ApprovalPrompt = forwardRef(
|
|
|
53
58
|
if (isPlanReview) {
|
|
54
59
|
options.push({ id: "plan-approve", label: "Approve" });
|
|
55
60
|
options.push({ id: "plan-approve-accept-edits", label: "Approve + Accept All Edits" });
|
|
56
|
-
} else if (isCommandApproval) {
|
|
57
|
-
options.push({ id: "yes", label: "Yes" });
|
|
58
|
-
options.push({ id: "no", label: "No" });
|
|
59
|
-
} else if (hasApprovalKey) {
|
|
60
|
-
options.push({ id: "yes", label: "Yes (once)" });
|
|
61
|
-
options.push({ id: "yes-session", label: "Yes, remember this approval" });
|
|
62
|
-
options.push({ id: "no", label: "No" });
|
|
63
|
-
} else if (isEditOrWriteTool) {
|
|
64
|
-
options.push({ id: "yes", label: "Yes" });
|
|
65
|
-
options.push({ id: "yes-accept-edits", label: "Yes, and accept all edits" });
|
|
66
|
-
options.push({ id: "no", label: "No" });
|
|
67
61
|
} else {
|
|
68
|
-
options.push({ id: "yes", label: "
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
options.push({ id: "yes", label: "Allow once" });
|
|
63
|
+
if (canRemember) {
|
|
64
|
+
options.push({
|
|
65
|
+
id: "yes-session",
|
|
66
|
+
label: `Allow ${rememberedScope} for this session`
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
if (canAcceptEdits) {
|
|
70
|
+
options.push({ id: "yes-accept-edits", label: "Allow all edits for this session" });
|
|
71
|
+
}
|
|
72
|
+
options.push({ id: "no", label: "Reject" });
|
|
71
73
|
}
|
|
72
74
|
useEffect(() => {
|
|
73
75
|
selectedIndexRef.current = selectedIndex;
|
|
@@ -131,7 +133,7 @@ const ApprovalPrompt = forwardRef(
|
|
|
131
133
|
onDeny();
|
|
132
134
|
}
|
|
133
135
|
return true;
|
|
134
|
-
} else if (key.shift && key.tab &&
|
|
136
|
+
} else if (key.shift && key.tab && canAcceptEdits) {
|
|
135
137
|
onApprove({ enableAcceptEditsMode: true });
|
|
136
138
|
return true;
|
|
137
139
|
} else if (key.escape) {
|
|
@@ -143,7 +145,7 @@ const ApprovalPrompt = forwardRef(
|
|
|
143
145
|
}),
|
|
144
146
|
[
|
|
145
147
|
isElicitation,
|
|
146
|
-
|
|
148
|
+
canAcceptEdits,
|
|
147
149
|
isPlanReview,
|
|
148
150
|
options,
|
|
149
151
|
onApprove,
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_react = require("react");
|
|
3
|
+
var import_node_stream = require("node:stream");
|
|
4
|
+
var import_ink = require("ink");
|
|
5
|
+
var import_vitest = require("vitest");
|
|
6
|
+
var import_ApprovalPrompt = require("./ApprovalPrompt.js");
|
|
7
|
+
const key = {
|
|
8
|
+
upArrow: false,
|
|
9
|
+
downArrow: false,
|
|
10
|
+
leftArrow: false,
|
|
11
|
+
rightArrow: false,
|
|
12
|
+
pageUp: false,
|
|
13
|
+
pageDown: false,
|
|
14
|
+
return: false,
|
|
15
|
+
escape: false,
|
|
16
|
+
ctrl: false,
|
|
17
|
+
shift: false,
|
|
18
|
+
meta: false,
|
|
19
|
+
tab: false,
|
|
20
|
+
backspace: false,
|
|
21
|
+
delete: false,
|
|
22
|
+
paste: false
|
|
23
|
+
};
|
|
24
|
+
(0, import_vitest.describe)("ApprovalPrompt", () => {
|
|
25
|
+
(0, import_vitest.it)("shows the remembered command scope and submits a session approval", async () => {
|
|
26
|
+
const stdout = Object.assign(new import_node_stream.PassThrough(), { columns: 120, rows: 40, isTTY: false });
|
|
27
|
+
let output = "";
|
|
28
|
+
stdout.on("data", (chunk) => {
|
|
29
|
+
output += String(chunk);
|
|
30
|
+
});
|
|
31
|
+
const ref = (0, import_react.createRef)();
|
|
32
|
+
const onApprove = import_vitest.vi.fn();
|
|
33
|
+
const view = (0, import_ink.render)(
|
|
34
|
+
(0, import_react.createElement)(import_ApprovalPrompt.ApprovalPrompt, {
|
|
35
|
+
ref,
|
|
36
|
+
approval: {
|
|
37
|
+
approvalId: "request",
|
|
38
|
+
type: "tool_approval",
|
|
39
|
+
sessionId: "a",
|
|
40
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
41
|
+
metadata: {
|
|
42
|
+
toolName: "bash_exec",
|
|
43
|
+
approvalKey: "bash:git status *",
|
|
44
|
+
args: { command: "git status --short" }
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
onApprove,
|
|
48
|
+
onDeny: import_vitest.vi.fn(),
|
|
49
|
+
onCancel: import_vitest.vi.fn()
|
|
50
|
+
}),
|
|
51
|
+
{
|
|
52
|
+
stdout,
|
|
53
|
+
// Ink buffers dynamic frames in CI unless debug rendering is enabled.
|
|
54
|
+
debug: true,
|
|
55
|
+
patchConsole: false,
|
|
56
|
+
exitOnCtrlC: false
|
|
57
|
+
}
|
|
58
|
+
);
|
|
59
|
+
try {
|
|
60
|
+
await import_vitest.vi.waitFor(() => (0, import_vitest.expect)(output).toContain("Allow git status * for this session"));
|
|
61
|
+
ref.current?.handleInput("", { ...key, downArrow: true });
|
|
62
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
63
|
+
ref.current?.handleInput("", { ...key, return: true });
|
|
64
|
+
(0, import_vitest.expect)(onApprove).toHaveBeenCalledWith({ rememberChoice: true });
|
|
65
|
+
} finally {
|
|
66
|
+
view.unmount();
|
|
67
|
+
view.cleanup();
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
import_vitest.it.each([
|
|
71
|
+
{ type: "command_approval", metadata: { toolName: "edit_file" } },
|
|
72
|
+
{
|
|
73
|
+
type: "tool_approval",
|
|
74
|
+
autoApproval: "disallowed",
|
|
75
|
+
metadata: { toolName: "edit_file" }
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
type: "tool_approval",
|
|
79
|
+
metadata: { toolName: "edit_file", approvalKey: "file:specific-path" }
|
|
80
|
+
}
|
|
81
|
+
])("does not broaden restricted edit approvals: %j", async (request) => {
|
|
82
|
+
const stdout = Object.assign(new import_node_stream.PassThrough(), { columns: 120, rows: 40, isTTY: false });
|
|
83
|
+
let output = "";
|
|
84
|
+
stdout.on("data", (chunk) => {
|
|
85
|
+
output += String(chunk);
|
|
86
|
+
});
|
|
87
|
+
const ref = (0, import_react.createRef)();
|
|
88
|
+
const onApprove = import_vitest.vi.fn();
|
|
89
|
+
const view = (0, import_ink.render)(
|
|
90
|
+
(0, import_react.createElement)(import_ApprovalPrompt.ApprovalPrompt, {
|
|
91
|
+
ref,
|
|
92
|
+
approval: {
|
|
93
|
+
...request,
|
|
94
|
+
approvalId: "restricted",
|
|
95
|
+
sessionId: "a",
|
|
96
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
97
|
+
},
|
|
98
|
+
onApprove,
|
|
99
|
+
onDeny: import_vitest.vi.fn(),
|
|
100
|
+
onCancel: import_vitest.vi.fn()
|
|
101
|
+
}),
|
|
102
|
+
{
|
|
103
|
+
stdout,
|
|
104
|
+
debug: true,
|
|
105
|
+
patchConsole: false,
|
|
106
|
+
exitOnCtrlC: false
|
|
107
|
+
}
|
|
108
|
+
);
|
|
109
|
+
try {
|
|
110
|
+
await import_vitest.vi.waitFor(() => (0, import_vitest.expect)(output).toContain("Allow once"));
|
|
111
|
+
(0, import_vitest.expect)(output).not.toContain("Allow all edits for this session");
|
|
112
|
+
ref.current?.handleInput("", { ...key, shift: true, tab: true });
|
|
113
|
+
(0, import_vitest.expect)(onApprove).not.toHaveBeenCalled();
|
|
114
|
+
} finally {
|
|
115
|
+
view.unmount();
|
|
116
|
+
view.cleanup();
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApprovalPrompt.test.d.ts","sourceRoot":"","sources":["../../src/components/ApprovalPrompt.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import { createElement, createRef } from "react";
|
|
2
|
+
import { PassThrough } from "node:stream";
|
|
3
|
+
import { render } from "ink";
|
|
4
|
+
import { describe, expect, it, vi } from "vitest";
|
|
5
|
+
import {
|
|
6
|
+
ApprovalPrompt
|
|
7
|
+
} from "./ApprovalPrompt.js";
|
|
8
|
+
const key = {
|
|
9
|
+
upArrow: false,
|
|
10
|
+
downArrow: false,
|
|
11
|
+
leftArrow: false,
|
|
12
|
+
rightArrow: false,
|
|
13
|
+
pageUp: false,
|
|
14
|
+
pageDown: false,
|
|
15
|
+
return: false,
|
|
16
|
+
escape: false,
|
|
17
|
+
ctrl: false,
|
|
18
|
+
shift: false,
|
|
19
|
+
meta: false,
|
|
20
|
+
tab: false,
|
|
21
|
+
backspace: false,
|
|
22
|
+
delete: false,
|
|
23
|
+
paste: false
|
|
24
|
+
};
|
|
25
|
+
describe("ApprovalPrompt", () => {
|
|
26
|
+
it("shows the remembered command scope and submits a session approval", async () => {
|
|
27
|
+
const stdout = Object.assign(new PassThrough(), { columns: 120, rows: 40, isTTY: false });
|
|
28
|
+
let output = "";
|
|
29
|
+
stdout.on("data", (chunk) => {
|
|
30
|
+
output += String(chunk);
|
|
31
|
+
});
|
|
32
|
+
const ref = createRef();
|
|
33
|
+
const onApprove = vi.fn();
|
|
34
|
+
const view = render(
|
|
35
|
+
createElement(ApprovalPrompt, {
|
|
36
|
+
ref,
|
|
37
|
+
approval: {
|
|
38
|
+
approvalId: "request",
|
|
39
|
+
type: "tool_approval",
|
|
40
|
+
sessionId: "a",
|
|
41
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
42
|
+
metadata: {
|
|
43
|
+
toolName: "bash_exec",
|
|
44
|
+
approvalKey: "bash:git status *",
|
|
45
|
+
args: { command: "git status --short" }
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
onApprove,
|
|
49
|
+
onDeny: vi.fn(),
|
|
50
|
+
onCancel: vi.fn()
|
|
51
|
+
}),
|
|
52
|
+
{
|
|
53
|
+
stdout,
|
|
54
|
+
// Ink buffers dynamic frames in CI unless debug rendering is enabled.
|
|
55
|
+
debug: true,
|
|
56
|
+
patchConsole: false,
|
|
57
|
+
exitOnCtrlC: false
|
|
58
|
+
}
|
|
59
|
+
);
|
|
60
|
+
try {
|
|
61
|
+
await vi.waitFor(() => expect(output).toContain("Allow git status * for this session"));
|
|
62
|
+
ref.current?.handleInput("", { ...key, downArrow: true });
|
|
63
|
+
await new Promise((resolve) => setTimeout(resolve, 20));
|
|
64
|
+
ref.current?.handleInput("", { ...key, return: true });
|
|
65
|
+
expect(onApprove).toHaveBeenCalledWith({ rememberChoice: true });
|
|
66
|
+
} finally {
|
|
67
|
+
view.unmount();
|
|
68
|
+
view.cleanup();
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
it.each([
|
|
72
|
+
{ type: "command_approval", metadata: { toolName: "edit_file" } },
|
|
73
|
+
{
|
|
74
|
+
type: "tool_approval",
|
|
75
|
+
autoApproval: "disallowed",
|
|
76
|
+
metadata: { toolName: "edit_file" }
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
type: "tool_approval",
|
|
80
|
+
metadata: { toolName: "edit_file", approvalKey: "file:specific-path" }
|
|
81
|
+
}
|
|
82
|
+
])("does not broaden restricted edit approvals: %j", async (request) => {
|
|
83
|
+
const stdout = Object.assign(new PassThrough(), { columns: 120, rows: 40, isTTY: false });
|
|
84
|
+
let output = "";
|
|
85
|
+
stdout.on("data", (chunk) => {
|
|
86
|
+
output += String(chunk);
|
|
87
|
+
});
|
|
88
|
+
const ref = createRef();
|
|
89
|
+
const onApprove = vi.fn();
|
|
90
|
+
const view = render(
|
|
91
|
+
createElement(ApprovalPrompt, {
|
|
92
|
+
ref,
|
|
93
|
+
approval: {
|
|
94
|
+
...request,
|
|
95
|
+
approvalId: "restricted",
|
|
96
|
+
sessionId: "a",
|
|
97
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
98
|
+
},
|
|
99
|
+
onApprove,
|
|
100
|
+
onDeny: vi.fn(),
|
|
101
|
+
onCancel: vi.fn()
|
|
102
|
+
}),
|
|
103
|
+
{
|
|
104
|
+
stdout,
|
|
105
|
+
debug: true,
|
|
106
|
+
patchConsole: false,
|
|
107
|
+
exitOnCtrlC: false
|
|
108
|
+
}
|
|
109
|
+
);
|
|
110
|
+
try {
|
|
111
|
+
await vi.waitFor(() => expect(output).toContain("Allow once"));
|
|
112
|
+
expect(output).not.toContain("Allow all edits for this session");
|
|
113
|
+
ref.current?.handleInput("", { ...key, shift: true, tab: true });
|
|
114
|
+
expect(onApprove).not.toHaveBeenCalled();
|
|
115
|
+
} finally {
|
|
116
|
+
view.unmount();
|
|
117
|
+
view.cleanup();
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
@@ -154,6 +154,10 @@ function Footer({
|
|
|
154
154
|
"% context left"
|
|
155
155
|
] }) }),
|
|
156
156
|
chatGPTRateLimitHint && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: chatGPTRateLimitColor, children: chatGPTRateLimitHint }) }),
|
|
157
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Box, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Text, { color: "gray", children: [
|
|
158
|
+
"approvals: ",
|
|
159
|
+
agent.getEffectiveConfig(sessionId ?? void 0).permissions.mode
|
|
160
|
+
] }) }),
|
|
157
161
|
isShellMode && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { children: [
|
|
158
162
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "yellow", bold: true, children: "!" }),
|
|
159
163
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: " for shell mode" })
|
|
@@ -167,7 +171,7 @@ function Footer({
|
|
|
167
171
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: " (shift + tab to cycle)" })
|
|
168
172
|
] }),
|
|
169
173
|
bypassPermissions && !planModeActive && !autoApproveEdits && !isShellMode && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_ink.Box, { children: [
|
|
170
|
-
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "
|
|
174
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: "auto-approve (session)" }),
|
|
171
175
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_ink.Text, { color: "gray", children: " (shift + tab to cycle)" })
|
|
172
176
|
] })
|
|
173
177
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Footer.d.ts","sourceRoot":"","sources":["../../src/components/Footer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAM7E,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEjF,UAAU,WAAW;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC1D;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,EACnB,KAAK,EACL,SAAS,EACT,SAAS,EACT,GAAG,EACH,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,sBAAsB,GACzB,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"Footer.d.ts","sourceRoot":"","sources":["../../src/components/Footer.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAMH,OAAO,EAAqB,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAM7E,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEjF,UAAU,WAAW;IACjB,KAAK,EAAE,eAAe,CAAC;IACvB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kEAAkE;IAClE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,IAAI,CAAC;CAC1D;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,EACnB,KAAK,EACL,SAAS,EACT,SAAS,EACT,GAAG,EACH,UAAU,EACV,gBAAgB,EAChB,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,sBAAsB,GACzB,EAAE,WAAW,2CAkLb"}
|
|
@@ -124,6 +124,10 @@ function Footer({
|
|
|
124
124
|
"% context left"
|
|
125
125
|
] }) }),
|
|
126
126
|
chatGPTRateLimitHint && /* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsx(Text, { color: chatGPTRateLimitColor, children: chatGPTRateLimitHint }) }),
|
|
127
|
+
/* @__PURE__ */ jsx(Box, { children: /* @__PURE__ */ jsxs(Text, { color: "gray", children: [
|
|
128
|
+
"approvals: ",
|
|
129
|
+
agent.getEffectiveConfig(sessionId ?? void 0).permissions.mode
|
|
130
|
+
] }) }),
|
|
127
131
|
isShellMode && /* @__PURE__ */ jsxs(Box, { children: [
|
|
128
132
|
/* @__PURE__ */ jsx(Text, { color: "yellow", bold: true, children: "!" }),
|
|
129
133
|
/* @__PURE__ */ jsx(Text, { color: "gray", children: " for shell mode" })
|
|
@@ -137,7 +141,7 @@ function Footer({
|
|
|
137
141
|
/* @__PURE__ */ jsx(Text, { color: "gray", children: " (shift + tab to cycle)" })
|
|
138
142
|
] }),
|
|
139
143
|
bypassPermissions && !planModeActive && !autoApproveEdits && !isShellMode && /* @__PURE__ */ jsxs(Box, { children: [
|
|
140
|
-
/* @__PURE__ */ jsx(Text, { color: "
|
|
144
|
+
/* @__PURE__ */ jsx(Text, { color: "gray", children: "auto-approve (session)" }),
|
|
141
145
|
/* @__PURE__ */ jsx(Text, { color: "gray", children: " (shift + tab to cycle)" })
|
|
142
146
|
] })
|
|
143
147
|
] });
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_react = require("react");
|
|
3
|
+
var import_node_stream = require("node:stream");
|
|
4
|
+
var import_ink = require("ink");
|
|
5
|
+
var import_vitest = require("vitest");
|
|
6
|
+
var import_Footer = require("./Footer.js");
|
|
7
|
+
(0, import_vitest.describe)("configured approval policy in the TUI footer", () => {
|
|
8
|
+
import_vitest.it.each(["manual", "auto-approve"])(
|
|
9
|
+
"shows %s independently of session shortcuts",
|
|
10
|
+
async (mode) => {
|
|
11
|
+
const stdout = Object.assign(new import_node_stream.PassThrough(), {
|
|
12
|
+
columns: 120,
|
|
13
|
+
rows: 40,
|
|
14
|
+
isTTY: false
|
|
15
|
+
});
|
|
16
|
+
let output = "";
|
|
17
|
+
stdout.on("data", (chunk) => {
|
|
18
|
+
output += String(chunk);
|
|
19
|
+
});
|
|
20
|
+
const agent = {
|
|
21
|
+
capabilities: { contextStats: false },
|
|
22
|
+
getEffectiveConfig: () => ({ permissions: { mode } })
|
|
23
|
+
};
|
|
24
|
+
const view = (0, import_ink.render)(
|
|
25
|
+
(0, import_react.createElement)(import_Footer.Footer, {
|
|
26
|
+
agent,
|
|
27
|
+
sessionId: null,
|
|
28
|
+
modelName: "test-model",
|
|
29
|
+
autoApproveEdits: true
|
|
30
|
+
}),
|
|
31
|
+
{
|
|
32
|
+
stdout,
|
|
33
|
+
debug: true,
|
|
34
|
+
patchConsole: false,
|
|
35
|
+
exitOnCtrlC: false
|
|
36
|
+
}
|
|
37
|
+
);
|
|
38
|
+
try {
|
|
39
|
+
await import_vitest.vi.waitFor(() => (0, import_vitest.expect)(output).toContain(`approvals: ${mode}`));
|
|
40
|
+
(0, import_vitest.expect)(output).toContain("accept edits");
|
|
41
|
+
} finally {
|
|
42
|
+
view.unmount();
|
|
43
|
+
stdout.destroy();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Footer.test.d.ts","sourceRoot":"","sources":["../../src/components/Footer.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { createElement } from "react";
|
|
2
|
+
import { PassThrough } from "node:stream";
|
|
3
|
+
import { render } from "ink";
|
|
4
|
+
import { describe, expect, it, vi } from "vitest";
|
|
5
|
+
import { Footer } from "./Footer.js";
|
|
6
|
+
describe("configured approval policy in the TUI footer", () => {
|
|
7
|
+
it.each(["manual", "auto-approve"])(
|
|
8
|
+
"shows %s independently of session shortcuts",
|
|
9
|
+
async (mode) => {
|
|
10
|
+
const stdout = Object.assign(new PassThrough(), {
|
|
11
|
+
columns: 120,
|
|
12
|
+
rows: 40,
|
|
13
|
+
isTTY: false
|
|
14
|
+
});
|
|
15
|
+
let output = "";
|
|
16
|
+
stdout.on("data", (chunk) => {
|
|
17
|
+
output += String(chunk);
|
|
18
|
+
});
|
|
19
|
+
const agent = {
|
|
20
|
+
capabilities: { contextStats: false },
|
|
21
|
+
getEffectiveConfig: () => ({ permissions: { mode } })
|
|
22
|
+
};
|
|
23
|
+
const view = render(
|
|
24
|
+
createElement(Footer, {
|
|
25
|
+
agent,
|
|
26
|
+
sessionId: null,
|
|
27
|
+
modelName: "test-model",
|
|
28
|
+
autoApproveEdits: true
|
|
29
|
+
}),
|
|
30
|
+
{
|
|
31
|
+
stdout,
|
|
32
|
+
debug: true,
|
|
33
|
+
patchConsole: false,
|
|
34
|
+
exitOnCtrlC: false
|
|
35
|
+
}
|
|
36
|
+
);
|
|
37
|
+
try {
|
|
38
|
+
await vi.waitFor(() => expect(output).toContain(`approvals: ${mode}`));
|
|
39
|
+
expect(output).toContain("accept edits");
|
|
40
|
+
} finally {
|
|
41
|
+
view.unmount();
|
|
42
|
+
stdout.destroy();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
);
|
|
46
|
+
});
|
|
@@ -84,7 +84,8 @@ function AlternateBufferCLI({
|
|
|
84
84
|
inputService,
|
|
85
85
|
buffer,
|
|
86
86
|
overlayContainerRef,
|
|
87
|
-
visibleMessages
|
|
87
|
+
visibleMessages,
|
|
88
|
+
isHydratingHistory
|
|
88
89
|
} = (0, import_useCLIState.useCLIState)({
|
|
89
90
|
agent,
|
|
90
91
|
initialSessionId,
|
|
@@ -303,6 +304,7 @@ function AlternateBufferCLI({
|
|
|
303
304
|
ui,
|
|
304
305
|
session,
|
|
305
306
|
initialPrompt,
|
|
307
|
+
isHydratingHistory,
|
|
306
308
|
approval,
|
|
307
309
|
steerMessages,
|
|
308
310
|
queuedMessages,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AlternateBufferCLI.d.ts","sourceRoot":"","sources":["../../../src/components/modes/AlternateBufferCLI.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,KAAK,EAAW,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA+BjE,UAAU,uBAAuB;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,EAC/B,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,cAAc,EACd,wBAAgC,EAChC,kBAAkB,EAClB,YAAmB,GACtB,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"AlternateBufferCLI.d.ts","sourceRoot":"","sources":["../../../src/components/modes/AlternateBufferCLI.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,OAAO,KAAK,EAAW,WAAW,EAAE,MAAM,sBAAsB,CAAC;AA+BjE,UAAU,uBAAuB;IAC7B,KAAK,EAAE,eAAe,CAAC;IACvB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,WAAW,EAAE,WAAW,CAAC;IACzB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,wBAAwB,CAAC,EAAE,OAAO,CAAC;IACnC,2EAA2E;IAC3E,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAC;IAChC,6DAA6D;IAC7D,YAAY,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,kBAAkB,CAAC,EAC/B,KAAK,EACL,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,cAAc,EACd,wBAAgC,EAChC,kBAAkB,EAClB,YAAmB,GACtB,EAAE,uBAAuB,2CAiYzB"}
|