agent-sh 0.14.9 → 0.14.11

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.
Files changed (68) hide show
  1. package/README.md +47 -20
  2. package/dist/agent/agent-loop.js +20 -15
  3. package/dist/agent/events.d.ts +2 -1
  4. package/dist/agent/index.js +44 -7
  5. package/dist/agent/live-view.d.ts +3 -3
  6. package/dist/agent/live-view.js +15 -7
  7. package/dist/agent/providers/ollama.d.ts +11 -0
  8. package/dist/agent/providers/ollama.js +72 -0
  9. package/dist/agent/providers/opencode.d.ts +10 -0
  10. package/dist/agent/providers/opencode.js +112 -0
  11. package/dist/agent/providers/openrouter.js +9 -0
  12. package/dist/agent/providers/zai-coding-plan.d.ts +5 -0
  13. package/dist/agent/providers/zai-coding-plan.js +26 -0
  14. package/dist/agent/subagent.js +1 -1
  15. package/dist/cli/args.js +2 -2
  16. package/dist/cli/install.js +10 -1
  17. package/dist/shell/events.d.ts +3 -0
  18. package/dist/shell/shell.js +3 -0
  19. package/dist/utils/diff-renderer.d.ts +4 -0
  20. package/dist/utils/diff-renderer.js +15 -20
  21. package/examples/extensions/ads/SKILL.md +170 -0
  22. package/examples/extensions/ads/index.ts +695 -0
  23. package/examples/extensions/ash-scheme/index.ts +339 -605
  24. package/examples/extensions/ash-scheme/package.json +1 -1
  25. package/examples/extensions/ashi/EXTENDING.md +116 -0
  26. package/examples/extensions/ashi/README.md +10 -54
  27. package/examples/extensions/ashi/package.json +6 -2
  28. package/examples/extensions/ashi/src/autocomplete-controller.ts +95 -0
  29. package/examples/extensions/ashi/src/autocomplete.ts +1 -23
  30. package/examples/extensions/ashi/src/capture.ts +9 -3
  31. package/examples/extensions/ashi/src/chat/assistant.ts +87 -0
  32. package/examples/extensions/ashi/src/chat/lines.ts +20 -0
  33. package/examples/extensions/ashi/src/chat/thinking.ts +42 -0
  34. package/examples/extensions/ashi/src/chat/tool-group.ts +84 -0
  35. package/examples/extensions/ashi/src/chat/user-message.ts +20 -0
  36. package/examples/extensions/ashi/src/cli.ts +58 -12
  37. package/examples/extensions/ashi/src/clipboard-image.ts +41 -0
  38. package/examples/extensions/ashi/src/commands.ts +11 -1
  39. package/examples/extensions/ashi/src/display-config.ts +9 -1
  40. package/examples/extensions/ashi/src/frontend.ts +340 -259
  41. package/examples/extensions/ashi/src/hooks.ts +33 -40
  42. package/examples/extensions/ashi/src/renderer.ts +222 -0
  43. package/examples/extensions/ashi/src/renderers/pi-tui/app.ts +122 -0
  44. package/examples/extensions/ashi/src/renderers/pi-tui/index.ts +23 -0
  45. package/examples/extensions/ashi/src/renderers/pi-tui/nodes.ts +133 -0
  46. package/examples/extensions/ashi/src/renderers/pi-tui/schema-mount.ts +193 -0
  47. package/examples/extensions/ashi/src/renderers/pi-tui/theme-adapters.ts +48 -0
  48. package/examples/extensions/ashi/src/renderers/pi-tui/tool-group.ts +21 -0
  49. package/examples/extensions/ashi/src/schema.ts +43 -205
  50. package/examples/extensions/ashi/src/status-footer.ts +15 -23
  51. package/examples/extensions/ashi/src/terminal-mode.ts +9 -0
  52. package/examples/extensions/ashi/src/theme.ts +1 -47
  53. package/examples/extensions/ashi-ink/README.md +59 -0
  54. package/examples/extensions/ashi-ink/package.json +30 -0
  55. package/examples/extensions/ashi-ink/src/index.ts +6 -0
  56. package/examples/extensions/ashi-ink/src/ink-renderer.tsx +865 -0
  57. package/examples/extensions/ashi-ink/src/shims.d.ts +5 -0
  58. package/examples/extensions/ashi-ink/test/render.test.tsx +408 -0
  59. package/examples/extensions/ashi-ink/tsconfig.json +14 -0
  60. package/examples/extensions/ashi-scheme-render.ts +4 -10
  61. package/examples/extensions/ashi-shell-passthrough.ts +95 -0
  62. package/examples/extensions/latex-images.ts +22 -19
  63. package/examples/extensions/terminal-buffer.ts +4 -2
  64. package/package.json +3 -9
  65. package/examples/extensions/ashi/src/components.ts +0 -238
  66. package/examples/extensions/ollama.ts +0 -108
  67. package/examples/extensions/opencode-provider.ts +0 -251
  68. package/examples/extensions/zai-coding-plan.ts +0 -35
