hankweave 0.7.2 → 0.7.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/claude-agent-sdk-manager.d.ts +27 -0
- package/dist/codon-runner.d.ts +28 -14
- package/dist/config.d.ts +8 -0
- package/dist/cost-tracker.d.ts +5 -2
- package/dist/error-classification.d.ts +78 -0
- package/dist/index.js +237 -233
- package/dist/index.js.map +20 -18
- package/dist/provider-ids.d.ts +5 -0
- package/dist/shims/codex/VERSION +1 -1
- package/dist/shims/codex/index.js +1 -1
- package/dist/shims/codex/package.json +1 -1
- package/dist/shims/pi/VERSION +1 -1
- package/dist/shims/pi/index.js +77678 -61248
- package/dist/shims/pi/package.json +1 -1
- package/package.json +2 -2
- package/schemas/hank.schema.json +2 -2
|
@@ -9,6 +9,16 @@ import type { Logger } from "./utils.js";
|
|
|
9
9
|
export declare class ClaudeExecutableNotFoundError extends Error {
|
|
10
10
|
constructor(message: string);
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Default stream-inactivity timeout for SDK sessions, in seconds.
|
|
14
|
+
*
|
|
15
|
+
* Unlike the shim binaries (which apply their own internal 120s default), the
|
|
16
|
+
* SDK path historically had NO inactivity bound when shimIdleTimeout was
|
|
17
|
+
* unset — a hung streaming connection would sit silent until the OS killed
|
|
18
|
+
* the socket. SDK messages arrive at message granularity (not per token), so 180s of total silence
|
|
19
|
+
* reliably indicates a dead stream rather than a slow turn.
|
|
20
|
+
*/
|
|
21
|
+
export declare const DEFAULT_SDK_IDLE_TIMEOUT_SECONDS = 180;
|
|
12
22
|
/**
|
|
13
23
|
* Whether lenient ("legacy") Claude auth is enabled via HW_INTERNAL_CLAUDE_LEGACY_AUTH.
|
|
14
24
|
*
|
|
@@ -107,6 +117,14 @@ export declare class ClaudeAgentSDKManager extends BaseProcessManager {
|
|
|
107
117
|
* Write a message to the log file.
|
|
108
118
|
*/
|
|
109
119
|
private writeToLog;
|
|
120
|
+
/**
|
|
121
|
+
* Write a synthetic error result message to the log and wait for the write
|
|
122
|
+
* to flush. Used when the session dies without the SDK emitting a result
|
|
123
|
+
* (e.g. idle timeout): the log parser picks it up so the runtime gets a
|
|
124
|
+
* classifiable failure reason. The flush matters — emitExit() synchronously
|
|
125
|
+
* re-parses the log file, so a buffered write would be invisible to it.
|
|
126
|
+
*/
|
|
127
|
+
private writeSyntheticErrorResult;
|
|
110
128
|
/**
|
|
111
129
|
* Kill the Claude Agent SDK session gracefully.
|
|
112
130
|
* Aborts the query (which triggers SIGTERM on the child via the SDK's abort handler),
|
|
@@ -136,6 +154,15 @@ export declare class ClaudeAgentSDKManager extends BaseProcessManager {
|
|
|
136
154
|
* Get session ID.
|
|
137
155
|
*/
|
|
138
156
|
getSessionId(): string | undefined;
|
|
157
|
+
/**
|
|
158
|
+
* Whether the SDK delivered at least one message (the session id is captured
|
|
159
|
+
* from the first message). This is a synchronous, race-free establishment
|
|
160
|
+
* signal: it is set inside the message loop and survives `cleanup()`, so it is
|
|
161
|
+
* still readable on the error path after a query-promise rejection — unlike the
|
|
162
|
+
* log-parser-fed flag in CodonRunner, which may not have parsed the init line
|
|
163
|
+
* yet when the SDK emits "error".
|
|
164
|
+
*/
|
|
165
|
+
getSessionEstablished(): boolean;
|
|
139
166
|
/**
|
|
140
167
|
* Get synthetic PID (for compatibility with ClaudeProcessManager API).
|
|
141
168
|
* Note: This is not a real process ID since SDK runs in-process.
|
package/dist/codon-runner.d.ts
CHANGED
|
@@ -123,21 +123,10 @@ export type CodonRunnerConfig = CodonRunnerConfigWithoutExtension | CodonRunnerC
|
|
|
123
123
|
* ensuring they are created together, used together, and cleaned up together.
|
|
124
124
|
*/
|
|
125
125
|
/**
|
|
126
|
-
* Failure reasons that prevent extension
|
|
126
|
+
* Failure reasons that prevent extension.
|
|
127
|
+
* Shared with the runtime's failure-policy machinery (see event-schemas.ts).
|
|
127
128
|
*/
|
|
128
|
-
type FailureReason =
|
|
129
|
-
type: "timeout";
|
|
130
|
-
retriable: boolean;
|
|
131
|
-
} | {
|
|
132
|
-
type: "rate-limit";
|
|
133
|
-
retriable: boolean;
|
|
134
|
-
} | {
|
|
135
|
-
type: "api-error";
|
|
136
|
-
retriable: boolean;
|
|
137
|
-
} | {
|
|
138
|
-
type: "unknown";
|
|
139
|
-
retriable: boolean;
|
|
140
|
-
};
|
|
129
|
+
type FailureReason = import("./types/types.js").FailureReason;
|
|
141
130
|
/**
|
|
142
131
|
* Determines whether a codon should extend based on exit conditions.
|
|
143
132
|
* Pure function for unit testing.
|
|
@@ -160,6 +149,7 @@ export declare function shouldExtendCodon(params: {
|
|
|
160
149
|
isInterrupted: boolean;
|
|
161
150
|
failureReason: FailureReason | undefined;
|
|
162
151
|
isBudgetExceeded?: boolean;
|
|
152
|
+
errorResultReceived?: boolean;
|
|
163
153
|
}): boolean;
|
|
164
154
|
export declare class CodonRunner extends TypedEventEmitter<CodonRunnerEvents> {
|
|
165
155
|
private readonly config;
|
|
@@ -172,8 +162,10 @@ export declare class CodonRunner extends TypedEventEmitter<CodonRunnerEvents> {
|
|
|
172
162
|
private successResultReceived;
|
|
173
163
|
private extensionCount;
|
|
174
164
|
private resultMessageReceived;
|
|
165
|
+
private errorResultReceived;
|
|
175
166
|
private failureReason;
|
|
176
167
|
private currentSessionId;
|
|
168
|
+
private systemMessageReceived;
|
|
177
169
|
constructor(config: CodonRunnerConfig);
|
|
178
170
|
/**
|
|
179
171
|
* Check if a model can be run by CodonRunner.
|
|
@@ -182,6 +174,7 @@ export declare class CodonRunner extends TypedEventEmitter<CodonRunnerEvents> {
|
|
|
182
174
|
* - Anthropic models via ClaudeAgentSDKManager
|
|
183
175
|
* - Google models via ShimProcessManager (gemini shim)
|
|
184
176
|
* - OpenAI models via ShimProcessManager (codex shim)
|
|
177
|
+
* - DeepSeek, Pi, and OpenCode models via ShimProcessManager
|
|
185
178
|
*
|
|
186
179
|
* @param model - The ModelInfo to check
|
|
187
180
|
* @returns true if the model can be executed, false otherwise
|
|
@@ -263,6 +256,27 @@ export declare class CodonRunner extends TypedEventEmitter<CodonRunnerEvents> {
|
|
|
263
256
|
* Get the process ID (if running)
|
|
264
257
|
*/
|
|
265
258
|
getPid(): number | undefined;
|
|
259
|
+
/**
|
|
260
|
+
* The classified failure reason for the current attempt, if one was derived
|
|
261
|
+
* from an error result message or a transient mid-stream crash. The runtime
|
|
262
|
+
* adopts this on the exit path when it has no result-message-derived reason of
|
|
263
|
+
* its own, so `onFailure: retry` can act on SDK crashes that never produced a
|
|
264
|
+
* terminal result.
|
|
265
|
+
*/
|
|
266
|
+
getFailureReason(): FailureReason | undefined;
|
|
267
|
+
/**
|
|
268
|
+
* Whether the agent session was established (first system/init message
|
|
269
|
+
* observed) before any failure. Used to gate the retriability of unrecognized
|
|
270
|
+
* crashes: a process that dies before establishing a session, with text we
|
|
271
|
+
* don't recognize as a transient API error, is a local setup failure, not a
|
|
272
|
+
* transient one.
|
|
273
|
+
*
|
|
274
|
+
* ORs the log-parser-fed flag with the SDK manager's synchronous signal: the
|
|
275
|
+
* SDK emits "error" after cleanup() without force-parsing the log, so the
|
|
276
|
+
* parser-fed flag can lag a genuine establishment — `getSessionEstablished()`
|
|
277
|
+
* (derived from the session id captured in the message loop) closes that race.
|
|
278
|
+
*/
|
|
279
|
+
getSystemMessageReceived(): boolean;
|
|
266
280
|
/**
|
|
267
281
|
* Get the prompt frontmatter (if any was parsed from the prompt file)
|
|
268
282
|
*/
|
package/dist/config.d.ts
CHANGED
|
@@ -10,6 +10,7 @@ export declare const TIMEOUTS: {
|
|
|
10
10
|
readonly LOG_PARSER_DELAY_MS: 100;
|
|
11
11
|
readonly CODON_CLEANUP_DELAY_MS: 100;
|
|
12
12
|
readonly SELF_TEST_TIMEOUT_MS: 30000 | 60000;
|
|
13
|
+
readonly SHUTDOWN_WATCHDOG_MS: 30000;
|
|
13
14
|
};
|
|
14
15
|
/** Maximum allowed shimIdleTimeout in seconds */
|
|
15
16
|
export declare const SHIM_IDLE_TIMEOUT_MAX_SECONDS = 1800;
|
|
@@ -40633,6 +40634,13 @@ export interface HankweaveConfig extends Omit<Required<RuntimeConfig>, "model" |
|
|
|
40633
40634
|
isResuming: boolean;
|
|
40634
40635
|
/** How data is linked (symlink or copy) */
|
|
40635
40636
|
linkType: "symlink" | "copy";
|
|
40637
|
+
/**
|
|
40638
|
+
* True when launched with --headless: no interactive TUI/client is driving
|
|
40639
|
+
* the run. Used to decide that a retriable failure under onFailure:"abort"
|
|
40640
|
+
* must fail-and-shutdown rather than park in "stay-active" (which would hang
|
|
40641
|
+
* forever waiting for a client that will never connect).
|
|
40642
|
+
*/
|
|
40643
|
+
headless?: boolean;
|
|
40636
40644
|
/** Array of codon configurations to execute */
|
|
40637
40645
|
codons: CodonConfig[];
|
|
40638
40646
|
/** Path to a replay source directory (for replaying execution from JSONL logs without real LLM calls) */
|
package/dist/cost-tracker.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { LlmProviderRegistry } from "./llm/llm-provider-registry.js";
|
|
2
|
+
import type { ModelInfo } from "./llm/models-dev-schema.js";
|
|
2
3
|
import { TypedEventEmitter } from "./typed-event-emitter.js";
|
|
3
4
|
import type { TokenUsage } from "./types/types.js";
|
|
4
5
|
import type { Logger } from "./utils.js";
|
|
@@ -48,12 +49,14 @@ export interface CostTrackerEvents extends Record<string, unknown[]> {
|
|
|
48
49
|
* Owned by CodonRunner. The runtime subscribes to its events.
|
|
49
50
|
*/
|
|
50
51
|
export declare class CostTracker extends TypedEventEmitter<CostTrackerEvents> {
|
|
51
|
-
private readonly modelId;
|
|
52
52
|
private readonly llmRegistry;
|
|
53
53
|
private readonly logger;
|
|
54
54
|
private runningCost;
|
|
55
55
|
private runningTokens;
|
|
56
|
-
|
|
56
|
+
private readonly executableModelId;
|
|
57
|
+
private readonly pricingModelId;
|
|
58
|
+
constructor(model: ModelInfo | undefined, llmRegistry: LlmProviderRegistry, logger: Logger);
|
|
59
|
+
private static getPricingModelId;
|
|
57
60
|
/**
|
|
58
61
|
* Process usage from an assistant message. Calculates incremental cost,
|
|
59
62
|
* accumulates running totals, and emits costIncremented.
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { FailureReason } from "./types/types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Pure decision core of the runtime's failure policy
|
|
4
|
+
* (HankweaveRuntime.resolveFailurePolicy delegates here; extracted for unit
|
|
5
|
+
* testing, mirroring shouldExtendCodon in codon-runner.ts).
|
|
6
|
+
*
|
|
7
|
+
* - abort: retriable errors leave the server active for manual retry,
|
|
8
|
+
* permanent ones shut the run down.
|
|
9
|
+
* - retry: retriable errors retry until maxAttempts is exhausted; permanent
|
|
10
|
+
* errors shut down immediately.
|
|
11
|
+
* - ignore: always continue to the next codon.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resolveFailureAction(params: {
|
|
14
|
+
onFailure: "abort" | "retry" | "ignore";
|
|
15
|
+
retriable: boolean;
|
|
16
|
+
attempts: number;
|
|
17
|
+
maxAttempts: number;
|
|
18
|
+
}): "shutdown" | "stay-active" | "retry" | "continue";
|
|
19
|
+
/**
|
|
20
|
+
* Classify API error text into a FailureReason with a retriability verdict.
|
|
21
|
+
*
|
|
22
|
+
* This is the single source of truth for deciding whether an API-level error
|
|
23
|
+
* is transient (worth retrying under onFailure: "retry") or permanent.
|
|
24
|
+
* Both the runtime's result-message handling and CodonRunner's extension
|
|
25
|
+
* logic must use this — divergent heuristics in those two places previously
|
|
26
|
+
* caused transient socket drops to abort runs that were configured to retry
|
|
27
|
+
*
|
|
28
|
+
* Classification policy:
|
|
29
|
+
* - Billing/credit/quota and auth errors are permanent: retrying burns
|
|
30
|
+
* attempts on a hopeless request.
|
|
31
|
+
* - Invalid-request (400) errors are permanent: the same request will fail
|
|
32
|
+
* the same way.
|
|
33
|
+
* - Transport faults (socket closed/reset, connection errors), timeouts,
|
|
34
|
+
* rate limits, and server-side errors (5xx, overloaded) are transient.
|
|
35
|
+
* - Unrecognized error text defaults to RETRIABLE: retries are bounded by
|
|
36
|
+
* retryConfig.maxAttempts, so a wrong "retriable" costs one extra attempt,
|
|
37
|
+
* while a wrong "non-retriable" kills the whole run. This default is gated on
|
|
38
|
+
* `opts.sessionEstablished`: when the caller knows no session was ever
|
|
39
|
+
* established (the process failed before its first message), unrecognized text
|
|
40
|
+
* is a local setup failure and is classified NON-retriable instead. The known
|
|
41
|
+
* transient/permanent patterns above are unaffected by the gate.
|
|
42
|
+
*/
|
|
43
|
+
export declare function classifyApiErrorText(text: string, opts?: {
|
|
44
|
+
sessionEstablished?: boolean;
|
|
45
|
+
}): FailureReason;
|
|
46
|
+
/**
|
|
47
|
+
* Synthesize a failure reason for a codon that ended in a FAILED state without
|
|
48
|
+
* any classified reason of its own (no error result message, no transient-crash
|
|
49
|
+
* classification from the runner).
|
|
50
|
+
*
|
|
51
|
+
* This is the single convergence point for every process manager when a process
|
|
52
|
+
* exits without reporting a usable outcome:
|
|
53
|
+
* - An early/pre-init shim exit on an API error returns a non-zero code with no
|
|
54
|
+
* result message (gemini shim.ts:593 `!systemEmitted`; pi index.ts:452;
|
|
55
|
+
* opencode shim.ts:462/486 and binary/arg-resolution failures).
|
|
56
|
+
* - The Claude Agent SDK or any child process can crash without a terminal
|
|
57
|
+
* result.
|
|
58
|
+
*
|
|
59
|
+
* Retriability is gated on session establishment (`sessionEstablished`):
|
|
60
|
+
* - established then exited with no result → plausibly transient, RETRIABLE
|
|
61
|
+
* (bounded by retryConfig.maxAttempts), mirroring classifyApiErrorText's
|
|
62
|
+
* policy for unrecognized errors.
|
|
63
|
+
* - never established (the process exited before its first message) → a local
|
|
64
|
+
* setup/binary/resume-resolution failure that retrying cannot fix →
|
|
65
|
+
* NON-retriable. Defaults to true so callers that don't supply the signal
|
|
66
|
+
* keep the original retriable behavior.
|
|
67
|
+
*
|
|
68
|
+
* Returns undefined (no synthesis — preserve the existing non-retriable default)
|
|
69
|
+
* when the failure is intentional or owned by another mechanism:
|
|
70
|
+
* - force-stop: the user asked to stop; retrying would fight that intent.
|
|
71
|
+
* - context-exceeded: the loop/termination logic owns this outcome, not retry.
|
|
72
|
+
*/
|
|
73
|
+
export declare function synthesizeMissingFailureReason(params: {
|
|
74
|
+
isForceStopping: boolean;
|
|
75
|
+
isContextExceeded: boolean;
|
|
76
|
+
exitCode: number;
|
|
77
|
+
sessionEstablished?: boolean;
|
|
78
|
+
}): FailureReason | undefined;
|