@relace-ai/jacq 0.1.2-beta.4 → 0.1.2-beta.6
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/actions/messages.d.ts +16 -16
- package/dist/actions/messages.js +47 -29
- package/dist/actions/messages.js.map +1 -1
- package/dist/actions/tasks.d.ts +1 -2
- package/dist/actions/tasks.js +8 -8
- package/dist/actions/tasks.js.map +1 -1
- package/dist/approvalGate.d.ts +42 -0
- package/dist/approvalGate.js +140 -0
- package/dist/approvalGate.js.map +1 -0
- package/dist/approvals.d.ts +21 -0
- package/dist/approvals.js +79 -0
- package/dist/approvals.js.map +1 -0
- package/dist/auth.d.ts +1 -0
- package/dist/auth.js +3 -0
- package/dist/auth.js.map +1 -1
- package/dist/charWidth.d.ts +7 -0
- package/dist/charWidth.js +24 -19
- package/dist/charWidth.js.map +1 -1
- package/dist/clipboard.d.ts +0 -5
- package/dist/clipboard.js +0 -5
- package/dist/clipboard.js.map +1 -1
- package/dist/commands.js +3 -2
- package/dist/commands.js.map +1 -1
- package/dist/config.d.ts +2 -1
- package/dist/config.js +17 -10
- package/dist/config.js.map +1 -1
- package/dist/connection.d.ts +2 -0
- package/dist/connection.js +199 -6
- package/dist/connection.js.map +1 -1
- package/dist/index.js +196 -34
- package/dist/index.js.map +1 -1
- package/dist/markdown/parser.js +248 -60
- package/dist/markdown/parser.js.map +1 -1
- package/dist/markdown/renderer.d.ts +3 -3
- package/dist/markdown/renderer.js +254 -108
- package/dist/markdown/renderer.js.map +1 -1
- package/dist/markdown/types.d.ts +4 -1
- package/dist/markdown/types.js.map +1 -1
- package/dist/protocol.d.ts +0 -2
- package/dist/protocol.js +137 -98
- package/dist/protocol.js.map +1 -1
- package/dist/renderer.js +4 -0
- package/dist/renderer.js.map +1 -1
- package/dist/startupAnimation.d.ts +4 -0
- package/dist/startupAnimation.js +326 -0
- package/dist/startupAnimation.js.map +1 -0
- package/dist/state.js +23 -5
- package/dist/state.js.map +1 -1
- package/dist/styles.js +4 -1
- package/dist/styles.js.map +1 -1
- package/dist/terminal.d.ts +9 -0
- package/dist/terminal.js +15 -0
- package/dist/terminal.js.map +1 -1
- package/dist/tools/registry.js +138 -13
- package/dist/tools/registry.js.map +1 -1
- package/dist/types.d.ts +57 -21
- package/dist/types.js +3 -1
- package/dist/types.js.map +1 -1
- package/dist/ui/config.d.ts +6 -0
- package/dist/ui/config.js +53 -0
- package/dist/ui/config.js.map +1 -0
- package/dist/ui/diffViewer.d.ts +9 -0
- package/dist/ui/diffViewer.js +320 -0
- package/dist/ui/diffViewer.js.map +1 -0
- package/dist/ui/index.js +40 -21
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/input.d.ts +1 -1
- package/dist/ui/input.js +40 -15
- package/dist/ui/input.js.map +1 -1
- package/dist/ui/localCommands.d.ts +8 -0
- package/dist/ui/localCommands.js +267 -0
- package/dist/ui/localCommands.js.map +1 -0
- package/dist/ui/messages.js +195 -93
- package/dist/ui/messages.js.map +1 -1
- package/dist/ui/primitives.js +2 -1
- package/dist/ui/primitives.js.map +1 -1
- package/dist/ui/promptInput.js +42 -8
- package/dist/ui/promptInput.js.map +1 -1
- package/dist/ui/promptPicker.js +3 -4
- package/dist/ui/promptPicker.js.map +1 -1
- package/dist/ui/resumeTask.d.ts +6 -0
- package/dist/ui/resumeTask.js +136 -0
- package/dist/ui/resumeTask.js.map +1 -0
- package/dist/ui/sessions.js +2 -2
- package/dist/ui/sessions.js.map +1 -1
- package/dist/ui/welcome.js +22 -35
- package/dist/ui/welcome.js.map +1 -1
- package/dist/utils/resolvePath.d.ts +10 -0
- package/dist/utils/resolvePath.js +24 -0
- package/dist/utils/resolvePath.js.map +1 -0
- package/package.json +7 -4
- package/dist/ui/backgroundTasks.d.ts +0 -7
- package/dist/ui/backgroundTasks.js +0 -192
- package/dist/ui/backgroundTasks.js.map +0 -1
|
@@ -1,31 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Message actions
|
|
3
|
-
*
|
|
4
|
-
* Message types: 'user' | 'agent' | 'tool' | 'status' | 'error'
|
|
2
|
+
* Message actions — typed factory functions for each message variant.
|
|
5
3
|
*/
|
|
6
|
-
import type { Message } from '../types.js';
|
|
7
|
-
|
|
4
|
+
import type { Message, UserMessage, ToolMessage, StatusMessage, ErrorMessage, ToolCall, StatusKind } from '../types.js';
|
|
5
|
+
export declare function addUserMessage(content: string, taskId?: string): UserMessage;
|
|
6
|
+
export declare function addToolMessage(content: string, attrs: {
|
|
8
7
|
taskId?: string;
|
|
9
|
-
toolCalls
|
|
8
|
+
toolCalls: ToolCall[];
|
|
10
9
|
agentMessage?: string | null;
|
|
11
10
|
tokens?: {
|
|
12
11
|
input: number;
|
|
13
12
|
output: number;
|
|
14
13
|
} | null;
|
|
14
|
+
}): ToolMessage;
|
|
15
|
+
export declare function addStatusMessage(content: string, attrs: {
|
|
16
|
+
taskId?: string;
|
|
17
|
+
statusKind: StatusKind;
|
|
15
18
|
linkUrl?: string;
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
timestamp?: number;
|
|
20
|
+
}): StatusMessage;
|
|
21
|
+
export declare function addErrorMessage(content: string, attrs?: {
|
|
22
|
+
taskId?: string;
|
|
23
|
+
statusKind?: StatusKind;
|
|
24
|
+
timestamp?: number;
|
|
25
|
+
}): ErrorMessage;
|
|
21
26
|
/**
|
|
22
27
|
* Append to stream buffer (for streaming responses)
|
|
23
28
|
*/
|
|
24
29
|
export declare function appendStream(chunk: string): void;
|
|
25
|
-
/**
|
|
26
|
-
* Flush stream buffer to a message
|
|
27
|
-
*/
|
|
28
|
-
export declare function flushStream(taskId?: string): void;
|
|
29
30
|
/**
|
|
30
31
|
* Clear messages (when switching tasks)
|
|
31
32
|
*/
|
|
@@ -38,4 +39,3 @@ export declare function getVisibleMessages(): Message[];
|
|
|
38
39
|
* Check if the current task is running
|
|
39
40
|
*/
|
|
40
41
|
export declare function isCurrentTaskRunning(): boolean;
|
|
41
|
-
export {};
|
package/dist/actions/messages.js
CHANGED
|
@@ -1,28 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Message actions
|
|
3
|
-
*
|
|
4
|
-
* Message types: 'user' | 'agent' | 'tool' | 'status' | 'error'
|
|
2
|
+
* Message actions — typed factory functions for each message variant.
|
|
5
3
|
*/
|
|
6
4
|
import { state, markDirty } from '../state.js';
|
|
7
5
|
let messageIdCounter = 0;
|
|
8
|
-
const MAX_MESSAGES =
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
export function addMessage(type, content, options = {}) {
|
|
13
|
-
const message = {
|
|
14
|
-
id: `msg-${++messageIdCounter}`,
|
|
15
|
-
type,
|
|
16
|
-
content,
|
|
17
|
-
taskId: options.taskId || state.currentTaskId || undefined,
|
|
18
|
-
toolCalls: options.toolCalls || null,
|
|
19
|
-
agentMessage: options.agentMessage || null,
|
|
20
|
-
tokens: options.tokens || null,
|
|
21
|
-
linkUrl: options.linkUrl,
|
|
22
|
-
timestamp: Date.now(),
|
|
23
|
-
};
|
|
6
|
+
const MAX_MESSAGES = 10000;
|
|
7
|
+
function nextId() { return `msg-${++messageIdCounter}`; }
|
|
8
|
+
function resolveTaskId(taskId) { return taskId || state.currentTaskId || undefined; }
|
|
9
|
+
function pushMessage(message) {
|
|
24
10
|
state.messages.push(message);
|
|
25
|
-
// Trim old messages
|
|
26
11
|
if (state.messages.length > MAX_MESSAGES) {
|
|
27
12
|
const trimCount = state.messages.length - MAX_MESSAGES;
|
|
28
13
|
state.messages = state.messages.slice(trimCount);
|
|
@@ -30,6 +15,48 @@ export function addMessage(type, content, options = {}) {
|
|
|
30
15
|
markDirty();
|
|
31
16
|
return message;
|
|
32
17
|
}
|
|
18
|
+
export function addUserMessage(content, taskId) {
|
|
19
|
+
return pushMessage({
|
|
20
|
+
id: nextId(),
|
|
21
|
+
type: 'user',
|
|
22
|
+
content,
|
|
23
|
+
taskId: resolveTaskId(taskId),
|
|
24
|
+
timestamp: Date.now(),
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export function addToolMessage(content, attrs) {
|
|
28
|
+
return pushMessage({
|
|
29
|
+
id: nextId(),
|
|
30
|
+
type: 'tool',
|
|
31
|
+
content,
|
|
32
|
+
taskId: resolveTaskId(attrs.taskId),
|
|
33
|
+
toolCalls: attrs.toolCalls,
|
|
34
|
+
agentMessage: attrs.agentMessage ?? null,
|
|
35
|
+
tokens: attrs.tokens ?? null,
|
|
36
|
+
timestamp: Date.now(),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
export function addStatusMessage(content, attrs) {
|
|
40
|
+
return pushMessage({
|
|
41
|
+
id: nextId(),
|
|
42
|
+
type: 'status',
|
|
43
|
+
content,
|
|
44
|
+
taskId: resolveTaskId(attrs.taskId),
|
|
45
|
+
statusKind: attrs.statusKind,
|
|
46
|
+
linkUrl: attrs.linkUrl,
|
|
47
|
+
timestamp: attrs.timestamp || Date.now(),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export function addErrorMessage(content, attrs) {
|
|
51
|
+
return pushMessage({
|
|
52
|
+
id: nextId(),
|
|
53
|
+
type: 'error',
|
|
54
|
+
content,
|
|
55
|
+
taskId: resolveTaskId(attrs?.taskId),
|
|
56
|
+
statusKind: attrs?.statusKind,
|
|
57
|
+
timestamp: attrs?.timestamp || Date.now(),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
33
60
|
/**
|
|
34
61
|
* Append to stream buffer (for streaming responses)
|
|
35
62
|
*/
|
|
@@ -37,15 +64,6 @@ export function appendStream(chunk) {
|
|
|
37
64
|
state.streamBuffer += chunk;
|
|
38
65
|
markDirty();
|
|
39
66
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Flush stream buffer to a message
|
|
42
|
-
*/
|
|
43
|
-
export function flushStream(taskId) {
|
|
44
|
-
if (state.streamBuffer.trim()) {
|
|
45
|
-
addMessage('agent', state.streamBuffer, { taskId });
|
|
46
|
-
}
|
|
47
|
-
state.streamBuffer = '';
|
|
48
|
-
}
|
|
49
67
|
/**
|
|
50
68
|
* Clear messages (when switching tasks)
|
|
51
69
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/actions/messages.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"messages.js","sourceRoot":"","sources":["../../src/actions/messages.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG/C,IAAI,gBAAgB,GAAG,CAAC,CAAC;AACzB,MAAM,YAAY,GAAG,KAAK,CAAC;AAE3B,SAAS,MAAM,KAAa,OAAO,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAC,CAAC;AACjE,SAAS,aAAa,CAAC,MAAe,IAAwB,OAAO,MAAM,IAAI,KAAK,CAAC,aAAa,IAAI,SAAS,CAAC,CAAC,CAAC;AAElH,SAAS,WAAW,CAAoB,OAAU;IAC9C,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC7B,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;QACvC,MAAM,SAAS,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,YAAY,CAAC;QACvD,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACrD,CAAC;IACD,SAAS,EAAE,CAAC;IACZ,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,MAAe;IAC3D,OAAO,WAAW,CAAC;QACf,EAAE,EAAE,MAAM,EAAE;QACZ,IAAI,EAAE,MAAM;QACZ,OAAO;QACP,MAAM,EAAE,aAAa,CAAC,MAAM,CAAC;QAC7B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,KAK/C;IACG,OAAO,WAAW,CAAC;QACf,EAAE,EAAE,MAAM,EAAE;QACZ,IAAI,EAAE,MAAM;QACZ,OAAO;QACP,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC;QACnC,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,YAAY,EAAE,KAAK,CAAC,YAAY,IAAI,IAAI;QACxC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;QAC5B,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;KACxB,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,OAAe,EAAE,KAKjD;IACG,OAAO,WAAW,CAAC;QACf,EAAE,EAAE,MAAM,EAAE;QACZ,IAAI,EAAE,QAAQ;QACd,OAAO;QACP,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,MAAM,CAAC;QACnC,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;KAC3C,CAAC,CAAC;AACP,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,KAIhD;IACG,OAAO,WAAW,CAAC;QACf,EAAE,EAAE,MAAM,EAAE;QACZ,IAAI,EAAE,OAAO;QACb,OAAO;QACP,MAAM,EAAE,aAAa,CAAC,KAAK,EAAE,MAAM,CAAC;QACpC,UAAU,EAAE,KAAK,EAAE,UAAU;QAC7B,SAAS,EAAE,KAAK,EAAE,SAAS,IAAI,IAAI,CAAC,GAAG,EAAE;KAC5C,CAAC,CAAC;AACP,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACtC,KAAK,CAAC,YAAY,IAAI,KAAK,CAAC;IAC5B,SAAS,EAAE,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa;IACzB,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC;IACpB,KAAK,CAAC,YAAY,GAAG,EAAE,CAAC;IACxB,SAAS,EAAE,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAC9B,IAAI,CAAC,KAAK,CAAC,aAAa,EAAE,CAAC;QACvB,OAAO,KAAK,CAAC,QAAQ,CAAC;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAC7B,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,aAAa,CAChD,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB;IAChC,IAAI,KAAK,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAClC,IAAI,CAAC,KAAK,CAAC,aAAa;QAAE,OAAO,KAAK,CAAC;IACvC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,CAAC,aAAa,CAAC,CAAC;IACjE,OAAO,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;AAC9E,CAAC"}
|
package/dist/actions/tasks.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Task & connection state actions
|
|
3
3
|
*/
|
|
4
|
-
import type { Task
|
|
4
|
+
import type { Task } from '../types.js';
|
|
5
5
|
export declare function setConnected(clientId: string): void;
|
|
6
6
|
export declare function setDisconnected(): void;
|
|
7
7
|
export declare function setServerStatus(status: unknown): void;
|
|
@@ -10,4 +10,3 @@ export declare function setTasks(tasks: Task[]): void;
|
|
|
10
10
|
export declare function updateTask(taskId: string | undefined, updates: Record<string, unknown>): void;
|
|
11
11
|
export declare function setCurrentTask(taskId: string | null): void;
|
|
12
12
|
export declare function setSubmitting(val: boolean): void;
|
|
13
|
-
export declare function setWidgets(widgets: Widget[]): void;
|
package/dist/actions/tasks.js
CHANGED
|
@@ -5,12 +5,14 @@ import { state, markDirty } from '../state.js';
|
|
|
5
5
|
// --- Connection state ---
|
|
6
6
|
export function setConnected(clientId) {
|
|
7
7
|
state.connected = true;
|
|
8
|
+
state.wasConnected = true;
|
|
8
9
|
state.clientId = clientId;
|
|
9
10
|
state.statusMessage = null;
|
|
10
11
|
markDirty();
|
|
11
12
|
}
|
|
12
13
|
export function setDisconnected() {
|
|
13
14
|
state.connected = false;
|
|
15
|
+
state.statusMessage = null;
|
|
14
16
|
markDirty();
|
|
15
17
|
}
|
|
16
18
|
export function setServerStatus(status) {
|
|
@@ -42,10 +44,14 @@ export function updateTask(taskId, updates) {
|
|
|
42
44
|
cacheCreate: prev.cacheCreate + (delta.cacheCreate || 0),
|
|
43
45
|
};
|
|
44
46
|
const { tokensDelta: _, ...rest } = updates;
|
|
45
|
-
Object.assign(task, rest
|
|
47
|
+
Object.assign(task, rest);
|
|
48
|
+
if (!rest.updatedAt)
|
|
49
|
+
task.updatedAt = new Date().toISOString();
|
|
46
50
|
}
|
|
47
51
|
else {
|
|
48
|
-
Object.assign(task, updates
|
|
52
|
+
Object.assign(task, updates);
|
|
53
|
+
if (!updates.updatedAt)
|
|
54
|
+
task.updatedAt = new Date().toISOString();
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
}
|
|
@@ -57,10 +63,4 @@ export function setSubmitting(val) {
|
|
|
57
63
|
state.submitting = val;
|
|
58
64
|
markDirty();
|
|
59
65
|
}
|
|
60
|
-
// --- Widgets ---
|
|
61
|
-
export function setWidgets(widgets) {
|
|
62
|
-
state.widgets = widgets;
|
|
63
|
-
state.widgetsLoaded = true;
|
|
64
|
-
markDirty();
|
|
65
|
-
}
|
|
66
66
|
//# sourceMappingURL=tasks.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/actions/tasks.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAG/C,2BAA2B;AAE3B,MAAM,UAAU,YAAY,CAAC,QAAgB;IACzC,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;IACvB,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC1B,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe;IAC3B,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC;IACxB,SAAS,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,MAAe;IAC3C,KAAK,CAAC,YAAY,GAAG,MAAM,CAAC;IAC5B,SAAS,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,GAAW;IACpC,KAAK,CAAC,SAAS,GAAG,GAAG,CAAC;AAC1B,CAAC;AAED,oBAAoB;AAEpB,MAAM,UAAU,QAAQ,CAAC,KAAa;IAClC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC;IACpB,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,MAA0B,EAAE,OAAgC;IACnF,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IACpD,IAAI,IAAI,EAAE,CAAC;QACP,uCAAuC;QACvC,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,KAAK,GAAG,OAAO,CAAC,WAA4F,CAAC;YACnH,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC;YAClF,IAAI,CAAC,MAAM,GAAG;gBACV,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,CAAC;gBACtC,MAAM,EAAE,IAAI,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;gBACzC,SAAS,EAAE,IAAI,CAAC,SAAS,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,CAAC,CAAC;gBAClD,WAAW,EAAE,IAAI,CAAC,WAAW,GAAG,CAAC,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;aAC3D,CAAC;YACF,MAAM,EAAE,WAAW,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;YAC5C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,
|
|
1
|
+
{"version":3,"file":"tasks.js","sourceRoot":"","sources":["../../src/actions/tasks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval gate — promise-based gate for tool execution approval
|
|
3
|
+
*
|
|
4
|
+
* When a bash or write_file tool needs user approval, creates a promise
|
|
5
|
+
* that blocks execution until the user acts on the overlay dialog.
|
|
6
|
+
* Only one approval can be pending at a time (server waits for tool.result).
|
|
7
|
+
*/
|
|
8
|
+
export type ApprovalDecision = {
|
|
9
|
+
action: 'approve';
|
|
10
|
+
} | {
|
|
11
|
+
action: 'allowlist';
|
|
12
|
+
prefix?: string;
|
|
13
|
+
dir?: string;
|
|
14
|
+
} | {
|
|
15
|
+
action: 'reject';
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Request approval for a bash command.
|
|
19
|
+
* Returns null if the command is already allowlisted (auto-approved).
|
|
20
|
+
* Otherwise returns a Promise that resolves when the user acts.
|
|
21
|
+
*/
|
|
22
|
+
export declare function requestBashApproval(command: string): Promise<ApprovalDecision> | null;
|
|
23
|
+
/**
|
|
24
|
+
* Request approval for a file edit (write_file).
|
|
25
|
+
* Returns null if the edit is already allowed (dir allowlist).
|
|
26
|
+
* Otherwise returns a Promise that resolves when the user acts.
|
|
27
|
+
*/
|
|
28
|
+
export declare function requestEditApproval(filePath: string, newContent: string, cwd: string, append?: boolean): Promise<ApprovalDecision> | null;
|
|
29
|
+
/**
|
|
30
|
+
* Request approval for an edit_file operation.
|
|
31
|
+
* Returns null if auto-approved. Otherwise shows diff viewer.
|
|
32
|
+
*/
|
|
33
|
+
export declare function requestEditFileApproval(filePath: string, oldString: string, newString: string, replaceAll: boolean, cwd: string): Promise<ApprovalDecision> | null;
|
|
34
|
+
/**
|
|
35
|
+
* Request approval for a file operation (copy_file, delete_file).
|
|
36
|
+
* Returns null if auto-approved. Otherwise shows localCommands overlay.
|
|
37
|
+
*/
|
|
38
|
+
export declare function requestFileOpApproval(title: string, description: string, targetPath: string, cwd: string): Promise<ApprovalDecision> | null;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the pending approval promise. Called from index.ts action handlers.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveApproval(decision: ApprovalDecision): void;
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval gate — promise-based gate for tool execution approval
|
|
3
|
+
*
|
|
4
|
+
* When a bash or write_file tool needs user approval, creates a promise
|
|
5
|
+
* that blocks execution until the user acts on the overlay dialog.
|
|
6
|
+
* Only one approval can be pending at a time (server waits for tool.result).
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { state, markDirty } from './state.js';
|
|
11
|
+
import { isBashAllowed, isEditAllowed, suggestBashPrefix } from './approvals.js';
|
|
12
|
+
import { resolvePath } from './utils/resolvePath.js';
|
|
13
|
+
let pendingResolve = null;
|
|
14
|
+
/**
|
|
15
|
+
* Request approval for a bash command.
|
|
16
|
+
* Returns null if the command is already allowlisted (auto-approved).
|
|
17
|
+
* Otherwise returns a Promise that resolves when the user acts.
|
|
18
|
+
*/
|
|
19
|
+
export function requestBashApproval(command) {
|
|
20
|
+
if (isBashAllowed(command))
|
|
21
|
+
return null;
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
pendingResolve = resolve;
|
|
24
|
+
state.localCommandsTitle = null; // Reset to show default "Bash command" title
|
|
25
|
+
state.localCommandsProposed = command;
|
|
26
|
+
state.localCommandsSuggestedPrefix = suggestBashPrefix(command);
|
|
27
|
+
state.localCommandsDir = process.cwd();
|
|
28
|
+
state.localCommandsIndex = 0;
|
|
29
|
+
state.localCommandsFullscreen = false;
|
|
30
|
+
state.localCommandsScrollOffset = 0;
|
|
31
|
+
state.overlay = 'localCommands';
|
|
32
|
+
markDirty();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Request approval for a file edit (write_file).
|
|
37
|
+
* Returns null if the edit is already allowed (dir allowlist).
|
|
38
|
+
* Otherwise returns a Promise that resolves when the user acts.
|
|
39
|
+
*/
|
|
40
|
+
export function requestEditApproval(filePath, newContent, cwd, append) {
|
|
41
|
+
const resolved = resolvePath(filePath, cwd);
|
|
42
|
+
if (isEditAllowed(resolved))
|
|
43
|
+
return null;
|
|
44
|
+
// Read existing file content for diff
|
|
45
|
+
let oldContent = '';
|
|
46
|
+
try {
|
|
47
|
+
oldContent = fs.readFileSync(resolved, 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
// File doesn't exist yet — old content is empty
|
|
51
|
+
}
|
|
52
|
+
// For append mode, new content is old + appended
|
|
53
|
+
const effectiveNewContent = append ? oldContent + newContent : newContent;
|
|
54
|
+
return new Promise((resolve) => {
|
|
55
|
+
pendingResolve = resolve;
|
|
56
|
+
state.diffViewerFileName = filePath;
|
|
57
|
+
state.diffViewerOldContent = oldContent;
|
|
58
|
+
state.diffViewerNewContent = effectiveNewContent;
|
|
59
|
+
state.diffViewerSuggestedDir = path.dirname(resolved);
|
|
60
|
+
state.diffViewerIndex = 0;
|
|
61
|
+
state.diffViewerFullscreen = false;
|
|
62
|
+
state.diffViewerScrollOffset = 0;
|
|
63
|
+
state.overlay = 'diffViewer';
|
|
64
|
+
markDirty();
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Request approval for an edit_file operation.
|
|
69
|
+
* Returns null if auto-approved. Otherwise shows diff viewer.
|
|
70
|
+
*/
|
|
71
|
+
export function requestEditFileApproval(filePath, oldString, newString, replaceAll, cwd) {
|
|
72
|
+
const resolved = resolvePath(filePath, cwd);
|
|
73
|
+
if (isEditAllowed(resolved))
|
|
74
|
+
return null;
|
|
75
|
+
// Read file and compute replacement result
|
|
76
|
+
let oldContent = '';
|
|
77
|
+
try {
|
|
78
|
+
oldContent = fs.readFileSync(resolved, 'utf-8');
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
// File doesn't exist — will error in execution
|
|
82
|
+
}
|
|
83
|
+
let newContent;
|
|
84
|
+
if (replaceAll) {
|
|
85
|
+
newContent = oldContent.split(oldString).join(newString);
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const pos = oldContent.indexOf(oldString);
|
|
89
|
+
if (pos === -1) {
|
|
90
|
+
newContent = oldContent; // No match — execution will handle the error
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
newContent = oldContent.slice(0, pos) + newString + oldContent.slice(pos + oldString.length);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return new Promise((resolve) => {
|
|
97
|
+
pendingResolve = resolve;
|
|
98
|
+
state.diffViewerFileName = filePath;
|
|
99
|
+
state.diffViewerOldContent = oldContent;
|
|
100
|
+
state.diffViewerNewContent = newContent;
|
|
101
|
+
state.diffViewerSuggestedDir = path.dirname(resolved);
|
|
102
|
+
state.diffViewerIndex = 0;
|
|
103
|
+
state.diffViewerFullscreen = false;
|
|
104
|
+
state.diffViewerScrollOffset = 0;
|
|
105
|
+
state.overlay = 'diffViewer';
|
|
106
|
+
markDirty();
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Request approval for a file operation (copy_file, delete_file).
|
|
111
|
+
* Returns null if auto-approved. Otherwise shows localCommands overlay.
|
|
112
|
+
*/
|
|
113
|
+
export function requestFileOpApproval(title, description, targetPath, cwd) {
|
|
114
|
+
const resolved = resolvePath(targetPath, cwd);
|
|
115
|
+
if (isEditAllowed(resolved))
|
|
116
|
+
return null;
|
|
117
|
+
return new Promise((resolve) => {
|
|
118
|
+
pendingResolve = resolve;
|
|
119
|
+
state.localCommandsTitle = title;
|
|
120
|
+
state.localCommandsProposed = description;
|
|
121
|
+
state.localCommandsSuggestedPrefix = null;
|
|
122
|
+
state.localCommandsDir = path.dirname(resolved);
|
|
123
|
+
state.localCommandsIndex = 0;
|
|
124
|
+
state.localCommandsFullscreen = false;
|
|
125
|
+
state.localCommandsScrollOffset = 0;
|
|
126
|
+
state.overlay = 'localCommands';
|
|
127
|
+
markDirty();
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Resolve the pending approval promise. Called from index.ts action handlers.
|
|
132
|
+
*/
|
|
133
|
+
export function resolveApproval(decision) {
|
|
134
|
+
if (pendingResolve) {
|
|
135
|
+
const resolve = pendingResolve;
|
|
136
|
+
pendingResolve = null;
|
|
137
|
+
resolve(decision);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
//# sourceMappingURL=approvalGate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvalGate.js","sourceRoot":"","sources":["../src/approvalGate.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAOrD,IAAI,cAAc,GAAkD,IAAI,CAAC;AAEzE;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAe;IAC/C,IAAI,aAAa,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAExC,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;QAC7C,cAAc,GAAG,OAAO,CAAC;QAEzB,KAAK,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC,6CAA6C;QAC9E,KAAK,CAAC,qBAAqB,GAAG,OAAO,CAAC;QACtC,KAAK,CAAC,4BAA4B,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAChE,KAAK,CAAC,gBAAgB,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QACvC,KAAK,CAAC,kBAAkB,GAAG,CAAC,CAAC;QAC7B,KAAK,CAAC,uBAAuB,GAAG,KAAK,CAAC;QACtC,KAAK,CAAC,yBAAyB,GAAG,CAAC,CAAC;QACpC,KAAK,CAAC,OAAO,GAAG,eAAe,CAAC;QAChC,SAAS,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAC/B,QAAgB,EAChB,UAAkB,EAClB,GAAW,EACX,MAAgB;IAEhB,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAE5C,IAAI,aAAa,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,sCAAsC;IACtC,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,CAAC;QACD,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACL,gDAAgD;IACpD,CAAC;IAED,iDAAiD;IACjD,MAAM,mBAAmB,GAAG,MAAM,CAAC,CAAC,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;IAE1E,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;QAC7C,cAAc,GAAG,OAAO,CAAC;QAEzB,KAAK,CAAC,kBAAkB,GAAG,QAAQ,CAAC;QACpC,KAAK,CAAC,oBAAoB,GAAG,UAAU,CAAC;QACxC,KAAK,CAAC,oBAAoB,GAAG,mBAAmB,CAAC;QACjD,KAAK,CAAC,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtD,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC;QAC1B,KAAK,CAAC,oBAAoB,GAAG,KAAK,CAAC;QACnC,KAAK,CAAC,sBAAsB,GAAG,CAAC,CAAC;QACjC,KAAK,CAAC,OAAO,GAAG,YAAY,CAAC;QAC7B,SAAS,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,uBAAuB,CACnC,QAAgB,EAChB,SAAiB,EACjB,SAAiB,EACjB,UAAmB,EACnB,GAAW;IAEX,MAAM,QAAQ,GAAG,WAAW,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;IAE5C,IAAI,aAAa,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,2CAA2C;IAC3C,IAAI,UAAU,GAAG,EAAE,CAAC;IACpB,IAAI,CAAC;QACD,UAAU,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACpD,CAAC;IAAC,MAAM,CAAC;QACL,+CAA+C;IACnD,CAAC;IAED,IAAI,UAAkB,CAAC;IACvB,IAAI,UAAU,EAAE,CAAC;QACb,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAC7D,CAAC;SAAM,CAAC;QACJ,MAAM,GAAG,GAAG,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAC1C,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;YACb,UAAU,GAAG,UAAU,CAAC,CAAC,6CAA6C;QAC1E,CAAC;aAAM,CAAC;YACJ,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,SAAS,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;QACjG,CAAC;IACL,CAAC;IAED,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;QAC7C,cAAc,GAAG,OAAO,CAAC;QAEzB,KAAK,CAAC,kBAAkB,GAAG,QAAQ,CAAC;QACpC,KAAK,CAAC,oBAAoB,GAAG,UAAU,CAAC;QACxC,KAAK,CAAC,oBAAoB,GAAG,UAAU,CAAC;QACxC,KAAK,CAAC,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtD,KAAK,CAAC,eAAe,GAAG,CAAC,CAAC;QAC1B,KAAK,CAAC,oBAAoB,GAAG,KAAK,CAAC;QACnC,KAAK,CAAC,sBAAsB,GAAG,CAAC,CAAC;QACjC,KAAK,CAAC,OAAO,GAAG,YAAY,CAAC;QAC7B,SAAS,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACjC,KAAa,EACb,WAAmB,EACnB,UAAkB,EAClB,GAAW;IAEX,MAAM,QAAQ,GAAG,WAAW,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IAE9C,IAAI,aAAa,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAEzC,OAAO,IAAI,OAAO,CAAmB,CAAC,OAAO,EAAE,EAAE;QAC7C,cAAc,GAAG,OAAO,CAAC;QAEzB,KAAK,CAAC,kBAAkB,GAAG,KAAK,CAAC;QACjC,KAAK,CAAC,qBAAqB,GAAG,WAAW,CAAC;QAC1C,KAAK,CAAC,4BAA4B,GAAG,IAAI,CAAC;QAC1C,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAChD,KAAK,CAAC,kBAAkB,GAAG,CAAC,CAAC;QAC7B,KAAK,CAAC,uBAAuB,GAAG,KAAK,CAAC;QACtC,KAAK,CAAC,yBAAyB,GAAG,CAAC,CAAC;QACpC,KAAK,CAAC,OAAO,GAAG,eAAe,CAAC;QAChC,SAAS,EAAE,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,QAA0B;IACtD,IAAI,cAAc,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,cAAc,CAAC;QAC/B,cAAc,GAAG,IAAI,CAAC;QACtB,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtB,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval persistence — manages ~/.jacq/approvals.json
|
|
3
|
+
*
|
|
4
|
+
* Stores bash command prefix allowlist and edit directory allowlist.
|
|
5
|
+
* Uses atomic writes (write-to-tmp + rename) same as config.ts.
|
|
6
|
+
*/
|
|
7
|
+
interface ApprovalsData {
|
|
8
|
+
bash_allowlist: string[];
|
|
9
|
+
edit_allowed_dirs: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function loadApprovals(): ApprovalsData;
|
|
12
|
+
export declare function saveApprovals(data: ApprovalsData): void;
|
|
13
|
+
export declare function addBashPrefix(prefix: string): void;
|
|
14
|
+
export declare function addEditDir(dir: string): void;
|
|
15
|
+
export declare function isBashAllowed(command: string): boolean;
|
|
16
|
+
export declare function isEditAllowed(filePath: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Extract the first word of a command as a suggested allowlist prefix.
|
|
19
|
+
*/
|
|
20
|
+
export declare function suggestBashPrefix(command: string): string;
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Approval persistence — manages ~/.jacq/approvals.json
|
|
3
|
+
*
|
|
4
|
+
* Stores bash command prefix allowlist and edit directory allowlist.
|
|
5
|
+
* Uses atomic writes (write-to-tmp + rename) same as config.ts.
|
|
6
|
+
*/
|
|
7
|
+
import fs from 'fs';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import os from 'os';
|
|
10
|
+
const APPROVALS_DIR = path.join(os.homedir(), '.jacq');
|
|
11
|
+
const APPROVALS_FILE = path.join(APPROVALS_DIR, 'approvals.json');
|
|
12
|
+
const DEFAULT_DATA = {
|
|
13
|
+
bash_allowlist: [],
|
|
14
|
+
edit_allowed_dirs: [],
|
|
15
|
+
};
|
|
16
|
+
export function loadApprovals() {
|
|
17
|
+
try {
|
|
18
|
+
if (fs.existsSync(APPROVALS_FILE)) {
|
|
19
|
+
const content = fs.readFileSync(APPROVALS_FILE, 'utf-8');
|
|
20
|
+
const parsed = JSON.parse(content);
|
|
21
|
+
return {
|
|
22
|
+
bash_allowlist: Array.isArray(parsed.bash_allowlist) ? parsed.bash_allowlist : [],
|
|
23
|
+
edit_allowed_dirs: Array.isArray(parsed.edit_allowed_dirs) ? parsed.edit_allowed_dirs : [],
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// Ignore errors, use defaults
|
|
29
|
+
}
|
|
30
|
+
return { ...DEFAULT_DATA };
|
|
31
|
+
}
|
|
32
|
+
export function saveApprovals(data) {
|
|
33
|
+
if (!fs.existsSync(APPROVALS_DIR)) {
|
|
34
|
+
fs.mkdirSync(APPROVALS_DIR, { recursive: true });
|
|
35
|
+
}
|
|
36
|
+
const tmpFile = APPROVALS_FILE + '.tmp';
|
|
37
|
+
fs.writeFileSync(tmpFile, JSON.stringify(data, null, 2) + '\n', 'utf-8');
|
|
38
|
+
fs.renameSync(tmpFile, APPROVALS_FILE);
|
|
39
|
+
}
|
|
40
|
+
export function addBashPrefix(prefix) {
|
|
41
|
+
const data = loadApprovals();
|
|
42
|
+
if (!data.bash_allowlist.includes(prefix)) {
|
|
43
|
+
data.bash_allowlist.push(prefix);
|
|
44
|
+
saveApprovals(data);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export function addEditDir(dir) {
|
|
48
|
+
const normalized = dir.endsWith('/') ? dir : dir + '/';
|
|
49
|
+
const data = loadApprovals();
|
|
50
|
+
if (!data.edit_allowed_dirs.includes(normalized)) {
|
|
51
|
+
data.edit_allowed_dirs.push(normalized);
|
|
52
|
+
saveApprovals(data);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export function isBashAllowed(command) {
|
|
56
|
+
const data = loadApprovals();
|
|
57
|
+
// Check that prefix is followed by a space or end-of-string to prevent
|
|
58
|
+
// bypass via shell operators (e.g., "git status && malicious_cmd")
|
|
59
|
+
return data.bash_allowlist.some(prefix => {
|
|
60
|
+
if (!command.startsWith(prefix))
|
|
61
|
+
return false;
|
|
62
|
+
const nextChar = command[prefix.length];
|
|
63
|
+
return nextChar === undefined || nextChar === ' ';
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
export function isEditAllowed(filePath) {
|
|
67
|
+
const resolved = path.resolve(filePath);
|
|
68
|
+
const data = loadApprovals();
|
|
69
|
+
return data.edit_allowed_dirs.some(dir => resolved.startsWith(dir));
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Extract the first word of a command as a suggested allowlist prefix.
|
|
73
|
+
*/
|
|
74
|
+
export function suggestBashPrefix(command) {
|
|
75
|
+
const trimmed = command.trimStart();
|
|
76
|
+
const firstWord = trimmed.split(/\s+/)[0] || trimmed;
|
|
77
|
+
return firstWord;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=approvals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"approvals.js","sourceRoot":"","sources":["../src/approvals.ts"],"names":[],"mappings":"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"}
|
package/dist/auth.d.ts
CHANGED
package/dist/auth.js
CHANGED
|
@@ -104,6 +104,9 @@ export async function loginFromTUI(onProgress) {
|
|
|
104
104
|
if (pollRes.status === 410 || pollRes.data.status === 'expired') {
|
|
105
105
|
return { success: false, error: 'Device code expired. Try again.' };
|
|
106
106
|
}
|
|
107
|
+
if (pollRes.data.status === 'denied') {
|
|
108
|
+
return { success: false, error: 'Unauthorized', denied: true };
|
|
109
|
+
}
|
|
107
110
|
onProgress('Waiting for approval...');
|
|
108
111
|
}
|
|
109
112
|
catch {
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAErD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,KAAK,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/charWidth.d.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Character display width helpers for terminal rendering.
|
|
3
|
+
* Uses `string-width` which correctly handles East Asian Width,
|
|
4
|
+
* Emoji_Presentation, combining marks, ZWJ sequences, etc.
|
|
3
5
|
*/
|
|
6
|
+
/** Return the display width (in terminal columns) of a single code point. */
|
|
4
7
|
export declare function codePointWidth(cp: number): number;
|
|
8
|
+
/** Return the display width (in terminal columns) of a string. */
|
|
9
|
+
export declare function displayWidth(text: string): number;
|
|
10
|
+
/** Truncate or pad `text` to exactly `targetWidth` display columns. */
|
|
11
|
+
export declare function fitToDisplayWidth(text: string, targetWidth: number): string;
|
package/dist/charWidth.js
CHANGED
|
@@ -1,26 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Character display width helpers for terminal rendering.
|
|
3
|
+
* Uses `string-width` which correctly handles East Asian Width,
|
|
4
|
+
* Emoji_Presentation, combining marks, ZWJ sequences, etc.
|
|
3
5
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
(cp >= 0x20d0 && cp <= 0x20ff) ||
|
|
9
|
-
(cp >= 0xfe20 && cp <= 0xfe2f));
|
|
6
|
+
import stringWidth from 'string-width';
|
|
7
|
+
/** Return the display width (in terminal columns) of a single code point. */
|
|
8
|
+
export function codePointWidth(cp) {
|
|
9
|
+
return stringWidth(String.fromCodePoint(cp));
|
|
10
10
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
(cp >= 0xac00 && cp <= 0xd7a3) ||
|
|
15
|
-
(cp >= 0xf900 && cp <= 0xfaff) ||
|
|
16
|
-
(cp >= 0xfe10 && cp <= 0xfe6f) ||
|
|
17
|
-
(cp >= 0xff01 && cp <= 0xff60) ||
|
|
18
|
-
(cp >= 0xffe0 && cp <= 0xffe6) ||
|
|
19
|
-
(cp >= 0x1f300 && cp <= 0x1faff));
|
|
11
|
+
/** Return the display width (in terminal columns) of a string. */
|
|
12
|
+
export function displayWidth(text) {
|
|
13
|
+
return stringWidth(text);
|
|
20
14
|
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
15
|
+
/** Truncate or pad `text` to exactly `targetWidth` display columns. */
|
|
16
|
+
export function fitToDisplayWidth(text, targetWidth) {
|
|
17
|
+
let out = '';
|
|
18
|
+
let used = 0;
|
|
19
|
+
for (const ch of text) {
|
|
20
|
+
const w = codePointWidth(ch.codePointAt(0));
|
|
21
|
+
if (used + w > targetWidth)
|
|
22
|
+
break;
|
|
23
|
+
out += ch;
|
|
24
|
+
used += w;
|
|
25
|
+
}
|
|
26
|
+
if (used < targetWidth) {
|
|
27
|
+
out += ' '.repeat(targetWidth - used);
|
|
28
|
+
}
|
|
29
|
+
return out;
|
|
25
30
|
}
|
|
26
31
|
//# sourceMappingURL=charWidth.js.map
|