@raidiant/notifai 0.3.0 → 0.5.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 +19 -4
- package/dist/atomic-file.d.ts +4 -0
- package/dist/atomic-file.js +60 -10
- package/dist/atomic-file.js.map +1 -1
- package/dist/client.d.ts +25 -2
- package/dist/client.js +45 -1
- package/dist/client.js.map +1 -1
- package/dist/commands.d.ts +56 -7
- package/dist/commands.js +980 -318
- package/dist/commands.js.map +1 -1
- package/dist/config-schema.d.ts +1 -1
- package/dist/config-schema.js +46 -8
- package/dist/config-schema.js.map +1 -1
- package/dist/config.d.ts +38 -3
- package/dist/config.js +61 -14
- package/dist/config.js.map +1 -1
- package/dist/file-lock.d.ts +26 -0
- package/dist/file-lock.js +268 -0
- package/dist/file-lock.js.map +1 -0
- package/dist/harnesses.d.ts +28 -0
- package/dist/harnesses.js +40 -0
- package/dist/harnesses.js.map +1 -0
- package/dist/hook-adapter.d.ts +27 -0
- package/dist/hook-adapter.js +188 -0
- package/dist/hook-adapter.js.map +1 -0
- package/dist/hook-input.d.ts +10 -0
- package/dist/hook-input.js +64 -0
- package/dist/hook-input.js.map +1 -0
- package/dist/hooks.d.ts +66 -10
- package/dist/hooks.js +751 -276
- package/dist/hooks.js.map +1 -1
- package/dist/install-hooks.d.ts +40 -16
- package/dist/install-hooks.js +217 -73
- package/dist/install-hooks.js.map +1 -1
- package/dist/interactive.d.ts +1 -1
- package/dist/interactive.js +3 -3
- package/dist/interactive.js.map +1 -1
- package/dist/logging.d.ts +142 -0
- package/dist/logging.js +533 -0
- package/dist/logging.js.map +1 -0
- package/dist/main.js +97 -36
- package/dist/main.js.map +1 -1
- package/dist/opencode-plugin.d.ts +7 -7
- package/dist/opencode-plugin.js +12 -13
- package/dist/opencode-plugin.js.map +1 -1
- package/dist/ui/config-view.js +3 -0
- package/dist/ui/config-view.js.map +1 -1
- package/dist/ui/theme.d.ts +1 -1
- package/package.json +3 -2
- package/src/atomic-file.ts +86 -7
- package/src/claude-wake.test.ts +320 -0
- package/src/claude-wake.ts +489 -0
- package/src/client.test.ts +12 -0
- package/src/client.ts +72 -4
- package/src/codex-wake.test.ts +253 -0
- package/src/codex-wake.ts +288 -0
- package/src/commands.test.ts +1261 -77
- package/src/commands.ts +1482 -375
- package/src/config-schema.test.ts +3 -3
- package/src/config-schema.ts +57 -44
- package/src/config.test.ts +22 -16
- package/src/config.ts +81 -66
- package/src/file-lock-process-worker.test.ts +64 -0
- package/src/file-lock.test.ts +279 -0
- package/src/file-lock.ts +318 -0
- package/src/harnesses.test.ts +34 -0
- package/src/harnesses.ts +57 -0
- package/src/hook-adapter.test.ts +187 -0
- package/src/hook-adapter.ts +212 -0
- package/src/hook-input.test.ts +39 -0
- package/src/hook-input.ts +72 -0
- package/src/hooks.test.ts +1985 -417
- package/src/hooks.ts +1338 -461
- package/src/install-hooks.test.ts +131 -41
- package/src/install-hooks.ts +284 -84
- package/src/interactive.ts +3 -8
- package/src/logging-process-worker.test.ts +39 -0
- package/src/logging.test.ts +453 -0
- package/src/logging.ts +639 -0
- package/src/main.ts +113 -32
- package/src/opencode-plugin.ts +15 -16
- package/src/session-end-log-lock-worker.test.ts +35 -0
- package/src/skill.test.ts +34 -0
- package/src/ui/config-view.test.ts +9 -7
- package/src/ui/config-view.ts +3 -0
- package/src/idle.test.ts +0 -32
- package/src/idle.ts +0 -41
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hook-input.js","sourceRoot":"","sources":["../src/hook-input.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import type { LifecycleEndState, QuestionT, ReplyView } from '@raidiant/notifai-protocol';
|
|
2
|
-
import type
|
|
1
|
+
import type { LifecycleEndState, NotificationDraftT, QuestionT, ReplyView } from '@raidiant/notifai-protocol';
|
|
2
|
+
import { type ApiClient } from './client.js';
|
|
3
3
|
import { type CliConfig } from './config.js';
|
|
4
|
+
import type { Logger } from './logging.js';
|
|
5
|
+
import { type Harness } from './harnesses.js';
|
|
4
6
|
/**
|
|
5
7
|
* Harness hook handlers.
|
|
6
8
|
*
|
|
7
9
|
* The supported harnesses expose the same useful lifecycle joints: a turn-end
|
|
8
|
-
* event and an event that fires when the user submits a prompt. Claude Code
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* No question detection or context-window state is needed in either path.
|
|
10
|
+
* event and an event that fires when the user submits a prompt. Claude Code
|
|
11
|
+
* and Codex can continue directly from a turn-end answer. Harnesses without a
|
|
12
|
+
* proven exact-session continuation fail closed at question admission.
|
|
12
13
|
*
|
|
13
14
|
* The load-bearing constraint is that these hooks are synchronous: while one
|
|
14
15
|
* blocks, the harness cannot show its own prompt either. So a hook may only
|
|
@@ -32,6 +33,8 @@ export interface HookEnvelope {
|
|
|
32
33
|
export interface SessionState {
|
|
33
34
|
/** Epoch ms of the user's last prompt in this session — our presence signal. */
|
|
34
35
|
last_prompt_at?: number;
|
|
36
|
+
/** Epoch ms of the last observed Stop hook, distinct from prompt routing. */
|
|
37
|
+
last_stop_at?: number;
|
|
35
38
|
/**
|
|
36
39
|
* Questions registered by `notifai ask`, in registration order, each
|
|
37
40
|
* awaiting escalation or its answer. A list, deliberately: registering a
|
|
@@ -59,6 +62,19 @@ export interface SessionState {
|
|
|
59
62
|
answered_at: number;
|
|
60
63
|
count: number;
|
|
61
64
|
};
|
|
65
|
+
/**
|
|
66
|
+
* A phone answer durably captured but not yet acknowledged by a successor
|
|
67
|
+
* hook. It stays here until the next Stop proves the harness processed the
|
|
68
|
+
* continuation; a crash before stdout therefore replays instead of erasing
|
|
69
|
+
* the user's answer.
|
|
70
|
+
*/
|
|
71
|
+
accepted?: AcceptedAnswerDelivery;
|
|
72
|
+
}
|
|
73
|
+
interface AcceptedAnswerDelivery {
|
|
74
|
+
answers: AnsweredPending[];
|
|
75
|
+
remaining: number;
|
|
76
|
+
recorded_at: number;
|
|
77
|
+
continuation_count?: number;
|
|
62
78
|
}
|
|
63
79
|
/** A delivered question awaiting its retirement push. */
|
|
64
80
|
export interface RetiringQuestion {
|
|
@@ -88,6 +104,8 @@ export interface OrphanRetirement extends RetiringQuestion {
|
|
|
88
104
|
enqueued_at: number;
|
|
89
105
|
}
|
|
90
106
|
export interface PendingQuestion {
|
|
107
|
+
/** Stable local identity across racing state writers and submit recovery. */
|
|
108
|
+
question_id?: string;
|
|
91
109
|
/** One-line summary: the single question's text, or the set's first. */
|
|
92
110
|
question: string;
|
|
93
111
|
/**
|
|
@@ -108,6 +126,18 @@ export interface PendingQuestion {
|
|
|
108
126
|
collapse_key?: string;
|
|
109
127
|
/** Exact fanout of the live question; routing config may change afterwards. */
|
|
110
128
|
device_ids?: string[];
|
|
129
|
+
/** Absolute end of the server reply window and its local continuation owner. */
|
|
130
|
+
reply_deadline_at?: number;
|
|
131
|
+
/** Frozen before the first network byte, so an ambiguous submit is replayable. */
|
|
132
|
+
submission?: PendingSubmissionIntent;
|
|
133
|
+
}
|
|
134
|
+
interface PendingSubmissionIntent {
|
|
135
|
+
request_id: string;
|
|
136
|
+
idempotency_key: string;
|
|
137
|
+
collapse_key: string;
|
|
138
|
+
device_ids: string[];
|
|
139
|
+
draft: NotificationDraftT;
|
|
140
|
+
owner_deadline_at: number;
|
|
111
141
|
}
|
|
112
142
|
export type GraceOutcome =
|
|
113
143
|
/** The window elapsed with the user still gone; escalate. */
|
|
@@ -141,6 +171,8 @@ export interface HookOutcome {
|
|
|
141
171
|
stdout?: string;
|
|
142
172
|
/** Diagnostics; harnesses surface hook stderr in the transcript. */
|
|
143
173
|
notes: string[];
|
|
174
|
+
/** Structured lifecycle detail that belongs on hook.end without user text. */
|
|
175
|
+
log?: Record<string, unknown>;
|
|
144
176
|
}
|
|
145
177
|
export declare function readSessionState(sessionId: string, env: NodeJS.ProcessEnv): SessionState;
|
|
146
178
|
export declare function writeSessionState(sessionId: string, env: NodeJS.ProcessEnv, state: SessionState): void;
|
|
@@ -148,7 +180,7 @@ export declare function clearSessionState(sessionId: string, env: NodeJS.Process
|
|
|
148
180
|
export declare function pruneAbandonedSessions(env: NodeJS.ProcessEnv, now?: number, maxAgeMs?: number): number;
|
|
149
181
|
export declare function claimQuestionPush(sessionId: string, env: NodeJS.ProcessEnv, now?: number, beforeStaleReplace?: () => void): boolean;
|
|
150
182
|
export declare function releaseQuestionPush(sessionId: string, env: NodeJS.ProcessEnv): void;
|
|
151
|
-
/** Records
|
|
183
|
+
/** Records every live session working in a directory, for `notifai ask`. */
|
|
152
184
|
export declare function writeProjectSession(cwd: string, env: NodeJS.ProcessEnv, sessionId: string, now: number, harness: HookHarness): void;
|
|
153
185
|
export interface ProjectSessionPointer {
|
|
154
186
|
sessionId: string;
|
|
@@ -161,6 +193,7 @@ export interface ProjectSessionPointer {
|
|
|
161
193
|
*/
|
|
162
194
|
export declare function readProjectSession(cwd: string, env: NodeJS.ProcessEnv, now: number, maxAgeMs?: number): string | null;
|
|
163
195
|
export declare function readProjectSessionPointer(cwd: string, env: NodeJS.ProcessEnv, now: number, maxAgeMs?: number): ProjectSessionPointer | null;
|
|
196
|
+
export declare function readMatchingProjectSessionPointer(cwd: string, env: NodeJS.ProcessEnv, now: number, sessionId: string, harness: HookHarness, maxAgeMs?: number): ProjectSessionPointer | null;
|
|
164
197
|
/**
|
|
165
198
|
* Absent means the user is not at this machine's keyboard.
|
|
166
199
|
*
|
|
@@ -203,10 +236,26 @@ export interface HookContext {
|
|
|
203
236
|
timedOut: boolean;
|
|
204
237
|
degraded?: boolean;
|
|
205
238
|
}>;
|
|
206
|
-
/**
|
|
239
|
+
/** The active harness selects the native continuation output adapter. */
|
|
207
240
|
harness?: HookHarness;
|
|
241
|
+
/**
|
|
242
|
+
* The local record. A hook's decisions are invisible from everywhere else —
|
|
243
|
+
* its stderr belongs to the harness and its usual outcome is to do nothing —
|
|
244
|
+
* so this is the only account of why a question did or did not travel.
|
|
245
|
+
*/
|
|
246
|
+
log?: Logger;
|
|
208
247
|
}
|
|
209
|
-
|
|
248
|
+
/**
|
|
249
|
+
* Record one gate decision.
|
|
250
|
+
*
|
|
251
|
+
* `verdict` is what happened to the question and `reason` is the closed-set
|
|
252
|
+
* name of the rule that decided it, so an agent can ask "why was it held" with
|
|
253
|
+
* a filter rather than by matching on prose. The prose still exists — it is what
|
|
254
|
+
* the user sees in the terminal — but it is free to be rewritten, and a log a
|
|
255
|
+
* filter cannot rely on is a log nobody filters.
|
|
256
|
+
*/
|
|
257
|
+
export type GateReason = 'no-session' | 'no-question' | 'answered' | 'already-asked' | 'continuation-repeat' | 'continuation-limit' | 'notifications-off' | 'user-present' | 'claimed-elsewhere' | 'user-returned' | 'no-devices' | 'proceeding';
|
|
258
|
+
export type HookHarness = Harness;
|
|
210
259
|
/**
|
|
211
260
|
* Everything retirement needs. Narrower than a HookContext on purpose:
|
|
212
261
|
* `notifai ask` supersedes the previous question and it is a plain command with
|
|
@@ -234,6 +283,12 @@ export declare function orphanRetirements(env: NodeJS.ProcessEnv, entries: Retir
|
|
|
234
283
|
* next holder of a client; entries past the TTL are dropped as already dead.
|
|
235
284
|
*/
|
|
236
285
|
export declare function drainOrphanRetirements(ctx: RetireDeps, env: NodeJS.ProcessEnv, now: number): Promise<string[]>;
|
|
286
|
+
/** One answered registered question, with everything the agent needs to read it. */
|
|
287
|
+
interface AnsweredPending {
|
|
288
|
+
pending: PendingQuestion;
|
|
289
|
+
reply: ReplyView;
|
|
290
|
+
replies: ReplyView[];
|
|
291
|
+
}
|
|
237
292
|
/**
|
|
238
293
|
* Records presence and retires anything still asking on companion devices. This is the
|
|
239
294
|
* "answered in the terminal" case from the original design: we cannot tell
|
|
@@ -246,7 +301,7 @@ export declare function handleUserPromptSubmit(ctx: HookContext, envelope: HookE
|
|
|
246
301
|
* `notifai ask`. Guessing from the last assistant message was the alternative
|
|
247
302
|
* and it is not worth it: a false positive here hijacks the terminal.
|
|
248
303
|
*/
|
|
249
|
-
export declare function handleStop(ctx: HookContext, envelope: HookEnvelope): Promise<HookOutcome>;
|
|
304
|
+
export declare function handleStop(ctx: HookContext, envelope: HookEnvelope, processDeadlineAt?: number): Promise<HookOutcome>;
|
|
250
305
|
/**
|
|
251
306
|
* Claude Code gives SessionEnd hooks a 1.5-second shared budget and Codex 1
|
|
252
307
|
* second, so this cannot make a network call. It drops the local marker — but
|
|
@@ -279,3 +334,4 @@ export declare function registerQuestion(sessionId: string, env: NodeJS.ProcessE
|
|
|
279
334
|
/** Parses hook JSON from stdin, tolerating an empty or malformed body. */
|
|
280
335
|
export declare function parseHookInput(raw: string): HookEnvelope;
|
|
281
336
|
export declare function resolveHookConfig(cwd: string, env: NodeJS.ProcessEnv, sessionId: string | undefined): CliConfig;
|
|
337
|
+
export {};
|