@ridit/lens 0.4.6 → 0.4.7
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/index.mjs +40 -14
- package/package.json +1 -1
- package/src/index.tsx +57 -16
package/dist/index.mjs
CHANGED
|
@@ -78205,16 +78205,42 @@ function getLastDeniedAction(messages) {
|
|
|
78205
78205
|
async function runHeadless(opts) {
|
|
78206
78206
|
const repoPath = opts.path;
|
|
78207
78207
|
let session = opts.sessionId ? loadSession(opts.sessionId) ?? createSessionWithId(opts.sessionId, repoPath) : opts.single ? getLatestSession(repoPath) ?? createSession(repoPath) : createSession(repoPath);
|
|
78208
|
-
|
|
78209
|
-
|
|
78210
|
-
|
|
78211
|
-
|
|
78212
|
-
|
|
78208
|
+
if (opts.resume) {
|
|
78209
|
+
const msgs = getMessages(session);
|
|
78210
|
+
let trimAt = -1;
|
|
78211
|
+
for (let i = msgs.length - 1;i >= 0; i--) {
|
|
78212
|
+
const msg = msgs[i];
|
|
78213
|
+
if (!msg || msg.role !== "tool")
|
|
78214
|
+
continue;
|
|
78215
|
+
const content = Array.isArray(msg.content) ? msg.content : [];
|
|
78216
|
+
const isDenied = content.some((p) => typeof p === "object" && p !== null && ("type" in p) && p.type === "tool-result" && ("result" in p) && typeof p.result === "string" && p.result.includes("Permission denied"));
|
|
78217
|
+
if (isDenied) {
|
|
78218
|
+
for (let j = i - 1;j >= 0; j--) {
|
|
78219
|
+
if (msgs[j]?.role === "assistant") {
|
|
78220
|
+
trimAt = j;
|
|
78221
|
+
break;
|
|
78222
|
+
}
|
|
78223
|
+
}
|
|
78224
|
+
break;
|
|
78225
|
+
}
|
|
78226
|
+
}
|
|
78227
|
+
if (trimAt >= 0) {
|
|
78228
|
+
session = { ...session, messages: msgs.slice(0, trimAt) };
|
|
78229
|
+
}
|
|
78230
|
+
if (!opts.single || opts.sessionId)
|
|
78231
|
+
saveSession(session);
|
|
78232
|
+
} else {
|
|
78233
|
+
let prompt = opts.prompt;
|
|
78234
|
+
if (opts.forceAll && APPROVAL_WORDS.has(prompt.trim().toLowerCase())) {
|
|
78235
|
+
const pending = getLastDeniedAction(getMessages(session));
|
|
78236
|
+
if (pending) {
|
|
78237
|
+
prompt = `Proceed with the previously denied operation: use the ${pending.tool} tool on "${pending.description}".`;
|
|
78238
|
+
}
|
|
78213
78239
|
}
|
|
78240
|
+
session = addMessage(session, "user", prompt);
|
|
78241
|
+
if (!opts.single || opts.sessionId)
|
|
78242
|
+
saveSession(session);
|
|
78214
78243
|
}
|
|
78215
|
-
session = addMessage(session, "user", prompt);
|
|
78216
|
-
if (!opts.single || opts.sessionId)
|
|
78217
|
-
saveSession(session);
|
|
78218
78244
|
const toolLog = [];
|
|
78219
78245
|
const denied = [];
|
|
78220
78246
|
const runtimeToolNames = new Set;
|
|
@@ -78264,10 +78290,10 @@ async function runHeadless(opts) {
|
|
|
78264
78290
|
});
|
|
78265
78291
|
}
|
|
78266
78292
|
var program = new Command().enablePositionalOptions();
|
|
78267
|
-
program.command("chat").description("Chat with your codebase — ask questions or make changes").option("-p, --path <path>", "Path to the repo", ".").option("-d, --dev", "Output structured JSON (no UI)").option("--single", "Single-shot: run one message then exit").option("--session <id>", "Resume session by ID, or create one with that ID").option("--id <id>", "Alias for --session").option("--force-all", "Auto-approve all tools").option("--prompt <text>", "Run a prompt non-interactively").option("--runtime-tools <path>", "path to runtime tools JSON file").action((opts) => {
|
|
78293
|
+
program.command("chat").description("Chat with your codebase — ask questions or make changes").option("-p, --path <path>", "Path to the repo", ".").option("-d, --dev", "Output structured JSON (no UI)").option("--single", "Single-shot: run one message then exit").option("--session <id>", "Resume session by ID, or create one with that ID").option("--id <id>", "Alias for --session").option("--force-all", "Auto-approve all tools").option("--prompt <text>", "Run a prompt non-interactively").option("--resume", "Resume from last permission-denied tool call (no new prompt needed)").option("--runtime-tools <path>", "path to runtime tools JSON file").action((opts) => {
|
|
78268
78294
|
const sessionId = opts.session ?? opts.id;
|
|
78269
|
-
if (opts.prompt && (opts.dev || opts.single)) {
|
|
78270
|
-
runHeadless({ path: opts.path, prompt: opts.prompt, sessionId, single: opts.single, forceAll: opts.forceAll, runtimeTools: opts.runtimeTools });
|
|
78295
|
+
if ((opts.prompt || opts.resume) && (opts.dev || opts.single)) {
|
|
78296
|
+
runHeadless({ path: opts.path, prompt: opts.prompt, sessionId, single: opts.single, forceAll: opts.forceAll ?? opts.resume, runtimeTools: opts.runtimeTools, resume: opts.resume });
|
|
78271
78297
|
return;
|
|
78272
78298
|
}
|
|
78273
78299
|
render(/* @__PURE__ */ jsxDEV21(ChatCommand, {
|
|
@@ -78365,13 +78391,13 @@ program.command("run <cmd>").description("Run your dev server. Lens watches and
|
|
|
78365
78391
|
});
|
|
78366
78392
|
var firstArg = process.argv[2];
|
|
78367
78393
|
if (!firstArg || firstArg.startsWith("-")) {
|
|
78368
|
-
const defaultFlags = new Command().option("-p, --path <path>", "Path to the repo", ".").option("--session <id>", "Resume session by ID").option("--single", "Single-shot mode").option("--prompt <text>", "Run a prompt").option("-d, --dev", "Output JSON (no UI)").option("--force-all", "Auto-approve all tools").allowUnknownOption().exitOverride();
|
|
78394
|
+
const defaultFlags = new Command().option("-p, --path <path>", "Path to the repo", ".").option("--session <id>", "Resume session by ID").option("--single", "Single-shot mode").option("--prompt <text>", "Run a prompt").option("-d, --dev", "Output JSON (no UI)").option("--force-all", "Auto-approve all tools").option("--resume", "Resume from last permission-denied tool call").allowUnknownOption().exitOverride();
|
|
78369
78395
|
try {
|
|
78370
78396
|
defaultFlags.parse(process.argv);
|
|
78371
78397
|
} catch {}
|
|
78372
78398
|
const opts = defaultFlags.opts();
|
|
78373
|
-
if (opts.prompt && (opts.dev || opts.single)) {
|
|
78374
|
-
runHeadless({ path: opts.path ?? ".", prompt: opts.prompt, sessionId: opts.session, single: opts.single, forceAll: opts.forceAll });
|
|
78399
|
+
if ((opts.prompt || opts.resume) && (opts.dev || opts.single)) {
|
|
78400
|
+
runHeadless({ path: opts.path ?? ".", prompt: opts.prompt, sessionId: opts.session, single: opts.single, forceAll: opts.forceAll ?? opts.resume, resume: opts.resume });
|
|
78375
78401
|
} else {
|
|
78376
78402
|
render(/* @__PURE__ */ jsxDEV21(ChatCommand, {
|
|
78377
78403
|
path: opts.path ?? ".",
|
package/package.json
CHANGED
package/src/index.tsx
CHANGED
|
@@ -72,11 +72,12 @@ function getLastDeniedAction(messages: ReturnType<typeof getMessages>): { tool:
|
|
|
72
72
|
|
|
73
73
|
async function runHeadless(opts: {
|
|
74
74
|
path: string;
|
|
75
|
-
prompt
|
|
75
|
+
prompt?: string;
|
|
76
76
|
sessionId?: string;
|
|
77
77
|
single?: boolean;
|
|
78
78
|
forceAll?: boolean;
|
|
79
79
|
runtimeTools?: string;
|
|
80
|
+
resume?: boolean;
|
|
80
81
|
}) {
|
|
81
82
|
const repoPath = opts.path;
|
|
82
83
|
|
|
@@ -86,18 +87,54 @@ async function runHeadless(opts: {
|
|
|
86
87
|
? (getLatestSession(repoPath) ?? createSession(repoPath))
|
|
87
88
|
: createSession(repoPath);
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
90
|
+
if (opts.resume) {
|
|
91
|
+
// Rewind the session: strip the last denied tool-call (assistant message),
|
|
92
|
+
// its "Permission denied" tool result, and the assistant's text response after it.
|
|
93
|
+
// This leaves the session ending at the last successful state so the agent
|
|
94
|
+
// can re-attempt the denied tool with forceAll: true.
|
|
95
|
+
const msgs = getMessages(session);
|
|
96
|
+
let trimAt = -1;
|
|
97
|
+
for (let i = msgs.length - 1; i >= 0; i--) {
|
|
98
|
+
const msg = msgs[i];
|
|
99
|
+
if (!msg || msg.role !== "tool") continue;
|
|
100
|
+
const content = Array.isArray(msg.content) ? msg.content : [];
|
|
101
|
+
const isDenied = content.some(
|
|
102
|
+
(p: unknown) =>
|
|
103
|
+
typeof p === "object" && p !== null &&
|
|
104
|
+
"type" in p && (p as { type: string }).type === "tool-result" &&
|
|
105
|
+
"result" in p && typeof (p as { result: unknown }).result === "string" &&
|
|
106
|
+
((p as { result: string }).result).includes("Permission denied"),
|
|
107
|
+
);
|
|
108
|
+
if (isDenied) {
|
|
109
|
+
// Find the assistant message immediately before this tool result (the tool-call message)
|
|
110
|
+
for (let j = i - 1; j >= 0; j--) {
|
|
111
|
+
if (msgs[j]?.role === "assistant") {
|
|
112
|
+
trimAt = j;
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
break;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
if (trimAt >= 0) {
|
|
120
|
+
session = { ...session, messages: msgs.slice(0, trimAt) };
|
|
121
|
+
}
|
|
122
|
+
// Save trimmed session so context is clean for this run
|
|
123
|
+
if (!opts.single || opts.sessionId) saveSession(session);
|
|
124
|
+
} else {
|
|
125
|
+
// if user is approving a prior denial, make the intent unambiguous
|
|
126
|
+
let prompt = opts.prompt!;
|
|
127
|
+
if (opts.forceAll && APPROVAL_WORDS.has(prompt.trim().toLowerCase())) {
|
|
128
|
+
const pending = getLastDeniedAction(getMessages(session));
|
|
129
|
+
if (pending) {
|
|
130
|
+
prompt = `Proceed with the previously denied operation: use the ${pending.tool} tool on "${pending.description}".`;
|
|
131
|
+
}
|
|
95
132
|
}
|
|
96
|
-
}
|
|
97
133
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
134
|
+
session = addMessage(session, "user", prompt);
|
|
135
|
+
// save now so context is available on follow-up messages even if we exit early
|
|
136
|
+
if (!opts.single || opts.sessionId) saveSession(session);
|
|
137
|
+
}
|
|
101
138
|
|
|
102
139
|
const toolLog: { tool: string; args: unknown; result: unknown }[] = [];
|
|
103
140
|
const denied: { tool: string; description: string }[] = [];
|
|
@@ -170,6 +207,7 @@ program
|
|
|
170
207
|
.option("--id <id>", "Alias for --session")
|
|
171
208
|
.option("--force-all", "Auto-approve all tools")
|
|
172
209
|
.option("--prompt <text>", "Run a prompt non-interactively")
|
|
210
|
+
.option("--resume", "Resume from last permission-denied tool call (no new prompt needed)")
|
|
173
211
|
.option("--runtime-tools <path>", "path to runtime tools JSON file")
|
|
174
212
|
.action(
|
|
175
213
|
(opts: {
|
|
@@ -180,12 +218,13 @@ program
|
|
|
180
218
|
id?: string;
|
|
181
219
|
forceAll?: boolean;
|
|
182
220
|
prompt?: string;
|
|
221
|
+
resume?: boolean;
|
|
183
222
|
runtimeTools?: string;
|
|
184
223
|
}) => {
|
|
185
224
|
const sessionId = opts.session ?? opts.id;
|
|
186
|
-
// headless: dev+prompt
|
|
187
|
-
if (opts.prompt && (opts.dev || opts.single)) {
|
|
188
|
-
runHeadless({ path: opts.path, prompt: opts.prompt, sessionId, single: opts.single, forceAll: opts.forceAll, runtimeTools: opts.runtimeTools });
|
|
225
|
+
// headless: dev+prompt, single+prompt, or --resume → no UI, output JSON and exit
|
|
226
|
+
if ((opts.prompt || opts.resume) && (opts.dev || opts.single)) {
|
|
227
|
+
runHeadless({ path: opts.path, prompt: opts.prompt, sessionId, single: opts.single, forceAll: opts.forceAll ?? opts.resume, runtimeTools: opts.runtimeTools, resume: opts.resume });
|
|
189
228
|
return;
|
|
190
229
|
}
|
|
191
230
|
render(
|
|
@@ -367,6 +406,7 @@ if (!firstArg || firstArg.startsWith("-")) {
|
|
|
367
406
|
.option("--prompt <text>", "Run a prompt")
|
|
368
407
|
.option("-d, --dev", "Output JSON (no UI)")
|
|
369
408
|
.option("--force-all", "Auto-approve all tools")
|
|
409
|
+
.option("--resume", "Resume from last permission-denied tool call")
|
|
370
410
|
.allowUnknownOption()
|
|
371
411
|
.exitOverride();
|
|
372
412
|
|
|
@@ -379,10 +419,11 @@ if (!firstArg || firstArg.startsWith("-")) {
|
|
|
379
419
|
prompt?: string;
|
|
380
420
|
dev?: boolean;
|
|
381
421
|
forceAll?: boolean;
|
|
422
|
+
resume?: boolean;
|
|
382
423
|
}>();
|
|
383
424
|
|
|
384
|
-
if (opts.prompt && (opts.dev || opts.single)) {
|
|
385
|
-
runHeadless({ path: opts.path ?? ".", prompt: opts.prompt, sessionId: opts.session, single: opts.single, forceAll: opts.forceAll });
|
|
425
|
+
if ((opts.prompt || opts.resume) && (opts.dev || opts.single)) {
|
|
426
|
+
runHeadless({ path: opts.path ?? ".", prompt: opts.prompt, sessionId: opts.session, single: opts.single, forceAll: opts.forceAll ?? opts.resume, resume: opts.resume });
|
|
386
427
|
} else {
|
|
387
428
|
render(
|
|
388
429
|
<ChatCommand
|