@cockpit-ai/agents 0.1.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/dist/index.d.ts +67 -0
- package/dist/index.js +138 -0
- package/dist/index.js.map +1 -0
- package/package.json +39 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { ResolvedAgent, AgentStatus } from '@cockpit-ai/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Load a single agent from a YAML file and resolve it to ResolvedAgent.
|
|
5
|
+
* Throws ConfigLoadError or ConfigValidationError on failure.
|
|
6
|
+
*/
|
|
7
|
+
declare function loadAgentFromFile(filePath: string): ResolvedAgent;
|
|
8
|
+
/**
|
|
9
|
+
* Load all agents from a directory (*.yaml, *.yml files).
|
|
10
|
+
* Skips files that fail to load, collecting errors separately.
|
|
11
|
+
*/
|
|
12
|
+
declare function loadAgentsFromDir(dirPath: string): {
|
|
13
|
+
agents: ResolvedAgent[];
|
|
14
|
+
errors: Array<{
|
|
15
|
+
file: string;
|
|
16
|
+
error: unknown;
|
|
17
|
+
}>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
declare class AgentRegistry {
|
|
21
|
+
private agents;
|
|
22
|
+
add(agent: ResolvedAgent): void;
|
|
23
|
+
get(name: string): ResolvedAgent | undefined;
|
|
24
|
+
has(name: string): boolean;
|
|
25
|
+
list(): ResolvedAgent[];
|
|
26
|
+
remove(name: string): boolean;
|
|
27
|
+
size(): number;
|
|
28
|
+
/**
|
|
29
|
+
* Load all agents from one or more directories into the registry.
|
|
30
|
+
* Returns any load errors encountered.
|
|
31
|
+
*/
|
|
32
|
+
loadFromDirs(dirs: string[]): Array<{
|
|
33
|
+
file: string;
|
|
34
|
+
error: unknown;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
interface AgentStateEntry {
|
|
39
|
+
status: AgentStatus;
|
|
40
|
+
startedAt?: string;
|
|
41
|
+
stoppedAt?: string;
|
|
42
|
+
pid?: number;
|
|
43
|
+
}
|
|
44
|
+
interface AgentState {
|
|
45
|
+
agents: Record<string, AgentStateEntry>;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Read the agent state from disk.
|
|
49
|
+
* Returns an empty state if the file does not exist.
|
|
50
|
+
*/
|
|
51
|
+
declare function readAgentState(): AgentState;
|
|
52
|
+
/**
|
|
53
|
+
* Write the agent state to disk.
|
|
54
|
+
* Creates the ~/.cockpit directory if it does not exist.
|
|
55
|
+
*/
|
|
56
|
+
declare function writeAgentState(state: AgentState): void;
|
|
57
|
+
/**
|
|
58
|
+
* Set the status for a named agent, updating timestamps as appropriate.
|
|
59
|
+
*/
|
|
60
|
+
declare function setAgentStatus(name: string, status: AgentStatus): void;
|
|
61
|
+
/**
|
|
62
|
+
* Get the current status for a named agent.
|
|
63
|
+
* Returns "idle" if no state has been recorded.
|
|
64
|
+
*/
|
|
65
|
+
declare function getAgentStatus(name: string): AgentStatus;
|
|
66
|
+
|
|
67
|
+
export { AgentRegistry, getAgentStatus, loadAgentFromFile, loadAgentsFromDir, readAgentState, setAgentStatus, writeAgentState };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// src/loader.ts
|
|
2
|
+
import { readdirSync, existsSync } from "fs";
|
|
3
|
+
import { join, extname } from "path";
|
|
4
|
+
import {
|
|
5
|
+
loadConfig,
|
|
6
|
+
ConfigLoadError,
|
|
7
|
+
ConfigValidationError,
|
|
8
|
+
AgentDefinitionSchema
|
|
9
|
+
} from "@cockpit-ai/core";
|
|
10
|
+
function loadAgentFromFile(filePath) {
|
|
11
|
+
const raw = loadConfig(filePath, AgentDefinitionSchema);
|
|
12
|
+
return {
|
|
13
|
+
name: raw.name,
|
|
14
|
+
role: raw.role,
|
|
15
|
+
model: raw.model,
|
|
16
|
+
skills: raw.skills ?? [],
|
|
17
|
+
contextIncludes: raw.context?.include ?? [],
|
|
18
|
+
contextRules: raw.context?.rules ?? [],
|
|
19
|
+
worktreeConfig: {
|
|
20
|
+
autoCreate: raw.worktree?.auto_create ?? false,
|
|
21
|
+
branchPrefix: raw.worktree?.branch_prefix
|
|
22
|
+
},
|
|
23
|
+
sourcePath: filePath,
|
|
24
|
+
status: "idle"
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function loadAgentsFromDir(dirPath) {
|
|
28
|
+
if (!existsSync(dirPath)) {
|
|
29
|
+
return { agents: [], errors: [] };
|
|
30
|
+
}
|
|
31
|
+
const agents = [];
|
|
32
|
+
const errors = [];
|
|
33
|
+
for (const entry of readdirSync(dirPath, { withFileTypes: true })) {
|
|
34
|
+
if (!entry.isFile()) continue;
|
|
35
|
+
const ext = extname(entry.name);
|
|
36
|
+
if (ext !== ".yaml" && ext !== ".yml") continue;
|
|
37
|
+
const filePath = join(dirPath, entry.name);
|
|
38
|
+
try {
|
|
39
|
+
agents.push(loadAgentFromFile(filePath));
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (err instanceof ConfigLoadError || err instanceof ConfigValidationError) {
|
|
42
|
+
errors.push({ file: filePath, error: err });
|
|
43
|
+
} else {
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return { agents, errors };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/registry.ts
|
|
52
|
+
var AgentRegistry = class {
|
|
53
|
+
agents = /* @__PURE__ */ new Map();
|
|
54
|
+
add(agent) {
|
|
55
|
+
this.agents.set(agent.name, agent);
|
|
56
|
+
}
|
|
57
|
+
get(name) {
|
|
58
|
+
return this.agents.get(name);
|
|
59
|
+
}
|
|
60
|
+
has(name) {
|
|
61
|
+
return this.agents.has(name);
|
|
62
|
+
}
|
|
63
|
+
list() {
|
|
64
|
+
return [...this.agents.values()];
|
|
65
|
+
}
|
|
66
|
+
remove(name) {
|
|
67
|
+
return this.agents.delete(name);
|
|
68
|
+
}
|
|
69
|
+
size() {
|
|
70
|
+
return this.agents.size;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Load all agents from one or more directories into the registry.
|
|
74
|
+
* Returns any load errors encountered.
|
|
75
|
+
*/
|
|
76
|
+
loadFromDirs(dirs) {
|
|
77
|
+
const allErrors = [];
|
|
78
|
+
for (const dir of dirs) {
|
|
79
|
+
const { agents, errors } = loadAgentsFromDir(dir);
|
|
80
|
+
for (const agent of agents) {
|
|
81
|
+
this.add(agent);
|
|
82
|
+
}
|
|
83
|
+
allErrors.push(...errors);
|
|
84
|
+
}
|
|
85
|
+
return allErrors;
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// src/state.ts
|
|
90
|
+
import { readFileSync, writeFileSync, mkdirSync, existsSync as existsSync2 } from "fs";
|
|
91
|
+
import { join as join2, dirname } from "path";
|
|
92
|
+
import { homedir } from "os";
|
|
93
|
+
var STATE_FILE = join2(homedir(), ".cockpit", "agent-state.json");
|
|
94
|
+
function readAgentState() {
|
|
95
|
+
if (!existsSync2(STATE_FILE)) {
|
|
96
|
+
return { agents: {} };
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
const raw = readFileSync(STATE_FILE, "utf-8");
|
|
100
|
+
return JSON.parse(raw);
|
|
101
|
+
} catch {
|
|
102
|
+
return { agents: {} };
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
function writeAgentState(state) {
|
|
106
|
+
const dir = dirname(STATE_FILE);
|
|
107
|
+
if (!existsSync2(dir)) {
|
|
108
|
+
mkdirSync(dir, { recursive: true });
|
|
109
|
+
}
|
|
110
|
+
writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), "utf-8");
|
|
111
|
+
}
|
|
112
|
+
function setAgentStatus(name, status) {
|
|
113
|
+
const state = readAgentState();
|
|
114
|
+
const existing = state.agents[name] ?? { status: "idle" };
|
|
115
|
+
const updated = { ...existing, status };
|
|
116
|
+
if (status === "running") {
|
|
117
|
+
updated.startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
118
|
+
delete updated.stoppedAt;
|
|
119
|
+
} else if (status === "stopped" || status === "error") {
|
|
120
|
+
updated.stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
121
|
+
}
|
|
122
|
+
state.agents[name] = updated;
|
|
123
|
+
writeAgentState(state);
|
|
124
|
+
}
|
|
125
|
+
function getAgentStatus(name) {
|
|
126
|
+
const state = readAgentState();
|
|
127
|
+
return state.agents[name]?.status ?? "idle";
|
|
128
|
+
}
|
|
129
|
+
export {
|
|
130
|
+
AgentRegistry,
|
|
131
|
+
getAgentStatus,
|
|
132
|
+
loadAgentFromFile,
|
|
133
|
+
loadAgentsFromDir,
|
|
134
|
+
readAgentState,
|
|
135
|
+
setAgentStatus,
|
|
136
|
+
writeAgentState
|
|
137
|
+
};
|
|
138
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/loader.ts","../src/registry.ts","../src/state.ts"],"sourcesContent":["import { readdirSync, existsSync } from \"node:fs\";\nimport { join, extname } from \"node:path\";\nimport {\n loadConfig,\n ConfigLoadError,\n ConfigValidationError,\n AgentDefinitionSchema,\n type ResolvedAgent,\n} from \"@cockpit-ai/core\";\n\n// ─── Agent Loader ───────────────────────────────────────────────────────────\n\n/**\n * Load a single agent from a YAML file and resolve it to ResolvedAgent.\n * Throws ConfigLoadError or ConfigValidationError on failure.\n */\nexport function loadAgentFromFile(filePath: string): ResolvedAgent {\n const raw = loadConfig(filePath, AgentDefinitionSchema);\n\n return {\n name: raw.name,\n role: raw.role,\n model: raw.model,\n skills: raw.skills ?? [],\n contextIncludes: raw.context?.include ?? [],\n contextRules: raw.context?.rules ?? [],\n worktreeConfig: {\n autoCreate: raw.worktree?.auto_create ?? false,\n branchPrefix: raw.worktree?.branch_prefix,\n },\n sourcePath: filePath,\n status: \"idle\",\n };\n}\n\n/**\n * Load all agents from a directory (*.yaml, *.yml files).\n * Skips files that fail to load, collecting errors separately.\n */\nexport function loadAgentsFromDir(dirPath: string): {\n agents: ResolvedAgent[];\n errors: Array<{ file: string; error: unknown }>;\n} {\n if (!existsSync(dirPath)) {\n return { agents: [], errors: [] };\n }\n\n const agents: ResolvedAgent[] = [];\n const errors: Array<{ file: string; error: unknown }> = [];\n\n for (const entry of readdirSync(dirPath, { withFileTypes: true })) {\n if (!entry.isFile()) continue;\n const ext = extname(entry.name);\n if (ext !== \".yaml\" && ext !== \".yml\") continue;\n\n const filePath = join(dirPath, entry.name);\n try {\n agents.push(loadAgentFromFile(filePath));\n } catch (err) {\n if (err instanceof ConfigLoadError || err instanceof ConfigValidationError) {\n errors.push({ file: filePath, error: err });\n } else {\n throw err;\n }\n }\n }\n\n return { agents, errors };\n}\n","import { type ResolvedAgent } from \"@cockpit-ai/core\";\nimport { loadAgentsFromDir } from \"./loader.js\";\n\n// ─── Agent Registry ─────────────────────────────────────────────────────────\n\nexport class AgentRegistry {\n private agents = new Map<string, ResolvedAgent>();\n\n add(agent: ResolvedAgent): void {\n this.agents.set(agent.name, agent);\n }\n\n get(name: string): ResolvedAgent | undefined {\n return this.agents.get(name);\n }\n\n has(name: string): boolean {\n return this.agents.has(name);\n }\n\n list(): ResolvedAgent[] {\n return [...this.agents.values()];\n }\n\n remove(name: string): boolean {\n return this.agents.delete(name);\n }\n\n size(): number {\n return this.agents.size;\n }\n\n /**\n * Load all agents from one or more directories into the registry.\n * Returns any load errors encountered.\n */\n loadFromDirs(dirs: string[]): Array<{ file: string; error: unknown }> {\n const allErrors: Array<{ file: string; error: unknown }> = [];\n\n for (const dir of dirs) {\n const { agents, errors } = loadAgentsFromDir(dir);\n for (const agent of agents) {\n this.add(agent);\n }\n allErrors.push(...errors);\n }\n\n return allErrors;\n }\n}\n","import { readFileSync, writeFileSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { type AgentStatus } from \"@cockpit-ai/core\";\n\n// ─── Agent State ────────────────────────────────────────────────────────────\n\nconst STATE_FILE = join(homedir(), \".cockpit\", \"agent-state.json\");\n\ninterface AgentStateEntry {\n status: AgentStatus;\n startedAt?: string;\n stoppedAt?: string;\n pid?: number;\n}\n\ninterface AgentState {\n agents: Record<string, AgentStateEntry>;\n}\n\n/**\n * Read the agent state from disk.\n * Returns an empty state if the file does not exist.\n */\nexport function readAgentState(): AgentState {\n if (!existsSync(STATE_FILE)) {\n return { agents: {} };\n }\n\n try {\n const raw = readFileSync(STATE_FILE, \"utf-8\");\n return JSON.parse(raw) as AgentState;\n } catch {\n return { agents: {} };\n }\n}\n\n/**\n * Write the agent state to disk.\n * Creates the ~/.cockpit directory if it does not exist.\n */\nexport function writeAgentState(state: AgentState): void {\n const dir = dirname(STATE_FILE);\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), \"utf-8\");\n}\n\n/**\n * Set the status for a named agent, updating timestamps as appropriate.\n */\nexport function setAgentStatus(name: string, status: AgentStatus): void {\n const state = readAgentState();\n const existing = state.agents[name] ?? { status: \"idle\" };\n\n const updated: AgentStateEntry = { ...existing, status };\n\n if (status === \"running\") {\n updated.startedAt = new Date().toISOString();\n delete updated.stoppedAt;\n } else if (status === \"stopped\" || status === \"error\") {\n updated.stoppedAt = new Date().toISOString();\n }\n\n state.agents[name] = updated;\n writeAgentState(state);\n}\n\n/**\n * Get the current status for a named agent.\n * Returns \"idle\" if no state has been recorded.\n */\nexport function getAgentStatus(name: string): AgentStatus {\n const state = readAgentState();\n return state.agents[name]?.status ?? \"idle\";\n}\n"],"mappings":";AAAA,SAAS,aAAa,kBAAkB;AACxC,SAAS,MAAM,eAAe;AAC9B;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AAQA,SAAS,kBAAkB,UAAiC;AACjE,QAAM,MAAM,WAAW,UAAU,qBAAqB;AAEtD,SAAO;AAAA,IACL,MAAM,IAAI;AAAA,IACV,MAAM,IAAI;AAAA,IACV,OAAO,IAAI;AAAA,IACX,QAAQ,IAAI,UAAU,CAAC;AAAA,IACvB,iBAAiB,IAAI,SAAS,WAAW,CAAC;AAAA,IAC1C,cAAc,IAAI,SAAS,SAAS,CAAC;AAAA,IACrC,gBAAgB;AAAA,MACd,YAAY,IAAI,UAAU,eAAe;AAAA,MACzC,cAAc,IAAI,UAAU;AAAA,IAC9B;AAAA,IACA,YAAY;AAAA,IACZ,QAAQ;AAAA,EACV;AACF;AAMO,SAAS,kBAAkB,SAGhC;AACA,MAAI,CAAC,WAAW,OAAO,GAAG;AACxB,WAAO,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE;AAAA,EAClC;AAEA,QAAM,SAA0B,CAAC;AACjC,QAAM,SAAkD,CAAC;AAEzD,aAAW,SAAS,YAAY,SAAS,EAAE,eAAe,KAAK,CAAC,GAAG;AACjE,QAAI,CAAC,MAAM,OAAO,EAAG;AACrB,UAAM,MAAM,QAAQ,MAAM,IAAI;AAC9B,QAAI,QAAQ,WAAW,QAAQ,OAAQ;AAEvC,UAAM,WAAW,KAAK,SAAS,MAAM,IAAI;AACzC,QAAI;AACF,aAAO,KAAK,kBAAkB,QAAQ,CAAC;AAAA,IACzC,SAAS,KAAK;AACZ,UAAI,eAAe,mBAAmB,eAAe,uBAAuB;AAC1E,eAAO,KAAK,EAAE,MAAM,UAAU,OAAO,IAAI,CAAC;AAAA,MAC5C,OAAO;AACL,cAAM;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ,OAAO;AAC1B;;;AC/DO,IAAM,gBAAN,MAAoB;AAAA,EACjB,SAAS,oBAAI,IAA2B;AAAA,EAEhD,IAAI,OAA4B;AAC9B,SAAK,OAAO,IAAI,MAAM,MAAM,KAAK;AAAA,EACnC;AAAA,EAEA,IAAI,MAAyC;AAC3C,WAAO,KAAK,OAAO,IAAI,IAAI;AAAA,EAC7B;AAAA,EAEA,IAAI,MAAuB;AACzB,WAAO,KAAK,OAAO,IAAI,IAAI;AAAA,EAC7B;AAAA,EAEA,OAAwB;AACtB,WAAO,CAAC,GAAG,KAAK,OAAO,OAAO,CAAC;AAAA,EACjC;AAAA,EAEA,OAAO,MAAuB;AAC5B,WAAO,KAAK,OAAO,OAAO,IAAI;AAAA,EAChC;AAAA,EAEA,OAAe;AACb,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,aAAa,MAAyD;AACpE,UAAM,YAAqD,CAAC;AAE5D,eAAW,OAAO,MAAM;AACtB,YAAM,EAAE,QAAQ,OAAO,IAAI,kBAAkB,GAAG;AAChD,iBAAW,SAAS,QAAQ;AAC1B,aAAK,IAAI,KAAK;AAAA,MAChB;AACA,gBAAU,KAAK,GAAG,MAAM;AAAA,IAC1B;AAEA,WAAO;AAAA,EACT;AACF;;;ACjDA,SAAS,cAAc,eAAe,WAAW,cAAAA,mBAAkB;AACnE,SAAS,QAAAC,OAAM,eAAe;AAC9B,SAAS,eAAe;AAKxB,IAAM,aAAaA,MAAK,QAAQ,GAAG,YAAY,kBAAkB;AAiB1D,SAAS,iBAA6B;AAC3C,MAAI,CAACD,YAAW,UAAU,GAAG;AAC3B,WAAO,EAAE,QAAQ,CAAC,EAAE;AAAA,EACtB;AAEA,MAAI;AACF,UAAM,MAAM,aAAa,YAAY,OAAO;AAC5C,WAAO,KAAK,MAAM,GAAG;AAAA,EACvB,QAAQ;AACN,WAAO,EAAE,QAAQ,CAAC,EAAE;AAAA,EACtB;AACF;AAMO,SAAS,gBAAgB,OAAyB;AACvD,QAAM,MAAM,QAAQ,UAAU;AAC9B,MAAI,CAACA,YAAW,GAAG,GAAG;AACpB,cAAU,KAAK,EAAE,WAAW,KAAK,CAAC;AAAA,EACpC;AACA,gBAAc,YAAY,KAAK,UAAU,OAAO,MAAM,CAAC,GAAG,OAAO;AACnE;AAKO,SAAS,eAAe,MAAc,QAA2B;AACtE,QAAM,QAAQ,eAAe;AAC7B,QAAM,WAAW,MAAM,OAAO,IAAI,KAAK,EAAE,QAAQ,OAAO;AAExD,QAAM,UAA2B,EAAE,GAAG,UAAU,OAAO;AAEvD,MAAI,WAAW,WAAW;AACxB,YAAQ,aAAY,oBAAI,KAAK,GAAE,YAAY;AAC3C,WAAO,QAAQ;AAAA,EACjB,WAAW,WAAW,aAAa,WAAW,SAAS;AACrD,YAAQ,aAAY,oBAAI,KAAK,GAAE,YAAY;AAAA,EAC7C;AAEA,QAAM,OAAO,IAAI,IAAI;AACrB,kBAAgB,KAAK;AACvB;AAMO,SAAS,eAAe,MAA2B;AACxD,QAAM,QAAQ,eAAe;AAC7B,SAAO,MAAM,OAAO,IAAI,GAAG,UAAU;AACvC;","names":["existsSync","join"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cockpit-ai/agents",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Cockpit agent loader and registry",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"main": "./dist/index.js",
|
|
16
|
+
"types": "./dist/index.d.ts",
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@cockpit-ai/core": "0.1.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20.0.0",
|
|
28
|
+
"tsup": "^8.0.0",
|
|
29
|
+
"typescript": "^5.5.0",
|
|
30
|
+
"vitest": "^2.0.0"
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"build": "tsup",
|
|
34
|
+
"dev": "tsup --watch",
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"test:watch": "vitest",
|
|
37
|
+
"clean": "rm -rf dist"
|
|
38
|
+
}
|
|
39
|
+
}
|