@harperfast/agent 0.16.1 → 0.16.2
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/agent.js +119 -43
- package/dist/schema.graphql +245 -0
- package/package.json +3 -2
package/dist/agent.js
CHANGED
|
@@ -875,9 +875,9 @@ async function execute10({ skill }) {
|
|
|
875
875
|
|
|
876
876
|
// tools/files/workspaceEditor.ts
|
|
877
877
|
import { applyDiff } from "@openai/agents";
|
|
878
|
-
import { existsSync as
|
|
878
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5 } from "fs";
|
|
879
879
|
import { mkdir, rm, writeFile } from "fs/promises";
|
|
880
|
-
import
|
|
880
|
+
import path5 from "path";
|
|
881
881
|
|
|
882
882
|
// utils/files/normalizeDiff.ts
|
|
883
883
|
function normalizeDiff(diff) {
|
|
@@ -993,6 +993,61 @@ function resolvePath(root, relativePath) {
|
|
|
993
993
|
return resolved;
|
|
994
994
|
}
|
|
995
995
|
|
|
996
|
+
// utils/files/validateGraphQL.ts
|
|
997
|
+
import { buildSchema, extendSchema, parse, validateSchema } from "graphql";
|
|
998
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4 } from "fs";
|
|
999
|
+
import path4 from "path";
|
|
1000
|
+
import { fileURLToPath } from "url";
|
|
1001
|
+
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
1002
|
+
var cachedSchema = null;
|
|
1003
|
+
function getHarperSchema(root) {
|
|
1004
|
+
if (cachedSchema) {
|
|
1005
|
+
return cachedSchema;
|
|
1006
|
+
}
|
|
1007
|
+
const paths = [
|
|
1008
|
+
path4.join(root, "node_modules", "harperdb", "schema.graphql"),
|
|
1009
|
+
path4.join(__dirname, "schema.graphql"),
|
|
1010
|
+
path4.join(__dirname, "..", "schema.graphql"),
|
|
1011
|
+
path4.join(__dirname, "..", "..", "schema.graphql")
|
|
1012
|
+
];
|
|
1013
|
+
for (const schemaPath of paths) {
|
|
1014
|
+
if (existsSync6(schemaPath)) {
|
|
1015
|
+
try {
|
|
1016
|
+
const schemaSource = readFileSync4(schemaPath, "utf8");
|
|
1017
|
+
cachedSchema = buildSchema(schemaSource, { assumeValidSDL: true });
|
|
1018
|
+
return cachedSchema;
|
|
1019
|
+
} catch (e) {
|
|
1020
|
+
console.error(`Error parsing HarperDB schema at ${schemaPath}:`, e);
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
return null;
|
|
1025
|
+
}
|
|
1026
|
+
function validateGraphQL(content, filePath, root) {
|
|
1027
|
+
if (!filePath.endsWith(".graphql")) {
|
|
1028
|
+
return null;
|
|
1029
|
+
}
|
|
1030
|
+
try {
|
|
1031
|
+
const document2 = parse(content);
|
|
1032
|
+
const schema = getHarperSchema(root);
|
|
1033
|
+
if (schema) {
|
|
1034
|
+
const extendedSchema = extendSchema(schema, document2, { assumeValidSDL: false });
|
|
1035
|
+
const errors = validateSchema(extendedSchema).filter(
|
|
1036
|
+
(e) => !e.message.includes("Query root type must be provided")
|
|
1037
|
+
);
|
|
1038
|
+
if (errors.length > 0) {
|
|
1039
|
+
return `GraphQL validation error in ${filePath}:
|
|
1040
|
+
${errors.map((e) => e.message).join("\n")}`;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
return null;
|
|
1044
|
+
} catch (err) {
|
|
1045
|
+
const message = err.message || String(err);
|
|
1046
|
+
const type = message.includes("Syntax Error") ? "syntax" : "validation";
|
|
1047
|
+
return `GraphQL ${type} error in ${filePath}: ${message}`;
|
|
1048
|
+
}
|
|
1049
|
+
}
|
|
1050
|
+
|
|
996
1051
|
// tools/files/workspaceEditor.ts
|
|
997
1052
|
var WorkspaceEditor = class {
|
|
998
1053
|
root;
|
|
@@ -1002,11 +1057,18 @@ var WorkspaceEditor = class {
|
|
|
1002
1057
|
async createFile(operation) {
|
|
1003
1058
|
try {
|
|
1004
1059
|
const targetPath = resolvePath(this.root(), operation.path);
|
|
1005
|
-
await mkdir(
|
|
1060
|
+
await mkdir(path5.dirname(targetPath), { recursive: true });
|
|
1006
1061
|
const normalizedDiff = normalizeDiff(operation.diff);
|
|
1007
1062
|
const content = applyDiff("", normalizedDiff, "create");
|
|
1008
1063
|
await writeFile(targetPath, content, "utf8");
|
|
1009
|
-
|
|
1064
|
+
let output = `Created ${operation.path}`;
|
|
1065
|
+
const validationError = validateGraphQL(content, operation.path, this.root());
|
|
1066
|
+
if (validationError) {
|
|
1067
|
+
output += `
|
|
1068
|
+
|
|
1069
|
+
${validationError}`;
|
|
1070
|
+
}
|
|
1071
|
+
return { status: "completed", output };
|
|
1010
1072
|
} catch (err) {
|
|
1011
1073
|
return { status: "failed", output: `Error creating ${operation.path}: ${String(err)}` };
|
|
1012
1074
|
}
|
|
@@ -1014,14 +1076,21 @@ var WorkspaceEditor = class {
|
|
|
1014
1076
|
async updateFile(operation) {
|
|
1015
1077
|
try {
|
|
1016
1078
|
const targetPath = resolvePath(this.root(), operation.path);
|
|
1017
|
-
if (!
|
|
1079
|
+
if (!existsSync7(targetPath)) {
|
|
1018
1080
|
return { status: "failed", output: "Error: file not found at path " + targetPath };
|
|
1019
1081
|
}
|
|
1020
|
-
const original =
|
|
1082
|
+
const original = readFileSync5(targetPath, "utf8");
|
|
1021
1083
|
const normalizedDiff = normalizeDiff(operation.diff);
|
|
1022
1084
|
const patched = applyDiff(original, normalizedDiff);
|
|
1023
1085
|
await writeFile(targetPath, patched, "utf8");
|
|
1024
|
-
|
|
1086
|
+
let output = `Updated ${operation.path}`;
|
|
1087
|
+
const validationError = validateGraphQL(patched, operation.path, this.root());
|
|
1088
|
+
if (validationError) {
|
|
1089
|
+
output += `
|
|
1090
|
+
|
|
1091
|
+
${validationError}`;
|
|
1092
|
+
}
|
|
1093
|
+
return { status: "completed", output };
|
|
1025
1094
|
} catch (err) {
|
|
1026
1095
|
return { status: "failed", output: `Error updating ${operation.path}: ${String(err)}` };
|
|
1027
1096
|
}
|
|
@@ -1029,7 +1098,7 @@ var WorkspaceEditor = class {
|
|
|
1029
1098
|
async overwriteFile(operation) {
|
|
1030
1099
|
try {
|
|
1031
1100
|
const targetPath = resolvePath(this.root(), operation.path);
|
|
1032
|
-
await mkdir(
|
|
1101
|
+
await mkdir(path5.dirname(targetPath), { recursive: true });
|
|
1033
1102
|
const normalizedInput = normalizeDiff(operation.diff);
|
|
1034
1103
|
const lines = normalizedInput.split(/\r?\n/);
|
|
1035
1104
|
const hasDiffMarkers = lines.some((line) => line.startsWith("+") || line.startsWith("-"));
|
|
@@ -1040,7 +1109,14 @@ var WorkspaceEditor = class {
|
|
|
1040
1109
|
finalContent = normalizedInput;
|
|
1041
1110
|
}
|
|
1042
1111
|
await writeFile(targetPath, finalContent, "utf8");
|
|
1043
|
-
|
|
1112
|
+
let output = `Overwrote ${operation.path}`;
|
|
1113
|
+
const validationError = validateGraphQL(finalContent, operation.path, this.root());
|
|
1114
|
+
if (validationError) {
|
|
1115
|
+
output += `
|
|
1116
|
+
|
|
1117
|
+
${validationError}`;
|
|
1118
|
+
}
|
|
1119
|
+
return { status: "completed", output };
|
|
1044
1120
|
} catch (err) {
|
|
1045
1121
|
return { status: "failed", output: `Error overwriting ${operation.path}: ${String(err)}` };
|
|
1046
1122
|
}
|
|
@@ -1048,7 +1124,7 @@ var WorkspaceEditor = class {
|
|
|
1048
1124
|
async deleteFile(operation) {
|
|
1049
1125
|
try {
|
|
1050
1126
|
const targetPath = resolvePath(this.root(), operation.path);
|
|
1051
|
-
if (!
|
|
1127
|
+
if (!existsSync7(targetPath)) {
|
|
1052
1128
|
return { status: "failed", output: "Error: file not found at path " + targetPath };
|
|
1053
1129
|
}
|
|
1054
1130
|
await rm(targetPath, { force: true });
|
|
@@ -1089,11 +1165,11 @@ function pickExistingSkill(candidates) {
|
|
|
1089
1165
|
}
|
|
1090
1166
|
return null;
|
|
1091
1167
|
}
|
|
1092
|
-
async function requiredSkillForOperation(
|
|
1168
|
+
async function requiredSkillForOperation(path10, type) {
|
|
1093
1169
|
if (type === "delete_file") {
|
|
1094
1170
|
return null;
|
|
1095
1171
|
}
|
|
1096
|
-
const p = normalizedPath(
|
|
1172
|
+
const p = normalizedPath(path10);
|
|
1097
1173
|
const read = await getSkillsRead();
|
|
1098
1174
|
if (p.includes("/resources/") || p.startsWith("resources/") || p.endsWith("resources.ts") || p.endsWith("resources.js")) {
|
|
1099
1175
|
if (!read.includes("automatic-apis")) {
|
|
@@ -1214,9 +1290,9 @@ import { z as z12 } from "zod";
|
|
|
1214
1290
|
var ToolParameters11 = z12.object({
|
|
1215
1291
|
path: z12.string().describe("Directory to switch into. Can be absolute or relative to current workspace.")
|
|
1216
1292
|
});
|
|
1217
|
-
async function execute12({ path:
|
|
1293
|
+
async function execute12({ path: path10 }) {
|
|
1218
1294
|
try {
|
|
1219
|
-
const target = resolvePath(trackedState.cwd,
|
|
1295
|
+
const target = resolvePath(trackedState.cwd, path10);
|
|
1220
1296
|
const stat = statSync(target);
|
|
1221
1297
|
if (!stat.isDirectory()) {
|
|
1222
1298
|
return `Path is not a directory: ${target}`;
|
|
@@ -1317,7 +1393,7 @@ var findTool = tool14({
|
|
|
1317
1393
|
// tools/files/readDirTool.ts
|
|
1318
1394
|
import { tool as tool15 } from "@openai/agents";
|
|
1319
1395
|
import { readdir } from "fs/promises";
|
|
1320
|
-
import
|
|
1396
|
+
import path6 from "path";
|
|
1321
1397
|
import { z as z15 } from "zod";
|
|
1322
1398
|
var ToolParameters14 = z15.object({
|
|
1323
1399
|
directoryName: z15.string().describe("The name of the directory to read.")
|
|
@@ -1330,7 +1406,7 @@ var readDirTool = tool15({
|
|
|
1330
1406
|
try {
|
|
1331
1407
|
const resolvedPath = resolvePath(trackedState.cwd, directoryName);
|
|
1332
1408
|
const files = await readdir(resolvedPath, "utf8");
|
|
1333
|
-
return files.filter((file) => !isIgnored(
|
|
1409
|
+
return files.filter((file) => !isIgnored(path6.join(resolvedPath, file)));
|
|
1334
1410
|
} catch (error) {
|
|
1335
1411
|
return `Error reading directory: ${error}`;
|
|
1336
1412
|
}
|
|
@@ -1386,7 +1462,7 @@ var readFileTool = tool16({
|
|
|
1386
1462
|
import { tool as tool17 } from "@openai/agents";
|
|
1387
1463
|
import { exec } from "child_process";
|
|
1388
1464
|
import { unlink, writeFile as writeFile2 } from "fs/promises";
|
|
1389
|
-
import
|
|
1465
|
+
import path7 from "path";
|
|
1390
1466
|
import { promisify as promisify3 } from "util";
|
|
1391
1467
|
import { z as z17 } from "zod";
|
|
1392
1468
|
var execAsync = promisify3(exec);
|
|
@@ -1429,7 +1505,7 @@ async function needsApproval2(runContext, parameters, callId) {
|
|
|
1429
1505
|
async function execute14({ code, language }) {
|
|
1430
1506
|
const extension = language === "javascript" ? "js" : "py";
|
|
1431
1507
|
const interpreter = language === "javascript" ? "node" : "python3";
|
|
1432
|
-
const tempFile =
|
|
1508
|
+
const tempFile = path7.join(trackedState.cwd, `.temp_code_${Date.now()}.${extension}`);
|
|
1433
1509
|
try {
|
|
1434
1510
|
await writeFile2(tempFile, code, "utf8");
|
|
1435
1511
|
const { stdout, stderr } = await execAsync(`${interpreter} ${tempFile}`);
|
|
@@ -1488,7 +1564,7 @@ import { tool as tool19 } from "@openai/agents";
|
|
|
1488
1564
|
import { z as z19 } from "zod";
|
|
1489
1565
|
|
|
1490
1566
|
// utils/files/updateEnv.ts
|
|
1491
|
-
import { existsSync as
|
|
1567
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync6, writeFileSync } from "fs";
|
|
1492
1568
|
import { homedir as homedir3 } from "os";
|
|
1493
1569
|
import { dirname as dirname4, join as join7 } from "path";
|
|
1494
1570
|
function updateEnv(key, value) {
|
|
@@ -1496,14 +1572,14 @@ function updateEnv(key, value) {
|
|
|
1496
1572
|
process.env[key] = normalizedValue;
|
|
1497
1573
|
const topLevelEnvPath = join7(homedir3(), ".harper", "harper-agent-env");
|
|
1498
1574
|
const localEnvPath = join7(trackedState.cwd, ".env");
|
|
1499
|
-
const envPath =
|
|
1575
|
+
const envPath = existsSync8(topLevelEnvPath) || !existsSync8(localEnvPath) ? topLevelEnvPath : localEnvPath;
|
|
1500
1576
|
const dir = dirname4(envPath);
|
|
1501
|
-
if (!
|
|
1577
|
+
if (!existsSync8(dir)) {
|
|
1502
1578
|
mkdirSync2(dir, { recursive: true });
|
|
1503
1579
|
}
|
|
1504
1580
|
let envContent = "";
|
|
1505
|
-
if (
|
|
1506
|
-
envContent =
|
|
1581
|
+
if (existsSync8(envPath)) {
|
|
1582
|
+
envContent = readFileSync6(envPath, "utf8");
|
|
1507
1583
|
}
|
|
1508
1584
|
const regex = new RegExp(`^${key}=.*`, "m");
|
|
1509
1585
|
if (regex.test(envContent)) {
|
|
@@ -2023,7 +2099,7 @@ var checkHarperStatusTool = tool30({
|
|
|
2023
2099
|
// tools/harper/createNewHarperApplicationTool.ts
|
|
2024
2100
|
import { tool as tool31 } from "@openai/agents";
|
|
2025
2101
|
import { execSync as execSync3 } from "child_process";
|
|
2026
|
-
import
|
|
2102
|
+
import path8 from "path";
|
|
2027
2103
|
import { z as z31 } from "zod";
|
|
2028
2104
|
|
|
2029
2105
|
// utils/package/buildHarperCreateCommand.ts
|
|
@@ -2082,8 +2158,8 @@ async function execute16({ directoryName, template }) {
|
|
|
2082
2158
|
const currentCwd = trackedState.cwd;
|
|
2083
2159
|
const resolvedPath = resolvePath(currentCwd, directoryName);
|
|
2084
2160
|
const isCurrentDir = resolvedPath === currentCwd;
|
|
2085
|
-
const executionCwd = isCurrentDir ? resolvedPath :
|
|
2086
|
-
const appName = isCurrentDir ? "." :
|
|
2161
|
+
const executionCwd = isCurrentDir ? resolvedPath : path8.dirname(resolvedPath);
|
|
2162
|
+
const appName = isCurrentDir ? "." : path8.basename(resolvedPath);
|
|
2087
2163
|
try {
|
|
2088
2164
|
const pm = pickPreferredPackageManager();
|
|
2089
2165
|
const { cmd, label } = buildCreateCommand(pm, appName, template);
|
|
@@ -2244,14 +2320,14 @@ var hitHarperAPITool = tool35({
|
|
|
2244
2320
|
}
|
|
2245
2321
|
return false;
|
|
2246
2322
|
},
|
|
2247
|
-
async execute({ path:
|
|
2323
|
+
async execute({ path: path10 = "/openapi", port, method = "GET", body }) {
|
|
2248
2324
|
try {
|
|
2249
2325
|
const effectivePort = port ?? (harperProcess.running ? harperProcess.httpPort : void 0);
|
|
2250
2326
|
if (!effectivePort) {
|
|
2251
2327
|
return `Error: No Harper application is currently running and no port was specified.`;
|
|
2252
2328
|
}
|
|
2253
2329
|
const response = await fetch(
|
|
2254
|
-
`http://localhost:${effectivePort}${
|
|
2330
|
+
`http://localhost:${effectivePort}${path10.startsWith("/") ? "" : "/"}${path10}`,
|
|
2255
2331
|
{
|
|
2256
2332
|
method,
|
|
2257
2333
|
headers: body ? { "Content-Type": "application/json" } : {},
|
|
@@ -2291,7 +2367,7 @@ var readHarperLogsTool = tool36({
|
|
|
2291
2367
|
|
|
2292
2368
|
// tools/harper/startHarperTool.ts
|
|
2293
2369
|
import { tool as tool37 } from "@openai/agents";
|
|
2294
|
-
import { existsSync as
|
|
2370
|
+
import { existsSync as existsSync9 } from "fs";
|
|
2295
2371
|
import { basename, resolve } from "path";
|
|
2296
2372
|
import { z as z37 } from "zod";
|
|
2297
2373
|
|
|
@@ -2318,7 +2394,7 @@ var startHarperTool = tool37({
|
|
|
2318
2394
|
try {
|
|
2319
2395
|
let effectiveDirectory = directoryName;
|
|
2320
2396
|
const candidatePath = resolve(process.cwd(), directoryName);
|
|
2321
|
-
if (!
|
|
2397
|
+
if (!existsSync9(candidatePath)) {
|
|
2322
2398
|
const cwd = process.cwd();
|
|
2323
2399
|
if (basename(cwd) === directoryName) {
|
|
2324
2400
|
effectiveDirectory = cwd;
|
|
@@ -2646,7 +2722,7 @@ Stack: ${String(err.stack).split("\n").slice(0, 8).join("\n")}` : "";
|
|
|
2646
2722
|
|
|
2647
2723
|
// utils/sessions/DiskSession.ts
|
|
2648
2724
|
import { MemorySession } from "@openai/agents";
|
|
2649
|
-
import { existsSync as
|
|
2725
|
+
import { existsSync as existsSync10 } from "fs";
|
|
2650
2726
|
import { mkdir as mkdir2, readFile as readFile5, rename, writeFile as writeFile3 } from "fs/promises";
|
|
2651
2727
|
import { dirname as dirname8 } from "path";
|
|
2652
2728
|
var DiskSession = class extends MemorySession {
|
|
@@ -2697,7 +2773,7 @@ var DiskSession = class extends MemorySession {
|
|
|
2697
2773
|
}
|
|
2698
2774
|
}
|
|
2699
2775
|
async loadStorage() {
|
|
2700
|
-
if (
|
|
2776
|
+
if (existsSync10(this.filePath)) {
|
|
2701
2777
|
try {
|
|
2702
2778
|
const data = await readFile5(this.filePath, "utf-8");
|
|
2703
2779
|
const parsed = JSON.parse(data);
|
|
@@ -2715,7 +2791,7 @@ var DiskSession = class extends MemorySession {
|
|
|
2715
2791
|
const storage = await this.loadStorage();
|
|
2716
2792
|
update(storage);
|
|
2717
2793
|
const dir = dirname8(this.filePath);
|
|
2718
|
-
if (!
|
|
2794
|
+
if (!existsSync10(dir)) {
|
|
2719
2795
|
await mkdir2(dir, { recursive: true });
|
|
2720
2796
|
}
|
|
2721
2797
|
const data = JSON.stringify(storage, null, 2);
|
|
@@ -4947,7 +5023,7 @@ function PlanView() {
|
|
|
4947
5023
|
|
|
4948
5024
|
// ink/components/SettingsView.tsx
|
|
4949
5025
|
import { Box as Box7, Text as Text7, useInput as useInput2 } from "ink";
|
|
4950
|
-
import
|
|
5026
|
+
import path9 from "path";
|
|
4951
5027
|
import { useEffect as useEffect6, useMemo as useMemo9, useState as useState11 } from "react";
|
|
4952
5028
|
|
|
4953
5029
|
// ink/contexts/SettingsContext.tsx
|
|
@@ -5089,8 +5165,8 @@ function SettingsView({ isDense = false }) {
|
|
|
5089
5165
|
if (!sessionPath) {
|
|
5090
5166
|
return null;
|
|
5091
5167
|
}
|
|
5092
|
-
const relative =
|
|
5093
|
-
if (!relative.startsWith("..") && !
|
|
5168
|
+
const relative = path9.relative(cwd, sessionPath);
|
|
5169
|
+
if (!relative.startsWith("..") && !path9.isAbsolute(relative)) {
|
|
5094
5170
|
return `./${relative}`;
|
|
5095
5171
|
}
|
|
5096
5172
|
return sessionPath;
|
|
@@ -6500,13 +6576,13 @@ function warnAndPersistRedirect(original, envKey, replacement, reason) {
|
|
|
6500
6576
|
import chalk5 from "chalk";
|
|
6501
6577
|
|
|
6502
6578
|
// utils/package/getOwnPackageJson.ts
|
|
6503
|
-
import { readFileSync as
|
|
6579
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
6504
6580
|
import { join as join11 } from "path";
|
|
6505
|
-
import { fileURLToPath } from "url";
|
|
6506
|
-
var
|
|
6581
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
6582
|
+
var __dirname2 = fileURLToPath2(new URL(".", import.meta.url));
|
|
6507
6583
|
function getOwnPackageJson() {
|
|
6508
6584
|
try {
|
|
6509
|
-
const packageContents =
|
|
6585
|
+
const packageContents = readFileSync7(join11(__dirname2, "../package.json"), "utf8");
|
|
6510
6586
|
return JSON.parse(packageContents);
|
|
6511
6587
|
} catch {
|
|
6512
6588
|
return { name: "@harperfast/agent", version: "0.0.0" };
|
|
@@ -6710,16 +6786,16 @@ function parseArgs() {
|
|
|
6710
6786
|
|
|
6711
6787
|
// utils/envLoader.ts
|
|
6712
6788
|
import dotenv from "dotenv";
|
|
6713
|
-
import { existsSync as
|
|
6789
|
+
import { existsSync as existsSync11 } from "fs";
|
|
6714
6790
|
import { homedir as homedir4 } from "os";
|
|
6715
6791
|
import { join as join12 } from "path";
|
|
6716
6792
|
function loadEnv() {
|
|
6717
6793
|
const topLevelEnvPath = join12(homedir4(), ".harper", "harper-agent-env");
|
|
6718
6794
|
const localEnvPath = join12(process.cwd(), ".env");
|
|
6719
|
-
if (
|
|
6795
|
+
if (existsSync11(topLevelEnvPath)) {
|
|
6720
6796
|
dotenv.config({ path: topLevelEnvPath, quiet: true });
|
|
6721
6797
|
}
|
|
6722
|
-
if (
|
|
6798
|
+
if (existsSync11(localEnvPath)) {
|
|
6723
6799
|
dotenv.config({ path: localEnvPath, override: true, quiet: true });
|
|
6724
6800
|
}
|
|
6725
6801
|
}
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""
|
|
2
|
+
A flexible JSON-like value.
|
|
3
|
+
Accepts objects, arrays, strings, numbers, booleans, or null.
|
|
4
|
+
Useful for schemaless or mixed content.
|
|
5
|
+
"""
|
|
6
|
+
scalar Any
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
Arbitrary-precision integer for values larger than 32-bit/64-bit ranges.
|
|
10
|
+
Input may be provided as a JSON number or string; tooling may return it as a
|
|
11
|
+
string to avoid precision loss. Use `Long` for 64-bit integers when possible.
|
|
12
|
+
"""
|
|
13
|
+
scalar BigInt
|
|
14
|
+
|
|
15
|
+
"""
|
|
16
|
+
Binary large object. Represents binary data such as images or files.
|
|
17
|
+
Typically encoded as Base64 in JSON.
|
|
18
|
+
"""
|
|
19
|
+
scalar Blob
|
|
20
|
+
|
|
21
|
+
"""
|
|
22
|
+
true or false
|
|
23
|
+
"""
|
|
24
|
+
scalar Boolean
|
|
25
|
+
|
|
26
|
+
"""
|
|
27
|
+
Raw bytes. Typically encoded/transported as Base64 in JSON.
|
|
28
|
+
Use when you need deterministic binary data that is not a large file.
|
|
29
|
+
"""
|
|
30
|
+
scalar Bytes
|
|
31
|
+
|
|
32
|
+
"""
|
|
33
|
+
Date/time scalar. Recommended format: RFC 3339/ISO-8601 (e.g.,
|
|
34
|
+
"2025-12-02T19:44:00Z"). Represents an absolute timestamp.
|
|
35
|
+
"""
|
|
36
|
+
scalar Date
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
A signed double-precision floating-point value
|
|
40
|
+
"""
|
|
41
|
+
scalar Float
|
|
42
|
+
|
|
43
|
+
"""
|
|
44
|
+
ID (serialized as a String): A unique identifier that's often used to refetch an
|
|
45
|
+
object or as the key for a cache. Although it's serialized as a String, an ID is
|
|
46
|
+
not intended to be human‐readable.
|
|
47
|
+
"""
|
|
48
|
+
scalar ID
|
|
49
|
+
|
|
50
|
+
"""
|
|
51
|
+
A signed 32‐bit integer
|
|
52
|
+
"""
|
|
53
|
+
scalar Int
|
|
54
|
+
|
|
55
|
+
"""
|
|
56
|
+
64-bit signed integer. Some clients may serialize values as strings to
|
|
57
|
+
preserve precision across environments.
|
|
58
|
+
"""
|
|
59
|
+
scalar Long
|
|
60
|
+
|
|
61
|
+
"""
|
|
62
|
+
A UTF‐8 character sequence
|
|
63
|
+
"""
|
|
64
|
+
scalar String
|
|
65
|
+
|
|
66
|
+
"""
|
|
67
|
+
Attach to an object type to persist it as a table.
|
|
68
|
+
|
|
69
|
+
Example:
|
|
70
|
+
```
|
|
71
|
+
type Post @table(table: "posts", database: "blog") {
|
|
72
|
+
id: ID @primaryKey
|
|
73
|
+
title: String @indexed(type: "fulltext")
|
|
74
|
+
body: String
|
|
75
|
+
createdAt: Date @createdTime
|
|
76
|
+
updatedAt: Date @updatedTime
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
"""
|
|
80
|
+
directive @table(
|
|
81
|
+
"""
|
|
82
|
+
Explicit table name. If omitted, a sensible default derived from the
|
|
83
|
+
type name will be used.
|
|
84
|
+
"""
|
|
85
|
+
table: String
|
|
86
|
+
"""
|
|
87
|
+
Logical database/namespace to place this table in.
|
|
88
|
+
"""
|
|
89
|
+
database: String
|
|
90
|
+
"""
|
|
91
|
+
Default time-to-live (TTL) for records in seconds. Use a positive value to
|
|
92
|
+
enable automatic expiration; omit or set to 0 to disable.
|
|
93
|
+
"""
|
|
94
|
+
expiration: Int
|
|
95
|
+
"""
|
|
96
|
+
Enable auditing for create/update/delete operations.
|
|
97
|
+
"""
|
|
98
|
+
audit: Boolean
|
|
99
|
+
"""
|
|
100
|
+
The amount of time after expiration before a record can be evicted (defaults to zero).
|
|
101
|
+
"""
|
|
102
|
+
eviction: Int
|
|
103
|
+
"""
|
|
104
|
+
The interval for scanning for expired records (defaults to one quarter of the
|
|
105
|
+
total of expiration and eviction).
|
|
106
|
+
"""
|
|
107
|
+
scanInterval: Int
|
|
108
|
+
"""
|
|
109
|
+
By default, all tables within a replicated database will be replicated. Transactions
|
|
110
|
+
are replicated atomically, which may involve data across multiple tables. However,
|
|
111
|
+
you can also configure replication for individual tables, and disable and exclude
|
|
112
|
+
replication for specific tables in a database by setting replicate to false in the
|
|
113
|
+
table definition.
|
|
114
|
+
"""
|
|
115
|
+
replicate: Boolean
|
|
116
|
+
) on OBJECT
|
|
117
|
+
|
|
118
|
+
"""
|
|
119
|
+
Expose the table via the REST API. When applied to a `@table` type, routes are
|
|
120
|
+
generated using the type name or the provided alias.
|
|
121
|
+
"""
|
|
122
|
+
directive @export(
|
|
123
|
+
"""
|
|
124
|
+
Optional alias to use for REST endpoints. If omitted, the type/table name is
|
|
125
|
+
used.
|
|
126
|
+
"""
|
|
127
|
+
name: String
|
|
128
|
+
"""
|
|
129
|
+
REST support is, by default, turned on for any exported resource. You may specify
|
|
130
|
+
false to disable this automatic API support.
|
|
131
|
+
"""
|
|
132
|
+
rest: Boolean
|
|
133
|
+
"""
|
|
134
|
+
MQTT support is, by default, turned on for any exported resource. You may specify
|
|
135
|
+
false to disable this automatic API support.
|
|
136
|
+
"""
|
|
137
|
+
mqtt: Boolean
|
|
138
|
+
) on OBJECT
|
|
139
|
+
"""
|
|
140
|
+
As a NoSQL database, HarperDB supports heterogeneous records (also referred to as
|
|
141
|
+
documents), so you can freely specify additional properties on any record. If you
|
|
142
|
+
do want to restrict the records to only defined properties, you can always do that
|
|
143
|
+
by adding the sealed directive.
|
|
144
|
+
"""
|
|
145
|
+
directive @sealed on OBJECT
|
|
146
|
+
|
|
147
|
+
"""
|
|
148
|
+
Marks the primary key field for the table. The value must be unique per record
|
|
149
|
+
and is used for lookups, updates, and relationships.
|
|
150
|
+
"""
|
|
151
|
+
directive @primaryKey on FIELD_DEFINITION
|
|
152
|
+
|
|
153
|
+
"""
|
|
154
|
+
Allows enumeration over a computed field, causing it to be included in serialized responses. (Non-computed fields are always enumerable, and don't need to be flagged.)
|
|
155
|
+
"""
|
|
156
|
+
directive @enumerable on FIELD_DEFINITION
|
|
157
|
+
|
|
158
|
+
"""
|
|
159
|
+
Flags the field as containing the expiration time of the entry.
|
|
160
|
+
"""
|
|
161
|
+
directive @expiresAt on FIELD_DEFINITION
|
|
162
|
+
|
|
163
|
+
"""
|
|
164
|
+
Permit access to the field based on the named roles, only.
|
|
165
|
+
"""
|
|
166
|
+
directive @allow(role: String) on FIELD_DEFINITION
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
Create an index for the annotated field. Supports traditional and vector/ANN
|
|
170
|
+
index types.
|
|
171
|
+
"""
|
|
172
|
+
directive @indexed(
|
|
173
|
+
"""
|
|
174
|
+
Optional index type, e.g. "HNSW"
|
|
175
|
+
"""
|
|
176
|
+
type: String
|
|
177
|
+
"""
|
|
178
|
+
Distance metric for vector indexes (e.g., "euclidean", "cosine").
|
|
179
|
+
Ignored for non-vector index types.
|
|
180
|
+
"""
|
|
181
|
+
distance: String
|
|
182
|
+
"""
|
|
183
|
+
Construction effort/recall parameter (HNSW). Higher values improve recall at
|
|
184
|
+
the cost of build time and memory.
|
|
185
|
+
"""
|
|
186
|
+
efConstruction: Int
|
|
187
|
+
"""
|
|
188
|
+
Maximum number of bi-directional connections per node (HNSW).
|
|
189
|
+
Typical range: 4–64.
|
|
190
|
+
"""
|
|
191
|
+
M: Int
|
|
192
|
+
"""
|
|
193
|
+
Routing optimization level for search graphs (implementation-specific).
|
|
194
|
+
"""
|
|
195
|
+
optimizeRouting: Int
|
|
196
|
+
"""
|
|
197
|
+
Additional multiplier for graph links (implementation-specific).
|
|
198
|
+
"""
|
|
199
|
+
mL: Int
|
|
200
|
+
"""
|
|
201
|
+
Search-time effort/recall parameter used during construction (implementation-
|
|
202
|
+
specific). Larger values typically yield better accuracy.
|
|
203
|
+
"""
|
|
204
|
+
efConstructionSearch: Int
|
|
205
|
+
) on FIELD_DEFINITION
|
|
206
|
+
|
|
207
|
+
"""
|
|
208
|
+
Define a derived field whose value is computed from other fields.
|
|
209
|
+
Useful for denormalized or presentation-friendly data.
|
|
210
|
+
"""
|
|
211
|
+
directive @computed(
|
|
212
|
+
"""
|
|
213
|
+
Computation expression or reference describing how to derive this field from
|
|
214
|
+
other fields (engine-specific syntax).
|
|
215
|
+
"""
|
|
216
|
+
from: String
|
|
217
|
+
"""
|
|
218
|
+
Increment when the computation changes to trigger recomputation.
|
|
219
|
+
"""
|
|
220
|
+
version: Int
|
|
221
|
+
) on FIELD_DEFINITION
|
|
222
|
+
"""
|
|
223
|
+
Automatically sets this field to the record's creation timestamp. The server
|
|
224
|
+
assigns the value on insert.
|
|
225
|
+
"""
|
|
226
|
+
directive @createdTime on FIELD_DEFINITION
|
|
227
|
+
"""
|
|
228
|
+
Automatically updates this field to the current timestamp whenever the record
|
|
229
|
+
is updated.
|
|
230
|
+
"""
|
|
231
|
+
directive @updatedTime on FIELD_DEFINITION
|
|
232
|
+
"""
|
|
233
|
+
Declares a relationship to another record or records.
|
|
234
|
+
Use on fields that should resolve to related entities by ID.
|
|
235
|
+
"""
|
|
236
|
+
directive @relationship(
|
|
237
|
+
"""
|
|
238
|
+
Name of field in THIS table containing foreign key(s) (for one-to-many or many-to-many).
|
|
239
|
+
"""
|
|
240
|
+
from: String
|
|
241
|
+
"""
|
|
242
|
+
Name of field in OTHER table containing foreign key (for one-to-one or many-to-one).
|
|
243
|
+
"""
|
|
244
|
+
to: String
|
|
245
|
+
) on FIELD_DEFINITION
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@harperfast/agent",
|
|
3
3
|
"description": "AI to help you with Harper app management",
|
|
4
|
-
"version": "0.16.
|
|
4
|
+
"version": "0.16.2",
|
|
5
5
|
"main": "dist/agent.js",
|
|
6
6
|
"repository": "github:HarperFast/harper-agent",
|
|
7
7
|
"bugs": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"dev": "tsup agent.ts --format esm --clean --dts --watch --external puppeteer",
|
|
13
13
|
"link": "npm run build && npm link",
|
|
14
|
-
"build": "tsup agent.ts --format esm --clean --dts --external puppeteer",
|
|
14
|
+
"build": "tsup agent.ts --format esm --clean --dts --external puppeteer && cp node_modules/harperdb/schema.graphql dist/",
|
|
15
15
|
"commitlint": "commitlint --edit",
|
|
16
16
|
"start": "node ./dist/agent.js",
|
|
17
17
|
"lint": "oxlint --format stylish .",
|
|
@@ -54,6 +54,7 @@
|
|
|
54
54
|
"chalk": "^5.6.2",
|
|
55
55
|
"cross-spawn": "^7.0.6",
|
|
56
56
|
"dotenv": "^17.2.4",
|
|
57
|
+
"graphql": "^16.13.1",
|
|
57
58
|
"ink": "^6.7.0",
|
|
58
59
|
"ink-stepper": "^0.2.1",
|
|
59
60
|
"ink-task-list": "^2.0.0",
|