pendingyou 0.34.0 → 0.34.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/permission.js +46 -24
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.34.2 (2026-10-09)
|
|
4
|
+
|
|
5
|
+
- Fixed: in bypassPermissions or dontAsk mode, a Claude Code dialog for a tool its agent had used before (a subagent's
|
|
6
|
+
second Bash) could get no card. Claude Code writes a prompted call to its transcript only once its dialog is
|
|
7
|
+
answered, so 20 seconds in the check for an unanswered call found the agent's earlier call of the same tool,
|
|
8
|
+
answered, and settled the prompt. Now only the prompt's own call counts: not in the transcript yet, it's still
|
|
9
|
+
waiting and its card goes up; the same command answered before the prompt was asked is an earlier call and doesn't
|
|
10
|
+
count; a call Claude Code denied by itself is written with its refusal at once, so it still gets no card. A
|
|
11
|
+
Notification picks the prompt it shows the same way, so it names the second call rather than putting up a card in
|
|
12
|
+
Claude Code's words.
|
|
13
|
+
|
|
14
|
+
## 0.34.1 (2026-10-09)
|
|
15
|
+
|
|
16
|
+
- Fixed: a Claude Code permission prompt answered through the permission channel (`npx pendingyou claude`) could get
|
|
17
|
+
two cards, the relayed one with **Allow** and **Deny** and the old button-less “Claude Code is waiting for your OK”
|
|
18
|
+
one. It happened to any tool the session had used before (a second Write): Claude Code writes a prompted call to its
|
|
19
|
+
transcript only once it's answered, so the Notification hook, six seconds into the dialog, found the earlier call
|
|
20
|
+
answered, took the dialog for one nothing explained and put up a card for it. A relayed prompt now counts as on
|
|
21
|
+
screen, a Notification adds nothing while one is open, and a button-less card already up for a relayed dialog is
|
|
22
|
+
withdrawn as the relayed card goes up at once (“It has a card of its own now, with Allow and Deny.”).
|
|
23
|
+
|
|
3
24
|
## 0.34.0 (2026-10-09)
|
|
4
25
|
|
|
5
26
|
- Codex can ask on your phone first. `npx pendingyou codex-answers --wait <minutes>` (0 to 10; 0, the default, is off)
|
package/dist/permission.js
CHANGED
|
@@ -232,6 +232,18 @@ function keepNewest(state) {
|
|
|
232
232
|
closeCards(state, state.prompts.slice(0, -MAX_PROMPTS), 'answered');
|
|
233
233
|
state.prompts = state.prompts.slice(-MAX_PROMPTS);
|
|
234
234
|
}
|
|
235
|
+
function markMoving(state) {
|
|
236
|
+
const card = state.card;
|
|
237
|
+
if (!card)
|
|
238
|
+
return;
|
|
239
|
+
const shown = state.prompts.find((prompt) => prompt.key === card.key && !prompt.notice);
|
|
240
|
+
if (shown ? shown.relay : state.prompts.some((prompt) => prompt.relay))
|
|
241
|
+
card.moving = true;
|
|
242
|
+
}
|
|
243
|
+
function relayed(state) {
|
|
244
|
+
state.prompts = state.prompts.filter((prompt) => !prompt.notice);
|
|
245
|
+
markMoving(state);
|
|
246
|
+
}
|
|
235
247
|
const ADOPT_MS = 30_000;
|
|
236
248
|
function adopt(state, prompt) {
|
|
237
249
|
const own = state.prompts.find((each) => each.relay?.own &&
|
|
@@ -407,7 +419,7 @@ async function notified(io, origin, input) {
|
|
|
407
419
|
for (const prompt of (known?.prompts ?? []).slice().reverse()) {
|
|
408
420
|
if (prompt.shown !== undefined || prompt.notice || prompt.at > before)
|
|
409
421
|
continue;
|
|
410
|
-
if (await stillAsked(known, prompt)) {
|
|
422
|
+
if (prompt.relay || (await stillAsked(known, prompt))) {
|
|
411
423
|
picked = promptId(prompt);
|
|
412
424
|
break;
|
|
413
425
|
}
|
|
@@ -436,7 +448,7 @@ async function notified(io, origin, input) {
|
|
|
436
448
|
shows.shown = now;
|
|
437
449
|
delete shows.failed;
|
|
438
450
|
}
|
|
439
|
-
else if (next.prompts.some((prompt) => prompt.shown !== undefined)) {
|
|
451
|
+
else if (next.prompts.some((prompt) => prompt.shown !== undefined || prompt.relay)) {
|
|
440
452
|
return state;
|
|
441
453
|
}
|
|
442
454
|
else
|
|
@@ -506,7 +518,9 @@ function relayPlan(state, now, grace, then) {
|
|
|
506
518
|
const waiting = state.prompts.filter((prompt) => prompt.relay && !prompt.card && !prompt.failed);
|
|
507
519
|
if (waiting.length === 0)
|
|
508
520
|
return then;
|
|
509
|
-
const dueAt = (prompt) =>
|
|
521
|
+
const dueAt = (prompt) => state.card?.moving
|
|
522
|
+
? now
|
|
523
|
+
: Math.min(Math.min(prompt.at, prompt.relay.at) + grace, prompt.shown ?? Number.POSITIVE_INFINITY);
|
|
510
524
|
const first = waiting.reduce((soonest, prompt) => dueAt(prompt) < dueAt(soonest) ? prompt : soonest);
|
|
511
525
|
const due = dueAt(first) - now;
|
|
512
526
|
if (due <= 0)
|
|
@@ -520,7 +534,9 @@ function relayPlan(state, now, grace, then) {
|
|
|
520
534
|
function cardPlan(state, now, grace) {
|
|
521
535
|
const prompts = state.prompts.filter((prompt) => seen(prompt) && !prompt.relay);
|
|
522
536
|
if (prompts.length === 0)
|
|
523
|
-
return state.card
|
|
537
|
+
return state.card
|
|
538
|
+
? { kind: 'cancel', ...(state.card.moving ? { moved: true } : {}) }
|
|
539
|
+
: { kind: 'done' };
|
|
524
540
|
if (state.card) {
|
|
525
541
|
const newest = shownOf(prompts);
|
|
526
542
|
if (state.card.key === newest.key)
|
|
@@ -724,8 +740,7 @@ async function callState(calls, prompt) {
|
|
|
724
740
|
const size = (await file.stat()).size;
|
|
725
741
|
let position = size;
|
|
726
742
|
let carry = Buffer.alloc(0);
|
|
727
|
-
const results = new
|
|
728
|
-
let sameTool = null;
|
|
743
|
+
const results = new Map();
|
|
729
744
|
let found = null;
|
|
730
745
|
const read = (line) => {
|
|
731
746
|
if (!line.includes('tool_'))
|
|
@@ -746,13 +761,16 @@ async function callState(calls, prompt) {
|
|
|
746
761
|
continue;
|
|
747
762
|
const id = text(block.tool_use_id) || text(block.id);
|
|
748
763
|
if (block.type === 'tool_result' && id)
|
|
749
|
-
results.
|
|
750
|
-
else if (block.type === 'tool_use' &&
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
764
|
+
results.set(id, Date.parse(text(entry.timestamp)));
|
|
765
|
+
else if (block.type === 'tool_use' &&
|
|
766
|
+
entry.type === 'assistant' &&
|
|
767
|
+
found === null &&
|
|
768
|
+
promptKey(text(block.name), block.input, prompt.agent) === prompt.key) {
|
|
769
|
+
const answered = results.get(id);
|
|
770
|
+
if (answered === undefined)
|
|
771
|
+
found = 'waiting';
|
|
772
|
+
else if (!(answered < prompt.at))
|
|
773
|
+
found = 'answered';
|
|
756
774
|
}
|
|
757
775
|
}
|
|
758
776
|
};
|
|
@@ -772,11 +790,7 @@ async function callState(calls, prompt) {
|
|
|
772
790
|
}
|
|
773
791
|
if (found === null && position === 0)
|
|
774
792
|
read(carry.toString('utf8'));
|
|
775
|
-
|
|
776
|
-
return found;
|
|
777
|
-
if (sameTool !== null)
|
|
778
|
-
return results.has(sameTool) ? 'answered' : 'waiting';
|
|
779
|
-
return 'waiting';
|
|
793
|
+
return found ?? 'waiting';
|
|
780
794
|
}
|
|
781
795
|
catch {
|
|
782
796
|
return null;
|
|
@@ -940,6 +954,7 @@ async function post(io, client, state, prompt, worker) {
|
|
|
940
954
|
const kept = await record(io, state.session, worker, (state) => {
|
|
941
955
|
state.card = card;
|
|
942
956
|
state.areaId = areaId;
|
|
957
|
+
markMoving(state);
|
|
943
958
|
});
|
|
944
959
|
if (!kept)
|
|
945
960
|
await withdraw(io, client, card, state, 'answered').catch(() => { });
|
|
@@ -1064,19 +1079,24 @@ async function update(io, client, state, prompt, worker) {
|
|
|
1064
1079
|
}
|
|
1065
1080
|
const version = typeof result.version === 'number' ? result.version : card.version + 1;
|
|
1066
1081
|
await record(io, state.session, worker, (state) => {
|
|
1067
|
-
if (state.card?.requestId === card.requestId)
|
|
1068
|
-
|
|
1082
|
+
if (state.card?.requestId === card.requestId) {
|
|
1083
|
+
const { moving: _, ...shown } = card;
|
|
1084
|
+
state.card = { ...shown, version, key: prompt.key };
|
|
1085
|
+
}
|
|
1069
1086
|
});
|
|
1070
1087
|
}
|
|
1088
|
+
const MOVED = 'It has a card of its own now, with Allow and Deny.';
|
|
1071
1089
|
async function withdraw(io, client, card, state, how) {
|
|
1072
1090
|
const machine = await computerOf(io, state.origin, appOf(state));
|
|
1073
1091
|
try {
|
|
1074
1092
|
await client.call('cancel_request', {
|
|
1075
1093
|
requestId: card.requestId,
|
|
1076
1094
|
name: card.name,
|
|
1077
|
-
reason: how === '
|
|
1078
|
-
?
|
|
1079
|
-
:
|
|
1095
|
+
reason: how === 'moved'
|
|
1096
|
+
? MOVED
|
|
1097
|
+
: how === 'answered'
|
|
1098
|
+
? cut(`Answered in ${APP_NAMES[appOf(state)]} on ${machine}.`, 200)
|
|
1099
|
+
: cut(`That ${APP_NAMES[appOf(state)]} session on ${machine} ended, so it isn’t waiting any more.`, 200),
|
|
1080
1100
|
...(how === 'answered' ? { answeredHere: true } : {}),
|
|
1081
1101
|
});
|
|
1082
1102
|
}
|
|
@@ -1192,7 +1212,7 @@ export async function permissionWorker(io, options) {
|
|
|
1192
1212
|
}
|
|
1193
1213
|
else {
|
|
1194
1214
|
const card = state.card;
|
|
1195
|
-
await withdraw(io, client, card, state, state.settled ?? 'answered');
|
|
1215
|
+
await withdraw(io, client, card, state, plan.moved ? 'moved' : (state.settled ?? 'answered'));
|
|
1196
1216
|
await record(io, session, worker, (state) => {
|
|
1197
1217
|
if (state.card?.requestId === card.requestId)
|
|
1198
1218
|
delete state.card;
|
|
@@ -1288,6 +1308,7 @@ export async function recordRelay(io, origin, heard, options) {
|
|
|
1288
1308
|
return state;
|
|
1289
1309
|
prompt.relay = heard.relay;
|
|
1290
1310
|
delete prompt.failed;
|
|
1311
|
+
relayed(state);
|
|
1291
1312
|
matched = true;
|
|
1292
1313
|
delete state.settled;
|
|
1293
1314
|
worker = claim(state, io.now());
|
|
@@ -1324,6 +1345,7 @@ export async function recordRelay(io, origin, heard, options) {
|
|
|
1324
1345
|
if (next.prompts.some((each) => each.relay?.id === heard.relay.id))
|
|
1325
1346
|
return next;
|
|
1326
1347
|
next.prompts.push(prompt);
|
|
1348
|
+
relayed(next);
|
|
1327
1349
|
keepNewest(next);
|
|
1328
1350
|
delete next.settled;
|
|
1329
1351
|
next.at = now;
|
package/dist/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.34.
|
|
1
|
+
export const VERSION = '0.34.2';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pendingyou",
|
|
3
|
-
"version": "0.34.
|
|
3
|
+
"version": "0.34.2",
|
|
4
4
|
"description": "Pending You for your coding agents: one command sets up Claude Code, Codex, OpenCode and Pi to ask you through Pending You and hear your answers, even while they sit idle.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://www.pendingyou.com",
|