@@ -14,7 +14,16 @@ const EXT_DIR = path.join(CONFIG_DIR, "extensions");
14
14
  export function listBundled() {
15
15
  if (!fs.existsSync(BUNDLED_DIR))
16
16
  return [];
17
- return fs.readdirSync(BUNDLED_DIR).map((n) => n.replace(/\.(ts|js|mjs)$/, ""));
17
+ const out = [];
18
+ for (const d of fs.readdirSync(BUNDLED_DIR, { withFileTypes: true })) {
19
+ if (d.name.startsWith("."))
20
+ continue;
21
+ if (d.isDirectory())
22
+ out.push(d.name);
23
+ else if (SCRIPT_EXTS.some((ext) => d.name.endsWith(ext)))
24
+ out.push(d.name.replace(/\.[^.]+$/, ""));
25
+ }
26
+ return out;
18
27
  }
19
28
  /** Heuristic: a backend named "pi" is typically provided by an extension called "pi-bridge". */
20
29
  export function suggestBridgeFor(backend) {
@@ -32,6 +32,9 @@ declare module "../core/event-bus.js" {
32
32
  cols: number;
33
33
  rows: number;
34
34
  };
35
+ "shell:host-write": {
36
+ data: string;
37
+ };
35
38
  "shell:buffer-request": Record<string, never>;
36
39
  "shell:buffer-snapshot": {
37
40
  text: string;
@@ -110,6 +110,9 @@ export class Shell {
110
110
  this.bus.on("shell:pty-resize", ({ cols, rows }) => {
111
111
  this.ptyProcess.resize(cols, rows);
112
112
  });
113
+ this.bus.on("shell:host-write", ({ data }) => {
114
+ this.terminal.write(data);
115
+ });
113
116
  // Compat shims for the bus-event API. shell:stdout-hold maps to hard
114
117
  // mute so terminal_keys' stdout-show can't paint through the overlay.
115
118
  let holdRefcount = 0;
@@ -13,6 +13,10 @@ export interface DiffRenderOptions {
13
13
  trueColor?: boolean;
14
14
  /** Enable syntax highlighting on diff lines. Default true. */
15
15
  syntaxHighlight?: boolean;
16
+ /** Draw the `│` rule between the line number and the code (default true). Set false
17
+ * for a flush gutter: `<n> <sigil><code>`, the row background spans the line, and
18
+ * context code is left un-dimmed. */
19
+ gutterLine?: boolean;
16
20
  }
17
21
  export declare function detectLanguage(filePath?: string): string | undefined;
18
22
  /**
@@ -239,25 +239,35 @@ function unifiedLayout(diff, opts) {
239
239
  lineTextW: Math.max(1, textWidth - noW - 5),
240
240
  textWidth,
241
241
  useTrueColor: opts.trueColor !== false,
242
+ gutterLine: opts.gutterLine !== false,
242
243
  lang: opts.syntaxHighlight !== false ? detectLanguage(opts.filePath) : undefined,
243
244
  removedPalette: { rowBg: p.errorBg, emphBg: p.errorBgEmph },
244
245
  addedPalette: { rowBg: p.successBg, emphBg: p.successBgEmph },
245
246
  };
246
247
  }
247
248
  function renderUnifiedHunk(hunk, layout) {
248
- const { noW, lineTextW, textWidth, useTrueColor, lang, removedPalette, addedPalette } = layout;
249
+ const { noW, lineTextW, textWidth, useTrueColor, gutterLine, lang, removedPalette, addedPalette } = layout;
249
250
  const out = [];
250
251
  const pairs = findChangePairs(hunk);
251
252
  const renderedAsPartOfPair = new Set();
252
253
  const bgWidth = Math.max(1, textWidth - noW - 3);
253
254
  const gutter = (n) => `${p.dim}${n} │${p.reset} `;
255
+ const change = (no, sigil, bg, fg, text) => {
256
+ if (!gutterLine) {
257
+ return `${bg}${padToWidth(`${no} ${fg}${sigil}${preserveBg(text, bg)}`, textWidth)}${p.reset}`;
258
+ }
259
+ if (useTrueColor)
260
+ return gutter(no) + padToWidth(`${bg}${fg}${sigil} ${preserveBg(text, bg)}`, bgWidth) + p.reset;
261
+ return `${gutter(no)}${fg}${sigil} ${text}${p.reset}`;
262
+ };
254
263
  for (let i = 0; i < hunk.lines.length; i++) {
255
264
  const line = hunk.lines[i];
256
265
  const no = String(line.type === "removed" ? (line.oldNo ?? "") : (line.newNo ?? line.oldNo ?? "")).padStart(noW);
257
266
  if (line.type === "context") {
258
267
  const raw = truncateText(line.text, lineTextW);
259
268
  const text = lang ? highlightLine(raw, lang) : raw;
260
- out.push(`${gutter(no)} ${p.dim}${text}${p.reset}`);
269
+ // The flush gutter dims only the line number; the code stays normal/highlighted.
270
+ out.push(!gutterLine ? `${p.dim}${no}${p.reset} ${text}` : `${gutter(no)} ${p.dim}${text}${p.reset}`);
261
271
  continue;
262
272
  }
263
273
  if (line.type === "removed") {
@@ -276,19 +286,9 @@ function renderUnifiedHunk(hunk, layout) {
276
286
  const raw = truncateText(line.text, lineTextW);
277
287
  removedText = lang ? highlightLine(raw, lang) : raw;
278
288
  }
279
- if (useTrueColor) {
280
- out.push(gutter(no) + padToWidth(`${p.errorBg}${p.error}- ${preserveBg(removedText, p.errorBg)}`, bgWidth) + p.reset);
281
- }
282
- else {
283
- out.push(`${gutter(no)}${p.error}- ${removedText}${p.reset}`);
284
- }
289
+ out.push(change(no, "-", p.errorBg, p.error, removedText));
285
290
  if (addedText !== null && addedNo !== null) {
286
- if (useTrueColor) {
287
- out.push(gutter(addedNo) + padToWidth(`${p.successBg}${p.success}+ ${preserveBg(addedText, p.successBg)}`, bgWidth) + p.reset);
288
- }
289
- else {
290
- out.push(`${gutter(addedNo)}${p.success}+ ${addedText}${p.reset}`);
291
- }
291
+ out.push(change(addedNo, "+", p.successBg, p.success, addedText));
292
292
  }
293
293
  continue;
294
294
  }
@@ -297,12 +297,7 @@ function renderUnifiedHunk(hunk, layout) {
297
297
  continue;
298
298
  const raw = truncateText(line.text, lineTextW);
299
299
  const text = lang ? highlightLine(raw, lang) : raw;
300
- if (useTrueColor) {
301
- out.push(gutter(no) + padToWidth(`${p.successBg}${p.success}+ ${preserveBg(text, p.successBg)}`, bgWidth) + p.reset);
302
- }
303
- else {
304
- out.push(`${gutter(no)}${p.success}+ ${text}${p.reset}`);
305
- }
300
+ out.push(change(no, "+", p.successBg, p.success, text));
306
301
  }
307
302
  }
308
303
  return out;
@@ -0,0 +1,170 @@
1
+ ---
2
+ name: ads
3
+ description: >-
4
+ Full ADS query syntax reference and search strategy for the ads_search, ads_paper, ads_citations,
5
+ and ads_download_pdf tools. Load this before composing ADS queries — the tool descriptions only
6
+ cover basic field prefixes. Contains: fielded search syntax, date/class filters (entdate, arxiv_class),
7
+ citation operators, wildcards, positional search, properties, doctypes, daily arXiv listing patterns,
8
+ and query recipes.
9
+ ---
10
+
11
+ # ADS Query Syntax & Search Strategy
12
+
13
+ Reference: <https://ui.adsabs.harvard.edu/help/search/>
14
+
15
+ ## Query Basics
16
+
17
+ - Space = AND, `OR`, `NOT` / `-` (exclude), `()` group, `"phrase"`
18
+ - Precedence: `NOT` > `AND` > `OR` > implicit-AND > `-`
19
+
20
+ ## Fielded Search
21
+
22
+ ### Text Fields
23
+
24
+ | Field | Syntax |
25
+ |-------|--------|
26
+ | Title+Abstract+Keywords | `abs:"phrase"` |
27
+ | Title only | `title:"phrase"` |
28
+ | Abstract only | `abstract:"phrase"` |
29
+ | Keywords | `keyword:"phrase"` |
30
+ | Full text (body+abs+title+ack+kw) | `full:"phrase"` |
31
+ | Body only | `body:"phrase"` |
32
+ | Acknowledgements | `ack:"phrase"` |
33
+
34
+ ### Author
35
+
36
+ | Syntax | Meaning |
37
+ |--------|---------|
38
+ | `author:"Last, F"` | Greedy match (initials, variations) |
39
+ | `author:"Last, First M"` | More precise (recommended) |
40
+ | `author:"^Last, F"` | First-author only |
41
+ | `=author:"Last, F"` | Exact match, no synonym expansion |
42
+
43
+ Precision: `author:"murray, s"` (broadest) → `"murray, stephen"` → `"murray, stephen s"` (tightest)
44
+
45
+ ### Identifiers & Publication
46
+
47
+ `bibcode:ID`, `doi:DOI`, `arXiv:ID`, `identifier:ID`, `bibstem:ApJ`, `volume:N`, `issue:N`, `page:N`, `year:YYYY` or `year:YYYY-YYYY`, `pubdate:[YYYY-MM TO YYYY-MM]`
48
+
49
+ ### Affiliation
50
+
51
+ `aff:"phrase"` (raw), `inst:"Harvard U"` (curated, matches variants), `inst:"UCLA/IGPP"` (department), `aff_id:ID`
52
+
53
+ ### Object & Position
54
+
55
+ `object:Andromeda` (SIMBAD+NED), `object:"(SMC OR LMC) AND M31"` (combined), cone search: `object:"RA Dec:radius"` (decimal deg or sexagesimal, default 2', max 60')
56
+
57
+ ### Classification & Counts
58
+
59
+ `database:astronomy|physics|general`, `doctype:type`, `arxiv_class:"class"`, `property:flag`, `bibgroup:name`, `citation_count:[10 TO 100]`, `author_count:[10 TO 100]`, `read_count:N`, `facility:/regex/`, `orcid:ID`, `grant:agency`
60
+
61
+ ## Synonyms & Case Sensitivity
62
+
63
+ - lowercase → matches variations + synonyms (e.g. `title:star` → star, stars, stellar…)
64
+ - UPPERCASE → acronym-only (`title:STAR` → only "STAR")
65
+ - `=field:` prefix → exact match, no synonym expansion
66
+
67
+ ## Wildcards & Proximity
68
+
69
+ | Syntax | Meaning |
70
+ |--------|---------|
71
+ | `*` / `?` | Multi/single-char wildcard |
72
+ | `NEAR[N]` | ≤N words apart, any order |
73
+ | `"term1 term2"~N` | In-order proximity within N positions |
74
+ | `/regex/` | Lucene regex on indexed tokens |
75
+
76
+ ## Positional Search — `pos(query, positions...)`
77
+
78
+ Works on: `author`, `aff`, `title`. Examples: `pos(author:"Oort, J", 2)` (2nd author), `pos(author:"Oort", 1,3)` (1st–3rd), `pos(author:"Oort", -1)` (last), `pos(aff:"harvard", 1)` (1st author at Harvard)
79
+
80
+ ## Citation & Reference Operators
81
+
82
+ `citations(query)` = papers citing query results, `references(query)` = papers cited by query results. Nestable with other terms.
83
+
84
+ ## Second-Order Operators
85
+
86
+ `similar(query)` (textually similar), `trending(query)` (read by same readers), `useful(query)` (frequently cited by results), `reviews(query)` (citing papers ranked by freq), `topn(N, query, sort)`
87
+
88
+ Tip: `similar()` excludes originals; use disjoint `entdate` ranges to control overlap.
89
+
90
+ ## Properties
91
+
92
+ `refereed`, `notrefereed`, `article`, `nonarticle`, `openaccess`, `ads_openaccess`, `pub_openaccess`, `eprint_openaccess`, `author_openaccess`, `data`, `esource`, `inspire`, `toc`
93
+
94
+ ## Document Types
95
+
96
+ `article`, `eprint`, `inproceedings`, `inbook`, `abstract`, `book`, `bookreview`, `catalog`, `circular`, `erratum`, `mastersthesis`, `newsletter`, `obituary`, `phdthesis`, `pressrelease`, `proceedings`, `proposal`, `software`, `talk`, `techreport`, `misc`
97
+
98
+ ## Bibliographic Groups
99
+
100
+ Institutional: ARI, CfA, CFHT, Leiden, USNO | Telescope: ALMA, CXC, ESO, Gemini, Herschel, HST, ISO, IUE, JCMT, Keck, Magellan, NOIRLab, NRAO, ROSAT, SDO, SMA, Spitzer, Subaru, Swift, UKIRT, XMM
101
+
102
+ ## Daily arXiv Listings
103
+
104
+ Use `entdate` (day-resolution) with `doctype:eprint` and `arxiv_class`. Note: `pubdate` is month-resolution only.
105
+
106
+ ```
107
+ # Today's astro-ph.CO (±2 day window)
108
+ arxiv_class:"astro-ph.CO" entdate:[2026-04-07 TO 2026-04-09] doctype:eprint
109
+
110
+ # All astro-ph classes
111
+ arxiv_class:("astro-ph.CO" OR "astro-ph.GA" OR "astro-ph.HE" OR "astro-ph.IM" OR "astro-ph.EP" OR "astro-ph.SR") entdate:[2026-04-07 TO 2026-04-09] doctype:eprint
112
+ ```
113
+
114
+ Subclasses: `CO` (Cosmology), `EP` (Earth & Planetary), `GA` (Galaxy Astrophysics), `HE` (High Energy), `IM` (Instrumentation), `SR` (Solar & Stellar).
115
+
116
+ ## Search Strategy: Simplicity First
117
+
118
+ - Start with 2–3 core nouns. If too many results, add constraints (year, author, title:). Don't start with a sentence.
119
+ - ADS is keyword/metadata matching, not semantic search. Overloading queries kills recall.
120
+ - Use `detail='full'` on fewer results rather than compact on many — abstracts often contain the answer.
121
+
122
+ ### Common Pitfalls
123
+
124
+ **1. Compound multi-concept queries → zero results.**
125
+ Fix: 1–2 core terms + `sort_by` + `year_from:`. Scan abstracts for specifics.
126
+ ```
127
+ # Bad: "Population III He II helium 1640 JWST metal-poor galaxy candidate"
128
+ # Good: "Population III JWST" sort_by:date year_from:2024
129
+ ```
130
+
131
+ **2. Non-article doctypes polluting results.**
132
+ Fix: `doctype:article` or `property:refereed`.
133
+
134
+ **3. Iterative reformulation without simplifying.**
135
+ If 2+ zero-result queries on the same topic: strip to 1–2 broadest terms, or use `web_search` first to find titles/authors, then look up in ADS.
136
+
137
+ **4. Use `web_search` → ADS as a two-step pipeline.**
138
+ For complex/emerging topics, start with `web_search` (plural `queries`, 2–4 varied angles) to identify key papers/arXiv IDs, then verify via `ads_paper` or targeted `ads_search`.
139
+
140
+ ### When Keyword Search Fails, Use Citation Networks
141
+
142
+ For interdisciplinary connections, find a known paper then walk citations (`ads_citations`) or references. Citation chains beat keyword matching for cross-domain discovery.
143
+
144
+ ## Quick Query Recipes
145
+
146
+ ```
147
+ # Recent refereed articles on a topic
148
+ abs:"dark energy" year:2023-2025 property:refereed doctype:article
149
+
150
+ # Papers by first author at an institution
151
+ author:"^smith, john" inst:"MIT"
152
+
153
+ # Highly-cited reviews
154
+ reviews("machine learning astronomy") property:refereed
155
+
156
+ # Papers citing a specific work, sorted by citations
157
+ citations(bibcode:2023ApJ...950L..12A) sort:citation_count
158
+
159
+ # Object in specific journal
160
+ object:Andromeda bibstem:ApJ
161
+
162
+ # Open access with data links
163
+ property:openaccess property:data keyword:"gravitational waves"
164
+
165
+ # Exclude preprints, keep only journal articles
166
+ abs:"transiting exoplanet" doctype:article -arxiv_class:*
167
+
168
+ # Cone search
169
+ object:"12h30m49.4s +12d29m40s:5"
170
+ ```