@loicngr/kobo 1.7.15 → 1.7.16
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
CHANGED
|
@@ -4,6 +4,10 @@ All notable changes to Kōbō are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/). Each release is an `## <version>`
|
|
5
5
|
section — the in-app "What's new" dialog reads this file.
|
|
6
6
|
|
|
7
|
+
## 1.7.16
|
|
8
|
+
|
|
9
|
+
- feat(engine): handle user interruptions as clean stops
|
|
10
|
+
|
|
7
11
|
## 1.7.15
|
|
8
12
|
|
|
9
13
|
- docs: document new settings and features
|
|
@@ -154,10 +154,14 @@ export function createClaudeCodeEngine() {
|
|
|
154
154
|
// event-mapper already surfaced an `error` event but the iterator
|
|
155
155
|
// still terminated naturally. Reflect that in the session:ended
|
|
156
156
|
// reason so the orchestrator transitions the workspace to `error`.
|
|
157
|
+
// A user soft-interrupt also drains naturally (the SDK emits
|
|
158
|
+
// `error_during_execution`, which the mapper suppresses) — report
|
|
159
|
+
// it as `killed`, consistent with the catch-block abort path.
|
|
160
|
+
const endReason = userInterrupted ? 'killed' : mapperState.sawErrorResult ? 'error' : 'completed';
|
|
157
161
|
safeEmit({
|
|
158
162
|
kind: 'session:ended',
|
|
159
|
-
reason:
|
|
160
|
-
exitCode:
|
|
163
|
+
reason: endReason,
|
|
164
|
+
exitCode: endReason === 'completed' ? 0 : null,
|
|
161
165
|
});
|
|
162
166
|
}
|
|
163
167
|
catch (err) {
|
|
@@ -212,6 +216,10 @@ export function createClaudeCodeEngine() {
|
|
|
212
216
|
},
|
|
213
217
|
interrupt() {
|
|
214
218
|
userInterrupted = true;
|
|
219
|
+
// The SDK ends an interrupted run by emitting a `result` with
|
|
220
|
+
// subtype `error_during_execution` through the normal iterator —
|
|
221
|
+
// the mapper needs this flag to treat it as a clean stop.
|
|
222
|
+
mapperState.userInterrupted = true;
|
|
215
223
|
const qq = q;
|
|
216
224
|
if (typeof qq.interrupt === 'function') {
|
|
217
225
|
try {
|
|
@@ -83,6 +83,7 @@ export function createMapperState() {
|
|
|
83
83
|
openMessages: new Map(),
|
|
84
84
|
sawErrorResult: false,
|
|
85
85
|
quotaErrorEmitted: false,
|
|
86
|
+
userInterrupted: false,
|
|
86
87
|
};
|
|
87
88
|
}
|
|
88
89
|
/** Known SDK `result` subtypes that indicate the run failed. */
|
|
@@ -290,7 +291,12 @@ export function mapSdkMessage(msg, state) {
|
|
|
290
291
|
// the orchestrator can transition the workspace to `error` instead of
|
|
291
292
|
// `completed`. The flag on `state` lets the engine override the
|
|
292
293
|
// post-loop session:ended reason.
|
|
293
|
-
|
|
294
|
+
// A user soft-interrupt ends the run with `error_during_execution`
|
|
295
|
+
// through this normal iterator path. That is a clean stop, not a
|
|
296
|
+
// failure — skip the error event so the UI shows no red banner and the
|
|
297
|
+
// workspace is not pushed into `error`.
|
|
298
|
+
const isInterruptedStop = state.userInterrupted && subtype === 'error_during_execution';
|
|
299
|
+
if (isErrorResultSubtype(subtype) && !isInterruptedStop) {
|
|
294
300
|
state.sawErrorResult = true;
|
|
295
301
|
const detail = (typeof parsed.error === 'string' && parsed.error) || (typeof parsed.result === 'string' && parsed.result) || '';
|
|
296
302
|
const isQuota = QUOTA_PATTERN.test(detail);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loicngr/kobo",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.16",
|
|
4
4
|
"description": "Kōbō — multi-workspace agent manager for Claude Code. Orchestrates isolated git worktrees with dev servers, Notion integration, and MCP tools.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "GPL-3.0-or-later",
|