koneck 2.68.0 → 2.69.0

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.
@@ -28,6 +28,19 @@ export type WebEvent =
28
28
  seq: number;
29
29
  text: string;
30
30
  images?: number;
31
+ /**
32
+ * What an `@` in the message actually attached.
33
+ *
34
+ * Reported rather than assumed, because attaching a file spends tokens and a spend nobody can
35
+ * see is a spend nobody can question. The transcript shows the sentence as typed; this says
36
+ * what was added beneath it, and what could not be.
37
+ */
38
+ refs?: Array<{
39
+ ref: string;
40
+ kind: string;
41
+ lines: number | null;
42
+ note?: string;
43
+ }>;
31
44
  }
32
45
  /** A piece of the reply as it streams. */
33
46
  | {
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/web/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/web/events.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/web/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AA2DH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAalC,MAAM,OAAO,QAAQ;IACF,GAAG,GAAe,EAAE,CAAC;IACrB,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,GAAG,GAAG,CAAC,CAAC;IAEhB,oEAAoE;IACpE,IAAI,CAAC,KAAc;QACjB,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,EAAc,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,YAAY;YAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACrD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,4EAA4E;YAC5E,IAAI,CAAC;gBAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,sCAAsC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,KAAK,GAAG,CAAC;QACb,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IAC1E,CAAC;IAED,SAAS,CAAC,EAAyB;QACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,QAAQ,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,OAAO,KAAa,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3C"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/web/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAmEH;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,CAAC;AAalC,MAAM,OAAO,QAAQ;IACF,GAAG,GAAe,EAAE,CAAC;IACrB,OAAO,GAAG,IAAI,GAAG,EAAyB,CAAC;IACpD,GAAG,GAAG,CAAC,CAAC;IAEhB,oEAAoE;IACpE,IAAI,CAAC,KAAc;QACjB,MAAM,IAAI,GAAG,EAAE,GAAG,KAAK,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,CAAC,GAAG,EAAc,CAAC;QACnF,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,IAAI,CAAC,GAAG,CAAC,MAAM,GAAG,YAAY;YAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;QACrD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,4EAA4E;YAC5E,IAAI,CAAC;gBAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,sCAAsC,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,kEAAkE;IAClE,KAAK,CAAC,KAAK,GAAG,CAAC;QACb,OAAO,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,CAAC;IAC1E,CAAC;IAED,SAAS,CAAC,EAAyB;QACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACrB,OAAO,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5C,CAAC;IAED,IAAI,QAAQ,KAAa,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;IACpD,IAAI,OAAO,KAAa,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;CAC3C"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * What the workspace knows about which file you meant.
3
+ *
4
+ * `rankMentions` takes three lists and stays pure so it can be tested against fixed input. This is
5
+ * where the lists come from, and each one is cheap on purpose: a picker that reads the ledger and
6
+ * shells out to git on every keystroke stops being a picker and becomes a wait. So the signals are
7
+ * gathered once when the dropdown opens and reused for the rest of the typing.
8
+ */
9
+ import type { TrajectoryEvent } from '../trajectory.js';
10
+ import type { Signals } from './mention.js';
11
+ /**
12
+ * Files this session has actually handled, most recent first.
13
+ *
14
+ * Read from the trajectory rather than tracked separately, because the trajectory is already the
15
+ * record of what happened and a second list of the same thing is a second list to get wrong. Only
16
+ * the tools whose detail is a path: `execute_command` puts a command line there and `grep_search`
17
+ * puts a pattern, and either one offered as a filename is noise.
18
+ */
19
+ export declare function sessionPaths(events: readonly TrajectoryEvent[], limit?: number): string[];
20
+ /**
21
+ * Files git has touched lately, uncommitted first.
22
+ *
23
+ * Uncommitted first because that is a stronger statement about what the project is in the middle of
24
+ * than a commit from yesterday: work in the tree is work in progress. Then the recent commits,
25
+ * which is how a file you finished this morning stays near the top.
26
+ *
27
+ * Failure is silence. A directory that is not a repository is a perfectly ordinary place to work,
28
+ * and a picker that reported an error for it would be reporting its own assumption.
29
+ */
30
+ export declare function gitRecent(cwd: string, limit?: number): Promise<string[]>;
31
+ /**
32
+ * Files the ledger holds findings about, newest first.
33
+ *
34
+ * This is the signal no other picker has, because no other picker has the ledger: it is where the
35
+ * things that cost somebody an afternoon were written down. A file with a finding against it is a
36
+ * file where surprises live, and it belongs near the top of a list of files worth showing the model.
37
+ */
38
+ export declare function notedPaths(cwd: string, limit?: number): Promise<string[]>;
39
+ /** All three, gathered together. */
40
+ export declare function gatherSignals(cwd: string, events?: readonly TrajectoryEvent[]): Promise<Signals>;
41
+ //# sourceMappingURL=mention-signals.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mention-signals.d.ts","sourceRoot":"","sources":["../../src/web/mention-signals.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAO5C;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,SAAS,eAAe,EAAE,EAAE,KAAK,SAAK,GAAG,MAAM,EAAE,CAgBrF;AAED;;;;;;;;;GASG;AACH,wBAAsB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA8B1E;AAED;;;;;;GAMG;AACH,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAkB3E;AAED,oCAAoC;AACpC,wBAAsB,aAAa,CACjC,GAAG,EAAE,MAAM,EACX,MAAM,GAAE,SAAS,eAAe,EAAO,GACtC,OAAO,CAAC,OAAO,CAAC,CAGlB"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * What the workspace knows about which file you meant.
3
+ *
4
+ * `rankMentions` takes three lists and stays pure so it can be tested against fixed input. This is
5
+ * where the lists come from, and each one is cheap on purpose: a picker that reads the ledger and
6
+ * shells out to git on every keystroke stops being a picker and becomes a wait. So the signals are
7
+ * gathered once when the dropdown opens and reused for the rest of the typing.
8
+ */
9
+ import { readAll } from '../ledger.js';
10
+ /** Tools whose detail is a path rather than a command or a pattern. */
11
+ const PATH_TOOLS = new Set([
12
+ 'read_files', 'write_file', 'search_replace', 'apply_diff', 'delete_file', 'move_file', 'list_dir',
13
+ ]);
14
+ /**
15
+ * Files this session has actually handled, most recent first.
16
+ *
17
+ * Read from the trajectory rather than tracked separately, because the trajectory is already the
18
+ * record of what happened and a second list of the same thing is a second list to get wrong. Only
19
+ * the tools whose detail is a path: `execute_command` puts a command line there and `grep_search`
20
+ * puts a pattern, and either one offered as a filename is noise.
21
+ */
22
+ export function sessionPaths(events, limit = 40) {
23
+ const out = [];
24
+ const seen = new Set();
25
+ for (let i = events.length - 1; i >= 0 && out.length < limit; i--) {
26
+ const event = events[i];
27
+ if (event.t !== 'tool' || !PATH_TOOLS.has(event.name))
28
+ continue;
29
+ const detail = String(event.detail ?? '').trim();
30
+ // Absolute paths and traversal are outside the workspace listing, so they can never match a
31
+ // candidate and only take up a slot.
32
+ if (detail === '' || detail.startsWith('/') || detail.includes('..'))
33
+ continue;
34
+ const it = detail.replace(/^\.\//, '');
35
+ if (seen.has(it))
36
+ continue;
37
+ seen.add(it);
38
+ out.push(it);
39
+ }
40
+ return out;
41
+ }
42
+ /**
43
+ * Files git has touched lately, uncommitted first.
44
+ *
45
+ * Uncommitted first because that is a stronger statement about what the project is in the middle of
46
+ * than a commit from yesterday: work in the tree is work in progress. Then the recent commits,
47
+ * which is how a file you finished this morning stays near the top.
48
+ *
49
+ * Failure is silence. A directory that is not a repository is a perfectly ordinary place to work,
50
+ * and a picker that reported an error for it would be reporting its own assumption.
51
+ */
52
+ export async function gitRecent(cwd, limit = 40) {
53
+ const { execa } = await import('execa');
54
+ const run = async (args) => {
55
+ try {
56
+ const done = await execa('git', args, { cwd, reject: false, timeout: 4_000 });
57
+ if (done.exitCode !== 0)
58
+ return [];
59
+ return String(done.stdout ?? '').split('\n').map(line => line.trim()).filter(Boolean);
60
+ }
61
+ catch {
62
+ return [];
63
+ }
64
+ };
65
+ // --porcelain lines are "XY path", and a rename is "R old -> new", where the new name is the one
66
+ // that exists to be referenced.
67
+ const dirty = (await run(['status', '--porcelain', '--no-renames']))
68
+ .map(line => line.slice(3).trim())
69
+ .map(p => (p.includes(' -> ') ? p.split(' -> ').pop().trim() : p));
70
+ const committed = await run(['log', '-n', '12', '--name-only', '--pretty=format:', '--no-renames']);
71
+ const out = [];
72
+ const seen = new Set();
73
+ for (const p of [...dirty, ...committed]) {
74
+ const it = p.replace(/^"|"$/g, '').replace(/^\.\//, '');
75
+ if (it === '' || seen.has(it))
76
+ continue;
77
+ seen.add(it);
78
+ out.push(it);
79
+ if (out.length >= limit)
80
+ break;
81
+ }
82
+ return out;
83
+ }
84
+ /**
85
+ * Files the ledger holds findings about, newest first.
86
+ *
87
+ * This is the signal no other picker has, because no other picker has the ledger: it is where the
88
+ * things that cost somebody an afternoon were written down. A file with a finding against it is a
89
+ * file where surprises live, and it belongs near the top of a list of files worth showing the model.
90
+ */
91
+ export async function notedPaths(cwd, limit = 40) {
92
+ let findings;
93
+ try {
94
+ findings = await readAll(cwd);
95
+ }
96
+ catch {
97
+ return [];
98
+ }
99
+ const out = [];
100
+ const seen = new Set();
101
+ for (let i = findings.length - 1; i >= 0 && out.length < limit; i--) {
102
+ for (const p of findings[i].paths ?? []) {
103
+ const it = String(p).replace(/^\.\//, '');
104
+ if (it === '' || seen.has(it))
105
+ continue;
106
+ seen.add(it);
107
+ out.push(it);
108
+ }
109
+ }
110
+ return out;
111
+ }
112
+ /** All three, gathered together. */
113
+ export async function gatherSignals(cwd, events = []) {
114
+ const [recent, noted] = await Promise.all([gitRecent(cwd), notedPaths(cwd)]);
115
+ return { recent, noted, session: sessionPaths(events) };
116
+ }
117
+ //# sourceMappingURL=mention-signals.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mention-signals.js","sourceRoot":"","sources":["../../src/web/mention-signals.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAIvC,uEAAuE;AACvE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC;IACzB,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU;CACnG,CAAC,CAAC;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkC,EAAE,KAAK,GAAG,EAAE;IACzE,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAClE,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAE,CAAC;QACzB,IAAI,KAAK,CAAC,CAAC,KAAK,MAAM,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;YAAE,SAAS;QAChE,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,4FAA4F;QAC5F,qCAAqC;QACrC,IAAI,MAAM,KAAK,EAAE,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/E,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACvC,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QAC3B,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,GAAW,EAAE,KAAK,GAAG,EAAE;IACrD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,GAAG,GAAG,KAAK,EAAE,IAAc,EAAqB,EAAE;QACtD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;YAC9E,IAAI,IAAI,CAAC,QAAQ,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YACnC,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACxF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;IAEF,kGAAkG;IAClG,gCAAgC;IAChC,MAAM,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC,CAAC;SACjE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;SACjC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtE,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,aAAa,EAAE,kBAAkB,EAAE,cAAc,CAAC,CAAC,CAAC;IAEpG,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,GAAG,SAAS,CAAC,EAAE,CAAC;QACzC,MAAM,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACxD,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAAE,SAAS;QACxC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACb,IAAI,GAAG,CAAC,MAAM,IAAI,KAAK;YAAE,MAAM;IACjC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,GAAW,EAAE,KAAK,GAAG,EAAE;IACtD,IAAI,QAA6C,CAAC;IAClD,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QACpE,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,CAAC,CAAE,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;YACzC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAC1C,IAAI,EAAE,KAAK,EAAE,IAAI,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,SAAS;YACxC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACb,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,oCAAoC;AACpC,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,GAAW,EACX,SAAqC,EAAE;IAEvC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Referencing a file by name, and knowing what it costs before you do.
3
+ *
4
+ * The terminal has had `@` for a while: type it, get a subsequence match over every path in the
5
+ * workspace, pick one. The browser never got it, which is the gap this closes. But copying the
6
+ * terminal's version would have missed the two things that make this worth building rather than
7
+ * ticking off.
8
+ *
9
+ * ## Ranked by what this project is doing, not alphabetically
10
+ *
11
+ * A fuzzy match over four thousand paths answers "which files contain these letters". It does not
12
+ * answer "which file did you mean", and the difference is most of the value. KONECK already knows
13
+ * things no generic picker does:
14
+ *
15
+ * - which files git has touched recently — what the project is in the middle of;
16
+ * - which files this session has already read or written — what *you* are in the middle of;
17
+ * - which files the project ledger holds findings about — where the sharp edges were.
18
+ *
19
+ * A file carrying all three is almost certainly the one being reached for, and it is offered first
20
+ * with the reason attached, because a ranked list that will not say why it ranked something is a
21
+ * list you cannot correct.
22
+ *
23
+ * ## The cost is shown before the attachment is made
24
+ *
25
+ * Every candidate carries an estimate of what including it would spend. This matters here more than
26
+ * it might elsewhere: the person this was built for has run into truncated prompts and exhausted
27
+ * windows repeatedly, and "src/engine.ts ~48k tokens" is the difference between an informed choice
28
+ * and a surprise three turns later. It is an estimate and is labelled as one — four characters to
29
+ * the token is the usual rough figure and it is rough — but a rough number in front of the decision
30
+ * beats an exact one after it.
31
+ *
32
+ * A directory is offered as an outline rather than a concatenation, for the same reason: naming
33
+ * twenty files costs a few hundred tokens and pasting them costs a hundred thousand.
34
+ */
35
+ /** Why a candidate is where it is in the list. Shown, because an unexplained ranking cannot be trusted. */
36
+ export type Because =
37
+ /** Changed in git recently — what the project is in the middle of. */
38
+ 'recently changed'
39
+ /** Read or written by this session — what you are in the middle of. */
40
+ | 'used in this session'
41
+ /** The ledger holds a finding about it — where something was learned the hard way. */
42
+ | 'has notes';
43
+ export interface Candidate {
44
+ /** Repo-relative path. */
45
+ path: string;
46
+ kind: 'file' | 'dir';
47
+ /** Roughly what including it would spend, or null for a directory, which is offered as an outline. */
48
+ tokens: number | null;
49
+ /** Bytes on disk, when known. */
50
+ bytes: number | null;
51
+ /** Every reason this ranked where it did, in the order they were applied. */
52
+ because: Because[];
53
+ }
54
+ /** What the workspace knows that a filename match does not. */
55
+ export interface Signals {
56
+ /** Files git has touched recently, newest first. */
57
+ recent?: readonly string[];
58
+ /** Files this session has read or written. */
59
+ session?: readonly string[];
60
+ /** Files the ledger holds findings about. */
61
+ noted?: readonly string[];
62
+ }
63
+ /**
64
+ * Four characters to the token.
65
+ *
66
+ * The usual rough figure for English and code alike. Deliberately not a real tokeniser: loading one
67
+ * to put an advisory number beside forty filenames would cost more than the number is worth, and
68
+ * being out by a fifth does not change the decision anybody makes with it.
69
+ */
70
+ export declare const CHARS_PER_TOKEN = 4;
71
+ export declare function tokensForBytes(bytes: number): number;
72
+ /**
73
+ * The reasons a path carries, in a fixed order.
74
+ *
75
+ * Fixed so the list reads the same way every time — a reason that moves around between keystrokes
76
+ * makes the ranking look arbitrary even when it is not.
77
+ */
78
+ export declare function reasonsFor(p: string, signals: Signals): Because[];
79
+ /**
80
+ * The candidates for a query, best first.
81
+ *
82
+ * An empty query is not an empty answer: it offers what the project is doing — recent, in-session,
83
+ * noted — which is the list somebody wants when they type `@` and pause. A generic picker shows the
84
+ * alphabet at that moment, which is never what was meant.
85
+ */
86
+ export declare function rankMentions(entries: readonly string[], query: string, signals?: Signals, limit?: number): Array<{
87
+ path: string;
88
+ score: number;
89
+ because: Because[];
90
+ }>;
91
+ /**
92
+ * Fills in size and cost, and says which are directories.
93
+ *
94
+ * Done for the shown candidates only. Sizing four thousand paths to display forty is the kind of
95
+ * work that makes a picker feel slow for no reason anybody can see.
96
+ */
97
+ export declare function describeCandidates(cwd: string, ranked: ReadonlyArray<{
98
+ path: string;
99
+ because: Because[];
100
+ }>): Promise<Candidate[]>;
101
+ /** A size a person reads, rather than a byte count. */
102
+ export declare function humanBytes(bytes: number | null): string;
103
+ /** A token count a person reads. Approximate, and never dressed up as exact. */
104
+ export declare function humanTokens(tokens: number | null): string;
105
+ /**
106
+ * The short forms shown in a row, in place of the full reason.
107
+ *
108
+ * A row is a row, not a sentence: "used in this session" reads as prose beside a filename and
109
+ * "in session" reads as a label. The wording is shared so the terminal and the browser cannot drift
110
+ * into saying different things about the same signal.
111
+ */
112
+ export declare function shortReason(because: Because): string;
113
+ /**
114
+ * What a picker row says after the path: why it is there, and what it will cost.
115
+ *
116
+ * Shared by both surfaces. `bytes` is undefined while the size is still being read, which is the
117
+ * normal first state rather than an error — the rows appear at once and the numbers arrive behind
118
+ * them, because a picker that waits for forty stat calls before showing anything feels broken.
119
+ */
120
+ export declare function rowDetail(because: readonly Because[], bytes: number | undefined, kind?: 'file' | 'dir'): string;
121
+ //# sourceMappingURL=mention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mention.d.ts","sourceRoot":"","sources":["../../src/web/mention.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AAMH,2GAA2G;AAC3G,MAAM,MAAM,OAAO;AACjB,sEAAsE;AACpE,kBAAkB;AACpB,uEAAuE;GACrE,sBAAsB;AACxB,sFAAsF;GACpF,WAAW,CAAC;AAEhB,MAAM,WAAW,SAAS;IACxB,0BAA0B;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC;IACrB,sGAAsG;IACtG,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,iCAAiC;IACjC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,6EAA6E;IAC7E,OAAO,EAAE,OAAO,EAAE,CAAC;CACpB;AAED,+DAA+D;AAC/D,MAAM,WAAW,OAAO;IACtB,oDAAoD;IACpD,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,8CAA8C;IAC9C,OAAO,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,IAAI,CAAC;AAEjC,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAcD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,CAOjE;AA0BD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,SAAS,MAAM,EAAE,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,GAAE,OAAY,EACrB,KAAK,SAAK,GACT,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,CAgC5D;AAED;;;;;GAKG;AACH,wBAAsB,kBAAkB,CACtC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,aAAa,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,GAC1D,OAAO,CAAC,SAAS,EAAE,CAAC,CAmBtB;AAED,uDAAuD;AACvD,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAKvD;AAED,gFAAgF;AAChF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CAIzD;AAED;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,MAAM,CAIpD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CACvB,OAAO,EAAE,SAAS,OAAO,EAAE,EAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,IAAI,GAAE,MAAM,GAAG,KAAc,GAC5B,MAAM,CAKR"}
@@ -0,0 +1,211 @@
1
+ /**
2
+ * Referencing a file by name, and knowing what it costs before you do.
3
+ *
4
+ * The terminal has had `@` for a while: type it, get a subsequence match over every path in the
5
+ * workspace, pick one. The browser never got it, which is the gap this closes. But copying the
6
+ * terminal's version would have missed the two things that make this worth building rather than
7
+ * ticking off.
8
+ *
9
+ * ## Ranked by what this project is doing, not alphabetically
10
+ *
11
+ * A fuzzy match over four thousand paths answers "which files contain these letters". It does not
12
+ * answer "which file did you mean", and the difference is most of the value. KONECK already knows
13
+ * things no generic picker does:
14
+ *
15
+ * - which files git has touched recently — what the project is in the middle of;
16
+ * - which files this session has already read or written — what *you* are in the middle of;
17
+ * - which files the project ledger holds findings about — where the sharp edges were.
18
+ *
19
+ * A file carrying all three is almost certainly the one being reached for, and it is offered first
20
+ * with the reason attached, because a ranked list that will not say why it ranked something is a
21
+ * list you cannot correct.
22
+ *
23
+ * ## The cost is shown before the attachment is made
24
+ *
25
+ * Every candidate carries an estimate of what including it would spend. This matters here more than
26
+ * it might elsewhere: the person this was built for has run into truncated prompts and exhausted
27
+ * windows repeatedly, and "src/engine.ts ~48k tokens" is the difference between an informed choice
28
+ * and a surprise three turns later. It is an estimate and is labelled as one — four characters to
29
+ * the token is the usual rough figure and it is rough — but a rough number in front of the decision
30
+ * beats an exact one after it.
31
+ *
32
+ * A directory is offered as an outline rather than a concatenation, for the same reason: naming
33
+ * twenty files costs a few hundred tokens and pasting them costs a hundred thousand.
34
+ */
35
+ import path from 'path';
36
+ import { stat } from 'fs/promises';
37
+ import { scoreEntry } from '../workspace-files.js';
38
+ /**
39
+ * Four characters to the token.
40
+ *
41
+ * The usual rough figure for English and code alike. Deliberately not a real tokeniser: loading one
42
+ * to put an advisory number beside forty filenames would cost more than the number is worth, and
43
+ * being out by a fifth does not change the decision anybody makes with it.
44
+ */
45
+ export const CHARS_PER_TOKEN = 4;
46
+ export function tokensForBytes(bytes) {
47
+ return Math.max(1, Math.round(bytes / CHARS_PER_TOKEN));
48
+ }
49
+ /**
50
+ * Normalised for comparison: a path is the same path however it was written.
51
+ *
52
+ * The trailing slash goes too. The workspace listing marks directories with one, and carrying it
53
+ * through meant the candidate was `src/` — which the client then completed to `@src//`, and which
54
+ * matched nothing when compared against the same directory named by git or by the session.
55
+ */
56
+ function key(p) {
57
+ const cleaned = p.replace(/^\.\//, '').replace(/\\/g, '/').replace(/\/+$/, '');
58
+ return cleaned;
59
+ }
60
+ /**
61
+ * The reasons a path carries, in a fixed order.
62
+ *
63
+ * Fixed so the list reads the same way every time — a reason that moves around between keystrokes
64
+ * makes the ranking look arbitrary even when it is not.
65
+ */
66
+ export function reasonsFor(p, signals) {
67
+ const it = key(p);
68
+ const out = [];
69
+ if (signals.recent?.some(r => key(r) === it))
70
+ out.push('recently changed');
71
+ if (signals.session?.some(r => key(r) === it))
72
+ out.push('used in this session');
73
+ if (signals.noted?.some(r => key(r) === it))
74
+ out.push('has notes');
75
+ return out;
76
+ }
77
+ /**
78
+ * How much being known about is worth, against how well the name matches.
79
+ *
80
+ * The match still decides: somebody typing `engine` wants engine.ts even if they have never opened
81
+ * it. But among candidates that match comparably, the one the project is working on wins — and the
82
+ * weights are small enough that a strong name match cannot be displaced by mere familiarity.
83
+ */
84
+ const WORTH = {
85
+ 'used in this session': 8,
86
+ 'recently changed': 5,
87
+ 'has notes': 2,
88
+ };
89
+ /*
90
+ * Where those numbers came from.
91
+ *
92
+ * Measured, not chosen. The matcher scores a hit in the filename against a hit spread across
93
+ * directories about six points apart — `src/engine.ts` and `tests/engine.test.ts` for the query
94
+ * "enginets" come out 1008 and 1014 — while a genuinely different file is hundreds away or does not
95
+ * match at all. So eight is enough to turn a near miss into a win, and nowhere near enough to
96
+ * promote a file that merely happens to be open. The first version used six, which made the near
97
+ * miss an exact tie and left a length comparison to decide it, which is not a decision at all.
98
+ */
99
+ /**
100
+ * The candidates for a query, best first.
101
+ *
102
+ * An empty query is not an empty answer: it offers what the project is doing — recent, in-session,
103
+ * noted — which is the list somebody wants when they type `@` and pause. A generic picker shows the
104
+ * alphabet at that moment, which is never what was meant.
105
+ */
106
+ export function rankMentions(entries, query, signals = {}, limit = 40) {
107
+ const asked = query.trim();
108
+ if (asked === '') {
109
+ const seen = new Set();
110
+ const suggested = [];
111
+ // In the order they answer "what am I working on": this session, then the project, then history.
112
+ for (const source of [signals.session ?? [], signals.recent ?? [], signals.noted ?? []]) {
113
+ for (const p of source) {
114
+ const it = key(p);
115
+ if (seen.has(it))
116
+ continue;
117
+ seen.add(it);
118
+ const because = reasonsFor(it, signals);
119
+ suggested.push({ path: it, score: -because.reduce((n, b) => n + WORTH[b], 0), because });
120
+ }
121
+ }
122
+ suggested.sort((a, b) => a.score - b.score);
123
+ return suggested.slice(0, limit);
124
+ }
125
+ const scored = [];
126
+ for (const entry of entries) {
127
+ const base = scoreEntry(entry, asked);
128
+ if (base === null)
129
+ continue;
130
+ const because = reasonsFor(entry, signals);
131
+ // Lower is better in scoreEntry, so being known about subtracts.
132
+ const bonus = because.reduce((n, b) => n + WORTH[b], 0);
133
+ scored.push({ path: key(entry), score: base - bonus, because });
134
+ }
135
+ scored.sort((a, b) => (a.score - b.score) || a.path.length - b.path.length
136
+ || a.path.localeCompare(b.path));
137
+ return scored.slice(0, limit);
138
+ }
139
+ /**
140
+ * Fills in size and cost, and says which are directories.
141
+ *
142
+ * Done for the shown candidates only. Sizing four thousand paths to display forty is the kind of
143
+ * work that makes a picker feel slow for no reason anybody can see.
144
+ */
145
+ export async function describeCandidates(cwd, ranked) {
146
+ return Promise.all(ranked.map(async (entry) => {
147
+ const full = path.join(cwd, entry.path);
148
+ let bytes = null;
149
+ let kind = 'file';
150
+ try {
151
+ const info = await stat(full);
152
+ kind = info.isDirectory() ? 'dir' : 'file';
153
+ bytes = info.isDirectory() ? null : info.size;
154
+ }
155
+ catch { /* it was listed and has since gone; offered without a size */ }
156
+ return {
157
+ path: entry.path,
158
+ kind,
159
+ bytes,
160
+ // A directory is offered as an outline, so its cost is not the sum of its files.
161
+ tokens: kind === 'dir' || bytes === null ? null : tokensForBytes(bytes),
162
+ because: entry.because,
163
+ };
164
+ }));
165
+ }
166
+ /** A size a person reads, rather than a byte count. */
167
+ export function humanBytes(bytes) {
168
+ if (bytes === null)
169
+ return '';
170
+ if (bytes < 1024)
171
+ return `${bytes} B`;
172
+ if (bytes < 1024 * 1024)
173
+ return `${Math.round(bytes / 1024)} KB`;
174
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
175
+ }
176
+ /** A token count a person reads. Approximate, and never dressed up as exact. */
177
+ export function humanTokens(tokens) {
178
+ if (tokens === null)
179
+ return '';
180
+ if (tokens < 1000)
181
+ return `~${tokens} tok`;
182
+ return `~${Math.round(tokens / 100) / 10}k tok`;
183
+ }
184
+ /**
185
+ * The short forms shown in a row, in place of the full reason.
186
+ *
187
+ * A row is a row, not a sentence: "used in this session" reads as prose beside a filename and
188
+ * "in session" reads as a label. The wording is shared so the terminal and the browser cannot drift
189
+ * into saying different things about the same signal.
190
+ */
191
+ export function shortReason(because) {
192
+ return because === 'used in this session' ? 'in session'
193
+ : because === 'recently changed' ? 'changed'
194
+ : 'noted';
195
+ }
196
+ /**
197
+ * What a picker row says after the path: why it is there, and what it will cost.
198
+ *
199
+ * Shared by both surfaces. `bytes` is undefined while the size is still being read, which is the
200
+ * normal first state rather than an error — the rows appear at once and the numbers arrive behind
201
+ * them, because a picker that waits for forty stat calls before showing anything feels broken.
202
+ */
203
+ export function rowDetail(because, bytes, kind = 'file') {
204
+ const parts = because.map(shortReason);
205
+ if (kind === 'dir')
206
+ parts.push('folder');
207
+ else if (bytes !== undefined)
208
+ parts.push(humanTokens(tokensForBytes(bytes)));
209
+ return parts.join(' · ');
210
+ }
211
+ //# sourceMappingURL=mention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mention.js","sourceRoot":"","sources":["../../src/web/mention.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/web/sessions.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/web/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAE9D,OAAO,EAAE,QAAQ,EAAiB,MAAM,aAAa,CAAC;AACtD,OAAO,EAAqB,SAAS,IAAI,gBAAgB,EACjC,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,EAAoC,KAAK,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAIpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAMrD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AACvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,IAAI,EAAE,QAAQ,CAAC;IACf,0DAA0D;IAC1D,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,QAAQ,EAAE,OAAO,CAAC;IAClB,+FAA+F;IAC/F,QAAQ,EAAE,MAAM,CAAC;IACjB,6FAA6F;IAC7F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,+DAA+D;IAC/D,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,qCAAqC;AACrC,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,MAAM,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC3D;AAUD,qBAAa,UAAU;IAuFT,QAAQ,CAAC,EAAE,EAAE,MAAM;IAAE,OAAO,CAAC,MAAM;IAtF/C,QAAQ,CAAC,GAAG,WAAkB;IAC9B,QAAQ,CAAC,SAAS,SAAc;IAChC;;;;;;OAMG;IACH,KAAK,SAAK;IACV,KAAK,SAAiB;IACtB,KAAK,SAAK;IACV,WAAW,SAAK;IAChB,IAAI,UAAS;IAEb,OAAO,CAAC,KAAK,CAA+D;IAC5E,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAgC;IAEhD,wFAAwF;IACxF,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IACnD;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAuB;IAC9C,gEAAgE;IAChE,OAAO,CAAC,WAAW,CAAuB;IAC1C,2EAA2E;IAC3E,IAAI,SAAS,IAAI,MAAM,GAAG,IAAI,CAA6B;IAE3D,gFAAgF;IAChF,IAAI,EAAE,OAAO,WAAW,EAAE,SAAS,GAAG,IAAI,CAAQ;IAClD,8EAA8E;IAC9E,OAAO,CAAC,QAAQ,CAAuB;IAEvC,0FAA0F;IAC1F,OAAO,CAAC,IAAI,CACiD;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAA8B;IACtD,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,WAAW,CAAK;IACxB,gGAAgG;IAChG,OAAO,CAAC,QAAQ,CAAC,WAAW,CAA6B;IAEzD;;;;;;OAMG;IACH,OAAO,CAAC,QAAQ,CAAyB;IACzC,OAAO,CAAC,QAAQ,CAAyB;IACzC,wCAAwC;IACxC,QAAQ,CAAC,WAAW,EAAE,WAAW,EAAE,CAAM;IAEzC;;;;;;;;OAQG;IACH,IAAI,EAAE,QAAQ,CAAU;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmB;IAEzC;;;;;;OAMG;IACH,IAAI,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3B,MAAM,EAAE,MAAM,CAAY;IAC1B,4DAA4D;IAC5D,OAAO,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC9B,+DAA+D;IAC/D,OAAO,CAAC,QAAQ,CAAuB;gBAElB,EAAE,EAAE,MAAM,EAAU,MAAM,EAAE,WAAW;IAO5D,IAAI,IAAI,cAAc;IA0BtB;;;;;OAKG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAQ,GAAG,OAAO;IAUhE,uFAAuF;IACvF,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI;IAO3C;;;;;;;OAOG;IACH,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAS/B,qDAAqD;IACrD,IAAI,SAAS,IAAI,MAAM,GAAG,IAAI,CAA0B;IAExD;;;;;;OAMG;IACH,MAAM,IAAI,MAAM,GAAG,IAAI;IAYvB,oDAAoD;IACpD,OAAO,CAAC,IAAI,EAAE,QAAQ,GAAG,IAAI;IAM7B,iFAAiF;IACjF,eAAe,IAAI,MAAM,EAAE;IAE3B;;;;;OAKG;IACH,UAAU,IAAI,SAAS,eAAe,EAAE;YAI1B,WAAW;IAuKzB;;;;;;OAMG;IACH,UAAU,CAAC,IAAI,EAAE;QAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;QAAC,KAAK,EAAE,SAAS,CAAC,OAAO,CAAC,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAC;QAClE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IASxD;;;;;OAKG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAOtC,2FAA2F;IACrF,iBAAiB,IAAI,OAAO,CAAC;QAAE,OAAO,EAAE,UAAU,EAAE,CAAC;QAAC,MAAM,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAA;KAAE,GAAG,IAAI,CAAC;IAOjH;;;;;;OAMG;IACG,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,GAAE,SAAS,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA0F3E,iFAAiF;IACjF;;;;;;OAMG;IAYH,OAAO,CAAC,aAAa,CAAS;YAEhB,YAAY;IA6B1B,gFAAgF;IAChF,OAAO,CAAC,QAAQ;IAOV,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YA6BhB,iBAAiB;IAa/B,0DAA0D;IAC1D;;;;;;OAMG;IACH,KAAK,IAAI,OAAO;IAQhB;;;;;;;;;OASG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,EAAE,QAAQ,UAAO,GACrD;QAAE,EAAE,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,OAAO,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE;IAqDtF,kFAAkF;IAClF,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI9C;;;;;;OAMG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;IAItC;;;;;OAKG;IACH,WAAW,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI;IAUzC,kFAAkF;IAClF,WAAW,CAAC,KAAK,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI;IA4C9C,oGAAoG;IACpG,QAAQ,IAAI,MAAM;CAInB;AAED,iCAAiC;AACjC,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiC;IAC1D,OAAO,CAAC,OAAO,CAAK;IAEpB,sFAAsF;IACtF,OAAO,IAAI,MAAM,EAAE;IAInB,0FAA0F;IAC1F,aAAa,IAAI,MAAM,EAAE;IAIzB,MAAM,CAAC,MAAM,EAAE,WAAW,GAAG,UAAU;IAUvC,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,SAAS;IACvC,IAAI,IAAI,cAAc,EAAE;IAKxB,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAC3B,IAAI,IAAI,IAAI,MAAM,CAA+B;CAClD;AAED,2EAA2E;AAC3E,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAElD"}
@@ -13,6 +13,7 @@ import { createAgentSession, toolDetailFor } from '../engine.js';
13
13
  import { estimateCost } from '../pricing.js';
14
14
  import { EventBus } from './events.js';
15
15
  import { snapshot, compare, summarise as summariseChanges } from './changes.js';
16
+ import { attachReferences, linesIn } from '../mention-resolve.js';
16
17
  import { decide, modeSpec } from '../permissions.js';
17
18
  import { redactSecrets } from '../redact.js';
18
19
  import { keyEnvFor, resolveProvider } from '../providers.js';
@@ -438,7 +439,27 @@ export class WebSession {
438
439
  if (this.title === 'New session')
439
440
  this.title = redactSecrets(tidyTitle(text, 72)) || 'New session';
440
441
  this.lastText = text;
441
- this.bus.emit({ t: 'user', text, images: imagePaths.length });
442
+ /*
443
+ * An `@` becomes the file it names, before the model sees the message.
444
+ *
445
+ * The picker showed what each reference would cost, so this is the spend that was agreed to. The
446
+ * transcript keeps the sentence as typed — nobody wants to scroll past eight hundred lines of
447
+ * their own attachment to find what they asked — and the list of what was attached rides
448
+ * alongside it so the spend is visible rather than inferred.
449
+ */
450
+ const referenced = await attachReferences(this.config.cwd, text)
451
+ .catch(() => ({ text, attached: [] }));
452
+ this.bus.emit({
453
+ t: 'user', text, images: imagePaths.length,
454
+ ...(referenced.attached.length > 0 ? {
455
+ refs: referenced.attached.map(a => ({
456
+ ref: a.ref,
457
+ kind: a.kind,
458
+ lines: a.content === undefined ? null : linesIn(a.content),
459
+ ...(a.note ? { note: a.note } : {}),
460
+ })),
461
+ } : {}),
462
+ });
442
463
  try {
443
464
  const agent = await this.ensureAgent();
444
465
  // The same prefix the terminal builds: the standing goal, the mode's own instruction, and
@@ -451,7 +472,7 @@ export class WebSession {
451
472
  // AbortSignal — so passing undefined here meant stop had nothing to act on: the button
452
473
  // called an optional method that did not exist, and silently did nothing at all.
453
474
  this.stopping = new AbortController();
454
- const completed = await agent.send(prefix + text, this.stopping.signal, imagePaths.length ? imagePaths : undefined);
475
+ const completed = await agent.send(prefix + referenced.text, this.stopping.signal, imagePaths.length ? imagePaths : undefined);
455
476
  this.turns++;
456
477
  const ms = Date.now() - started;
457
478
  // What this turn changed, taken while it is still true. Comparing at the end of the session