oh-my-codex 0.3.9 → 0.4.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 +25 -0
- package/dist/cli/__tests__/doctor-team.test.js +58 -0
- package/dist/cli/__tests__/doctor-team.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +9 -3
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/lifecycle-notifications.test.d.ts +2 -0
- package/dist/cli/__tests__/lifecycle-notifications.test.d.ts.map +1 -0
- package/dist/cli/__tests__/lifecycle-notifications.test.js +48 -0
- package/dist/cli/__tests__/lifecycle-notifications.test.js.map +1 -0
- package/dist/cli/doctor.js +28 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/hooks.d.ts +4 -0
- package/dist/cli/hooks.d.ts.map +1 -0
- package/dist/cli/hooks.js +201 -0
- package/dist/cli/hooks.js.map +1 -0
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +181 -2
- package/dist/cli/index.js.map +1 -1
- package/dist/config/__tests__/models.test.d.ts +2 -0
- package/dist/config/__tests__/models.test.d.ts.map +1 -0
- package/dist/config/__tests__/models.test.js +69 -0
- package/dist/config/__tests__/models.test.js.map +1 -0
- package/dist/config/models.d.ts +24 -0
- package/dist/config/models.d.ts.map +1 -0
- package/dist/config/models.js +53 -0
- package/dist/config/models.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-linked-sync.test.js +6 -0
- package/dist/hooks/__tests__/notify-hook-linked-sync.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +6 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +224 -36
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +4 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js +1 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts +2 -0
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.d.ts.map +1 -0
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js +153 -0
- package/dist/hooks/extensibility/__tests__/example-hook-plugins.test.js.map +1 -0
- package/dist/hooks/extensibility/dispatcher.d.ts +4 -0
- package/dist/hooks/extensibility/dispatcher.d.ts.map +1 -0
- package/dist/hooks/extensibility/dispatcher.js +223 -0
- package/dist/hooks/extensibility/dispatcher.js.map +1 -0
- package/dist/hooks/extensibility/events.d.ts +18 -0
- package/dist/hooks/extensibility/events.d.ts.map +1 -0
- package/dist/hooks/extensibility/events.js +53 -0
- package/dist/hooks/extensibility/events.js.map +1 -0
- package/dist/hooks/extensibility/index.d.ts +6 -0
- package/dist/hooks/extensibility/index.d.ts.map +1 -0
- package/dist/hooks/extensibility/index.js +6 -0
- package/dist/hooks/extensibility/index.js.map +1 -0
- package/dist/hooks/extensibility/loader.d.ts +14 -0
- package/dist/hooks/extensibility/loader.d.ts.map +1 -0
- package/dist/hooks/extensibility/loader.js +102 -0
- package/dist/hooks/extensibility/loader.js.map +1 -0
- package/dist/hooks/extensibility/logging.d.ts +4 -0
- package/dist/hooks/extensibility/logging.d.ts.map +1 -0
- package/dist/hooks/extensibility/logging.js +16 -0
- package/dist/hooks/extensibility/logging.js.map +1 -0
- package/dist/hooks/extensibility/plugin-runner.d.ts +2 -0
- package/dist/hooks/extensibility/plugin-runner.d.ts.map +1 -0
- package/dist/hooks/extensibility/plugin-runner.js +69 -0
- package/dist/hooks/extensibility/plugin-runner.js.map +1 -0
- package/dist/hooks/extensibility/runtime.d.ts +3 -0
- package/dist/hooks/extensibility/runtime.d.ts.map +1 -0
- package/dist/hooks/extensibility/runtime.js +29 -0
- package/dist/hooks/extensibility/runtime.js.map +1 -0
- package/dist/hooks/extensibility/sdk.d.ts +11 -0
- package/dist/hooks/extensibility/sdk.d.ts.map +1 -0
- package/dist/hooks/extensibility/sdk.js +240 -0
- package/dist/hooks/extensibility/sdk.js.map +1 -0
- package/dist/hooks/extensibility/types.d.ts +122 -0
- package/dist/hooks/extensibility/types.d.ts.map +1 -0
- package/dist/hooks/extensibility/types.js +2 -0
- package/dist/hooks/extensibility/types.js.map +1 -0
- package/dist/mcp/__tests__/state-paths.test.js +21 -1
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server-team-tools.test.js +53 -1
- package/dist/mcp/__tests__/state-server-team-tools.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts +1 -0
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +34 -1
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +46 -11
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/notifications/__tests__/config.test.d.ts +2 -0
- package/dist/notifications/__tests__/config.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/config.test.js +186 -0
- package/dist/notifications/__tests__/config.test.js.map +1 -0
- package/dist/notifications/__tests__/dispatcher.test.d.ts +2 -0
- package/dist/notifications/__tests__/dispatcher.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/dispatcher.test.js +202 -0
- package/dist/notifications/__tests__/dispatcher.test.js.map +1 -0
- package/dist/notifications/__tests__/formatter.test.d.ts +2 -0
- package/dist/notifications/__tests__/formatter.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/formatter.test.js +103 -0
- package/dist/notifications/__tests__/formatter.test.js.map +1 -0
- package/dist/notifications/__tests__/notifier.test.d.ts +2 -0
- package/dist/notifications/__tests__/notifier.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/notifier.test.js +104 -0
- package/dist/notifications/__tests__/notifier.test.js.map +1 -0
- package/dist/notifications/__tests__/profiles.test.d.ts +2 -0
- package/dist/notifications/__tests__/profiles.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/profiles.test.js +404 -0
- package/dist/notifications/__tests__/profiles.test.js.map +1 -0
- package/dist/notifications/__tests__/reply-listener.test.d.ts +2 -0
- package/dist/notifications/__tests__/reply-listener.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/reply-listener.test.js +58 -0
- package/dist/notifications/__tests__/reply-listener.test.js.map +1 -0
- package/dist/notifications/__tests__/session-registry.test.d.ts +2 -0
- package/dist/notifications/__tests__/session-registry.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/session-registry.test.js +147 -0
- package/dist/notifications/__tests__/session-registry.test.js.map +1 -0
- package/dist/notifications/__tests__/tmux-detector.test.d.ts +2 -0
- package/dist/notifications/__tests__/tmux-detector.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/tmux-detector.test.js +77 -0
- package/dist/notifications/__tests__/tmux-detector.test.js.map +1 -0
- package/dist/notifications/__tests__/tmux.test.d.ts +2 -0
- package/dist/notifications/__tests__/tmux.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/tmux.test.js +90 -0
- package/dist/notifications/__tests__/tmux.test.js.map +1 -0
- package/dist/notifications/config.d.ts +44 -0
- package/dist/notifications/config.d.ts.map +1 -0
- package/dist/notifications/config.js +407 -0
- package/dist/notifications/config.js.map +1 -0
- package/dist/notifications/dispatcher.d.ts +15 -0
- package/dist/notifications/dispatcher.d.ts.map +1 -0
- package/dist/notifications/dispatcher.js +410 -0
- package/dist/notifications/dispatcher.js.map +1 -0
- package/dist/notifications/formatter.d.ts +14 -0
- package/dist/notifications/formatter.d.ts.map +1 -0
- package/dist/notifications/formatter.js +134 -0
- package/dist/notifications/formatter.js.map +1 -0
- package/dist/notifications/index.d.ts +32 -0
- package/dist/notifications/index.d.ts.map +1 -0
- package/dist/notifications/index.js +93 -0
- package/dist/notifications/index.js.map +1 -0
- package/dist/notifications/reply-listener.d.ts +47 -0
- package/dist/notifications/reply-listener.d.ts.map +1 -0
- package/dist/notifications/reply-listener.js +656 -0
- package/dist/notifications/reply-listener.js.map +1 -0
- package/dist/notifications/session-registry.d.ts +26 -0
- package/dist/notifications/session-registry.d.ts.map +1 -0
- package/dist/notifications/session-registry.js +275 -0
- package/dist/notifications/session-registry.js.map +1 -0
- package/dist/notifications/tmux-detector.d.ts +17 -0
- package/dist/notifications/tmux-detector.d.ts.map +1 -0
- package/dist/notifications/tmux-detector.js +82 -0
- package/dist/notifications/tmux-detector.js.map +1 -0
- package/dist/notifications/tmux.d.ts +28 -0
- package/dist/notifications/tmux.d.ts.map +1 -0
- package/dist/notifications/tmux.js +210 -0
- package/dist/notifications/tmux.js.map +1 -0
- package/dist/notifications/types.d.ts +181 -0
- package/dist/notifications/types.d.ts.map +1 -0
- package/dist/notifications/types.js +9 -0
- package/dist/notifications/types.js.map +1 -0
- package/dist/team/__tests__/runtime.test.js +54 -2
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +30 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +2 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/runtime.d.ts +2 -2
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +19 -12
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/state.d.ts +1 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +5 -0
- package/dist/team/state.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +59 -15
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +4 -0
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/package.json +1 -1
- package/scripts/hook-derived-watcher.js +335 -0
- package/scripts/notify-hook.js +168 -7
- package/scripts/tmux-hook-engine.js +3 -2
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { readFile } from 'node:fs';
|
|
3
|
+
import { access, mkdir, mkdtemp, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
import { describe, it } from 'node:test';
|
|
7
|
+
import { dispatchHookEvent } from '../dispatcher.js';
|
|
8
|
+
import { buildHookEvent } from '../events.js';
|
|
9
|
+
const ALL_EVENTS = [
|
|
10
|
+
'session-start',
|
|
11
|
+
'session-end',
|
|
12
|
+
'session-idle',
|
|
13
|
+
'turn-complete',
|
|
14
|
+
'needs-input',
|
|
15
|
+
'pre-tool-use',
|
|
16
|
+
'post-tool-use',
|
|
17
|
+
];
|
|
18
|
+
const DERIVED_EVENTS = new Set(['needs-input', 'pre-tool-use', 'post-tool-use']);
|
|
19
|
+
function examplePluginSource(expectedEvent) {
|
|
20
|
+
return `const EXPECTED_EVENT = ${JSON.stringify(expectedEvent)};
|
|
21
|
+
|
|
22
|
+
export async function onHookEvent(event, sdk) {
|
|
23
|
+
if (event.event !== EXPECTED_EVENT) return;
|
|
24
|
+
const runId = String((event.context && event.context.run_id) || 'unknown');
|
|
25
|
+
const seenKey = 'seen_count';
|
|
26
|
+
const prev = Number((await sdk.state.read(seenKey)) ?? 0);
|
|
27
|
+
const next = Number.isFinite(prev) ? prev + 1 : 1;
|
|
28
|
+
await sdk.state.write(seenKey, next);
|
|
29
|
+
await sdk.state.write('last_event', event.event);
|
|
30
|
+
await sdk.state.write('last_source', event.source);
|
|
31
|
+
await sdk.state.write('last_run_id', runId);
|
|
32
|
+
await sdk.state.write(\`run:\${runId}\`, { event: event.event, source: event.source, at: event.timestamp });
|
|
33
|
+
await sdk.log.info('example hook fired', {
|
|
34
|
+
expected: EXPECTED_EVENT,
|
|
35
|
+
seen_count: next,
|
|
36
|
+
source: event.source,
|
|
37
|
+
run_id: runId,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
`;
|
|
41
|
+
}
|
|
42
|
+
async function setupExamplePlugins(cwd) {
|
|
43
|
+
const hooksDir = join(cwd, '.omx', 'hooks');
|
|
44
|
+
await mkdir(hooksDir, { recursive: true });
|
|
45
|
+
for (const eventName of ALL_EVENTS) {
|
|
46
|
+
const filePath = join(hooksDir, `example-${eventName}.mjs`);
|
|
47
|
+
await writeFile(filePath, examplePluginSource(eventName), 'utf-8');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
function pluginDataPath(cwd, eventName) {
|
|
51
|
+
return join(cwd, '.omx', 'state', 'hooks', 'plugins', `example-${eventName}`, 'data.json');
|
|
52
|
+
}
|
|
53
|
+
async function readPluginData(cwd, eventName) {
|
|
54
|
+
const path = pluginDataPath(cwd, eventName);
|
|
55
|
+
try {
|
|
56
|
+
await access(path);
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
const raw = await new Promise((resolve, reject) => {
|
|
62
|
+
readFile(path, 'utf-8', (err, data) => {
|
|
63
|
+
if (err) {
|
|
64
|
+
reject(err);
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
resolve(data);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
return JSON.parse(raw);
|
|
71
|
+
}
|
|
72
|
+
describe('example hook plugins', () => {
|
|
73
|
+
it('dispatches only the matching example plugin for a single event', async () => {
|
|
74
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-hook-examples-'));
|
|
75
|
+
try {
|
|
76
|
+
await setupExamplePlugins(cwd);
|
|
77
|
+
const event = buildHookEvent('session-start', {
|
|
78
|
+
timestamp: '2026-01-01T00:00:00.000Z',
|
|
79
|
+
context: { run_id: 'run-session-start' },
|
|
80
|
+
});
|
|
81
|
+
const result = await dispatchHookEvent(event, {
|
|
82
|
+
cwd,
|
|
83
|
+
env: {
|
|
84
|
+
...process.env,
|
|
85
|
+
OMX_HOOK_PLUGINS: '1',
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
assert.equal(result.enabled, true);
|
|
89
|
+
assert.equal(result.plugin_count, ALL_EVENTS.length);
|
|
90
|
+
assert.equal(result.results.length, ALL_EVENTS.length);
|
|
91
|
+
const matched = result.results.find((item) => item.plugin === 'example-session-start');
|
|
92
|
+
assert.ok(matched);
|
|
93
|
+
assert.equal(matched.ok, true);
|
|
94
|
+
for (const eventName of ALL_EVENTS) {
|
|
95
|
+
const data = await readPluginData(cwd, eventName);
|
|
96
|
+
if (eventName === 'session-start') {
|
|
97
|
+
assert.ok(data);
|
|
98
|
+
assert.equal(data.seen_count, 1);
|
|
99
|
+
assert.equal(data.last_event, 'session-start');
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
assert.equal(data, null);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
finally {
|
|
107
|
+
await rm(cwd, { recursive: true, force: true });
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
it('covers all example plugin event types with deterministic state assertions', async () => {
|
|
111
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-hook-examples-all-'));
|
|
112
|
+
try {
|
|
113
|
+
await setupExamplePlugins(cwd);
|
|
114
|
+
for (const eventName of ALL_EVENTS) {
|
|
115
|
+
const timestamp = `2026-01-01T00:00:00.${String(ALL_EVENTS.indexOf(eventName)).padStart(3, '0')}Z`;
|
|
116
|
+
const runId = `run-${eventName}`;
|
|
117
|
+
const envelope = buildHookEvent(eventName, {
|
|
118
|
+
timestamp,
|
|
119
|
+
context: { run_id: runId },
|
|
120
|
+
});
|
|
121
|
+
const result = await dispatchHookEvent(envelope, {
|
|
122
|
+
cwd,
|
|
123
|
+
env: {
|
|
124
|
+
...process.env,
|
|
125
|
+
OMX_HOOK_PLUGINS: '1',
|
|
126
|
+
},
|
|
127
|
+
});
|
|
128
|
+
const matched = result.results.find((item) => item.plugin === `example-${eventName}`);
|
|
129
|
+
assert.ok(matched);
|
|
130
|
+
assert.equal(matched.ok, true);
|
|
131
|
+
}
|
|
132
|
+
for (const eventName of ALL_EVENTS) {
|
|
133
|
+
const data = await readPluginData(cwd, eventName);
|
|
134
|
+
const runId = `run-${eventName}`;
|
|
135
|
+
const expectedSource = DERIVED_EVENTS.has(eventName) ? 'derived' : 'native';
|
|
136
|
+
assert.ok(data);
|
|
137
|
+
assert.equal(data.seen_count, 1);
|
|
138
|
+
assert.equal(data.last_event, eventName);
|
|
139
|
+
assert.equal(data.last_source, expectedSource);
|
|
140
|
+
assert.equal(data.last_run_id, runId);
|
|
141
|
+
assert.deepEqual(data[`run:${runId}`], {
|
|
142
|
+
event: eventName,
|
|
143
|
+
source: expectedSource,
|
|
144
|
+
at: `2026-01-01T00:00:00.${String(ALL_EVENTS.indexOf(eventName)).padStart(3, '0')}Z`,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
finally {
|
|
149
|
+
await rm(cwd, { recursive: true, force: true });
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
//# sourceMappingURL=example-hook-plugins.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"example-hook-plugins.test.js","sourceRoot":"","sources":["../../../../src/hooks/extensibility/__tests__/example-hook-plugins.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HookDispatchOptions, HookDispatchResult, HookEventEnvelope } from './types.js';
|
|
2
|
+
export declare function isHookPluginFeatureEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
3
|
+
export declare function dispatchHookEvent(event: HookEventEnvelope, options?: HookDispatchOptions): Promise<HookDispatchResult>;
|
|
4
|
+
//# sourceMappingURL=dispatcher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.d.ts","sourceRoot":"","sources":["../../../src/hooks/extensibility/dispatcher.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,YAAY,CAAC;AA2KpB,wBAAgB,0BAA0B,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAExF;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,iBAAiB,EACxB,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC,kBAAkB,CAAC,CA8E7B"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { appendFile, mkdir } from 'fs/promises';
|
|
3
|
+
import { spawn } from 'child_process';
|
|
4
|
+
import { join } from 'path';
|
|
5
|
+
import { getPackageRoot } from '../../utils/package.js';
|
|
6
|
+
import { discoverHookPlugins, isHookPluginsEnabled, resolveHookPluginTimeoutMs, validateHookPluginExport, } from './loader.js';
|
|
7
|
+
const RESULT_PREFIX = '__OMX_PLUGIN_RESULT__ ';
|
|
8
|
+
function hooksLogPath(cwd) {
|
|
9
|
+
const day = new Date().toISOString().slice(0, 10);
|
|
10
|
+
return join(cwd, '.omx', 'logs', `hooks-${day}.jsonl`);
|
|
11
|
+
}
|
|
12
|
+
async function appendHooksLog(cwd, payload) {
|
|
13
|
+
await mkdir(join(cwd, '.omx', 'logs'), { recursive: true });
|
|
14
|
+
await appendFile(hooksLogPath(cwd), `${JSON.stringify({ timestamp: new Date().toISOString(), ...payload })}\n`).catch(() => { });
|
|
15
|
+
}
|
|
16
|
+
function isTeamWorker(env) {
|
|
17
|
+
return typeof env.OMX_TEAM_WORKER === 'string' && env.OMX_TEAM_WORKER.trim() !== '';
|
|
18
|
+
}
|
|
19
|
+
async function runPluginRunner(plugin, event, options, sideEffectsEnabled) {
|
|
20
|
+
const started = Date.now();
|
|
21
|
+
const runnerPath = join(getPackageRoot(), 'dist', 'hooks', 'extensibility', 'plugin-runner.js');
|
|
22
|
+
const timeoutMs = options.timeoutMs ?? resolveHookPluginTimeoutMs(options.env);
|
|
23
|
+
if (!existsSync(runnerPath)) {
|
|
24
|
+
const duration = Date.now() - started;
|
|
25
|
+
return {
|
|
26
|
+
plugin: plugin.id,
|
|
27
|
+
path: plugin.path,
|
|
28
|
+
file: plugin.file,
|
|
29
|
+
plugin_id: plugin.id,
|
|
30
|
+
ok: false,
|
|
31
|
+
status: 'runner_error',
|
|
32
|
+
skipped: true,
|
|
33
|
+
reason: 'runner_missing',
|
|
34
|
+
durationMs: duration,
|
|
35
|
+
duration_ms: duration,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
return await new Promise((resolve) => {
|
|
39
|
+
const child = spawn(process.execPath, [runnerPath], {
|
|
40
|
+
cwd: options.cwd,
|
|
41
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
42
|
+
env: {
|
|
43
|
+
...process.env,
|
|
44
|
+
...(options.env || {}),
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
let stdout = '';
|
|
48
|
+
let stderr = '';
|
|
49
|
+
let done = false;
|
|
50
|
+
let timedOut = false;
|
|
51
|
+
const timer = setTimeout(() => {
|
|
52
|
+
timedOut = true;
|
|
53
|
+
child.kill('SIGTERM');
|
|
54
|
+
}, timeoutMs);
|
|
55
|
+
child.stdout.on('data', (chunk) => {
|
|
56
|
+
stdout += chunk.toString();
|
|
57
|
+
});
|
|
58
|
+
child.stderr.on('data', (chunk) => {
|
|
59
|
+
stderr += chunk.toString();
|
|
60
|
+
});
|
|
61
|
+
child.on('error', (error) => {
|
|
62
|
+
if (done)
|
|
63
|
+
return;
|
|
64
|
+
done = true;
|
|
65
|
+
clearTimeout(timer);
|
|
66
|
+
const duration = Date.now() - started;
|
|
67
|
+
resolve({
|
|
68
|
+
plugin: plugin.id,
|
|
69
|
+
path: plugin.path,
|
|
70
|
+
file: plugin.file,
|
|
71
|
+
plugin_id: plugin.id,
|
|
72
|
+
ok: false,
|
|
73
|
+
status: 'runner_error',
|
|
74
|
+
reason: 'spawn_failed',
|
|
75
|
+
error: error.message,
|
|
76
|
+
durationMs: duration,
|
|
77
|
+
duration_ms: duration,
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
child.on('close', () => {
|
|
81
|
+
if (done)
|
|
82
|
+
return;
|
|
83
|
+
done = true;
|
|
84
|
+
clearTimeout(timer);
|
|
85
|
+
const duration = Date.now() - started;
|
|
86
|
+
if (timedOut) {
|
|
87
|
+
resolve({
|
|
88
|
+
plugin: plugin.id,
|
|
89
|
+
path: plugin.path,
|
|
90
|
+
file: plugin.file,
|
|
91
|
+
plugin_id: plugin.id,
|
|
92
|
+
ok: false,
|
|
93
|
+
status: 'timeout',
|
|
94
|
+
reason: 'timeout',
|
|
95
|
+
durationMs: duration,
|
|
96
|
+
duration_ms: duration,
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
const lines = stdout.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
101
|
+
const rawResult = [...lines].reverse().find((line) => line.startsWith(RESULT_PREFIX));
|
|
102
|
+
let parsed = null;
|
|
103
|
+
if (rawResult) {
|
|
104
|
+
try {
|
|
105
|
+
parsed = JSON.parse(rawResult.slice(RESULT_PREFIX.length));
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
parsed = null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (parsed?.ok) {
|
|
112
|
+
resolve({
|
|
113
|
+
plugin: plugin.id,
|
|
114
|
+
path: plugin.path,
|
|
115
|
+
file: plugin.file,
|
|
116
|
+
plugin_id: plugin.id,
|
|
117
|
+
ok: true,
|
|
118
|
+
status: 'ok',
|
|
119
|
+
reason: parsed.reason || 'ok',
|
|
120
|
+
durationMs: duration,
|
|
121
|
+
duration_ms: duration,
|
|
122
|
+
});
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const reason = parsed?.reason || 'plugin_error';
|
|
126
|
+
resolve({
|
|
127
|
+
plugin: plugin.id,
|
|
128
|
+
path: plugin.path,
|
|
129
|
+
file: plugin.file,
|
|
130
|
+
plugin_id: plugin.id,
|
|
131
|
+
ok: false,
|
|
132
|
+
status: reason === 'invalid_export' ? 'invalid_export' : 'error',
|
|
133
|
+
reason,
|
|
134
|
+
error: parsed?.error || stderr.trim() || undefined,
|
|
135
|
+
durationMs: duration,
|
|
136
|
+
duration_ms: duration,
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
child.stdin.write(JSON.stringify({
|
|
140
|
+
cwd: options.cwd,
|
|
141
|
+
pluginId: plugin.id,
|
|
142
|
+
pluginPath: plugin.path,
|
|
143
|
+
event,
|
|
144
|
+
sideEffectsEnabled,
|
|
145
|
+
}));
|
|
146
|
+
child.stdin.end();
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
export function isHookPluginFeatureEnabled(env = process.env) {
|
|
150
|
+
return isHookPluginsEnabled(env);
|
|
151
|
+
}
|
|
152
|
+
export async function dispatchHookEvent(event, options = {}) {
|
|
153
|
+
const cwd = options.cwd || process.cwd();
|
|
154
|
+
const env = options.env || process.env;
|
|
155
|
+
const enabled = options.enabled ?? isHookPluginsEnabled(env);
|
|
156
|
+
const summary = {
|
|
157
|
+
enabled,
|
|
158
|
+
reason: enabled ? 'ok' : 'disabled',
|
|
159
|
+
event: event.event,
|
|
160
|
+
source: event.source,
|
|
161
|
+
plugin_count: 0,
|
|
162
|
+
results: [],
|
|
163
|
+
};
|
|
164
|
+
if (!enabled) {
|
|
165
|
+
await appendHooksLog(cwd, {
|
|
166
|
+
type: 'hook_dispatch',
|
|
167
|
+
event: event.event,
|
|
168
|
+
source: event.source,
|
|
169
|
+
enabled: false,
|
|
170
|
+
reason: 'plugins_disabled',
|
|
171
|
+
});
|
|
172
|
+
return summary;
|
|
173
|
+
}
|
|
174
|
+
const plugins = await discoverHookPlugins(cwd);
|
|
175
|
+
summary.plugin_count = plugins.length;
|
|
176
|
+
const inTeamWorker = isTeamWorker(env);
|
|
177
|
+
const allowTeamSideEffects = options.allowTeamWorkerSideEffects ?? options.allowInTeamWorker ?? false;
|
|
178
|
+
const sideEffectsEnabled = options.sideEffectsEnabled ?? (!inTeamWorker || allowTeamSideEffects);
|
|
179
|
+
for (const plugin of plugins) {
|
|
180
|
+
const validation = await validateHookPluginExport(plugin.path);
|
|
181
|
+
if (!validation.valid) {
|
|
182
|
+
const invalid = {
|
|
183
|
+
plugin: plugin.id,
|
|
184
|
+
path: plugin.path,
|
|
185
|
+
file: plugin.file,
|
|
186
|
+
plugin_id: plugin.id,
|
|
187
|
+
ok: false,
|
|
188
|
+
status: 'invalid_export',
|
|
189
|
+
reason: validation.reason || 'invalid_export',
|
|
190
|
+
durationMs: 0,
|
|
191
|
+
duration_ms: 0,
|
|
192
|
+
};
|
|
193
|
+
summary.results.push(invalid);
|
|
194
|
+
await appendHooksLog(cwd, {
|
|
195
|
+
type: 'hook_plugin_dispatch',
|
|
196
|
+
event: event.event,
|
|
197
|
+
source: event.source,
|
|
198
|
+
plugin: plugin.id,
|
|
199
|
+
file: plugin.file,
|
|
200
|
+
ok: false,
|
|
201
|
+
status: invalid.status,
|
|
202
|
+
reason: invalid.reason,
|
|
203
|
+
});
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
const result = await runPluginRunner(plugin, event, { ...options, cwd, env }, sideEffectsEnabled);
|
|
207
|
+
summary.results.push(result);
|
|
208
|
+
await appendHooksLog(cwd, {
|
|
209
|
+
type: 'hook_plugin_dispatch',
|
|
210
|
+
event: event.event,
|
|
211
|
+
source: event.source,
|
|
212
|
+
plugin: plugin.id,
|
|
213
|
+
file: plugin.file,
|
|
214
|
+
ok: result.ok,
|
|
215
|
+
status: result.status,
|
|
216
|
+
reason: result.reason,
|
|
217
|
+
error: result.error,
|
|
218
|
+
duration_ms: result.duration_ms,
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
return summary;
|
|
222
|
+
}
|
|
223
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../../../src/hooks/extensibility/dispatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { HookEventEnvelope, HookEventName, HookEventSource } from './types.js';
|
|
2
|
+
interface BuildHookEventOptions {
|
|
3
|
+
source?: HookEventSource;
|
|
4
|
+
timestamp?: string;
|
|
5
|
+
context?: Record<string, unknown>;
|
|
6
|
+
session_id?: string;
|
|
7
|
+
thread_id?: string;
|
|
8
|
+
turn_id?: string;
|
|
9
|
+
mode?: string;
|
|
10
|
+
confidence?: number;
|
|
11
|
+
parser_reason?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function isDerivedEventName(event: string): boolean;
|
|
14
|
+
export declare function buildHookEvent(event: HookEventName | string, options?: BuildHookEventOptions): HookEventEnvelope;
|
|
15
|
+
export declare function buildNativeHookEvent(event: HookEventName | string, context?: Record<string, unknown>, options?: Omit<BuildHookEventOptions, 'source' | 'confidence' | 'parser_reason' | 'context'>): HookEventEnvelope;
|
|
16
|
+
export declare function buildDerivedHookEvent(event: HookEventName | string, context?: Record<string, unknown>, options?: Omit<BuildHookEventOptions, 'source' | 'context'>): HookEventEnvelope;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../../src/hooks/extensibility/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAIpF,UAAU,qBAAqB;IAC7B,MAAM,CAAC,EAAE,eAAe,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AASD,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,aAAa,GAAG,MAAM,EAC7B,OAAO,GAAE,qBAA0B,GAClC,iBAAiB,CAuBnB;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,aAAa,GAAG,MAAM,EAC7B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,OAAO,GAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,YAAY,GAAG,eAAe,GAAG,SAAS,CAAM,GAC/F,iBAAiB,CAMnB;AAED,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,GAAG,MAAM,EAC7B,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACrC,OAAO,GAAE,IAAI,CAAC,qBAAqB,EAAE,QAAQ,GAAG,SAAS,CAAM,GAC9D,iBAAiB,CAMnB"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const DERIVED_EVENTS = new Set(['needs-input', 'pre-tool-use', 'post-tool-use']);
|
|
2
|
+
function clampConfidence(value) {
|
|
3
|
+
if (typeof value !== 'number' || !Number.isFinite(value))
|
|
4
|
+
return undefined;
|
|
5
|
+
if (value < 0)
|
|
6
|
+
return 0;
|
|
7
|
+
if (value > 1)
|
|
8
|
+
return 1;
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
export function isDerivedEventName(event) {
|
|
12
|
+
return DERIVED_EVENTS.has(event);
|
|
13
|
+
}
|
|
14
|
+
export function buildHookEvent(event, options = {}) {
|
|
15
|
+
const source = options.source || (isDerivedEventName(event) ? 'derived' : 'native');
|
|
16
|
+
const confidence = clampConfidence(options.confidence);
|
|
17
|
+
const envelope = {
|
|
18
|
+
schema_version: '1',
|
|
19
|
+
event,
|
|
20
|
+
timestamp: options.timestamp || new Date().toISOString(),
|
|
21
|
+
source,
|
|
22
|
+
context: options.context && typeof options.context === 'object' ? options.context : {},
|
|
23
|
+
};
|
|
24
|
+
if (options.session_id)
|
|
25
|
+
envelope.session_id = options.session_id;
|
|
26
|
+
if (options.thread_id)
|
|
27
|
+
envelope.thread_id = options.thread_id;
|
|
28
|
+
if (options.turn_id)
|
|
29
|
+
envelope.turn_id = options.turn_id;
|
|
30
|
+
if (options.mode)
|
|
31
|
+
envelope.mode = options.mode;
|
|
32
|
+
if (source === 'derived') {
|
|
33
|
+
envelope.confidence = confidence ?? 0.5;
|
|
34
|
+
if (options.parser_reason)
|
|
35
|
+
envelope.parser_reason = options.parser_reason;
|
|
36
|
+
}
|
|
37
|
+
return envelope;
|
|
38
|
+
}
|
|
39
|
+
export function buildNativeHookEvent(event, context = {}, options = {}) {
|
|
40
|
+
return buildHookEvent(event, {
|
|
41
|
+
...options,
|
|
42
|
+
source: 'native',
|
|
43
|
+
context,
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
export function buildDerivedHookEvent(event, context = {}, options = {}) {
|
|
47
|
+
return buildHookEvent(event, {
|
|
48
|
+
...options,
|
|
49
|
+
source: 'derived',
|
|
50
|
+
context,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../../src/hooks/extensibility/events.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,IAAI,GAAG,CAAS,CAAC,aAAa,EAAE,cAAc,EAAE,eAAe,CAAC,CAAC,CAAC;AAczF,SAAS,eAAe,CAAC,KAAc;IACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IAC3E,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACxB,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,CAAC,CAAC;IACxB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC9C,OAAO,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACnC,CAAC;AAED,MAAM,UAAU,cAAc,CAC5B,KAA6B,EAC7B,UAAiC,EAAE;IAEnC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IACpF,MAAM,UAAU,GAAG,eAAe,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IAEvD,MAAM,QAAQ,GAAsB;QAClC,cAAc,EAAE,GAAG;QACnB,KAAK;QACL,SAAS,EAAE,OAAO,CAAC,SAAS,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACxD,MAAM;QACN,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,OAAO,OAAO,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;KACvF,CAAC;IAEF,IAAI,OAAO,CAAC,UAAU;QAAE,QAAQ,CAAC,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IACjE,IAAI,OAAO,CAAC,SAAS;QAAE,QAAQ,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAC9D,IAAI,OAAO,CAAC,OAAO;QAAE,QAAQ,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IACxD,IAAI,OAAO,CAAC,IAAI;QAAE,QAAQ,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAE/C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;QACzB,QAAQ,CAAC,UAAU,GAAG,UAAU,IAAI,GAAG,CAAC;QACxC,IAAI,OAAO,CAAC,aAAa;YAAE,QAAQ,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;IAC5E,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,MAAM,UAAU,oBAAoB,CAClC,KAA6B,EAC7B,UAAmC,EAAE,EACrC,UAA8F,EAAE;IAEhG,OAAO,cAAc,CAAC,KAAK,EAAE;QAC3B,GAAG,OAAO;QACV,MAAM,EAAE,QAAQ;QAChB,OAAO;KACR,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,qBAAqB,CACnC,KAA6B,EAC7B,UAAmC,EAAE,EACrC,UAA6D,EAAE;IAE/D,OAAO,cAAc,CAAC,KAAK,EAAE;QAC3B,GAAG,OAAO;QACV,MAAM,EAAE,SAAS;QACjB,OAAO;KACR,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hooks/extensibility/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hooks/extensibility/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,UAAU,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { HookPluginDescriptor } from './types.js';
|
|
2
|
+
export declare const HOOK_PLUGIN_ENABLE_ENV = "OMX_HOOK_PLUGINS";
|
|
3
|
+
export declare const HOOK_PLUGIN_TIMEOUT_ENV = "OMX_HOOK_PLUGIN_TIMEOUT_MS";
|
|
4
|
+
export declare function hooksDir(cwd: string): string;
|
|
5
|
+
export declare function isHookPluginsEnabled(env?: NodeJS.ProcessEnv): boolean;
|
|
6
|
+
export declare function resolveHookPluginTimeoutMs(env?: NodeJS.ProcessEnv, fallback?: number): number;
|
|
7
|
+
export declare function ensureHooksDir(cwd: string): Promise<string>;
|
|
8
|
+
export declare function validateHookPluginExport(pluginPath: string): Promise<{
|
|
9
|
+
valid: boolean;
|
|
10
|
+
reason?: string;
|
|
11
|
+
}>;
|
|
12
|
+
export declare function discoverHookPlugins(cwd: string): Promise<HookPluginDescriptor[]>;
|
|
13
|
+
export declare function loadHookPluginDescriptors(cwd: string): Promise<HookPluginDescriptor[]>;
|
|
14
|
+
//# sourceMappingURL=loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../../src/hooks/extensibility/loader.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAEvD,eAAO,MAAM,sBAAsB,qBAAqB,CAAC;AACzD,eAAO,MAAM,uBAAuB,+BAA+B,CAAC;AAsBpE,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE5C;AAED,wBAAgB,oBAAoB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAGlF;AAED,wBAAgB,0BAA0B,CACxC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,QAAQ,SAAO,GACd,MAAM,CAER;AAED,wBAAsB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAIjE;AAiBD,wBAAsB,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAE/G;AAED,wBAAsB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CA2BtF;AAED,wBAAsB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAY5F"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { mkdir, readdir, stat } from 'fs/promises';
|
|
3
|
+
import { basename, join } from 'path';
|
|
4
|
+
import { pathToFileURL } from 'url';
|
|
5
|
+
export const HOOK_PLUGIN_ENABLE_ENV = 'OMX_HOOK_PLUGINS';
|
|
6
|
+
export const HOOK_PLUGIN_TIMEOUT_ENV = 'OMX_HOOK_PLUGIN_TIMEOUT_MS';
|
|
7
|
+
function sanitizePluginId(fileName) {
|
|
8
|
+
const stem = basename(fileName, '.mjs');
|
|
9
|
+
const normalized = stem
|
|
10
|
+
.toLowerCase()
|
|
11
|
+
.replace(/[^a-z0-9_-]+/g, '-')
|
|
12
|
+
.replace(/-+/g, '-')
|
|
13
|
+
.replace(/^-+|-+$/g, '');
|
|
14
|
+
return normalized || 'plugin';
|
|
15
|
+
}
|
|
16
|
+
function readTimeout(raw, fallback) {
|
|
17
|
+
if (!raw)
|
|
18
|
+
return fallback;
|
|
19
|
+
const parsed = Number(raw);
|
|
20
|
+
if (!Number.isFinite(parsed))
|
|
21
|
+
return fallback;
|
|
22
|
+
const rounded = Math.floor(parsed);
|
|
23
|
+
if (rounded < 100)
|
|
24
|
+
return 100;
|
|
25
|
+
if (rounded > 60_000)
|
|
26
|
+
return 60_000;
|
|
27
|
+
return rounded;
|
|
28
|
+
}
|
|
29
|
+
export function hooksDir(cwd) {
|
|
30
|
+
return join(cwd, '.omx', 'hooks');
|
|
31
|
+
}
|
|
32
|
+
export function isHookPluginsEnabled(env = process.env) {
|
|
33
|
+
const raw = `${env[HOOK_PLUGIN_ENABLE_ENV] ?? ''}`.trim().toLowerCase();
|
|
34
|
+
return raw === '1' || raw === 'true' || raw === 'yes';
|
|
35
|
+
}
|
|
36
|
+
export function resolveHookPluginTimeoutMs(env = process.env, fallback = 1500) {
|
|
37
|
+
return readTimeout(env[HOOK_PLUGIN_TIMEOUT_ENV], fallback);
|
|
38
|
+
}
|
|
39
|
+
export async function ensureHooksDir(cwd) {
|
|
40
|
+
const dir = hooksDir(cwd);
|
|
41
|
+
await mkdir(dir, { recursive: true });
|
|
42
|
+
return dir;
|
|
43
|
+
}
|
|
44
|
+
async function validatePluginExport(pluginPath) {
|
|
45
|
+
try {
|
|
46
|
+
const mod = await import(`${pathToFileURL(pluginPath).href}?v=${Date.now()}`);
|
|
47
|
+
if (!mod || typeof mod.onHookEvent !== 'function') {
|
|
48
|
+
return { valid: false, reason: 'missing_onHookEvent_export' };
|
|
49
|
+
}
|
|
50
|
+
return { valid: true };
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
return {
|
|
54
|
+
valid: false,
|
|
55
|
+
reason: err instanceof Error ? err.message : 'failed_to_import_plugin',
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export async function validateHookPluginExport(pluginPath) {
|
|
60
|
+
return validatePluginExport(pluginPath);
|
|
61
|
+
}
|
|
62
|
+
export async function discoverHookPlugins(cwd) {
|
|
63
|
+
const dir = hooksDir(cwd);
|
|
64
|
+
if (!existsSync(dir))
|
|
65
|
+
return [];
|
|
66
|
+
const names = await readdir(dir).catch(() => []);
|
|
67
|
+
const plugins = [];
|
|
68
|
+
for (const name of names) {
|
|
69
|
+
if (!name.endsWith('.mjs'))
|
|
70
|
+
continue;
|
|
71
|
+
const path = join(dir, name);
|
|
72
|
+
const st = await stat(path).catch(() => null);
|
|
73
|
+
if (!st || !st.isFile())
|
|
74
|
+
continue;
|
|
75
|
+
const id = sanitizePluginId(name);
|
|
76
|
+
plugins.push({
|
|
77
|
+
id,
|
|
78
|
+
name: id,
|
|
79
|
+
file: name,
|
|
80
|
+
path,
|
|
81
|
+
filePath: path,
|
|
82
|
+
fileName: name,
|
|
83
|
+
valid: true,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
plugins.sort((a, b) => a.file.localeCompare(b.file));
|
|
87
|
+
return plugins;
|
|
88
|
+
}
|
|
89
|
+
export async function loadHookPluginDescriptors(cwd) {
|
|
90
|
+
const discovered = await discoverHookPlugins(cwd);
|
|
91
|
+
const validated = [];
|
|
92
|
+
for (const plugin of discovered) {
|
|
93
|
+
const validation = await validatePluginExport(plugin.path);
|
|
94
|
+
validated.push({
|
|
95
|
+
...plugin,
|
|
96
|
+
valid: validation.valid,
|
|
97
|
+
reason: validation.reason,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
return validated;
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../../src/hooks/extensibility/loader.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { HookPluginLogContext } from './types.js';
|
|
2
|
+
export declare function hookLogPath(cwd: string, timestamp?: Date): string;
|
|
3
|
+
export declare function appendHookPluginLog(cwd: string, entry: HookPluginLogContext): Promise<void>;
|
|
4
|
+
//# sourceMappingURL=logging.d.ts.map
|