@raidiant/notifai 11.0.6 → 11.2.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/CHANGELOG.md +49 -0
- package/README.md +6 -0
- package/dist/agent-update-notice.d.ts +7 -0
- package/dist/agent-update-notice.js +77 -0
- package/dist/agent-update-notice.js.map +1 -0
- package/dist/cli-release.d.ts +3 -3
- package/dist/cli-release.js +12 -16
- package/dist/cli-release.js.map +1 -1
- package/dist/codex-wake.d.ts +44 -63
- package/dist/codex-wake.js +71 -174
- package/dist/codex-wake.js.map +1 -1
- package/dist/commands-ask.js +3 -1
- package/dist/commands-ask.js.map +1 -1
- package/dist/commands-close.js +28 -14
- package/dist/commands-close.js.map +1 -1
- package/dist/commands-core.d.ts +1 -1
- package/dist/commands-doctor.js +36 -19
- package/dist/commands-doctor.js.map +1 -1
- package/dist/commands-guidance.d.ts +1 -1
- package/dist/commands-guidance.js +15 -2
- package/dist/commands-guidance.js.map +1 -1
- package/dist/commands-hook-install.js +146 -54
- package/dist/commands-hook-install.js.map +1 -1
- package/dist/commands-hook-run.js +21 -13
- package/dist/commands-hook-run.js.map +1 -1
- package/dist/commands-hook-shape.js +3 -2
- package/dist/commands-hook-shape.js.map +1 -1
- package/dist/commands-update-check.d.ts +6 -0
- package/dist/commands-update-check.js +86 -0
- package/dist/commands-update-check.js.map +1 -0
- package/dist/commands-update-skill.d.ts +5 -0
- package/dist/commands-update-skill.js +36 -0
- package/dist/commands-update-skill.js.map +1 -0
- package/dist/commands-update.js +29 -1
- package/dist/commands-update.js.map +1 -1
- package/dist/commands.d.ts +2 -0
- package/dist/commands.js +2 -0
- package/dist/commands.js.map +1 -1
- package/dist/credentials.js +7 -4
- package/dist/credentials.js.map +1 -1
- package/dist/harnesses.d.ts +1 -1
- package/dist/harnesses.js +2 -2
- package/dist/harnesses.js.map +1 -1
- package/dist/hook-adapter.d.ts +7 -1
- package/dist/hook-adapter.js +36 -3
- package/dist/hook-adapter.js.map +1 -1
- package/dist/hook-events.d.ts +69 -2
- package/dist/hook-events.js +75 -13
- package/dist/hook-events.js.map +1 -1
- package/dist/hook-lifecycle.js +44 -15
- package/dist/hook-lifecycle.js.map +1 -1
- package/dist/hook-question-retirement.d.ts +9 -0
- package/dist/hook-question-retirement.js +38 -3
- package/dist/hook-question-retirement.js.map +1 -1
- package/dist/hook-question-state.d.ts +14 -5
- package/dist/hook-question-state.js +55 -24
- package/dist/hook-question-state.js.map +1 -1
- package/dist/hook-types.d.ts +6 -0
- package/dist/install-hooks.d.ts +70 -12
- package/dist/install-hooks.js +352 -198
- package/dist/install-hooks.js.map +1 -1
- package/dist/native-skills.d.ts +2 -0
- package/dist/native-skills.js +3 -1
- package/dist/native-skills.js.map +1 -1
- package/dist/openclaw-plugin.d.ts +0 -1
- package/dist/openclaw-plugin.js +0 -7
- package/dist/openclaw-plugin.js.map +1 -1
- package/dist/opencode-plugin.d.ts +9 -0
- package/dist/opencode-plugin.js +19 -2
- package/dist/opencode-plugin.js.map +1 -1
- package/dist/program.d.ts +3 -1
- package/dist/program.js +21 -6
- package/dist/program.js.map +1 -1
- package/dist/readiness.d.ts +9 -1
- package/dist/readiness.js +11 -3
- package/dist/readiness.js.map +1 -1
- package/dist/session-activation.d.ts +2 -2
- package/dist/session-activation.js +8 -7
- package/dist/session-activation.js.map +1 -1
- package/dist/session-labels.js +6 -6
- package/dist/session-labels.js.map +1 -1
- package/dist/skill-source/manifest.json +8 -4
- package/dist/skill-source/notifai/SKILL.md +14 -16
- package/dist/skill-source/notifai/references/harness-setup.md +23 -14
- package/dist/skill-source/notifai/references/updates.md +74 -0
- package/dist/ui/theme.d.ts +1 -1
- package/dist/update-handoff.d.ts +29 -0
- package/dist/update-handoff.js +66 -0
- package/dist/update-handoff.js.map +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
8
8
|
This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html)
|
|
9
9
|
and [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
|
|
10
10
|
|
|
11
|
+
## [11.2.0](https://github.com/Raidiant-io/notifai/compare/v11.1.1...v11.2.0) (2026-09-20)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
* **cli:** offer weekly updates with session-aware guidance ([#175](https://github.com/Raidiant-io/notifai/issues/175)) ([b4e56a2](https://github.com/Raidiant-io/notifai/commit/b4e56a2f45865720a3dc5478268fa726e880393c))
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
### Dependencies
|
|
20
|
+
|
|
21
|
+
* The following workspace dependencies were updated
|
|
22
|
+
* dependencies
|
|
23
|
+
* @raidiant/notifai-protocol bumped from 7.0.2 to 7.0.3
|
|
24
|
+
|
|
25
|
+
## [11.1.1](https://github.com/Raidiant-io/notifai/compare/v11.1.0...v11.1.1) (2026-09-20)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Bug Fixes
|
|
29
|
+
|
|
30
|
+
* **cli:** recover publication after registry processing delays ([#173](https://github.com/Raidiant-io/notifai/issues/173)) ([0ce6e0b](https://github.com/Raidiant-io/notifai/commit/0ce6e0be40e46be42441e0e22600937ef1b8be0a))
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
### Dependencies
|
|
34
|
+
|
|
35
|
+
* The following workspace dependencies were updated
|
|
36
|
+
* dependencies
|
|
37
|
+
* @raidiant/notifai-protocol bumped from 7.0.1 to 7.0.2
|
|
38
|
+
|
|
39
|
+
## [11.1.0](https://github.com/Raidiant-io/notifai/compare/v11.0.6...v11.1.0) (2026-09-20)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
### Features
|
|
43
|
+
|
|
44
|
+
* **cli:** deliver Codex answers through the thread's durable queue ([#169](https://github.com/Raidiant-io/notifai/issues/169)) ([4941c3f](https://github.com/Raidiant-io/notifai/commit/4941c3f60e7b82e679e3a90ca3ef187ec10004a0))
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Bug Fixes
|
|
48
|
+
|
|
49
|
+
* **cli:** avoid slow PowerShell module loading for Windows credentials ([#172](https://github.com/Raidiant-io/notifai/issues/172)) ([cd35b10](https://github.com/Raidiant-io/notifai/commit/cd35b1040ddde59e7360beb2d5ba031e02b04c93))
|
|
50
|
+
* **cli:** make setup and queued-question retirement reliable ([#163](https://github.com/Raidiant-io/notifai/issues/163)) ([e4cee77](https://github.com/Raidiant-io/notifai/commit/e4cee77d2aaaf965544763a23cc0d3c4a636210c))
|
|
51
|
+
* **cli:** preserve harness configuration during setup and cleanup ([#164](https://github.com/Raidiant-io/notifai/issues/164)) ([f8f82e6](https://github.com/Raidiant-io/notifai/commit/f8f82e62241d5ab841130070070a55cf50ae98dd))
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
### Dependencies
|
|
55
|
+
|
|
56
|
+
* The following workspace dependencies were updated
|
|
57
|
+
* dependencies
|
|
58
|
+
* @raidiant/notifai-protocol bumped from 7.0.0 to 7.0.1
|
|
59
|
+
|
|
11
60
|
## [11.0.6](https://github.com/Raidiant-io/notifai/compare/v11.0.5...v11.0.6) (2026-09-06)
|
|
12
61
|
|
|
13
62
|
|
package/README.md
CHANGED
|
@@ -18,6 +18,12 @@ bin, `npx --yes @raidiant/notifai@<version>` is supported. Pin the version.
|
|
|
18
18
|
`hooks install` then writes that same pinned npx invocation into the harness
|
|
19
19
|
adapter. This is slower than a real install and is not the default path.
|
|
20
20
|
|
|
21
|
+
Run `notifai doctor` or `notifai update --check --json` to check for a newer
|
|
22
|
+
CLI and inspect release notes, guidance, and session requirements. Enabled
|
|
23
|
+
Projects give root agents a quiet update offer at most once every seven days
|
|
24
|
+
across the machine. A release does not install itself or restart an Agent
|
|
25
|
+
Session automatically. The package includes its changelog.
|
|
26
|
+
|
|
21
27
|
Use `notifai update` for later global updates. It repairs the installation the
|
|
22
28
|
shell actually selects and keeps the stable hook adapter on that same CLI. It
|
|
23
29
|
fails instead of moving the command to a different PATH slot when it cannot
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** One optional notice per machine-local state directory, across roots and harnesses. */
|
|
2
|
+
export declare function agentUpdateNotice(options: {
|
|
3
|
+
env: NodeJS.ProcessEnv;
|
|
4
|
+
now: number;
|
|
5
|
+
updateCommand: string;
|
|
6
|
+
fetchImpl?: typeof fetch;
|
|
7
|
+
}): Promise<string | undefined>;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { lstatSync, readFileSync } from 'node:fs';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { atomicWriteFileSync } from './atomic-file.js';
|
|
4
|
+
import { stateDir } from './config.js';
|
|
5
|
+
import { withFileLock } from './file-lock.js';
|
|
6
|
+
import { latestPublishedCliVersion, newerPublishedCli, shouldConsultCliRegistry, thisCliVersion } from './cli-release.js';
|
|
7
|
+
import { CLI_UPDATE_AVAILABLE } from './cli-contract.js';
|
|
8
|
+
const CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
9
|
+
const NOTICE_INTERVAL_MS = 7 * CHECK_INTERVAL_MS;
|
|
10
|
+
function readState(file) {
|
|
11
|
+
try {
|
|
12
|
+
const stat = lstatSync(file);
|
|
13
|
+
if (!stat.isFile() || stat.size > 1024)
|
|
14
|
+
throw new Error('invalid update notice state');
|
|
15
|
+
const value = JSON.parse(readFileSync(file, 'utf8'));
|
|
16
|
+
if (typeof value !== 'object' || value === null)
|
|
17
|
+
throw new Error('invalid update notice state');
|
|
18
|
+
const state = value;
|
|
19
|
+
for (const timestamp of [state.checked_at, state.notified_at]) {
|
|
20
|
+
if (timestamp !== undefined && (!Number.isSafeInteger(timestamp) || timestamp < 0)) {
|
|
21
|
+
throw new Error('invalid update notice timestamp');
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return state;
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
if (error.code === 'ENOENT')
|
|
28
|
+
return {};
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function recent(timestamp, now, interval) {
|
|
33
|
+
// A clock rollback must not create another notice.
|
|
34
|
+
return timestamp !== undefined && now - timestamp < interval;
|
|
35
|
+
}
|
|
36
|
+
/** One optional notice per machine-local state directory, across roots and harnesses. */
|
|
37
|
+
export async function agentUpdateNotice(options) {
|
|
38
|
+
if (!shouldConsultCliRegistry({ env: options.env }))
|
|
39
|
+
return undefined;
|
|
40
|
+
const file = path.join(stateDir(options.env), 'cli-update-notice.json');
|
|
41
|
+
const save = (state) => atomicWriteFileSync(file, `${JSON.stringify(state)}\n`);
|
|
42
|
+
try {
|
|
43
|
+
// Claim the lookup before doing network I/O. Another process neither waits
|
|
44
|
+
// for the registry nor emits a duplicate. Only short disk work holds a lock.
|
|
45
|
+
const claimed = withFileLock(`${file}.lock`, () => {
|
|
46
|
+
const state = readState(file);
|
|
47
|
+
if (recent(state.notified_at, options.now, NOTICE_INTERVAL_MS) ||
|
|
48
|
+
recent(state.checked_at, options.now, CHECK_INTERVAL_MS))
|
|
49
|
+
return false;
|
|
50
|
+
save({ ...state, checked_at: options.now });
|
|
51
|
+
return true;
|
|
52
|
+
}, { waitMs: 50 });
|
|
53
|
+
if (!claimed)
|
|
54
|
+
return undefined;
|
|
55
|
+
const latest = await latestPublishedCliVersion(options.fetchImpl, { useCache: false });
|
|
56
|
+
if (newerPublishedCli(thisCliVersion(), latest) === null)
|
|
57
|
+
return undefined;
|
|
58
|
+
const notify = withFileLock(`${file}.lock`, () => {
|
|
59
|
+
const state = readState(file);
|
|
60
|
+
if (recent(state.notified_at, options.now, NOTICE_INTERVAL_MS))
|
|
61
|
+
return false;
|
|
62
|
+
save({ ...state, notified_at: options.now });
|
|
63
|
+
return true;
|
|
64
|
+
}, { waitMs: 50 });
|
|
65
|
+
if (!notify)
|
|
66
|
+
return undefined;
|
|
67
|
+
return `${CLI_UPDATE_AVAILABLE} Run \`notifai update --check --json\`, read the release notes, and briefly offer to perform the update at a natural pause. ` +
|
|
68
|
+
`When authorized, use \`${options.updateCommand}\` and follow the new CLI guidance and session handoff. ` +
|
|
69
|
+
'Follow the User\'s instructions about updating; keep working if deferred. ' +
|
|
70
|
+
'Do not send a Notification Request just for this notice. It appears at most once every seven days on this machine.';
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
// Update discovery must never interrupt lifecycle guidance or routing.
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=agent-update-notice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-update-notice.js","sourceRoot":"","sources":["../src/agent-update-notice.ts"],"names":[],"mappings":"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"}
|
package/dist/cli-release.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export declare function shouldConsultCliRegistry(input: {
|
|
2
|
-
interactive?: boolean;
|
|
3
|
-
json?: boolean;
|
|
4
2
|
env?: NodeJS.ProcessEnv;
|
|
5
3
|
}): boolean;
|
|
6
|
-
export declare function latestPublishedCliVersion(fetchImpl?: typeof fetch
|
|
4
|
+
export declare function latestPublishedCliVersion(fetchImpl?: typeof fetch, options?: {
|
|
5
|
+
useCache?: boolean;
|
|
6
|
+
}): Promise<string | null>;
|
|
7
7
|
export declare function newerPublishedCli(local: string | null, latest: string | null): string | null;
|
|
8
8
|
export declare function thisCliVersion(): string | null;
|
|
9
9
|
export declare function resetLatestPublishedCliVersionForTest(): void;
|
package/dist/cli-release.js
CHANGED
|
@@ -1,28 +1,23 @@
|
|
|
1
1
|
import { packageVersion } from './release.js';
|
|
2
2
|
import { cliDistTagsUrl } from './cli-contract.js';
|
|
3
|
-
import { compareVersions } from './version.js';
|
|
3
|
+
import { compareVersions, isSemVer } from './version.js';
|
|
4
4
|
/**
|
|
5
5
|
* The newest published CLI, read from the registry that publishes it.
|
|
6
6
|
*
|
|
7
7
|
* Which version is newest is a registry fact. Doctor consults it as a
|
|
8
|
-
* best-effort, cached, short-timeout hint
|
|
9
|
-
*
|
|
10
|
-
* support state from the server when they are signed in.
|
|
8
|
+
* best-effort, cached, short-timeout hint in human and structured diagnostics.
|
|
9
|
+
* Automatic lifecycle notices have their own persistent throttle.
|
|
11
10
|
*/
|
|
12
11
|
const DIST_TAGS_URL = cliDistTagsUrl();
|
|
13
12
|
const REQUEST_TIMEOUT_MS = 2_000;
|
|
14
13
|
const CACHE_TTL_MS = 60 * 60 * 1000;
|
|
15
14
|
let cached = null;
|
|
16
15
|
export function shouldConsultCliRegistry(input) {
|
|
17
|
-
if (input.json === true)
|
|
18
|
-
return false;
|
|
19
|
-
if (input.interactive !== true)
|
|
20
|
-
return false;
|
|
21
16
|
const ci = input.env?.['CI'];
|
|
22
17
|
return ci !== '1' && ci !== 'true';
|
|
23
18
|
}
|
|
24
|
-
export async function latestPublishedCliVersion(fetchImpl = fetch) {
|
|
25
|
-
if (cached !== null && Date.now() - cached.at < CACHE_TTL_MS)
|
|
19
|
+
export async function latestPublishedCliVersion(fetchImpl = fetch, options = {}) {
|
|
20
|
+
if (options.useCache !== false && cached !== null && Date.now() - cached.at < CACHE_TTL_MS)
|
|
26
21
|
return cached.value;
|
|
27
22
|
try {
|
|
28
23
|
const response = await fetchImpl(DIST_TAGS_URL, {
|
|
@@ -30,19 +25,20 @@ export async function latestPublishedCliVersion(fetchImpl = fetch) {
|
|
|
30
25
|
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
31
26
|
});
|
|
32
27
|
if (!response.ok)
|
|
33
|
-
return
|
|
28
|
+
return null;
|
|
34
29
|
const body = await response.json();
|
|
35
30
|
if (typeof body !== 'object' || body === null)
|
|
36
|
-
return
|
|
31
|
+
return null;
|
|
37
32
|
const latest = body.latest;
|
|
38
|
-
if (typeof latest !== 'string' ||
|
|
39
|
-
return
|
|
33
|
+
if (typeof latest !== 'string' || !isSemVer(latest)) {
|
|
34
|
+
return null;
|
|
40
35
|
}
|
|
41
|
-
|
|
36
|
+
if (options.useCache !== false)
|
|
37
|
+
cached = { value: latest, at: Date.now() };
|
|
42
38
|
return latest;
|
|
43
39
|
}
|
|
44
40
|
catch {
|
|
45
|
-
return
|
|
41
|
+
return null;
|
|
46
42
|
}
|
|
47
43
|
}
|
|
48
44
|
export function newerPublishedCli(local, latest) {
|
package/dist/cli-release.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-release.js","sourceRoot":"","sources":["../src/cli-release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"cli-release.js","sourceRoot":"","sources":["../src/cli-release.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAClD,OAAO,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAExD;;;;;;GAMG;AACH,MAAM,aAAa,GAAG,cAAc,EAAE,CAAA;AACtC,MAAM,kBAAkB,GAAG,KAAK,CAAA;AAChC,MAAM,YAAY,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA;AAEnC,IAAI,MAAM,GAAgD,IAAI,CAAA;AAE9D,MAAM,UAAU,wBAAwB,CAAC,KAExC;IACC,MAAM,EAAE,GAAG,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAA;IAC5B,OAAO,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,MAAM,CAAA;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,YAA0B,KAAK,EAC/B,UAAkC,EAAE;IAEpC,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK,IAAI,MAAM,KAAK,IAAI,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,EAAE,GAAG,YAAY;QAAE,OAAO,MAAM,CAAC,KAAK,CAAA;IAC/G,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,aAAa,EAAE;YAC9C,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;YACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,kBAAkB,CAAC;SAChD,CAAC,CAAA;QACF,IAAI,CAAC,QAAQ,CAAC,EAAE;YAAE,OAAO,IAAI,CAAA;QAC7B,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC3C,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;QAC1D,MAAM,MAAM,GAAI,IAA6B,CAAC,MAAM,CAAA;QACpD,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;YACpD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,IAAI,OAAO,CAAC,QAAQ,KAAK,KAAK;YAAE,MAAM,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAA;QAC1E,OAAO,MAAM,CAAA;IACf,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAoB,EAAE,MAAqB;IAC3E,IAAI,KAAK,KAAK,IAAI,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAA;IAClD,OAAO,eAAe,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAA;AACnE,CAAC;AAED,MAAM,UAAU,cAAc;IAC5B,OAAO,cAAc,EAAE,CAAA;AACzB,CAAC;AAED,MAAM,UAAU,qCAAqC;IACnD,MAAM,GAAG,IAAI,CAAA;AACf,CAAC"}
|
package/dist/codex-wake.d.ts
CHANGED
|
@@ -1,86 +1,67 @@
|
|
|
1
1
|
import { type EscalationDeliveryRoute } from './hook-types.js';
|
|
2
|
-
/** Codex's per-thread writer lock directory, relative to `$CODEX_HOME`. */
|
|
3
|
-
export declare const CODEX_THREAD_LOCK_DIR = "thread-writer-locks";
|
|
4
|
-
export type CodexWakeObservation =
|
|
5
|
-
/** A live writer owns this thread. Resuming it would create a divergent ghost. */
|
|
6
|
-
{
|
|
7
|
-
state: 'live';
|
|
8
|
-
}
|
|
9
|
-
/** No process holds the thread's writer lock; a cold resume can own it. */
|
|
10
|
-
| {
|
|
11
|
-
state: 'stopped';
|
|
12
|
-
} | {
|
|
13
|
-
state: 'unknown';
|
|
14
|
-
reason: string;
|
|
15
|
-
};
|
|
16
|
-
export interface CodexWakeAdapters {
|
|
17
|
-
/** Non-blocking writer-lock probe. Never holds the lock beyond the probe. */
|
|
18
|
-
probeThreadWriter(lockPath: string): CodexWakeObservation;
|
|
19
|
-
/** Is the harness process that will read this hook's stdout still running? */
|
|
20
|
-
sourceAlive(pid: number): boolean;
|
|
21
|
-
resume(threadId: string, cwd: string, context: string): Promise<void>;
|
|
22
|
-
}
|
|
23
2
|
/**
|
|
24
|
-
* The
|
|
3
|
+
* The per-thread durable inbox `codex queue` writes to, relative to `$CODEX_HOME`.
|
|
25
4
|
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* in-process `codex exec` run (2026-08-12). Because the kernel holds it, a
|
|
30
|
-
* crash, SIGKILL, or reboot releases it instantly, and the leftover file proves
|
|
31
|
-
* nothing: only the lock does. Codex fails closed itself with `-32600` when a
|
|
32
|
-
* second writer contends, but that is the backstop; this is the gate.
|
|
5
|
+
* Named for diagnostics only. Notifai never opens it: the schema is private to
|
|
6
|
+
* Codex, versioned by its own migration table, and the supported writer is the
|
|
7
|
+
* CLI. Reading it here would couple Notifai to an internal shape it does not own.
|
|
33
8
|
*/
|
|
34
|
-
export declare
|
|
35
|
-
export
|
|
36
|
-
|
|
37
|
-
|
|
9
|
+
export declare const CODEX_QUEUE_STORE_FILE = "queue_1.sqlite";
|
|
10
|
+
export interface CodexWakeAdapters {
|
|
11
|
+
/** Write one message into the thread's durable inbox via `codex queue`. */
|
|
12
|
+
queue(threadId: string, cwd: string, context: string): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export type CodexQueueReadiness = {
|
|
38
15
|
state: 'ready';
|
|
39
|
-
|
|
16
|
+
threadId: string;
|
|
40
17
|
} | {
|
|
41
18
|
state: 'unavailable';
|
|
42
19
|
reason: string;
|
|
43
20
|
};
|
|
21
|
+
export declare function codexHome(env: NodeJS.ProcessEnv): string;
|
|
22
|
+
export declare function codexQueueStorePath(env: NodeJS.ProcessEnv): string;
|
|
44
23
|
/**
|
|
45
|
-
* Whether
|
|
46
|
-
* cold-resumed, decided without taking any lock or spawning anything.
|
|
24
|
+
* Whether this Stop hook could queue an answer into its own thread.
|
|
47
25
|
*
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
* held turn.
|
|
26
|
+
* The only precondition the route actually has is an exact thread id: queueing
|
|
27
|
+
* needs no writer lock, no daemon, no socket and no platform syscall, and it
|
|
28
|
+
* succeeds against a live, busy or stopped thread alike. The absence of the
|
|
29
|
+
* queue store is deliberately *not* a blocker — Codex creates it on first
|
|
30
|
+
* write — so this reports readiness, never a store-existence gate.
|
|
54
31
|
*/
|
|
55
|
-
export declare function
|
|
56
|
-
platform: NodeJS.Platform;
|
|
57
|
-
directoryExists: (directory: string) => boolean;
|
|
58
|
-
}): CodexResumeReadiness;
|
|
32
|
+
export declare function inspectCodexQueue(threadId: string | undefined, _env: NodeJS.ProcessEnv): CodexQueueReadiness;
|
|
59
33
|
/**
|
|
60
|
-
* Codex's answer-delivery route: the
|
|
34
|
+
* Codex's answer-delivery route: the thread's own durable inbox.
|
|
35
|
+
*
|
|
36
|
+
* `codex queue --thread <id> --message <text>` is not an IPC call into a live
|
|
37
|
+
* process. It writes one FIFO item into a per-thread inbox in `$CODEX_HOME`,
|
|
38
|
+
* and whichever client owns that thread drains it: a live idle session within
|
|
39
|
+
* seconds, a busy one at its next turn boundary, a stopped one the next time it
|
|
40
|
+
* is opened. The answer arrives as an ordinary user turn, firing
|
|
41
|
+
* `UserPromptSubmit` with the queued text.
|
|
42
|
+
*
|
|
43
|
+
* That is why this route replaced the writer-lock probe rather than joining it.
|
|
44
|
+
* The probe existed so a cold resume could never ghost-write a thread another
|
|
45
|
+
* process owned; queueing cannot ghost-write, because the message is delivered
|
|
46
|
+
* *by* the owner and simply waits when there is none. There is no race to lose,
|
|
47
|
+
* and nothing here depends on a BSD `O_EXLOCK`.
|
|
61
48
|
*
|
|
62
|
-
*
|
|
63
|
-
* invoked this hook is alive it is reading this process's stdout, and
|
|
64
|
-
* `{"decision":"block"}` there creates a real new user turn — no launch
|
|
65
|
-
* ownership, no control plane, no probe required. That path must never depend
|
|
66
|
-
* on the lock probe: printing to a dead pipe cannot ghost-write anything, so
|
|
67
|
-
* an unreadable `$CODEX_HOME` is not a reason to withhold a continuation.
|
|
49
|
+
* Two limits are load-bearing and are honoured here:
|
|
68
50
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
51
|
+
* 1. **Exit 0 is not delivery.** `codex queue` reports the same success against
|
|
52
|
+
* an exited session as a live one, so this route never claims `delivered`.
|
|
53
|
+
* It reports `queued`, and Notifai's own `UserPromptSubmit` hook is what
|
|
54
|
+
* observes actual consumption.
|
|
55
|
+
* 2. **Never queue and cold-resume the same answer.** `codex exec resume <id>
|
|
56
|
+
* "<prompt>"` drains the pending queue *and* runs the prompt, delivering it
|
|
57
|
+
* twice. This module therefore has no resume path at all: the routes must be
|
|
58
|
+
* mutually exclusive per answer, and the simplest way to guarantee that is
|
|
59
|
+
* for only one of them to exist.
|
|
76
60
|
*/
|
|
77
61
|
export declare function codexWakeRoute(options: {
|
|
78
62
|
threadId: string;
|
|
79
63
|
cwd: string;
|
|
80
|
-
sourcePid: number;
|
|
81
64
|
env?: NodeJS.ProcessEnv;
|
|
82
65
|
adapters?: CodexWakeAdapters;
|
|
83
|
-
/** False for a detached recovery owner whose stdout no harness will read. */
|
|
84
|
-
continuationActive?: boolean;
|
|
85
66
|
}): EscalationDeliveryRoute;
|
|
86
67
|
export declare function systemCodexWakeAdapters(env?: NodeJS.ProcessEnv): CodexWakeAdapters;
|