pi-goosedump 0.12.72 → 0.13.1

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 (2) hide show
  1. package/dist/index.ts +385 -23
  2. package/package.json +2 -2
package/dist/index.ts CHANGED
@@ -1871,6 +1871,367 @@ import {
1871
1871
  truncateHead
1872
1872
  } from "@earendil-works/pi-coding-agent";
1873
1873
  import { Type as Type3 } from "typebox";
1874
+
1875
+ // src/tui-render-utils.ts
1876
+ import { Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
1877
+ var SUMMARY_PREFIX = "↳";
1878
+ var EXPAND_HINT = " • Ctrl+O to expand";
1879
+ function renderToolLabel(theme, label) {
1880
+ const boldFn = typeof theme.bold === "function" ? theme.bold.bind(theme) : (text) => text;
1881
+ return theme.fg("toolTitle", boldFn(label));
1882
+ }
1883
+ function appendExpandHint(text, hidden) {
1884
+ return hidden ? `${text}${EXPAND_HINT}` : text;
1885
+ }
1886
+ function summaryLine(summary, options = {}) {
1887
+ const prefix = options.theme ? options.theme.fg(options.style ?? "dim", SUMMARY_PREFIX) : SUMMARY_PREFIX;
1888
+ return appendExpandHint(`${prefix} ${summary}`, Boolean(options.hidden));
1889
+ }
1890
+ function isRendererExpanded(options, context, defaultExpanded = false) {
1891
+ return context?.expanded ?? options?.expanded ?? defaultExpanded;
1892
+ }
1893
+ function resolveRenderResultContext(options, rest, defaultExpanded = false) {
1894
+ const context = rest[0] ?? options ?? {};
1895
+ return {
1896
+ isPartial: context.isPartial ?? options?.isPartial ?? false,
1897
+ isError: context.isError ?? false,
1898
+ expanded: isRendererExpanded(options, context, defaultExpanded),
1899
+ width: context.width ?? options?.width,
1900
+ cwd: context.cwd ?? process.cwd(),
1901
+ context
1902
+ };
1903
+ }
1904
+ function normalizeWidth(width, fallback = 80) {
1905
+ return typeof width === "number" && Number.isFinite(width) && width > 0 ? Math.floor(width) : fallback;
1906
+ }
1907
+ function clampLineToWidth(line, width) {
1908
+ if (width === undefined || width === null)
1909
+ return line;
1910
+ const normalized = normalizeWidth(width);
1911
+ return visibleWidth(line) <= normalized ? line : truncateToWidth(line, normalized);
1912
+ }
1913
+ function clampLinesToWidth(lines, width) {
1914
+ if (width === undefined || width === null)
1915
+ return lines;
1916
+ return lines.map((line) => clampLineToWidth(line, width));
1917
+ }
1918
+ function renderPendingResult(pendingLabel, width, theme) {
1919
+ return new Text(clampLinesToWidth([summaryLine(pendingLabel, { theme, style: "muted" })], width).join(`
1920
+ `), 0, 0);
1921
+ }
1922
+ function renderErrorResult(textContent, options) {
1923
+ const firstLine = textContent.split(`
1924
+ `)[0] || (options.fallback ?? "Error");
1925
+ const body = options.expanded && textContent ? textContent : firstLine;
1926
+ return new Text(clampLinesToWidth(summaryLine(body, { theme: options.theme, style: "error" }).split(`
1927
+ `), options.width).join(`
1928
+ `), 0, 0);
1929
+ }
1930
+ function upsertTextComponent(lastComponent, text) {
1931
+ const component = lastComponent instanceof Text ? lastComponent : new Text("", 0, 0);
1932
+ component.setText(text);
1933
+ return component;
1934
+ }
1935
+
1936
+ // src/tool-renderers.ts
1937
+ function renderGooseRememberCall(args, theme, ...rest) {
1938
+ const context = rest[0] ?? {};
1939
+ const target = args?.session ? `${args?.provider ?? "pi"}:${args.session}` : "current session";
1940
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_remember")} ${theme.fg("accent", target)}`, context.width);
1941
+ return upsertTextComponent(context.lastComponent, text);
1942
+ }
1943
+ function renderGooseRememberResult(result, options, theme, ...rest) {
1944
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
1945
+ if (isPartial)
1946
+ return renderPendingResult("pending goose_remember", width, theme);
1947
+ const content = result.content?.[0]?.text ?? "";
1948
+ if (isError || result.isError) {
1949
+ return renderErrorResult(content, {
1950
+ expanded,
1951
+ width,
1952
+ fallback: "goose_remember failed",
1953
+ theme
1954
+ });
1955
+ }
1956
+ const style = content.includes("dropped") ? "warning" : content.includes("disabled") ? "dim" : "success";
1957
+ const summary = summaryLine(content.split(`
1958
+ `)[0] || "memory learning completed", {
1959
+ theme,
1960
+ style
1961
+ });
1962
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summary, width));
1963
+ }
1964
+ function renderGooseRecallCall(args, theme, ...rest) {
1965
+ const context = rest[0] ?? {};
1966
+ const query = typeof args?.query === "string" ? `"${args.query}"` : '""';
1967
+ const flags = [
1968
+ args?.type && `type=${args.type}`,
1969
+ args?.limit !== undefined && args.limit !== 5 && `limit=${args.limit}`,
1970
+ args?.allProjects && "all-projects",
1971
+ args?.history && "history"
1972
+ ].filter(Boolean);
1973
+ const flagsBadge = flags.length > 0 ? theme.fg("dim", ` [${flags.join(", ")}]`) : "";
1974
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_recall")} ${theme.fg("accent", query)}${flagsBadge}`, context.width);
1975
+ return upsertTextComponent(context.lastComponent, text);
1976
+ }
1977
+ function renderGooseRecallResult(result, options, theme, ...rest) {
1978
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
1979
+ if (isPartial)
1980
+ return renderPendingResult("pending goose_recall", width, theme);
1981
+ const content = result.content?.[0]?.text ?? "";
1982
+ if (isError || result.isError) {
1983
+ return renderErrorResult(content, { expanded, width, fallback: "goose_recall failed", theme });
1984
+ }
1985
+ if (content.startsWith("No durable memory") || content.startsWith("Durable memory is disabled") || content.startsWith("Memory recall dropped")) {
1986
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summaryLine(content, { theme, style: "dim" }), width));
1987
+ }
1988
+ const matchCount = (content.match(/\[mem_[^\]]+\]/g) || []).length;
1989
+ const count = matchCount > 0 ? matchCount : content.split(`
1990
+ `).filter((l) => l.trim().startsWith("-")).length;
1991
+ const unit = count === 1 ? "memory" : "memories";
1992
+ const summary = summaryLine(`${count} ${unit} recalled`, {
1993
+ hidden: !expanded,
1994
+ theme,
1995
+ style: "success"
1996
+ });
1997
+ const body = expanded ? `${summary}
1998
+
1999
+ ${content}` : summary;
2000
+ return upsertTextComponent(rest[0]?.lastComponent, clampLinesToWidth(body.split(`
2001
+ `), width).join(`
2002
+ `));
2003
+ }
2004
+ function renderGooseForgetCall(args, theme, ...rest) {
2005
+ const context = rest[0] ?? {};
2006
+ const target = args?.target ? String(args.target) : '""';
2007
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_forget")} ${theme.fg("accent", target)}`, context.width);
2008
+ return upsertTextComponent(context.lastComponent, text);
2009
+ }
2010
+ function renderGooseForgetResult(result, options, theme, ...rest) {
2011
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
2012
+ if (isPartial)
2013
+ return renderPendingResult("pending goose_forget", width, theme);
2014
+ const content = result.content?.[0]?.text ?? "";
2015
+ if (isError || result.isError) {
2016
+ return renderErrorResult(content, { expanded, width, fallback: "goose_forget failed", theme });
2017
+ }
2018
+ const isFailure = content.toLowerCase().includes("error");
2019
+ const summary = summaryLine(content, { theme, style: isFailure ? "error" : "success" });
2020
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summary, width));
2021
+ }
2022
+ function renderGooseMemoryStatusCall(_args, theme, ...rest) {
2023
+ const context = rest[0] ?? {};
2024
+ const text = clampLineToWidth(renderToolLabel(theme, "goose_memory_status"), context.width);
2025
+ return upsertTextComponent(context.lastComponent, text);
2026
+ }
2027
+ function renderGooseMemoryStatusResult(result, options, theme, ...rest) {
2028
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
2029
+ if (isPartial)
2030
+ return renderPendingResult("pending goose_memory_status", width, theme);
2031
+ const content = result.content?.[0]?.text ?? "";
2032
+ if (isError || result.isError) {
2033
+ return renderErrorResult(content, {
2034
+ expanded,
2035
+ width,
2036
+ fallback: "goose_memory_status failed",
2037
+ theme
2038
+ });
2039
+ }
2040
+ if (content.startsWith("Durable memory is disabled")) {
2041
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summaryLine(content, { theme, style: "dim" }), width));
2042
+ }
2043
+ let summaryText = "durable memory status";
2044
+ try {
2045
+ const parsed = JSON.parse(content);
2046
+ if (typeof parsed.entries === "number") {
2047
+ summaryText = `${parsed.entries} ${parsed.entries === 1 ? "entry" : "entries"} in durable memory`;
2048
+ }
2049
+ } catch {
2050
+ const firstLine = content.split(`
2051
+ `)[0];
2052
+ if (firstLine)
2053
+ summaryText = firstLine;
2054
+ }
2055
+ const summary = summaryLine(summaryText, { hidden: !expanded, theme, style: "success" });
2056
+ const body = expanded ? `${summary}
2057
+
2058
+ ${content}` : summary;
2059
+ return upsertTextComponent(rest[0]?.lastComponent, clampLinesToWidth(body.split(`
2060
+ `), width).join(`
2061
+ `));
2062
+ }
2063
+ function renderGooseSearchCall(args, theme, ...rest) {
2064
+ const context = rest[0] ?? {};
2065
+ const query = typeof args?.query === "string" ? `"${args.query}"` : '""';
2066
+ const target = args?.session ? theme.fg("dim", ` in ${args.provider ?? "pi"}:${args.session}`) : "";
2067
+ const flags = [
2068
+ args?.scope && args.scope !== "lineage" && `scope=${args.scope}`,
2069
+ args?.page && args.page > 1 && `page=${args.page}`
2070
+ ].filter(Boolean);
2071
+ const flagsBadge = flags.length > 0 ? theme.fg("dim", ` [${flags.join(", ")}]`) : "";
2072
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_search")} ${theme.fg("accent", query)}${target}${flagsBadge}`, context.width);
2073
+ return upsertTextComponent(context.lastComponent, text);
2074
+ }
2075
+ function renderGooseSearchResult(result, options, theme, ...rest) {
2076
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
2077
+ if (isPartial)
2078
+ return renderPendingResult("pending goose_search", width, theme);
2079
+ const content = result.content?.[0]?.text ?? "";
2080
+ if (isError || result.isError) {
2081
+ return renderErrorResult(content, { expanded, width, fallback: "goose_search failed", theme });
2082
+ }
2083
+ if (content.startsWith("No results")) {
2084
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summaryLine(content, { theme, style: "dim" }), width));
2085
+ }
2086
+ const hitCount = (content.match(/\[#[^\]]+\]/g) || []).length;
2087
+ const count = hitCount > 0 ? hitCount : content.split(`
2088
+ `).filter((l) => l.trim().length > 0).length;
2089
+ const unit = count === 1 ? "result" : "results";
2090
+ const pageMatch = content.match(/\(page (\d+)\)/);
2091
+ const pageSuffix = pageMatch ? ` (page ${pageMatch[1]})` : "";
2092
+ const summary = summaryLine(`${count} ${unit}${pageSuffix}`, {
2093
+ hidden: !expanded,
2094
+ theme,
2095
+ style: "success"
2096
+ });
2097
+ const body = expanded ? `${summary}
2098
+
2099
+ ${content}` : summary;
2100
+ return upsertTextComponent(rest[0]?.lastComponent, clampLinesToWidth(body.split(`
2101
+ `), width).join(`
2102
+ `));
2103
+ }
2104
+ function renderGooseGetCall(args, theme, ...rest) {
2105
+ const context = rest[0] ?? {};
2106
+ const ids = Array.isArray(args?.ids) ? args.ids : [];
2107
+ const idsDisplay = ids.length <= 3 ? ids.join(", ") : `${ids.slice(0, 3).join(", ")}… (${ids.length})`;
2108
+ const target = args?.session ? theme.fg("dim", ` in ${args.provider ?? "pi"}:${args.session}`) : "";
2109
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_get")} ${theme.fg("accent", `[${idsDisplay}]`)}${target}`, context.width);
2110
+ return upsertTextComponent(context.lastComponent, text);
2111
+ }
2112
+ function renderGooseGetResult(result, options, theme, ...rest) {
2113
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
2114
+ if (isPartial)
2115
+ return renderPendingResult("pending goose_get", width, theme);
2116
+ const content = result.content?.[0]?.text ?? "";
2117
+ if (isError || result.isError) {
2118
+ return renderErrorResult(content, { expanded, width, fallback: "goose_get failed", theme });
2119
+ }
2120
+ if (content.startsWith("No entries found")) {
2121
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summaryLine("no entries found", { theme, style: "dim" }), width));
2122
+ }
2123
+ const entryCount = (content.match(/\[#[^\]]+\]/g) || []).length;
2124
+ const count = entryCount > 0 ? entryCount : Array.isArray(options) ? options.length : 1;
2125
+ const unit = count === 1 ? "entry" : "entries";
2126
+ const summary = summaryLine(`${count} ${unit} retrieved`, {
2127
+ hidden: !expanded,
2128
+ theme,
2129
+ style: "success"
2130
+ });
2131
+ const body = expanded ? `${summary}
2132
+
2133
+ ${content}` : summary;
2134
+ return upsertTextComponent(rest[0]?.lastComponent, clampLinesToWidth(body.split(`
2135
+ `), width).join(`
2136
+ `));
2137
+ }
2138
+ function renderGooseGrepCall(args, theme, ...rest) {
2139
+ const context = rest[0] ?? {};
2140
+ const pattern = typeof args?.pattern === "string" ? `/${args.pattern}/` : "//";
2141
+ const target = args?.session ? theme.fg("dim", ` in ${args.provider ?? "pi"}:${args.session}`) : "";
2142
+ const flags = [args?.scope && args.scope !== "lineage" && `scope=${args.scope}`].filter(Boolean);
2143
+ const flagsBadge = flags.length > 0 ? theme.fg("dim", ` [${flags.join(", ")}]`) : "";
2144
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_grep")} ${theme.fg("accent", pattern)}${target}${flagsBadge}`, context.width);
2145
+ return upsertTextComponent(context.lastComponent, text);
2146
+ }
2147
+ function renderGooseGrepResult(result, options, theme, ...rest) {
2148
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
2149
+ if (isPartial)
2150
+ return renderPendingResult("pending goose_grep", width, theme);
2151
+ const content = result.content?.[0]?.text ?? "";
2152
+ if (isError || result.isError) {
2153
+ return renderErrorResult(content, { expanded, width, fallback: "goose_grep failed", theme });
2154
+ }
2155
+ if (content.startsWith("No matches")) {
2156
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summaryLine(content, { theme, style: "dim" }), width));
2157
+ }
2158
+ const matchCount = (content.match(/\[#[^\]]+\]/g) || []).length;
2159
+ const count = matchCount > 0 ? matchCount : content.split(`
2160
+ `).filter((l) => l.trim().length > 0).length;
2161
+ const unit = count === 1 ? "match" : "matches";
2162
+ const summary = summaryLine(`${count} ${unit}`, { hidden: !expanded, theme, style: "success" });
2163
+ const body = expanded ? `${summary}
2164
+
2165
+ ${content}` : summary;
2166
+ return upsertTextComponent(rest[0]?.lastComponent, clampLinesToWidth(body.split(`
2167
+ `), width).join(`
2168
+ `));
2169
+ }
2170
+ function renderGooseCompactCall(args, theme, ...rest) {
2171
+ const context = rest[0] ?? {};
2172
+ const flags = args?.keep ? [theme.fg("dim", `keep=${args.keep}`)] : [];
2173
+ const flagsBadge = flags.length > 0 ? ` [${flags.join(", ")}]` : "";
2174
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_compact")}${flagsBadge}`, context.width);
2175
+ return upsertTextComponent(context.lastComponent, text);
2176
+ }
2177
+ function renderGooseCompactResult(result, options, theme, ...rest) {
2178
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
2179
+ if (isPartial)
2180
+ return renderPendingResult("pending goose_compact", width, theme);
2181
+ const content = result.content?.[0]?.text ?? "";
2182
+ if (isError || result.isError) {
2183
+ return renderErrorResult(content, { expanded, width, fallback: "goose_compact failed", theme });
2184
+ }
2185
+ const style = content.includes("already in progress") ? "warning" : content.includes("Nothing to compact") ? "dim" : "success";
2186
+ const summary = summaryLine(content.split(`
2187
+ `)[0] || "compaction completed", { theme, style });
2188
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summary, width));
2189
+ }
2190
+ function renderGooseSessionsCall(args, theme, ...rest) {
2191
+ const context = rest[0] ?? {};
2192
+ const action = args?.action ?? "list";
2193
+ const target = args?.session ? `${args?.provider ?? "pi"}:${args.session}` : `(${args?.provider ?? "pi"})`;
2194
+ const text = clampLineToWidth(`${renderToolLabel(theme, "goose_sessions")} ${theme.fg("accent", action)} ${theme.fg("dim", target)}`, context.width);
2195
+ return upsertTextComponent(context.lastComponent, text);
2196
+ }
2197
+ function renderGooseSessionsResult(result, options, theme, ...rest) {
2198
+ const { isPartial, isError, expanded, width } = resolveRenderResultContext(options, rest);
2199
+ if (isPartial)
2200
+ return renderPendingResult("pending goose_sessions", width, theme);
2201
+ const content = result.content?.[0]?.text ?? "";
2202
+ if (isError || result.isError) {
2203
+ return renderErrorResult(content, {
2204
+ expanded,
2205
+ width,
2206
+ fallback: "goose_sessions failed",
2207
+ theme
2208
+ });
2209
+ }
2210
+ if (content.startsWith("No ")) {
2211
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summaryLine(content, { theme, style: "dim" }), width));
2212
+ }
2213
+ if (content.startsWith("Deleted session") || content.startsWith("Cannot delete")) {
2214
+ const style = content.startsWith("Cannot delete") ? "warning" : "success";
2215
+ return upsertTextComponent(rest[0]?.lastComponent, clampLineToWidth(summaryLine(content, { theme, style }), width));
2216
+ }
2217
+ const sessionCount = (content.match(/^- /gm) || []).length;
2218
+ const count = sessionCount > 0 ? sessionCount : content.split(`
2219
+ `).filter((l) => l.trim().startsWith("-")).length;
2220
+ const unit = count === 1 ? "session" : "sessions";
2221
+ const summary = summaryLine(`${count} ${unit} found`, {
2222
+ hidden: !expanded,
2223
+ theme,
2224
+ style: "success"
2225
+ });
2226
+ const body = expanded ? `${summary}
2227
+
2228
+ ${content}` : summary;
2229
+ return upsertTextComponent(rest[0]?.lastComponent, clampLinesToWidth(body.split(`
2230
+ `), width).join(`
2231
+ `));
2232
+ }
2233
+
2234
+ // src/tools.ts
1874
2235
  function memoryDisabledResult() {
1875
2236
  return textResult(MEMORY_DISABLED_MESSAGE);
1876
2237
  }
