@code-yeongyu/senpi 2026.10.10-8 → 2026.10.10-9
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 +16 -0
- package/dist/bundle/chunks/{anthropic-messages-6EZ2RZQI.js → anthropic-messages-2B35OVB7.js} +2 -2
- package/dist/bundle/chunks/{app-server-command-WVQZIVCM.js → app-server-command-2ZXLBILW.js} +1 -1
- package/dist/bundle/chunks/{chunk-KKJJVAVT.js → chunk-4WZF7G6N.js} +1 -1
- package/dist/bundle/chunks/{chunk-TUGQPBQG.js → chunk-NTH33AXY.js} +15 -4
- package/dist/bundle/chunks/{chunk-56NFYCQ3.js → chunk-QMUL36OS.js} +19 -24
- package/dist/bundle/chunks/{chunk-TLK72OXY.js → chunk-QQZREV6B.js} +1 -1
- package/dist/bundle/chunks/chunk-Z72GD25U.js +9 -0
- package/dist/bundle/chunks/{chunk-QYKYTDMI.js → chunk-ZCYTYHDN.js} +1 -1
- package/dist/bundle/chunks/{chunk-DOMETRRO.js → chunk-ZPJHS64R.js} +1 -1
- package/dist/bundle/chunks/{cli-main-CED4CUJM.js → cli-main-VTGNVET5.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-PSP2GJSG.js → help-fast-path-5P73752B.js} +1 -1
- package/dist/bundle/chunks/{host-command-5ILDFZVI.js → host-command-MWQNTWFA.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-ZKESRBOA.js → interactive-mode-ERBFHQQJ.js} +1 -1
- package/dist/bundle/chunks/{multi-session-host-AL2DTLN2.js → multi-session-host-S37LFCMH.js} +1 -1
- package/dist/bundle/chunks/{package-manager-cli-U4UWVUUX.js → package-manager-cli-FVEIJBD5.js} +1 -1
- package/dist/bundle/chunks/{rotation-stream-TAARAJGY.js → rotation-stream-FQH63DMY.js} +1 -1
- package/dist/bundle/chunks/{rpc-mode-MXEWGXIB.js → rpc-mode-KJFVBWIP.js} +1 -1
- package/dist/bundle/chunks/{session-control-endpoint-EQXHX4WI.js → session-control-endpoint-OH7XV2FN.js} +1 -1
- package/dist/bundle/chunks/{session-picker-LIZG5P3Q.js → session-picker-UUSW6YSU.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +31 -30
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/bundle/runtime-manifest.json +1 -1
- package/dist/core/agent-session.d.ts +16 -0
- package/dist/core/agent-session.js +61 -0
- package/dist/core/engine-turn-limit.d.ts +36 -0
- package/dist/core/engine-turn-limit.js +74 -0
- package/dist/core/extensions/builtin/ask-user/format.d.ts +9 -4
- package/dist/core/extensions/builtin/ask-user/format.js +37 -9
- package/dist/core/extensions/builtin/ask-user/params.d.ts +2 -0
- package/dist/core/extensions/builtin/ask-user/params.js +6 -0
- package/dist/core/extensions/builtin/ask-user/resume.js +8 -1
- package/dist/core/extensions/builtin/ask-user/schema.js +4 -0
- package/dist/core/extensions/builtin/ask-user/tool.js +18 -7
- package/dist/core/extensions/builtin/hooks/index.js +1 -1
- package/dist/core/extensions/builtin/ttsr/follow-up-limit.d.ts +11 -0
- package/dist/core/extensions/builtin/ttsr/follow-up-limit.js +30 -0
- package/dist/core/extensions/builtin/ttsr/index.js +9 -1
- package/dist/core/extensions/runner.d.ts +2 -0
- package/dist/core/extensions/runner.js +4 -0
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/settings-manager.d.ts +9 -0
- package/dist/core/settings-manager.js +9 -0
- package/dist/modes/interactive/interactive-mode.js +1 -1
- package/docs/settings.md +9 -0
- package/package.json +6 -6
- package/dist/bundle/chunks/chunk-V43EN5GQ.js +0 -14
|
@@ -1,16 +1,23 @@
|
|
|
1
1
|
import { WAKE_SOURCE_STATE_EVENT } from "../monitor-state-event.js";
|
|
2
2
|
import { TOOL_NAMES } from "./family.js";
|
|
3
|
-
import { formatModelAnswer, formatResultDetails, formatUserMessage } from "./format.js";
|
|
3
|
+
import { formatGatedCancellation, formatModelAnswer, formatResultDetails, formatUserMessage } from "./format.js";
|
|
4
4
|
import { ASK_USER_ASKED_EVENT, ASK_USER_QUESTION_ENTRY, ASK_USER_SETTLEMENT_ENTRY, emitAskUserClosed, emitAskUserNotification, } from "./notify.js";
|
|
5
5
|
import { createPendingQuestion } from "./pending.js";
|
|
6
6
|
import { getPendingQuestions, queueQuestionOutcome, registerPendingQuestion, } from "./registry.js";
|
|
7
7
|
import { renderCall, renderResult } from "./render.js";
|
|
8
8
|
import { AskUserSchemaError, CLAUDE_PARAMS, CODEX_PARAMS, toCanonical, } from "./schema.js";
|
|
9
9
|
const REASK = "The user did not answer the previous question this turn; continue without asking again.";
|
|
10
|
+
const REASK_REQUIRED = "The user did not answer the previous question this turn, so this one gets no answer either. No answer: do not take the action it gates. Keep that action pending and end the turn.";
|
|
10
11
|
function result(variant, response, request, text) {
|
|
11
12
|
return {
|
|
12
|
-
content: [
|
|
13
|
-
|
|
13
|
+
content: [
|
|
14
|
+
{
|
|
15
|
+
type: "text",
|
|
16
|
+
text: text ??
|
|
17
|
+
formatModelAnswer(response, request.requestId, request.questions, request.required === true).text,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
details: formatResultDetails(variant, response, request.requestId, request.questions, request.required === true),
|
|
14
21
|
};
|
|
15
22
|
}
|
|
16
23
|
/**
|
|
@@ -24,7 +31,7 @@ function result(variant, response, request, text) {
|
|
|
24
31
|
export function deliverAnswer(pi, ctx, request, response, variant) {
|
|
25
32
|
if (response.status === "cancelled")
|
|
26
33
|
return;
|
|
27
|
-
pi.sendUserMessage(formatUserMessage(response, request.requestId, request.questions), {
|
|
34
|
+
pi.sendUserMessage(formatUserMessage(response, request.requestId, request.questions, request.required === true), {
|
|
28
35
|
deliverAs: ctx.isIdle() ? "followUp" : "steer",
|
|
29
36
|
});
|
|
30
37
|
void emitAskUserNotification(pi, ctx, request, response, variant);
|
|
@@ -258,7 +265,7 @@ export function createAskUserTool(variant, pi, state) {
|
|
|
258
265
|
allowLazyActivation: false,
|
|
259
266
|
parameters: variant === "codex" ? CODEX_PARAMS : CLAUDE_PARAMS,
|
|
260
267
|
promptSnippet: "Ask a material question, explicitly choosing whether to wait or receive the answer later.",
|
|
261
|
-
description: `${opener} Set ${flag} true to pause here until the user answers (the answer returns as this tool's result, or a timeout result after 30 idle minutes); set ${flag} false to keep working while the question stays open (the answer arrives later as a user message). Use it only when the answer materially changes the work; if it returns no answers, continue with best judgment instead of asking again. Never use it for permission requests; ask those directly in your message. Unavailable to subagents.${variant === "claude" ? " Users will always be able to type a free-text answer or one comment covering everything; do not add an Other option." : ""} Call this tool directly, never from inside an eval cell (a cell that waits on the user would hold the kernel).`,
|
|
268
|
+
description: `${opener} Set ${flag} true to pause here until the user answers (the answer returns as this tool's result, or a timeout result after 30 idle minutes); set ${flag} false to keep working while the question stays open (the answer arrives later as a user message). Use it only when the answer materially changes the work; if it returns no answers, continue with best judgment instead of asking again, unless you set required true because the answer decides whether you take an action: then no answer means do not take it. Never use it for permission requests; ask those directly in your message. Unavailable to subagents.${variant === "claude" ? " Users will always be able to type a free-text answer or one comment covering everything; do not add an Other option." : ""} Call this tool directly, never from inside an eval cell (a cell that waits on the user would hold the kernel).`,
|
|
262
269
|
prepareArguments(args) {
|
|
263
270
|
toCanonical(variant, args);
|
|
264
271
|
return args;
|
|
@@ -284,7 +291,7 @@ export function createAskUserTool(variant, pi, state) {
|
|
|
284
291
|
};
|
|
285
292
|
if (state.timedOut) {
|
|
286
293
|
emitAskUserClosed(pi, request.requestId, unavailable);
|
|
287
|
-
return result(variant, unavailable, request, REASK);
|
|
294
|
+
return result(variant, unavailable, request, request.required === true ? REASK_REQUIRED : REASK);
|
|
288
295
|
}
|
|
289
296
|
if (state.unavailable ||
|
|
290
297
|
ctx.getAskUserSettings?.().enabled === false ||
|
|
@@ -307,7 +314,11 @@ export function createAskUserTool(variant, pi, state) {
|
|
|
307
314
|
if (response.status !== "cancelled") {
|
|
308
315
|
void emitAskUserNotification(pi, ctx, request, response, variant);
|
|
309
316
|
}
|
|
310
|
-
return result(variant, response, request, response.status === "cancelled" && response.comment
|
|
317
|
+
return result(variant, response, request, response.status === "cancelled" && response.comment
|
|
318
|
+
? request.required === true
|
|
319
|
+
? formatGatedCancellation(response.comment, response, request.requestId, request.questions)
|
|
320
|
+
: response.comment
|
|
321
|
+
: undefined);
|
|
311
322
|
},
|
|
312
323
|
renderCall,
|
|
313
324
|
renderResult,
|
|
@@ -54,7 +54,7 @@ export default function hooksExtension(pi) {
|
|
|
54
54
|
message: response === undefined
|
|
55
55
|
? `Question asked (${headers})`
|
|
56
56
|
: response.status === "timed_out"
|
|
57
|
-
? `Question timed out (${headers}): ${formatResultText(variant, response, request.questions)}`
|
|
57
|
+
? `Question timed out (${headers}): ${formatResultText(variant, response, request.questions, request.required === true)}`
|
|
58
58
|
: `Question ${response.status} (${headers})`,
|
|
59
59
|
requestId: request.requestId,
|
|
60
60
|
source: "ask-user",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SessionEntry } from "../../../session-manager.ts";
|
|
2
|
+
export declare const TTSR_LOOP_STOPPED_ENTRY_TYPE = "ttsr-loop-stopped";
|
|
3
|
+
export declare const TTSR_LOOP_STOPPED_EVENT = "ttsr:loop-stopped";
|
|
4
|
+
export declare function ttsrLoopStoppedNotice(rule: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Whether this rule already sent its one corrective follow-up since the user's last message. Read from the
|
|
7
|
+
* session, so a host that rebuilds the extension between turns cannot re-arm it (senpi#2967); the engine-wide
|
|
8
|
+
* turn bound covers every other source.
|
|
9
|
+
*/
|
|
10
|
+
export declare function ruleAlreadyCorrected(entries: readonly SessionEntry[], rule: string): boolean;
|
|
11
|
+
//# sourceMappingURL=follow-up-limit.d.ts.map
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { TTSR_INJECTION_CUSTOM_TYPE } from "./types.js";
|
|
2
|
+
export const TTSR_LOOP_STOPPED_ENTRY_TYPE = "ttsr-loop-stopped";
|
|
3
|
+
export const TTSR_LOOP_STOPPED_EVENT = "ttsr:loop-stopped";
|
|
4
|
+
export function ttsrLoopStoppedNotice(rule) {
|
|
5
|
+
return `The ${rule} stream rule flagged the reply again after its correction, so no further correction was sent. Send any message to continue.`;
|
|
6
|
+
}
|
|
7
|
+
function nudgedRules(entry) {
|
|
8
|
+
if (entry.type !== "custom_message" || entry.customType !== TTSR_INJECTION_CUSTOM_TYPE)
|
|
9
|
+
return [];
|
|
10
|
+
const details = entry.details;
|
|
11
|
+
if (typeof details !== "object" || details === null || !("rules" in details))
|
|
12
|
+
return [];
|
|
13
|
+
return Array.isArray(details.rules) ? details.rules : [];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Whether this rule already sent its one corrective follow-up since the user's last message. Read from the
|
|
17
|
+
* session, so a host that rebuilds the extension between turns cannot re-arm it (senpi#2967); the engine-wide
|
|
18
|
+
* turn bound covers every other source.
|
|
19
|
+
*/
|
|
20
|
+
export function ruleAlreadyCorrected(entries, rule) {
|
|
21
|
+
for (let index = entries.length - 1; index >= 0; index--) {
|
|
22
|
+
const entry = entries[index];
|
|
23
|
+
if (entry.type === "message" && entry.message.role === "user")
|
|
24
|
+
return false;
|
|
25
|
+
if (nudgedRules(entry).includes(rule))
|
|
26
|
+
return true;
|
|
27
|
+
}
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=follow-up-limit.js.map
|
|
@@ -6,6 +6,7 @@ import { registerTtsrCommands } from "./commands.js";
|
|
|
6
6
|
import { claimAbort, createGenerationState, markUserCancelled } from "./coordinator.js";
|
|
7
7
|
import { REPETITIVE_TURNS_RULE_NAME } from "./detectors/repetitive-turns.js";
|
|
8
8
|
import { discoverTtsrRulesSync } from "./discovery.js";
|
|
9
|
+
import { ruleAlreadyCorrected, TTSR_LOOP_STOPPED_ENTRY_TYPE, TTSR_LOOP_STOPPED_EVENT, ttsrLoopStoppedNotice, } from "./follow-up-limit.js";
|
|
9
10
|
import { TtsrManager } from "./manager.js";
|
|
10
11
|
import { getTtsrStreamDelta } from "./message-update.js";
|
|
11
12
|
import { REPETITIVE_TURNS_RULE_CONTENT } from "./prompts.js";
|
|
@@ -242,7 +243,7 @@ export default function ttsrExtension(pi) {
|
|
|
242
243
|
repetitiveTurns.recordCompletedTurn(turnText);
|
|
243
244
|
return undefined;
|
|
244
245
|
});
|
|
245
|
-
pi.on("agent_settled", () => {
|
|
246
|
+
pi.on("agent_settled", (_event, ctx) => {
|
|
246
247
|
if (pendingNudge === null || genState.userCancelled || settlingAgentEnd?.abortSource === "user") {
|
|
247
248
|
pendingNudge = null;
|
|
248
249
|
settlingAgentEnd = null;
|
|
@@ -250,6 +251,13 @@ export default function ttsrExtension(pi) {
|
|
|
250
251
|
}
|
|
251
252
|
const nudge = pendingNudge;
|
|
252
253
|
pendingNudge = null;
|
|
254
|
+
const [rule] = nudge.details.rules;
|
|
255
|
+
if (rule !== undefined && ruleAlreadyCorrected(ctx.sessionManager.getEntries(), rule)) {
|
|
256
|
+
pi.appendEntry(TTSR_LOOP_STOPPED_ENTRY_TYPE, { rules: nudge.details.rules, at: Date.now() });
|
|
257
|
+
pi.events.emit(TTSR_LOOP_STOPPED_EVENT, { rules: nudge.details.rules });
|
|
258
|
+
ctx.ui.notify(ttsrLoopStoppedNotice(rule), "warning");
|
|
259
|
+
return;
|
|
260
|
+
}
|
|
253
261
|
pi.sendMessage(nudge, { triggerTurn: true });
|
|
254
262
|
});
|
|
255
263
|
}
|
|
@@ -206,6 +206,8 @@ export declare class ExtensionRunner {
|
|
|
206
206
|
* signals extensions publish about work that outlives a turn (`wake_source_state`).
|
|
207
207
|
*/
|
|
208
208
|
onBusEvent(channel: string, handler: (data: unknown) => void): () => void;
|
|
209
|
+
/** Publish a session-originated signal on the shared bus, for extensions and hosts that observe it. */
|
|
210
|
+
emitBusEvent(channel: string, data: unknown): void;
|
|
209
211
|
/** Get extension-declared MCP servers (first declaration per name wins). */
|
|
210
212
|
getRegisteredMcpServers(): readonly RegisteredMcpServerDeclaration[];
|
|
211
213
|
/** Get a tool definition by name. Returns undefined if not found. */
|
|
@@ -594,6 +594,10 @@ export class ExtensionRunner {
|
|
|
594
594
|
onBusEvent(channel, handler) {
|
|
595
595
|
return this.eventBus.on(channel, handler);
|
|
596
596
|
}
|
|
597
|
+
/** Publish a session-originated signal on the shared bus, for extensions and hosts that observe it. */
|
|
598
|
+
emitBusEvent(channel, data) {
|
|
599
|
+
this.eventBus.emit(channel, data);
|
|
600
|
+
}
|
|
597
601
|
/** Get extension-declared MCP servers (first declaration per name wins). */
|
|
598
602
|
getRegisteredMcpServers() {
|
|
599
603
|
const serversByName = new Map();
|
|
@@ -94,6 +94,8 @@ export interface QuestionRequest {
|
|
|
94
94
|
}>;
|
|
95
95
|
waitForAnswer: boolean;
|
|
96
96
|
timeoutMs: number;
|
|
97
|
+
/** The question gates an action: a missing answer means the action is not taken (senpi#2949). */
|
|
98
|
+
required?: boolean;
|
|
97
99
|
}
|
|
98
100
|
/** Outcome of ExtensionUIContext.question. */
|
|
99
101
|
export interface QuestionResponse {
|
|
@@ -103,6 +103,11 @@ export interface Settings {
|
|
|
103
103
|
images?: ImageSettings;
|
|
104
104
|
lookAt?: LookAtSettings;
|
|
105
105
|
askUser?: AskUserSettings;
|
|
106
|
+
/** Bounds on turns the engine starts without a user message (senpi#2967). */
|
|
107
|
+
engineTurns?: {
|
|
108
|
+
maxPerUserInput?: number;
|
|
109
|
+
maxToolFreePerMinute?: number;
|
|
110
|
+
};
|
|
106
111
|
todo?: TodoSettings;
|
|
107
112
|
recommendedModels?: string[];
|
|
108
113
|
favoriteModels?: string[];
|
|
@@ -254,6 +259,10 @@ export declare class SettingsManager {
|
|
|
254
259
|
timeoutMinutes: number;
|
|
255
260
|
bell: boolean;
|
|
256
261
|
};
|
|
262
|
+
getEngineTurnSettings(): {
|
|
263
|
+
maxPerUserInput: number;
|
|
264
|
+
maxToolFreePerMinute: number;
|
|
265
|
+
};
|
|
257
266
|
getTodoFirstTurnPlan(): TodoFirstTurnPlan;
|
|
258
267
|
getTodoTurnEndBackstop(): boolean;
|
|
259
268
|
isProjectTrusted(): boolean;
|
|
@@ -12,6 +12,7 @@ import { normalizePath, resolvePath } from "../utils/paths.js";
|
|
|
12
12
|
import { envValue } from "./brand.js";
|
|
13
13
|
import { compactionEnabled, compactionKeepRecentTokens, compactionReserveTokens, } from "./compaction-settings-access.js";
|
|
14
14
|
import { resolveCompactionSettings } from "./compaction-settings-resolver.js";
|
|
15
|
+
import { MAX_ENGINE_TURNS_PER_USER_INPUT, MAX_TOOL_FREE_ENGINE_TURNS_PER_WINDOW } from "./engine-turn-limit.js";
|
|
15
16
|
import { DEFAULT_HTTP_IDLE_TIMEOUT_MS, parseHttpIdleTimeoutMs } from "./http-dispatcher.js";
|
|
16
17
|
import { CredentialStoreBusyError, FILE_STORAGE_LOCK_OPTIONS, FILE_STORAGE_LOCK_RETRY_BUDGET_MS, FILE_STORAGE_LOCK_RETRY_MAX_DELAY_MS, FILE_STORAGE_LOCK_RETRY_MIN_DELAY_MS, FILE_STORAGE_SYNC_LOCK_BUDGET_MS, isLockError, } from "./lockfile-policy.js";
|
|
17
18
|
import { resolveFallbackCircuitSettings, } from "./retry-fallback/circuit.js";
|
|
@@ -675,6 +676,14 @@ export class SettingsManager {
|
|
|
675
676
|
bell: typeof configured?.bell === "boolean" ? configured.bell : true,
|
|
676
677
|
};
|
|
677
678
|
}
|
|
679
|
+
getEngineTurnSettings() {
|
|
680
|
+
const configured = this.settings.engineTurns;
|
|
681
|
+
const limit = (value, fallback) => typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : fallback;
|
|
682
|
+
return {
|
|
683
|
+
maxPerUserInput: limit(configured?.maxPerUserInput, MAX_ENGINE_TURNS_PER_USER_INPUT),
|
|
684
|
+
maxToolFreePerMinute: limit(configured?.maxToolFreePerMinute, MAX_TOOL_FREE_ENGINE_TURNS_PER_WINDOW),
|
|
685
|
+
};
|
|
686
|
+
}
|
|
678
687
|
getTodoFirstTurnPlan() {
|
|
679
688
|
const configured = this.settings.todo?.firstTurnPlan;
|
|
680
689
|
return configured === "remind" || configured === "off" ? configured : "force";
|
|
@@ -3249,7 +3249,7 @@ export class InteractiveMode {
|
|
|
3249
3249
|
this.showStatus("The user dismissed the question.");
|
|
3250
3250
|
// Ordinary cancellation/abort stays silent in the builtin. Only this
|
|
3251
3251
|
// explicit command acknowledges dismissal, including on host bridges.
|
|
3252
|
-
await this.session.sendUserMessage(formatUserMessage(response, state.request.requestId, state.request.questions), {
|
|
3252
|
+
await this.session.sendUserMessage(formatUserMessage(response, state.request.requestId, state.request.questions, state.request.required === true), {
|
|
3253
3253
|
deliverAs: this.session.isStreaming ? "steer" : "followUp",
|
|
3254
3254
|
});
|
|
3255
3255
|
return;
|
package/docs/settings.md
CHANGED
|
@@ -528,6 +528,15 @@ await tool.monitor({ description: "build", command: "bun run build", filter: "^d
|
|
|
528
528
|
|
|
529
529
|
This is the default and has no setting. Tools may declare `exposure: "eval"` to join this policy; `bash`, `powershell` and `grep` use that declaration. They remain registered and discoverable through `tool_schema` inside eval. Hooks and permission checks apply unchanged to calls made this way, and the prompt surfaces that document these tools render the `tool.<name>(` form to match. If the model attempts a direct call anyway, the call returns a hint naming the eval form instead of executing the tool. When the `eval` tool is unavailable (codemode not loaded, or a child agent whose allowlist omits it), the policy stays inert and otherwise enabled tools remain directly callable, so shell, text search, workflow and monitor access is never lost.
|
|
530
530
|
|
|
531
|
+
### Automatic Turns
|
|
532
|
+
|
|
533
|
+
| Setting | Type | Default | Description |
|
|
534
|
+
|---------|------|---------|-------------|
|
|
535
|
+
| `engineTurns.maxPerUserInput` | number | `150` | Turns the agent may start on its own (stream-rule nudges, goal continuations, other extension follow-ups) after one user message before it pauses; `0` turns the limit off |
|
|
536
|
+
| `engineTurns.maxToolFreePerMinute` | number | `12` | Turns started on its own within 60 s that called no tool before it pauses; `0` turns the limit off |
|
|
537
|
+
|
|
538
|
+
When a limit is reached the session pauses with a notice instead of starting another turn; any message you send continues it, because only turns since your last message count.
|
|
539
|
+
|
|
531
540
|
### Ask User
|
|
532
541
|
|
|
533
542
|
| Setting | Type | Default | Description |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/senpi",
|
|
3
|
-
"version": "2026.10.10-
|
|
3
|
+
"version": "2026.10.10-9",
|
|
4
4
|
"description": "Coding agent CLI with read, bash, edit, write tools and session management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"piConfig": {
|
|
@@ -57,9 +57,9 @@
|
|
|
57
57
|
},
|
|
58
58
|
"dependencies": {
|
|
59
59
|
"@earendil-works/chord": "0.99.1",
|
|
60
|
-
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.10.10-
|
|
61
|
-
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.10-
|
|
62
|
-
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.10.10-
|
|
60
|
+
"@earendil-works/pi-agent-core": "npm:@code-yeongyu/senpi-agent-core@2026.10.10-9",
|
|
61
|
+
"@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.10-9",
|
|
62
|
+
"@earendil-works/pi-tui": "npm:@code-yeongyu/senpi-tui@2026.10.10-9",
|
|
63
63
|
"@silvia-odwyer/photon-node": "0.3.4",
|
|
64
64
|
"chalk": "6.0.0",
|
|
65
65
|
"cross-spawn": "7.0.6",
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"yaml": "2.9.1",
|
|
79
79
|
"@anthropic-ai/claude-agent-sdk": "0.3.292",
|
|
80
80
|
"@anthropic-ai/sdk": "0.127.0",
|
|
81
|
-
"@code-yeongyu/senpi-codemode": "2026.10.10-
|
|
82
|
-
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.10.10-
|
|
81
|
+
"@code-yeongyu/senpi-codemode": "2026.10.10-9",
|
|
82
|
+
"@earendil-works/pi-pty": "npm:@code-yeongyu/senpi-pty@2026.10.10-9",
|
|
83
83
|
"@modelcontextprotocol/sdk": "1.32.1",
|
|
84
84
|
"@mozilla/readability": "0.6.0",
|
|
85
85
|
"linkedom": "0.18.13",
|