@sns-myagent/cli 0.3.4 → 0.3.6
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 +6 -4
- package/scripts/smoke-tui.ts +110 -0
- package/src/cli/agents-cli.ts +1 -1
- package/src/cli/commands/init-xdg.ts +1 -1
- package/src/cli/profile-alias.ts +6 -6
- package/src/cli/ssh-cli.ts +7 -7
- package/src/commands/read.ts +1 -1
- package/src/config/settings-schema.ts +1 -1
- package/src/config/settings.ts +1 -1
- package/src/dap/session.ts +2 -2
- package/src/hindsight/bank.ts +1 -1
- package/src/hindsight/config.ts +1 -1
- package/src/internal-urls/docs-index.ts +1 -1
- package/src/internal-urls/index.ts +1 -1
- package/src/internal-urls/local-protocol.ts +2 -2
- package/src/internal-urls/router.ts +3 -3
- package/src/internal-urls/{omp-protocol.ts → snsagent-protocol.ts} +12 -12
- package/src/internal-urls/types.ts +1 -1
- package/src/modes/acp/acp-agent.ts +1 -1
- package/src/modes/components/welcome.ts +9 -7
- package/src/modes/internal-url-autocomplete.ts +1 -1
- package/src/modes/setup-wizard/scenes/splash.ts +1 -1
- package/src/task/omp-command.ts +1 -1
- package/src/tools/image-gen.ts +1 -1
- package/src/tools/read.ts +2 -2
- package/src/tools/report-tool-issue.ts +1 -1
- package/src/tools/search.ts +4 -4
- package/src/tui/chat-blocks.ts +117 -174
- package/src/tui/code-cell.ts +9 -9
- package/src/tui/command-palette.ts +62 -175
- package/src/tui/hyperlink.ts +1 -1
- package/src/tui/index.ts +1 -1
- package/src/tui/splash.ts +67 -111
- package/src/ui/banner.ts +1 -1
- package/src/ui/error-display.ts +67 -103
- package/src/ui/gradient.ts +15 -95
- package/src/ui/index.ts +3 -9
- package/src/ui/memory-toast.ts +51 -77
- package/src/ui/status-bar.ts +26 -47
- package/src/web/scrapers/crates-io.ts +1 -1
- package/src/web/scrapers/docs-rs.ts +1 -1
- package/src/web/scrapers/github.ts +1 -1
- package/src/web/search/providers/codex.ts +2 -2
package/src/ui/memory-toast.ts
CHANGED
|
@@ -1,102 +1,76 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Memory toast
|
|
3
|
-
*
|
|
4
|
-
* Shows brief, non-intrusive memory recall/save notifications.
|
|
5
|
-
* Auto-dismiss style — fades after a short duration.
|
|
2
|
+
* Memory toast — brief non-intrusive recall/save notifications.
|
|
3
|
+
* Single accent (cyan), no gradient, no per-type color explosion.
|
|
6
4
|
*/
|
|
5
|
+
|
|
7
6
|
import chalk from "chalk";
|
|
8
|
-
import gradient from "gradient-string";
|
|
9
|
-
import { BRAND_GRADIENT } from "./colors.js";
|
|
10
7
|
|
|
11
8
|
export type ToastType = "recall" | "save" | "forget" | "info";
|
|
12
9
|
|
|
13
10
|
export interface MemoryToastOptions {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
memoryId?: string;
|
|
20
|
-
/** Relevance score (0-1). */
|
|
21
|
-
relevance?: number;
|
|
22
|
-
/** Duration in ms before auto-dismiss (default: 3000). */
|
|
23
|
-
duration?: number;
|
|
11
|
+
type: ToastType;
|
|
12
|
+
message: string;
|
|
13
|
+
memoryId?: string;
|
|
14
|
+
relevance?: number;
|
|
15
|
+
duration?: number;
|
|
24
16
|
}
|
|
25
17
|
|
|
26
|
-
const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
18
|
+
const TOAST_LABEL: Record<ToastType, string> = {
|
|
19
|
+
recall: "memory",
|
|
20
|
+
save: "saved",
|
|
21
|
+
forget: "forgot",
|
|
22
|
+
info: "info",
|
|
23
|
+
};
|
|
32
24
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
const grad = gradient(config.gradient);
|
|
25
|
+
const TOAST_ICON: Record<ToastType, string> = {
|
|
26
|
+
recall: "·",
|
|
27
|
+
save: "+",
|
|
28
|
+
forget: "-",
|
|
29
|
+
info: "i",
|
|
30
|
+
};
|
|
40
31
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
export function renderMemoryToast(opts: MemoryToastOptions): string {
|
|
33
|
+
const icon = TOAST_ICON[opts.type];
|
|
34
|
+
const label = chalk.cyan.bold(` ${TOAST_LABEL[opts.type]} `);
|
|
35
|
+
const msg = opts.message;
|
|
44
36
|
|
|
45
|
-
|
|
37
|
+
const parts = [chalk.dim(icon), label, msg];
|
|
46
38
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
39
|
+
if (opts.memoryId) {
|
|
40
|
+
parts.push(chalk.dim(`#${opts.memoryId.slice(0, 8)}`));
|
|
41
|
+
}
|
|
50
42
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
43
|
+
if (opts.relevance !== undefined) {
|
|
44
|
+
const score = Math.round(opts.relevance * 100);
|
|
45
|
+
const scoreColor = score > 80 ? chalk.cyan : chalk.dim;
|
|
46
|
+
parts.push(scoreColor(`(${score}%)`));
|
|
47
|
+
}
|
|
56
48
|
|
|
57
|
-
|
|
49
|
+
return ` ${parts.join(" ")}`;
|
|
58
50
|
}
|
|
59
51
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
const scoreStr = relevance !== undefined
|
|
73
|
-
? chalk.dim(` ${Math.round(relevance * 100)}% match`)
|
|
74
|
-
: "";
|
|
75
|
-
|
|
76
|
-
const lines = [
|
|
77
|
-
`${icon} ${label} ${queryStr}${scoreStr}`,
|
|
78
|
-
` ${chalk.dim(snippet.slice(0, 120))}${snippet.length > 120 ? chalk.dim("...") : ""}`,
|
|
79
|
-
];
|
|
80
|
-
|
|
81
|
-
return lines.join("\n");
|
|
52
|
+
export function renderMemoryRecall(query: string, snippet: string, relevance?: number): string {
|
|
53
|
+
const queryStr = chalk.cyan(`"${query}"`);
|
|
54
|
+
const scoreStr = relevance !== undefined
|
|
55
|
+
? chalk.dim(` ${Math.round(relevance * 100)}% match`)
|
|
56
|
+
: "";
|
|
57
|
+
|
|
58
|
+
const lines = [
|
|
59
|
+
`${chalk.dim("·")} ${chalk.cyan.bold(" memory ")} ${queryStr}${scoreStr}`,
|
|
60
|
+
` ${chalk.dim(snippet.slice(0, 120))}${snippet.length > 120 ? chalk.dim("...") : ""}`,
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
return lines.join("\n");
|
|
82
64
|
}
|
|
83
65
|
|
|
84
|
-
/**
|
|
85
|
-
* Render a memory save confirmation toast.
|
|
86
|
-
*/
|
|
87
66
|
export function renderMemorySave(content: string, scope?: string): string {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const scopeStr = scope ? chalk.dim(` [${scope}]`) : "";
|
|
92
|
-
const preview = content.length > 80 ? content.slice(0, 80) + "..." : content;
|
|
67
|
+
const label = chalk.cyan.bold(" saved ");
|
|
68
|
+
const scopeStr = scope ? chalk.dim(` [${scope}]`) : "";
|
|
69
|
+
const preview = content.length > 80 ? content.slice(0, 80) + "..." : content;
|
|
93
70
|
|
|
94
|
-
|
|
71
|
+
return `${chalk.dim("+")} ${label}${scopeStr} ${chalk.dim(preview)}`;
|
|
95
72
|
}
|
|
96
73
|
|
|
97
|
-
/**
|
|
98
|
-
* Clear toast line (ANSI escape to clear current line).
|
|
99
|
-
*/
|
|
100
74
|
export function clearToastLine(): void {
|
|
101
|
-
|
|
75
|
+
process.stdout.write("\x1b[2K\r");
|
|
102
76
|
}
|
package/src/ui/status-bar.ts
CHANGED
|
@@ -1,63 +1,42 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Status bar
|
|
3
|
-
*
|
|
4
|
-
* Renders a bottom-line summary: model, tokens, session time, memory hits.
|
|
5
|
-
* Uses ANSI to draw a single-line bar at the bottom of the terminal.
|
|
6
|
-
* Premium gradient styling.
|
|
2
|
+
* Status bar — bottom-line summary.
|
|
3
|
+
* Minimal: dim key + accent value. No gradient, no per-segment color.
|
|
7
4
|
*/
|
|
8
5
|
|
|
9
6
|
import chalk from "chalk";
|
|
10
|
-
import gradient from "gradient-string";
|
|
11
|
-
import { BRAND_GRADIENT } from "./colors.js";
|
|
12
7
|
|
|
13
|
-
/** Runtime state passed into the status bar renderer. */
|
|
14
8
|
export interface StatusBarState {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
/** Session start timestamp (ms since epoch). */
|
|
20
|
-
sessionStarted: number;
|
|
21
|
-
/** Number of memory/context hits. */
|
|
22
|
-
memoryHits: number;
|
|
9
|
+
model: string;
|
|
10
|
+
tokensUsed: number;
|
|
11
|
+
sessionStarted: number;
|
|
12
|
+
memoryHits: number;
|
|
23
13
|
}
|
|
24
14
|
|
|
25
15
|
function formatDuration(ms: number): string {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
16
|
+
const secs = Math.floor(ms / 1000);
|
|
17
|
+
const mins = Math.floor(secs / 60);
|
|
18
|
+
const hrs = Math.floor(mins / 60);
|
|
19
|
+
if (hrs > 0) return `${hrs}h${mins % 60}m`;
|
|
20
|
+
if (mins > 0) return `${mins}m${secs % 60}s`;
|
|
21
|
+
return `${secs}s`;
|
|
32
22
|
}
|
|
33
23
|
|
|
34
|
-
/**
|
|
35
|
-
* Render the status bar to stdout.
|
|
36
|
-
* Overwrites the current line using `\r` + ANSI clear-line.
|
|
37
|
-
*/
|
|
38
24
|
export function renderStatusBar(state: StatusBarState): void {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
const sep = chalk.dim(" │ ");
|
|
54
|
-
const bar = ` ${segments.join(sep)} `;
|
|
55
|
-
process.stdout.write(`\x1b[2K\r${bar}`);
|
|
25
|
+
const elapsed = formatDuration(Date.now() - state.sessionStarted);
|
|
26
|
+
const tokens = state.tokensUsed > 1000
|
|
27
|
+
? `${(state.tokensUsed / 1000).toFixed(1)}k`
|
|
28
|
+
: String(state.tokensUsed);
|
|
29
|
+
|
|
30
|
+
// Single dim/accent pair, no per-segment color
|
|
31
|
+
const k = (s: string) => chalk.dim(s);
|
|
32
|
+
const v = (s: string) => chalk.cyan(s);
|
|
33
|
+
const sep = chalk.dim(" · ");
|
|
34
|
+
|
|
35
|
+
const bar = ` ${k("model")} ${v(state.model)}${sep}${k("tokens")} ${v(tokens)}${sep}${k("time")} ${v(elapsed)}${sep}${k("mem")} ${v(String(state.memoryHits))} `;
|
|
36
|
+
|
|
37
|
+
process.stdout.write(`\x1b[2K\r${bar}`);
|
|
56
38
|
}
|
|
57
39
|
|
|
58
|
-
/**
|
|
59
|
-
* Clear the status bar line (call before printing normal output).
|
|
60
|
-
*/
|
|
61
40
|
export function clearStatusBar(): void {
|
|
62
|
-
|
|
41
|
+
process.stdout.write("\x1b[2K\r");
|
|
63
42
|
}
|
|
@@ -26,7 +26,7 @@ export const handleCratesIo: SpecialHandler = async (
|
|
|
26
26
|
const result = await loadPage(apiUrl, {
|
|
27
27
|
timeout,
|
|
28
28
|
signal,
|
|
29
|
-
headers: { "User-Agent": "
|
|
29
|
+
headers: { "User-Agent": "snsagent-web-fetch/1.0 (https://github.com/Reihantt6/sns-myagent)" },
|
|
30
30
|
});
|
|
31
31
|
|
|
32
32
|
if (!result.ok) return null;
|
|
@@ -377,7 +377,7 @@ export const handleDocsRs: SpecialHandler = async (
|
|
|
377
377
|
const requestSignal = ptree.combineSignals(signal, timeout * 1000);
|
|
378
378
|
const response = await fetch(jsonUrl, {
|
|
379
379
|
signal: requestSignal,
|
|
380
|
-
headers: { "User-Agent": "
|
|
380
|
+
headers: { "User-Agent": "snsagent-web-fetch/1.0", Accept: "application/gzip" },
|
|
381
381
|
redirect: "follow",
|
|
382
382
|
});
|
|
383
383
|
if (!response.ok) return null;
|
|
@@ -121,7 +121,7 @@ export async function fetchGitHubApi(
|
|
|
121
121
|
|
|
122
122
|
const headers: Record<string, string> = {
|
|
123
123
|
Accept: "application/vnd.github.v3+json",
|
|
124
|
-
"User-Agent": "
|
|
124
|
+
"User-Agent": "snsagent-web-fetch/1.0",
|
|
125
125
|
};
|
|
126
126
|
|
|
127
127
|
// Use GITHUB_TOKEN if available
|
|
@@ -303,8 +303,8 @@ function buildCodexHeaders(accessToken: string, accountId: string): Record<strin
|
|
|
303
303
|
Authorization: `Bearer ${accessToken}`,
|
|
304
304
|
"chatgpt-account-id": accountId,
|
|
305
305
|
"OpenAI-Beta": "responses=experimental",
|
|
306
|
-
originator: "
|
|
307
|
-
"User-Agent": `
|
|
306
|
+
originator: "snsagent",
|
|
307
|
+
"User-Agent": `snsagent/${packageJson.version} (${os.platform()} ${os.release()}; ${os.arch()})`,
|
|
308
308
|
Accept: "text/event-stream",
|
|
309
309
|
"Content-Type": "application/json",
|
|
310
310
|
};
|