Skip to content

Commit 77d1af2

Browse files
committed
fix: withAddTelemetry defensive init, PolicyEnginePrimitive keeps telemetry in CLI handler
1 parent 12b0e12 commit 77d1af2

2 files changed

Lines changed: 68 additions & 41 deletions

File tree

src/cli/primitives/PolicyEnginePrimitive.ts

Lines changed: 65 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ import type { AgentCoreProjectSpec, PolicyEngine } from '../../schema';
33
import { PolicyEngineModeSchema, PolicyEngineSchema } from '../../schema';
44
import { getErrorMessage } from '../errors';
55
import type { RemovalPreview, RemovalResult, SchemaChange } from '../operations/remove/types';
6-
import { cliCommandRun, withAddTelemetry } from '../telemetry/cli-command-run.js';
6+
import { cliCommandRun } from '../telemetry/cli-command-run.js';
7+
import { TelemetryClientAccessor } from '../telemetry/client-accessor.js';
8+
import type { CommandAttrs } from '../telemetry/schemas/command-run.js';
9+
import { AttachMode, standardize } from '../telemetry/schemas/common-shapes.js';
710
import { requireTTY } from '../tui/guards/tty';
811
import { BasePrimitive } from './BasePrimitive';
912
import { SOURCE_CODE_NOTE } from './constants';
@@ -22,27 +25,25 @@ export class PolicyEnginePrimitive extends BasePrimitive<AddPolicyEngineOptions,
2225
readonly primitiveSchema = PolicyEngineSchema;
2326

2427
async add(options: AddPolicyEngineOptions): Promise<AddResult<{ engineName: string }>> {
25-
return withAddTelemetry('add.policy-engine', { attach_gateway_count: 0, attach_mode: 'log_only' }, async () => {
26-
try {
27-
const project = await this.readProjectSpec();
28+
try {
29+
const project = await this.readProjectSpec();
2830

29-
this.checkDuplicate(project.policyEngines, options.name);
31+
this.checkDuplicate(project.policyEngines, options.name);
3032

31-
const engine: PolicyEngine = {
32-
name: options.name,
33-
...(options.description && { description: options.description }),
34-
...(options.encryptionKeyArn && { encryptionKeyArn: options.encryptionKeyArn }),
35-
policies: [],
36-
};
33+
const engine: PolicyEngine = {
34+
name: options.name,
35+
...(options.description && { description: options.description }),
36+
...(options.encryptionKeyArn && { encryptionKeyArn: options.encryptionKeyArn }),
37+
policies: [],
38+
};
3739

38-
project.policyEngines.push(engine);
39-
await this.writeProjectSpec(project);
40+
project.policyEngines.push(engine);
41+
await this.writeProjectSpec(project);
4042

41-
return { success: true, engineName: engine.name };
42-
} catch (err) {
43-
return { success: false, error: getErrorMessage(err) };
44-
}
45-
});
43+
return { success: true, engineName: engine.name };
44+
} catch (err) {
45+
return { success: false, error: getErrorMessage(err) };
46+
}
4647
}
4748

4849
async remove(engineName: string): Promise<RemovalResult> {
@@ -235,30 +236,56 @@ export class PolicyEnginePrimitive extends BasePrimitive<AddPolicyEngineOptions,
235236
throw new Error('--name is required');
236237
}
237238

238-
const result = await this.add({
239-
name: cliOptions.name,
240-
description: cliOptions.description,
241-
encryptionKeyArn: cliOptions.encryptionKeyArn,
242-
});
243-
244-
// Attach to gateways if requested
245-
if (result.success && cliOptions.attachToGateways) {
246-
const mode = PolicyEngineModeSchema.parse(cliOptions.attachMode ?? 'LOG_ONLY');
247-
const gateways = cliOptions.attachToGateways
248-
.split(',')
249-
.map(s => s.trim())
250-
.filter(Boolean);
251-
await this.attachToGateways(cliOptions.name, gateways, mode);
239+
const gatewayNames = cliOptions.attachToGateways
240+
? cliOptions.attachToGateways
241+
.split(',')
242+
.map(s => s.trim())
243+
.filter(Boolean)
244+
: [];
245+
const attachMode = cliOptions.attachMode ?? 'LOG_ONLY';
246+
const telemetryAttrs: CommandAttrs<'add.policy-engine'> = {
247+
attach_gateway_count: gatewayNames.length,
248+
attach_mode: standardize(AttachMode, attachMode),
249+
};
250+
251+
let client;
252+
try {
253+
client = await TelemetryClientAccessor.get();
254+
} catch {
255+
/* telemetry init failed */
252256
}
253257

254-
if (!result.success) {
255-
throw new Error(result.error);
256-
}
258+
const name = cliOptions.name;
259+
260+
const run = async () => {
261+
const result = await this.add({
262+
name,
263+
description: cliOptions.description,
264+
encryptionKeyArn: cliOptions.encryptionKeyArn,
265+
});
266+
267+
if (result.success && gatewayNames.length > 0) {
268+
const mode = PolicyEngineModeSchema.parse(attachMode);
269+
await this.attachToGateways(name, gatewayNames, mode);
270+
}
271+
272+
if (!result.success) {
273+
throw new Error(result.error);
274+
}
275+
276+
if (cliOptions.json) {
277+
console.log(JSON.stringify(result));
278+
} else {
279+
console.log(`Added policy engine '${result.engineName}'`);
280+
}
281+
282+
return telemetryAttrs;
283+
};
257284

258-
if (cliOptions.json) {
259-
console.log(JSON.stringify(result));
285+
if (client) {
286+
await client.withCommandRun('add.policy-engine', run);
260287
} else {
261-
console.log(`Added policy engine '${result.engineName}'`);
288+
await run();
262289
}
263290
});
264291
} else {

src/cli/telemetry/cli-command-run.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@ export async function withAddTelemetry<C extends Command, T extends Record<strin
3939
return fn();
4040
}
4141

42-
let result!: AddResult<T>;
42+
let result: AddResult<T> | undefined;
4343
try {
4444
await client.withCommandRun(command, async () => {
4545
result = await fn();
4646
if (!result.success) throw new Error(result.error);
4747
return attrs;
4848
});
4949
} catch {
50-
// withCommandRun already recorded the failure; swallow the re-throw
50+
if (!result) return fn();
5151
}
52-
return result;
52+
return result!;
5353
}

0 commit comments

Comments
 (0)