spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic · github.com/anthropics

telemetry: the test plugins a person installed hook and call the collector's stream by nameBrowse files
poteat authored 28 days ago parent 6557bbe · commit 6239bb50143e
7 changed files+34 -22compared with 6557bbe
Mmods/telemetry/tests/fixtures/plugins/holding.ts
Mmods/telemetry/tests/fixtures/plugins/meddling.ts
Mmods/telemetry/tests/fixtures/plugins/reaching.ts
Mmods/telemetry/tests/fixtures/plugins/replacing.ts
Mmods/telemetry/tests/fixtures/plugins/swallowing.ts
Mmods/telemetry/tests/fixtures/plugins/visiting.ts
Mmods/telemetry/tests/gate.test.ts
@@ -21,7 +21,7 @@
2121 })
2222
2323 on('command.run', { command: 'hold' }, async () => {
24- await held?.telemetry.log({ event: 'held' })
24+ await held?.telemetry.log({ to: 'collector', event: 'held' })
2525
2626 return { text: 'served' }
2727 })
@@ -1,17 +1,20 @@
11 import type { Plugin } from 'claude-code/testing'
22
33 /**
4- * A plugin a person installed that hooks `telemetry.log` above the gate to
5- * rename every row, and logs one of its own through `/meddle`.
4+ * A plugin a person installed that hooks `telemetry.log` above the gate for
5+ * the one stream it may, the collector's, to rename every record there, and
6+ * logs one of its own through `/meddle`.
67 */
78 export const meddling: Plugin = {
89 name: 'meddling',
910 tier: 'user',
1011 register(on) {
11- on('telemetry.log', (_$, e, next) => next({ ...e, event: 'renamed' }))
12+ on('telemetry.log', { to: 'collector' }, (_$, e, next) =>
13+ next({ ...e, event: 'renamed' }),
14+ )
1215
1316 on('command.run', { command: 'meddle' }, $ =>
14- $.telemetry.log({ event: 'mine' }).then(
17+ $.telemetry.log({ to: 'collector', event: 'mine' }).then(
1518 () => ({ text: 'served' }),
1619 (error: unknown) => ({ text: String(error) }),
1720 ),
@@ -17,7 +17,7 @@
1717 const beneath = await next(e)
1818
1919 during = await beneath.telemetry
20- .log({ event: 'during_create' })
20+ .log({ to: 'collector', event: 'during_create' })
2121 .then(() => 'served', String)
2222
2323 return beneath
@@ -26,7 +26,7 @@
2626 on('session.start', ($, e, next) => {
2727 $.clock.after(1, () => {
2828 void $.telemetry
29- .log({ event: 'from_timer' })
29+ .log({ to: 'collector', event: 'from_timer' })
3030 .then(() => 'served', String)
3131 .then(outcome => $.ui.log(`timer: ${outcome}`, { to: 'debug' }))
3232 })
@@ -36,7 +36,7 @@
3636
3737 on('tool.call', { tool: 'Read' }, async ($, e, next) => {
3838 const outcome = await $.telemetry
39- .log({ event: 'from_tool' })
39+ .log({ to: 'collector', event: 'from_tool' })
4040 .then(() => 'served', String)
4141
4242 await $.ui.log(`tool: ${outcome}`, { to: 'debug' })
@@ -16,7 +16,7 @@
1616 }))
1717
1818 on('command.run', { command: 'replace' }, $ =>
19- $.telemetry.log({ event: 'mine' }).then(
19+ $.telemetry.log({ to: 'collector', event: 'mine' }).then(
2020 () => ({ text: 'served' }),
2121 (error: unknown) => ({ text: String(error) }),
2222 ),
@@ -2,12 +2,13 @@
22
33 /**
44 * A plugin a person installed that answers `telemetry.log` above the gate
5- * without going on beneath: the rows of everyone beneath it stop there.
5+ * without going on beneath, for the one stream it may hook, the
6+ * collector's: the records of everyone beneath it stop there.
67 */
78 export const swallowing: Plugin = {
89 name: 'swallowing',
910 tier: 'user',
1011 register(on) {
11- on('telemetry.log', () => ({ value: undefined }))
12+ on('telemetry.log', { to: 'collector' }, () => ({ value: undefined }))
1213 },
1314 }
@@ -1,18 +1,21 @@
11 import type { Plugin } from 'claude-code/testing'
22
33 /**
4- * A plugin a person installed whose `/visit <entry>` logs the entry through
5- * `$.telemetry`, answering "queued", or why the row was refused.
4+ * A plugin a person installed whose `/visit <entry>` logs the entry's event
5+ * and properties through `$.telemetry`, naming the one stream it may, the
6+ * collector's; it answers "queued", or why the call was refused.
67 */
78 export const visiting: Plugin = {
89 name: 'visiting',
910 tier: 'user',
1011 register(on) {
11- on('command.run', { command: 'visit' }, ($, e) =>
12- $.telemetry.log(JSON.parse(e.args)).then(
12+ on('command.run', { command: 'visit' }, ($, e) => {
13+ const { event, props } = JSON.parse(e.args)
14+
15+ return $.telemetry.log({ to: 'collector', event, props }).then(
1316 () => ({ text: 'queued' }),
1417 (error: unknown) => ({ text: String(error) }),
15- ),
16- )
18+ )
19+ })
1720 },
1821 }
@@ -61,7 +61,7 @@
6161 )
6262
6363 test(
64- 'a hook above may rename a row a built-in sends, never send its own',
64+ "a hook above on the collector's stream renames no row, sends none",
6565 { plugins: [Fixtures.recording, Fixtures.meddling] },
6666 async ($, on) => {
6767 mock.env(on, Fixtures.SENDING_ENV)
@@ -77,13 +77,13 @@
7777 rows: Fixtures.rowsOf(session).map(Fixtures.eventNameOf),
7878 }).toEqual({
7979 own: `HooksError: meddling: $.telemetry.log: ${Hooks.REFUSED.deny}`,
80- rows: ['tengu_plugin_renamed'],
80+ rows: ['tengu_plugin_survey_answered'],
8181 })
8282 },
8383 )
8484
8585 test(
86- 'a hook above that answers without going on sends nothing at all',
86+ "a hook above that swallows the collector's stream stops no row",
8787 { plugins: [Fixtures.recording, Fixtures.swallowing] },
8888 async ($, on) => {
8989 mock.env(on, Fixtures.SENDING_ENV)
@@ -96,9 +96,14 @@
9696
9797 await session.clock.advance(Hooks.BATCH_WINDOW_MS)
9898
99- expect({ answer, posts: session.posts }).toEqual({
99+ expect({
100+ answer,
101+ posts: session.posts.length,
102+ rows: Fixtures.rowsOf(session).map(Fixtures.eventNameOf),
103+ }).toEqual({
100104 answer: 'queued',
101- posts: [],
105+ posts: 1,
106+ rows: ['tengu_plugin_survey_answered'],
102107 })
103108 },
104109 )