@cleocode/adapters 2026.10.18 → 2026.10.19
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/dist/heavy-command-hook.js +124 -18
- package/dist/heavy-command-hook.js.map +3 -3
- package/dist/index.js +54 -12
- package/dist/index.js.map +2 -2
- package/dist/project-hook-native.d.ts.map +1 -1
- package/dist/project-hook-native.js +9 -1
- package/dist/project-hook-native.js.map +1 -1
- package/dist/providers/shared/heavy-command-hook-delivery.d.ts +14 -0
- package/dist/providers/shared/heavy-command-hook-delivery.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/__tests__/harness-interop.test.ts +19 -6
- package/src/project-hook-native.ts +15 -1
- package/src/providers/shared/heavy-command-hook-delivery.ts +51 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-hook-native.d.ts","sourceRoot":"","sources":["../src/project-hook-native.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,sCAAsC,CAAC;AAmCvF,+FAA+F;AAC/F,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,wBAAwB,
|
|
1
|
+
{"version":3,"file":"project-hook-native.d.ts","sourceRoot":"","sources":["../src/project-hook-native.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EACxB,MAAM,8CAA8C,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,sCAAsC,CAAC;AAmCvF,+FAA+F;AAC/F,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,GACV,wBAAwB,CA6C1B;AAED,+EAA+E;AAC/E,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,wBAAwB,EACjC,QAAQ,EAAE,WAAW,EAAE,GACtB,uBAAuB,CA4CzB"}
|
|
@@ -45,11 +45,19 @@ function normalizeNativeProjectHook(argv, body, cwd) {
|
|
|
45
45
|
};
|
|
46
46
|
const payload = JSON.parse(body || "{}");
|
|
47
47
|
if (!object(payload)) throw new Error("HOOK_AGENT_INPUT_INVALID");
|
|
48
|
+
const sessionId = payload.session_id;
|
|
49
|
+
const nativeSession = typeof sessionId === "string" && sessionId.length > 0 && sessionId.length <= 256 && /^[a-z][a-z0-9-]{0,63}$/.test(provider) ? { sessionId, harness: provider } : void 0;
|
|
48
50
|
return {
|
|
49
51
|
cwd: typeof payload.cwd === "string" ? payload.cwd : cwd,
|
|
50
52
|
provider,
|
|
51
53
|
nativeEvent: typeof payload.hook_event_name === "string" ? payload.hook_event_name : event,
|
|
52
|
-
input: {
|
|
54
|
+
input: {
|
|
55
|
+
schemaVersion: 1,
|
|
56
|
+
source,
|
|
57
|
+
event,
|
|
58
|
+
toolInput: payload.tool_input ?? {},
|
|
59
|
+
...nativeSession ? { nativeSession } : {}
|
|
60
|
+
}
|
|
53
61
|
};
|
|
54
62
|
}
|
|
55
63
|
function renderNativeProjectHook(request, outcomes) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/project-hook-native.ts"],
|
|
4
|
-
"mappings": ";AAQA,SAAS,KAAK,MAAyB,MAAkC;AACvE,QAAM,YAAY,KAAK,QAAQ,IAAI;AACnC,QAAM,UAAU,YAAY,IAAI,OAAO,KAAK,MAAM,GAAG,SAAS;AAC9D,QAAM,QAAQ,QAAQ;AAAA,IACpB,CAAC,QAAQ,QAAQ,OAAO,QAAQ,IAAI,WAAW,OAAO,OAAO,GAAG;AAAA,EAClE;AACA,SAAO,QAAQ,IACX,SACA,QAAQ,KAAK,GAAG,MAAM,GAAG,EAAE,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,QAAQ,QAAQ,CAAC;AACxE;AACA,SAAS,OAAO,OAA0E;AACxF,SAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAC5E;AACA,SAAS,cAAc,MAA+B;AACpD,QAAM,OAAwB,CAAC;AAC/B,aAAW,QAAQ,KAAK,MAAM,OAAO,EAAE,OAAO,CAACA,UAASA,MAAK,KAAK,CAAC,GAAG;AACpE,UAAM,SAAS,KAAK,KAAK,EAAE,MAAM,KAAK;AACtC,UAAM,CAAC,UAAU,UAAU,WAAW,SAAS,IAAI;AACnD,QACE,OAAO,WAAW,KAClB,CAAC,YACD,CAAC,aACD,CAAC,YACD,CAAC,aACD,CAAC,kCAAkC,KAAK,QAAQ,KAChD,CAAC,kCAAkC,KAAK,SAAS;AAEjD,YAAM,IAAI,MAAM,wBAAwB;AAC1C,SAAK,KAAK,EAAE,UAAU,UAAU,WAAW,UAAU,CAAC;AAAA,EACxD;AACA,SAAO;AACT;AAGO,SAAS,2BACd,MACA,MACA,KAC0B;AAC1B,MAAI,OAAO,WAAW,IAAI,IAAI,OAAQ,OAAM,IAAI,MAAM,sBAAsB;AAC5E,QAAM,SAAS,KAAK,MAAM,QAAQ,KAAK;AACvC,MAAI,WAAW,WAAW,WAAW,MAAO,OAAM,IAAI,MAAM,qBAAqB;AACjF,QAAM,WAAW,KAAK,MAAM,UAAU,KAAK;AAC3C,QAAM,QAAQ,KAAK,MAAM,OAAO,MAAM,WAAW,QAAQ,aAAa;AACtE,QAAM,YAAY,KAAK,QAAQ,IAAI;AACnC,MAAI,WAAW;AACb,WAAO;AAAA,MACL;AAAA,MACA;AAAA,MACA,OAAO;AAAA,QACL,eAAe;AAAA,QACf;AAAA,QACA;AAAA,QACA,MAAM,cAAc,IAAI;AAAA,QACxB,QAAQ;AAAA,UACN,MAAM,KAAK,MAAM,aAAa,MAAM,YAAY,IAAI,KAAK,KAAK,YAAY,CAAC,MAAM;AAAA,UACjF,UACE,KAAK,MAAM,iBAAiB,MAAM,YAAY,IAAI,KAAK,KAAK,YAAY,CAAC,MAAM;AAAA,QACnF;AAAA,MACF;AAAA,IACF;AACF,QAAM,UAAU,KAAK,MAAM,QAAQ,IAAI;AACvC,MAAI,CAAC,OAAO,OAAO,EAAG,OAAM,IAAI,MAAM,0BAA0B;AAChE,SAAO;AAAA,IACL,KAAK,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM;AAAA,IACrD;AAAA,IACA,aAAa,OAAO,QAAQ,oBAAoB,WAAW,QAAQ,kBAAkB;AAAA,IACrF,OAAO,
|
|
4
|
+
"mappings": "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",
|
|
5
5
|
"names": ["line"]
|
|
6
6
|
}
|
|
@@ -55,6 +55,20 @@ export interface HeavyHookDetection {
|
|
|
55
55
|
* @returns whether it is in use, and why.
|
|
56
56
|
*/
|
|
57
57
|
export declare function detectHeavyHookProvider(provider: HeavyCommandHookProvider, projectDir: string, env?: Env): HeavyHookDetection;
|
|
58
|
+
/**
|
|
59
|
+
* Install only CLEO's Stop dispatcher (`cleo hook stop`, T13796) for one
|
|
60
|
+
* provider in the project, whatever the heavy-command mode, and nothing
|
|
61
|
+
* else (no `PreToolUse` hook). `cleo goal install --harness claude|codex`
|
|
62
|
+
* uses it so the dispatcher runs the CLEO Goal tick (T13820). Project-level
|
|
63
|
+
* only: a project that is the home directory, a target in the user-global
|
|
64
|
+
* Claude config, or a shared `.codex/hooks.json` is refused unwritten.
|
|
65
|
+
* Never throws.
|
|
66
|
+
*
|
|
67
|
+
* @param projectDir - the project root.
|
|
68
|
+
* @param provider - `claude-code` or `codex`.
|
|
69
|
+
* @returns the outcome for that provider.
|
|
70
|
+
*/
|
|
71
|
+
export declare function syncProjectStopDispatch(projectDir: string, provider: 'claude-code' | 'codex'): Promise<HeavyHookDeliveryOutcome>;
|
|
58
72
|
/**
|
|
59
73
|
* Install, refresh or (mode `off`) remove CLEO's heavy-command hook for every
|
|
60
74
|
* provider in use in `projectDir`, each independently: one provider's failure
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heavy-command-hook-delivery.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/heavy-command-hook-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,OAAO,KAAK,EACV,oBAAoB,EACpB,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"heavy-command-hook-delivery.d.ts","sourceRoot":"","sources":["../../../src/providers/shared/heavy-command-hook-delivery.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAOH,OAAO,KAAK,EACV,oBAAoB,EACpB,wBAAwB,EACxB,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACpB,MAAM,qBAAqB,CAAC;AA8B7B,8DAA8D;AAC9D,eAAO,MAAM,6BAA6B,EAAE,SAAS,wBAAwB,EAK3E,CAAC;AAEH,gEAAgE;AAChE,eAAO,MAAM,sBAAsB,yCAAyC,CAAC;AAE7E,KAAK,GAAG,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAgBxD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,GAAiB,GACrB,MAAM,CAWR;AAED,uEAAuE;AACvE,MAAM,WAAW,kBAAkB;IACjC,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,8DAA8D;IAC9D,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,wBAAwB,EAClC,UAAU,EAAE,MAAM,EAClB,GAAG,GAAE,GAAiB,GACrB,kBAAkB,CAgDpB;AA2BD;;;;;;;;;;;;GAYG;AACH,wBAAsB,uBAAuB,CAC3C,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,aAAa,GAAG,OAAO,GAChC,OAAO,CAAC,wBAAwB,CAAC,CA6BnC;AA4DD;;;;;;;;;;GAUG;AACH,wBAAsB,4BAA4B,CAChD,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,oBAAoB,EAC1B,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,SAAS,wBAAwB,EAAE,CAAC,CAwB9C;AA2MD;;;;;;;;GAQG;AACH,wBAAgB,+BAA+B,CAC7C,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,oBAAoB,EAC1B,OAAO,GAAE,wBAA6B,GACrC,SAAS,mBAAmB,EAAE,CAchC;AAwCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,wBAA6B,GACrC,iBAAiB,CA6CnB;AAED,+DAA+D;AAC/D,eAAO,MAAM,oBAAoB,EAAE,oBAKjC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/adapters",
|
|
3
|
-
"version": "2026.10.
|
|
3
|
+
"version": "2026.10.19",
|
|
4
4
|
"description": "Unified provider adapters for CLEO (Claude Code, OpenCode, Cursor)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -27,9 +27,9 @@
|
|
|
27
27
|
"@ai-sdk/anthropic": "^3.0.69",
|
|
28
28
|
"@ai-sdk/openai": "^2.0.53",
|
|
29
29
|
"ai": "^6.0.168",
|
|
30
|
-
"@cleocode/caamp": "2026.10.
|
|
31
|
-
"@cleocode/contracts": "2026.10.
|
|
32
|
-
"@cleocode/paths": "2026.10.
|
|
30
|
+
"@cleocode/caamp": "2026.10.19",
|
|
31
|
+
"@cleocode/contracts": "2026.10.19",
|
|
32
|
+
"@cleocode/paths": "2026.10.19"
|
|
33
33
|
},
|
|
34
34
|
"license": "MIT",
|
|
35
35
|
"engines": {
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@types/node": "^24.3.0",
|
|
44
44
|
"vitest": "^4.1.4",
|
|
45
|
-
"@cleocode/
|
|
46
|
-
"@cleocode/
|
|
45
|
+
"@cleocode/core": "2026.10.19",
|
|
46
|
+
"@cleocode/playbooks": "2026.10.19"
|
|
47
47
|
},
|
|
48
48
|
"repository": {
|
|
49
49
|
"type": "git",
|
|
@@ -133,10 +133,23 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
|
133
133
|
* `@cleocode/core`. Loading the SQL directly keeps the test hermetic without
|
|
134
134
|
* re-implementing the schema inline.
|
|
135
135
|
*/
|
|
136
|
-
const
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
)
|
|
136
|
+
const PROJECT_MIGRATIONS = resolve(__dirname, '../../../core/migrations/drizzle-cleo-project');
|
|
137
|
+
|
|
138
|
+
/** The playbook twins the state layer writes, as a project store creates them (T12535). */
|
|
139
|
+
function playbookTwinSql(): string {
|
|
140
|
+
const consolidation = readFileSync(
|
|
141
|
+
resolve(PROJECT_MIGRATIONS, '20260531000001_t11363-consolidation-cleo-project/migration.sql'),
|
|
142
|
+
'utf8',
|
|
143
|
+
);
|
|
144
|
+
const tables = ['tasks_playbook_runs', 'tasks_playbook_approvals'].map(
|
|
145
|
+
(t) => consolidation.match(new RegExp(`CREATE TABLE \`${t}\` \\([\\s\\S]*?\\n\\);`))?.[0] ?? '',
|
|
146
|
+
);
|
|
147
|
+
const uids = readFileSync(
|
|
148
|
+
resolve(PROJECT_MIGRATIONS, '20261016120000_t12535-playbook-row-uids/migration.sql'),
|
|
149
|
+
'utf8',
|
|
150
|
+
);
|
|
151
|
+
return [...tables, uids].join('\n--> statement-breakpoint\n');
|
|
152
|
+
}
|
|
140
153
|
|
|
141
154
|
/** Absolute path to the rcasd.cantbook starter playbook (T934). */
|
|
142
155
|
const RCASD_CANTBOOK = resolve(__dirname, '../../../playbooks/starter/rcasd.cantbook');
|
|
@@ -263,7 +276,7 @@ describe('T937 — harness interop: playbook runtime across provider adapters',
|
|
|
263
276
|
beforeEach(() => {
|
|
264
277
|
db = new DatabaseSync(':memory:');
|
|
265
278
|
db.exec('PRAGMA foreign_keys=ON');
|
|
266
|
-
applyMigration(db,
|
|
279
|
+
applyMigration(db, playbookTwinSql());
|
|
267
280
|
|
|
268
281
|
anthropicCalls.length = 0;
|
|
269
282
|
openaiCalls.length = 0;
|
|
@@ -393,7 +406,7 @@ describe('T937 — harness interop: playbook runtime across provider adapters',
|
|
|
393
406
|
// Reset per-provider state so DB rows don't collide.
|
|
394
407
|
const freshDb = new DatabaseSync(':memory:');
|
|
395
408
|
freshDb.exec('PRAGMA foreign_keys=ON');
|
|
396
|
-
applyMigration(freshDb,
|
|
409
|
+
applyMigration(freshDb, playbookTwinSql());
|
|
397
410
|
|
|
398
411
|
const result = await executePlaybook({
|
|
399
412
|
db: freshDb,
|
|
@@ -69,11 +69,25 @@ export function normalizeNativeProjectHook(
|
|
|
69
69
|
};
|
|
70
70
|
const payload = JSON.parse(body || '{}') as HookJsonValue;
|
|
71
71
|
if (!object(payload)) throw new Error('HOOK_AGENT_INPUT_INVALID');
|
|
72
|
+
const sessionId = payload.session_id;
|
|
73
|
+
const nativeSession =
|
|
74
|
+
typeof sessionId === 'string' &&
|
|
75
|
+
sessionId.length > 0 &&
|
|
76
|
+
sessionId.length <= 256 &&
|
|
77
|
+
/^[a-z][a-z0-9-]{0,63}$/.test(provider)
|
|
78
|
+
? { sessionId, harness: provider }
|
|
79
|
+
: undefined;
|
|
72
80
|
return {
|
|
73
81
|
cwd: typeof payload.cwd === 'string' ? payload.cwd : cwd,
|
|
74
82
|
provider,
|
|
75
83
|
nativeEvent: typeof payload.hook_event_name === 'string' ? payload.hook_event_name : event,
|
|
76
|
-
input: {
|
|
84
|
+
input: {
|
|
85
|
+
schemaVersion: 1,
|
|
86
|
+
source,
|
|
87
|
+
event,
|
|
88
|
+
toolInput: payload.tool_input ?? {},
|
|
89
|
+
...(nativeSession ? { nativeSession } : {}),
|
|
90
|
+
},
|
|
77
91
|
};
|
|
78
92
|
}
|
|
79
93
|
|
|
@@ -37,12 +37,15 @@ import type {
|
|
|
37
37
|
HeavyHookInspection,
|
|
38
38
|
} from '@cleocode/contracts';
|
|
39
39
|
import { findOnPath } from '@cleocode/paths';
|
|
40
|
+
import { projectClaudeSettingsPath } from '../claude-code/paths.js';
|
|
40
41
|
import {
|
|
41
42
|
CLAUDE_LOCAL_SETTINGS,
|
|
42
43
|
CODEX_HOOKS_FILE,
|
|
43
44
|
codexHookSnippet,
|
|
44
45
|
codexHooksSharedReason,
|
|
45
46
|
excludedByCleo,
|
|
47
|
+
excludeHookFileFromGit,
|
|
48
|
+
excludeLocalSettingsFromGit,
|
|
46
49
|
HEAVY_COMMAND_HOOK_ID,
|
|
47
50
|
HeavyHookPathBlockedError,
|
|
48
51
|
HeavyHookSharedConfigError,
|
|
@@ -212,6 +215,53 @@ async function syncStopDispatch(
|
|
|
212
215
|
}
|
|
213
216
|
}
|
|
214
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Install only CLEO's Stop dispatcher (`cleo hook stop`, T13796) for one
|
|
220
|
+
* provider in the project, whatever the heavy-command mode, and nothing
|
|
221
|
+
* else (no `PreToolUse` hook). `cleo goal install --harness claude|codex`
|
|
222
|
+
* uses it so the dispatcher runs the CLEO Goal tick (T13820). Project-level
|
|
223
|
+
* only: a project that is the home directory, a target in the user-global
|
|
224
|
+
* Claude config, or a shared `.codex/hooks.json` is refused unwritten.
|
|
225
|
+
* Never throws.
|
|
226
|
+
*
|
|
227
|
+
* @param projectDir - the project root.
|
|
228
|
+
* @param provider - `claude-code` or `codex`.
|
|
229
|
+
* @returns the outcome for that provider.
|
|
230
|
+
*/
|
|
231
|
+
export async function syncProjectStopDispatch(
|
|
232
|
+
projectDir: string,
|
|
233
|
+
provider: 'claude-code' | 'codex',
|
|
234
|
+
): Promise<HeavyHookDeliveryOutcome> {
|
|
235
|
+
let target = heavyHookTarget(provider, projectDir);
|
|
236
|
+
if (isUserHomeDir(projectDir)) {
|
|
237
|
+
return {
|
|
238
|
+
provider,
|
|
239
|
+
status: 'skipped',
|
|
240
|
+
target,
|
|
241
|
+
reason: 'the project is the home directory, whose .claude/ and .codex/ are user-global',
|
|
242
|
+
remedy: 'run it from a project directory',
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
try {
|
|
246
|
+
if (provider === 'claude-code') target = projectClaudeSettingsPath(projectDir);
|
|
247
|
+
else {
|
|
248
|
+
const shared = codexHooksSharedReason(projectDir);
|
|
249
|
+
if (shared !== null) throw new HeavyHookSharedConfigError(target, shared);
|
|
250
|
+
}
|
|
251
|
+
const status = await syncJsonStopDispatchHook(target, provider, true);
|
|
252
|
+
if (provider === 'claude-code') excludeLocalSettingsFromGit(projectDir);
|
|
253
|
+
else excludeHookFileFromGit(projectDir, CODEX_HOOKS_FILE);
|
|
254
|
+
return { provider, status, target };
|
|
255
|
+
} catch (err) {
|
|
256
|
+
return {
|
|
257
|
+
provider,
|
|
258
|
+
status: err instanceof HeavyHookSharedConfigError ? 'needs-consent' : 'failed',
|
|
259
|
+
target,
|
|
260
|
+
reason: errorText(err),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
215
265
|
async function syncProvider(
|
|
216
266
|
provider: HeavyCommandHookProvider,
|
|
217
267
|
projectDir: string,
|
|
@@ -645,6 +695,7 @@ export function probeHeavyHookCli(
|
|
|
645
695
|
/** The delivery surface `@cleocode/core` loads at run time. */
|
|
646
696
|
export const heavyHookDeliveryApi: HeavyHookDeliveryApi = Object.freeze({
|
|
647
697
|
syncProjectHeavyCommandHooks,
|
|
698
|
+
syncProjectStopDispatch,
|
|
648
699
|
inspectProjectHeavyCommandHooks,
|
|
649
700
|
probeHeavyHookCli,
|
|
650
701
|
});
|