create-expert 0.0.22 → 0.0.23
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/bin/cli.js +51 -26
- package/dist/bin/cli.js.map +1 -1
- package/package.json +4 -4
package/dist/bin/cli.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { readFileSync, existsSync, mkdirSync, writeFileSync, readdirSync } from 'fs';
|
|
3
|
-
import { parseWithFriendlyError, perstackConfigSchema, startCommandInputSchema, defaultMaxRetries, defaultTimeout, checkpointSchema, jobSchema, runSettingSchema, BASE_SKILL_PREFIX, createBaseToolActivity, createGeneralToolActivity } from '@perstack/core';
|
|
3
|
+
import { parseWithFriendlyError, perstackConfigSchema, startCommandInputSchema, defaultMaxRetries, defaultTimeout, checkpointSchema, lockfileSchema, jobSchema, runSettingSchema, BASE_SKILL_PREFIX, createBaseToolActivity, createGeneralToolActivity } from '@perstack/core';
|
|
4
4
|
import { readFile, mkdir, writeFile } from 'fs/promises';
|
|
5
|
-
import
|
|
6
|
-
import {
|
|
5
|
+
import path6 from 'path';
|
|
6
|
+
import { runtimeVersion, run } from '@perstack/runtime';
|
|
7
7
|
import dotenv from 'dotenv';
|
|
8
8
|
import TOML from 'smol-toml';
|
|
9
9
|
import { render, useApp, useInput, Box, Text } from 'ink';
|
|
@@ -1728,12 +1728,12 @@ function storeJob(job) {
|
|
|
1728
1728
|
if (!existsSync(jobDir)) {
|
|
1729
1729
|
mkdirSync(jobDir, { recursive: true });
|
|
1730
1730
|
}
|
|
1731
|
-
const jobPath =
|
|
1731
|
+
const jobPath = path6.resolve(jobDir, "job.json");
|
|
1732
1732
|
writeFileSync(jobPath, JSON.stringify(job, null, 2));
|
|
1733
1733
|
}
|
|
1734
1734
|
function retrieveJob(jobId) {
|
|
1735
1735
|
const jobDir = getJobDir(jobId);
|
|
1736
|
-
const jobPath =
|
|
1736
|
+
const jobPath = path6.resolve(jobDir, "job.json");
|
|
1737
1737
|
if (!existsSync(jobPath)) {
|
|
1738
1738
|
return void 0;
|
|
1739
1739
|
}
|
|
@@ -1751,7 +1751,7 @@ function getAllJobs() {
|
|
|
1751
1751
|
}
|
|
1752
1752
|
const jobs = [];
|
|
1753
1753
|
for (const jobDirName of jobDirNames) {
|
|
1754
|
-
const jobPath =
|
|
1754
|
+
const jobPath = path6.resolve(jobsDir, jobDirName, "job.json");
|
|
1755
1755
|
if (!existsSync(jobPath)) {
|
|
1756
1756
|
continue;
|
|
1757
1757
|
}
|
|
@@ -1812,7 +1812,7 @@ function getCheckpointsByJobId(jobId) {
|
|
|
1812
1812
|
const checkpoints = [];
|
|
1813
1813
|
for (const file of files) {
|
|
1814
1814
|
try {
|
|
1815
|
-
const content = readFileSync(
|
|
1815
|
+
const content = readFileSync(path6.resolve(checkpointDir, file), "utf-8");
|
|
1816
1816
|
checkpoints.push(checkpointSchema.parse(JSON.parse(content)));
|
|
1817
1817
|
} catch {
|
|
1818
1818
|
}
|
|
@@ -1833,13 +1833,13 @@ function getAllRuns() {
|
|
|
1833
1833
|
}
|
|
1834
1834
|
const runs = [];
|
|
1835
1835
|
for (const jobDirName of jobDirNames) {
|
|
1836
|
-
const runsDir =
|
|
1836
|
+
const runsDir = path6.resolve(jobsDir, jobDirName, "runs");
|
|
1837
1837
|
if (!existsSync(runsDir)) {
|
|
1838
1838
|
continue;
|
|
1839
1839
|
}
|
|
1840
1840
|
const runDirNames = readdirSync(runsDir, { withFileTypes: true }).filter((dir) => dir.isDirectory()).map((dir) => dir.name);
|
|
1841
1841
|
for (const runDirName of runDirNames) {
|
|
1842
|
-
const runSettingPath =
|
|
1842
|
+
const runSettingPath = path6.resolve(runsDir, runDirName, "run-setting.json");
|
|
1843
1843
|
if (!existsSync(runSettingPath)) {
|
|
1844
1844
|
continue;
|
|
1845
1845
|
}
|
|
@@ -1873,7 +1873,7 @@ function getEventContents(jobId, runId, maxStepNumber) {
|
|
|
1873
1873
|
const events = [];
|
|
1874
1874
|
for (const { file } of eventFiles) {
|
|
1875
1875
|
try {
|
|
1876
|
-
const content = readFileSync(
|
|
1876
|
+
const content = readFileSync(path6.resolve(runDir, file), "utf-8");
|
|
1877
1877
|
events.push(JSON.parse(content));
|
|
1878
1878
|
} catch {
|
|
1879
1879
|
}
|
|
@@ -1881,7 +1881,7 @@ function getEventContents(jobId, runId, maxStepNumber) {
|
|
|
1881
1881
|
return events;
|
|
1882
1882
|
}
|
|
1883
1883
|
function getRunIdsByJobId(jobId) {
|
|
1884
|
-
const runsDir =
|
|
1884
|
+
const runsDir = path6.resolve(getJobDir(jobId), "runs");
|
|
1885
1885
|
if (!existsSync(runsDir)) {
|
|
1886
1886
|
return [];
|
|
1887
1887
|
}
|
|
@@ -1936,23 +1936,23 @@ async function findPerstackConfigString(configPath) {
|
|
|
1936
1936
|
return await fetchRemoteConfig(configPath);
|
|
1937
1937
|
}
|
|
1938
1938
|
try {
|
|
1939
|
-
const tomlString = await readFile(
|
|
1939
|
+
const tomlString = await readFile(path6.resolve(process.cwd(), configPath), "utf-8");
|
|
1940
1940
|
return tomlString;
|
|
1941
1941
|
} catch {
|
|
1942
1942
|
throw new Error(`Given config path "${configPath}" is not found`);
|
|
1943
1943
|
}
|
|
1944
1944
|
}
|
|
1945
|
-
return await findPerstackConfigStringRecursively(
|
|
1945
|
+
return await findPerstackConfigStringRecursively(path6.resolve(process.cwd()));
|
|
1946
1946
|
}
|
|
1947
1947
|
async function findPerstackConfigStringRecursively(cwd) {
|
|
1948
1948
|
try {
|
|
1949
|
-
const tomlString = await readFile(
|
|
1949
|
+
const tomlString = await readFile(path6.resolve(cwd, "perstack.toml"), "utf-8");
|
|
1950
1950
|
return tomlString;
|
|
1951
1951
|
} catch {
|
|
1952
|
-
if (cwd ===
|
|
1952
|
+
if (cwd === path6.parse(cwd).root) {
|
|
1953
1953
|
return null;
|
|
1954
1954
|
}
|
|
1955
|
-
return await findPerstackConfigStringRecursively(
|
|
1955
|
+
return await findPerstackConfigStringRecursively(path6.dirname(cwd));
|
|
1956
1956
|
}
|
|
1957
1957
|
}
|
|
1958
1958
|
async function parsePerstackConfig(config2) {
|
|
@@ -2168,6 +2168,7 @@ async function resolveRunContext(input) {
|
|
|
2168
2168
|
{
|
|
2169
2169
|
name,
|
|
2170
2170
|
version: expert.version ?? "1.0.0",
|
|
2171
|
+
minRuntimeVersion: expert.minRuntimeVersion,
|
|
2171
2172
|
description: expert.description,
|
|
2172
2173
|
instruction: expert.instruction,
|
|
2173
2174
|
skills: expert.skills,
|
|
@@ -2210,6 +2211,30 @@ function parseInteractiveToolCallResult(query, checkpoint) {
|
|
|
2210
2211
|
}
|
|
2211
2212
|
};
|
|
2212
2213
|
}
|
|
2214
|
+
function loadLockfile(lockfilePath) {
|
|
2215
|
+
try {
|
|
2216
|
+
const content = readFileSync(lockfilePath, "utf-8");
|
|
2217
|
+
const parsed = TOML.parse(content);
|
|
2218
|
+
return parseWithFriendlyError(lockfileSchema, parsed, "perstack.lock");
|
|
2219
|
+
} catch {
|
|
2220
|
+
return null;
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
function findLockfile(configPath) {
|
|
2224
|
+
return findLockfileRecursively(process.cwd());
|
|
2225
|
+
}
|
|
2226
|
+
function findLockfileRecursively(cwd) {
|
|
2227
|
+
const lockfilePath = path6.resolve(cwd, "perstack.lock");
|
|
2228
|
+
try {
|
|
2229
|
+
readFileSync(lockfilePath);
|
|
2230
|
+
return lockfilePath;
|
|
2231
|
+
} catch {
|
|
2232
|
+
if (cwd === path6.parse(cwd).root) {
|
|
2233
|
+
return null;
|
|
2234
|
+
}
|
|
2235
|
+
return findLockfileRecursively(path6.dirname(cwd));
|
|
2236
|
+
}
|
|
2237
|
+
}
|
|
2213
2238
|
|
|
2214
2239
|
// ../../packages/tui-components/src/utils/event-queue.ts
|
|
2215
2240
|
var defaultErrorLogger = (message, error) => {
|
|
@@ -3533,7 +3558,7 @@ function renderTodo(action, color) {
|
|
|
3533
3558
|
] }) });
|
|
3534
3559
|
}
|
|
3535
3560
|
function renderReadTextFile(action, color) {
|
|
3536
|
-
const { path:
|
|
3561
|
+
const { path: path7, content, from, to } = action;
|
|
3537
3562
|
const lineRange = from !== void 0 && to !== void 0 ? `#${from}-${to}` : "";
|
|
3538
3563
|
const lines = content?.split("\n") ?? [];
|
|
3539
3564
|
return /* @__PURE__ */ jsx(
|
|
@@ -3541,24 +3566,24 @@ function renderReadTextFile(action, color) {
|
|
|
3541
3566
|
{
|
|
3542
3567
|
indicatorColor: color,
|
|
3543
3568
|
label: "Read Text File",
|
|
3544
|
-
summary: `${shortenPath(
|
|
3569
|
+
summary: `${shortenPath(path7)}${lineRange}`,
|
|
3545
3570
|
children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsx(Box, { flexDirection: "row", gap: 1, children: /* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: line }) }, `read-${idx}`)) })
|
|
3546
3571
|
}
|
|
3547
3572
|
);
|
|
3548
3573
|
}
|
|
3549
3574
|
function renderWriteTextFile(action, color) {
|
|
3550
|
-
const { path:
|
|
3575
|
+
const { path: path7, text } = action;
|
|
3551
3576
|
const lines = text.split("\n");
|
|
3552
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Write Text File", summary: shortenPath(
|
|
3577
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Write Text File", summary: shortenPath(path7), children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
3553
3578
|
/* @__PURE__ */ jsx(Text, { color: "green", dimColor: true, children: "+" }),
|
|
3554
3579
|
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: line })
|
|
3555
3580
|
] }, `write-${idx}`)) }) });
|
|
3556
3581
|
}
|
|
3557
3582
|
function renderEditTextFile(action, color) {
|
|
3558
|
-
const { path:
|
|
3583
|
+
const { path: path7, oldText, newText } = action;
|
|
3559
3584
|
const oldLines = oldText.split("\n");
|
|
3560
3585
|
const newLines = newText.split("\n");
|
|
3561
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Edit Text File", summary: shortenPath(
|
|
3586
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Edit Text File", summary: shortenPath(path7), children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3562
3587
|
oldLines.map((line, idx) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
3563
3588
|
/* @__PURE__ */ jsx(Text, { color: "red", dimColor: true, children: "-" }),
|
|
3564
3589
|
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: line })
|
|
@@ -3570,18 +3595,18 @@ function renderEditTextFile(action, color) {
|
|
|
3570
3595
|
] }) });
|
|
3571
3596
|
}
|
|
3572
3597
|
function renderAppendTextFile(action, color) {
|
|
3573
|
-
const { path:
|
|
3598
|
+
const { path: path7, text } = action;
|
|
3574
3599
|
const lines = text.split("\n");
|
|
3575
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Append Text File", summary: shortenPath(
|
|
3600
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "Append Text File", summary: shortenPath(path7), children: /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: lines.map((line, idx) => /* @__PURE__ */ jsxs(Box, { flexDirection: "row", gap: 1, children: [
|
|
3576
3601
|
/* @__PURE__ */ jsx(Text, { color: "green", dimColor: true, children: "+" }),
|
|
3577
3602
|
/* @__PURE__ */ jsx(Text, { color: "white", dimColor: true, children: line })
|
|
3578
3603
|
] }, `append-${idx}`)) }) });
|
|
3579
3604
|
}
|
|
3580
3605
|
function renderListDirectory(action, color) {
|
|
3581
|
-
const { path:
|
|
3606
|
+
const { path: path7, items } = action;
|
|
3582
3607
|
const itemLines = items?.map((item) => `${item.type === "directory" ? "\u{1F4C1}" : "\u{1F4C4}"} ${item.name}`) ?? [];
|
|
3583
3608
|
const { visible, remaining } = summarizeOutput(itemLines, RENDER_CONSTANTS.LIST_DIR_MAX_ITEMS);
|
|
3584
|
-
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "List", summary: shortenPath(
|
|
3609
|
+
return /* @__PURE__ */ jsx(ActionRow, { indicatorColor: color, label: "List", summary: shortenPath(path7), children: /* @__PURE__ */ jsxs(Box, { flexDirection: "column", children: [
|
|
3585
3610
|
visible.map((line, idx) => /* @__PURE__ */ jsx(Text, { dimColor: true, children: truncateText(line, UI_CONSTANTS.TRUNCATE_TEXT_DEFAULT) }, `dir-${idx}`)),
|
|
3586
3611
|
remaining > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
|
|
3587
3612
|
"... +",
|