@lazyingart/agintiflow 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -2
- package/docs/project-agent-lessons.md +41 -0
- package/package.json +1 -1
- package/public/app.js +225 -11
- package/public/index.html +41 -0
- package/public/styles.css +115 -5
- package/scripts/smoke-coding-tools.js +19 -4
- package/scripts/smoke-web-api.js +43 -0
- package/src/agent-runner.js +14 -0
- package/src/cli.js +179 -0
- package/src/config.js +6 -2
- package/src/model-client.js +28 -7
- package/src/project.js +332 -0
- package/src/task-profiles.js +85 -0
- package/src/web-db.js +6 -2
- package/web.js +47 -6
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
export const TASK_PROFILES = {
|
|
2
|
+
auto: {
|
|
3
|
+
id: "auto",
|
|
4
|
+
label: "Auto",
|
|
5
|
+
prompt:
|
|
6
|
+
"Infer the task type from the user request. Prefer the smallest safe tool sequence, preserve workspace files, and summarize what changed.",
|
|
7
|
+
tools: ["browser", "shell", "files", "canvas"],
|
|
8
|
+
},
|
|
9
|
+
code: {
|
|
10
|
+
id: "code",
|
|
11
|
+
label: "Code writing",
|
|
12
|
+
prompt:
|
|
13
|
+
"Act like a coding agent: inspect files first, make targeted workspace-local edits, run relevant checks, and report changed files and residual risks.",
|
|
14
|
+
tools: ["files", "shell", "sandbox"],
|
|
15
|
+
},
|
|
16
|
+
writing: {
|
|
17
|
+
id: "writing",
|
|
18
|
+
label: "Book/script writing",
|
|
19
|
+
prompt:
|
|
20
|
+
"Create structured drafts with outlines, sections, and revision notes. Use files for long-form output and canvas for important drafts.",
|
|
21
|
+
tools: ["files", "canvas"],
|
|
22
|
+
},
|
|
23
|
+
design: {
|
|
24
|
+
id: "design",
|
|
25
|
+
label: "Design docs",
|
|
26
|
+
prompt:
|
|
27
|
+
"Produce concise design documents with goals, constraints, options, tradeoffs, implementation steps, and verification criteria.",
|
|
28
|
+
tools: ["files", "canvas"],
|
|
29
|
+
},
|
|
30
|
+
python: {
|
|
31
|
+
id: "python",
|
|
32
|
+
label: "Python",
|
|
33
|
+
prompt:
|
|
34
|
+
"For Python tasks, create small scripts or notebooks as files, prefer virtual environments or Docker for package setup, and run smoke checks when shell is enabled.",
|
|
35
|
+
tools: ["files", "shell", "sandbox"],
|
|
36
|
+
},
|
|
37
|
+
shell: {
|
|
38
|
+
id: "shell",
|
|
39
|
+
label: "Shell",
|
|
40
|
+
prompt:
|
|
41
|
+
"For shell tasks, use allowlisted commands, explain blocked commands, avoid destructive operations, and keep outputs concise.",
|
|
42
|
+
tools: ["shell", "sandbox"],
|
|
43
|
+
},
|
|
44
|
+
node: {
|
|
45
|
+
id: "node",
|
|
46
|
+
label: "Node",
|
|
47
|
+
prompt:
|
|
48
|
+
"For Node.js tasks, inspect package scripts, use npm checks/tests when safe, and keep generated files inside the project workspace.",
|
|
49
|
+
tools: ["files", "shell", "sandbox"],
|
|
50
|
+
},
|
|
51
|
+
aaps: {
|
|
52
|
+
id: "aaps",
|
|
53
|
+
label: "AAPS",
|
|
54
|
+
prompt:
|
|
55
|
+
"For AAPS tasks, recognize .aaps folders and @lazyingart/aaps package workflows. Prefer project-local config, safe publish preparation, and explicit secret handling.",
|
|
56
|
+
tools: ["files", "shell", "sandbox"],
|
|
57
|
+
},
|
|
58
|
+
latex: {
|
|
59
|
+
id: "latex",
|
|
60
|
+
label: "LaTeX",
|
|
61
|
+
prompt:
|
|
62
|
+
"For LaTeX/PDF tasks, create source and figures in a subfolder, compile when a TeX toolchain is available, and send the PDF through the canvas tunnel.",
|
|
63
|
+
tools: ["files", "shell", "canvas", "sandbox"],
|
|
64
|
+
},
|
|
65
|
+
maintenance: {
|
|
66
|
+
id: "maintenance",
|
|
67
|
+
label: "System maintenance",
|
|
68
|
+
prompt:
|
|
69
|
+
"For system maintenance, diagnose first, prefer idempotent scripts, ask for approval before privileged or destructive operations, and avoid leaking credentials.",
|
|
70
|
+
tools: ["shell", "sandbox", "files"],
|
|
71
|
+
},
|
|
72
|
+
};
|
|
73
|
+
|
|
74
|
+
export function listTaskProfiles() {
|
|
75
|
+
return Object.values(TASK_PROFILES);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function normalizeTaskProfile(value = "auto") {
|
|
79
|
+
const key = String(value || "auto").trim().toLowerCase();
|
|
80
|
+
return TASK_PROFILES[key] ? key : "auto";
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function getTaskProfile(value = "auto") {
|
|
84
|
+
return TASK_PROFILES[normalizeTaskProfile(value)];
|
|
85
|
+
}
|
package/src/web-db.js
CHANGED
|
@@ -3,7 +3,7 @@ import path from "node:path";
|
|
|
3
3
|
import { DatabaseSync } from "node:sqlite";
|
|
4
4
|
import { getModelPresets } from "./model-routing.js";
|
|
5
5
|
|
|
6
|
-
const PREFERENCES_SCHEMA_VERSION =
|
|
6
|
+
const PREFERENCES_SCHEMA_VERSION = 3;
|
|
7
7
|
|
|
8
8
|
function defaultPreferences(baseDir) {
|
|
9
9
|
const presets = getModelPresets();
|
|
@@ -16,7 +16,7 @@ function defaultPreferences(baseDir) {
|
|
|
16
16
|
maxSteps: 15,
|
|
17
17
|
startUrl: "",
|
|
18
18
|
allowedDomains: "",
|
|
19
|
-
commandCwd: path.resolve(baseDir
|
|
19
|
+
commandCwd: path.resolve(baseDir),
|
|
20
20
|
allowShellTool: true,
|
|
21
21
|
allowFileTools: true,
|
|
22
22
|
allowWrapperTools: false,
|
|
@@ -29,6 +29,7 @@ function defaultPreferences(baseDir) {
|
|
|
29
29
|
allowPasswords: false,
|
|
30
30
|
allowDestructive: false,
|
|
31
31
|
language: "en",
|
|
32
|
+
taskProfile: "auto",
|
|
32
33
|
};
|
|
33
34
|
}
|
|
34
35
|
|
|
@@ -81,6 +82,9 @@ export class WebDatabase {
|
|
|
81
82
|
};
|
|
82
83
|
if ((parsed.preferencesSchemaVersion || 1) < PREFERENCES_SCHEMA_VERSION) {
|
|
83
84
|
preferences.preferencesSchemaVersion = PREFERENCES_SCHEMA_VERSION;
|
|
85
|
+
if (!parsed.commandCwd || parsed.commandCwd === path.resolve(this.baseDir, "..")) {
|
|
86
|
+
preferences.commandCwd = path.resolve(this.baseDir);
|
|
87
|
+
}
|
|
84
88
|
if (["host", "docker-readonly"].includes(parsed.sandboxMode || "")) {
|
|
85
89
|
preferences.sandboxMode = "docker-workspace";
|
|
86
90
|
preferences.useDockerSandbox = true;
|
package/web.js
CHANGED
|
@@ -11,6 +11,8 @@ import { listAgentWrappers, normalizeWrapperName } from "./src/tool-wrappers.js"
|
|
|
11
11
|
import { getDockerSandboxStatus, getSandboxLogs, runDockerPreflight } from "./src/docker-sandbox.js";
|
|
12
12
|
import { normalizePackageInstallPolicy, normalizeSandboxMode } from "./src/command-policy.js";
|
|
13
13
|
import { summarizeWorkspaceTools, WORKSPACE_TOOL_NAMES } from "./src/workspace-tools.js";
|
|
14
|
+
import { listTaskProfiles, normalizeTaskProfile } from "./src/task-profiles.js";
|
|
15
|
+
import { loadProjectEnv, projectPaths, providerKeyStatus, setProviderKey } from "./src/project.js";
|
|
14
16
|
import {
|
|
15
17
|
buildArtifacts,
|
|
16
18
|
countUnreadArtifacts,
|
|
@@ -24,6 +26,7 @@ const __dirname = path.dirname(__filename);
|
|
|
24
26
|
const packageDir = __dirname;
|
|
25
27
|
const baseDir = path.resolve(process.env.AGINTIFLOW_RUNTIME_DIR || process.cwd());
|
|
26
28
|
const sessionsDir = path.join(baseDir, ".sessions");
|
|
29
|
+
loadProjectEnv(baseDir);
|
|
27
30
|
|
|
28
31
|
const app = express();
|
|
29
32
|
const port = Number(process.env.PORT || 3210);
|
|
@@ -132,7 +135,8 @@ function normalizePreferencePayload(body = {}, current = db.getPreferences()) {
|
|
|
132
135
|
commandCwd:
|
|
133
136
|
typeof body.commandCwd === "string" && body.commandCwd.trim()
|
|
134
137
|
? body.commandCwd.trim()
|
|
135
|
-
: current.commandCwd ||
|
|
138
|
+
: current.commandCwd || baseDir,
|
|
139
|
+
taskProfile: normalizeTaskProfile(body.taskProfile || current.taskProfile || "auto"),
|
|
136
140
|
allowShellTool: typeof body.allowShellTool === "boolean" ? body.allowShellTool : Boolean(current.allowShellTool),
|
|
137
141
|
allowFileTools: typeof body.allowFileTools === "boolean" ? body.allowFileTools : current.allowFileTools !== false,
|
|
138
142
|
allowWrapperTools:
|
|
@@ -172,6 +176,17 @@ function publicProviderDefault(provider) {
|
|
|
172
176
|
};
|
|
173
177
|
}
|
|
174
178
|
|
|
179
|
+
function publicKeyStatus(projectRoot = baseDir) {
|
|
180
|
+
const status = providerKeyStatus(projectRoot);
|
|
181
|
+
return {
|
|
182
|
+
openai: status.openai,
|
|
183
|
+
deepseek: status.deepseek,
|
|
184
|
+
mock: true,
|
|
185
|
+
localEnv: status.localEnv,
|
|
186
|
+
envVars: status.envVars,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
|
|
175
190
|
function buildRunConfig(body, overrides = {}) {
|
|
176
191
|
const preferences = normalizePreferencePayload(body, db.getPreferences());
|
|
177
192
|
const merged = {
|
|
@@ -208,6 +223,7 @@ function buildRunConfig(body, overrides = {}) {
|
|
|
208
223
|
useDockerSandbox: merged.useDockerSandbox,
|
|
209
224
|
dockerSandboxImage: merged.dockerSandboxImage,
|
|
210
225
|
commandCwd: merged.commandCwd,
|
|
226
|
+
taskProfile: merged.taskProfile,
|
|
211
227
|
baseDir,
|
|
212
228
|
packageDir,
|
|
213
229
|
sessionId: overrides.sessionId,
|
|
@@ -485,7 +501,17 @@ app.get("/api/config", async (_req, res) => {
|
|
|
485
501
|
await syncStoredSessions();
|
|
486
502
|
const preferences = normalizePreferencePayload({}, db.getPreferences());
|
|
487
503
|
const config = buildRunConfig({ ...preferences, goal: "" });
|
|
504
|
+
const paths = projectPaths(baseDir);
|
|
505
|
+
const keyStatus = publicKeyStatus(baseDir);
|
|
488
506
|
res.json({
|
|
507
|
+
project: {
|
|
508
|
+
root: paths.root,
|
|
509
|
+
commandCwd: config.commandCwd,
|
|
510
|
+
sessionsDir,
|
|
511
|
+
sessionDbPath: paths.sessionDbPath,
|
|
512
|
+
sharedSessionFolder: path.resolve(config.sessionsDir) === path.resolve(sessionsDir),
|
|
513
|
+
localEnvPresent: keyStatus.localEnv,
|
|
514
|
+
},
|
|
489
515
|
defaults: {
|
|
490
516
|
openai: publicProviderDefault("openai"),
|
|
491
517
|
deepseek: publicProviderDefault("deepseek"),
|
|
@@ -493,6 +519,7 @@ app.get("/api/config", async (_req, res) => {
|
|
|
493
519
|
headless: true,
|
|
494
520
|
maxSteps: 15,
|
|
495
521
|
},
|
|
522
|
+
taskProfiles: listTaskProfiles(),
|
|
496
523
|
routing: {
|
|
497
524
|
modes: ["smart", "fast", "complex", "manual"],
|
|
498
525
|
presets: getModelPresets(),
|
|
@@ -503,15 +530,29 @@ app.get("/api/config", async (_req, res) => {
|
|
|
503
530
|
},
|
|
504
531
|
workspace: summarizeWorkspaceTools(config),
|
|
505
532
|
preferences,
|
|
506
|
-
keyStatus
|
|
507
|
-
openai: Boolean(process.env.OPENAI_API_KEY),
|
|
508
|
-
deepseek: Boolean(process.env.DEEPSEEK_API_KEY),
|
|
509
|
-
mock: true,
|
|
510
|
-
},
|
|
533
|
+
keyStatus,
|
|
511
534
|
sessions: db.listSessions(100),
|
|
512
535
|
});
|
|
513
536
|
});
|
|
514
537
|
|
|
538
|
+
app.get("/api/keys/status", (_req, res) => {
|
|
539
|
+
res.json({ ok: true, keyStatus: publicKeyStatus(baseDir) });
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
app.post("/api/keys/:provider", async (req, res) => {
|
|
543
|
+
try {
|
|
544
|
+
const result = await setProviderKey(baseDir, req.params.provider, req.body?.apiKey || req.body?.key || "");
|
|
545
|
+
res.json({
|
|
546
|
+
ok: true,
|
|
547
|
+
provider: result.provider,
|
|
548
|
+
keyName: result.keyName,
|
|
549
|
+
keyStatus: publicKeyStatus(baseDir),
|
|
550
|
+
});
|
|
551
|
+
} catch (error) {
|
|
552
|
+
res.status(400).json({ error: error instanceof Error ? error.message : String(error) });
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
|
|
515
556
|
app.get("/api/sandbox/status", async (_req, res) => {
|
|
516
557
|
const config = buildRunConfig({ ...db.getPreferences(), goal: "" });
|
|
517
558
|
const status = await getDockerSandboxStatus(config);
|