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
| @@ -105,6 +105,11 @@ | ||
| 105 | 105 | registerCommand: (spec: CommandSpec) => Promise<unknown> |
| 106 | 106 | |
| 107 | 107 | /** |
| 108 | + * `$.session.id`: the session the pane-shown row is latched to. | |
| 109 | + */ | |
| 110 | + sessionId: () => Promise<string> | |
| 111 | + | |
| 112 | + /** | |
| 108 | 113 | * `$.telemetry.mark`; rejects where the telemetry built-in is absent. |
| 109 | 114 | */ |
| 110 | 115 | mark: EngineInterface['telemetry']['mark'] |
| @@ -3,11 +3,12 @@ | ||
| 3 | 3 | * feature surface keeps one series across the swap. |
| 4 | 4 | * |
| 5 | 5 | * `read` per fetch round, `tabSwitch` per open or close, `baseSwitch` per |
| 6 | - * base pick, `baseResolve` once a session. | |
| 6 | + * base pick, `baseResolve` once a session, `selectionAttach` per diff asked. | |
| 7 | 7 | */ |
| 8 | 8 | export const FEATURES = { |
| 9 | 9 | read: 'repl_diff_read', |
| 10 | 10 | tabSwitch: 'repl_tab_switch', |
| 11 | 11 | baseSwitch: 'repl_diff_base_switch', |
| 12 | 12 | baseResolve: 'diff_base_resolve', |
| 13 | + selectionAttach: 'diff_selection_attach', | |
| 13 | 14 | } as const |
| @@ -13,7 +13,7 @@ | ||
| 13 | 13 | mark: (feature: string, outcome: MarkOutcome) => void |
| 14 | 14 | |
| 15 | 15 | /** |
| 16 | - * `tengu_plugin_diff_pane_shown`, once a session. | |
| 16 | + * The built-in panel's `tengu_repl_diff_panel_shown` row, once a session. | |
| 17 | 17 | */ |
| 18 | 18 | shown: ( |
| 19 | 19 | trigger: (typeof SHOWN_TRIGGERS)[number], |
| @@ -21,7 +21,8 @@ | ||
| 21 | 21 | ) => void |
| 22 | 22 | |
| 23 | 23 | /** |
| 24 | - * `tengu_plugin_diff_ask_attach`: a file's diff rode the next prompt. | |
| 24 | + * The built-in's `diff_selection_attach` feature mark: a file's diff rode | |
| 25 | + * the next prompt. | |
| 25 | 26 | */ |
| 26 | - asked: (lines: number) => void | |
| 27 | + asked: () => void | |
| 27 | 28 | } |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | import type { Host } from '../host' |
| 2 | +import { FEATURES } from './features' | |
| 2 | 3 | import type { Recorder } from './recorder' |
| 3 | 4 | import { safely } from './safely' |
| 4 | 5 | import { SHOWN_TRIGGERS } from './shown-triggers' |
| @@ -6,7 +7,8 @@ | ||
| 6 | 7 | |
| 7 | 8 | /** |
| 8 | 9 | * The plugin's Recorder over the host: each row goes through the telemetry |
| 9 | - * built-in's `$.telemetry`; a missing noun or a refused row is dropped. | |
| 10 | + * built-in's `$.telemetry`, named and shaped as the built-in panel's own; | |
| 11 | + * a missing noun or a refused row is dropped. | |
| 10 | 12 | * |
| 11 | 13 | * @param host the engine as session.start bound it |
| 12 | 14 | * @returns the recorder |
| @@ -16,13 +18,13 @@ | ||
| 16 | 18 | shown: (trigger, bucket) => |
| 17 | 19 | safely(() => |
| 18 | 20 | host.log({ |
| 19 | - event: 'diff_pane_shown', | |
| 21 | + event: 'tengu_repl_diff_panel_shown', | |
| 20 | 22 | props: { |
| 21 | 23 | trigger: { value: trigger, of: SHOWN_TRIGGERS }, |
| 22 | - width_bucket: { value: bucket, of: WIDTH_BUCKETS }, | |
| 24 | + terminal_width_bucket: { value: bucket, of: WIDTH_BUCKETS }, | |
| 23 | 25 | }, |
| 24 | 26 | }), |
| 25 | 27 | ), |
| 26 | - asked: lines => | |
| 27 | - safely(() => host.log({ event: 'diff_ask_attach', props: { lines } })), | |
| 28 | + asked: () => | |
| 29 | + safely(() => host.mark({ feature: FEATURES.selectionAttach, kind: 'ok' })), | |
| 28 | 30 | }) |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | /** |
| 2 | - * The terminal-width buckets `diff_pane_shown` reports, the built-in's | |
| 3 | - * `tengu_repl_diff_panel_shown` buckets. | |
| 2 | + * The terminal-width buckets the pane-shown row reports, the built-in | |
| 3 | + * panel's own. | |
| 4 | 4 | */ |
| 5 | 5 | export const WIDTH_BUCKETS = [ |
| 6 | 6 | 'under_110', |
| @@ -37,7 +37,7 @@ | ||
| 37 | 37 | let isPaneOpen = false |
| 38 | 38 | let hasAutoOpened = false |
| 39 | 39 | let columns: number | null = null |
| 40 | - let hasShownOnce = false | |
| 40 | + let shownSessionId: string | null = null | |
| 41 | 41 | let wasDrawnSinceProbe = false |
| 42 | 42 | let armed: Ask.ArmedAsk | null = null |
| 43 | 43 | let carrying: Ask.ArmedAsk | null = null |
| @@ -288,9 +288,10 @@ | ||
| 288 | 288 | isPaneOpen = true |
| 289 | 289 | const record = Record.recorderOf(engine) |
| 290 | 290 | record.mark(Record.FEATURES.tabSwitch, { kind: 'ok' }) |
| 291 | + const sessionId = await engine.sessionId().catch(() => null) | |
| 291 | 292 | |
| 292 | - if (!hasShownOnce) { | |
| 293 | - hasShownOnce = true | |
| 293 | + if (sessionId !== null && sessionId !== shownSessionId) { | |
| 294 | + shownSessionId = sessionId | |
| 294 | 295 | record.shown(trigger, Record.widthBucketOf(columns)) |
| 295 | 296 | } |
| 296 | 297 | |
| @@ -464,6 +465,7 @@ | ||
| 464 | 465 | openPane: pane => $.ui.open(pane), |
| 465 | 466 | closePane: pane => $.ui.close(pane), |
| 466 | 467 | registerCommand: spec => $.command.register(spec), |
| 468 | + sessionId: () => $.session.id(), | |
| 467 | 469 | mark: entry => $.telemetry.mark(entry), |
| 468 | 470 | log: entry => $.telemetry.log(entry), |
| 469 | 471 | }) |
| @@ -621,7 +623,7 @@ | ||
| 621 | 623 | const result = await next({ ...e, context: [...context, text] }) |
| 622 | 624 | |
| 623 | 625 | if (result.drop === undefined) { |
| 624 | - Record.recorderOf(host).asked(asked.lines) | |
| 626 | + Record.recorderOf(host).asked() | |
| 625 | 627 | |
| 626 | 628 | if (armed === asked) { |
| 627 | 629 | disarm(host) |