mu-harness 0.16.20 → 0.16.22

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.
@@ -717,6 +717,8 @@ export class ChatApp {
717
717
  return true;
718
718
  }
719
719
  deleteMention() {
720
+ if (this.pickerMention !== undefined)
721
+ return false;
720
722
  const value = this.editor.getValue();
721
723
  const cursor = this.editor.cursorPos;
722
724
  const re = /@[^\s]+/g;
@@ -1159,7 +1161,7 @@ export class ChatApp {
1159
1161
  children.push(listView(rows, this.paletteCursor, this.theme()));
1160
1162
  }
1161
1163
  else if (this.pickerVisible()) {
1162
- const rows = this.pickerRanked.map((c) => ({ left: c.label, right: c.kind === 'agent' ? 'agent' : '' }));
1164
+ const rows = this.pickerRanked.map((c) => ({ left: c.label, right: c.kind === 'file' ? '' : c.kind }));
1163
1165
  children.push(listView(rows, this.pickerCursor, this.theme()));
1164
1166
  }
1165
1167
  const waiting = this.waitingView();
@@ -1,7 +1,7 @@
1
1
  export interface Candidate {
2
2
  label: string;
3
3
  insert: string;
4
- kind: 'file' | 'agent';
4
+ kind: 'file' | 'dir' | 'agent';
5
5
  }
6
6
  export declare function collectCandidates(cwd: string, agentNames: string[]): Candidate[];
7
7
  export declare function rank(query: string, candidates: Candidate[], limit?: number): Candidate[];
@@ -36,9 +36,10 @@ function gitFiles(cwd) {
36
36
  }
37
37
  }
