@jpcasabiancai/cayenne 0.5.3 → 0.5.4
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/cli.js +115 -16
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7753,7 +7753,15 @@ async function askGuard(guard, toolName2, input) {
|
|
|
7753
7753
|
return GUARD_FAILED;
|
|
7754
7754
|
}
|
|
7755
7755
|
}
|
|
7756
|
-
|
|
7756
|
+
function asInterrupted(row) {
|
|
7757
|
+
return {
|
|
7758
|
+
...row,
|
|
7759
|
+
content: row.content.map(
|
|
7760
|
+
(block) => block.type === "result" ? { ...block, isError: false, text: INTERRUPTED } : block
|
|
7761
|
+
)
|
|
7762
|
+
};
|
|
7763
|
+
}
|
|
7764
|
+
var SESSION_FLAG_SETTINGS, GUARD_FAILED, ASK_TOOL_REASON, INTERRUPTED, STOPPED_TURN, ClaudeSession;
|
|
7757
7765
|
var init_session2 = __esm({
|
|
7758
7766
|
"src/claude/session.ts"() {
|
|
7759
7767
|
"use strict";
|
|
@@ -7768,6 +7776,8 @@ var init_session2 = __esm({
|
|
|
7768
7776
|
};
|
|
7769
7777
|
GUARD_FAILED = "Refused: the runner could not check this tool call.";
|
|
7770
7778
|
ASK_TOOL_REASON = "This session was started from a task, so every shell command needs the member's approval.";
|
|
7779
|
+
INTERRUPTED = "interrupted";
|
|
7780
|
+
STOPPED_TURN = "error_during_execution after a requested stop: recorded as interrupted";
|
|
7771
7781
|
ClaudeSession = class extends EventEmitter {
|
|
7772
7782
|
constructor(opts) {
|
|
7773
7783
|
super();
|
|
@@ -7786,6 +7796,13 @@ var init_session2 = __esm({
|
|
|
7786
7796
|
/** `null` until `accountInfo()` answers, and for good when it cannot. */
|
|
7787
7797
|
authMode = null;
|
|
7788
7798
|
authAsked = false;
|
|
7799
|
+
/** A prompt is waiting for its turn, or a turn began (`init`), and no result has closed it. */
|
|
7800
|
+
turnOpen = false;
|
|
7801
|
+
/**
|
|
7802
|
+
* `interrupt()` or `stop()` was asked of the open turn. The CLI reports a turn cut short as
|
|
7803
|
+
* `error_during_execution`; with this set, that result is the stop landing, not a failure.
|
|
7804
|
+
*/
|
|
7805
|
+
stopAsked = false;
|
|
7789
7806
|
start() {
|
|
7790
7807
|
if (this.q) throw new Error("VALIDATION: session already started");
|
|
7791
7808
|
const queryFn = this.opts.queryFn ?? sdkQuery;
|
|
@@ -7869,6 +7886,7 @@ var init_session2 = __esm({
|
|
|
7869
7886
|
})),
|
|
7870
7887
|
{ type: "text", text }
|
|
7871
7888
|
] : text;
|
|
7889
|
+
this.turnOpen = true;
|
|
7872
7890
|
this.inbox.push({
|
|
7873
7891
|
type: "user",
|
|
7874
7892
|
message: { role: "user", content },
|
|
@@ -7885,6 +7903,7 @@ var init_session2 = __esm({
|
|
|
7885
7903
|
return true;
|
|
7886
7904
|
}
|
|
7887
7905
|
async interrupt() {
|
|
7906
|
+
if (this.turnOpen) this.stopAsked = true;
|
|
7888
7907
|
await this.q?.interrupt();
|
|
7889
7908
|
}
|
|
7890
7909
|
async setPermissionMode(mode) {
|
|
@@ -7901,6 +7920,7 @@ var init_session2 = __esm({
|
|
|
7901
7920
|
for (const id of [...this.pending.keys()]) {
|
|
7902
7921
|
this.expire(id, "session stopped");
|
|
7903
7922
|
}
|
|
7923
|
+
if (this.turnOpen) this.stopAsked = true;
|
|
7904
7924
|
void this.q?.interrupt().catch(() => void 0);
|
|
7905
7925
|
const killer = setTimeout(() => this.abort.abort(), 5e3);
|
|
7906
7926
|
await this.pumping;
|
|
@@ -7955,6 +7975,7 @@ ${this.stderrTail.join("\n")}` : "";
|
|
|
7955
7975
|
}
|
|
7956
7976
|
route(msg) {
|
|
7957
7977
|
if (msg.type === "system" && msg.subtype === "init") {
|
|
7978
|
+
this.turnOpen = true;
|
|
7958
7979
|
this.providerSessionId = msg.session_id;
|
|
7959
7980
|
this.lookUpAuthMode();
|
|
7960
7981
|
this.emit("init", {
|
|
@@ -7974,15 +7995,19 @@ ${this.stderrTail.join("\n")}` : "";
|
|
|
7974
7995
|
});
|
|
7975
7996
|
return;
|
|
7976
7997
|
}
|
|
7998
|
+
const stopped = msg.type === "result" && this.stopAsked && msg.subtype === "error_during_execution";
|
|
7999
|
+
if (stopped) logger.info({ providerSessionId: this.providerSessionId }, STOPPED_TURN);
|
|
7977
8000
|
const normalized = normalizeSdkMessage(msg);
|
|
7978
|
-
if (normalized) this.emit("message", normalized);
|
|
8001
|
+
if (normalized) this.emit("message", stopped ? asInterrupted(normalized) : normalized);
|
|
7979
8002
|
if (msg.type === "result") {
|
|
8003
|
+
this.turnOpen = false;
|
|
8004
|
+
this.stopAsked = false;
|
|
7980
8005
|
this.emit("result", {
|
|
7981
|
-
isError: msg.is_error,
|
|
8006
|
+
isError: stopped ? false : msg.is_error,
|
|
7982
8007
|
durationMs: msg.duration_ms,
|
|
7983
8008
|
numTurns: msg.num_turns,
|
|
7984
8009
|
totalCostUsd: msg.total_cost_usd,
|
|
7985
|
-
stopReason: msg.stop_reason,
|
|
8010
|
+
stopReason: stopped ? INTERRUPTED : msg.stop_reason,
|
|
7986
8011
|
authMode: this.authMode
|
|
7987
8012
|
});
|
|
7988
8013
|
}
|
|
@@ -9965,7 +9990,7 @@ function shrink(event) {
|
|
|
9965
9990
|
return null;
|
|
9966
9991
|
}
|
|
9967
9992
|
}
|
|
9968
|
-
var READ_ONLY_TEXT, REFRESH_WITHIN_MS, betweenTurns, UNREADABLE_MARK_CREDS, roundUsd, UNIQUE_VIOLATION, ROW_WRITE_TIMEOUT_MS, ORPHANED_STATUSES, RESTARTABLE_STATUSES, isAtOrBelow3, DENY_MESSAGE_MAX, EXIT_ERROR_MAX, INITIAL_PROMPT_MAX, TASK_SKILL_LOOKUP_MS, TASK_REFUSED_MODES, OWNER_DRIVEN_KINDS, REPO_OWNER_ONLY, REPO_NO_DUPLICATE, PROVIDER_SESSION_ID, REPO_WORKTREE_GONE, TASK_ASK_TOOLS, MEMORY_PREAMBLE, MEMORY_SOURCE, wrapMemory, PATH_INPUT_TOOLS, PATH_INPUT_KEYS, isRecord, errorCode, SessionManager;
|
|
9993
|
+
var READ_ONLY_TEXT, REFRESH_WITHIN_MS, betweenTurns, UNREADABLE_MARK_CREDS, DRAINED_AFTER_MS, roundUsd, UNIQUE_VIOLATION, ROW_WRITE_TIMEOUT_MS, ORPHANED_STATUSES, RESTARTABLE_STATUSES, isAtOrBelow3, DENY_MESSAGE_MAX, EXIT_ERROR_MAX, INITIAL_PROMPT_MAX, TASK_SKILL_LOOKUP_MS, TASK_REFUSED_MODES, OWNER_DRIVEN_KINDS, REPO_OWNER_ONLY, REPO_NO_DUPLICATE, PROVIDER_SESSION_ID, REPO_WORKTREE_GONE, TASK_ASK_TOOLS, MEMORY_PREAMBLE, MEMORY_SOURCE, wrapMemory, PATH_INPUT_TOOLS, PATH_INPUT_KEYS, isRecord, errorCode, SessionManager;
|
|
9969
9994
|
var init_manager = __esm({
|
|
9970
9995
|
"src/sessions/manager.ts"() {
|
|
9971
9996
|
"use strict";
|
|
@@ -10006,6 +10031,7 @@ var init_manager = __esm({
|
|
|
10006
10031
|
state: "unavailable",
|
|
10007
10032
|
readOnlyText: READ_ONLY_UNAVAILABLE
|
|
10008
10033
|
};
|
|
10034
|
+
DRAINED_AFTER_MS = 2e3;
|
|
10009
10035
|
roundUsd = (usd) => Math.round(usd * 1e6) / 1e6;
|
|
10010
10036
|
UNIQUE_VIOLATION = "23505";
|
|
10011
10037
|
ROW_WRITE_TIMEOUT_MS = 3e4;
|
|
@@ -10609,6 +10635,7 @@ var init_manager = __esm({
|
|
|
10609
10635
|
);
|
|
10610
10636
|
await this.setStatus(sessionId, "running");
|
|
10611
10637
|
live.session.prompt(text, p.clientUuid, staged);
|
|
10638
|
+
this.turnHandedOver(live);
|
|
10612
10639
|
this.deps.timings?.prompted(sessionId);
|
|
10613
10640
|
} catch (err) {
|
|
10614
10641
|
staged.discard();
|
|
@@ -10971,12 +10998,78 @@ var init_manager = __esm({
|
|
|
10971
10998
|
async interrupt(sessionId) {
|
|
10972
10999
|
const live = this.live.get(sessionId);
|
|
10973
11000
|
if (live) {
|
|
10974
|
-
|
|
11001
|
+
const { turns } = live;
|
|
11002
|
+
turns.stops = turns.owed;
|
|
11003
|
+
turns.chased = false;
|
|
11004
|
+
turns.early = turns.owed > 0 && !turns.begun && !live.stopping && !live.dropping;
|
|
11005
|
+
if (turns.early) {
|
|
11006
|
+
this.sendStop(sessionId, live);
|
|
11007
|
+
if (live.status === "running") await this.setStatus(sessionId, "idle");
|
|
11008
|
+
return {};
|
|
11009
|
+
}
|
|
11010
|
+
try {
|
|
11011
|
+
await this.provider(() => live.session.interrupt());
|
|
11012
|
+
} catch (err) {
|
|
11013
|
+
turns.stops = 0;
|
|
11014
|
+
throw err;
|
|
11015
|
+
}
|
|
10975
11016
|
return {};
|
|
10976
11017
|
}
|
|
10977
11018
|
await this.settleOrphans([sessionId]);
|
|
10978
11019
|
return {};
|
|
10979
11020
|
}
|
|
11021
|
+
/** A stop nobody waits on: a provider that is starting, or between turns, may answer late. */
|
|
11022
|
+
sendStop(sessionId, live) {
|
|
11023
|
+
void live.session.interrupt().catch(
|
|
11024
|
+
(err) => this.deps.log.warn(
|
|
11025
|
+
{ err: err instanceof Error ? err.message : String(err), sessionId },
|
|
11026
|
+
"a stop sent ahead of its turn failed"
|
|
11027
|
+
)
|
|
11028
|
+
);
|
|
11029
|
+
}
|
|
11030
|
+
/** A prompt went to the provider. */
|
|
11031
|
+
turnHandedOver(live) {
|
|
11032
|
+
const { turns } = live;
|
|
11033
|
+
const leftover = live.provider === "claude" && turns.stops === 0 && turns.drainedAt !== null && Date.now() - turns.drainedAt > DRAINED_AFTER_MS;
|
|
11034
|
+
if (leftover) {
|
|
11035
|
+
turns.owed = 0;
|
|
11036
|
+
turns.stops = 0;
|
|
11037
|
+
}
|
|
11038
|
+
turns.drainedAt = null;
|
|
11039
|
+
turns.owed += 1;
|
|
11040
|
+
}
|
|
11041
|
+
/** The provider announced a turn (`init`): if a Stop covers it, this is where it lands. */
|
|
11042
|
+
turnBegan(sessionId, live) {
|
|
11043
|
+
if (live.provider !== "claude") return;
|
|
11044
|
+
const { turns } = live;
|
|
11045
|
+
turns.drainedAt = null;
|
|
11046
|
+
if (turns.owed > 0) turns.begun = true;
|
|
11047
|
+
if (turns.stops > 0 && turns.early) this.sendStop(sessionId, live);
|
|
11048
|
+
}
|
|
11049
|
+
/**
|
|
11050
|
+
* The provider produced output. For a turn stopped before it began that means the stop did not
|
|
11051
|
+
* land (a backend with no `init` per turn, or a stop that was lost): it is sent once more, and
|
|
11052
|
+
* `true` tells the caller the row must say `running` again, since a turn is.
|
|
11053
|
+
*/
|
|
11054
|
+
turnOutput(sessionId, live) {
|
|
11055
|
+
const { turns } = live;
|
|
11056
|
+
turns.drainedAt = null;
|
|
11057
|
+
if (turns.owed > 0) turns.begun = true;
|
|
11058
|
+
if (turns.stops === 0 || !turns.early || turns.chased) return false;
|
|
11059
|
+
turns.chased = true;
|
|
11060
|
+
this.sendStop(sessionId, live);
|
|
11061
|
+
return live.status === "idle";
|
|
11062
|
+
}
|
|
11063
|
+
/** A turn ended: whatever a Stop still covers is behind it, and has not begun. */
|
|
11064
|
+
turnEnded(live) {
|
|
11065
|
+
const { turns } = live;
|
|
11066
|
+
turns.owed = Math.max(0, turns.owed - 1);
|
|
11067
|
+
turns.stops = Math.max(0, turns.stops - 1);
|
|
11068
|
+
turns.begun = false;
|
|
11069
|
+
turns.drainedAt = Date.now();
|
|
11070
|
+
turns.early = true;
|
|
11071
|
+
turns.chased = false;
|
|
11072
|
+
}
|
|
10980
11073
|
/**
|
|
10981
11074
|
* Put rows on this runner that claim a turn in progress back to `idle`, for the chats that have
|
|
10982
11075
|
* no live session here — at boot every one of them, since nothing is live yet, and again when
|
|
@@ -11809,6 +11902,7 @@ var init_manager = __esm({
|
|
|
11809
11902
|
permissions: /* @__PURE__ */ new Map(),
|
|
11810
11903
|
cwd: opts.cwd,
|
|
11811
11904
|
stopping: false,
|
|
11905
|
+
turns: { owed: 0, begun: false, drainedAt: null, stops: 0, early: false, chased: false },
|
|
11812
11906
|
dropping: null,
|
|
11813
11907
|
inflight: /* @__PURE__ */ new Set(),
|
|
11814
11908
|
writes: Promise.resolve(),
|
|
@@ -11975,9 +12069,12 @@ var init_manager = __esm({
|
|
|
11975
12069
|
live.inflight.add(task);
|
|
11976
12070
|
void task.finally(() => live.inflight.delete(task));
|
|
11977
12071
|
};
|
|
11978
|
-
|
|
11979
|
-
"
|
|
11980
|
-
|
|
12072
|
+
const output = () => {
|
|
12073
|
+
if (this.turnOutput(sessionId, live)) guard(() => this.setStatus(sessionId, "running"))();
|
|
12074
|
+
};
|
|
12075
|
+
session.on("init", (init) => {
|
|
12076
|
+
this.turnBegan(sessionId, live);
|
|
12077
|
+
return guard(async () => {
|
|
11981
12078
|
await this.updateSession(sessionId, {
|
|
11982
12079
|
provider_session_id: init.providerSessionId,
|
|
11983
12080
|
model: init.model
|
|
@@ -11988,9 +12085,10 @@ var init_manager = __esm({
|
|
|
11988
12085
|
providerSessionId: init.providerSessionId,
|
|
11989
12086
|
model: init.model
|
|
11990
12087
|
});
|
|
11991
|
-
})()
|
|
11992
|
-
);
|
|
12088
|
+
})();
|
|
12089
|
+
});
|
|
11993
12090
|
session.on("stream", (s) => {
|
|
12091
|
+
output();
|
|
11994
12092
|
this.deps.timings?.streamed(sessionId);
|
|
11995
12093
|
guard(
|
|
11996
12094
|
() => this.broadcast(sessionId, {
|
|
@@ -12001,9 +12099,9 @@ var init_manager = __esm({
|
|
|
12001
12099
|
})
|
|
12002
12100
|
)();
|
|
12003
12101
|
});
|
|
12004
|
-
session.on(
|
|
12005
|
-
"
|
|
12006
|
-
|
|
12102
|
+
session.on("message", (m) => {
|
|
12103
|
+
if (m.role === "assistant" || m.role === "tool") output();
|
|
12104
|
+
return guard(async () => {
|
|
12007
12105
|
if (m.role === "user" && m.providerUuid && live.echoed.has(m.providerUuid)) return;
|
|
12008
12106
|
await this.persist(
|
|
12009
12107
|
sessionId,
|
|
@@ -12014,8 +12112,8 @@ var init_manager = __esm({
|
|
|
12014
12112
|
m.parentToolUseId,
|
|
12015
12113
|
m.raw
|
|
12016
12114
|
);
|
|
12017
|
-
})()
|
|
12018
|
-
);
|
|
12115
|
+
})();
|
|
12116
|
+
});
|
|
12019
12117
|
session.on(
|
|
12020
12118
|
"permission",
|
|
12021
12119
|
(rawReq) => guard(async () => {
|
|
@@ -12104,6 +12202,7 @@ var init_manager = __esm({
|
|
|
12104
12202
|
})()
|
|
12105
12203
|
);
|
|
12106
12204
|
session.on("result", (r) => {
|
|
12205
|
+
this.turnEnded(live);
|
|
12107
12206
|
this.deps.timings?.finished(sessionId);
|
|
12108
12207
|
const lastSeq = live.writes.then(() => live.seq);
|
|
12109
12208
|
guard(async () => {
|