picocode-core 0.9.120 → 0.9.121

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "picocode-core",
3
- "version": "0.9.120",
3
+ "version": "0.9.121",
4
4
  "description": "The agent runtime behind pico: sessions, tools, subagents, MCP, memory, and model access",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/ansi.js ADDED
@@ -0,0 +1,52 @@
1
+ const CSI_RE = /\x1b\[[0-9;?]*[ -/]*[@-~]/g
2
+ const MAX_ACTIVE_SGR = 32
3
+
4
+ export function stripAnsi(text) {
5
+ return String(text).replace(CSI_RE, '')
6
+ }
7
+
8
+ function isReset(params) {
9
+ return params === '' || params === '0' || params.split(';').every((code) => code === '0' || code === '')
10
+ }
11
+
12
+ // remembers which sgr sequences are still in effect so a line that starts
13
+ // mid-style can be prefixed with exactly the sequences the terminal would
14
+ // have applied, without interpreting colors at all
15
+ export function createSgrTracker() {
16
+ let active = []
17
+ let pending = ''
18
+
19
+ function feed(text) {
20
+ const input = pending + String(text)
21
+ pending = ''
22
+ let i = 0
23
+ while (i < input.length) {
24
+ const start = input.indexOf('\x1b[', i)
25
+ if (start === -1) break
26
+ let end = start + 2
27
+ while (end < input.length && !(input.charCodeAt(end) >= 0x40 && input.charCodeAt(end) <= 0x7e)) end++
28
+ if (end >= input.length) {
29
+ pending = input.slice(start)
30
+ break
31
+ }
32
+ if (input[end] === 'm') apply(input.slice(start + 2, end))
33
+ i = end + 1
34
+ }
35
+ }
36
+
37
+ function apply(params) {
38
+ if (isReset(params)) {
39
+ active = []
40
+ return
41
+ }
42
+ if (params.startsWith('0;')) active = []
43
+ active.push(params.startsWith('0;') ? params.slice(2) : params)
44
+ if (active.length > MAX_ACTIVE_SGR) active = active.slice(-MAX_ACTIVE_SGR)
45
+ }
46
+
47
+ function style() {
48
+ return active.map((params) => `\x1b[${params}m`).join('')
49
+ }
50
+
51
+ return { feed, style }
52
+ }
package/src/tools/bash.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { spawn } from 'node:child_process'
2
- import { sgr, stripAnsi, updateSgrState } from '@trendr/core'
2
+ import { stripAnsi, createSgrTracker } from '../ansi.js'
3
3
 
4
4
  const MAX_OUTPUT_CHARS = 30000
5
5
  const MAX_BUFFER_BYTES = 10 * 1024 * 1024
@@ -17,19 +17,19 @@ function createOutputPreview() {
17
17
  let current = ''
18
18
  let currentStartStyle = ''
19
19
  let completed = 0
20
- const ansiState = { fg: null, bg: null, attrs: 0 }
20
+ const sgr = createSgrTracker()
21
21
 
22
22
  function add(chunk) {
23
23
  const parts = String(chunk).split('\n')
24
24
  current = (current + parts[0]).slice(0, MAX_PREVIEW_LINE_CHARS)
25
- updateSgrState(parts[0], ansiState)
25
+ sgr.feed(parts[0])
26
26
  for (let i = 1; i < parts.length; i++) {
27
27
  lines.push({ text: current, startStyle: currentStartStyle })
28
28
  if (lines.length > OUTPUT_PREVIEW_LINES) lines.shift()
29
29
  completed++
30
- currentStartStyle = ansiState.fg != null || ansiState.bg != null || ansiState.attrs ? sgr(ansiState.fg, ansiState.bg, ansiState.attrs) : ''
30
+ currentStartStyle = sgr.style()
31
31
  current = parts[i].slice(0, MAX_PREVIEW_LINE_CHARS)
32
- updateSgrState(parts[i], ansiState)
32
+ sgr.feed(parts[i])
33
33
  }
34
34
  }
35
35