38
38
  function walk(cwd) {
39
- const out = [];
39
+ const files = [];
40
+ const dirs = [];
40
41
  const stack = [{ dir: cwd, depth: 0 }];
41
- while (stack.length > 0 && out.length < MAX_ENTRIES) {
42
+ while (stack.length > 0 && files.length < MAX_ENTRIES) {
42
43
  const { dir, depth } = stack.pop();
43
44
  let entries;
44
45
  try {
@@ -61,23 +62,34 @@ function walk(cwd) {
61
62
  continue;
62
63
  }
63
64
  if (isDir) {
65
+ dirs.push(relative(cwd, full));
64
66
  if (depth < MAX_DEPTH)
65
67
  stack.push({ dir: full, depth: depth + 1 });
66
68
  }
67
69
  else {
68
- out.push(relative(cwd, full));
69
- if (out.length >= MAX_ENTRIES)
70
+ files.push(relative(cwd, full));
71
+ if (files.length >= MAX_ENTRIES)
70
72
  break;
71
73
  }
72
74
  }
73
75
  }
74
- return out.sort();
76
+ return { files: files.sort(), dirs: dirs.sort() };
75
77
  }
76
78
  export function collectCandidates(cwd, agentNames) {
77
- const paths = gitFiles(cwd) ?? walk(cwd);
78
79
  const agents = agentNames.map((name) => ({ label: `@${name}`, insert: name, kind: 'agent' }));
80
+ const tracked = gitFiles(cwd);
81
+ const walked = walk(cwd);
82
+ const paths = tracked ?? walked.files;
83
+ const dirs = new Set(walked.dirs);
84
+ for (const path of paths) {
85
+ for (let i = 0; i < path.length; i++) {
86
+ if (path[i] === '/' || path[i] === '\\')
87
+ dirs.add(path.slice(0, i));
88
+ }
89
+ }
90
+ const dirCandidates = [...dirs].map((path) => ({ label: `${path}/`, insert: `${path}/`, kind: 'dir' }));
79
91
  const files = paths.map((path) => ({ label: path, insert: path, kind: 'file' }));
80
- return [...agents, ...files];
92
+ return [...agents, ...dirCandidates, ...files];
81
93
  }
82
94
  function isBoundary(target, i) {
83
95
  if (i === 0)
@@ -119,8 +131,9 @@ function fuzzyScore(query, target) {
119
131
  return total;
120
132
  }
121
133
  function basename(path) {
122
- const cut = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
123
- return cut === -1 ? path : path.slice(cut + 1);
134
+ const p = path.endsWith('/') || path.endsWith('\\') ? path.slice(0, -1) : path;
135
+ const cut = Math.max(p.lastIndexOf('/'), p.lastIndexOf('\\'));
136
+ return cut === -1 ? p : p.slice(cut + 1);
124
137
  }
125
138
  function score(query, candidate) {
126
139
  if (query.length === 0)
@@ -129,7 +142,7 @@ function score(query, candidate) {
129
142
  if (pathScore === undefined)
130
143
  return undefined;
131
144
  let total = pathScore;
132
- if (candidate.kind === 'file') {
145
+ if (candidate.kind === 'file' || candidate.kind === 'dir') {
133
146
  const base = basename(candidate.label);
134
147
  const baseScore = fuzzyScore(query, base);
135
148
  if (baseScore !== undefined) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mu-harness",
3
- "version": "0.16.20",
3
+ "version": "0.16.22",
4
4
  "description": "Agent harness: createHarness wires mu-core into a host — XDG paths, model registry, plugins, disk-loaded agents & skills, sub-agents, sessions (JSONL + SQLite catalog), slash commands, permission/approval hooks, an optional scheduler, and a composable TUI chat app",
5
5
  "license": "MIT",
6
6
  "main": "./script/index.js",
@@ -23,8 +23,8 @@
23
23
  "@swc/wasm-typescript": "^1.15.0",
24
24
  "cli-highlight": "^2.1.11",
25
25
  "croner": "^9.0.0",
26
- "mu-core": "^0.16.20",
27
- "mu-tui": "^0.16.20"
26
+ "mu-core": "^0.16.22",
27
+ "mu-tui": "^0.16.22"
28
28
  },
29
29
  "_generatedBy": "dnt@dev",
30
30
  "types": "./esm/index.d.ts"
@@ -720,6 +720,8 @@ class ChatApp {
720
720
  return true;
721
721
  }
722
722
  deleteMention() {
723
+ if (this.pickerMention !== undefined)
724
+ return false;
723
725
  const value = this.editor.getValue();
724
726
  const cursor = this.editor.cursorPos;
725
727
  const re = /@[^\s]+/g;
@@ -1162,7 +1164,7 @@ class ChatApp {
1162
1164
  children.push(listView(rows, this.paletteCursor, this.theme()));
1163
1165
  }
1164
1166
  else if (this.pickerVisible()) {
1165
- const rows = this.pickerRanked.map((c) => ({ left: c.label, right: c.kind === 'agent' ? 'agent' : '' }));
1167
+ const rows = this.pickerRanked.map((c) => ({ left: c.label, right: c.kind === 'file' ? '' : c.kind }));
1166
1168
  children.push(listView(rows, this.pickerCursor, this.theme()));
1167
1169
  }
1168
1170
  const waiting = this.waitingView();
@@ -1,7 +1,7 @@
1
1
  export interface Candidate {
2
2
  label: string;
3
3
  insert: string;
4
- kind: 'file' | 'agent';
4
+ kind: 'file' | 'dir' | 'agent';
5
5
  }
6
6
  export declare function collectCandidates(cwd: string, agentNames: string[]): Candidate[];
7
7
  export declare function rank(query: string, candidates: Candidate[], limit?: number): Candidate[];
@@ -41,9 +41,10 @@ function gitFiles(cwd) {
41
41
  }
42
42
  }
43
43
  function walk(cwd) {
44
- const out = [];
44
+ const files = [];
45
+ const dirs = [];
45
46
  const stack = [{ dir: cwd, depth: 0 }];
46
- while (stack.length > 0 && out.length < MAX_ENTRIES) {
47
+ while (stack.length > 0 && files.length < MAX_ENTRIES) {
47
48
  const { dir, depth } = stack.pop();
48
49
  let entries;
49
50
  try {
@@ -66,23 +67,34 @@ function walk(cwd) {
66
67
  continue;
67
68
  }
68
69
  if (isDir) {
70
+ dirs.push((0, node_path_1.relative)(cwd, full));
69
71
  if (depth < MAX_DEPTH)
70
72
  stack.push({ dir: full, depth: depth + 1 });
71
73
  }
72
74
  else {
73
- out.push((0, node_path_1.relative)(cwd, full));
74
- if (out.length >= MAX_ENTRIES)
75
+ files.push((0, node_path_1.relative)(cwd, full));
76
+ if (files.length >= MAX_ENTRIES)
75
77
  break;
76
78
  }
77
79
  }
78
80
  }
79
- return out.sort();
81
+ return { files: files.sort(), dirs: dirs.sort() };
80
82
  }
81
83
  function collectCandidates(cwd, agentNames) {
82
- const paths = gitFiles(cwd) ?? walk(cwd);
83
84
  const agents = agentNames.map((name) => ({ label: `@${name}`, insert: name, kind: 'agent' }));
85
+ const tracked = gitFiles(cwd);
86
+ const walked = walk(cwd);
87
+ const paths = tracked ?? walked.files;
88
+ const dirs = new Set(walked.dirs);
89
+ for (const path of paths) {
90
+ for (let i = 0; i < path.length; i++) {
91
+ if (path[i] === '/' || path[i] === '\\')
92
+ dirs.add(path.slice(0, i));
93
+ }
94
+ }
95
+ const dirCandidates = [...dirs].map((path) => ({ label: `${path}/`, insert: `${path}/`, kind: 'dir' }));
84
96
  const files = paths.map((path) => ({ label: path, insert: path, kind: 'file' }));
85
- return [...agents, ...files];
97
+ return [...agents, ...dirCandidates, ...files];
86
98
  }
87
99
  function isBoundary(target, i) {
88
100
  if (i === 0)
@@ -124,8 +136,9 @@ function fuzzyScore(query, target) {
124
136
  return total;
125
137
  }
126
138
  function basename(path) {
127
- const cut = Math.max(path.lastIndexOf('/'), path.lastIndexOf('\\'));
128
- return cut === -1 ? path : path.slice(cut + 1);
139
+ const p = path.endsWith('/') || path.endsWith('\\') ? path.slice(0, -1) : path;
140
+ const cut = Math.max(p.lastIndexOf('/'), p.lastIndexOf('\\'));
141
+ return cut === -1 ? p : p.slice(cut + 1);
129
142
  }
130
143
  function score(query, candidate) {
131
144
  if (query.length === 0)
@@ -134,7 +147,7 @@ function score(query, candidate) {
134
147
  if (pathScore === undefined)
135
148
  return undefined;
136
149
  let total = pathScore;
137
- if (candidate.kind === 'file') {
150
+ if (candidate.kind === 'file' || candidate.kind === 'dir') {
138
151
  const base = basename(candidate.label);
139
152
  const baseScore = fuzzyScore(query, base);
140
153
  if (baseScore !== undefined) {