agent-afk 5.274.6 → 5.275.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.
package/README.md CHANGED
@@ -22,7 +22,7 @@ Open source. Runs locally. Works with any model provider, including local models
22
22
  ## Quick Start
23
23
 
24
24
  ```bash
25
- npm install -g agent-afk # Node ≥ 22 required
25
+ npm install -g agent-afk # Node ≥ 22.13 required
26
26
  afk login # authenticate (auto-detects Claude Code / Codex creds)
27
27
  afk doctor # verify everything works
28
28
  afk chat "hello" # first real conversation
@@ -30,7 +30,7 @@ afk chat "hello" # first real conversation
30
30
 
31
31
  That's it. You're in.
32
32
 
33
- **Using pnpm?** `pnpm add -g agent-afk` works, but pnpm 10 blocks build scripts by default and skips `postinstall` (with an easy-to-miss warning — see [#2199](https://github.com/griffinwork40/agent-afk/issues/2199)). Run `pnpm approve-builds -g` after install to approve the hook, or use `npm install -g agent-afk` instead. If an `afk daemon` is already running and pnpm skipped the hook, restart it manually with `afk service restart daemon` — on macOS the hook restarts the daemon automatically when it runs, but on Linux you must always run this command after an upgrade even when the hook ran. If you have a manually-started Telegram bot, also run `afk telegram restart`.
33
+ **Using pnpm?** `pnpm add -g agent-afk` works, but pnpm 10 and later block build scripts by default and skips `postinstall` (with an easy-to-miss warning — see [#2199](https://github.com/griffinwork40/agent-afk/issues/2199)). Run `pnpm approve-builds -g` after install to approve the hook, or use `npm install -g agent-afk` instead. If an `afk daemon` is already running and pnpm skipped the hook, restart it manually with `afk service restart daemon` — on macOS the hook restarts the daemon automatically when it runs, but on Linux you must always run this command after an upgrade even when the hook ran. If you have a manually-started Telegram bot, also run `afk telegram restart`.
34
34
 
35
35
  **Try without installing:** `npx agent-afk chat "hello"` runs a one-shot turn with zero global install.
36
36
 
@@ -0,0 +1,5 @@
1
+ import type { AnthropicToolDef } from '../anthropic-direct/types.js';
2
+ export declare function selectBaseSchemas(schemas: AnthropicToolDef[], opts: {
3
+ isSkillDispatch?: boolean;
4
+ isNonInteractive?: boolean;
5
+ }): AnthropicToolDef[];
@@ -13,6 +13,7 @@ import type { ToolPermissionConfig } from './permissions.js';
13
13
  import type { CanUseTool } from '../types/sdk-types.js';
14
14
  import { type GrantSnapshot, type GrantManager } from './grant-manager.js';
15
15
  import type { TraceSink } from '../trace/index.js';
16
+ import { type UserAttention } from './user-yield.js';
16
17
  export { defaultConcurrencyClassifier } from './dispatch-batching.js';
17
18
  export declare const REPEAT_CIRCUIT_BREAKER_THRESHOLD = 8;
18
19
  export { DEFAULT_MAX_CONCURRENT_SAFE_TOOL_CALLS, resolveMaxConcurrentSafeToolCalls };
@@ -40,6 +41,7 @@ export interface SessionToolDispatcherOptions {
40
41
  readOnlyBash?: boolean;
41
42
  maxOutputBytes?: number;
42
43
  spawnedPidRegistry?: SpawnedPidRegistry;
44
+ userAttention?: UserAttention;
43
45
  bashOutputTailReporter?: (toolUseId: string) => (tail: string | undefined) => void;
44
46
  }
45
47
  export declare class SessionToolDispatcher implements ToolDispatcher {
@@ -66,6 +68,7 @@ export declare class SessionToolDispatcher implements ToolDispatcher {
66
68
  private readonly readOnlyBash;
67
69
  private readonly maxOutputBytes;
68
70
  private readonly spawnedPidRegistry;
71
+ private readonly userAttention;
69
72
  private readonly bashOutputTailReporter;
70
73
  private readonly gateState;
71
74
  private readonly repeatFailureGuard;
@@ -8,9 +8,11 @@ export interface PollOptions {
8
8
  poll_interval_ms: number;
9
9
  backoff: 'none' | 'linear' | 'exponential';
10
10
  signal: AbortSignal;
11
+ shouldYield?: () => boolean;
11
12
  }
13
+ export declare const YIELD_CHECK_SLICE_MS = 1000;
12
14
  export interface PollResult {
13
- status: 'succeeded' | 'timed_out' | 'cancelled' | 'failed';
15
+ status: 'succeeded' | 'timed_out' | 'cancelled' | 'failed' | 'yielded_to_user';
14
16
  elapsed_ms: number;
15
17
  attempts: number;
16
18
  result?: WaitResult;
@@ -5,6 +5,7 @@ export type { ToolDispatcher } from '../providers/anthropic-direct/tool-dispatch
5
5
  import type { ToolResult } from '../providers/shared/tool-result.js';
6
6
  import type { TraceSink } from '../trace/index.js';
7
7
  import type { SpawnedPidRegistry } from './handlers/pid-registry.js';
8
+ import type { UserAttention } from './user-yield.js';
8
9
  export interface ToolHandlerContext {
9
10
  cwd?: string;
10
11
  resolveBase?: string;
@@ -17,6 +18,7 @@ export interface ToolHandlerContext {
17
18
  sessionId?: string;
18
19
  spawnedPidRegistry?: SpawnedPidRegistry;
19
20
  onBashOutputTail?: (tail: string | undefined) => void;
21
+ userAttention?: UserAttention;
20
22
  }
21
23
  export type ToolHandler = (input: unknown, signal: AbortSignal, context?: ToolHandlerContext) => Promise<ToolResult>;
22
24
  export type ConcurrencyClassifier = (toolName: string, input?: unknown) => boolean;
@@ -0,0 +1,10 @@
1
+ export interface UserAttention {
2
+ hasPendingUserMessage(): boolean;
3
+ }
4
+ export declare const YIELDABLE_TOOLS: ReadonlySet<string>;
5
+ export declare function isYieldableTool(name: string): boolean;
6
+ export declare function userAttentionFrom(holder: {
7
+ hasPendingUserMessage?: () => boolean;
8
+ } | undefined): UserAttention | undefined;
9
+ export declare function isUserWaiting(attention: UserAttention | undefined): boolean;
10
+ export declare function yieldNotice(retry: string, lead?: string): string;
@@ -31,6 +31,7 @@ export declare function getBuffer(self: ApiHost): {
31
31
  queued: boolean;
32
32
  };
33
33
  export declare function getPendingCount(self: ApiHost): number;
34
+ export declare function hasPendingSubmission(self: ApiHost): boolean;
34
35
  export declare function peekQueuedText(self: ApiHost): QueuedSnapshot | undefined;
35
36
  export declare function reserveQueued(self: ApiHost, snapshot: QueuedSnapshot): void;
36
37
  export declare function releaseQueued(self: ApiHost, snapshot: QueuedSnapshot): void;
@@ -136,6 +136,7 @@ export declare class TerminalCompositor {
136
136
  };
137
137
  getPendingCount(): number;
138
138
  peekQueuedText(): QueuedAccess.QueuedSnapshot | undefined;
139
+ hasPendingSubmission(): boolean;
139
140
  reserveQueued(snapshot: QueuedAccess.QueuedSnapshot): void;
140
141
  releaseQueued(snapshot: QueuedAccess.QueuedSnapshot): void;
141
142
  dropQueued(snapshot: QueuedAccess.QueuedSnapshot): number;
@@ -15,5 +15,6 @@ export interface QueuedSnapshot {
15
15
  export declare function reserveQueued(self: QueuedAccessHost, snapshot: QueuedSnapshot): void;
16
16
  export declare function releaseQueued(self: QueuedAccessHost, snapshot: QueuedSnapshot): void;
17
17
  export declare function isQueuedReserved(self: QueuedAccessHost, payload: SubmissionPayload): boolean;
18
+ export declare function hasPendingSubmission(self: QueuedAccessHost): boolean;
18
19
  export declare function peekQueuedText(self: QueuedAccessHost): QueuedSnapshot | undefined;
19
20
  export declare function dropQueued(self: QueuedAccessHost, snapshot: QueuedSnapshot): number;