@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
package/README.md
CHANGED
|
@@ -42,10 +42,9 @@ The agent registers the question, ends its turn, and your answer comes
|
|
|
42
42
|
back on its next turn. On iPhone the choices are buttons on the banner
|
|
43
43
|
itself.
|
|
44
44
|
|
|
45
|
-
By default a question
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
turns that off if you would rather always be notified.
|
|
45
|
+
By default a question reaches your devices when the agent turn ends, whether or
|
|
46
|
+
not you are at the keyboard (`ask_grace_seconds = 0`). Set a positive grace
|
|
47
|
+
period for a terminal-only answer window first.
|
|
49
48
|
|
|
50
49
|
For a harness that cannot resume an idle agent turn, `notifai send
|
|
51
50
|
--reply` blocks and waits for the answer instead.
|
|
@@ -61,6 +60,22 @@ is what lets an agent's question reach your phone without the agent
|
|
|
61
60
|
having to cooperate — no question detection, no state in a context window
|
|
62
61
|
that compaction will eat.
|
|
63
62
|
|
|
63
|
+
Every harness definition calls one stable user-level adapter at
|
|
64
|
+
`~/.notifai/bin/hook-adapter`. Node, package manager, CLI version, checkout,
|
|
65
|
+
XDG directories, and notification preferences are resolved behind it, so
|
|
66
|
+
upgrades and configuration changes do not rewrite trusted hook definitions.
|
|
67
|
+
The first migration may require one Codex `/hooks` approval; later repairs keep
|
|
68
|
+
the same identity. Codex's Stop definition omits its timeout so the host default
|
|
69
|
+
remains authoritative; prompt-submit and session-end retain fixed short limits.
|
|
70
|
+
|
|
71
|
+
`notifai doctor` compares Codex trust on a best-effort basis against Codex's
|
|
72
|
+
current persisted representation. Notifai never writes that trust store;
|
|
73
|
+
Codex's `/hooks` review is authoritative if the diagnostic and UI disagree.
|
|
74
|
+
|
|
75
|
+
Uninstall removes only the selected harness definition. It intentionally keeps
|
|
76
|
+
the shared adapter because definitions for other harnesses or projects may
|
|
77
|
+
still invoke it and cannot all be discovered from one working directory.
|
|
78
|
+
|
|
64
79
|
## Checking it works
|
|
65
80
|
|
|
66
81
|
```sh
|
package/dist/atomic-file.d.ts
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
export interface AtomicWriteOptions {
|
|
2
2
|
/** Mode for a newly created file. Existing regular files keep their mode. */
|
|
3
3
|
mode?: number;
|
|
4
|
+
/** False when a managed executable must keep the requested mode on repair. */
|
|
5
|
+
preserveMode?: boolean;
|
|
6
|
+
/** Reject a target owned by another user instead of replacing it. */
|
|
7
|
+
requireCurrentUserOwner?: boolean;
|
|
4
8
|
}
|
|
5
9
|
/**
|
|
6
10
|
* Replace one regular file without exposing a truncated intermediate state.
|
package/dist/atomic-file.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { randomBytes } from 'node:crypto';
|
|
2
|
-
import { closeSync, fsyncSync, lstatSync, mkdirSync, openSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
2
|
+
import { chmodSync, closeSync, fsyncSync, lstatSync, mkdirSync, openSync, renameSync, unlinkSync, writeFileSync, } from 'node:fs';
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
/**
|
|
5
5
|
* Replace one regular file without exposing a truncated intermediate state.
|
|
@@ -9,16 +9,21 @@ import path from 'node:path';
|
|
|
9
9
|
* symlink target is refused instead of silently writing through it.
|
|
10
10
|
*/
|
|
11
11
|
export function atomicWriteFileSync(file, contents, options = {}) {
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
12
|
+
const directory = path.dirname(file);
|
|
13
|
+
mkdirSync(directory, { recursive: true });
|
|
14
|
+
const parent = safeDirectory(directory, options.requireCurrentUserOwner ?? false);
|
|
15
|
+
const target = targetMetadata(file, options.mode ?? 0o600, options.preserveMode ?? true, options.requireCurrentUserOwner ?? false);
|
|
16
|
+
const temp = path.join(directory, `.${path.basename(file)}.notifai-${process.pid}-${randomBytes(6).toString('hex')}.tmp`);
|
|
15
17
|
let handle;
|
|
16
18
|
try {
|
|
17
|
-
handle = openSync(temp, 'wx', mode);
|
|
19
|
+
handle = openSync(temp, 'wx', target.mode);
|
|
18
20
|
writeFileSync(handle, contents);
|
|
19
21
|
fsyncSync(handle);
|
|
20
22
|
closeSync(handle);
|
|
21
23
|
handle = undefined;
|
|
24
|
+
chmodSync(temp, target.mode);
|
|
25
|
+
assertSameDirectory(directory, parent);
|
|
26
|
+
assertUnchangedTarget(file, target);
|
|
22
27
|
renameSync(temp, file);
|
|
23
28
|
}
|
|
24
29
|
catch (err) {
|
|
@@ -33,15 +38,15 @@ export function atomicWriteFileSync(file, contents, options = {}) {
|
|
|
33
38
|
throw err;
|
|
34
39
|
}
|
|
35
40
|
}
|
|
36
|
-
|
|
37
|
-
function targetMode(file, fallback) {
|
|
41
|
+
function targetMetadata(file, fallback, preserveMode, requireCurrentUserOwner) {
|
|
38
42
|
let stat;
|
|
39
43
|
try {
|
|
40
44
|
stat = lstatSync(file);
|
|
41
45
|
}
|
|
42
46
|
catch (err) {
|
|
43
|
-
if (err.code === 'ENOENT')
|
|
44
|
-
return fallback;
|
|
47
|
+
if (err.code === 'ENOENT') {
|
|
48
|
+
return { mode: fallback, identity: null };
|
|
49
|
+
}
|
|
45
50
|
throw err;
|
|
46
51
|
}
|
|
47
52
|
if (stat.isSymbolicLink()) {
|
|
@@ -50,6 +55,51 @@ function targetMode(file, fallback) {
|
|
|
50
55
|
}
|
|
51
56
|
if (!stat.isFile())
|
|
52
57
|
throw new Error(`${file} is not a regular file; refusing to replace it.`);
|
|
53
|
-
|
|
58
|
+
if (requireCurrentUserOwner)
|
|
59
|
+
assertCurrentUserOwns(file, stat.uid);
|
|
60
|
+
return {
|
|
61
|
+
mode: preserveMode ? stat.mode & 0o777 : fallback,
|
|
62
|
+
identity: { dev: stat.dev, ino: stat.ino },
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function assertUnchangedTarget(file, target) {
|
|
66
|
+
let current;
|
|
67
|
+
try {
|
|
68
|
+
current = lstatSync(file);
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
if (err.code === 'ENOENT' && target.identity === null)
|
|
72
|
+
return;
|
|
73
|
+
throw new Error(`${file} changed during the atomic write; refusing to replace it.`);
|
|
74
|
+
}
|
|
75
|
+
if (target.identity === null ||
|
|
76
|
+
current.dev !== target.identity.dev ||
|
|
77
|
+
current.ino !== target.identity.ino) {
|
|
78
|
+
throw new Error(`${file} changed during the atomic write; refusing to replace it.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function safeDirectory(directory, requireCurrentUserOwner) {
|
|
82
|
+
const stat = lstatSync(directory);
|
|
83
|
+
if (stat.isSymbolicLink() || !stat.isDirectory()) {
|
|
84
|
+
throw new Error(`${directory} is not a regular directory; refusing to write inside it.`);
|
|
85
|
+
}
|
|
86
|
+
if (requireCurrentUserOwner)
|
|
87
|
+
assertCurrentUserOwns(directory, stat.uid);
|
|
88
|
+
return { dev: stat.dev, ino: stat.ino };
|
|
89
|
+
}
|
|
90
|
+
function assertSameDirectory(directory, expected) {
|
|
91
|
+
const current = lstatSync(directory);
|
|
92
|
+
if (current.isSymbolicLink() ||
|
|
93
|
+
!current.isDirectory() ||
|
|
94
|
+
current.dev !== expected.dev ||
|
|
95
|
+
current.ino !== expected.ino) {
|
|
96
|
+
throw new Error(`${directory} changed during the write; refusing to publish the file.`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function assertCurrentUserOwns(file, owner) {
|
|
100
|
+
const uid = typeof process.getuid === 'function' ? process.getuid() : undefined;
|
|
101
|
+
if (uid !== undefined && owner !== uid) {
|
|
102
|
+
throw new Error(`${file} is owned by uid ${owner}, not the current user; refusing to replace it.`);
|
|
103
|
+
}
|
|
54
104
|
}
|
|
55
105
|
//# sourceMappingURL=atomic-file.js.map
|
package/dist/atomic-file.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../src/atomic-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAA;AAChB,OAAO,IAAI,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"atomic-file.js","sourceRoot":"","sources":["../src/atomic-file.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,EACL,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,UAAU,EACV,UAAU,EACV,aAAa,GACd,MAAM,SAAS,CAAA;AAChB,OAAO,IAAI,MAAM,WAAW,CAAA;AAW5B;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAAY,EACZ,QAAgB,EAChB,UAA8B,EAAE;IAEhC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IACpC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IACzC,MAAM,MAAM,GAAG,aAAa,CAAC,SAAS,EAAE,OAAO,CAAC,uBAAuB,IAAI,KAAK,CAAC,CAAA;IACjF,MAAM,MAAM,GAAG,cAAc,CAC3B,IAAI,EACJ,OAAO,CAAC,IAAI,IAAI,KAAK,EACrB,OAAO,CAAC,YAAY,IAAI,IAAI,EAC5B,OAAO,CAAC,uBAAuB,IAAI,KAAK,CACzC,CAAA;IACD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CACpB,SAAS,EACT,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,OAAO,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CACvF,CAAA;IACD,IAAI,MAA0B,CAAA;IAC9B,IAAI,CAAC;QACH,MAAM,GAAG,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QAC1C,aAAa,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAC/B,SAAS,CAAC,MAAM,CAAC,CAAA;QACjB,SAAS,CAAC,MAAM,CAAC,CAAA;QACjB,MAAM,GAAG,SAAS,CAAA;QAClB,SAAS,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAA;QAC5B,mBAAmB,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QACtC,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;QACnC,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IACxB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,MAAM,KAAK,SAAS;YAAE,SAAS,CAAC,MAAM,CAAC,CAAA;QAC3C,IAAI,CAAC;YACH,UAAU,CAAC,IAAI,CAAC,CAAA;QAClB,CAAC;QAAC,MAAM,CAAC;YACP,mEAAmE;QACrE,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;AACH,CAAC;AAQD,SAAS,cAAc,CACrB,IAAY,EACZ,QAAgB,EAChB,YAAqB,EACrB,uBAAgC;IAEhC,IAAI,IAAI,CAAA;IACR,IAAI,CAAC;QACH,IAAI,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAA;QAC3C,CAAC;QACD,MAAM,GAAG,CAAA;IACX,CAAC;IACD,IAAI,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;QAC1B,MAAM,IAAI,KAAK,CACb,GAAG,IAAI,+EAA+E;YACpF,qCAAqC,CACxC,CAAA;IACH,CAAC;IACD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,iDAAiD,CAAC,CAAA;IAC7F,IAAI,uBAAuB;QAAE,qBAAqB,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IAClE,OAAO;QACL,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ;QACjD,QAAQ,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE;KAC3C,CAAA;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY,EAAE,MAAsB;IACjE,IAAI,OAAO,CAAA;IACX,IAAI,CAAC;QACH,OAAO,GAAG,SAAS,CAAC,IAAI,CAAC,CAAA;IAC3B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,IAAI;YAAE,OAAM;QACxF,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,2DAA2D,CAAC,CAAA;IACrF,CAAC;IACD,IACE,MAAM,CAAC,QAAQ,KAAK,IAAI;QACxB,OAAO,CAAC,GAAG,KAAK,MAAM,CAAC,QAAQ,CAAC,GAAG;QACnC,OAAO,CAAC,GAAG,KAAK,MAAM,CAAC,QAAQ,CAAC,GAAG,EACnC,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,2DAA2D,CAAC,CAAA;IACrF,CAAC;AACH,CAAC;AAED,SAAS,aAAa,CACpB,SAAiB,EACjB,uBAAgC;IAEhC,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IACjC,IAAI,IAAI,CAAC,cAAc,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,2DAA2D,CAAC,CAAA;IAC1F,CAAC;IACD,IAAI,uBAAuB;QAAE,qBAAqB,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,CAAC,CAAA;IACvE,OAAO,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAA;AACzC,CAAC;AAED,SAAS,mBAAmB,CAAC,SAAiB,EAAE,QAAsC;IACpF,MAAM,OAAO,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IACpC,IACE,OAAO,CAAC,cAAc,EAAE;QACxB,CAAC,OAAO,CAAC,WAAW,EAAE;QACtB,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,GAAG;QAC5B,OAAO,CAAC,GAAG,KAAK,QAAQ,CAAC,GAAG,EAC5B,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,GAAG,SAAS,0DAA0D,CAAC,CAAA;IACzF,CAAC;AACH,CAAC;AAED,SAAS,qBAAqB,CAAC,IAAY,EAAE,KAAa;IACxD,MAAM,GAAG,GAAG,OAAO,OAAO,CAAC,MAAM,KAAK,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAC/E,IAAI,GAAG,KAAK,SAAS,IAAI,KAAK,KAAK,GAAG,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,oBAAoB,KAAK,iDAAiD,CAAC,CAAA;IACpG,CAAC;AACH,CAAC"}
|
package/dist/client.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AccountAccessResponse, BeginPairingResponse, CapabilityDocument, CreateMediaUploadRequestT, CreateMediaUploadResponse, EvidenceSnapshot, ListDevicesResponse, ListRepliesResponse, Platform, PollPairingResponse, SubmissionReceipt, SubmitNotificationRequestT } from '@raidiant/notifai-protocol';
|
|
2
|
+
import type { Logger } from './logging.js';
|
|
2
3
|
export declare class ApiCallError extends Error {
|
|
3
4
|
status: number;
|
|
4
5
|
code: string;
|
|
@@ -8,6 +9,13 @@ export declare class ApiCallError extends Error {
|
|
|
8
9
|
}
|
|
9
10
|
export declare class NetworkError extends Error {
|
|
10
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Whether a replies-poll failure is temporary while the durable request stays
|
|
14
|
+
* live. Transport faults, throttling, request timeouts, and server failures
|
|
15
|
+
* can recover on a later poll; client errors cannot be repaired by retrying
|
|
16
|
+
* the same authenticated request.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isRetryableReplyPollError(err: unknown): boolean;
|
|
11
19
|
export interface ApiClient {
|
|
12
20
|
beginPairing(body: {
|
|
13
21
|
machine_name: string;
|
|
@@ -24,8 +32,8 @@ export interface ApiClient {
|
|
|
24
32
|
waitSeconds: number;
|
|
25
33
|
afterSeq: number;
|
|
26
34
|
}): Promise<ListRepliesResponse>;
|
|
27
|
-
/** Retire a question
|
|
28
|
-
closeReplies(requestId: string): Promise<
|
|
35
|
+
/** Retire a question and return the replies committed before the close fence. */
|
|
36
|
+
closeReplies(requestId: string): Promise<ListRepliesResponse>;
|
|
29
37
|
createMediaUpload(body: CreateMediaUploadRequestT): Promise<CreateMediaUploadResponse>;
|
|
30
38
|
uploadMedia(grant: CreateMediaUploadResponse, bytes: Uint8Array): Promise<void>;
|
|
31
39
|
health(): Promise<boolean>;
|
|
@@ -37,5 +45,20 @@ export interface ClientOptions {
|
|
|
37
45
|
* whole network path stays inside the budget the harness allows them.
|
|
38
46
|
*/
|
|
39
47
|
timeoutMs?: number;
|
|
48
|
+
/**
|
|
49
|
+
* Absolute wall-clock ceiling for the caller's whole operation. This is
|
|
50
|
+
* intentionally separate from `timeoutMs`: a late long poll must not get a
|
|
51
|
+
* fresh per-request allowance after its owning harness hook is nearly done.
|
|
52
|
+
*/
|
|
53
|
+
deadlineAt?: number;
|
|
54
|
+
/** Test seam for `deadlineAt`; production uses the wall clock. */
|
|
55
|
+
now?: () => number;
|
|
56
|
+
/**
|
|
57
|
+
* Records each call locally. Worth having because the two failures that cost
|
|
58
|
+
* the most time — a server older than this CLI, and a network path that only
|
|
59
|
+
* fails inside a hook — both look identical from outside and are told apart
|
|
60
|
+
* instantly by a status code and a duration.
|
|
61
|
+
*/
|
|
62
|
+
logger?: Pick<Logger, 'debug' | 'error'>;
|
|
40
63
|
}
|
|
41
64
|
export declare function createClient(baseUrl: string, bearer: string | null, options?: ClientOptions): ApiClient;
|
package/dist/client.js
CHANGED
|
@@ -13,6 +13,19 @@ export class ApiCallError extends Error {
|
|
|
13
13
|
}
|
|
14
14
|
export class NetworkError extends Error {
|
|
15
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Whether a replies-poll failure is temporary while the durable request stays
|
|
18
|
+
* live. Transport faults, throttling, request timeouts, and server failures
|
|
19
|
+
* can recover on a later poll; client errors cannot be repaired by retrying
|
|
20
|
+
* the same authenticated request.
|
|
21
|
+
*/
|
|
22
|
+
export function isRetryableReplyPollError(err) {
|
|
23
|
+
if (err instanceof NetworkError)
|
|
24
|
+
return true;
|
|
25
|
+
if (!(err instanceof ApiCallError))
|
|
26
|
+
return false;
|
|
27
|
+
return err.status >= 500 || err.status === 429 || err.status === 408;
|
|
28
|
+
}
|
|
16
29
|
/**
|
|
17
30
|
* A deadline that fired reads as an abort, which says nothing useful on its
|
|
18
31
|
* own. Naming the timeout is what lets someone tell a hung server apart from a
|
|
@@ -30,14 +43,45 @@ const DEFAULT_TIMEOUT_MS = 20_000;
|
|
|
30
43
|
export function createClient(baseUrl, bearer, options = {}) {
|
|
31
44
|
const root = baseUrl.replace(/\/$/, '');
|
|
32
45
|
const budgetMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
46
|
+
const now = options.now ?? Date.now;
|
|
47
|
+
const logger = options.logger;
|
|
33
48
|
async function call(method, apiPath, body,
|
|
34
49
|
/** Seconds the server was asked to hold the connection open. */
|
|
35
50
|
serverWaitSeconds = 0) {
|
|
51
|
+
const startedAt = Date.now();
|
|
52
|
+
try {
|
|
53
|
+
const result = await callOnce(method, apiPath, body, serverWaitSeconds);
|
|
54
|
+
logger?.debug('http.call', {
|
|
55
|
+
method,
|
|
56
|
+
path: apiPath,
|
|
57
|
+
ok: true,
|
|
58
|
+
duration_ms: Date.now() - startedAt,
|
|
59
|
+
});
|
|
60
|
+
return result;
|
|
61
|
+
}
|
|
62
|
+
catch (err) {
|
|
63
|
+
logger?.error('http.call', {
|
|
64
|
+
method,
|
|
65
|
+
path: apiPath,
|
|
66
|
+
ok: false,
|
|
67
|
+
duration_ms: Date.now() - startedAt,
|
|
68
|
+
...(err instanceof ApiCallError
|
|
69
|
+
? { status: err.status, code: err.code, message: err.message, details: err.details }
|
|
70
|
+
: { message: String(err) }),
|
|
71
|
+
});
|
|
72
|
+
throw err;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function callOnce(method, apiPath, body, serverWaitSeconds = 0) {
|
|
36
76
|
// Without this, a server that accepts the connection and then never answers
|
|
37
77
|
// hangs until the harness kills the whole hook — and the reply-poll deadline
|
|
38
78
|
// cannot interrupt an individual fetch. The signal covers the
|
|
39
79
|
// body read too, not just the response headers.
|
|
40
|
-
const
|
|
80
|
+
const requestBudgetMs = budgetMs + serverWaitSeconds * 1000;
|
|
81
|
+
const remainingMs = options.deadlineAt === undefined
|
|
82
|
+
? requestBudgetMs
|
|
83
|
+
: Math.max(1, options.deadlineAt - now());
|
|
84
|
+
const limitMs = Math.max(1, Math.min(requestBudgetMs, remainingMs));
|
|
41
85
|
const signal = AbortSignal.timeout(limitMs);
|
|
42
86
|
let response;
|
|
43
87
|
try {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/commands.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type { CredentialStore } from './credentials.js';
|
|
|
4
4
|
import { type Readiness } from './readiness.js';
|
|
5
5
|
import type { Tone } from './ui/theme.js';
|
|
6
6
|
import { type HookHarness } from './hooks.js';
|
|
7
|
+
import { type Logger } from './logging.js';
|
|
7
8
|
import { type SendFlags } from './send.js';
|
|
8
9
|
import type { NativeSkills, SkillScope } from './native-skills.js';
|
|
9
10
|
export interface CommandIo {
|
|
@@ -47,6 +48,8 @@ export interface CommandDeps {
|
|
|
47
48
|
store: CredentialStore;
|
|
48
49
|
env: NodeJS.ProcessEnv;
|
|
49
50
|
cwd: string;
|
|
51
|
+
/** Test seam; production fixes the hook adapter under os.homedir(). */
|
|
52
|
+
hookAdapterHome?: string;
|
|
50
53
|
/** Test seam; production uses fetch against base_url. */
|
|
51
54
|
clientFactory?: (baseUrl: string, bearer: string | null, options?: ClientOptions) => ApiClient;
|
|
52
55
|
/** Test seam for bounded polling without wall-clock sleeps. */
|
|
@@ -57,7 +60,14 @@ export interface CommandDeps {
|
|
|
57
60
|
idleSeconds?: () => number | null;
|
|
58
61
|
/** Test seam and production adapter for the external native skills installer. */
|
|
59
62
|
nativeSkills?: NativeSkills;
|
|
63
|
+
/**
|
|
64
|
+
* The local record of what this invocation did. Optional so a test fake need
|
|
65
|
+
* not carry one; `log(deps)` supplies a logger that records nothing.
|
|
66
|
+
*/
|
|
67
|
+
logger?: Logger;
|
|
60
68
|
}
|
|
69
|
+
/** The invocation's logger, or one that discards everything. */
|
|
70
|
+
export declare function log(deps: CommandDeps): Logger;
|
|
61
71
|
export declare const EXIT: {
|
|
62
72
|
readonly ok: 0;
|
|
63
73
|
readonly failed: 1;
|
|
@@ -147,6 +157,8 @@ export declare function statusCommand(deps: CommandDeps, requestId: string, flag
|
|
|
147
157
|
}): Promise<number>;
|
|
148
158
|
export declare const HOOK_EVENTS: readonly ["user-prompt-submit", "stop", "session-end"];
|
|
149
159
|
export type HookEvent = (typeof HOOK_EVENTS)[number];
|
|
160
|
+
/** SessionEnd cleanup must precede every diagnostic that can wait on a file lock. */
|
|
161
|
+
export declare function hookDefersDiagnosticsUntilAfterCleanup(event: unknown): event is 'session-end';
|
|
150
162
|
/**
|
|
151
163
|
* Runs one harness hook. Contract with every harness: hook JSON arrives on
|
|
152
164
|
* stdin, the decision (if any) goes to stdout, diagnostics go to stderr, and
|
|
@@ -197,9 +209,9 @@ export declare function buildQuestions(flags: AskFlags, question: string | undef
|
|
|
197
209
|
};
|
|
198
210
|
/**
|
|
199
211
|
* Registers a question for turn-end routing under the user's presence config.
|
|
200
|
-
* Returns immediately so the agent can ask in prose and end its turn.
|
|
201
|
-
*
|
|
202
|
-
*
|
|
212
|
+
* Returns immediately so the agent can ask in prose and end its turn. Presence
|
|
213
|
+
* does not block the shipped default; `require_idle = true` intentionally keeps
|
|
214
|
+
* the question local while the user is active.
|
|
203
215
|
*/
|
|
204
216
|
export declare function askCommand(deps: CommandDeps, question: string | undefined, flags: AskFlags): number;
|
|
205
217
|
/** Retire a question so a late answer is rejected rather than silently lost. */
|
|
@@ -221,9 +233,10 @@ export declare function configShowCommand(deps: CommandDeps, flags: {
|
|
|
221
233
|
/**
|
|
222
234
|
* One setting, explained in full.
|
|
223
235
|
*
|
|
224
|
-
* The gap this closes: `config show` prints
|
|
225
|
-
*
|
|
226
|
-
* TypeScript comment, read by everyone except the
|
|
236
|
+
* The gap this closes: `config show` prints a value and provenance but that is
|
|
237
|
+
* not enough to explain the setting's consequences. Every key already had a
|
|
238
|
+
* careful explanation — in a TypeScript comment, read by everyone except the
|
|
239
|
+
* person who needed it.
|
|
227
240
|
*/
|
|
228
241
|
export declare function configExplainCommand(deps: CommandDeps, key: string, flags?: {
|
|
229
242
|
json?: boolean;
|
|
@@ -234,12 +247,48 @@ export declare function configSetCommand(deps: CommandDeps, key: string, rawValu
|
|
|
234
247
|
session?: string;
|
|
235
248
|
yes?: boolean;
|
|
236
249
|
}): Promise<number>;
|
|
250
|
+
type ConfigMutationFlags = {
|
|
251
|
+
project?: boolean;
|
|
252
|
+
local?: boolean;
|
|
253
|
+
session?: string;
|
|
254
|
+
yes?: boolean;
|
|
255
|
+
};
|
|
256
|
+
export declare function configUnsetCommand(deps: CommandDeps, key: string, flags: ConfigMutationFlags): Promise<number>;
|
|
257
|
+
export interface LogsFlags {
|
|
258
|
+
json?: boolean;
|
|
259
|
+
limit?: number;
|
|
260
|
+
all?: boolean;
|
|
261
|
+
since?: string;
|
|
262
|
+
level?: string;
|
|
263
|
+
event?: string[];
|
|
264
|
+
run?: string;
|
|
265
|
+
request?: string;
|
|
266
|
+
session?: string;
|
|
267
|
+
project?: string;
|
|
268
|
+
allProjects?: boolean;
|
|
269
|
+
grep?: string;
|
|
270
|
+
path?: boolean;
|
|
271
|
+
clear?: boolean;
|
|
272
|
+
}
|
|
273
|
+
/** `10m`, `2h`, `1d`, or an ISO 8601 instant. */
|
|
274
|
+
export declare function parseSince(raw: string, now: number): number | null;
|
|
275
|
+
/**
|
|
276
|
+
* What this machine recorded about itself.
|
|
277
|
+
*
|
|
278
|
+
* The retrieval half of the local log, and the half that decides whether the
|
|
279
|
+
* log is worth having. Three things make it usable by an agent rather than
|
|
280
|
+
* merely available to one: the default is bounded and scoped to this project,
|
|
281
|
+
* the filters match the questions actually asked ("that run", "that
|
|
282
|
+
* notification", "just the failures"), and `--json` gives the machine the
|
|
283
|
+
* records untouched on stdout while every word of explanation goes to stderr.
|
|
284
|
+
*/
|
|
285
|
+
export declare function logsCommand(deps: CommandDeps, flags: LogsFlags): number;
|
|
237
286
|
/**
|
|
238
287
|
* Where `npx skills add` fetches the optional agent skill from. In skills CLI
|
|
239
288
|
* 1.5.x, `owner/repo@name` selects a skill; a Git ref belongs after `#`.
|
|
240
289
|
* Keep this immutable and public because the command is printed to users.
|
|
241
290
|
*/
|
|
242
|
-
export declare const SKILLS_SOURCE = "Raidiant-io/notifai#v0.
|
|
291
|
+
export declare const SKILLS_SOURCE = "Raidiant-io/notifai#v0.4.0";
|
|
243
292
|
/** Derive a contract-valid project slug from a directory name. */
|
|
244
293
|
export declare function projectSlugFrom(name: string): string;
|
|
245
294
|
export interface InitFlags {
|