@@ -1945,7 +2306,7 @@ function gooseToolMeta(name) {
1945
2306
  promptGuidelines: [...policy.guidelines]
1946
2307
  };
1947
2308
  }
1948
- function defineGooseTool(name, parameters, handler) {
2309
+ function defineGooseTool(name, parameters, handler, renderers) {
1949
2310
  return defineTool({
1950
2311
  ...gooseToolMeta(name),
1951
2312
  parameters,
@@ -1955,7 +2316,9 @@ function defineGooseTool(name, parameters, handler) {
1955
2316
  } catch (err) {
1956
2317
  return goosedumpErrorResult(err);
1957
2318
  }
1958
- }
2319
+ },
2320
+ ...renderers?.renderCall ? { renderCall: renderers.renderCall } : {},
2321
+ ...renderers?.renderResult ? { renderResult: renderers.renderResult } : {}
1959
2322
  });
1960
2323
  }
1961
2324
  function registerGooseTools(pi, deps) {
@@ -1973,7 +2336,7 @@ function registerGooseTools(pi, deps) {
1973
2336
  }
1974
2337
  });
1975
2338
  return textResult(accepted ? `Memory learning started for ${resolved.target}.` : `Memory learning dropped for ${resolved.target}: another inference task is active.`);
1976
- }));
2339
+ }, { renderCall: renderGooseRememberCall, renderResult: renderGooseRememberResult }));
1977
2340
  pi.registerTool(defineGooseTool("goose_recall", Type3.Object({
1978
2341
  query: Type3.String({ description: PARAM_DESCRIPTIONS.memoryQuery }),
1979
2342
  type: Type3.Optional(Type3.Union(GOOSE_MEMORY_TYPES.map((type) => Type3.Literal(type)), { description: PARAM_DESCRIPTIONS.memoryType })),
@@ -2010,7 +2373,7 @@ function registerGooseTools(pi, deps) {
2010
2373
  if (hits.length === 0)
2011
2374
  return textResult(`No durable memory for "${params.query}"`);
2012
2375
  return textResult(formatMemoryHits(hits));
2013
- }));
2376
+ }, { renderCall: renderGooseRecallCall, renderResult: renderGooseRecallResult }));
2014
2377
  pi.registerTool(defineGooseTool("goose_forget", Type3.Object({
2015
2378
  target: Type3.String({
2016
2379
  description: PARAM_DESCRIPTIONS.forgetTarget
@@ -2024,13 +2387,13 @@ function registerGooseTools(pi, deps) {
2024
2387
  }
2025
2388
  const res = await goosedumpMemoryForget(params.target.trim(), signal, nativeExecutablePath);
2026
2389
  return textResult(res);
2027
- }));
2390
+ }, { renderCall: renderGooseForgetCall, renderResult: renderGooseForgetResult }));
2028
2391
  pi.registerTool(defineGooseTool("goose_memory_status", Type3.Object({}), async (_params, signal, ctx) => {
2029
2392
  const disabled = requireMemoryEnabled(ctx);
2030
2393
  if (disabled)
2031
2394
  return disabled;
2032
2395
  return textResult(await goosedumpMemoryStatus(signal, nativeExecutablePath));
2033
- }));
2396
+ }, { renderCall: renderGooseMemoryStatusCall, renderResult: renderGooseMemoryStatusResult }));
2034
2397
  pi.registerTool(defineGooseTool("goose_search", Type3.Object({
2035
2398
  query: Type3.String({ description: PARAM_DESCRIPTIONS.searchQuery }),
2036
2399
  ...historyBranchParams(),
@@ -2052,7 +2415,7 @@ function registerGooseTools(pi, deps) {
2052
2415
  return textResult(`Results for "${params.query}" (page ${page}):
2053
2416
 
2054
2417
  ${text}`);
2055
- }));
2418
+ }, { renderCall: renderGooseSearchCall, renderResult: renderGooseSearchResult }));
2056
2419
  pi.registerTool(defineGooseTool("goose_get", Type3.Object({
2057
2420
  ids: Type3.Array(Type3.String(), {
2058
2421
  minItems: 1,
@@ -2068,7 +2431,7 @@ ${text}`);
2068
2431
  return textResult("No entries found for the given IDs.");
2069
2432
  }
2070
2433
  return boundedHistoryResult(formatMessagesFull(messages));
2071
- }));
2434
+ }, { renderCall: renderGooseGetCall, renderResult: renderGooseGetResult }));
2072
2435
  pi.registerTool(defineGooseTool("goose_grep", Type3.Object({
2073
2436
  pattern: Type3.String({ description: PARAM_DESCRIPTIONS.pattern }),
2074
2437
  ...historyBranchParams()
@@ -2081,7 +2444,7 @@ ${text}`);
2081
2444
  return textResult(`No matches for "${params.pattern}"`);
2082
2445
  }
2083
2446
  return boundedHistoryResult(formatMessagesCompact(messages));
2084
- }));
2447
+ }, { renderCall: renderGooseGrepCall, renderResult: renderGooseGrepResult }));
2085
2448
  pi.registerTool(defineGooseTool("goose_compact", Type3.Object({
2086
2449
  keep: Type3.Optional(Type3.Integer({
2087
2450
  minimum: 1,
@@ -2096,7 +2459,7 @@ ${text}`);
2096
2459
  return textResult("Nothing to compact (session too small).");
2097
2460
  }
2098
2461
  return textResult(compactStartedMessage(keep, result === "queued"));
2099
- }));
2462
+ }, { renderCall: renderGooseCompactCall, renderResult: renderGooseCompactResult }));
2100
2463
  pi.registerTool(defineGooseTool("goose_sessions", Type3.Object({
2101
2464
  action: Type3.Optional(Type3.Union([Type3.Literal("list"), Type3.Literal("delete")], {
2102
2465
  default: "list",
@@ -2141,7 +2504,7 @@ ${text}`);
2141
2504
 
2142
2505
  ${lines.join(`
2143
2506
  `)}`);
2144
- }));
2507
+ }, { renderCall: renderGooseSessionsCall, renderResult: renderGooseSessionsResult }));
2145
2508
  }
2146
2509
 
2147
2510
  // src/tui.ts
@@ -2151,8 +2514,8 @@ import {
2151
2514
  Key,
2152
2515
  decodeKittyPrintable,
2153
2516
  matchesKey,
2154
- truncateToWidth,
2155
- visibleWidth,
2517
+ truncateToWidth as truncateToWidth2,
2518
+ visibleWidth as visibleWidth2,
2156
2519
  wrapTextWithAnsi
2157
2520
  } from "@earendil-works/pi-tui";
2158
2521
  import { existsSync as existsSync3 } from "node:fs";
@@ -2234,8 +2597,8 @@ class NumberInputSubmenu {
2234
2597
  }
2235
2598
  }
2236
2599
  function makeRow(content, innerW, border) {
2237
- const line = truncateToWidth(content, innerW);
2238
- const pad = Math.max(0, innerW - visibleWidth(line));
2600
+ const line = truncateToWidth2(content, innerW);
2601
+ const pad = Math.max(0, innerW - visibleWidth2(line));
2239
2602
  return `${border} ${line}${" ".repeat(pad)} ${border}`;
2240
2603
  }
2241
2604
  function overlayColors(theme) {
@@ -2254,7 +2617,7 @@ function overlayInnerWidth(width) {
2254
2617
  }
2255
2618
  function overlayHeader(colors, width, title) {
2256
2619
  const styled = colors.accent(` ${title} `);
2257
- const fill = colors.borderFg("─".repeat(Math.max(0, width - 4 - visibleWidth(styled))));
2620
+ const fill = colors.borderFg("─".repeat(Math.max(0, width - 4 - visibleWidth2(styled))));
2258
2621
  return `${colors.borderFg("╭─")}${styled}${fill}${colors.borderFg("─╮")}`;
2259
2622
  }
2260
2623
  function overlayFooter(colors, width) {
@@ -2386,8 +2749,8 @@ async function runSettingsEditor(ctx) {
2386
2749
  const { accent, bold, dim, muted, text } = colors;
2387
2750
  const innerW = overlayInnerWidth(width);
2388
2751
  const pad = (value, cellWidth) => {
2389
- const clipped = truncateToWidth(value, cellWidth);
2390
- return `${clipped}${" ".repeat(Math.max(0, cellWidth - visibleWidth(clipped)))}`;
2752
+ const clipped = truncateToWidth2(value, cellWidth);
2753
+ return `${clipped}${" ".repeat(Math.max(0, cellWidth - visibleWidth2(clipped)))}`;
2391
2754
  };
2392
2755
  const tabLabel = (label, active) => active ? accent(bold(`[${label}]`)) : muted(label);
2393
2756
  const tabs = `${tabLabel("Settings", tab === "settings")} ${tabLabel("Help", tab === "help")}`;
@@ -2395,11 +2758,11 @@ async function runSettingsEditor(ctx) {
2395
2758
  if (editor) {
2396
2759
  content.push(...editor.render(innerW));
2397
2760
  } else if (tab === "help") {
2398
- const shortcutWidth = Math.max(visibleWidth("Shortcut"), ...helpRows.map(([shortcut]) => visibleWidth(shortcut)));
2761
+ const shortcutWidth = Math.max(visibleWidth2("Shortcut"), ...helpRows.map(([shortcut]) => visibleWidth2(shortcut)));
2399
2762
  const descriptionWidth = Math.max(1, innerW - shortcutWidth - 4);
2400
- content.push(dim(` ${pad("Shortcut", shortcutWidth)} Description`), ...helpRows.map(([shortcut, description]) => ` ${accent(pad(shortcut, shortcutWidth))} ${text(truncateToWidth(description, descriptionWidth))}`));
2763
+ content.push(dim(` ${pad("Shortcut", shortcutWidth)} Description`), ...helpRows.map(([shortcut, description]) => ` ${accent(pad(shortcut, shortcutWidth))} ${text(truncateToWidth2(description, descriptionWidth))}`));
2401
2764
  } else {
2402
- const labelWidth = Math.max(...specs.map(({ key }) => visibleWidth(settingLabel(key))));
2765
+ const labelWidth = Math.max(...specs.map(({ key }) => visibleWidth2(settingLabel(key))));
2403
2766
  for (const [index, entry] of specs.entries()) {
2404
2767
  const selected = index === selectedSetting;
2405
2768
  const inherited = projectSettings[entry.key] === undefined;
@@ -2537,7 +2900,7 @@ async function runSearchPanel(ctx, query, executablePath) {
2537
2900
  }
2538
2901
  return {
2539
2902
  render(width) {
2540
- const header = overlayHeader(colors, width, `Goosedump search: ${truncateToWidth(query, 44)}`);
2903
+ const header = overlayHeader(colors, width, `Goosedump search: ${truncateToWidth2(query, 44)}`);
2541
2904
  if (error) {
2542
2905
  return [header, ...overlayError(colors, width, error), overlayFooter(colors, width)];
2543
2906
  }
@@ -3006,7 +3369,6 @@ ${renderToolRoutingPolicy()}`
3006
3369
  compaction.updateStatus(ctx);
3007
3370
  };
3008
3371
  registerGooseCommand("goose-settings", "Edit goosedump settings", openSettingsEditor);
3009
- registerGooseCommand("goosedump-settings", "Edit goosedump settings", openSettingsEditor);
3010
3372
  registerGooseCommand("goose-compact", "Compact the current session now; optionally keep the last N user turns", async (args, ctx) => {
3011
3373
  let keep = null;
3012
3374
  if (args.trim()) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-goosedump",
3
- "version": "0.12.72",
3
+ "version": "0.13.1",
4
4
  "description": "Pi extension for goosedump session search, durable memory, session management, and compaction",
5
5
  "keywords": [
6
6
  "compaction",
@@ -37,7 +37,7 @@
37
37
  "ci:test": "npm test"
38
38
  },
39
39
  "dependencies": {
40
- "@jarkkojs/goosedump": "^0.12.72"
40
+ "@jarkkojs/goosedump": "^0.13.1"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@earendil-works/pi-coding-agent": "^0.84.2",