@harperfast/agent 0.16.14 → 0.16.16
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/{chunk-SEYUVI2L.js → chunk-HQGGUF5D.js} +34 -28
- package/dist/cli.js +329 -281
- package/dist/index.js +1 -1
- package/dist/schema.graphql +99 -99
- package/package.json +3 -3
|
@@ -712,7 +712,6 @@ function getEnv(newKey, oldKey) {
|
|
|
712
712
|
// tools/harper/getHarperSkillTool.ts
|
|
713
713
|
import { ruleNames, rules, skillSummary } from "@harperfast/skills";
|
|
714
714
|
import { tool as tool10 } from "@openai/agents";
|
|
715
|
-
import "fs";
|
|
716
715
|
import { z as z10 } from "zod";
|
|
717
716
|
var skillLinkRegex = /\[[^\]]+]\((?:rules|skills)\/([^)]+)\.md\)/g;
|
|
718
717
|
var skills = ruleNames;
|
|
@@ -749,7 +748,7 @@ async function execute10({ skill }) {
|
|
|
749
748
|
|
|
750
749
|
// tools/files/workspaceEditor.ts
|
|
751
750
|
import { applyDiff } from "@openai/agents";
|
|
752
|
-
import { existsSync as existsSync7, readFileSync as
|
|
751
|
+
import { existsSync as existsSync7, readFileSync as readFileSync4 } from "fs";
|
|
753
752
|
import { mkdir, rm, writeFile } from "fs/promises";
|
|
754
753
|
import path5 from "path";
|
|
755
754
|
|
|
@@ -771,14 +770,14 @@ function normalizeDiff(diff) {
|
|
|
771
770
|
import path3 from "path";
|
|
772
771
|
|
|
773
772
|
// utils/files/aiignore.ts
|
|
774
|
-
import { existsSync as existsSync5, readFileSync as
|
|
773
|
+
import { existsSync as existsSync5, readFileSync as readFileSync2 } from "fs";
|
|
775
774
|
import path2 from "path";
|
|
776
775
|
var ignorePatterns = [];
|
|
777
776
|
function loadAiIgnore() {
|
|
778
777
|
const ignorePath = path2.join(trackedState.cwd, ".aiignore");
|
|
779
778
|
if (existsSync5(ignorePath)) {
|
|
780
779
|
try {
|
|
781
|
-
const content =
|
|
780
|
+
const content = readFileSync2(ignorePath, "utf8");
|
|
782
781
|
ignorePatterns = content.split(/\r?\n/).map((line) => line.trim()).filter((line) => line && !line.startsWith("#")).map((pattern) => pattern.endsWith("/") || pattern.endsWith("\\") ? pattern.slice(0, -1) : pattern);
|
|
783
782
|
} catch (error) {
|
|
784
783
|
logError(error);
|
|
@@ -832,18 +831,22 @@ function resolvePath(root, relativePath) {
|
|
|
832
831
|
}
|
|
833
832
|
|
|
834
833
|
// utils/files/validateGraphQL.ts
|
|
835
|
-
import {
|
|
836
|
-
|
|
834
|
+
import { extendSchema, parse, validateSchema } from "graphql";
|
|
835
|
+
|
|
836
|
+
// utils/files/getHarperSchema.ts
|
|
837
|
+
import { buildSchema } from "graphql";
|
|
838
|
+
import { existsSync as existsSync6, readFileSync as readFileSync3 } from "fs";
|
|
837
839
|
import path4 from "path";
|
|
838
840
|
import { fileURLToPath } from "url";
|
|
839
841
|
var __dirname = path4.dirname(fileURLToPath(import.meta.url));
|
|
840
842
|
var cachedSchema = null;
|
|
841
|
-
function
|
|
843
|
+
function getHarperSchemaContent(root) {
|
|
842
844
|
if (cachedSchema) {
|
|
843
845
|
return cachedSchema;
|
|
844
846
|
}
|
|
845
847
|
const paths = [
|
|
846
848
|
path4.join(root, "node_modules", "harperdb", "schema.graphql"),
|
|
849
|
+
path4.join(root, "node_modules", "harper", "schema.graphql"),
|
|
847
850
|
path4.join(__dirname, "schema.graphql"),
|
|
848
851
|
path4.join(__dirname, "..", "schema.graphql"),
|
|
849
852
|
path4.join(__dirname, "..", "..", "schema.graphql")
|
|
@@ -851,9 +854,7 @@ function getHarperSchema(root) {
|
|
|
851
854
|
for (const schemaPath of paths) {
|
|
852
855
|
if (existsSync6(schemaPath)) {
|
|
853
856
|
try {
|
|
854
|
-
|
|
855
|
-
cachedSchema = buildSchema(schemaSource, { assumeValidSDL: true });
|
|
856
|
-
return cachedSchema;
|
|
857
|
+
return readFileSync3(schemaPath, "utf8");
|
|
857
858
|
} catch (e) {
|
|
858
859
|
console.error(`Error parsing HarperDB schema at ${schemaPath}:`, e);
|
|
859
860
|
}
|
|
@@ -861,13 +862,26 @@ function getHarperSchema(root) {
|
|
|
861
862
|
}
|
|
862
863
|
return null;
|
|
863
864
|
}
|
|
865
|
+
function getHarperSchemaBuilt(root) {
|
|
866
|
+
if (cachedSchema) {
|
|
867
|
+
return cachedSchema;
|
|
868
|
+
}
|
|
869
|
+
const schemaSource = getHarperSchemaContent(root);
|
|
870
|
+
if (schemaSource) {
|
|
871
|
+
cachedSchema = buildSchema(schemaSource, { assumeValidSDL: true });
|
|
872
|
+
return cachedSchema;
|
|
873
|
+
}
|
|
874
|
+
return null;
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
// utils/files/validateGraphQL.ts
|
|
864
878
|
function validateGraphQL(content, filePath, root) {
|
|
865
879
|
if (!filePath.endsWith(".graphql")) {
|
|
866
880
|
return null;
|
|
867
881
|
}
|
|
868
882
|
try {
|
|
869
883
|
const document2 = parse(content);
|
|
870
|
-
const schema =
|
|
884
|
+
const schema = getHarperSchemaBuilt(root);
|
|
871
885
|
if (schema) {
|
|
872
886
|
const extendedSchema = extendSchema(schema, document2, { assumeValidSDL: false });
|
|
873
887
|
const errors = validateSchema(extendedSchema).filter(
|
|
@@ -917,7 +931,7 @@ ${validationError}`;
|
|
|
917
931
|
if (!existsSync7(targetPath)) {
|
|
918
932
|
return { status: "failed", output: "Error: file not found at path " + targetPath };
|
|
919
933
|
}
|
|
920
|
-
const original =
|
|
934
|
+
const original = readFileSync4(targetPath, "utf8");
|
|
921
935
|
const normalizedDiff = normalizeDiff(operation.diff);
|
|
922
936
|
const patched = applyDiff(original, normalizedDiff);
|
|
923
937
|
await writeFile(targetPath, patched, "utf8");
|
|
@@ -1387,7 +1401,7 @@ import { tool as tool19 } from "@openai/agents";
|
|
|
1387
1401
|
import { z as z19 } from "zod";
|
|
1388
1402
|
|
|
1389
1403
|
// utils/files/updateEnv.ts
|
|
1390
|
-
import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as
|
|
1404
|
+
import { existsSync as existsSync8, mkdirSync as mkdirSync2, readFileSync as readFileSync5, writeFileSync } from "fs";
|
|
1391
1405
|
import { homedir as homedir3 } from "os";
|
|
1392
1406
|
import { dirname as dirname3, join as join6 } from "path";
|
|
1393
1407
|
function updateEnv(key, value) {
|
|
@@ -1402,7 +1416,7 @@ function updateEnv(key, value) {
|
|
|
1402
1416
|
}
|
|
1403
1417
|
let envContent = "";
|
|
1404
1418
|
if (existsSync8(envPath)) {
|
|
1405
|
-
envContent =
|
|
1419
|
+
envContent = readFileSync5(envPath, "utf8");
|
|
1406
1420
|
}
|
|
1407
1421
|
const regex = new RegExp(`^${key}=.*`, "m");
|
|
1408
1422
|
if (regex.test(envContent)) {
|
|
@@ -2066,9 +2080,6 @@ var getHarperResourceInterfaceTool = tool33({
|
|
|
2066
2080
|
|
|
2067
2081
|
// tools/harper/getHarperSchemaGraphQLTool.ts
|
|
2068
2082
|
import { tool as tool34 } from "@openai/agents";
|
|
2069
|
-
import { readFile as readFile4 } from "fs/promises";
|
|
2070
|
-
import { createRequire as createRequire3 } from "module";
|
|
2071
|
-
import { dirname as dirname6, join as join9 } from "path";
|
|
2072
2083
|
import { z as z34 } from "zod";
|
|
2073
2084
|
var ToolParameters21 = z34.object({});
|
|
2074
2085
|
var getHarperSchemaGraphQLTool = tool34({
|
|
@@ -2077,13 +2088,7 @@ var getHarperSchemaGraphQLTool = tool34({
|
|
|
2077
2088
|
parameters: ToolParameters21,
|
|
2078
2089
|
async execute() {
|
|
2079
2090
|
try {
|
|
2080
|
-
return
|
|
2081
|
-
join9(
|
|
2082
|
-
dirname6(createRequire3(import.meta.url).resolve("harperdb")),
|
|
2083
|
-
`schema.graphql`
|
|
2084
|
-
),
|
|
2085
|
-
"utf8"
|
|
2086
|
-
);
|
|
2091
|
+
return getHarperSchemaContent(trackedState.cwd);
|
|
2087
2092
|
} catch (error) {
|
|
2088
2093
|
return `Error reading HarperDB GraphQL schema: ${error}`;
|
|
2089
2094
|
}
|
|
@@ -2548,8 +2553,8 @@ Stack: ${String(err.stack).split("\n").slice(0, 8).join("\n")}` : "";
|
|
|
2548
2553
|
// utils/sessions/DiskSession.ts
|
|
2549
2554
|
import { MemorySession } from "@openai/agents";
|
|
2550
2555
|
import { existsSync as existsSync10 } from "fs";
|
|
2551
|
-
import { mkdir as mkdir2, readFile as
|
|
2552
|
-
import { dirname as
|
|
2556
|
+
import { mkdir as mkdir2, readFile as readFile4, rename, writeFile as writeFile3 } from "fs/promises";
|
|
2557
|
+
import { dirname as dirname6 } from "path";
|
|
2553
2558
|
var DiskSession = class extends MemorySession {
|
|
2554
2559
|
filePath;
|
|
2555
2560
|
ready;
|
|
@@ -2600,7 +2605,7 @@ var DiskSession = class extends MemorySession {
|
|
|
2600
2605
|
async loadStorage() {
|
|
2601
2606
|
if (existsSync10(this.filePath)) {
|
|
2602
2607
|
try {
|
|
2603
|
-
const data = await
|
|
2608
|
+
const data = await readFile4(this.filePath, "utf-8");
|
|
2604
2609
|
const parsed = JSON.parse(data);
|
|
2605
2610
|
parsed.sessions = parsed.sessions || {};
|
|
2606
2611
|
parsed.skillsRead = parsed.skillsRead || {};
|
|
@@ -2615,7 +2620,7 @@ var DiskSession = class extends MemorySession {
|
|
|
2615
2620
|
async updateStorage(update) {
|
|
2616
2621
|
const storage = await this.loadStorage();
|
|
2617
2622
|
update(storage);
|
|
2618
|
-
const dir =
|
|
2623
|
+
const dir = dirname6(this.filePath);
|
|
2619
2624
|
if (!existsSync10(dir)) {
|
|
2620
2625
|
await mkdir2(dir, { recursive: true });
|
|
2621
2626
|
}
|
|
@@ -4051,6 +4056,7 @@ export {
|
|
|
4051
4056
|
defaultOllamaModel,
|
|
4052
4057
|
defaultOllamaCompactionModel,
|
|
4053
4058
|
isOpenAIModel,
|
|
4059
|
+
getProvider,
|
|
4054
4060
|
handleExit,
|
|
4055
4061
|
setupGlobalErrorHandlers,
|
|
4056
4062
|
updateEnv,
|
package/dist/cli.js
CHANGED
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
emitToListeners,
|
|
16
16
|
excludeFalsy,
|
|
17
17
|
fetchOllamaModels,
|
|
18
|
+
getProvider,
|
|
18
19
|
handleExit,
|
|
19
20
|
isOpenAIModel,
|
|
20
21
|
isTrue,
|
|
@@ -26,7 +27,7 @@ import {
|
|
|
26
27
|
updateEnv,
|
|
27
28
|
useActions,
|
|
28
29
|
useListener
|
|
29
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-HQGGUF5D.js";
|
|
30
31
|
|
|
31
32
|
// lifecycle/patchFetch.ts
|
|
32
33
|
var originalFetch = globalThis.fetch;
|
|
@@ -85,6 +86,249 @@ import chalk5 from "chalk";
|
|
|
85
86
|
import { render, useApp } from "ink";
|
|
86
87
|
import "react";
|
|
87
88
|
|
|
89
|
+
// utils/models/deprecations.ts
|
|
90
|
+
import chalk from "chalk";
|
|
91
|
+
var DEPRECATION_RULES = [
|
|
92
|
+
// Redirect any gpt-4o variants (including dated and -mini) to gpt-5-nano
|
|
93
|
+
{
|
|
94
|
+
match: (name) => name.toLowerCase().startsWith("gpt-4o"),
|
|
95
|
+
replacement: "gpt-5-nano",
|
|
96
|
+
reason: "OpenAI gpt-4o family is deprecated in this agent"
|
|
97
|
+
}
|
|
98
|
+
];
|
|
99
|
+
function getDeprecatedReplacement(modelName) {
|
|
100
|
+
if (!modelName) {
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
for (const rule of DEPRECATION_RULES) {
|
|
104
|
+
if (rule.match(modelName)) {
|
|
105
|
+
return { replacement: rule.replacement, rule };
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
function warnAndPersistRedirect(original, envKey, replacement, reason) {
|
|
111
|
+
const reasonSuffix = reason ? ` Reason: ${reason}.` : "";
|
|
112
|
+
console.warn(
|
|
113
|
+
chalk.yellow(
|
|
114
|
+
`Warning: model "${original}" is deprecated and will be redirected to "${replacement}". Your environment setting (${envKey}) has been updated.${reasonSuffix}`
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
updateEnv(envKey, replacement);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// utils/shell/cli.ts
|
|
121
|
+
import chalk2 from "chalk";
|
|
122
|
+
|
|
123
|
+
// utils/package/getOwnPackageJson.ts
|
|
124
|
+
import { readFileSync } from "fs";
|
|
125
|
+
import { join } from "path";
|
|
126
|
+
import { fileURLToPath } from "url";
|
|
127
|
+
var __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
128
|
+
function getOwnPackageJson() {
|
|
129
|
+
try {
|
|
130
|
+
const packageContents = readFileSync(join(__dirname, "../package.json"), "utf8");
|
|
131
|
+
return JSON.parse(packageContents);
|
|
132
|
+
} catch {
|
|
133
|
+
return { name: "@harperfast/agent", version: "0.0.0" };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// utils/shell/cli.ts
|
|
138
|
+
function isHelpRequest(args) {
|
|
139
|
+
const helpVariants = ["--help", "-h", "help"];
|
|
140
|
+
return args.some((arg) => helpVariants.includes(arg.toLowerCase()));
|
|
141
|
+
}
|
|
142
|
+
function isVersionRequest(args) {
|
|
143
|
+
const versionVariants = ["--version", "-v", "version"];
|
|
144
|
+
return args.some((arg) => versionVariants.includes(arg.toLowerCase()));
|
|
145
|
+
}
|
|
146
|
+
function handleHelp() {
|
|
147
|
+
console.log(`
|
|
148
|
+
${chalk2.bold("harper-agent")} - AI to help you with Harper app creation and modification
|
|
149
|
+
|
|
150
|
+
${chalk2.bold("USAGE")}
|
|
151
|
+
$ harper-agent [options]
|
|
152
|
+
$ harper-agent [command]
|
|
153
|
+
|
|
154
|
+
${chalk2.bold("OPTIONS")}
|
|
155
|
+
-h, --help Show help information
|
|
156
|
+
-v, --version Show version information
|
|
157
|
+
-m, --model Specify the model to use (e.g., ${defaultOpenAIModel}, ${defaultAnthropicModel}, ${defaultOllamaModel})
|
|
158
|
+
Can also be set via HARPER_AGENT_MODEL environment variable.
|
|
159
|
+
For Ollama, use the ollama- prefix (e.g., ${defaultOllamaCompactionModel}).
|
|
160
|
+
-c, --compaction-model Specify the compaction model to use (defaults to ${defaultOpenAICompactionModel}).
|
|
161
|
+
Can also be set via HARPER_AGENT_COMPACTION_MODEL environment variable.
|
|
162
|
+
-s, --session Specify a path to a SQLite database file to persist the chat session.
|
|
163
|
+
Can also be set via HARPER_AGENT_SESSION environment variable.
|
|
164
|
+
--max-turns Specify the maximum number of turns for the agent run.
|
|
165
|
+
Can also be set via HARPER_AGENT_MAX_TURNS environment variable.
|
|
166
|
+
--max-cost Specify the maximum cost (in USD) for the agent run.
|
|
167
|
+
If exceeded, the agent will exit with a non-zero code.
|
|
168
|
+
Can also be set via HARPER_AGENT_MAX_COST environment variable.
|
|
169
|
+
--flex-tier Force the use of the flex service tier for lower costs but potentially
|
|
170
|
+
more errors under high system load.
|
|
171
|
+
Can also be set via HARPER_AGENT_FLEX_TIER=true environment variable.
|
|
172
|
+
-p, --prompt Specify a prompt to be executed autonomously until completion.
|
|
173
|
+
|
|
174
|
+
${chalk2.bold("COMMANDS")}
|
|
175
|
+
--help Show help information
|
|
176
|
+
--version Show version information
|
|
177
|
+
|
|
178
|
+
${chalk2.bold("EXAMPLES")}
|
|
179
|
+
$ harper-agent --help
|
|
180
|
+
$ harper-agent --version
|
|
181
|
+
$ harper-agent
|
|
182
|
+
`);
|
|
183
|
+
process.exit(0);
|
|
184
|
+
}
|
|
185
|
+
function handleVersion() {
|
|
186
|
+
const pkg = getOwnPackageJson();
|
|
187
|
+
console.log(pkg.version);
|
|
188
|
+
process.exit(0);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
// lifecycle/parseArgs.ts
|
|
192
|
+
function stripQuotes(str) {
|
|
193
|
+
if (str.startsWith('"') && str.endsWith('"') || str.startsWith("'") && str.endsWith("'")) {
|
|
194
|
+
return str.slice(1, -1);
|
|
195
|
+
}
|
|
196
|
+
return str;
|
|
197
|
+
}
|
|
198
|
+
function parseArgs() {
|
|
199
|
+
const args = process.argv.slice(2);
|
|
200
|
+
if (isHelpRequest(args)) {
|
|
201
|
+
handleHelp();
|
|
202
|
+
}
|
|
203
|
+
if (isVersionRequest(args)) {
|
|
204
|
+
handleVersion();
|
|
205
|
+
}
|
|
206
|
+
for (let i = 0; i < args.length; i++) {
|
|
207
|
+
const arg = args[i];
|
|
208
|
+
const flagPairs = [
|
|
209
|
+
["model", ["--model", "-m", "model"]],
|
|
210
|
+
["compactionModel", ["--compaction-model", "-c", "compaction-model"]],
|
|
211
|
+
["sessionPath", ["--session", "-s", "session"]],
|
|
212
|
+
["maxTurns", ["--max-turns"]],
|
|
213
|
+
["maxCost", ["--max-cost"]],
|
|
214
|
+
["rateLimitThreshold", ["--rate-limit-threshold"]],
|
|
215
|
+
["prompt", ["--prompt", "-p"]]
|
|
216
|
+
];
|
|
217
|
+
let handled = false;
|
|
218
|
+
for (const [key, prefixes] of flagPairs) {
|
|
219
|
+
for (const prefix of prefixes) {
|
|
220
|
+
if (arg === prefix) {
|
|
221
|
+
if (args[i + 1]) {
|
|
222
|
+
const val = stripQuotes(args[++i]);
|
|
223
|
+
if (key === "maxTurns" || key === "maxCost" || key === "rateLimitThreshold") {
|
|
224
|
+
trackedState[key] = parseFloat(val);
|
|
225
|
+
} else {
|
|
226
|
+
trackedState[key] = val;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
handled = true;
|
|
230
|
+
break;
|
|
231
|
+
} else if (arg.startsWith(`${prefix}=`)) {
|
|
232
|
+
const val = stripQuotes(arg.slice(prefix.length + 1));
|
|
233
|
+
if (key === "maxTurns" || key === "maxCost" || key === "rateLimitThreshold") {
|
|
234
|
+
trackedState[key] = parseFloat(val);
|
|
235
|
+
} else {
|
|
236
|
+
trackedState[key] = val;
|
|
237
|
+
}
|
|
238
|
+
handled = true;
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (handled) {
|
|
243
|
+
break;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
if (handled) {
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
if (arg === "--flex-tier") {
|
|
250
|
+
trackedState.useFlexTier = true;
|
|
251
|
+
} else if (arg === "--no-monitor-rate-limits") {
|
|
252
|
+
trackedState.monitorRateLimits = false;
|
|
253
|
+
} else if (arg === "--autonomous" || arg === "-a") {
|
|
254
|
+
trackedState.autonomous = true;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (!trackedState.model && process.env.HARPER_AGENT_MODEL) {
|
|
258
|
+
trackedState.model = process.env.HARPER_AGENT_MODEL;
|
|
259
|
+
}
|
|
260
|
+
if (!trackedState.compactionModel && process.env.HARPER_AGENT_COMPACTION_MODEL) {
|
|
261
|
+
trackedState.compactionModel = process.env.HARPER_AGENT_COMPACTION_MODEL;
|
|
262
|
+
}
|
|
263
|
+
if (!trackedState.sessionPath && process.env.HARPER_AGENT_SESSION) {
|
|
264
|
+
trackedState.sessionPath = process.env.HARPER_AGENT_SESSION;
|
|
265
|
+
}
|
|
266
|
+
if (process.env.HARPER_AGENT_MAX_TURNS) {
|
|
267
|
+
trackedState.maxTurns = parseFloat(process.env.HARPER_AGENT_MAX_TURNS);
|
|
268
|
+
}
|
|
269
|
+
if (process.env.HARPER_AGENT_MAX_COST) {
|
|
270
|
+
trackedState.maxCost = parseFloat(process.env.HARPER_AGENT_MAX_COST);
|
|
271
|
+
}
|
|
272
|
+
if (process.env.HARPER_AGENT_RATE_LIMIT_THRESHOLD) {
|
|
273
|
+
trackedState.rateLimitThreshold = parseFloat(process.env.HARPER_AGENT_RATE_LIMIT_THRESHOLD);
|
|
274
|
+
}
|
|
275
|
+
if (process.env.HARPER_AGENT_MONITOR_RATE_LIMITS === "false") {
|
|
276
|
+
trackedState.monitorRateLimits = false;
|
|
277
|
+
}
|
|
278
|
+
if (!trackedState.useFlexTier && isTrue(process.env.HARPER_AGENT_FLEX_TIER)) {
|
|
279
|
+
trackedState.useFlexTier = true;
|
|
280
|
+
}
|
|
281
|
+
if (isTrue(process.env.HARPER_AGENT_AUTO_APPROVE_CODE_INTERPRETER)) {
|
|
282
|
+
trackedState.autoApproveCodeInterpreter = true;
|
|
283
|
+
}
|
|
284
|
+
if (isTrue(process.env.HARPER_AGENT_AUTO_APPROVE_PATCHES)) {
|
|
285
|
+
trackedState.autoApprovePatches = true;
|
|
286
|
+
}
|
|
287
|
+
if (isTrue(process.env.HARPER_AGENT_AUTO_APPROVE_SHELL)) {
|
|
288
|
+
trackedState.autoApproveShell = true;
|
|
289
|
+
}
|
|
290
|
+
if (isTrue(process.env.HARPER_AGENT_AUTONOMOUS)) {
|
|
291
|
+
trackedState.autonomous = true;
|
|
292
|
+
}
|
|
293
|
+
if (!trackedState.model || trackedState.model === defaultModelToken) {
|
|
294
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
295
|
+
trackedState.model = defaultAnthropicModel;
|
|
296
|
+
} else if (process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
|
|
297
|
+
trackedState.model = defaultGoogleModel;
|
|
298
|
+
} else if (process.env.OLLAMA_BASE_URL) {
|
|
299
|
+
trackedState.model = defaultOllamaModel;
|
|
300
|
+
} else {
|
|
301
|
+
trackedState.model = defaultOpenAIModel;
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
if (!trackedState.compactionModel || trackedState.compactionModel === defaultModelToken) {
|
|
305
|
+
const m = trackedState.model;
|
|
306
|
+
if (m.startsWith("claude-")) {
|
|
307
|
+
trackedState.compactionModel = defaultAnthropicCompactionModel;
|
|
308
|
+
} else if (m.startsWith("gemini-")) {
|
|
309
|
+
trackedState.compactionModel = defaultGoogleCompactionModel;
|
|
310
|
+
} else if (m.startsWith("ollama-")) {
|
|
311
|
+
trackedState.compactionModel = defaultOllamaCompactionModel;
|
|
312
|
+
} else {
|
|
313
|
+
trackedState.compactionModel = defaultOpenAICompactionModel;
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
if (!isOpenAIModel(trackedState.model)) {
|
|
317
|
+
process.env.OPENAI_AGENTS_DISABLE_TRACING = process.env.OPENAI_AGENTS_DISABLE_TRACING || "1";
|
|
318
|
+
}
|
|
319
|
+
const maybeRedirect = (current, envKey) => {
|
|
320
|
+
const hit = getDeprecatedReplacement(current);
|
|
321
|
+
if (hit) {
|
|
322
|
+
const { replacement, rule } = hit;
|
|
323
|
+
warnAndPersistRedirect(current, envKey, replacement, rule.reason);
|
|
324
|
+
return replacement;
|
|
325
|
+
}
|
|
326
|
+
return current;
|
|
327
|
+
};
|
|
328
|
+
trackedState.model = maybeRedirect(trackedState.model, "HARPER_AGENT_MODEL");
|
|
329
|
+
trackedState.compactionModel = maybeRedirect(trackedState.compactionModel, "HARPER_AGENT_COMPACTION_MODEL");
|
|
330
|
+
}
|
|
331
|
+
|
|
88
332
|
// ink/components/ChatContent.tsx
|
|
89
333
|
import { Spinner as Spinner2 } from "@inkjs/ui";
|
|
90
334
|
import { Box as Box10, Text as Text10, useInput as useInput4 } from "ink";
|
|
@@ -1067,7 +1311,7 @@ function SettingsView({ isDense = false }) {
|
|
|
1067
1311
|
{
|
|
1068
1312
|
label: "<edit settings>",
|
|
1069
1313
|
isAction: true,
|
|
1070
|
-
action:
|
|
1314
|
+
action: showConfigThenReparse
|
|
1071
1315
|
}
|
|
1072
1316
|
], [autoApproveCodeInterpreter, autoApprovePatches, autoApproveShell, monitorRateLimits]);
|
|
1073
1317
|
useInput2((_input, key) => {
|
|
@@ -1180,7 +1424,7 @@ function SettingsView({ isDense = false }) {
|
|
|
1180
1424
|
] })
|
|
1181
1425
|
] }),
|
|
1182
1426
|
/* @__PURE__ */ jsxs7(Box7, { marginTop: 1, flexDirection: "column", children: [
|
|
1183
|
-
/* @__PURE__ */ jsx12(Text7, { bold: true, children: "Auto-approvals (up/down & space to toggle):" }),
|
|
1427
|
+
/* @__PURE__ */ jsx12(Text7, { bold: true, children: "Auto-approvals (up/down & <space> to toggle):" }),
|
|
1184
1428
|
selectableOptions.map((option, index) => {
|
|
1185
1429
|
const isSelected = index === selectedIndex && focusedArea === "status";
|
|
1186
1430
|
return /* @__PURE__ */ jsx12(Box7, { children: /* @__PURE__ */ jsxs7(Text7, { color: isSelected ? "cyan" : "white", children: [
|
|
@@ -1200,7 +1444,7 @@ import { promisify } from "util";
|
|
|
1200
1444
|
import { useCallback as useCallback3, useState as useState11 } from "react";
|
|
1201
1445
|
|
|
1202
1446
|
// ink/components/BlinkingTextInput.tsx
|
|
1203
|
-
import
|
|
1447
|
+
import chalk3 from "chalk";
|
|
1204
1448
|
import { Box as Box8, Text as Text8, useInput as useInput3 } from "ink";
|
|
1205
1449
|
import { useEffect as useEffect5, useMemo as useMemo8, useReducer, useState as useState10 } from "react";
|
|
1206
1450
|
import { jsx as jsx13 } from "react/jsx-runtime";
|
|
@@ -1245,6 +1489,7 @@ var reducer = (state, action) => {
|
|
|
1245
1489
|
};
|
|
1246
1490
|
function BlinkingTextInput({
|
|
1247
1491
|
isDisabled = false,
|
|
1492
|
+
isPassword = false,
|
|
1248
1493
|
defaultValue = "",
|
|
1249
1494
|
placeholder = "",
|
|
1250
1495
|
suggestions = [],
|
|
@@ -1309,20 +1554,21 @@ function BlinkingTextInput({
|
|
|
1309
1554
|
{ isActive: !isDisabled }
|
|
1310
1555
|
);
|
|
1311
1556
|
const renderedValue = useMemo8(() => {
|
|
1557
|
+
const displayValue = isPassword ? "*".repeat(state.value.length) : state.value;
|
|
1312
1558
|
if (isDisabled) {
|
|
1313
|
-
const lines2 = (
|
|
1559
|
+
const lines2 = (displayValue || (placeholder ? chalk3.dim(placeholder) : "")).split("\n");
|
|
1314
1560
|
return /* @__PURE__ */ jsx13(Box8, { flexDirection: "column", children: lines2.map((line, i) => /* @__PURE__ */ jsx13(Box8, { children: /* @__PURE__ */ jsx13(Text8, { children: line }) }, i)) });
|
|
1315
1561
|
}
|
|
1316
1562
|
if (state.value.length === 0) {
|
|
1317
1563
|
let displayContent = "";
|
|
1318
1564
|
if (placeholder && placeholder.length > 0) {
|
|
1319
|
-
displayContent = (isCursorVisible ?
|
|
1565
|
+
displayContent = (isCursorVisible ? chalk3.inverse(placeholder[0]) : placeholder[0]) + chalk3.dim(placeholder.slice(1));
|
|
1320
1566
|
} else {
|
|
1321
|
-
displayContent = isCursorVisible ?
|
|
1567
|
+
displayContent = isCursorVisible ? chalk3.inverse(" ") : " ";
|
|
1322
1568
|
}
|
|
1323
1569
|
return /* @__PURE__ */ jsx13(Box8, { flexGrow: 1, minWidth: 1, children: /* @__PURE__ */ jsx13(Text8, { wrap: "end", children: displayContent }) });
|
|
1324
1570
|
}
|
|
1325
|
-
const lines =
|
|
1571
|
+
const lines = displayValue.split("\n");
|
|
1326
1572
|
const result = [];
|
|
1327
1573
|
let totalOffset = 0;
|
|
1328
1574
|
lines.forEach((line, lineIndex) => {
|
|
@@ -1330,7 +1576,7 @@ function BlinkingTextInput({
|
|
|
1330
1576
|
for (let i = 0; i < line.length; i++) {
|
|
1331
1577
|
const char = line[i];
|
|
1332
1578
|
if (totalOffset === state.cursorOffset) {
|
|
1333
|
-
lineContent += isCursorVisible ?
|
|
1579
|
+
lineContent += isCursorVisible ? chalk3.inverse(char) : char;
|
|
1334
1580
|
} else {
|
|
1335
1581
|
lineContent += char;
|
|
1336
1582
|
}
|
|
@@ -1338,12 +1584,12 @@ function BlinkingTextInput({
|
|
|
1338
1584
|
}
|
|
1339
1585
|
if (totalOffset === state.cursorOffset) {
|
|
1340
1586
|
if (lineIndex === lines.length - 1 && suggestion) {
|
|
1341
|
-
lineContent += (isCursorVisible ?
|
|
1587
|
+
lineContent += (isCursorVisible ? chalk3.inverse(suggestion[0]) : suggestion[0]) + chalk3.dim(suggestion.slice(1));
|
|
1342
1588
|
} else {
|
|
1343
|
-
lineContent += isCursorVisible ?
|
|
1589
|
+
lineContent += isCursorVisible ? chalk3.inverse(" ") : " ";
|
|
1344
1590
|
}
|
|
1345
1591
|
} else if (lineIndex === lines.length - 1 && suggestion) {
|
|
1346
|
-
lineContent +=
|
|
1592
|
+
lineContent += chalk3.dim(suggestion);
|
|
1347
1593
|
}
|
|
1348
1594
|
result.push(
|
|
1349
1595
|
/* @__PURE__ */ jsx13(Box8, { flexGrow: 1, children: /* @__PURE__ */ jsx13(Text8, { wrap: "end", children: lineContent }) }, lineIndex)
|
|
@@ -2005,7 +2251,7 @@ function DiffApprovalView() {
|
|
|
2005
2251
|
}
|
|
2006
2252
|
|
|
2007
2253
|
// ink/configurationWizard/ConfigurationWizard.tsx
|
|
2008
|
-
import { Box as Box18, useInput as
|
|
2254
|
+
import { Box as Box18, useInput as useInput11 } from "ink";
|
|
2009
2255
|
import { Step, Stepper } from "ink-stepper";
|
|
2010
2256
|
import { useEffect as useEffect12, useState as useState15 } from "react";
|
|
2011
2257
|
|
|
@@ -2030,12 +2276,11 @@ function updateEnvKeyForProvider(provider, key) {
|
|
|
2030
2276
|
}
|
|
2031
2277
|
|
|
2032
2278
|
// ink/configurationWizard/ApiKeyStep.tsx
|
|
2033
|
-
import { PasswordInput } from "@inkjs/ui";
|
|
2034
2279
|
import { Box as Box12, Text as Text12, useInput as useInput6 } from "ink";
|
|
2035
2280
|
import { useStepperInput } from "ink-stepper";
|
|
2036
2281
|
import { useEffect as useEffect7 } from "react";
|
|
2037
2282
|
import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
2038
|
-
function ApiKeyStep({ provider, onConfirm, onBack }) {
|
|
2283
|
+
function ApiKeyStep({ provider, defaultValue, onConfirm, onBack }) {
|
|
2039
2284
|
const { disableNavigation, enableNavigation } = useStepperInput();
|
|
2040
2285
|
useEffect7(() => {
|
|
2041
2286
|
disableNavigation();
|
|
@@ -2060,18 +2305,20 @@ function ApiKeyStep({ provider, onConfirm, onBack }) {
|
|
|
2060
2305
|
] }),
|
|
2061
2306
|
/* @__PURE__ */ jsx17(Text12, { dimColor: true, children: instructions[provider] }),
|
|
2062
2307
|
/* @__PURE__ */ jsx17(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx17(
|
|
2063
|
-
|
|
2308
|
+
BlinkingTextInput,
|
|
2064
2309
|
{
|
|
2310
|
+
isPassword: true,
|
|
2311
|
+
defaultValue,
|
|
2065
2312
|
onSubmit: (v) => {
|
|
2066
2313
|
if (v === "exit") {
|
|
2067
2314
|
emitToListeners("ExitUI", void 0);
|
|
2068
2315
|
} else {
|
|
2069
|
-
onConfirm(v);
|
|
2316
|
+
onConfirm(v || defaultValue || "");
|
|
2070
2317
|
}
|
|
2071
2318
|
}
|
|
2072
2319
|
}
|
|
2073
2320
|
) }),
|
|
2074
|
-
/* @__PURE__ */ jsx17(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text12, { dimColor: true, children: "Press
|
|
2321
|
+
/* @__PURE__ */ jsx17(Box12, { marginTop: 1, children: /* @__PURE__ */ jsx17(Text12, { dimColor: true, children: "Press <esc> to go back, <enter> to proceed" }) })
|
|
2075
2322
|
] });
|
|
2076
2323
|
}
|
|
2077
2324
|
|
|
@@ -2080,7 +2327,7 @@ import { Box as Box13, Text as Text13, useInput as useInput7 } from "ink";
|
|
|
2080
2327
|
import { useStepperInput as useStepperInput2 } from "ink-stepper";
|
|
2081
2328
|
import { useEffect as useEffect8 } from "react";
|
|
2082
2329
|
import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
2083
|
-
function ApiUrlStep({ provider, onConfirm, onBack }) {
|
|
2330
|
+
function ApiUrlStep({ provider, defaultValue, onConfirm, onBack }) {
|
|
2084
2331
|
const { disableNavigation, enableNavigation } = useStepperInput2();
|
|
2085
2332
|
useEffect8(() => {
|
|
2086
2333
|
disableNavigation();
|
|
@@ -2106,17 +2353,18 @@ function ApiUrlStep({ provider, onConfirm, onBack }) {
|
|
|
2106
2353
|
/* @__PURE__ */ jsx18(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx18(
|
|
2107
2354
|
BlinkingTextInput,
|
|
2108
2355
|
{
|
|
2356
|
+
defaultValue: defaultValue || "",
|
|
2109
2357
|
placeholder: defaultApi[provider] || "",
|
|
2110
2358
|
onSubmit: (v) => {
|
|
2111
2359
|
if (v === "exit") {
|
|
2112
2360
|
emitToListeners("ExitUI", void 0);
|
|
2113
2361
|
} else {
|
|
2114
|
-
onConfirm(v || defaultApi[provider] || "");
|
|
2362
|
+
onConfirm(v || defaultValue || defaultApi[provider] || "");
|
|
2115
2363
|
}
|
|
2116
2364
|
}
|
|
2117
2365
|
}
|
|
2118
2366
|
) }),
|
|
2119
|
-
/* @__PURE__ */ jsx18(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text13, { dimColor: true, children: "Press
|
|
2367
|
+
/* @__PURE__ */ jsx18(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx18(Text13, { dimColor: true, children: "Press <esc> to go back, <enter> to proceed" }) })
|
|
2120
2368
|
] });
|
|
2121
2369
|
}
|
|
2122
2370
|
|
|
@@ -2168,7 +2416,13 @@ function EnvironmentSettingsStep({ onConfirm, onBack }) {
|
|
|
2168
2416
|
label: s.label,
|
|
2169
2417
|
value: s.value
|
|
2170
2418
|
}));
|
|
2171
|
-
const defaultValues = SETTINGS.
|
|
2419
|
+
const defaultValues = SETTINGS.filter((s) => {
|
|
2420
|
+
const currentValue = process.env[s.value];
|
|
2421
|
+
if (currentValue === void 0) {
|
|
2422
|
+
return true;
|
|
2423
|
+
}
|
|
2424
|
+
return currentValue === s.defaultValue;
|
|
2425
|
+
}).map((s) => s.value);
|
|
2172
2426
|
const handleSubmit = (values) => {
|
|
2173
2427
|
for (const setting of SETTINGS) {
|
|
2174
2428
|
if (values.includes(setting.value)) {
|
|
@@ -2215,11 +2469,12 @@ var compactorModelsByProvider = {
|
|
|
2215
2469
|
import { Select } from "@inkjs/ui";
|
|
2216
2470
|
import { Box as Box15, Text as Text15, useInput as useInput9 } from "ink";
|
|
2217
2471
|
import { useStepperInput as useStepperInput4 } from "ink-stepper";
|
|
2218
|
-
import { useEffect as useEffect10, useState as useState14 } from "react";
|
|
2472
|
+
import { useEffect as useEffect10, useMemo as useMemo11, useState as useState14 } from "react";
|
|
2219
2473
|
import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
2220
2474
|
function ModelSelectionStep({
|
|
2221
2475
|
title,
|
|
2222
2476
|
models,
|
|
2477
|
+
defaultValue,
|
|
2223
2478
|
onConfirm,
|
|
2224
2479
|
onBack
|
|
2225
2480
|
}) {
|
|
@@ -2238,6 +2493,18 @@ function ModelSelectionStep({
|
|
|
2238
2493
|
}
|
|
2239
2494
|
}
|
|
2240
2495
|
});
|
|
2496
|
+
const modelOptions = useMemo11(() => {
|
|
2497
|
+
const defaultIndex = models.indexOf(defaultValue);
|
|
2498
|
+
const sortedModels = defaultIndex >= 0 && models[defaultIndex] ? [
|
|
2499
|
+
models[defaultIndex],
|
|
2500
|
+
...models.slice(0, defaultIndex),
|
|
2501
|
+
...models.slice(defaultIndex + 1)
|
|
2502
|
+
] : models;
|
|
2503
|
+
return [
|
|
2504
|
+
...sortedModels.map((m) => ({ label: m, value: m })),
|
|
2505
|
+
{ label: "Other...", value: "other" }
|
|
2506
|
+
];
|
|
2507
|
+
}, [models, defaultValue]);
|
|
2241
2508
|
if (isCustom) {
|
|
2242
2509
|
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", children: [
|
|
2243
2510
|
/* @__PURE__ */ jsxs14(Text15, { children: [
|
|
@@ -2247,16 +2514,17 @@ function ModelSelectionStep({
|
|
|
2247
2514
|
/* @__PURE__ */ jsx20(
|
|
2248
2515
|
BlinkingTextInput,
|
|
2249
2516
|
{
|
|
2517
|
+
defaultValue,
|
|
2250
2518
|
onSubmit: (v) => {
|
|
2251
2519
|
if (v === "exit") {
|
|
2252
2520
|
emitToListeners("ExitUI", void 0);
|
|
2253
2521
|
} else {
|
|
2254
|
-
onConfirm(v);
|
|
2522
|
+
onConfirm(v || defaultValue || "");
|
|
2255
2523
|
}
|
|
2256
2524
|
}
|
|
2257
2525
|
}
|
|
2258
2526
|
),
|
|
2259
|
-
/* @__PURE__ */ jsx20(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text15, { dimColor: true, children: "Press
|
|
2527
|
+
/* @__PURE__ */ jsx20(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text15, { dimColor: true, children: "Press <esc> to go back, <enter> to select" }) })
|
|
2260
2528
|
] });
|
|
2261
2529
|
}
|
|
2262
2530
|
return /* @__PURE__ */ jsxs14(Box15, { flexDirection: "column", children: [
|
|
@@ -2264,10 +2532,7 @@ function ModelSelectionStep({
|
|
|
2264
2532
|
/* @__PURE__ */ jsx20(
|
|
2265
2533
|
Select,
|
|
2266
2534
|
{
|
|
2267
|
-
options:
|
|
2268
|
-
...models.map((m) => ({ label: m, value: m })),
|
|
2269
|
-
{ label: "Other...", value: "other" }
|
|
2270
|
-
],
|
|
2535
|
+
options: modelOptions,
|
|
2271
2536
|
onChange: (v) => {
|
|
2272
2537
|
if (v === "other") {
|
|
2273
2538
|
setIsCustom(true);
|
|
@@ -2277,15 +2542,15 @@ function ModelSelectionStep({
|
|
|
2277
2542
|
}
|
|
2278
2543
|
}
|
|
2279
2544
|
),
|
|
2280
|
-
/* @__PURE__ */ jsx20(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text15, { dimColor: true, children: "Press
|
|
2545
|
+
/* @__PURE__ */ jsx20(Box15, { marginTop: 1, children: /* @__PURE__ */ jsx20(Text15, { dimColor: true, children: "Press <esc> to go back, <enter> to select" }) })
|
|
2281
2546
|
] });
|
|
2282
2547
|
}
|
|
2283
2548
|
|
|
2284
2549
|
// ink/configurationWizard/ProviderStep.tsx
|
|
2285
2550
|
import { Select as Select2 } from "@inkjs/ui";
|
|
2286
|
-
import { Box as Box16, Text as Text16 } from "ink";
|
|
2551
|
+
import { Box as Box16, Text as Text16, useInput as useInput10 } from "ink";
|
|
2287
2552
|
import { useStepperInput as useStepperInput5 } from "ink-stepper";
|
|
2288
|
-
import { useEffect as useEffect11 } from "react";
|
|
2553
|
+
import { useEffect as useEffect11, useMemo as useMemo12 } from "react";
|
|
2289
2554
|
|
|
2290
2555
|
// ink/configurationWizard/providers.ts
|
|
2291
2556
|
var providers = [
|
|
@@ -2297,21 +2562,31 @@ var providers = [
|
|
|
2297
2562
|
|
|
2298
2563
|
// ink/configurationWizard/ProviderStep.tsx
|
|
2299
2564
|
import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
2300
|
-
function ProviderStep({ onConfirm }) {
|
|
2565
|
+
function ProviderStep({ defaultValue, onConfirm, onExit }) {
|
|
2301
2566
|
const { disableNavigation, enableNavigation } = useStepperInput5();
|
|
2567
|
+
const sortedProviders = useMemo12(
|
|
2568
|
+
() => providers.sort((a, b) => a.label === defaultValue ? -1 : a.label.localeCompare(b.label)),
|
|
2569
|
+
[defaultValue]
|
|
2570
|
+
);
|
|
2302
2571
|
useEffect11(() => {
|
|
2303
2572
|
disableNavigation();
|
|
2304
2573
|
return () => enableNavigation();
|
|
2305
2574
|
}, [disableNavigation, enableNavigation]);
|
|
2575
|
+
useInput10((input, key) => {
|
|
2576
|
+
if (key.escape) {
|
|
2577
|
+
onExit();
|
|
2578
|
+
}
|
|
2579
|
+
});
|
|
2306
2580
|
return /* @__PURE__ */ jsxs15(Box16, { flexDirection: "column", children: [
|
|
2307
2581
|
/* @__PURE__ */ jsx21(Text16, { children: "What model provider would you like to use today?" }),
|
|
2308
2582
|
/* @__PURE__ */ jsx21(
|
|
2309
2583
|
Select2,
|
|
2310
2584
|
{
|
|
2311
|
-
options:
|
|
2585
|
+
options: sortedProviders,
|
|
2312
2586
|
onChange: (v) => onConfirm(v)
|
|
2313
2587
|
}
|
|
2314
|
-
)
|
|
2588
|
+
),
|
|
2589
|
+
/* @__PURE__ */ jsx21(Box16, { marginTop: 1, children: /* @__PURE__ */ jsx21(Text16, { dimColor: true, children: "Press <esc> to cancel, <enter> to select" }) })
|
|
2315
2590
|
] });
|
|
2316
2591
|
}
|
|
2317
2592
|
|
|
@@ -2355,7 +2630,9 @@ function StepperProgress({ steps, currentStep }) {
|
|
|
2355
2630
|
// ink/configurationWizard/ConfigurationWizard.tsx
|
|
2356
2631
|
import { jsx as jsx23, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2357
2632
|
function ConfigurationWizard({ onComplete }) {
|
|
2358
|
-
const [provider, setProvider] = useState15(
|
|
2633
|
+
const [provider, setProvider] = useState15(
|
|
2634
|
+
trackedState?.model && getProvider(trackedState.model) || "OpenAI"
|
|
2635
|
+
);
|
|
2359
2636
|
const [ollamaModels, setOllamaModels] = useState15([]);
|
|
2360
2637
|
useEffect12(() => {
|
|
2361
2638
|
if (provider === "Ollama") {
|
|
@@ -2366,10 +2643,13 @@ function ConfigurationWizard({ onComplete }) {
|
|
|
2366
2643
|
});
|
|
2367
2644
|
}
|
|
2368
2645
|
}, [provider]);
|
|
2369
|
-
|
|
2646
|
+
useInput11((input, key) => {
|
|
2370
2647
|
if (key.ctrl && input === "x") {
|
|
2371
2648
|
emitToListeners("ExitUI", void 0);
|
|
2372
2649
|
}
|
|
2650
|
+
if (key.escape) {
|
|
2651
|
+
onComplete();
|
|
2652
|
+
}
|
|
2373
2653
|
});
|
|
2374
2654
|
const models = provider === "Ollama" && ollamaModels.length > 0 ? [.../* @__PURE__ */ new Set([...ollamaModels, ...modelsByProvider[provider]])] : modelsByProvider[provider];
|
|
2375
2655
|
const compactorModels = provider === "Ollama" && ollamaModels.length > 0 ? [.../* @__PURE__ */ new Set([...ollamaModels, ...compactorModelsByProvider[provider]])] : compactorModelsByProvider[provider];
|
|
@@ -2384,16 +2664,19 @@ function ConfigurationWizard({ onComplete }) {
|
|
|
2384
2664
|
/* @__PURE__ */ jsx23(Step, { name: "AI Provider", children: ({ goNext }) => /* @__PURE__ */ jsx23(
|
|
2385
2665
|
ProviderStep,
|
|
2386
2666
|
{
|
|
2667
|
+
defaultValue: provider,
|
|
2387
2668
|
onConfirm: (p) => {
|
|
2388
2669
|
setProvider(p);
|
|
2389
2670
|
goNext();
|
|
2390
|
-
}
|
|
2671
|
+
},
|
|
2672
|
+
onExit: onComplete
|
|
2391
2673
|
}
|
|
2392
2674
|
) }),
|
|
2393
2675
|
/* @__PURE__ */ jsx23(Step, { name: provider !== "Ollama" ? "API Key" : "API", children: ({ goNext, goBack }) => provider !== "Ollama" ? /* @__PURE__ */ jsx23(
|
|
2394
2676
|
ApiKeyStep,
|
|
2395
2677
|
{
|
|
2396
2678
|
provider,
|
|
2679
|
+
defaultValue: process.env[getEnvVarForProvider(provider)] || "",
|
|
2397
2680
|
onConfirm: (key) => {
|
|
2398
2681
|
updateEnvKeyForProvider(provider, key);
|
|
2399
2682
|
goNext();
|
|
@@ -2404,6 +2687,7 @@ function ConfigurationWizard({ onComplete }) {
|
|
|
2404
2687
|
ApiUrlStep,
|
|
2405
2688
|
{
|
|
2406
2689
|
provider,
|
|
2690
|
+
defaultValue: process.env[getEnvVarForProvider(provider)] || "",
|
|
2407
2691
|
onConfirm: (key) => {
|
|
2408
2692
|
updateEnvKeyForProvider(provider, key);
|
|
2409
2693
|
goNext();
|
|
@@ -2416,6 +2700,7 @@ function ConfigurationWizard({ onComplete }) {
|
|
|
2416
2700
|
{
|
|
2417
2701
|
title: "What model would you like to use?",
|
|
2418
2702
|
models,
|
|
2703
|
+
defaultValue: trackedState?.model || "",
|
|
2419
2704
|
onConfirm: (m) => {
|
|
2420
2705
|
const finalModelName = provider === "Ollama" && !m.startsWith("ollama-") && !m.includes(":") ? `ollama-${m}` : m;
|
|
2421
2706
|
updateEnv("HARPER_AGENT_MODEL", finalModelName);
|
|
@@ -2429,6 +2714,7 @@ function ConfigurationWizard({ onComplete }) {
|
|
|
2429
2714
|
{
|
|
2430
2715
|
title: "What model should we use for memory compaction?",
|
|
2431
2716
|
models: compactorModels,
|
|
2717
|
+
defaultValue: trackedState?.compactionModel || "",
|
|
2432
2718
|
onConfirm: (m) => {
|
|
2433
2719
|
const finalModelName = provider === "Ollama" && !m.startsWith("ollama-") && !m.includes(":") ? `ollama-${m}` : m;
|
|
2434
2720
|
updateEnv("HARPER_AGENT_COMPACTION_MODEL", finalModelName);
|
|
@@ -2458,6 +2744,11 @@ function bootstrapConfig() {
|
|
|
2458
2744
|
render(/* @__PURE__ */ jsx24(MainConfig, { onComplete: resolve }));
|
|
2459
2745
|
});
|
|
2460
2746
|
}
|
|
2747
|
+
async function showConfigThenReparse() {
|
|
2748
|
+
await bootstrapConfig();
|
|
2749
|
+
parseArgs();
|
|
2750
|
+
bootstrapMain();
|
|
2751
|
+
}
|
|
2461
2752
|
function MainConfig({ onComplete }) {
|
|
2462
2753
|
const { exit } = useApp();
|
|
2463
2754
|
useListener("ExitUI", () => exit(), [exit]);
|
|
@@ -2475,249 +2766,6 @@ function MainChat() {
|
|
|
2475
2766
|
] }) }) }) }) }) });
|
|
2476
2767
|
}
|
|
2477
2768
|
|
|
2478
|
-
// utils/models/deprecations.ts
|
|
2479
|
-
import chalk2 from "chalk";
|
|
2480
|
-
var DEPRECATION_RULES = [
|
|
2481
|
-
// Redirect any gpt-4o variants (including dated and -mini) to gpt-5-nano
|
|
2482
|
-
{
|
|
2483
|
-
match: (name) => name.toLowerCase().startsWith("gpt-4o"),
|
|
2484
|
-
replacement: "gpt-5-nano",
|
|
2485
|
-
reason: "OpenAI gpt-4o family is deprecated in this agent"
|
|
2486
|
-
}
|
|
2487
|
-
];
|
|
2488
|
-
function getDeprecatedReplacement(modelName) {
|
|
2489
|
-
if (!modelName) {
|
|
2490
|
-
return null;
|
|
2491
|
-
}
|
|
2492
|
-
for (const rule of DEPRECATION_RULES) {
|
|
2493
|
-
if (rule.match(modelName)) {
|
|
2494
|
-
return { replacement: rule.replacement, rule };
|
|
2495
|
-
}
|
|
2496
|
-
}
|
|
2497
|
-
return null;
|
|
2498
|
-
}
|
|
2499
|
-
function warnAndPersistRedirect(original, envKey, replacement, reason) {
|
|
2500
|
-
const reasonSuffix = reason ? ` Reason: ${reason}.` : "";
|
|
2501
|
-
console.warn(
|
|
2502
|
-
chalk2.yellow(
|
|
2503
|
-
`Warning: model "${original}" is deprecated and will be redirected to "${replacement}". Your environment setting (${envKey}) has been updated.${reasonSuffix}`
|
|
2504
|
-
)
|
|
2505
|
-
);
|
|
2506
|
-
updateEnv(envKey, replacement);
|
|
2507
|
-
}
|
|
2508
|
-
|
|
2509
|
-
// utils/shell/cli.ts
|
|
2510
|
-
import chalk3 from "chalk";
|
|
2511
|
-
|
|
2512
|
-
// utils/package/getOwnPackageJson.ts
|
|
2513
|
-
import { readFileSync } from "fs";
|
|
2514
|
-
import { join } from "path";
|
|
2515
|
-
import { fileURLToPath } from "url";
|
|
2516
|
-
var __dirname = fileURLToPath(new URL(".", import.meta.url));
|
|
2517
|
-
function getOwnPackageJson() {
|
|
2518
|
-
try {
|
|
2519
|
-
const packageContents = readFileSync(join(__dirname, "../package.json"), "utf8");
|
|
2520
|
-
return JSON.parse(packageContents);
|
|
2521
|
-
} catch {
|
|
2522
|
-
return { name: "@harperfast/agent", version: "0.0.0" };
|
|
2523
|
-
}
|
|
2524
|
-
}
|
|
2525
|
-
|
|
2526
|
-
// utils/shell/cli.ts
|
|
2527
|
-
function isHelpRequest(args) {
|
|
2528
|
-
const helpVariants = ["--help", "-h", "help"];
|
|
2529
|
-
return args.some((arg) => helpVariants.includes(arg.toLowerCase()));
|
|
2530
|
-
}
|
|
2531
|
-
function isVersionRequest(args) {
|
|
2532
|
-
const versionVariants = ["--version", "-v", "version"];
|
|
2533
|
-
return args.some((arg) => versionVariants.includes(arg.toLowerCase()));
|
|
2534
|
-
}
|
|
2535
|
-
function handleHelp() {
|
|
2536
|
-
console.log(`
|
|
2537
|
-
${chalk3.bold("harper-agent")} - AI to help you with Harper app creation and modification
|
|
2538
|
-
|
|
2539
|
-
${chalk3.bold("USAGE")}
|
|
2540
|
-
$ harper-agent [options]
|
|
2541
|
-
$ harper-agent [command]
|
|
2542
|
-
|
|
2543
|
-
${chalk3.bold("OPTIONS")}
|
|
2544
|
-
-h, --help Show help information
|
|
2545
|
-
-v, --version Show version information
|
|
2546
|
-
-m, --model Specify the model to use (e.g., ${defaultOpenAIModel}, ${defaultAnthropicModel}, ${defaultOllamaModel})
|
|
2547
|
-
Can also be set via HARPER_AGENT_MODEL environment variable.
|
|
2548
|
-
For Ollama, use the ollama- prefix (e.g., ${defaultOllamaCompactionModel}).
|
|
2549
|
-
-c, --compaction-model Specify the compaction model to use (defaults to ${defaultOpenAICompactionModel}).
|
|
2550
|
-
Can also be set via HARPER_AGENT_COMPACTION_MODEL environment variable.
|
|
2551
|
-
-s, --session Specify a path to a SQLite database file to persist the chat session.
|
|
2552
|
-
Can also be set via HARPER_AGENT_SESSION environment variable.
|
|
2553
|
-
--max-turns Specify the maximum number of turns for the agent run.
|
|
2554
|
-
Can also be set via HARPER_AGENT_MAX_TURNS environment variable.
|
|
2555
|
-
--max-cost Specify the maximum cost (in USD) for the agent run.
|
|
2556
|
-
If exceeded, the agent will exit with a non-zero code.
|
|
2557
|
-
Can also be set via HARPER_AGENT_MAX_COST environment variable.
|
|
2558
|
-
--flex-tier Force the use of the flex service tier for lower costs but potentially
|
|
2559
|
-
more errors under high system load.
|
|
2560
|
-
Can also be set via HARPER_AGENT_FLEX_TIER=true environment variable.
|
|
2561
|
-
-p, --prompt Specify a prompt to be executed autonomously until completion.
|
|
2562
|
-
|
|
2563
|
-
${chalk3.bold("COMMANDS")}
|
|
2564
|
-
--help Show help information
|
|
2565
|
-
--version Show version information
|
|
2566
|
-
|
|
2567
|
-
${chalk3.bold("EXAMPLES")}
|
|
2568
|
-
$ harper-agent --help
|
|
2569
|
-
$ harper-agent --version
|
|
2570
|
-
$ harper-agent
|
|
2571
|
-
`);
|
|
2572
|
-
process.exit(0);
|
|
2573
|
-
}
|
|
2574
|
-
function handleVersion() {
|
|
2575
|
-
const pkg = getOwnPackageJson();
|
|
2576
|
-
console.log(pkg.version);
|
|
2577
|
-
process.exit(0);
|
|
2578
|
-
}
|
|
2579
|
-
|
|
2580
|
-
// lifecycle/parseArgs.ts
|
|
2581
|
-
function stripQuotes(str) {
|
|
2582
|
-
if (str.startsWith('"') && str.endsWith('"') || str.startsWith("'") && str.endsWith("'")) {
|
|
2583
|
-
return str.slice(1, -1);
|
|
2584
|
-
}
|
|
2585
|
-
return str;
|
|
2586
|
-
}
|
|
2587
|
-
function parseArgs() {
|
|
2588
|
-
const args = process.argv.slice(2);
|
|
2589
|
-
if (isHelpRequest(args)) {
|
|
2590
|
-
handleHelp();
|
|
2591
|
-
}
|
|
2592
|
-
if (isVersionRequest(args)) {
|
|
2593
|
-
handleVersion();
|
|
2594
|
-
}
|
|
2595
|
-
for (let i = 0; i < args.length; i++) {
|
|
2596
|
-
const arg = args[i];
|
|
2597
|
-
const flagPairs = [
|
|
2598
|
-
["model", ["--model", "-m", "model"]],
|
|
2599
|
-
["compactionModel", ["--compaction-model", "-c", "compaction-model"]],
|
|
2600
|
-
["sessionPath", ["--session", "-s", "session"]],
|
|
2601
|
-
["maxTurns", ["--max-turns"]],
|
|
2602
|
-
["maxCost", ["--max-cost"]],
|
|
2603
|
-
["rateLimitThreshold", ["--rate-limit-threshold"]],
|
|
2604
|
-
["prompt", ["--prompt", "-p"]]
|
|
2605
|
-
];
|
|
2606
|
-
let handled = false;
|
|
2607
|
-
for (const [key, prefixes] of flagPairs) {
|
|
2608
|
-
for (const prefix of prefixes) {
|
|
2609
|
-
if (arg === prefix) {
|
|
2610
|
-
if (args[i + 1]) {
|
|
2611
|
-
const val = stripQuotes(args[++i]);
|
|
2612
|
-
if (key === "maxTurns" || key === "maxCost" || key === "rateLimitThreshold") {
|
|
2613
|
-
trackedState[key] = parseFloat(val);
|
|
2614
|
-
} else {
|
|
2615
|
-
trackedState[key] = val;
|
|
2616
|
-
}
|
|
2617
|
-
}
|
|
2618
|
-
handled = true;
|
|
2619
|
-
break;
|
|
2620
|
-
} else if (arg.startsWith(`${prefix}=`)) {
|
|
2621
|
-
const val = stripQuotes(arg.slice(prefix.length + 1));
|
|
2622
|
-
if (key === "maxTurns" || key === "maxCost" || key === "rateLimitThreshold") {
|
|
2623
|
-
trackedState[key] = parseFloat(val);
|
|
2624
|
-
} else {
|
|
2625
|
-
trackedState[key] = val;
|
|
2626
|
-
}
|
|
2627
|
-
handled = true;
|
|
2628
|
-
break;
|
|
2629
|
-
}
|
|
2630
|
-
}
|
|
2631
|
-
if (handled) {
|
|
2632
|
-
break;
|
|
2633
|
-
}
|
|
2634
|
-
}
|
|
2635
|
-
if (handled) {
|
|
2636
|
-
continue;
|
|
2637
|
-
}
|
|
2638
|
-
if (arg === "--flex-tier") {
|
|
2639
|
-
trackedState.useFlexTier = true;
|
|
2640
|
-
} else if (arg === "--no-monitor-rate-limits") {
|
|
2641
|
-
trackedState.monitorRateLimits = false;
|
|
2642
|
-
} else if (arg === "--autonomous" || arg === "-a") {
|
|
2643
|
-
trackedState.autonomous = true;
|
|
2644
|
-
}
|
|
2645
|
-
}
|
|
2646
|
-
if (!trackedState.model && process.env.HARPER_AGENT_MODEL) {
|
|
2647
|
-
trackedState.model = process.env.HARPER_AGENT_MODEL;
|
|
2648
|
-
}
|
|
2649
|
-
if (!trackedState.compactionModel && process.env.HARPER_AGENT_COMPACTION_MODEL) {
|
|
2650
|
-
trackedState.compactionModel = process.env.HARPER_AGENT_COMPACTION_MODEL;
|
|
2651
|
-
}
|
|
2652
|
-
if (!trackedState.sessionPath && process.env.HARPER_AGENT_SESSION) {
|
|
2653
|
-
trackedState.sessionPath = process.env.HARPER_AGENT_SESSION;
|
|
2654
|
-
}
|
|
2655
|
-
if (process.env.HARPER_AGENT_MAX_TURNS) {
|
|
2656
|
-
trackedState.maxTurns = parseFloat(process.env.HARPER_AGENT_MAX_TURNS);
|
|
2657
|
-
}
|
|
2658
|
-
if (process.env.HARPER_AGENT_MAX_COST) {
|
|
2659
|
-
trackedState.maxCost = parseFloat(process.env.HARPER_AGENT_MAX_COST);
|
|
2660
|
-
}
|
|
2661
|
-
if (process.env.HARPER_AGENT_RATE_LIMIT_THRESHOLD) {
|
|
2662
|
-
trackedState.rateLimitThreshold = parseFloat(process.env.HARPER_AGENT_RATE_LIMIT_THRESHOLD);
|
|
2663
|
-
}
|
|
2664
|
-
if (process.env.HARPER_AGENT_MONITOR_RATE_LIMITS === "false") {
|
|
2665
|
-
trackedState.monitorRateLimits = false;
|
|
2666
|
-
}
|
|
2667
|
-
if (!trackedState.useFlexTier && isTrue(process.env.HARPER_AGENT_FLEX_TIER)) {
|
|
2668
|
-
trackedState.useFlexTier = true;
|
|
2669
|
-
}
|
|
2670
|
-
if (isTrue(process.env.HARPER_AGENT_AUTO_APPROVE_CODE_INTERPRETER)) {
|
|
2671
|
-
trackedState.autoApproveCodeInterpreter = true;
|
|
2672
|
-
}
|
|
2673
|
-
if (isTrue(process.env.HARPER_AGENT_AUTO_APPROVE_PATCHES)) {
|
|
2674
|
-
trackedState.autoApprovePatches = true;
|
|
2675
|
-
}
|
|
2676
|
-
if (isTrue(process.env.HARPER_AGENT_AUTO_APPROVE_SHELL)) {
|
|
2677
|
-
trackedState.autoApproveShell = true;
|
|
2678
|
-
}
|
|
2679
|
-
if (isTrue(process.env.HARPER_AGENT_AUTONOMOUS)) {
|
|
2680
|
-
trackedState.autonomous = true;
|
|
2681
|
-
}
|
|
2682
|
-
if (!trackedState.model || trackedState.model === defaultModelToken) {
|
|
2683
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
2684
|
-
trackedState.model = defaultAnthropicModel;
|
|
2685
|
-
} else if (process.env.GOOGLE_GENERATIVE_AI_API_KEY) {
|
|
2686
|
-
trackedState.model = defaultGoogleModel;
|
|
2687
|
-
} else if (process.env.OLLAMA_BASE_URL) {
|
|
2688
|
-
trackedState.model = defaultOllamaModel;
|
|
2689
|
-
} else {
|
|
2690
|
-
trackedState.model = defaultOpenAIModel;
|
|
2691
|
-
}
|
|
2692
|
-
}
|
|
2693
|
-
if (!trackedState.compactionModel || trackedState.compactionModel === defaultModelToken) {
|
|
2694
|
-
const m = trackedState.model;
|
|
2695
|
-
if (m.startsWith("claude-")) {
|
|
2696
|
-
trackedState.compactionModel = defaultAnthropicCompactionModel;
|
|
2697
|
-
} else if (m.startsWith("gemini-")) {
|
|
2698
|
-
trackedState.compactionModel = defaultGoogleCompactionModel;
|
|
2699
|
-
} else if (m.startsWith("ollama-")) {
|
|
2700
|
-
trackedState.compactionModel = defaultOllamaCompactionModel;
|
|
2701
|
-
} else {
|
|
2702
|
-
trackedState.compactionModel = defaultOpenAICompactionModel;
|
|
2703
|
-
}
|
|
2704
|
-
}
|
|
2705
|
-
if (!isOpenAIModel(trackedState.model)) {
|
|
2706
|
-
process.env.OPENAI_AGENTS_DISABLE_TRACING = process.env.OPENAI_AGENTS_DISABLE_TRACING || "1";
|
|
2707
|
-
}
|
|
2708
|
-
const maybeRedirect = (current, envKey) => {
|
|
2709
|
-
const hit = getDeprecatedReplacement(current);
|
|
2710
|
-
if (hit) {
|
|
2711
|
-
const { replacement, rule } = hit;
|
|
2712
|
-
warnAndPersistRedirect(current, envKey, replacement, rule.reason);
|
|
2713
|
-
return replacement;
|
|
2714
|
-
}
|
|
2715
|
-
return current;
|
|
2716
|
-
};
|
|
2717
|
-
trackedState.model = maybeRedirect(trackedState.model, "HARPER_AGENT_MODEL");
|
|
2718
|
-
trackedState.compactionModel = maybeRedirect(trackedState.compactionModel, "HARPER_AGENT_COMPACTION_MODEL");
|
|
2719
|
-
}
|
|
2720
|
-
|
|
2721
2769
|
// utils/envLoader.ts
|
|
2722
2770
|
import dotenv from "dotenv";
|
|
2723
2771
|
import { existsSync } from "fs";
|
package/dist/index.js
CHANGED
package/dist/schema.graphql
CHANGED
|
@@ -78,41 +78,41 @@ updatedAt: Date @updatedTime
|
|
|
78
78
|
```
|
|
79
79
|
"""
|
|
80
80
|
directive @table(
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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
116
|
) on OBJECT
|
|
117
117
|
|
|
118
118
|
"""
|
|
@@ -120,21 +120,21 @@ Expose the table via the REST API. When applied to a `@table` type, routes are
|
|
|
120
120
|
generated using the type name or the provided alias.
|
|
121
121
|
"""
|
|
122
122
|
directive @export(
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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
138
|
) on OBJECT
|
|
139
139
|
"""
|
|
140
140
|
As a NoSQL database, HarperDB supports heterogeneous records (also referred to as
|
|
@@ -170,38 +170,38 @@ Create an index for the annotated field. Supports traditional and vector/ANN
|
|
|
170
170
|
index types.
|
|
171
171
|
"""
|
|
172
172
|
directive @indexed(
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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
205
|
) on FIELD_DEFINITION
|
|
206
206
|
|
|
207
207
|
"""
|
|
@@ -209,15 +209,15 @@ Define a derived field whose value is computed from other fields.
|
|
|
209
209
|
Useful for denormalized or presentation-friendly data.
|
|
210
210
|
"""
|
|
211
211
|
directive @computed(
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
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
221
|
) on FIELD_DEFINITION
|
|
222
222
|
"""
|
|
223
223
|
Automatically sets this field to the record's creation timestamp. The server
|
|
@@ -234,12 +234,12 @@ Declares a relationship to another record or records.
|
|
|
234
234
|
Use on fields that should resolve to related entities by ID.
|
|
235
235
|
"""
|
|
236
236
|
directive @relationship(
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
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
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.16",
|
|
5
5
|
"main": "dist/cli.js",
|
|
6
6
|
"repository": "github:HarperFast/harper-agent",
|
|
7
7
|
"bugs": {
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"scripts": {
|
|
12
12
|
"dev": "tsup index.ts cli.ts --format esm --clean --dts --watch --external puppeteer",
|
|
13
13
|
"link": "npm run build && npm link",
|
|
14
|
-
"build": "tsup index.ts cli.ts --format esm --clean --dts --external puppeteer && cp node_modules/
|
|
14
|
+
"build": "tsup index.ts cli.ts --format esm --clean --dts --external puppeteer && cp node_modules/harper/schema.graphql dist/",
|
|
15
15
|
"commitlint": "commitlint --edit",
|
|
16
16
|
"start": "node ./dist/cli.js",
|
|
17
17
|
"lint": "oxlint --format stylish .",
|
|
@@ -84,7 +84,7 @@
|
|
|
84
84
|
"conventional-changelog-conventionalcommits": "^9.1.0",
|
|
85
85
|
"dprint": "^0.53.0",
|
|
86
86
|
"express": "^5.2.1",
|
|
87
|
-
"
|
|
87
|
+
"harper": "^5.0.10",
|
|
88
88
|
"hono": "^4.11.9",
|
|
89
89
|
"husky": "^9.1.7",
|
|
90
90
|
"ink-testing-library": "^4.0.0",
|