@iseoane/agent-depot 0.5.2 → 0.6.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.
- package/CHANGELOG.md +47 -0
- package/README.es.md +137 -34
- package/README.md +120 -29
- package/dist/src/app-flow.js +56 -24
- package/dist/src/profile-export.js +72 -9
- package/dist/src/profile-import.js +3 -2
- package/dist/src/profile.js +71 -7
- package/dist/src/tui/app-actions.js +82 -33
- package/dist/src/tui/app.js +19 -14
- package/dist/src/tui/catalog-browse.js +6 -1
- package/dist/src/tui/catalog-panel.js +11 -11
- package/dist/src/tui/catalog-state.js +28 -0
- package/dist/src/tui/catalog-tree.js +22 -5
- package/dist/src/tui/catalog-view.js +59 -16
- package/dist/src/tui/file-picker-model.js +87 -0
- package/dist/src/tui/file-picker.js +142 -0
- package/dist/src/tui/header-layout.js +33 -0
- package/dist/src/tui/installations-panel.js +3 -3
- package/dist/src/tui/installations-rows.js +20 -5
- package/dist/src/tui/installations-tree.js +4 -7
- package/dist/src/tui/installations-view.js +15 -6
- package/dist/src/tui/installations.js +9 -7
- package/dist/src/tui/manage-panel.js +7 -6
- package/dist/src/tui/mode-keys.js +9 -0
- package/dist/src/tui/package-rows.js +17 -5
- package/dist/src/tui/panel-parts.js +119 -6
- package/dist/src/tui/preview-window.js +51 -0
- package/dist/src/tui/profile-view.js +394 -136
- package/dist/src/tui/sources-mode.js +3 -1
- package/dist/src/tui/sources-recipes.js +50 -19
- package/dist/src/tui/sources-view.js +50 -14
- package/dist/src/tui/text-wrap.js +53 -0
- package/dist/src/tui/theme.js +14 -7
- package/dist/src/tui/updates-flow.js +2 -2
- package/dist/src/tui/updates-keys.js +34 -5
- package/dist/src/tui/updates-model.js +2 -0
- package/dist/src/tui/updates-panel.js +40 -15
- package/dist/src/tui/updates-preview.js +65 -0
- package/dist/src/tui/updates-view.js +17 -2
- package/dist/src/tui/updates.js +14 -5
- package/dist/src/tui/window.js +8 -6
- package/package.json +6 -6
- package/skills/doctor-md-agents/README.md +3 -1
- package/skills/doctor-md-skill/README.md +2 -2
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Box, Text } from "ink";
|
|
2
|
+
import { Box, Text, useWindowSize } from "ink";
|
|
3
3
|
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
4
|
import { theme } from "./theme.js";
|
|
5
|
+
import { previewViewport } from "./preview-window.js";
|
|
5
6
|
import { computeWindow, useListHeight } from "./window.js";
|
|
6
7
|
import { BROWSE } from "./updates-mode.js";
|
|
7
8
|
import { useMirrored } from "./view-state.js";
|
|
@@ -9,12 +10,16 @@ import { useUpdatesFlow } from "./updates-flow.js";
|
|
|
9
10
|
import { handleUpdatesKey } from "./updates-keys.js";
|
|
10
11
|
import { viewOf } from "./updates-model.js";
|
|
11
12
|
import { CheckStatus, EntryLine, ModePanel, UpdatesFooter } from "./updates-panel.js";
|
|
13
|
+
import { previewLineText } from "./updates.js";
|
|
14
|
+
import { updateModePreviewChrome, updateModePreviewLines } from "./updates-preview.js";
|
|
12
15
|
import { useKeys } from "./keys.js";
|
|
16
|
+
import { BorderPanel, FieldLine } from "./panel-parts.js";
|
|
13
17
|
const NO_ENVIRONMENT = {};
|
|
14
18
|
/** How often the age of the check is redrawn. */
|
|
15
19
|
const CLOCK_TICK_MS = 10_000;
|
|
16
20
|
export function UpdatesView({ operations, environment, onCapturingChange, listHeight, now }) {
|
|
17
21
|
const height = useListHeight(listHeight, 9);
|
|
22
|
+
const { rows: terminalRows, columns: terminalColumns } = useWindowSize();
|
|
18
23
|
const env = environment ?? NO_ENVIRONMENT;
|
|
19
24
|
const clock = now ?? Date.now;
|
|
20
25
|
// Scope, cursor, fold and selection are mirrored in refs updated first, so keys delivered in one burst act on the latest state.
|
|
@@ -74,8 +79,17 @@ export function UpdatesView({ operations, environment, onCapturingChange, listHe
|
|
|
74
79
|
dataRef.current = data;
|
|
75
80
|
const { shown, updatable, unknown, upToDate, entries } = viewOf(data, scope, showUnknown);
|
|
76
81
|
const index = Math.min(cursor, Math.max(entries.length - 1, 0));
|
|
82
|
+
const previewGeometry = (current) => {
|
|
83
|
+
const cursor = "cursor" in current ? current.cursor : 0;
|
|
84
|
+
return previewViewport(updateModePreviewLines(current).map(previewLineText), cursor, terminalRows || 24, terminalColumns || 80, updateModePreviewChrome(current));
|
|
85
|
+
};
|
|
77
86
|
const keyContext = {
|
|
78
87
|
height,
|
|
88
|
+
previewMetrics: current => {
|
|
89
|
+
const geometry = previewGeometry(current);
|
|
90
|
+
return { length: geometry.total, pageSize: geometry.height };
|
|
91
|
+
},
|
|
92
|
+
previewAtEnd: current => previewGeometry(current).reachedEnd,
|
|
79
93
|
latest,
|
|
80
94
|
checked: () => checkedRef.current,
|
|
81
95
|
setChecked,
|
|
@@ -97,5 +111,6 @@ export function UpdatesView({ operations, environment, onCapturingChange, listHe
|
|
|
97
111
|
const window = computeWindow(entries.length, index, height);
|
|
98
112
|
const view = { shown, updatable, unknown, upToDate, entries };
|
|
99
113
|
const hasErrors = data?.appError !== undefined || (data?.results ?? []).some((result) => result.error !== undefined);
|
|
100
|
-
|
|
114
|
+
const showingBrowse = mode.kind === "browse";
|
|
115
|
+
return (_jsxs(Box, { flexDirection: "column", children: [showingBrowse ? _jsxs(Text, { color: theme.title, bold: true, children: ["Updates (scope: ", scope, ") t all \u00B7 p project \u00B7 g user-global \u00B7 u update"] }) : null, state.status === "loading" ? _jsx(BorderPanel, { title: "Update check", children: _jsx(FieldLine, { label: "Status", value: state.label }) }) : null, showingBrowse && data ? _jsx(CheckStatus, { data: data, now: clock() }) : null, showingBrowse && data && !hasErrors && shown.length === 0 ? _jsx(Text, { children: "No installations" }) : null, showingBrowse ? entries.slice(window.start, window.end).map((entry, offset) => (_jsx(EntryLine, { entry: entry, selected: window.start + offset === index, checked: entry.kind === "update" && checked.includes(entry.row.key), view: view, showUnknown: showUnknown }, entry.kind === "summary" ? "summary" : entry.row.key))) : null, showingBrowse ? _jsx(UpdatesFooter, { indicator: window.indicator, upToDate: upToDate, updatableCount: updatable.length, checkedCount: checked.length, message: message }) : null, _jsx(ModePanel, { mode: mode })] }));
|
|
101
116
|
}
|
package/dist/src/tui/updates.js
CHANGED
|
@@ -111,7 +111,7 @@ export async function loadUpdateRows(operations, environment, options) {
|
|
|
111
111
|
catch (error) {
|
|
112
112
|
appError = errorText(error);
|
|
113
113
|
}
|
|
114
|
-
for (const check of appChecks) {
|
|
114
|
+
for (const check of appChecks.filter(candidate => candidate.inspection.status === "installed")) {
|
|
115
115
|
rows.push({
|
|
116
116
|
kind: "app",
|
|
117
117
|
key: `app:${check.entry.file}`,
|
|
@@ -161,6 +161,12 @@ export function formatAgo(elapsedMs) {
|
|
|
161
161
|
return `${minutes} min ago`;
|
|
162
162
|
return `${Math.floor(minutes / 60)} h ago`;
|
|
163
163
|
}
|
|
164
|
+
export function previewText(text) {
|
|
165
|
+
return { kind: "text", text };
|
|
166
|
+
}
|
|
167
|
+
export function previewLineText(line) {
|
|
168
|
+
return line.kind === "field" ? `${line.label} ${line.value}` : line.text;
|
|
169
|
+
}
|
|
164
170
|
/** Plan step: previews the selection from the assessed snapshots, scope by scope. Changes nothing. */
|
|
165
171
|
export async function prepareUpdates(data, selected) {
|
|
166
172
|
const groups = [];
|
|
@@ -176,7 +182,7 @@ export async function prepareUpdates(data, selected) {
|
|
|
176
182
|
continue;
|
|
177
183
|
const { context } = loaded;
|
|
178
184
|
const outcome = await previewUpdateCandidates(items, context);
|
|
179
|
-
lines.push(...outcome.plans.flatMap((plan) => describeUpdatePreview(plan, scope, context.projectRoot, "prompt")));
|
|
185
|
+
lines.push(...outcome.plans.flatMap((plan) => describeUpdatePreview(plan, scope, context.projectRoot, "prompt").map(previewText)));
|
|
180
186
|
failures.push(...outcome.failures);
|
|
181
187
|
groups.push({
|
|
182
188
|
scope,
|
|
@@ -192,7 +198,10 @@ export async function prepareUpdates(data, selected) {
|
|
|
192
198
|
try {
|
|
193
199
|
const plan = await data.apps.planLifecycle(row.check.entry, "update", undefined, row.check);
|
|
194
200
|
appPlans.push(plan);
|
|
195
|
-
lines.push(
|
|
201
|
+
lines.push({ kind: "field", label: "Environment:", value: plan.environment }, previewText(row.path), { kind: "field", label: "Version:", value: `${plan.previousVersion} -> ${plan.latestVersion ?? "unknown"}` }, ...(plan.argv ? [
|
|
202
|
+
{ kind: "field", label: "argv:", value: JSON.stringify(plan.argv) },
|
|
203
|
+
{ kind: "field", label: "Executable:", value: plan.executable ?? `${JSON.stringify(plan.argv[0])} not found in PATH` },
|
|
204
|
+
] : []), ...(plan.manual ? [{ kind: "field", label: "Manual:", value: plan.manual }] : []), { kind: "field", label: "Working directory:", value: plan.cwd }, ...(plan.warning ? [previewText(plan.warning)] : []));
|
|
196
205
|
}
|
|
197
206
|
catch (error) {
|
|
198
207
|
appFailures.push(`Failed ${row.path}: preview failed: ${errorText(error)}`);
|
|
@@ -205,9 +214,9 @@ export async function prepareUpdates(data, selected) {
|
|
|
205
214
|
const plan = await data.packages.planLifecycle(row.check.installed.selection, "update");
|
|
206
215
|
const approval = await data.packages.approvalStatus(row.check.installed.selection, "update");
|
|
207
216
|
packagePlans.push({ plan, approval });
|
|
208
|
-
lines.push(...packagePlanLines(plan, approval));
|
|
217
|
+
lines.push(...packagePlanLines(plan, approval).map(previewText));
|
|
209
218
|
if (approval === "needs approval")
|
|
210
|
-
lines.push("This apply approves the declaration above.");
|
|
219
|
+
lines.push(previewText("This apply approves the declaration above."));
|
|
211
220
|
}
|
|
212
221
|
catch (error) {
|
|
213
222
|
packageFailures.push(`Failed ${row.path}: preview failed: ${errorText(error)}`);
|
package/dist/src/tui/window.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { useWindowSize } from "ink";
|
|
2
|
+
import { headerTabRowCount } from "./header-layout.js";
|
|
2
3
|
/** Rows assumed when the terminal size is unknown (for example under test renderers). */
|
|
3
4
|
export const FALLBACK_TERMINAL_ROWS = 24;
|
|
4
|
-
/**
|
|
5
|
-
export const APP_CHROME_ROWS =
|
|
6
|
-
const
|
|
5
|
+
/** Header borders, title, one tab row and footer; extra tab rows are added per terminal width. */
|
|
6
|
+
export const APP_CHROME_ROWS = 5;
|
|
7
|
+
const DEFAULT_MINIMUM_ROWS = 3;
|
|
7
8
|
/** The slice of a list that fits in `height` rows while keeping `selected` visible (roughly centred). */
|
|
8
9
|
export function computeWindow(total, selected, height) {
|
|
9
10
|
const size = Math.max(Math.floor(height), 1);
|
|
@@ -22,9 +23,10 @@ export function pageStep(height) {
|
|
|
22
23
|
* Rows available to a list: the terminal height minus the shell chrome and the
|
|
23
24
|
* view's own `reserved` lines. `override` fixes the height for tests.
|
|
24
25
|
*/
|
|
25
|
-
export function useListHeight(override, reserved) {
|
|
26
|
-
const { rows } = useWindowSize();
|
|
26
|
+
export function useListHeight(override, reserved, minimumRows = DEFAULT_MINIMUM_ROWS) {
|
|
27
|
+
const { rows, columns } = useWindowSize();
|
|
27
28
|
if (override !== undefined)
|
|
28
29
|
return Math.max(override, 1);
|
|
29
|
-
|
|
30
|
+
const chromeRows = APP_CHROME_ROWS + headerTabRowCount(Math.max(columns - 4, 1)) - 1;
|
|
31
|
+
return Math.max((rows || FALLBACK_TERMINAL_ROWS) - chromeRows - reserved, minimumRows);
|
|
30
32
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@iseoane/agent-depot",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "A cross-platform catalog for reusable coding-agent skills.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "iseoane",
|
|
@@ -28,8 +28,6 @@
|
|
|
28
28
|
"!dist/src/**/*.map",
|
|
29
29
|
"resources/pi",
|
|
30
30
|
"skills",
|
|
31
|
-
"!skills/**/test_*.py",
|
|
32
|
-
"!skills/**/testdata",
|
|
33
31
|
"README.md",
|
|
34
32
|
"README.es.md",
|
|
35
33
|
"LICENSE",
|
|
@@ -82,12 +80,14 @@
|
|
|
82
80
|
"audit:dupes": "npx --yes fallow@3.30.0 dupes",
|
|
83
81
|
"audit:health": "pnpm test:coverage && npx --yes fallow@3.30.0 health --coverage coverage/v8 --min-score 85",
|
|
84
82
|
"audit:all": "pnpm audit:dead-code && pnpm audit:dupes && pnpm audit:health",
|
|
85
|
-
"test:e2e": "pnpm build && node --test --test-timeout=120000 \"dist/tests/e2e/*.e2e.test.js\"",
|
|
83
|
+
"test:e2e": "pnpm build && node --import ./dist/tests/isolated-env.js --test --test-timeout=120000 \"dist/tests/e2e/*.e2e.test.js\"",
|
|
86
84
|
"prepublishOnly": "pnpm build && pnpm test",
|
|
87
|
-
"test:pack": "pnpm build && node scripts/pack-smoke.mjs"
|
|
85
|
+
"test:pack": "pnpm build && node scripts/pack-smoke.mjs",
|
|
86
|
+
"test:skills": "node scripts/test-skills.mjs"
|
|
88
87
|
},
|
|
89
88
|
"dependencies": {
|
|
90
89
|
"ink": "^7.1.1",
|
|
91
|
-
"react": "^19.3.0"
|
|
90
|
+
"react": "^19.3.0",
|
|
91
|
+
"string-width": "^8.3.0"
|
|
92
92
|
}
|
|
93
93
|
}
|
|
@@ -44,8 +44,10 @@ Cada cita del juez se verifica mecánicamente contra la transcripción por subca
|
|
|
44
44
|
|
|
45
45
|
## Tests
|
|
46
46
|
|
|
47
|
+
Desde la raíz del repositorio Agent Depot, ejecuta:
|
|
48
|
+
|
|
47
49
|
```bash
|
|
48
|
-
|
|
50
|
+
pnpm test:skills
|
|
49
51
|
```
|
|
50
52
|
|
|
51
53
|
Sin dependencias: stdlib de Python 3.9+.
|
|
@@ -20,8 +20,8 @@ ln -s /path/to/doctor-md-skill ~/.agents/skills/doctor-md-skill
|
|
|
20
20
|
|
|
21
21
|
## Run the tests
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
The tests use Python 3.9+ and the standard library. They need no network access. From the Agent Depot repository root, run:
|
|
24
24
|
|
|
25
25
|
```bash
|
|
26
|
-
|
|
26
|
+
pnpm test:skills
|
|
27
27
|
```
|