@bastani/atomic 0.5.27-0 → 0.5.28-0
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.
|
@@ -133,6 +133,34 @@ export declare function releasePath(claudeSessionId: string): string;
|
|
|
133
133
|
* Safe to call more than once.
|
|
134
134
|
*/
|
|
135
135
|
export declare function releaseClaudeSession(claudeSessionId: string): Promise<void>;
|
|
136
|
+
/**
|
|
137
|
+
* Wait for the Claude session to become idle using `fs.watch` on the
|
|
138
|
+
* `~/.atomic/claude-stop/` marker directory.
|
|
139
|
+
*
|
|
140
|
+
* When Claude finishes a turn, the `atomic _claude-stop-hook` Stop hook writes
|
|
141
|
+
* `~/.atomic/claude-stop/<session_id>`. The write triggers an OS-native
|
|
142
|
+
* `fs.watch` event on the parent directory — far more reliable than polling
|
|
143
|
+
* tmux pane glyphs, which vary between Claude Code versions.
|
|
144
|
+
*
|
|
145
|
+
* This function is strictly about *idle detection*. HIL is detected separately
|
|
146
|
+
* by {@link watchHILMarker}; the Stop hook does not fire while
|
|
147
|
+
* `AskUserQuestion` is pending (the agent loop blocks on deferred tools), so
|
|
148
|
+
* mixing the two would silently miss the HIL window.
|
|
149
|
+
*
|
|
150
|
+
* Algorithm:
|
|
151
|
+
* 1. Attach the directory watcher, then check for the marker file on disk —
|
|
152
|
+
* this closes the race where the Stop hook fires between prompt submission
|
|
153
|
+
* and watcher attach.
|
|
154
|
+
* 2. On any event, re-check the marker file on disk (we intentionally do NOT
|
|
155
|
+
* filter by `event.filename`, because on Linux a write can deliver multiple
|
|
156
|
+
* events with varying filenames and editor tools may race us).
|
|
157
|
+
* 3. Read the session transcript via `getSessionMessages` and slice messages
|
|
158
|
+
* from `transcriptBeforeCount`.
|
|
159
|
+
* 4. Clean up the `fs.watch` watcher on any exit path via AbortController.
|
|
160
|
+
*
|
|
161
|
+
* @param claudeSessionId - Claude's session UUID (used to identify marker file)
|
|
162
|
+
* @param transcriptBeforeCount - number of messages in transcript before this turn
|
|
163
|
+
*/
|
|
136
164
|
/**
|
|
137
165
|
* @internal Exported for unit tests.
|
|
138
166
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/sdk/providers/claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAGL,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,OAAO,IAAI,UAAU,EAC3B,MAAM,gCAAgC,CAAC;AAgCxC;;;;;;GAMG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAWtE;AAqID,MAAM,WAAW,oBAAoB;IACnC,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,sIAAsI;IACtI,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,sEAAsE;IACtE,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAAC,MAAM,CAAC,CAexF;AAsID;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,cAAc,EAAE,GAAG,OAAO,CAUnE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,cAAc,CAClC,eAAe,EAAE,MAAM,EACvB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,EACjC,MAAM,EAAE,WAAW,GAClB,OAAO,CAAC,IAAI,CAAC,CAyCf;AAMD;;;;;;GAMG;AACH,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAE1D;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,MAAM,CAEjC;AAED,0EAA0E;AAC1E,wBAAgB,SAAS,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED,4EAA4E;AAC5E,wBAAgB,WAAW,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,CAE3D;AAiED;;;;GAIG;AACH,wBAAsB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAGjF;
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/sdk/providers/claude.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -121,9 +121,9 @@ export async function claudeStopHookCommand(
|
|
|
121
121
|
// `src/query.ts` → `transition: { reason: 'stop_hook_blocking' }`). In a
|
|
122
122
|
// multi-turn workflow, every follow-up turn after the first is therefore
|
|
123
123
|
// invoked with `stop_hook_active=true`. Returning early here would skip the
|
|
124
|
-
// marker write, leaving `waitForIdle` hanging
|
|
125
|
-
//
|
|
126
|
-
//
|
|
124
|
+
// marker write, leaving `waitForIdle` hanging forever, and would skip the
|
|
125
|
+
// queue poll so the workflow's next `s.session.query(...)` would never
|
|
126
|
+
// reach Claude.
|
|
127
127
|
//
|
|
128
128
|
// Our design doesn't need the generic loop guard: the hook only emits a
|
|
129
129
|
// `block` decision when the workflow runtime has written a prompt to the
|
|
@@ -641,11 +641,6 @@ export async function releaseClaudeSession(claudeSessionId: string): Promise<voi
|
|
|
641
641
|
* @param claudeSessionId - Claude's session UUID (used to identify marker file)
|
|
642
642
|
* @param transcriptBeforeCount - number of messages in transcript before this turn
|
|
643
643
|
*/
|
|
644
|
-
/** Safety timeout so the workflow's next stage still fires if the Stop hook
|
|
645
|
-
* never runs (misconfigured settings, killed Claude process, etc.). 15 min
|
|
646
|
-
* covers any reasonable single-turn run without hanging forever. */
|
|
647
|
-
const IDLE_TIMEOUT_MS = 15 * 60 * 1000;
|
|
648
|
-
|
|
649
644
|
/**
|
|
650
645
|
* @internal Exported for unit tests.
|
|
651
646
|
*/
|
|
@@ -658,7 +653,6 @@ export async function waitForIdle(
|
|
|
658
653
|
const sessionId = claudeSessionId;
|
|
659
654
|
const target = markerPath(sessionId);
|
|
660
655
|
const ac = new AbortController();
|
|
661
|
-
const timeout = setTimeout(() => ac.abort(), IDLE_TIMEOUT_MS);
|
|
662
656
|
|
|
663
657
|
// Process a marker that has appeared on disk. Returns a tuple:
|
|
664
658
|
// [resolved, result] — when resolved=true, waitForIdle should return.
|
|
@@ -743,13 +737,10 @@ export async function waitForIdle(
|
|
|
743
737
|
}
|
|
744
738
|
}
|
|
745
739
|
} catch (e: unknown) {
|
|
746
|
-
// AbortError is expected when we call ac.abort() to stop watching
|
|
747
|
-
// when the safety timeout fires.
|
|
740
|
+
// AbortError is expected when we call ac.abort() to stop watching.
|
|
748
741
|
if (!(e instanceof Error && e.name === "AbortError")) {
|
|
749
742
|
throw e;
|
|
750
743
|
}
|
|
751
|
-
} finally {
|
|
752
|
-
clearTimeout(timeout);
|
|
753
744
|
}
|
|
754
745
|
|
|
755
746
|
return [];
|