@brunobracaioli/aibrain 0.2.0-beta.1 → 0.3.0-beta.13
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 +67 -4
- package/dist/assets/claude/.claude-plugin/plugin.json +49 -1
- package/dist/assets/claude/hooks/context-compaction.ts +6062 -734
- package/dist/assets/claude/hooks/provider-window.js +263 -0
- package/dist/assets/claude/hooks/state-fitting.d.mts +47 -0
- package/dist/assets/claude/hooks/state-fitting.mjs +324 -0
- package/dist/assets/codex-context-compaction.mjs +2690 -266
- package/dist/assets/context-selection-fitting.mjs +194 -0
- package/dist/assets/context-state-fitting.mjs +324 -0
- package/dist/assets/context-telemetry-reporter.mjs +305 -0
- package/dist/assets/jev-paid-pilot-terminal.mjs +591 -125
- package/dist/claude-checkpoint.mjs +1338 -0
- package/dist/claude-observation.mjs +1336 -0
- package/dist/cli.mjs +250 -20
- package/dist/codex-compatibility.mjs +467 -0
- package/dist/codex-diagnostics.mjs +426 -0
- package/dist/codex-permissions.mjs +590 -0
- package/dist/codex-protocol-fingerprint.json +131 -0
- package/dist/context-telemetry.mjs +257 -0
- package/dist/launch.mjs +341 -22
- package/dist/mcp.mjs +329 -7
- package/dist/monitor.mjs +11 -0
- package/dist/package.json +1 -1
- package/dist/platform.mjs +33 -3
- package/dist/state.mjs +107 -4
- package/dist/telemetry-report.mjs +133 -0
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -15,12 +15,21 @@ import {
|
|
|
15
15
|
stateRoot,
|
|
16
16
|
tokenDigest,
|
|
17
17
|
} from './state.mjs';
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
isTestedNativeVersion,
|
|
20
|
+
nativeVersion,
|
|
21
|
+
nativeVersionDiagnostic,
|
|
22
|
+
platformCheck,
|
|
23
|
+
resolveNative,
|
|
24
|
+
} from './platform.mjs';
|
|
19
25
|
import { launchClaude, launchCodex } from './launch.mjs';
|
|
26
|
+
import { codexCompatibilityError, resolveCodexCompatibility } from './codex-compatibility.mjs';
|
|
20
27
|
import { providerFreeProbe } from './mcp.mjs';
|
|
21
28
|
import { codexPolicyJson, makePolicy, publicPolicy, isProfile } from './policy.mjs';
|
|
29
|
+
import { readDiagnostics } from './claude-observation.mjs';
|
|
30
|
+
import { readCodexDiagnostics } from './codex-diagnostics.mjs';
|
|
22
31
|
|
|
23
|
-
const VERSION = '0.
|
|
32
|
+
const VERSION = '0.3.0-beta.13';
|
|
24
33
|
const ENDPOINT = 'https://mcp.ai-brain.aisac.cloud/mcp';
|
|
25
34
|
const PACKAGE_ROOT = dirname(fileURLToPath(import.meta.url));
|
|
26
35
|
const LEGACY_DISCLOSURE_VERSION = 'aibrain-paid-context-v1-2026-10-09';
|
|
@@ -29,8 +38,15 @@ function usage() {
|
|
|
29
38
|
console.log(
|
|
30
39
|
`aibrain ${VERSION}\n\nUsage:\n aibrain setup [--client claude|codex|both] [--context-profile upstream|conservative]\n [--compact-at 1..95] [--keep-threshold 0..1] [--preserve-recent 1..100]\n [--min-reduction 0..1] [--truncate-head-chars 0..4096]\n [--max-state-tokens 1000..25000] [--max-request-tokens 1000..30000]\n [--tool-policy compatible|read_only] [--goal TEXT]\n aibrain doctor [--json]\n aibrain status [--json]\n aibrain disable\n aibrain setup --undo\n aibrain claude [-- native-args...]\n aibrain codex [-- native-args...]\n\nPolicy notes:\n Automatic monitoring asks for compaction at compact-at percent; state/request\n limits are estimated upper bounds and do not override server quotas.\n min-reduction, truncate-head-chars and tool-policy apply only to Claude;\n Codex keeps native compaction and same-session recovery.`,
|
|
31
40
|
);
|
|
41
|
+
console.log(
|
|
42
|
+
'Telemetry: setup --telemetry on|off (omitted preserves the stored choice; fresh defaults off).',
|
|
43
|
+
);
|
|
44
|
+
console.log(
|
|
45
|
+
'Claude shadow: setup --claude-shadow on|off and --claude-diagnostics on|off (preview stays applied=false).',
|
|
46
|
+
);
|
|
32
47
|
}
|
|
33
48
|
|
|
49
|
+
// Telemetry is opt-in; setup omits the flag to preserve the stored choice.
|
|
34
50
|
function version() {
|
|
35
51
|
console.log(`aibrain ${VERSION}`);
|
|
36
52
|
}
|
|
@@ -141,7 +157,13 @@ function selectedPolicy(args, previous) {
|
|
|
141
157
|
const explicitProfile = option(args, '--context-profile');
|
|
142
158
|
const explicitV2 =
|
|
143
159
|
explicitProfile !== undefined ||
|
|
144
|
-
args.some(
|
|
160
|
+
args.some(
|
|
161
|
+
(item) =>
|
|
162
|
+
POLICY_OPTION_NAMES.has(item) ||
|
|
163
|
+
item === '--goal' ||
|
|
164
|
+
item === '--claude-shadow' ||
|
|
165
|
+
item === '--claude-diagnostics',
|
|
166
|
+
);
|
|
145
167
|
if (previous?.schemaVersion === 1 && !explicitV2)
|
|
146
168
|
return { v2: false, policy: makePolicy('conservative') };
|
|
147
169
|
const inherited = previous?.schemaVersion === 2 ? previous.context : undefined;
|
|
@@ -188,6 +210,100 @@ function policySummary(policy) {
|
|
|
188
210
|
return JSON.stringify({ effective: publicPolicy(policy) });
|
|
189
211
|
}
|
|
190
212
|
|
|
213
|
+
/** @param {string[]} args @param {Awaited<ReturnType<typeof readConfig>>} previous */
|
|
214
|
+
function telemetrySelection(args, previous) {
|
|
215
|
+
const requested = option(args, '--telemetry');
|
|
216
|
+
if (requested !== undefined && requested !== 'on' && requested !== 'off')
|
|
217
|
+
throw new Error('invalid_telemetry');
|
|
218
|
+
const current = previous?.telemetry;
|
|
219
|
+
const enabled = requested === undefined ? current?.enabled === true : requested === 'on';
|
|
220
|
+
return {
|
|
221
|
+
enabled,
|
|
222
|
+
disclosedAt: current?.disclosedAt ?? null,
|
|
223
|
+
};
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** @param {string[]} args @param {Awaited<ReturnType<typeof readConfig>>} previous */
|
|
227
|
+
function claudeObservationSelection(args, previous) {
|
|
228
|
+
const shadow = option(args, '--claude-shadow');
|
|
229
|
+
const diagnostics = option(args, '--claude-diagnostics');
|
|
230
|
+
for (const value of [shadow, diagnostics]) {
|
|
231
|
+
if (value !== undefined && value !== 'on' && value !== 'off')
|
|
232
|
+
throw new Error('invalid_claude_observation');
|
|
233
|
+
}
|
|
234
|
+
const current = previous?.claudeObservation;
|
|
235
|
+
const shadowEnabled = shadow === undefined ? current?.shadowEnabled === true : shadow === 'on';
|
|
236
|
+
const diagnosticsEnabled =
|
|
237
|
+
diagnostics === undefined ? current?.diagnosticsEnabled === true : diagnostics === 'on';
|
|
238
|
+
const enabled = shadowEnabled || diagnosticsEnabled;
|
|
239
|
+
return {
|
|
240
|
+
shadowEnabled,
|
|
241
|
+
diagnosticsEnabled,
|
|
242
|
+
disclosedAt: enabled
|
|
243
|
+
? (current?.disclosedAt ?? new Date().toISOString())
|
|
244
|
+
: (current?.disclosedAt ?? null),
|
|
245
|
+
};
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** @param {Awaited<ReturnType<typeof readConfig>>} previous Disable future-launch egress locally without probing the server or requiring native clients. */
|
|
249
|
+
async function disableTelemetryLocally(previous) {
|
|
250
|
+
if (!previous) {
|
|
251
|
+
console.log('Context dashboard telemetry is already disabled; no local setup exists.');
|
|
252
|
+
return;
|
|
253
|
+
}
|
|
254
|
+
const root = await ensureStateRoot();
|
|
255
|
+
await atomicJson(`${root}/config.json`, {
|
|
256
|
+
...previous,
|
|
257
|
+
telemetry: {
|
|
258
|
+
enabled: false,
|
|
259
|
+
disclosedAt: previous.telemetry?.disclosedAt ?? null,
|
|
260
|
+
},
|
|
261
|
+
});
|
|
262
|
+
console.log(
|
|
263
|
+
`Context dashboard telemetry disabled for future launches in ${root}. Close and restart currently monitored sessions to stop their launch-captured reporting settings.`,
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/** @param {Awaited<ReturnType<typeof readConfig>>} previous @param {string[]} args */
|
|
268
|
+
async function updateLocalOptOut(previous, args) {
|
|
269
|
+
const allowed = new Set([
|
|
270
|
+
'--accept-disclosure',
|
|
271
|
+
'--telemetry',
|
|
272
|
+
'off',
|
|
273
|
+
'--claude-shadow',
|
|
274
|
+
'--claude-diagnostics',
|
|
275
|
+
]);
|
|
276
|
+
const hasOptOut =
|
|
277
|
+
args.includes('--telemetry') ||
|
|
278
|
+
args.includes('--claude-shadow') ||
|
|
279
|
+
args.includes('--claude-diagnostics');
|
|
280
|
+
if (!hasOptOut || args.some((argument) => !allowed.has(argument))) return false;
|
|
281
|
+
const requestedOff =
|
|
282
|
+
option(args, '--telemetry') === 'off' ||
|
|
283
|
+
option(args, '--claude-shadow') === 'off' ||
|
|
284
|
+
option(args, '--claude-diagnostics') === 'off';
|
|
285
|
+
if (!requestedOff) return false;
|
|
286
|
+
if (!previous) {
|
|
287
|
+
console.log(
|
|
288
|
+
'AI Brain local opt-out already has no configured account; no provider call was made.',
|
|
289
|
+
);
|
|
290
|
+
return true;
|
|
291
|
+
}
|
|
292
|
+
const root = await ensureStateRoot();
|
|
293
|
+
const observation = claudeObservationSelection(args, previous);
|
|
294
|
+
const telemetry = telemetrySelection(args, previous);
|
|
295
|
+
await atomicJson(`${root}/config.json`, {
|
|
296
|
+
...previous,
|
|
297
|
+
telemetry: {
|
|
298
|
+
enabled: telemetry.enabled,
|
|
299
|
+
disclosedAt: telemetry.disclosedAt,
|
|
300
|
+
},
|
|
301
|
+
claudeObservation: observation,
|
|
302
|
+
});
|
|
303
|
+
console.log(`Local observation settings updated in ${root}; no provider call was made.`);
|
|
304
|
+
return true;
|
|
305
|
+
}
|
|
306
|
+
|
|
191
307
|
/** @param {string} endpoint */
|
|
192
308
|
function validateEndpoint(endpoint) {
|
|
193
309
|
if (endpoint.length > 2048) throw new Error('endpoint_too_long');
|
|
@@ -209,9 +325,28 @@ function validateEndpoint(endpoint) {
|
|
|
209
325
|
throw new Error('endpoint_credentials_query_or_fragment_rejected');
|
|
210
326
|
}
|
|
211
327
|
|
|
212
|
-
/** @param {string[]} args @param {string} endpoint @param {import('./policy.mjs').ContextPolicy} policy @param {string} disclosureVersion */
|
|
213
|
-
async function disclosureAccepted(
|
|
214
|
-
|
|
328
|
+
/** @param {string[]} args @param {string} endpoint @param {import('./policy.mjs').ContextPolicy} policy @param {string} disclosureVersion @param {boolean} telemetryEnabled @param {boolean} shadowEnabled @param {boolean} diagnosticsEnabled */
|
|
329
|
+
async function disclosureAccepted(
|
|
330
|
+
args,
|
|
331
|
+
endpoint,
|
|
332
|
+
policy,
|
|
333
|
+
disclosureVersion,
|
|
334
|
+
telemetryEnabled,
|
|
335
|
+
shadowEnabled,
|
|
336
|
+
diagnosticsEnabled,
|
|
337
|
+
) {
|
|
338
|
+
const telemetryDisclosure = telemetryEnabled
|
|
339
|
+
? ' Operational telemetry is enabled: only a hashed native session key, random lifecycle identifiers, client version, phase, timestamps, numeric counts and allowed measurement/reason enums are sent for the authenticated Contexto dashboard. Prompts, notes, paths, tool names, credentials and raw errors are excluded; the dashboard shows a 30-day visible window and physical cleanup runs on the next successful daily cleanup; delivery failure does not affect compaction.'
|
|
340
|
+
: '';
|
|
341
|
+
const shadowDisclosure =
|
|
342
|
+
shadowEnabled || option(args, '--claude-shadow') === 'on'
|
|
343
|
+
? ' Claude shadow observation is enabled: bounded redacted task and tool metadata may be sent through AI Brain to the existing JEV selection service for hypothetical decisions; native Claude results remain unchanged and private diagnostics exclude prompts, paths, inputs, result bodies, credentials and raw errors.'
|
|
344
|
+
: '';
|
|
345
|
+
const diagnosticsDisclosure =
|
|
346
|
+
diagnosticsEnabled || option(args, '--claude-diagnostics') === 'on'
|
|
347
|
+
? ' Claude compact diagnostics are enabled locally: bounded stages, enums, pseudonymous identifiers, timestamps and numeric measurements are stored in private rotated logs; prompts, paths, inputs, result bodies, credentials and raw errors are excluded.'
|
|
348
|
+
: '';
|
|
349
|
+
const disclosure = `AI Brain sends selected task/message/tool-input projections through AI Brain to JEV/TypeSafe at https://api.typesafe.ai/v1/systemone. Retention profile: ${policy.profile}; compact at ${policy.compactAtPercent}%; keep threshold ${policy.keepThreshold}; recent messages ${policy.preserveRecentMessages}; Claude tool policy ${policy.toolPolicy}. Selected projections are bounded and filtered; private local recovery files remain on this machine. Hidden fields and redaction limits apply; no zero-retention or complete-redaction claim. Goal present: ${policy.goal !== undefined}.${telemetryDisclosure}${shadowDisclosure}${diagnosticsDisclosure} Endpoint: ${endpoint}. Disclosure: ${disclosureVersion}.`;
|
|
215
350
|
if (args.includes('--accept-disclosure')) {
|
|
216
351
|
console.log(disclosure);
|
|
217
352
|
return true;
|
|
@@ -241,6 +376,9 @@ async function setup(args) {
|
|
|
241
376
|
'--context-profile',
|
|
242
377
|
...POLICY_OPTION_NAMES,
|
|
243
378
|
'--goal',
|
|
379
|
+
'--telemetry',
|
|
380
|
+
'--claude-shadow',
|
|
381
|
+
'--claude-diagnostics',
|
|
244
382
|
]),
|
|
245
383
|
new Set([
|
|
246
384
|
'--client',
|
|
@@ -249,25 +387,51 @@ async function setup(args) {
|
|
|
249
387
|
'--context-profile',
|
|
250
388
|
...POLICY_OPTION_NAMES,
|
|
251
389
|
'--goal',
|
|
390
|
+
'--telemetry',
|
|
391
|
+
'--claude-shadow',
|
|
392
|
+
'--claude-diagnostics',
|
|
252
393
|
]),
|
|
253
394
|
);
|
|
254
395
|
if (args.includes('--undo') && args.length !== 1)
|
|
255
396
|
throw new Error('setup_undo_cannot_have_options');
|
|
256
397
|
const previous = await readConfig();
|
|
398
|
+
if (await updateLocalOptOut(previous, args)) return;
|
|
399
|
+
const localOptOut =
|
|
400
|
+
option(args, '--telemetry') === 'off' &&
|
|
401
|
+
args.every((argument) => ['--telemetry', 'off', '--accept-disclosure'].includes(argument));
|
|
402
|
+
if (localOptOut) return disableTelemetryLocally(previous);
|
|
257
403
|
const platform = platformCheck();
|
|
258
404
|
if (!platform.ok) throw new Error(`${platform.code}:${platform.message}`);
|
|
259
405
|
const clients = option(args, '--client') ?? 'both';
|
|
260
406
|
if (!['claude', 'codex', 'both'].includes(clients)) throw new Error('invalid_client');
|
|
407
|
+
if (
|
|
408
|
+
clients === 'codex' &&
|
|
409
|
+
(option(args, '--claude-shadow') !== undefined ||
|
|
410
|
+
option(args, '--claude-diagnostics') !== undefined)
|
|
411
|
+
)
|
|
412
|
+
throw new Error('claude_observation_requires_claude_client');
|
|
261
413
|
const endpoint = option(args, '--endpoint') ?? ENDPOINT;
|
|
262
414
|
validateEndpoint(endpoint);
|
|
263
415
|
const selection = selectedPolicy(args, previous);
|
|
416
|
+
const telemetry = telemetrySelection(args, previous);
|
|
417
|
+
const claudeObservation = claudeObservationSelection(args, previous);
|
|
264
418
|
const policy = selection.policy;
|
|
265
419
|
const disclosureVersion = selection.v2
|
|
266
420
|
? DISCLOSURE_VERSION
|
|
267
421
|
: (previous?.disclosureVersion ?? LEGACY_DISCLOSURE_VERSION);
|
|
268
422
|
if (selection.v2 && (clients === 'codex' || clients === 'both')) codexPolicyJson(policy);
|
|
269
423
|
console.log(`Effective context policy ${policySummary(policy)}`);
|
|
270
|
-
if (
|
|
424
|
+
if (
|
|
425
|
+
!(await disclosureAccepted(
|
|
426
|
+
args,
|
|
427
|
+
endpoint,
|
|
428
|
+
policy,
|
|
429
|
+
disclosureVersion,
|
|
430
|
+
telemetry.enabled,
|
|
431
|
+
claudeObservation.shadowEnabled,
|
|
432
|
+
claudeObservation.diagnosticsEnabled,
|
|
433
|
+
))
|
|
434
|
+
)
|
|
271
435
|
throw new Error('disclosure_not_accepted');
|
|
272
436
|
const root = await ensureStateRoot();
|
|
273
437
|
const tokenPath = option(args, '--token-file');
|
|
@@ -281,13 +445,16 @@ async function setup(args) {
|
|
|
281
445
|
if ((clients === 'codex' || clients === 'both') && (!codex || !node))
|
|
282
446
|
throw new Error('codex_or_node_not_found');
|
|
283
447
|
const claudeVersion = claude ? nativeVersion(claude) : null;
|
|
284
|
-
const codexVersion = codex ? nativeVersion(codex) : null;
|
|
285
448
|
const claudeSupported = claudeVersion !== null && isTestedNativeVersion('claude', claudeVersion);
|
|
286
|
-
const codexSupported = codexVersion !== null && isTestedNativeVersion('codex', codexVersion);
|
|
287
449
|
if ((clients === 'claude' || clients === 'both') && !claudeSupported)
|
|
288
|
-
throw new Error('
|
|
289
|
-
|
|
290
|
-
|
|
450
|
+
throw new Error(nativeVersionDiagnostic('claude', claudeVersion ?? ''));
|
|
451
|
+
let codexCompatibility = null;
|
|
452
|
+
if (clients === 'codex' || clients === 'both') {
|
|
453
|
+
codexCompatibility = codex ? await resolveCodexCompatibility(codex) : null;
|
|
454
|
+
if (codexCompatibility?.status === 'rejected')
|
|
455
|
+
throw new Error(codexCompatibilityError(codexCompatibility));
|
|
456
|
+
}
|
|
457
|
+
const codexVersion = codexCompatibility?.version ?? (codex ? nativeVersion(codex) : null);
|
|
291
458
|
const config = {
|
|
292
459
|
schemaVersion: selection.v2 ? 2 : 1,
|
|
293
460
|
packageVersion: VERSION,
|
|
@@ -299,6 +466,13 @@ async function setup(args) {
|
|
|
299
466
|
codexVersion,
|
|
300
467
|
packageRoot: PACKAGE_ROOT,
|
|
301
468
|
...(selection.v2 ? { context: policy } : {}),
|
|
469
|
+
telemetry: {
|
|
470
|
+
enabled: telemetry.enabled,
|
|
471
|
+
disclosedAt: telemetry.enabled
|
|
472
|
+
? (telemetry.disclosedAt ?? new Date().toISOString())
|
|
473
|
+
: telemetry.disclosedAt,
|
|
474
|
+
},
|
|
475
|
+
claudeObservation,
|
|
302
476
|
};
|
|
303
477
|
let probe;
|
|
304
478
|
try {
|
|
@@ -345,10 +519,16 @@ async function doctor(json) {
|
|
|
345
519
|
codex: resolveNative('codex'),
|
|
346
520
|
node: resolveNative('node'),
|
|
347
521
|
};
|
|
348
|
-
const
|
|
522
|
+
const rawNativeVersions = {
|
|
349
523
|
claude: native.claude ? nativeVersion(native.claude) : '',
|
|
350
524
|
codex: native.codex ? nativeVersion(native.codex) : '',
|
|
351
525
|
};
|
|
526
|
+
const codexCompatibility =
|
|
527
|
+
native.codex !== null ? await resolveCodexCompatibility(native.codex) : null;
|
|
528
|
+
const nativeVersions = {
|
|
529
|
+
...rawNativeVersions,
|
|
530
|
+
codex: codexCompatibility?.version ?? rawNativeVersions.codex,
|
|
531
|
+
};
|
|
352
532
|
const needsClaude = config?.clientSelection === 'claude' || config?.clientSelection === 'both';
|
|
353
533
|
const needsCodex = config?.clientSelection === 'codex' || config?.clientSelection === 'both';
|
|
354
534
|
const nativeReady =
|
|
@@ -357,7 +537,8 @@ async function doctor(json) {
|
|
|
357
537
|
(!needsCodex ||
|
|
358
538
|
(native.codex !== null &&
|
|
359
539
|
native.node !== null &&
|
|
360
|
-
|
|
540
|
+
(codexCompatibility?.status === 'qualified' ||
|
|
541
|
+
codexCompatibility?.status === 'protocol_match')));
|
|
361
542
|
const result = {
|
|
362
543
|
version: VERSION,
|
|
363
544
|
platform: platform.ok ? process.platform : platform.code,
|
|
@@ -371,8 +552,23 @@ async function doctor(json) {
|
|
|
371
552
|
node: native.node !== null,
|
|
372
553
|
},
|
|
373
554
|
nativeVersions,
|
|
555
|
+
codexCompatibility: codexCompatibility?.status ?? 'unavailable',
|
|
556
|
+
codexCompatibilityReason: codexCompatibility?.reason ?? 'codex_not_found',
|
|
557
|
+
codexCompatibilityVersion: codexCompatibility?.version ?? null,
|
|
374
558
|
nativeReady,
|
|
375
559
|
context: publicPolicy(policy),
|
|
560
|
+
telemetry: {
|
|
561
|
+
enabled: config?.telemetry?.enabled === true,
|
|
562
|
+
disclosed:
|
|
563
|
+
config?.telemetry?.disclosedAt !== null && config?.telemetry?.disclosedAt !== undefined,
|
|
564
|
+
},
|
|
565
|
+
claudeObservation: {
|
|
566
|
+
shadowEnabled: config?.claudeObservation?.shadowEnabled === true,
|
|
567
|
+
diagnosticsEnabled: config?.claudeObservation?.diagnosticsEnabled === true,
|
|
568
|
+
disclosed:
|
|
569
|
+
config?.claudeObservation?.disclosedAt !== null &&
|
|
570
|
+
config?.claudeObservation?.disclosedAt !== undefined,
|
|
571
|
+
},
|
|
376
572
|
paidOrPilot: probe?.ok
|
|
377
573
|
? 'provider_free_probe_ok; paid entitlement or pilot invitation remains server-enforced'
|
|
378
574
|
: config
|
|
@@ -396,6 +592,18 @@ async function status(json) {
|
|
|
396
592
|
disclosed: config?.disclosureVersion !== undefined,
|
|
397
593
|
schemaVersion: config?.schemaVersion ?? null,
|
|
398
594
|
context: publicPolicy(policy),
|
|
595
|
+
telemetry: {
|
|
596
|
+
enabled: config?.telemetry?.enabled === true,
|
|
597
|
+
disclosed:
|
|
598
|
+
config?.telemetry?.disclosedAt !== null && config?.telemetry?.disclosedAt !== undefined,
|
|
599
|
+
},
|
|
600
|
+
claudeObservation: {
|
|
601
|
+
shadowEnabled: config?.claudeObservation?.shadowEnabled === true,
|
|
602
|
+
diagnosticsEnabled: config?.claudeObservation?.diagnosticsEnabled === true,
|
|
603
|
+
disclosed:
|
|
604
|
+
config?.claudeObservation?.disclosedAt !== null &&
|
|
605
|
+
config?.claudeObservation?.disclosedAt !== undefined,
|
|
606
|
+
},
|
|
399
607
|
monitoredSession: null,
|
|
400
608
|
monitoringStatus: 'not_observed',
|
|
401
609
|
};
|
|
@@ -423,6 +631,27 @@ async function main(argv) {
|
|
|
423
631
|
validateOptions(rest, new Set(['--json']), new Set());
|
|
424
632
|
return status(rest.includes('--json'));
|
|
425
633
|
}
|
|
634
|
+
if (command === 'diagnostics') {
|
|
635
|
+
validateOptions(
|
|
636
|
+
rest,
|
|
637
|
+
new Set(['--client', '--tail', '--json']),
|
|
638
|
+
new Set(['--client', '--tail']),
|
|
639
|
+
);
|
|
640
|
+
const requestedClient = option(rest, '--client');
|
|
641
|
+
if (requestedClient !== undefined && !['claude', 'codex'].includes(requestedClient))
|
|
642
|
+
throw new Error('diagnostics_client_unsupported');
|
|
643
|
+
const tail = Number(option(rest, '--tail') ?? '20');
|
|
644
|
+
if (!Number.isSafeInteger(tail) || tail < 1 || tail > 100)
|
|
645
|
+
throw new Error('invalid_diagnostics_tail');
|
|
646
|
+
const client = requestedClient ?? 'claude';
|
|
647
|
+
const records =
|
|
648
|
+
client === 'codex'
|
|
649
|
+
? await readCodexDiagnostics(stateRoot(), tail)
|
|
650
|
+
: await readDiagnostics(stateRoot(), tail);
|
|
651
|
+
if (rest.includes('--json')) console.log(JSON.stringify({ client, records }));
|
|
652
|
+
else console.log(records);
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
426
655
|
if (command === 'disable') {
|
|
427
656
|
if (rest.length > 0) throw new Error('disable_does_not_accept_options');
|
|
428
657
|
return removeOwnedSetup();
|
|
@@ -439,12 +668,13 @@ async function main(argv) {
|
|
|
439
668
|
(typeof config.claudeVersion !== 'string' ||
|
|
440
669
|
!isTestedNativeVersion('claude', config.claudeVersion))
|
|
441
670
|
)
|
|
442
|
-
throw new Error(
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
671
|
+
throw new Error(
|
|
672
|
+
nativeVersionDiagnostic(
|
|
673
|
+
'claude',
|
|
674
|
+
typeof config.claudeVersion === 'string' ? config.claudeVersion : '',
|
|
675
|
+
),
|
|
676
|
+
);
|
|
677
|
+
if (command === 'codex' && typeof config.codexVersion !== 'string')
|
|
448
678
|
throw new Error('codex_version_unverified');
|
|
449
679
|
const root = stateRoot();
|
|
450
680
|
const result = await (command === 'claude'
|