@skillkit/tui 1.3.0 → 1.4.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.
- package/README.md +161 -0
- package/dist/index.d.ts +61 -10
- package/dist/index.js +1023 -297
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { render } from "ink";
|
|
3
3
|
|
|
4
4
|
// src/App.tsx
|
|
5
|
-
import { useState as
|
|
6
|
-
import { Box as
|
|
5
|
+
import { useState as useState17 } from "react";
|
|
6
|
+
import { Box as Box15, Text as Text15, useInput as useInput13, useApp, useStdout } from "ink";
|
|
7
7
|
|
|
8
8
|
// src/components/Sidebar.tsx
|
|
9
9
|
import { Box, Text } from "ink";
|
|
@@ -27,7 +27,13 @@ var symbols = {
|
|
|
27
27
|
checkboxOff: chalk.dim("\u2716"),
|
|
28
28
|
check: chalk.white("\u2713"),
|
|
29
29
|
star: "\u2605",
|
|
30
|
-
spinner: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"]
|
|
30
|
+
spinner: ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"],
|
|
31
|
+
arrowUp: "\u2191",
|
|
32
|
+
arrowDown: "\u2193",
|
|
33
|
+
success: "\u2713",
|
|
34
|
+
error: "\u2717",
|
|
35
|
+
warning: "\u26A0",
|
|
36
|
+
info: "\u2139"
|
|
31
37
|
};
|
|
32
38
|
var logo = `
|
|
33
39
|
\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
|
|
@@ -41,14 +47,23 @@ var logo = `
|
|
|
41
47
|
// src/components/Sidebar.tsx
|
|
42
48
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
43
49
|
var NAV = [
|
|
44
|
-
|
|
45
|
-
{ id: "
|
|
46
|
-
{ id: "
|
|
47
|
-
{ id: "
|
|
48
|
-
|
|
49
|
-
{ id: "
|
|
50
|
-
{ id: "
|
|
51
|
-
{ id: "
|
|
50
|
+
// Discovery
|
|
51
|
+
{ id: "home", label: "Home", key: "h" },
|
|
52
|
+
{ id: "marketplace", label: "Marketplace", key: "m" },
|
|
53
|
+
{ id: "browse", label: "Browse", key: "b" },
|
|
54
|
+
// Execution
|
|
55
|
+
{ id: "workflow", label: "Workflows", key: "w" },
|
|
56
|
+
{ id: "execute", label: "Execute", key: "x" },
|
|
57
|
+
{ id: "history", label: "History", key: "y" },
|
|
58
|
+
// Tools
|
|
59
|
+
{ id: "recommend", label: "Recommend", key: "r" },
|
|
60
|
+
{ id: "translate", label: "Translate", key: "t" },
|
|
61
|
+
{ id: "context", label: "Context", key: "c" },
|
|
62
|
+
{ id: "memory", label: "Memory", key: "e" },
|
|
63
|
+
// Management
|
|
64
|
+
{ id: "installed", label: "Installed", key: "i" },
|
|
65
|
+
{ id: "sync", label: "Sync", key: "s" },
|
|
66
|
+
{ id: "settings", label: "Config", key: "," }
|
|
52
67
|
];
|
|
53
68
|
function Sidebar({ screen }) {
|
|
54
69
|
return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", width: 14, borderStyle: "single", paddingX: 1, children: [
|
|
@@ -58,12 +73,17 @@ function Sidebar({ screen }) {
|
|
|
58
73
|
item.label
|
|
59
74
|
] }, item.id)),
|
|
60
75
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
61
|
-
NAV.slice(3,
|
|
76
|
+
NAV.slice(3, 6).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
|
|
62
77
|
screen === item.id ? symbols.bullet : " ",
|
|
63
78
|
item.label
|
|
64
79
|
] }, item.id)),
|
|
65
80
|
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
66
|
-
NAV.slice(
|
|
81
|
+
NAV.slice(6, 10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
|
|
82
|
+
screen === item.id ? symbols.bullet : " ",
|
|
83
|
+
item.label
|
|
84
|
+
] }, item.id)),
|
|
85
|
+
/* @__PURE__ */ jsx(Text, { children: " " }),
|
|
86
|
+
NAV.slice(10).map((item) => /* @__PURE__ */ jsxs(Text, { inverse: screen === item.id, children: [
|
|
67
87
|
screen === item.id ? symbols.bullet : " ",
|
|
68
88
|
item.label
|
|
69
89
|
] }, item.id)),
|
|
@@ -722,174 +742,21 @@ function Settings({}) {
|
|
|
722
742
|
|
|
723
743
|
// src/screens/Recommend.tsx
|
|
724
744
|
import { useState as useState9 } from "react";
|
|
725
|
-
import { existsSync as
|
|
726
|
-
import { join as
|
|
745
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync2, cpSync as cpSync2, rmSync as rmSync2 } from "fs";
|
|
746
|
+
import { join as join3 } from "path";
|
|
727
747
|
import { Box as Box7, Text as Text7, useInput as useInput5 } from "ink";
|
|
728
748
|
|
|
729
749
|
// src/hooks/useRecommend.ts
|
|
730
750
|
import { useState as useState8, useCallback as useCallback2, useEffect as useEffect5 } from "react";
|
|
731
751
|
import {
|
|
732
752
|
RecommendationEngine,
|
|
733
|
-
ContextManager
|
|
753
|
+
ContextManager,
|
|
754
|
+
loadIndex as loadIndexFromCache,
|
|
755
|
+
saveIndex,
|
|
756
|
+
buildSkillIndex,
|
|
757
|
+
isIndexStale,
|
|
758
|
+
KNOWN_SKILL_REPOS
|
|
734
759
|
} from "@skillkit/core";
|
|
735
|
-
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
|
|
736
|
-
import { join as join3 } from "path";
|
|
737
|
-
var INDEX_PATH = join3(process.env.HOME || "~", ".skillkit", "index.json");
|
|
738
|
-
var INDEX_CACHE_HOURS = 24;
|
|
739
|
-
function getSampleSkills() {
|
|
740
|
-
return [
|
|
741
|
-
{
|
|
742
|
-
name: "vercel-react-best-practices",
|
|
743
|
-
description: "Modern React patterns including Server Components, hooks best practices, and performance optimization",
|
|
744
|
-
source: "vercel-labs/agent-skills",
|
|
745
|
-
tags: ["react", "frontend", "typescript", "nextjs", "performance"],
|
|
746
|
-
compatibility: {
|
|
747
|
-
frameworks: ["react", "nextjs"],
|
|
748
|
-
languages: ["typescript", "javascript"],
|
|
749
|
-
libraries: []
|
|
750
|
-
},
|
|
751
|
-
popularity: 1500,
|
|
752
|
-
quality: 95,
|
|
753
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
754
|
-
verified: true
|
|
755
|
-
},
|
|
756
|
-
{
|
|
757
|
-
name: "tailwind-v4-patterns",
|
|
758
|
-
description: "Tailwind CSS v4 utility patterns, responsive design, and component styling best practices",
|
|
759
|
-
source: "vercel-labs/agent-skills",
|
|
760
|
-
tags: ["tailwind", "css", "styling", "frontend", "responsive"],
|
|
761
|
-
compatibility: {
|
|
762
|
-
frameworks: [],
|
|
763
|
-
languages: ["typescript", "javascript"],
|
|
764
|
-
libraries: ["tailwindcss"]
|
|
765
|
-
},
|
|
766
|
-
popularity: 1200,
|
|
767
|
-
quality: 92,
|
|
768
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
769
|
-
verified: true
|
|
770
|
-
},
|
|
771
|
-
{
|
|
772
|
-
name: "nextjs-app-router",
|
|
773
|
-
description: "Next.js App Router patterns including layouts, server actions, and data fetching",
|
|
774
|
-
source: "vercel-labs/agent-skills",
|
|
775
|
-
tags: ["nextjs", "react", "routing", "server-actions", "frontend"],
|
|
776
|
-
compatibility: {
|
|
777
|
-
frameworks: ["nextjs"],
|
|
778
|
-
languages: ["typescript", "javascript"],
|
|
779
|
-
libraries: []
|
|
780
|
-
},
|
|
781
|
-
popularity: 1100,
|
|
782
|
-
quality: 94,
|
|
783
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
784
|
-
verified: true
|
|
785
|
-
},
|
|
786
|
-
{
|
|
787
|
-
name: "typescript-strict-patterns",
|
|
788
|
-
description: "TypeScript strict mode patterns, type safety, and advanced type utilities",
|
|
789
|
-
source: "anthropics/skills",
|
|
790
|
-
tags: ["typescript", "types", "safety", "patterns"],
|
|
791
|
-
compatibility: {
|
|
792
|
-
frameworks: [],
|
|
793
|
-
languages: ["typescript"],
|
|
794
|
-
libraries: []
|
|
795
|
-
},
|
|
796
|
-
popularity: 900,
|
|
797
|
-
quality: 90,
|
|
798
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
799
|
-
verified: true
|
|
800
|
-
},
|
|
801
|
-
{
|
|
802
|
-
name: "supabase-best-practices",
|
|
803
|
-
description: "Supabase integration patterns including auth, database queries, and real-time subscriptions",
|
|
804
|
-
source: "anthropics/skills",
|
|
805
|
-
tags: ["supabase", "database", "auth", "backend", "postgresql"],
|
|
806
|
-
compatibility: {
|
|
807
|
-
frameworks: [],
|
|
808
|
-
languages: ["typescript", "javascript"],
|
|
809
|
-
libraries: ["@supabase/supabase-js"]
|
|
810
|
-
},
|
|
811
|
-
popularity: 800,
|
|
812
|
-
quality: 88,
|
|
813
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
814
|
-
verified: true
|
|
815
|
-
},
|
|
816
|
-
{
|
|
817
|
-
name: "vitest-testing-patterns",
|
|
818
|
-
description: "Testing patterns with Vitest including mocking, assertions, and test organization",
|
|
819
|
-
source: "anthropics/skills",
|
|
820
|
-
tags: ["vitest", "testing", "typescript", "mocking", "tdd"],
|
|
821
|
-
compatibility: {
|
|
822
|
-
frameworks: [],
|
|
823
|
-
languages: ["typescript", "javascript"],
|
|
824
|
-
libraries: ["vitest"]
|
|
825
|
-
},
|
|
826
|
-
popularity: 700,
|
|
827
|
-
quality: 86,
|
|
828
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
829
|
-
verified: false
|
|
830
|
-
},
|
|
831
|
-
{
|
|
832
|
-
name: "prisma-database-patterns",
|
|
833
|
-
description: "Prisma ORM patterns for schema design, migrations, and efficient queries",
|
|
834
|
-
source: "vercel-labs/agent-skills",
|
|
835
|
-
tags: ["prisma", "database", "orm", "postgresql", "backend"],
|
|
836
|
-
compatibility: {
|
|
837
|
-
frameworks: [],
|
|
838
|
-
languages: ["typescript"],
|
|
839
|
-
libraries: ["@prisma/client"]
|
|
840
|
-
},
|
|
841
|
-
popularity: 850,
|
|
842
|
-
quality: 89,
|
|
843
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
844
|
-
verified: true
|
|
845
|
-
},
|
|
846
|
-
{
|
|
847
|
-
name: "security-best-practices",
|
|
848
|
-
description: "Security patterns for web applications including XSS prevention, CSRF, and secure headers",
|
|
849
|
-
source: "trailofbits/skills",
|
|
850
|
-
tags: ["security", "xss", "csrf", "headers", "owasp"],
|
|
851
|
-
compatibility: {
|
|
852
|
-
frameworks: [],
|
|
853
|
-
languages: ["typescript", "javascript", "python"],
|
|
854
|
-
libraries: []
|
|
855
|
-
},
|
|
856
|
-
popularity: 600,
|
|
857
|
-
quality: 95,
|
|
858
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
859
|
-
verified: true
|
|
860
|
-
},
|
|
861
|
-
{
|
|
862
|
-
name: "python-fastapi-patterns",
|
|
863
|
-
description: "FastAPI best practices for building high-performance Python APIs",
|
|
864
|
-
source: "python-skills/fastapi",
|
|
865
|
-
tags: ["python", "fastapi", "backend", "api", "async"],
|
|
866
|
-
compatibility: {
|
|
867
|
-
frameworks: ["fastapi"],
|
|
868
|
-
languages: ["python"],
|
|
869
|
-
libraries: []
|
|
870
|
-
},
|
|
871
|
-
popularity: 550,
|
|
872
|
-
quality: 85,
|
|
873
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
874
|
-
verified: false
|
|
875
|
-
},
|
|
876
|
-
{
|
|
877
|
-
name: "zustand-state-management",
|
|
878
|
-
description: "Zustand state management patterns for React applications",
|
|
879
|
-
source: "react-skills/state",
|
|
880
|
-
tags: ["zustand", "react", "state-management", "frontend"],
|
|
881
|
-
compatibility: {
|
|
882
|
-
frameworks: ["react"],
|
|
883
|
-
languages: ["typescript", "javascript"],
|
|
884
|
-
libraries: ["zustand"]
|
|
885
|
-
},
|
|
886
|
-
popularity: 650,
|
|
887
|
-
quality: 84,
|
|
888
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
889
|
-
verified: false
|
|
890
|
-
}
|
|
891
|
-
];
|
|
892
|
-
}
|
|
893
760
|
function useRecommend(projectPath = process.cwd()) {
|
|
894
761
|
const [recommendations, setRecommendations] = useState8([]);
|
|
895
762
|
const [searchResults, setSearchResults] = useState8([]);
|
|
@@ -900,25 +767,17 @@ function useRecommend(projectPath = process.cwd()) {
|
|
|
900
767
|
const [indexStatus, setIndexStatus] = useState8("missing");
|
|
901
768
|
const [engine] = useState8(() => new RecommendationEngine());
|
|
902
769
|
const loadIndex = useCallback2(() => {
|
|
903
|
-
|
|
770
|
+
const index = loadIndexFromCache();
|
|
771
|
+
if (!index) {
|
|
904
772
|
setIndexStatus("missing");
|
|
905
773
|
return null;
|
|
906
774
|
}
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
const hoursSinceUpdate = (Date.now() - lastUpdated.getTime()) / (1e3 * 60 * 60);
|
|
912
|
-
if (hoursSinceUpdate > INDEX_CACHE_HOURS) {
|
|
913
|
-
setIndexStatus("stale");
|
|
914
|
-
} else {
|
|
915
|
-
setIndexStatus("fresh");
|
|
916
|
-
}
|
|
917
|
-
return index;
|
|
918
|
-
} catch {
|
|
919
|
-
setIndexStatus("missing");
|
|
920
|
-
return null;
|
|
775
|
+
if (isIndexStale(index)) {
|
|
776
|
+
setIndexStatus("stale");
|
|
777
|
+
} else {
|
|
778
|
+
setIndexStatus("fresh");
|
|
921
779
|
}
|
|
780
|
+
return index;
|
|
922
781
|
}, []);
|
|
923
782
|
const getProjectProfile = useCallback2(() => {
|
|
924
783
|
try {
|
|
@@ -978,37 +837,17 @@ function useRecommend(projectPath = process.cwd()) {
|
|
|
978
837
|
const updateIndex = useCallback2(() => {
|
|
979
838
|
setLoading(true);
|
|
980
839
|
setError(null);
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
985
|
-
skills: getSampleSkills(),
|
|
986
|
-
sources: [
|
|
987
|
-
{
|
|
988
|
-
name: "vercel-labs",
|
|
989
|
-
url: "https://github.com/vercel-labs/agent-skills",
|
|
990
|
-
lastFetched: (/* @__PURE__ */ new Date()).toISOString(),
|
|
991
|
-
skillCount: 5
|
|
992
|
-
},
|
|
993
|
-
{
|
|
994
|
-
name: "anthropics",
|
|
995
|
-
url: "https://github.com/anthropics/skills",
|
|
996
|
-
lastFetched: (/* @__PURE__ */ new Date()).toISOString(),
|
|
997
|
-
skillCount: 3
|
|
998
|
-
}
|
|
999
|
-
]
|
|
1000
|
-
};
|
|
1001
|
-
const indexDir = join3(process.env.HOME || "~", ".skillkit");
|
|
1002
|
-
if (!existsSync2(indexDir)) {
|
|
1003
|
-
mkdirSync2(indexDir, { recursive: true });
|
|
840
|
+
buildSkillIndex(KNOWN_SKILL_REPOS).then(({ index, errors }) => {
|
|
841
|
+
if (errors.length > 0) {
|
|
842
|
+
console.warn("Index update warnings:", errors);
|
|
1004
843
|
}
|
|
1005
|
-
|
|
844
|
+
saveIndex(index);
|
|
1006
845
|
setIndexStatus("fresh");
|
|
1007
846
|
loadRecommendations();
|
|
1008
|
-
}
|
|
847
|
+
}).catch((err) => {
|
|
1009
848
|
setError(err instanceof Error ? err.message : "Failed to update index");
|
|
1010
849
|
setLoading(false);
|
|
1011
|
-
}
|
|
850
|
+
});
|
|
1012
851
|
}, [loadRecommendations]);
|
|
1013
852
|
const search = useCallback2((query) => {
|
|
1014
853
|
if (!query.trim()) {
|
|
@@ -1126,11 +965,11 @@ function Recommend({ rows = 24 }) {
|
|
|
1126
965
|
const targetAgentType = agentType || await detectAgent2();
|
|
1127
966
|
const adapter = getAdapter3(targetAgentType);
|
|
1128
967
|
const installDir = getInstallDir(false, targetAgentType);
|
|
1129
|
-
if (!
|
|
1130
|
-
|
|
968
|
+
if (!existsSync2(installDir)) {
|
|
969
|
+
mkdirSync2(installDir, { recursive: true });
|
|
1131
970
|
}
|
|
1132
|
-
const targetPath =
|
|
1133
|
-
if (
|
|
971
|
+
const targetPath = join3(installDir, skillName);
|
|
972
|
+
if (existsSync2(targetPath)) {
|
|
1134
973
|
rmSync2(targetPath, { recursive: true, force: true });
|
|
1135
974
|
}
|
|
1136
975
|
cpSync2(skill.path, targetPath, { recursive: true, dereference: true });
|
|
@@ -1334,8 +1173,8 @@ function Recommend({ rows = 24 }) {
|
|
|
1334
1173
|
|
|
1335
1174
|
// src/screens/Translate.tsx
|
|
1336
1175
|
import { useState as useState10, useEffect as useEffect6 } from "react";
|
|
1337
|
-
import { existsSync as
|
|
1338
|
-
import { join as
|
|
1176
|
+
import { existsSync as existsSync3, readdirSync, readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
1177
|
+
import { join as join4 } from "path";
|
|
1339
1178
|
import { Box as Box8, Text as Text8, useInput as useInput6 } from "ink";
|
|
1340
1179
|
import {
|
|
1341
1180
|
translateSkill,
|
|
@@ -1357,13 +1196,13 @@ function Translate({ rows = 24 }) {
|
|
|
1357
1196
|
const loadSkills = () => {
|
|
1358
1197
|
const installDir = getInstallDir(false);
|
|
1359
1198
|
const foundSkills = [];
|
|
1360
|
-
if (
|
|
1199
|
+
if (existsSync3(installDir)) {
|
|
1361
1200
|
const dirs = readdirSync(installDir, { withFileTypes: true }).filter((d) => d.isDirectory()).map((d) => d.name);
|
|
1362
1201
|
for (const dir of dirs) {
|
|
1363
|
-
const skillPath =
|
|
1364
|
-
const skillMdPath =
|
|
1365
|
-
if (
|
|
1366
|
-
const content =
|
|
1202
|
+
const skillPath = join4(installDir, dir);
|
|
1203
|
+
const skillMdPath = join4(skillPath, "SKILL.md");
|
|
1204
|
+
if (existsSync3(skillMdPath)) {
|
|
1205
|
+
const content = readFileSync2(skillMdPath, "utf-8");
|
|
1367
1206
|
foundSkills.push({
|
|
1368
1207
|
name: dir,
|
|
1369
1208
|
path: skillPath,
|
|
@@ -1413,13 +1252,13 @@ function Translate({ rows = 24 }) {
|
|
|
1413
1252
|
return;
|
|
1414
1253
|
}
|
|
1415
1254
|
const adapter = getAdapter4(selectedAgent.type);
|
|
1416
|
-
const targetDir = adapter?.skillsDir ?
|
|
1417
|
-
if (!
|
|
1418
|
-
|
|
1255
|
+
const targetDir = adapter?.skillsDir ? join4(process.cwd(), adapter.skillsDir) : join4(process.cwd(), `.${selectedAgent.type}/skills/`);
|
|
1256
|
+
if (!existsSync3(targetDir)) {
|
|
1257
|
+
mkdirSync3(targetDir, { recursive: true });
|
|
1419
1258
|
}
|
|
1420
1259
|
const filename = translationResult.filename || `${selectedSkill.name}.md`;
|
|
1421
|
-
const targetPath =
|
|
1422
|
-
|
|
1260
|
+
const targetPath = join4(targetDir, filename);
|
|
1261
|
+
writeFileSync(targetPath, translationResult.content, "utf-8");
|
|
1423
1262
|
setResult({
|
|
1424
1263
|
success: true,
|
|
1425
1264
|
message: `Translated ${selectedSkill.name} to ${selectedAgent.name} format`,
|
|
@@ -1812,16 +1651,780 @@ function Context({ rows = 24 }) {
|
|
|
1812
1651
|
] });
|
|
1813
1652
|
}
|
|
1814
1653
|
|
|
1815
|
-
// src/
|
|
1654
|
+
// src/screens/Workflow.tsx
|
|
1655
|
+
import { useState as useState12, useEffect as useEffect8 } from "react";
|
|
1656
|
+
import { Box as Box10, Text as Text10, useInput as useInput8 } from "ink";
|
|
1657
|
+
import { listWorkflows } from "@skillkit/core";
|
|
1816
1658
|
import { jsx as jsx10, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1659
|
+
function Workflow({ rows = 24 }) {
|
|
1660
|
+
const [workflows, setWorkflows] = useState12([]);
|
|
1661
|
+
const [loading, setLoading] = useState12(true);
|
|
1662
|
+
const [sel, setSel] = useState12(0);
|
|
1663
|
+
const [running, setRunning] = useState12(null);
|
|
1664
|
+
const [error, setError] = useState12(null);
|
|
1665
|
+
const maxVisible = Math.max(5, rows - 8);
|
|
1666
|
+
const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), workflows.length - maxVisible));
|
|
1667
|
+
const visible = workflows.slice(start, start + maxVisible);
|
|
1668
|
+
useEffect8(() => {
|
|
1669
|
+
loadWorkflows();
|
|
1670
|
+
}, []);
|
|
1671
|
+
const loadWorkflows = () => {
|
|
1672
|
+
setLoading(true);
|
|
1673
|
+
setError(null);
|
|
1674
|
+
try {
|
|
1675
|
+
const wfs = listWorkflows(process.cwd());
|
|
1676
|
+
setWorkflows(wfs);
|
|
1677
|
+
} catch (e) {
|
|
1678
|
+
setError(e instanceof Error ? e.message : "Failed to load workflows");
|
|
1679
|
+
}
|
|
1680
|
+
setLoading(false);
|
|
1681
|
+
};
|
|
1682
|
+
useInput8((input, key) => {
|
|
1683
|
+
if (loading || running) return;
|
|
1684
|
+
if (key.upArrow) setSel((i) => Math.max(0, i - 1));
|
|
1685
|
+
else if (key.downArrow) setSel((i) => Math.min(workflows.length - 1, i + 1));
|
|
1686
|
+
else if (input === "r") loadWorkflows();
|
|
1687
|
+
else if (key.return && workflows[sel]) {
|
|
1688
|
+
setRunning(workflows[sel].name);
|
|
1689
|
+
setTimeout(() => setRunning(null), 2e3);
|
|
1690
|
+
}
|
|
1691
|
+
});
|
|
1692
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
1693
|
+
/* @__PURE__ */ jsx10(Text10, { bold: true, color: colors.primary, children: "WORKFLOWS" }),
|
|
1694
|
+
/* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
1695
|
+
workflows.length,
|
|
1696
|
+
" workflow(s) found"
|
|
1697
|
+
] }),
|
|
1698
|
+
loading && /* @__PURE__ */ jsx10(Text10, { children: "Loading workflows..." }),
|
|
1699
|
+
error && /* @__PURE__ */ jsx10(Text10, { color: "red", children: error }),
|
|
1700
|
+
running && /* @__PURE__ */ jsxs10(Text10, { color: "yellow", children: [
|
|
1701
|
+
"Running: ",
|
|
1702
|
+
running,
|
|
1703
|
+
"..."
|
|
1704
|
+
] }),
|
|
1705
|
+
!loading && !running && workflows.length === 0 && /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
1706
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "No workflows found." }),
|
|
1707
|
+
/* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "Create one with: skillkit workflow create" })
|
|
1708
|
+
] }),
|
|
1709
|
+
!loading && !running && workflows.length > 0 && /* @__PURE__ */ jsxs10(Box10, { marginTop: 1, flexDirection: "column", children: [
|
|
1710
|
+
start > 0 && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
1711
|
+
" \u2191 ",
|
|
1712
|
+
start,
|
|
1713
|
+
" more"
|
|
1714
|
+
] }),
|
|
1715
|
+
visible.map((wf, i) => {
|
|
1716
|
+
const idx = start + i;
|
|
1717
|
+
const isSel = idx === sel;
|
|
1718
|
+
return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
|
|
1719
|
+
/* @__PURE__ */ jsxs10(Text10, { inverse: isSel, children: [
|
|
1720
|
+
isSel ? symbols.pointer : " ",
|
|
1721
|
+
" ",
|
|
1722
|
+
wf.name
|
|
1723
|
+
] }),
|
|
1724
|
+
isSel && wf.description && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
1725
|
+
" ",
|
|
1726
|
+
wf.description
|
|
1727
|
+
] }),
|
|
1728
|
+
isSel && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
1729
|
+
" ",
|
|
1730
|
+
wf.waves.length,
|
|
1731
|
+
" wave(s), ",
|
|
1732
|
+
wf.waves.reduce((acc, w) => acc + w.skills.length, 0),
|
|
1733
|
+
" skill(s)"
|
|
1734
|
+
] })
|
|
1735
|
+
] }, wf.name);
|
|
1736
|
+
}),
|
|
1737
|
+
start + maxVisible < workflows.length && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
|
|
1738
|
+
" \u2193 ",
|
|
1739
|
+
workflows.length - start - maxVisible,
|
|
1740
|
+
" more"
|
|
1741
|
+
] })
|
|
1742
|
+
] }),
|
|
1743
|
+
/* @__PURE__ */ jsx10(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx10(Text10, { dimColor: true, children: "Enter=run r=refresh q=quit" }) })
|
|
1744
|
+
] });
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
// src/screens/Execute.tsx
|
|
1748
|
+
import { useState as useState13, useEffect as useEffect9 } from "react";
|
|
1749
|
+
import { Box as Box11, Text as Text11, useInput as useInput9 } from "ink";
|
|
1750
|
+
import { createSessionManager } from "@skillkit/core";
|
|
1751
|
+
import { jsx as jsx11, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1752
|
+
function Execute({ rows = 24 }) {
|
|
1753
|
+
const [session, setSession] = useState13(null);
|
|
1754
|
+
const [loading, setLoading] = useState13(true);
|
|
1755
|
+
const maxVisible = Math.max(5, rows - 10);
|
|
1756
|
+
useEffect9(() => {
|
|
1757
|
+
loadSession();
|
|
1758
|
+
const interval = setInterval(loadSession, 1e3);
|
|
1759
|
+
return () => clearInterval(interval);
|
|
1760
|
+
}, []);
|
|
1761
|
+
const loadSession = () => {
|
|
1762
|
+
try {
|
|
1763
|
+
const manager = createSessionManager(process.cwd());
|
|
1764
|
+
const state = manager.get();
|
|
1765
|
+
setSession(state);
|
|
1766
|
+
} catch {
|
|
1767
|
+
setSession(null);
|
|
1768
|
+
}
|
|
1769
|
+
setLoading(false);
|
|
1770
|
+
};
|
|
1771
|
+
useInput9((input, _key) => {
|
|
1772
|
+
if (input === "r") loadSession();
|
|
1773
|
+
else if (input === "p" && session?.currentExecution?.status === "running") {
|
|
1774
|
+
const manager = createSessionManager(process.cwd());
|
|
1775
|
+
manager.pause();
|
|
1776
|
+
loadSession();
|
|
1777
|
+
} else if (input === "c" && session?.currentExecution?.status === "paused") {
|
|
1778
|
+
const manager = createSessionManager(process.cwd());
|
|
1779
|
+
manager.resume();
|
|
1780
|
+
loadSession();
|
|
1781
|
+
}
|
|
1782
|
+
});
|
|
1783
|
+
const renderExecution = (exec) => {
|
|
1784
|
+
const completedTasks = exec.tasks.filter((t) => t.status === "completed").length;
|
|
1785
|
+
const failedTasks = exec.tasks.filter((t) => t.status === "failed").length;
|
|
1786
|
+
const progress = exec.totalSteps > 0 ? Math.round(completedTasks / exec.totalSteps * 100) : 0;
|
|
1787
|
+
const statusColor = exec.status === "running" ? "yellow" : exec.status === "completed" ? "green" : exec.status === "paused" ? "blue" : exec.status === "failed" ? "red" : "white";
|
|
1788
|
+
const visibleTasks = exec.tasks.slice(0, maxVisible);
|
|
1789
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", marginTop: 1, children: [
|
|
1790
|
+
/* @__PURE__ */ jsx11(Text11, { bold: true, children: exec.skillName }),
|
|
1791
|
+
/* @__PURE__ */ jsxs11(Text11, { children: [
|
|
1792
|
+
"Source: ",
|
|
1793
|
+
/* @__PURE__ */ jsx11(Text11, { dimColor: true, children: exec.skillSource })
|
|
1794
|
+
] }),
|
|
1795
|
+
/* @__PURE__ */ jsxs11(Text11, { children: [
|
|
1796
|
+
"Status: ",
|
|
1797
|
+
/* @__PURE__ */ jsx11(Text11, { color: statusColor, children: exec.status.toUpperCase() })
|
|
1798
|
+
] }),
|
|
1799
|
+
/* @__PURE__ */ jsxs11(Text11, { children: [
|
|
1800
|
+
"Progress: ",
|
|
1801
|
+
completedTasks,
|
|
1802
|
+
"/",
|
|
1803
|
+
exec.totalSteps,
|
|
1804
|
+
" (",
|
|
1805
|
+
progress,
|
|
1806
|
+
"%)"
|
|
1807
|
+
] }),
|
|
1808
|
+
/* @__PURE__ */ jsxs11(Box11, { marginY: 1, children: [
|
|
1809
|
+
/* @__PURE__ */ jsx11(Text11, { children: "[" }),
|
|
1810
|
+
/* @__PURE__ */ jsx11(Text11, { color: "green", children: "\u2588".repeat(Math.floor(progress / 5)) }),
|
|
1811
|
+
/* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "\u2591".repeat(20 - Math.floor(progress / 5)) }),
|
|
1812
|
+
/* @__PURE__ */ jsx11(Text11, { children: "]" })
|
|
1813
|
+
] }),
|
|
1814
|
+
/* @__PURE__ */ jsx11(Text11, { bold: true, children: "Tasks:" }),
|
|
1815
|
+
visibleTasks.map((task, i) => {
|
|
1816
|
+
const icon = task.status === "completed" ? symbols.success : task.status === "failed" ? symbols.error : task.status === "in_progress" ? symbols.warning : task.status === "paused" ? symbols.info : symbols.bullet;
|
|
1817
|
+
const color = task.status === "completed" ? "green" : task.status === "failed" ? "red" : task.status === "in_progress" ? "yellow" : task.status === "paused" ? "blue" : "white";
|
|
1818
|
+
return /* @__PURE__ */ jsxs11(Text11, { color, children: [
|
|
1819
|
+
icon,
|
|
1820
|
+
" ",
|
|
1821
|
+
task.name,
|
|
1822
|
+
" ",
|
|
1823
|
+
task.error && /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
1824
|
+
"(",
|
|
1825
|
+
task.error,
|
|
1826
|
+
")"
|
|
1827
|
+
] })
|
|
1828
|
+
] }, task.id || i);
|
|
1829
|
+
}),
|
|
1830
|
+
exec.tasks.length > maxVisible && /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
1831
|
+
" ... and ",
|
|
1832
|
+
exec.tasks.length - maxVisible,
|
|
1833
|
+
" more"
|
|
1834
|
+
] }),
|
|
1835
|
+
failedTasks > 0 && /* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsxs11(Text11, { color: "red", children: [
|
|
1836
|
+
failedTasks,
|
|
1837
|
+
" task(s) failed"
|
|
1838
|
+
] }) })
|
|
1839
|
+
] });
|
|
1840
|
+
};
|
|
1841
|
+
return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
|
|
1842
|
+
/* @__PURE__ */ jsx11(Text11, { bold: true, color: colors.primary, children: "EXECUTION MONITOR" }),
|
|
1843
|
+
loading && /* @__PURE__ */ jsx11(Text11, { children: "Loading session..." }),
|
|
1844
|
+
!loading && !session?.currentExecution && /* @__PURE__ */ jsxs11(Box11, { marginTop: 1, flexDirection: "column", children: [
|
|
1845
|
+
/* @__PURE__ */ jsx11(Text11, { dimColor: true, children: "No active execution." }),
|
|
1846
|
+
/* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
1847
|
+
"Run a skill with: skillkit run ",
|
|
1848
|
+
"<skill>"
|
|
1849
|
+
] })
|
|
1850
|
+
] }),
|
|
1851
|
+
!loading && session?.currentExecution && renderExecution(session.currentExecution),
|
|
1852
|
+
/* @__PURE__ */ jsx11(Box11, { marginTop: 1, children: /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
|
|
1853
|
+
session?.currentExecution?.status === "running" ? "p=pause " : "",
|
|
1854
|
+
session?.currentExecution?.status === "paused" ? "c=continue " : "",
|
|
1855
|
+
"r=refresh q=quit"
|
|
1856
|
+
] }) })
|
|
1857
|
+
] });
|
|
1858
|
+
}
|
|
1859
|
+
|
|
1860
|
+
// src/screens/History.tsx
|
|
1861
|
+
import { useState as useState14, useEffect as useEffect10 } from "react";
|
|
1862
|
+
import { Box as Box12, Text as Text12, useInput as useInput10 } from "ink";
|
|
1863
|
+
import { createSessionManager as createSessionManager2 } from "@skillkit/core";
|
|
1864
|
+
import { jsx as jsx12, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1865
|
+
function History({ rows = 24 }) {
|
|
1866
|
+
const [history, setHistory] = useState14([]);
|
|
1867
|
+
const [loading, setLoading] = useState14(true);
|
|
1868
|
+
const [sel, setSel] = useState14(0);
|
|
1869
|
+
const [expanded, setExpanded] = useState14(false);
|
|
1870
|
+
const maxVisible = Math.max(5, rows - 8);
|
|
1871
|
+
const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), history.length - maxVisible));
|
|
1872
|
+
const visible = history.slice(start, start + maxVisible);
|
|
1873
|
+
useEffect10(() => {
|
|
1874
|
+
loadHistory();
|
|
1875
|
+
}, []);
|
|
1876
|
+
const loadHistory = () => {
|
|
1877
|
+
setLoading(true);
|
|
1878
|
+
try {
|
|
1879
|
+
const manager = createSessionManager2(process.cwd());
|
|
1880
|
+
const h = manager.getHistory(50);
|
|
1881
|
+
setHistory(h);
|
|
1882
|
+
} catch {
|
|
1883
|
+
setHistory([]);
|
|
1884
|
+
}
|
|
1885
|
+
setLoading(false);
|
|
1886
|
+
};
|
|
1887
|
+
useInput10((input, key) => {
|
|
1888
|
+
if (loading) return;
|
|
1889
|
+
if (key.upArrow) {
|
|
1890
|
+
setSel((i) => Math.max(0, i - 1));
|
|
1891
|
+
setExpanded(false);
|
|
1892
|
+
} else if (key.downArrow) {
|
|
1893
|
+
setSel((i) => Math.min(history.length - 1, i + 1));
|
|
1894
|
+
setExpanded(false);
|
|
1895
|
+
} else if (input === "r") loadHistory();
|
|
1896
|
+
else if (key.return) setExpanded((e) => !e);
|
|
1897
|
+
});
|
|
1898
|
+
const formatDuration = (ms) => {
|
|
1899
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
1900
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
1901
|
+
return `${(ms / 6e4).toFixed(1)}m`;
|
|
1902
|
+
};
|
|
1903
|
+
const formatDate = (iso) => {
|
|
1904
|
+
const d = new Date(iso);
|
|
1905
|
+
const now = /* @__PURE__ */ new Date();
|
|
1906
|
+
const diff = now.getTime() - d.getTime();
|
|
1907
|
+
if (diff < 6e4) return "Just now";
|
|
1908
|
+
if (diff < 36e5) return `${Math.floor(diff / 6e4)}m ago`;
|
|
1909
|
+
if (diff < 864e5) return `${Math.floor(diff / 36e5)}h ago`;
|
|
1910
|
+
return d.toLocaleDateString();
|
|
1911
|
+
};
|
|
1912
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
1913
|
+
/* @__PURE__ */ jsx12(Text12, { bold: true, color: colors.primary, children: "EXECUTION HISTORY" }),
|
|
1914
|
+
/* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1915
|
+
history.length,
|
|
1916
|
+
" execution(s)"
|
|
1917
|
+
] }),
|
|
1918
|
+
loading && /* @__PURE__ */ jsx12(Text12, { children: "Loading history..." }),
|
|
1919
|
+
!loading && history.length === 0 && /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
|
|
1920
|
+
/* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "No execution history." }),
|
|
1921
|
+
/* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1922
|
+
"Run a skill with: skillkit run ",
|
|
1923
|
+
"<skill>"
|
|
1924
|
+
] })
|
|
1925
|
+
] }),
|
|
1926
|
+
!loading && history.length > 0 && /* @__PURE__ */ jsxs12(Box12, { marginTop: 1, flexDirection: "column", children: [
|
|
1927
|
+
start > 0 && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1928
|
+
" \u2191 ",
|
|
1929
|
+
start,
|
|
1930
|
+
" more"
|
|
1931
|
+
] }),
|
|
1932
|
+
visible.map((entry, i) => {
|
|
1933
|
+
const idx = start + i;
|
|
1934
|
+
const isSel = idx === sel;
|
|
1935
|
+
const icon = entry.status === "completed" ? symbols.success : entry.status === "failed" ? symbols.error : symbols.warning;
|
|
1936
|
+
const color = entry.status === "completed" ? "green" : entry.status === "failed" ? "red" : "yellow";
|
|
1937
|
+
return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
|
|
1938
|
+
/* @__PURE__ */ jsxs12(Text12, { inverse: isSel, children: [
|
|
1939
|
+
isSel ? symbols.pointer : " ",
|
|
1940
|
+
/* @__PURE__ */ jsx12(Text12, { color, children: icon }),
|
|
1941
|
+
" ",
|
|
1942
|
+
entry.skillName.padEnd(25),
|
|
1943
|
+
" ",
|
|
1944
|
+
formatDate(entry.completedAt).padEnd(12),
|
|
1945
|
+
" ",
|
|
1946
|
+
formatDuration(entry.durationMs)
|
|
1947
|
+
] }),
|
|
1948
|
+
isSel && expanded && /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", marginLeft: 3, children: [
|
|
1949
|
+
/* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1950
|
+
"Source: ",
|
|
1951
|
+
entry.skillSource
|
|
1952
|
+
] }),
|
|
1953
|
+
/* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1954
|
+
"Status: ",
|
|
1955
|
+
entry.status
|
|
1956
|
+
] }),
|
|
1957
|
+
entry.commits.length > 0 && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1958
|
+
"Commits: ",
|
|
1959
|
+
entry.commits.join(", ")
|
|
1960
|
+
] }),
|
|
1961
|
+
entry.filesModified.length > 0 && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1962
|
+
"Files: ",
|
|
1963
|
+
entry.filesModified.length,
|
|
1964
|
+
" modified"
|
|
1965
|
+
] }),
|
|
1966
|
+
entry.error && /* @__PURE__ */ jsxs12(Text12, { color: "red", children: [
|
|
1967
|
+
"Error: ",
|
|
1968
|
+
entry.error
|
|
1969
|
+
] })
|
|
1970
|
+
] })
|
|
1971
|
+
] }, idx);
|
|
1972
|
+
}),
|
|
1973
|
+
start + maxVisible < history.length && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
|
|
1974
|
+
" \u2193 ",
|
|
1975
|
+
history.length - start - maxVisible,
|
|
1976
|
+
" more"
|
|
1977
|
+
] })
|
|
1978
|
+
] }),
|
|
1979
|
+
/* @__PURE__ */ jsx12(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx12(Text12, { dimColor: true, children: "Enter=expand r=refresh q=quit" }) })
|
|
1980
|
+
] });
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
// src/screens/Marketplace.tsx
|
|
1984
|
+
import { useState as useState15, useEffect as useEffect11 } from "react";
|
|
1985
|
+
import { Box as Box13, Text as Text13, useInput as useInput11 } from "ink";
|
|
1986
|
+
import { jsx as jsx13, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1987
|
+
var SKILL_SOURCES = [
|
|
1988
|
+
{ owner: "composioHQ", repo: "awesome-claude-code-skills", name: "Composio Curated" },
|
|
1989
|
+
{ owner: "anthropics", repo: "courses", name: "Anthropic Official" }
|
|
1990
|
+
];
|
|
1991
|
+
function Marketplace({ rows = 24 }) {
|
|
1992
|
+
const [skills, setSkills] = useState15([]);
|
|
1993
|
+
const [loading, setLoading] = useState15(true);
|
|
1994
|
+
const [error, setError] = useState15(null);
|
|
1995
|
+
const [sel, setSel] = useState15(0);
|
|
1996
|
+
const [search, setSearch] = useState15("");
|
|
1997
|
+
const [installing, setInstalling] = useState15(null);
|
|
1998
|
+
const filtered = skills.filter(
|
|
1999
|
+
(s) => s.name.toLowerCase().includes(search.toLowerCase()) || s.description.toLowerCase().includes(search.toLowerCase()) || s.tags?.some((t) => t.toLowerCase().includes(search.toLowerCase()))
|
|
2000
|
+
);
|
|
2001
|
+
const maxVisible = Math.max(5, rows - 10);
|
|
2002
|
+
const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), filtered.length - maxVisible));
|
|
2003
|
+
const visible = filtered.slice(start, start + maxVisible);
|
|
2004
|
+
useEffect11(() => {
|
|
2005
|
+
loadMarketplace();
|
|
2006
|
+
}, []);
|
|
2007
|
+
const loadMarketplace = async () => {
|
|
2008
|
+
setLoading(true);
|
|
2009
|
+
setError(null);
|
|
2010
|
+
try {
|
|
2011
|
+
const allSkills = [];
|
|
2012
|
+
for (const source of SKILL_SOURCES) {
|
|
2013
|
+
try {
|
|
2014
|
+
const indexUrl = `https://raw.githubusercontent.com/${source.owner}/${source.repo}/main/skills.json`;
|
|
2015
|
+
const response = await fetch(indexUrl);
|
|
2016
|
+
if (response.ok) {
|
|
2017
|
+
const data = await response.json();
|
|
2018
|
+
if (Array.isArray(data)) {
|
|
2019
|
+
allSkills.push(...data.map((s) => ({
|
|
2020
|
+
name: String(s.name || "Unknown"),
|
|
2021
|
+
description: String(s.description || ""),
|
|
2022
|
+
source: source.name,
|
|
2023
|
+
repo: `${source.owner}/${source.repo}`,
|
|
2024
|
+
tags: Array.isArray(s.tags) ? s.tags : [],
|
|
2025
|
+
stars: typeof s.stars === "number" ? s.stars : void 0
|
|
2026
|
+
})));
|
|
2027
|
+
}
|
|
2028
|
+
} else {
|
|
2029
|
+
allSkills.push({
|
|
2030
|
+
name: source.repo,
|
|
2031
|
+
description: `Skills from ${source.name}`,
|
|
2032
|
+
source: source.name,
|
|
2033
|
+
repo: `${source.owner}/${source.repo}`
|
|
2034
|
+
});
|
|
2035
|
+
}
|
|
2036
|
+
} catch {
|
|
2037
|
+
allSkills.push({
|
|
2038
|
+
name: source.repo,
|
|
2039
|
+
description: `Skills from ${source.name}`,
|
|
2040
|
+
source: source.name,
|
|
2041
|
+
repo: `${source.owner}/${source.repo}`
|
|
2042
|
+
});
|
|
2043
|
+
}
|
|
2044
|
+
}
|
|
2045
|
+
if (allSkills.length === 0) {
|
|
2046
|
+
allSkills.push(
|
|
2047
|
+
{ name: "typescript-strict", description: "Enable strict TypeScript mode", source: "Built-in", repo: "skillkit/skills", tags: ["typescript", "config"] },
|
|
2048
|
+
{ name: "eslint-setup", description: "Set up ESLint with recommended rules", source: "Built-in", repo: "skillkit/skills", tags: ["eslint", "linting"] },
|
|
2049
|
+
{ name: "prettier-config", description: "Configure Prettier formatting", source: "Built-in", repo: "skillkit/skills", tags: ["prettier", "formatting"] },
|
|
2050
|
+
{ name: "jest-setup", description: "Set up Jest testing framework", source: "Built-in", repo: "skillkit/skills", tags: ["jest", "testing"] },
|
|
2051
|
+
{ name: "nextjs-auth", description: "Add authentication to Next.js", source: "Community", repo: "community/skills", tags: ["nextjs", "auth"] }
|
|
2052
|
+
);
|
|
2053
|
+
}
|
|
2054
|
+
setSkills(allSkills);
|
|
2055
|
+
} catch (e) {
|
|
2056
|
+
setError(e instanceof Error ? e.message : "Failed to load marketplace");
|
|
2057
|
+
}
|
|
2058
|
+
setLoading(false);
|
|
2059
|
+
};
|
|
2060
|
+
useInput11((input, key) => {
|
|
2061
|
+
if (loading || installing) return;
|
|
2062
|
+
if (key.upArrow) setSel((i) => Math.max(0, i - 1));
|
|
2063
|
+
else if (key.downArrow) setSel((i) => Math.min(filtered.length - 1, i + 1));
|
|
2064
|
+
else if (input === "r") loadMarketplace();
|
|
2065
|
+
else if (input === "/") setSearch("");
|
|
2066
|
+
else if (key.backspace || key.delete) setSearch((s) => s.slice(0, -1));
|
|
2067
|
+
else if (key.return && filtered[sel]) {
|
|
2068
|
+
setInstalling(filtered[sel].name);
|
|
2069
|
+
setTimeout(() => setInstalling(null), 1500);
|
|
2070
|
+
} else if (input.length === 1 && /[a-zA-Z0-9-_]/.test(input)) {
|
|
2071
|
+
setSearch((s) => s + input);
|
|
2072
|
+
setSel(0);
|
|
2073
|
+
}
|
|
2074
|
+
});
|
|
2075
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
|
|
2076
|
+
/* @__PURE__ */ jsx13(Text13, { bold: true, color: colors.primary, children: "SKILL MARKETPLACE" }),
|
|
2077
|
+
/* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
2078
|
+
skills.length,
|
|
2079
|
+
" skills from ",
|
|
2080
|
+
SKILL_SOURCES.length,
|
|
2081
|
+
" sources"
|
|
2082
|
+
] }),
|
|
2083
|
+
search && /* @__PURE__ */ jsxs13(Text13, { children: [
|
|
2084
|
+
"Search: ",
|
|
2085
|
+
/* @__PURE__ */ jsx13(Text13, { color: "yellow", children: search }),
|
|
2086
|
+
" (",
|
|
2087
|
+
filtered.length,
|
|
2088
|
+
" results)"
|
|
2089
|
+
] }),
|
|
2090
|
+
loading && /* @__PURE__ */ jsx13(Text13, { children: "Loading marketplace..." }),
|
|
2091
|
+
error && /* @__PURE__ */ jsx13(Text13, { color: "red", children: error }),
|
|
2092
|
+
installing && /* @__PURE__ */ jsxs13(Text13, { color: "yellow", children: [
|
|
2093
|
+
"Installing ",
|
|
2094
|
+
installing,
|
|
2095
|
+
"..."
|
|
2096
|
+
] }),
|
|
2097
|
+
!loading && !installing && filtered.length === 0 && /* @__PURE__ */ jsx13(Box13, { marginTop: 1, children: /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
2098
|
+
"No skills found",
|
|
2099
|
+
search ? ` matching "${search}"` : "",
|
|
2100
|
+
"."
|
|
2101
|
+
] }) }),
|
|
2102
|
+
!loading && !installing && filtered.length > 0 && /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, flexDirection: "column", children: [
|
|
2103
|
+
start > 0 && /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
2104
|
+
" \u2191 ",
|
|
2105
|
+
start,
|
|
2106
|
+
" more"
|
|
2107
|
+
] }),
|
|
2108
|
+
visible.map((skill, i) => {
|
|
2109
|
+
const idx = start + i;
|
|
2110
|
+
const isSel = idx === sel;
|
|
2111
|
+
return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", children: [
|
|
2112
|
+
/* @__PURE__ */ jsxs13(Text13, { inverse: isSel, children: [
|
|
2113
|
+
isSel ? symbols.pointer : " ",
|
|
2114
|
+
" ",
|
|
2115
|
+
skill.name.padEnd(25),
|
|
2116
|
+
" ",
|
|
2117
|
+
/* @__PURE__ */ jsx13(Text13, { dimColor: true, children: skill.source })
|
|
2118
|
+
] }),
|
|
2119
|
+
isSel && /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", marginLeft: 3, children: [
|
|
2120
|
+
/* @__PURE__ */ jsx13(Text13, { dimColor: true, children: skill.description }),
|
|
2121
|
+
skill.tags && skill.tags.length > 0 && /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
2122
|
+
"Tags: ",
|
|
2123
|
+
skill.tags.join(", ")
|
|
2124
|
+
] }),
|
|
2125
|
+
/* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
2126
|
+
"Repo: ",
|
|
2127
|
+
skill.repo
|
|
2128
|
+
] })
|
|
2129
|
+
] })
|
|
2130
|
+
] }, `${skill.repo}/${skill.name}`);
|
|
2131
|
+
}),
|
|
2132
|
+
start + maxVisible < filtered.length && /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
|
|
2133
|
+
" \u2193 ",
|
|
2134
|
+
filtered.length - start - maxVisible,
|
|
2135
|
+
" more"
|
|
2136
|
+
] })
|
|
2137
|
+
] }),
|
|
2138
|
+
/* @__PURE__ */ jsx13(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx13(Text13, { dimColor: true, children: "Enter=install type=search r=refresh q=quit" }) })
|
|
2139
|
+
] });
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
// src/screens/Memory.tsx
|
|
2143
|
+
import { useState as useState16, useEffect as useEffect12 } from "react";
|
|
2144
|
+
import { Box as Box14, Text as Text14, useInput as useInput12 } from "ink";
|
|
2145
|
+
import {
|
|
2146
|
+
ObservationStore,
|
|
2147
|
+
LearningStore,
|
|
2148
|
+
getMemoryStatus,
|
|
2149
|
+
getMemoryPaths,
|
|
2150
|
+
createMemoryInjector
|
|
2151
|
+
} from "@skillkit/core";
|
|
2152
|
+
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2153
|
+
function Memory({ rows = 24 }) {
|
|
2154
|
+
const [tab, setTab] = useState16("learnings");
|
|
2155
|
+
const [learnings, setLearnings] = useState16([]);
|
|
2156
|
+
const [observationCount, setObservationCount] = useState16(0);
|
|
2157
|
+
const [globalCount, setGlobalCount] = useState16(0);
|
|
2158
|
+
const [loading, setLoading] = useState16(true);
|
|
2159
|
+
const [sel, setSel] = useState16(0);
|
|
2160
|
+
const [expanded, setExpanded] = useState16(false);
|
|
2161
|
+
const [searchQuery, setSearchQuery] = useState16("");
|
|
2162
|
+
const [searchResults, setSearchResults] = useState16([]);
|
|
2163
|
+
const [isGlobal, setIsGlobal] = useState16(false);
|
|
2164
|
+
const maxVisible = Math.max(5, rows - 10);
|
|
2165
|
+
const currentList = tab === "search" ? searchResults : learnings;
|
|
2166
|
+
const start = Math.max(0, Math.min(sel - Math.floor(maxVisible / 2), currentList.length - maxVisible));
|
|
2167
|
+
const visible = currentList.slice(start, start + maxVisible);
|
|
2168
|
+
useEffect12(() => {
|
|
2169
|
+
loadMemory();
|
|
2170
|
+
}, [isGlobal]);
|
|
2171
|
+
const loadMemory = () => {
|
|
2172
|
+
setLoading(true);
|
|
2173
|
+
try {
|
|
2174
|
+
const projectPath = process.cwd();
|
|
2175
|
+
const status = getMemoryStatus(projectPath);
|
|
2176
|
+
const store = new LearningStore(
|
|
2177
|
+
isGlobal ? "global" : "project",
|
|
2178
|
+
isGlobal ? void 0 : projectPath
|
|
2179
|
+
);
|
|
2180
|
+
setLearnings(store.getAll());
|
|
2181
|
+
if (status.hasObservations) {
|
|
2182
|
+
const obsStore = new ObservationStore(projectPath);
|
|
2183
|
+
setObservationCount(obsStore.count());
|
|
2184
|
+
} else {
|
|
2185
|
+
setObservationCount(0);
|
|
2186
|
+
}
|
|
2187
|
+
if (status.hasGlobalLearnings) {
|
|
2188
|
+
const globalStore = new LearningStore("global");
|
|
2189
|
+
setGlobalCount(globalStore.count());
|
|
2190
|
+
} else {
|
|
2191
|
+
setGlobalCount(0);
|
|
2192
|
+
}
|
|
2193
|
+
} catch {
|
|
2194
|
+
setLearnings([]);
|
|
2195
|
+
setObservationCount(0);
|
|
2196
|
+
setGlobalCount(0);
|
|
2197
|
+
}
|
|
2198
|
+
setLoading(false);
|
|
2199
|
+
};
|
|
2200
|
+
const handleSearch = (query) => {
|
|
2201
|
+
if (!query.trim()) {
|
|
2202
|
+
setSearchResults([]);
|
|
2203
|
+
return;
|
|
2204
|
+
}
|
|
2205
|
+
try {
|
|
2206
|
+
const projectPath = process.cwd();
|
|
2207
|
+
const injector = createMemoryInjector(projectPath);
|
|
2208
|
+
const results = injector.search(query, {
|
|
2209
|
+
includeGlobal: true,
|
|
2210
|
+
maxLearnings: 20,
|
|
2211
|
+
minRelevance: 0
|
|
2212
|
+
});
|
|
2213
|
+
setSearchResults(results.map((r) => r.learning));
|
|
2214
|
+
} catch {
|
|
2215
|
+
setSearchResults([]);
|
|
2216
|
+
}
|
|
2217
|
+
};
|
|
2218
|
+
useInput12((input, key) => {
|
|
2219
|
+
if (loading) return;
|
|
2220
|
+
if (input === "1") {
|
|
2221
|
+
setTab("learnings");
|
|
2222
|
+
setSel(0);
|
|
2223
|
+
setExpanded(false);
|
|
2224
|
+
} else if (input === "2") {
|
|
2225
|
+
setTab("observations");
|
|
2226
|
+
setSel(0);
|
|
2227
|
+
setExpanded(false);
|
|
2228
|
+
} else if (input === "3") {
|
|
2229
|
+
setTab("search");
|
|
2230
|
+
setSel(0);
|
|
2231
|
+
setExpanded(false);
|
|
2232
|
+
} else if (key.upArrow) {
|
|
2233
|
+
setSel((i) => Math.max(0, i - 1));
|
|
2234
|
+
setExpanded(false);
|
|
2235
|
+
} else if (key.downArrow) {
|
|
2236
|
+
setSel((i) => Math.min(currentList.length - 1, i + 1));
|
|
2237
|
+
setExpanded(false);
|
|
2238
|
+
} else if (input === "f") loadMemory();
|
|
2239
|
+
else if (input === "g") setIsGlobal((g) => !g);
|
|
2240
|
+
else if (key.return) setExpanded((e) => !e);
|
|
2241
|
+
else if (tab === "search" && input && input.length === 1 && !key.ctrl && !key.meta) {
|
|
2242
|
+
const newQuery = searchQuery + input;
|
|
2243
|
+
setSearchQuery(newQuery);
|
|
2244
|
+
handleSearch(newQuery);
|
|
2245
|
+
} else if (tab === "search" && key.backspace) {
|
|
2246
|
+
const newQuery = searchQuery.slice(0, -1);
|
|
2247
|
+
setSearchQuery(newQuery);
|
|
2248
|
+
handleSearch(newQuery);
|
|
2249
|
+
}
|
|
2250
|
+
});
|
|
2251
|
+
const ONE_MINUTE = 6e4;
|
|
2252
|
+
const ONE_HOUR = 36e5;
|
|
2253
|
+
const ONE_DAY = 864e5;
|
|
2254
|
+
function formatDate(iso) {
|
|
2255
|
+
const d = new Date(iso);
|
|
2256
|
+
const diff = Date.now() - d.getTime();
|
|
2257
|
+
if (diff < ONE_MINUTE) return "Just now";
|
|
2258
|
+
if (diff < ONE_HOUR) return `${Math.floor(diff / ONE_MINUTE)}m ago`;
|
|
2259
|
+
if (diff < ONE_DAY) return `${Math.floor(diff / ONE_HOUR)}h ago`;
|
|
2260
|
+
return d.toLocaleDateString();
|
|
2261
|
+
}
|
|
2262
|
+
function formatEffectiveness(eff) {
|
|
2263
|
+
if (eff === void 0) return " -";
|
|
2264
|
+
return eff.toString().padStart(3) + "%";
|
|
2265
|
+
}
|
|
2266
|
+
function getEffectivenessColor(eff) {
|
|
2267
|
+
if (eff === void 0) return void 0;
|
|
2268
|
+
if (eff >= 70) return "green";
|
|
2269
|
+
if (eff >= 40) return "yellow";
|
|
2270
|
+
return "red";
|
|
2271
|
+
}
|
|
2272
|
+
const renderLearnings = () => /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
2273
|
+
currentList.length === 0 && /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
|
|
2274
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "No learnings found." }),
|
|
2275
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Run skills to capture learnings, or add manually:" }),
|
|
2276
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: ' skillkit memory add --title "..." --content "..."' })
|
|
2277
|
+
] }),
|
|
2278
|
+
currentList.length > 0 && /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
|
|
2279
|
+
start > 0 && /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2280
|
+
" ",
|
|
2281
|
+
symbols.arrowUp,
|
|
2282
|
+
" ",
|
|
2283
|
+
start,
|
|
2284
|
+
" more"
|
|
2285
|
+
] }),
|
|
2286
|
+
visible.map((learning, i) => {
|
|
2287
|
+
const idx = start + i;
|
|
2288
|
+
const isSel = idx === sel;
|
|
2289
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
2290
|
+
/* @__PURE__ */ jsxs14(Text14, { inverse: isSel, children: [
|
|
2291
|
+
isSel ? symbols.pointer : " ",
|
|
2292
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.primary, children: symbols.bullet }),
|
|
2293
|
+
" ",
|
|
2294
|
+
learning.title.slice(0, 35).padEnd(35),
|
|
2295
|
+
" ",
|
|
2296
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: learning.tags.slice(0, 2).join(", ").slice(0, 15).padEnd(15) }),
|
|
2297
|
+
" ",
|
|
2298
|
+
/* @__PURE__ */ jsx14(Text14, { color: getEffectivenessColor(learning.effectiveness), children: formatEffectiveness(learning.effectiveness) }),
|
|
2299
|
+
" ",
|
|
2300
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: formatDate(learning.updatedAt) })
|
|
2301
|
+
] }),
|
|
2302
|
+
isSel && expanded && /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginLeft: 3, marginY: 1, children: [
|
|
2303
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2304
|
+
"ID: ",
|
|
2305
|
+
learning.id.slice(0, 8)
|
|
2306
|
+
] }),
|
|
2307
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2308
|
+
"Scope: ",
|
|
2309
|
+
learning.scope
|
|
2310
|
+
] }),
|
|
2311
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2312
|
+
"Source: ",
|
|
2313
|
+
learning.source
|
|
2314
|
+
] }),
|
|
2315
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2316
|
+
"Tags: ",
|
|
2317
|
+
learning.tags.join(", ")
|
|
2318
|
+
] }),
|
|
2319
|
+
learning.frameworks && learning.frameworks.length > 0 && /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2320
|
+
"Frameworks: ",
|
|
2321
|
+
learning.frameworks.join(", ")
|
|
2322
|
+
] }),
|
|
2323
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2324
|
+
"Uses: ",
|
|
2325
|
+
learning.useCount
|
|
2326
|
+
] }),
|
|
2327
|
+
/* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsxs14(Text14, { wrap: "wrap", children: [
|
|
2328
|
+
learning.content.slice(0, 300),
|
|
2329
|
+
learning.content.length > 300 ? "..." : ""
|
|
2330
|
+
] }) })
|
|
2331
|
+
] })
|
|
2332
|
+
] }, learning.id);
|
|
2333
|
+
}),
|
|
2334
|
+
start + maxVisible < currentList.length && /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2335
|
+
" ",
|
|
2336
|
+
symbols.arrowDown,
|
|
2337
|
+
" ",
|
|
2338
|
+
currentList.length - start - maxVisible,
|
|
2339
|
+
" more"
|
|
2340
|
+
] })
|
|
2341
|
+
] })
|
|
2342
|
+
] });
|
|
2343
|
+
const renderObservations = () => /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginTop: 1, children: [
|
|
2344
|
+
/* @__PURE__ */ jsxs14(Text14, { children: [
|
|
2345
|
+
"Session Observations: ",
|
|
2346
|
+
/* @__PURE__ */ jsx14(Text14, { bold: true, color: colors.primary, children: observationCount })
|
|
2347
|
+
] }),
|
|
2348
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Observations are raw captures from skill execution." }),
|
|
2349
|
+
observationCount > 0 && /* @__PURE__ */ jsxs14(Box14, { marginTop: 1, flexDirection: "column", children: [
|
|
2350
|
+
/* @__PURE__ */ jsx14(Text14, { children: "Compress observations into learnings:" }),
|
|
2351
|
+
/* @__PURE__ */ jsx14(Text14, { dimColor: true, children: " skillkit memory compress" })
|
|
2352
|
+
] }),
|
|
2353
|
+
observationCount >= 50 && /* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsxs14(Text14, { color: "yellow", children: [
|
|
2354
|
+
symbols.warning,
|
|
2355
|
+
" You have many uncompressed observations."
|
|
2356
|
+
] }) }),
|
|
2357
|
+
/* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Observations are stored at:" }) }),
|
|
2358
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2359
|
+
" ",
|
|
2360
|
+
getMemoryPaths(process.cwd()).observationsFile
|
|
2361
|
+
] })
|
|
2362
|
+
] });
|
|
2363
|
+
const renderSearch = () => /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", marginTop: 1, children: [
|
|
2364
|
+
/* @__PURE__ */ jsxs14(Box14, { children: [
|
|
2365
|
+
/* @__PURE__ */ jsx14(Text14, { children: "Search: " }),
|
|
2366
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.primary, children: searchQuery }),
|
|
2367
|
+
/* @__PURE__ */ jsx14(Text14, { color: colors.secondary, children: "_" })
|
|
2368
|
+
] }),
|
|
2369
|
+
searchQuery && searchResults.length === 0 && /* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2370
|
+
'No results found for "',
|
|
2371
|
+
searchQuery,
|
|
2372
|
+
'"'
|
|
2373
|
+
] }) }),
|
|
2374
|
+
searchResults.length > 0 && renderLearnings()
|
|
2375
|
+
] });
|
|
2376
|
+
return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", children: [
|
|
2377
|
+
/* @__PURE__ */ jsx14(Text14, { bold: true, color: colors.primary, children: "MEMORY" }),
|
|
2378
|
+
/* @__PURE__ */ jsxs14(Text14, { dimColor: true, children: [
|
|
2379
|
+
isGlobal ? "Global" : "Project",
|
|
2380
|
+
": ",
|
|
2381
|
+
learnings.length,
|
|
2382
|
+
" learning(s)",
|
|
2383
|
+
!isGlobal && globalCount > 0 && /* @__PURE__ */ jsxs14(Text14, { children: [
|
|
2384
|
+
" | Global: ",
|
|
2385
|
+
globalCount
|
|
2386
|
+
] })
|
|
2387
|
+
] }),
|
|
2388
|
+
/* @__PURE__ */ jsxs14(Box14, { marginTop: 1, children: [
|
|
2389
|
+
/* @__PURE__ */ jsx14(Text14, { inverse: tab === "learnings", children: "[1] Learnings" }),
|
|
2390
|
+
/* @__PURE__ */ jsx14(Text14, { children: " " }),
|
|
2391
|
+
/* @__PURE__ */ jsx14(Text14, { inverse: tab === "observations", children: "[2] Observations" }),
|
|
2392
|
+
/* @__PURE__ */ jsx14(Text14, { children: " " }),
|
|
2393
|
+
/* @__PURE__ */ jsx14(Text14, { inverse: tab === "search", children: "[3] Search" })
|
|
2394
|
+
] }),
|
|
2395
|
+
loading && /* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { children: "Loading..." }) }),
|
|
2396
|
+
!loading && tab === "learnings" && renderLearnings(),
|
|
2397
|
+
!loading && tab === "observations" && renderObservations(),
|
|
2398
|
+
!loading && tab === "search" && renderSearch(),
|
|
2399
|
+
/* @__PURE__ */ jsx14(Box14, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text14, { dimColor: true, children: "Enter=expand g=toggle global f=refresh 1-3=tabs" }) })
|
|
2400
|
+
] });
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
// src/App.tsx
|
|
2404
|
+
import { jsx as jsx15, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1817
2405
|
function App() {
|
|
1818
|
-
const [screen, setScreen] =
|
|
2406
|
+
const [screen, setScreen] = useState17("home");
|
|
1819
2407
|
const { exit } = useApp();
|
|
1820
2408
|
const { stdout } = useStdout();
|
|
1821
2409
|
const cols = stdout?.columns || 80;
|
|
1822
2410
|
const rows = stdout?.rows || 24;
|
|
1823
2411
|
const showSidebar = cols >= 70;
|
|
1824
|
-
|
|
2412
|
+
const NAV_KEYS = {
|
|
2413
|
+
h: "home",
|
|
2414
|
+
m: "marketplace",
|
|
2415
|
+
b: "browse",
|
|
2416
|
+
w: "workflow",
|
|
2417
|
+
x: "execute",
|
|
2418
|
+
y: "history",
|
|
2419
|
+
r: "recommend",
|
|
2420
|
+
t: "translate",
|
|
2421
|
+
c: "context",
|
|
2422
|
+
e: "memory",
|
|
2423
|
+
i: "installed",
|
|
2424
|
+
s: "sync",
|
|
2425
|
+
",": "settings"
|
|
2426
|
+
};
|
|
2427
|
+
useInput13((input, key) => {
|
|
1825
2428
|
if (input === "q") {
|
|
1826
2429
|
exit();
|
|
1827
2430
|
return;
|
|
@@ -1830,65 +2433,71 @@ function App() {
|
|
|
1830
2433
|
setScreen("home");
|
|
1831
2434
|
return;
|
|
1832
2435
|
}
|
|
1833
|
-
|
|
1834
|
-
if (
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
if (input === ",") setScreen("settings");
|
|
1838
|
-
if (input === "r") setScreen("recommend");
|
|
1839
|
-
if (input === "t") setScreen("translate");
|
|
1840
|
-
if (input === "c") setScreen("context");
|
|
2436
|
+
const targetScreen = NAV_KEYS[input];
|
|
2437
|
+
if (targetScreen) {
|
|
2438
|
+
setScreen(targetScreen);
|
|
2439
|
+
}
|
|
1841
2440
|
});
|
|
1842
2441
|
const renderScreen = () => {
|
|
1843
2442
|
switch (screen) {
|
|
1844
2443
|
case "home":
|
|
1845
|
-
return /* @__PURE__ */
|
|
2444
|
+
return /* @__PURE__ */ jsx15(Home, { onNavigate: setScreen, cols, rows });
|
|
1846
2445
|
case "browse":
|
|
1847
|
-
return /* @__PURE__ */
|
|
2446
|
+
return /* @__PURE__ */ jsx15(Browse, { cols, rows });
|
|
1848
2447
|
case "installed":
|
|
1849
|
-
return /* @__PURE__ */
|
|
2448
|
+
return /* @__PURE__ */ jsx15(Installed, { cols, rows });
|
|
1850
2449
|
case "sync":
|
|
1851
|
-
return /* @__PURE__ */
|
|
2450
|
+
return /* @__PURE__ */ jsx15(Sync, { cols, rows });
|
|
1852
2451
|
case "settings":
|
|
1853
|
-
return /* @__PURE__ */
|
|
2452
|
+
return /* @__PURE__ */ jsx15(Settings, { cols, rows });
|
|
1854
2453
|
case "recommend":
|
|
1855
|
-
return /* @__PURE__ */
|
|
2454
|
+
return /* @__PURE__ */ jsx15(Recommend, { cols, rows });
|
|
1856
2455
|
case "translate":
|
|
1857
|
-
return /* @__PURE__ */
|
|
2456
|
+
return /* @__PURE__ */ jsx15(Translate, { cols, rows });
|
|
1858
2457
|
case "context":
|
|
1859
|
-
return /* @__PURE__ */
|
|
2458
|
+
return /* @__PURE__ */ jsx15(Context, { cols, rows });
|
|
2459
|
+
case "workflow":
|
|
2460
|
+
return /* @__PURE__ */ jsx15(Workflow, { cols, rows });
|
|
2461
|
+
case "execute":
|
|
2462
|
+
return /* @__PURE__ */ jsx15(Execute, { cols, rows });
|
|
2463
|
+
case "history":
|
|
2464
|
+
return /* @__PURE__ */ jsx15(History, { cols, rows });
|
|
2465
|
+
case "marketplace":
|
|
2466
|
+
return /* @__PURE__ */ jsx15(Marketplace, { cols, rows });
|
|
2467
|
+
case "memory":
|
|
2468
|
+
return /* @__PURE__ */ jsx15(Memory, { cols, rows });
|
|
1860
2469
|
}
|
|
1861
2470
|
};
|
|
1862
2471
|
const contentHeight = rows - 2;
|
|
1863
|
-
return /* @__PURE__ */
|
|
1864
|
-
/* @__PURE__ */
|
|
1865
|
-
showSidebar && /* @__PURE__ */
|
|
1866
|
-
/* @__PURE__ */
|
|
2472
|
+
return /* @__PURE__ */ jsxs15(Box15, { flexDirection: "column", height: rows, children: [
|
|
2473
|
+
/* @__PURE__ */ jsxs15(Box15, { flexDirection: "row", height: contentHeight, children: [
|
|
2474
|
+
showSidebar && /* @__PURE__ */ jsx15(Sidebar, { screen, onNavigate: setScreen }),
|
|
2475
|
+
/* @__PURE__ */ jsx15(Box15, { flexDirection: "column", flexGrow: 1, marginLeft: 1, children: renderScreen() })
|
|
1867
2476
|
] }),
|
|
1868
|
-
/* @__PURE__ */
|
|
2477
|
+
/* @__PURE__ */ jsx15(Box15, { children: /* @__PURE__ */ jsx15(Text15, { dimColor: true, children: "h Home m Market b Browse i Inst w Wflow x Exec y Hist r Rec t Trans c Ctx e Mem s Sync , Cfg q Quit" }) })
|
|
1869
2478
|
] });
|
|
1870
2479
|
}
|
|
1871
2480
|
|
|
1872
2481
|
// src/components/Header.tsx
|
|
1873
|
-
import { Box as
|
|
1874
|
-
import { jsx as
|
|
2482
|
+
import { Box as Box16, Text as Text16 } from "ink";
|
|
2483
|
+
import { jsx as jsx16, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1875
2484
|
function Header({ title, subtitle, count }) {
|
|
1876
|
-
return /* @__PURE__ */
|
|
1877
|
-
/* @__PURE__ */
|
|
1878
|
-
/* @__PURE__ */
|
|
1879
|
-
count !== void 0 && /* @__PURE__ */
|
|
2485
|
+
return /* @__PURE__ */ jsxs16(Box16, { flexDirection: "column", marginBottom: 1, children: [
|
|
2486
|
+
/* @__PURE__ */ jsxs16(Box16, { justifyContent: "space-between", children: [
|
|
2487
|
+
/* @__PURE__ */ jsx16(Text16, { color: colors.primary, bold: true, children: title.toUpperCase() }),
|
|
2488
|
+
count !== void 0 && /* @__PURE__ */ jsxs16(Text16, { color: colors.secondaryDim, children: [
|
|
1880
2489
|
symbols.star,
|
|
1881
2490
|
" ",
|
|
1882
2491
|
count
|
|
1883
2492
|
] })
|
|
1884
2493
|
] }),
|
|
1885
|
-
subtitle && /* @__PURE__ */
|
|
2494
|
+
subtitle && /* @__PURE__ */ jsx16(Text16, { color: colors.secondaryDim, dimColor: true, children: subtitle })
|
|
1886
2495
|
] });
|
|
1887
2496
|
}
|
|
1888
2497
|
|
|
1889
2498
|
// src/components/SkillList.tsx
|
|
1890
|
-
import { Box as
|
|
1891
|
-
import { jsx as
|
|
2499
|
+
import { Box as Box17, Text as Text17 } from "ink";
|
|
2500
|
+
import { jsx as jsx17, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1892
2501
|
function formatInstalls(count) {
|
|
1893
2502
|
if (count >= 1e3) {
|
|
1894
2503
|
return `${(count / 1e3).toFixed(1)}K`;
|
|
@@ -1904,13 +2513,13 @@ function SkillList({
|
|
|
1904
2513
|
maxVisible = 10
|
|
1905
2514
|
}) {
|
|
1906
2515
|
if (skills.length === 0) {
|
|
1907
|
-
return /* @__PURE__ */
|
|
2516
|
+
return /* @__PURE__ */ jsx17(Box17, { children: /* @__PURE__ */ jsx17(Text17, { color: colors.secondaryDim, dimColor: true, children: "No skills found" }) });
|
|
1908
2517
|
}
|
|
1909
2518
|
const startIndex = Math.max(0, selectedIndex - Math.floor(maxVisible / 2));
|
|
1910
2519
|
const visibleSkills = skills.slice(startIndex, startIndex + maxVisible);
|
|
1911
2520
|
const actualStartIndex = startIndex;
|
|
1912
|
-
return /* @__PURE__ */
|
|
1913
|
-
showRank && /* @__PURE__ */
|
|
2521
|
+
return /* @__PURE__ */ jsxs17(Box17, { flexDirection: "column", children: [
|
|
2522
|
+
showRank && /* @__PURE__ */ jsx17(Box17, { marginBottom: 1, children: /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, children: [
|
|
1914
2523
|
" # SKILL",
|
|
1915
2524
|
showSource && " SOURCE",
|
|
1916
2525
|
showInstalls && " INSTALLS"
|
|
@@ -1920,9 +2529,9 @@ function SkillList({
|
|
|
1920
2529
|
const isSelected = realIndex === selectedIndex;
|
|
1921
2530
|
const skillName = skill.name.padEnd(28).slice(0, 28);
|
|
1922
2531
|
const sourceName = skill.source ? skill.source.slice(0, 25) : "";
|
|
1923
|
-
return /* @__PURE__ */
|
|
1924
|
-
/* @__PURE__ */
|
|
1925
|
-
|
|
2532
|
+
return /* @__PURE__ */ jsxs17(Box17, { children: [
|
|
2533
|
+
/* @__PURE__ */ jsxs17(
|
|
2534
|
+
Text17,
|
|
1926
2535
|
{
|
|
1927
2536
|
color: isSelected ? colors.primary : colors.secondary,
|
|
1928
2537
|
bold: isSelected,
|
|
@@ -1935,14 +2544,14 @@ function SkillList({
|
|
|
1935
2544
|
]
|
|
1936
2545
|
}
|
|
1937
2546
|
),
|
|
1938
|
-
showSource && /* @__PURE__ */
|
|
2547
|
+
showSource && /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, dimColor: !isSelected, children: [
|
|
1939
2548
|
" ",
|
|
1940
2549
|
sourceName
|
|
1941
2550
|
] }),
|
|
1942
|
-
showInstalls && skill.installs !== void 0 && /* @__PURE__ */
|
|
2551
|
+
showInstalls && skill.installs !== void 0 && /* @__PURE__ */ jsx17(Text17, { color: colors.secondaryDim, children: formatInstalls(skill.installs).padStart(8) })
|
|
1943
2552
|
] }, `${skill.source}-${skill.name}`);
|
|
1944
2553
|
}),
|
|
1945
|
-
skills.length > maxVisible && /* @__PURE__ */
|
|
2554
|
+
skills.length > maxVisible && /* @__PURE__ */ jsx17(Box17, { marginTop: 1, children: /* @__PURE__ */ jsxs17(Text17, { color: colors.secondaryDim, dimColor: true, children: [
|
|
1946
2555
|
"Showing ",
|
|
1947
2556
|
startIndex + 1,
|
|
1948
2557
|
"-",
|
|
@@ -1954,11 +2563,11 @@ function SkillList({
|
|
|
1954
2563
|
}
|
|
1955
2564
|
|
|
1956
2565
|
// src/components/StatusBar.tsx
|
|
1957
|
-
import { Box as
|
|
1958
|
-
import { jsx as
|
|
2566
|
+
import { Box as Box18, Text as Text18 } from "ink";
|
|
2567
|
+
import { jsx as jsx18, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1959
2568
|
function StatusBar({ shortcuts, message }) {
|
|
1960
|
-
return /* @__PURE__ */
|
|
1961
|
-
|
|
2569
|
+
return /* @__PURE__ */ jsxs18(
|
|
2570
|
+
Box18,
|
|
1962
2571
|
{
|
|
1963
2572
|
borderStyle: "single",
|
|
1964
2573
|
borderColor: colors.borderDim,
|
|
@@ -1969,11 +2578,11 @@ function StatusBar({ shortcuts, message }) {
|
|
|
1969
2578
|
paddingX: 1,
|
|
1970
2579
|
justifyContent: "space-between",
|
|
1971
2580
|
children: [
|
|
1972
|
-
/* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
/* @__PURE__ */
|
|
2581
|
+
/* @__PURE__ */ jsx18(Box18, { gap: 2, children: shortcuts.map((shortcut, idx) => /* @__PURE__ */ jsxs18(Box18, { gap: 1, children: [
|
|
2582
|
+
/* @__PURE__ */ jsx18(Text18, { color: colors.primary, bold: true, children: shortcut.key }),
|
|
2583
|
+
/* @__PURE__ */ jsx18(Text18, { color: colors.secondaryDim, children: shortcut.label })
|
|
1975
2584
|
] }, idx)) }),
|
|
1976
|
-
message && /* @__PURE__ */
|
|
2585
|
+
message && /* @__PURE__ */ jsxs18(Text18, { color: colors.success, children: [
|
|
1977
2586
|
symbols.check,
|
|
1978
2587
|
" ",
|
|
1979
2588
|
message
|
|
@@ -1984,44 +2593,44 @@ function StatusBar({ shortcuts, message }) {
|
|
|
1984
2593
|
}
|
|
1985
2594
|
|
|
1986
2595
|
// src/components/SearchInput.tsx
|
|
1987
|
-
import { Box as
|
|
2596
|
+
import { Box as Box19, Text as Text19 } from "ink";
|
|
1988
2597
|
import TextInput from "ink-text-input";
|
|
1989
|
-
import { jsx as
|
|
2598
|
+
import { jsx as jsx19, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1990
2599
|
function SearchInput({
|
|
1991
2600
|
value,
|
|
1992
2601
|
onChange,
|
|
1993
2602
|
placeholder = "Search skills...",
|
|
1994
2603
|
isFocused = false
|
|
1995
2604
|
}) {
|
|
1996
|
-
return /* @__PURE__ */
|
|
1997
|
-
|
|
2605
|
+
return /* @__PURE__ */ jsxs19(
|
|
2606
|
+
Box19,
|
|
1998
2607
|
{
|
|
1999
2608
|
borderStyle: "single",
|
|
2000
2609
|
borderColor: isFocused ? colors.primary : colors.borderDim,
|
|
2001
2610
|
paddingX: 1,
|
|
2002
2611
|
children: [
|
|
2003
|
-
/* @__PURE__ */
|
|
2004
|
-
isFocused ? /* @__PURE__ */
|
|
2612
|
+
/* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, children: "/ " }),
|
|
2613
|
+
isFocused ? /* @__PURE__ */ jsx19(
|
|
2005
2614
|
TextInput,
|
|
2006
2615
|
{
|
|
2007
2616
|
value,
|
|
2008
2617
|
onChange,
|
|
2009
2618
|
placeholder
|
|
2010
2619
|
}
|
|
2011
|
-
) : /* @__PURE__ */
|
|
2012
|
-
/* @__PURE__ */
|
|
2013
|
-
/* @__PURE__ */
|
|
2620
|
+
) : /* @__PURE__ */ jsx19(Text19, { color: value ? colors.secondary : colors.secondaryDim, children: value || placeholder }),
|
|
2621
|
+
/* @__PURE__ */ jsx19(Box19, { flexGrow: 1 }),
|
|
2622
|
+
/* @__PURE__ */ jsx19(Text19, { color: colors.secondaryDim, children: "/" })
|
|
2014
2623
|
]
|
|
2015
2624
|
}
|
|
2016
2625
|
);
|
|
2017
2626
|
}
|
|
2018
2627
|
|
|
2019
2628
|
// src/hooks/useKeyboard.ts
|
|
2020
|
-
import { useState as
|
|
2021
|
-
import { useInput as
|
|
2629
|
+
import { useState as useState18, useCallback as useCallback3, useEffect as useEffect13 } from "react";
|
|
2630
|
+
import { useInput as useInput14, useApp as useApp2 } from "ink";
|
|
2022
2631
|
function useKeyboard(options = {}) {
|
|
2023
2632
|
const { exit } = useApp2();
|
|
2024
|
-
|
|
2633
|
+
useInput14((input, key) => {
|
|
2025
2634
|
if (options.disabled) return;
|
|
2026
2635
|
if (input === "q" || key.ctrl && input === "c") {
|
|
2027
2636
|
exit();
|
|
@@ -2065,8 +2674,8 @@ function useKeyboard(options = {}) {
|
|
|
2065
2674
|
});
|
|
2066
2675
|
}
|
|
2067
2676
|
function useListNavigation(listLength, initialIndex = 0) {
|
|
2068
|
-
const [selectedIndex, setSelectedIndex] =
|
|
2069
|
-
|
|
2677
|
+
const [selectedIndex, setSelectedIndex] = useState18(initialIndex);
|
|
2678
|
+
useEffect13(() => {
|
|
2070
2679
|
if (selectedIndex >= listLength && listLength > 0) {
|
|
2071
2680
|
setSelectedIndex(listLength - 1);
|
|
2072
2681
|
}
|
|
@@ -2083,11 +2692,122 @@ function useListNavigation(listLength, initialIndex = 0) {
|
|
|
2083
2692
|
return { selectedIndex, setSelectedIndex, moveUp, moveDown, reset };
|
|
2084
2693
|
}
|
|
2085
2694
|
|
|
2695
|
+
// src/hooks/useMemory.ts
|
|
2696
|
+
import { useState as useState19, useEffect as useEffect14, useCallback as useCallback4 } from "react";
|
|
2697
|
+
import {
|
|
2698
|
+
LearningStore as LearningStore2,
|
|
2699
|
+
ObservationStore as ObservationStore2,
|
|
2700
|
+
getMemoryStatus as getMemoryStatus2,
|
|
2701
|
+
createMemoryInjector as createMemoryInjector2
|
|
2702
|
+
} from "@skillkit/core";
|
|
2703
|
+
function useMemory() {
|
|
2704
|
+
const [learnings, setLearnings] = useState19([]);
|
|
2705
|
+
const [observations, setObservations] = useState19([]);
|
|
2706
|
+
const [status, setStatus] = useState19(null);
|
|
2707
|
+
const [loading, setLoading] = useState19(true);
|
|
2708
|
+
const [error, setError] = useState19(null);
|
|
2709
|
+
const [isGlobal, setIsGlobal] = useState19(false);
|
|
2710
|
+
const projectPath = process.cwd();
|
|
2711
|
+
const refresh = useCallback4(() => {
|
|
2712
|
+
setLoading(true);
|
|
2713
|
+
setError(null);
|
|
2714
|
+
try {
|
|
2715
|
+
const memStatus = getMemoryStatus2(projectPath);
|
|
2716
|
+
setStatus(memStatus);
|
|
2717
|
+
const learningStore = new LearningStore2(
|
|
2718
|
+
isGlobal ? "global" : "project",
|
|
2719
|
+
isGlobal ? void 0 : projectPath
|
|
2720
|
+
);
|
|
2721
|
+
setLearnings(learningStore.getAll());
|
|
2722
|
+
if (memStatus.hasObservations) {
|
|
2723
|
+
const obsStore = new ObservationStore2(projectPath);
|
|
2724
|
+
setObservations(obsStore.getAll());
|
|
2725
|
+
} else {
|
|
2726
|
+
setObservations([]);
|
|
2727
|
+
}
|
|
2728
|
+
} catch (err) {
|
|
2729
|
+
setError(err instanceof Error ? err.message : "Failed to load memory");
|
|
2730
|
+
setLearnings([]);
|
|
2731
|
+
setObservations([]);
|
|
2732
|
+
} finally {
|
|
2733
|
+
setLoading(false);
|
|
2734
|
+
}
|
|
2735
|
+
}, [projectPath, isGlobal]);
|
|
2736
|
+
const search = useCallback4(
|
|
2737
|
+
(query) => {
|
|
2738
|
+
if (!query.trim()) {
|
|
2739
|
+
return [];
|
|
2740
|
+
}
|
|
2741
|
+
try {
|
|
2742
|
+
const injector = createMemoryInjector2(projectPath);
|
|
2743
|
+
const results = injector.search(query, {
|
|
2744
|
+
includeGlobal: true,
|
|
2745
|
+
maxLearnings: 50,
|
|
2746
|
+
minRelevance: 0
|
|
2747
|
+
});
|
|
2748
|
+
return results.map((r) => r.learning);
|
|
2749
|
+
} catch {
|
|
2750
|
+
return [];
|
|
2751
|
+
}
|
|
2752
|
+
},
|
|
2753
|
+
[projectPath]
|
|
2754
|
+
);
|
|
2755
|
+
const deleteLearning = useCallback4(
|
|
2756
|
+
(id) => {
|
|
2757
|
+
try {
|
|
2758
|
+
const store = new LearningStore2(
|
|
2759
|
+
isGlobal ? "global" : "project",
|
|
2760
|
+
isGlobal ? void 0 : projectPath
|
|
2761
|
+
);
|
|
2762
|
+
const result = store.delete(id);
|
|
2763
|
+
if (result) {
|
|
2764
|
+
refresh();
|
|
2765
|
+
}
|
|
2766
|
+
return result;
|
|
2767
|
+
} catch {
|
|
2768
|
+
return false;
|
|
2769
|
+
}
|
|
2770
|
+
},
|
|
2771
|
+
[projectPath, isGlobal, refresh]
|
|
2772
|
+
);
|
|
2773
|
+
const deleteObservation = useCallback4(
|
|
2774
|
+
(id) => {
|
|
2775
|
+
try {
|
|
2776
|
+
const store = new ObservationStore2(projectPath);
|
|
2777
|
+
const result = store.delete(id);
|
|
2778
|
+
if (result) {
|
|
2779
|
+
refresh();
|
|
2780
|
+
}
|
|
2781
|
+
return result;
|
|
2782
|
+
} catch {
|
|
2783
|
+
return false;
|
|
2784
|
+
}
|
|
2785
|
+
},
|
|
2786
|
+
[projectPath, refresh]
|
|
2787
|
+
);
|
|
2788
|
+
useEffect14(() => {
|
|
2789
|
+
refresh();
|
|
2790
|
+
}, [refresh]);
|
|
2791
|
+
return {
|
|
2792
|
+
learnings,
|
|
2793
|
+
observations,
|
|
2794
|
+
status,
|
|
2795
|
+
loading,
|
|
2796
|
+
error,
|
|
2797
|
+
isGlobal,
|
|
2798
|
+
setIsGlobal,
|
|
2799
|
+
refresh,
|
|
2800
|
+
search,
|
|
2801
|
+
deleteLearning,
|
|
2802
|
+
deleteObservation
|
|
2803
|
+
};
|
|
2804
|
+
}
|
|
2805
|
+
|
|
2086
2806
|
// src/index.tsx
|
|
2087
|
-
import { jsx as
|
|
2807
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
2088
2808
|
function startTUI() {
|
|
2089
2809
|
process.stdout.write("\x1B[2J\x1B[0f");
|
|
2090
|
-
const { waitUntilExit, clear } = render(/* @__PURE__ */
|
|
2810
|
+
const { waitUntilExit, clear } = render(/* @__PURE__ */ jsx20(App, {}), {
|
|
2091
2811
|
exitOnCtrlC: true
|
|
2092
2812
|
});
|
|
2093
2813
|
return waitUntilExit().then(() => {
|
|
@@ -2098,9 +2818,13 @@ export {
|
|
|
2098
2818
|
App,
|
|
2099
2819
|
Browse,
|
|
2100
2820
|
Context,
|
|
2821
|
+
Execute,
|
|
2101
2822
|
Header,
|
|
2823
|
+
History,
|
|
2102
2824
|
Home,
|
|
2103
2825
|
Installed,
|
|
2826
|
+
Marketplace,
|
|
2827
|
+
Memory,
|
|
2104
2828
|
Recommend,
|
|
2105
2829
|
SearchInput,
|
|
2106
2830
|
Settings,
|
|
@@ -2109,6 +2833,7 @@ export {
|
|
|
2109
2833
|
StatusBar,
|
|
2110
2834
|
Sync,
|
|
2111
2835
|
Translate,
|
|
2836
|
+
Workflow,
|
|
2112
2837
|
colors,
|
|
2113
2838
|
logo,
|
|
2114
2839
|
startTUI,
|
|
@@ -2116,6 +2841,7 @@ export {
|
|
|
2116
2841
|
useKeyboard,
|
|
2117
2842
|
useListNavigation,
|
|
2118
2843
|
useMarketplace,
|
|
2844
|
+
useMemory,
|
|
2119
2845
|
useRecommend,
|
|
2120
2846
|
useSkills
|
|
2121
2847
|
};
|