@thoth-agents/pi-thoth-theme 0.1.0 → 0.3.0

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 (41) hide show
  1. package/README.md +51 -10
  2. package/dist/index.ts +3967 -0
  3. package/package.json +7 -9
  4. package/src/index.ts +0 -53
  5. package/src/input-box/decorate.ts +0 -304
  6. package/src/input-box/frame.ts +0 -182
  7. package/src/input-box/gradient.ts +0 -92
  8. package/src/input-box/state.ts +0 -90
  9. package/src/render-kit/index.ts +0 -305
  10. package/src/render-kit/working.ts +0 -25
  11. package/src/shared/cache.ts +0 -21
  12. package/src/shared/config.ts +0 -86
  13. package/src/shared/duration.ts +0 -1
  14. package/src/shared/icons.ts +0 -89
  15. package/src/status-line/cost.ts +0 -56
  16. package/src/status-line/index.ts +0 -242
  17. package/src/status-line/layout.ts +0 -272
  18. package/src/status-line/snapshot.ts +0 -11
  19. package/src/status-line/throughput.ts +0 -61
  20. package/src/status-line/tokens.ts +0 -51
  21. package/src/tools/bash.ts +0 -237
  22. package/src/tools/border.ts +0 -21
  23. package/src/tools/box.ts +0 -258
  24. package/src/tools/edit.ts +0 -228
  25. package/src/tools/file-icons.ts +0 -139
  26. package/src/tools/find.ts +0 -227
  27. package/src/tools/frame.ts +0 -166
  28. package/src/tools/generic.ts +0 -195
  29. package/src/tools/grep.ts +0 -371
  30. package/src/tools/index.ts +0 -135
  31. package/src/tools/ls.ts +0 -231
  32. package/src/tools/ownership.ts +0 -70
  33. package/src/tools/powershell.ts +0 -1
  34. package/src/tools/read.ts +0 -194
  35. package/src/tools/ticker.ts +0 -101
  36. package/src/tools/write.ts +0 -188
  37. package/src/welcome/age.ts +0 -11
  38. package/src/welcome/index.ts +0 -132
  39. package/src/welcome/logo.ts +0 -35
  40. package/src/welcome/render.ts +0 -323
  41. package/src/welcome/resources.ts +0 -251
@@ -1,251 +0,0 @@
1
- import type {
2
- ExtensionAPI,
3
- ExtensionContext,
4
- SourceInfo,
5
- ToolInfo,
6
- } from '@earendil-works/pi-coding-agent';
7
- import {
8
- VERSION as PI_VERSION,
9
- SessionManager,
10
- } from '@earendil-works/pi-coding-agent';
11
- import type { IconMode } from '../shared/config.ts';
12
- import { icon } from '../shared/icons.ts';
13
- import { formatAge } from './age.ts';
14
-
15
- export interface WelcomeProvider {
16
- readonly name: string;
17
- readonly detail: string;
18
- }
19
-
20
- export interface WelcomeSession {
21
- readonly name: string;
22
- readonly timeAgo: string;
23
- }
24
-
25
- export interface WelcomeResourceCounts {
26
- readonly tools?: number | undefined;
27
- readonly skills?: number | undefined;
28
- readonly extensions?: number | undefined;
29
- }
30
-
31
- export interface WelcomeData {
32
- readonly version: string;
33
- readonly model?: string | undefined;
34
- readonly provider?: string | undefined;
35
- readonly resources: WelcomeResourceCounts;
36
- readonly providers: readonly WelcomeProvider[];
37
- readonly sessions: readonly WelcomeSession[];
38
- }
39
-
40
- export interface ResourceLoaderLike {
41
- getSkills?(): { skills: unknown[] };
42
- getExtensions?(): { extensions: unknown[] };
43
- }
44
-
45
- export interface StartupResourceOptions {
46
- sessionLister?: (cwd: string) => Promise<WelcomeSession[]>;
47
- skillCountLister?: (cwd: string) => number;
48
- extensionCountLister?: (cwd: string) => number;
49
- resourceLoader?: ResourceLoaderLike;
50
- iconMode?: IconMode;
51
- }
52
-
53
- function toolSourceLabel(sourceInfo: SourceInfo | undefined): string {
54
- if (!sourceInfo || typeof sourceInfo !== 'object') return 'core';
55
- const source = typeof sourceInfo.source === 'string' ? sourceInfo.source : '';
56
- if (source === 'builtin' || source === 'core') return 'core';
57
- if (source === 'sdk') return 'sdk';
58
- if (source.startsWith('npm:')) return source.slice('npm:'.length) || source;
59
- if (source.startsWith('git:')) return source.replace(/\.git(?:#.*)?$/i, '');
60
- const baseDir =
61
- typeof sourceInfo.baseDir === 'string' ? sourceInfo.baseDir : '';
62
- if (baseDir) {
63
- const parts = baseDir.replace(/\\/g, '/').split('/').filter(Boolean);
64
- return parts[parts.length - 1] || 'extension';
65
- }
66
- const path = typeof sourceInfo.path === 'string' ? sourceInfo.path : '';
67
- if (path) {
68
- const parts = path.replace(/\\/g, '/').split('/').filter(Boolean);
69
- const last = parts[parts.length - 1] || 'extension';
70
- return last.replace(/\.(?:ts|js|mjs|cjs)$/i, '');
71
- }
72
- return source || 'extension';
73
- }
74
-
75
- function groupToolDetails(tools: readonly ToolInfo[]): WelcomeProvider[] {
76
- const groups = new Map<string, string[]>();
77
- for (const tool of tools) {
78
- if (!tool || typeof tool.name !== 'string') continue;
79
- const name = tool.name.trim();
80
- if (!name) continue;
81
- const label = toolSourceLabel(tool.sourceInfo);
82
- let list = groups.get(label);
83
- if (!list) {
84
- list = [];
85
- groups.set(label, list);
86
- }
87
- list.push(name);
88
- }
89
-
90
- const result: WelcomeProvider[] = [];
91
- const sortedKeys = Array.from(groups.keys()).sort((a, b) => {
92
- if (a === 'core') return -1;
93
- if (b === 'core') return 1;
94
- return a.localeCompare(b);
95
- });
96
-
97
- for (const key of sortedKeys) {
98
- const toolNames = (groups.get(key) || []).sort();
99
- const sample = toolNames.slice(0, 3).join(' ');
100
- const remaining = toolNames.length > 3 ? ` +${toolNames.length - 3}` : '';
101
- result.push({
102
- name: key,
103
- detail: `${sample}${remaining}`,
104
- });
105
- }
106
-
107
- return result.slice(0, 4);
108
- }
109
-
110
- export async function fetchRecentSessions(
111
- cwd: string,
112
- limit = 4,
113
- mode: IconMode = 'nerd',
114
- ): Promise<WelcomeSession[]> {
115
- try {
116
- const sessions = await SessionManager.list(cwd);
117
- const sorted = [...sessions].sort(
118
- (a, b) => (b.modified?.getTime?.() ?? 0) - (a.modified?.getTime?.() ?? 0),
119
- );
120
- const out: WelcomeSession[] = [];
121
- for (const session of sorted) {
122
- if (out.length >= limit) break;
123
- const rawTitle =
124
- session.name?.trim() ||
125
- session.firstMessage?.trim() ||
126
- 'Untitled session';
127
- const cleanTitle = Array.from(rawTitle)
128
- .map((c) => {
129
- const code = c.charCodeAt(0);
130
- return code < 32 || code === 127 ? ' ' : c;
131
- })
132
- .join('')
133
- .replace(/\s+/g, ' ')
134
- .trim();
135
- const title =
136
- cleanTitle.length > 45
137
- ? `${cleanTitle.slice(0, 44)}${icon('ellipsis', mode)}`
138
- : cleanTitle;
139
- const timeAgo = formatAge(
140
- session.modified ? session.modified.getTime() : Date.now(),
141
- );
142
- out.push({ name: title, timeAgo });
143
- }
144
- return out;
145
- } catch {
146
- return [];
147
- }
148
- }
149
-
150
- export async function collectStartupResources(
151
- pi: ExtensionAPI,
152
- ctx: ExtensionContext,
153
- options?: StartupResourceOptions,
154
- ): Promise<WelcomeData> {
155
- let tools: ToolInfo[] = [];
156
- let toolsCount: number | undefined;
157
-
158
- if (typeof pi.getAllTools === 'function') {
159
- try {
160
- tools = pi.getAllTools() ?? [];
161
- toolsCount = tools.length;
162
- } catch {
163
- // ignore
164
- }
165
- } else if (typeof pi.getActiveTools === 'function') {
166
- try {
167
- const active = pi.getActiveTools() ?? [];
168
- toolsCount = active.length;
169
- } catch {
170
- // ignore
171
- }
172
- }
173
-
174
- const providers = groupToolDetails(tools);
175
-
176
- const loader: ResourceLoaderLike | undefined =
177
- options?.resourceLoader ??
178
- (ctx as unknown as { resourceLoader?: ResourceLoaderLike })
179
- ?.resourceLoader ??
180
- (pi as unknown as { resourceLoader?: ResourceLoaderLike })
181
- ?.resourceLoader ??
182
- (ctx as unknown as { session?: { resourceLoader?: ResourceLoaderLike } })
183
- ?.session?.resourceLoader;
184
-
185
- // 1. Loaded skills: live public source from options, resourceLoader, or pi.getCommands()
186
- let skillsCount: number | undefined;
187
- if (options?.skillCountLister) {
188
- skillsCount = options.skillCountLister(ctx.cwd);
189
- } else if (loader?.getSkills) {
190
- try {
191
- const skillsRes = loader.getSkills();
192
- if (skillsRes && Array.isArray(skillsRes.skills)) {
193
- skillsCount = skillsRes.skills.length;
194
- }
195
- } catch {
196
- // ignore
197
- }
198
- } else if (typeof pi.getCommands === 'function') {
199
- try {
200
- const commands = pi.getCommands();
201
- if (Array.isArray(commands)) {
202
- const skillCommands = commands.filter(
203
- (c) =>
204
- c?.source === 'skill' ||
205
- (typeof c?.name === 'string' && c.name.startsWith('skill:')),
206
- );
207
- skillsCount = skillCommands.length;
208
- }
209
- } catch {
210
- // ignore
211
- }
212
- }
213
-
214
- // 2. Loaded extensions: live public source from options or resourceLoader
215
- let extensionsCount: number | undefined;
216
- if (options?.extensionCountLister) {
217
- extensionsCount = options.extensionCountLister(ctx.cwd);
218
- } else if (loader?.getExtensions) {
219
- try {
220
- const extRes = loader.getExtensions();
221
- if (extRes && Array.isArray(extRes.extensions)) {
222
- extensionsCount = extRes.extensions.length;
223
- }
224
- } catch {
225
- // ignore
226
- }
227
- }
228
-
229
- let sessions: WelcomeSession[] = [];
230
- if (options?.sessionLister) {
231
- sessions = await options.sessionLister(ctx.cwd);
232
- } else {
233
- sessions = await fetchRecentSessions(ctx.cwd, 4, options?.iconMode);
234
- }
235
-
236
- const modelName = ctx.model?.name || ctx.model?.id;
237
- const provider = ctx.model?.provider;
238
-
239
- return {
240
- version: PI_VERSION,
241
- model: modelName,
242
- provider,
243
- resources: {
244
- tools: toolsCount,
245
- skills: skillsCount,
246
- extensions: extensionsCount,
247
- },
248
- providers,
249
- sessions,
250
- };
251
- }