@lazyingart/agintiflow 0.20.123 → 0.20.124
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 +3 -1
- package/package.json +6 -2
- package/scripts/postinstall-webapp.js +23 -0
- package/scripts/smoke-cli-chat.js +10 -0
- package/scripts/smoke-webapp-command.js +97 -0
- package/src/cli.js +15 -1
- package/src/i18n.js +1 -0
- package/src/interactive-cli.js +46 -15
- package/src/web-autostart.js +2 -1
package/README.md
CHANGED
|
@@ -103,7 +103,9 @@ Provider signup and key pages:
|
|
|
103
103
|
| Qwen / DashScope | [https://bailian.console.aliyun.com/](https://bailian.console.aliyun.com/) | `https://dashscope-intl.aliyuncs.com/compatible-mode/v1` |
|
|
104
104
|
| GRS AI image tools | [https://grsai.ai/dashboard/api-keys](https://grsai.ai/dashboard/api-keys) | Configure with `/auxiliary grsai` or `aginti login grsai` |
|
|
105
105
|
|
|
106
|
-
The CLI auto-starts or reuses the local web UI from the same project. It tries `http://127.0.0.1:3210` first, then `3211`, `3212`, and so on if the port is already occupied. The active URL is shown in the CLI launch header.
|
|
106
|
+
The CLI quietly auto-starts or reuses the local web UI from the same project. It tries `http://127.0.0.1:3210` first, then `3211`, `3212`, and so on if the port is already occupied. The active URL is shown in the CLI launch header. If startup is blocked or unavailable, the same header row shows the recovery hint; run `/webapp [port]` inside the CLI to retry.
|
|
107
|
+
|
|
108
|
+
Package installation also makes a best-effort, non-blocking webapp initialization. Install never fails because the optional local webapp could not start.
|
|
107
109
|
|
|
108
110
|
Launch the web UI explicitly when you want a foreground web server:
|
|
109
111
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.124",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -50,6 +50,7 @@
|
|
|
50
50
|
"scripts/install-docker-ubuntu.sh",
|
|
51
51
|
"scripts/setup-agent-toolchain-docker.sh",
|
|
52
52
|
"scripts/real-deepseek-capabilities.js",
|
|
53
|
+
"scripts/postinstall-webapp.js",
|
|
53
54
|
"scripts/smoke-auxiliary-tools.js",
|
|
54
55
|
"scripts/smoke-auth.js",
|
|
55
56
|
"scripts/smoke-aaps-adapter.js",
|
|
@@ -70,6 +71,7 @@
|
|
|
70
71
|
"scripts/smoke-toolchain-docker.js",
|
|
71
72
|
"scripts/smoke-web-autostart.js",
|
|
72
73
|
"scripts/smoke-web-api.js",
|
|
74
|
+
"scripts/smoke-webapp-command.js",
|
|
73
75
|
"scripts/smoke-web-port-fallback.js",
|
|
74
76
|
"src/",
|
|
75
77
|
"run.js",
|
|
@@ -103,12 +105,14 @@
|
|
|
103
105
|
"smoke:tmux-tools": "node scripts/smoke-tmux-tools.js",
|
|
104
106
|
"smoke:web-api": "node scripts/smoke-web-api.js",
|
|
105
107
|
"smoke:web-autostart": "node scripts/smoke-web-autostart.js",
|
|
108
|
+
"smoke:webapp-command": "node scripts/smoke-webapp-command.js",
|
|
106
109
|
"smoke:web-port-fallback": "node scripts/smoke-web-port-fallback.js",
|
|
107
110
|
"smoke:autoupdate": "node scripts/smoke-auto-update.js",
|
|
108
111
|
"real:deepseek": "node scripts/real-deepseek-capabilities.js",
|
|
112
|
+
"postinstall": "node scripts/postinstall-webapp.js",
|
|
109
113
|
"supervision:seed": "node scripts/seed-supervised-homework.js",
|
|
110
114
|
"storage:migrate": "node bin/aginti-cli.js storage migrate",
|
|
111
|
-
"test": "npm run check && npm run smoke:autoupdate && npm run smoke:web-api && npm run smoke:web-autostart && npm run smoke:web-port-fallback && npm run smoke:coding-tools && npm run smoke:dynamic-step-budget && npm run smoke:aaps-adapter && npm run smoke:auxiliary-tools && npm run smoke:perception-research && npm run smoke:auth && npm run smoke:canvas-artifacts && npm run smoke:capabilities && npm run smoke:model-roles && npm run smoke:platform && npm run smoke:permission-modes && npm run smoke:skills && npm run smoke:skillmesh && npm run smoke:tmux-tools && npm run smoke:cli-chat && npm run smoke:inbox",
|
|
115
|
+
"test": "npm run check && npm run smoke:autoupdate && npm run smoke:web-api && npm run smoke:web-autostart && npm run smoke:webapp-command && npm run smoke:web-port-fallback && npm run smoke:coding-tools && npm run smoke:dynamic-step-budget && npm run smoke:aaps-adapter && npm run smoke:auxiliary-tools && npm run smoke:perception-research && npm run smoke:auth && npm run smoke:canvas-artifacts && npm run smoke:capabilities && npm run smoke:model-roles && npm run smoke:platform && npm run smoke:permission-modes && npm run smoke:skills && npm run smoke:skillmesh && npm run smoke:tmux-tools && npm run smoke:cli-chat && npm run smoke:inbox",
|
|
112
116
|
"pack:dry-run": "npm pack --dry-run",
|
|
113
117
|
"smoke:capabilities": "node scripts/smoke-capabilities.js"
|
|
114
118
|
},
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
import { ensureAgintiWebApp } from "../src/web-autostart.js";
|
|
5
|
+
|
|
6
|
+
const packageDir = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
7
|
+
const cwd = process.env.INIT_CWD || process.cwd();
|
|
8
|
+
|
|
9
|
+
if (process.env.CI === "true" || process.env.AGINTIFLOW_SKIP_POSTINSTALL_WEBAPP === "1") {
|
|
10
|
+
process.exit(0);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
try {
|
|
14
|
+
await ensureAgintiWebApp({
|
|
15
|
+
packageDir,
|
|
16
|
+
cwd,
|
|
17
|
+
host: process.env.AGINTI_WEB_HOST || "127.0.0.1",
|
|
18
|
+
preferredPort: process.env.AGINTI_WEB_PORT || 3210,
|
|
19
|
+
language: process.env.AGINTI_LANGUAGE || "",
|
|
20
|
+
});
|
|
21
|
+
} catch {
|
|
22
|
+
// Installation must not fail because the optional local webapp could not be started.
|
|
23
|
+
}
|
|
@@ -326,6 +326,15 @@ try {
|
|
|
326
326
|
if (!launchHeaderWithWeb.includes("webapp: http://127.0.0.1:3210")) {
|
|
327
327
|
throw new Error("launch header did not render the active webapp URL in the tagline row");
|
|
328
328
|
}
|
|
329
|
+
const launchHeaderWithWebError = buildLaunchHeaderLines({
|
|
330
|
+
width: 120,
|
|
331
|
+
packageVersion: "0.0.0",
|
|
332
|
+
animated: false,
|
|
333
|
+
webAppNotice: "webapp unavailable - use /webapp to retry; error: smoke failure",
|
|
334
|
+
}).join("\n");
|
|
335
|
+
if (!launchHeaderWithWebError.includes("webapp unavailable - use /webapp to retry")) {
|
|
336
|
+
throw new Error("launch header did not render webapp recovery advice in the tagline row");
|
|
337
|
+
}
|
|
329
338
|
if (
|
|
330
339
|
formatElapsedDuration(0) !== "00:00" ||
|
|
331
340
|
formatElapsedDuration(65_000) !== "01:05" ||
|
|
@@ -650,6 +659,7 @@ try {
|
|
|
650
659
|
!helpResult.stdout.includes("/auxiliary") ||
|
|
651
660
|
!helpResult.stdout.includes("/review") ||
|
|
652
661
|
!helpResult.stdout.includes("/scs") ||
|
|
662
|
+
!helpResult.stdout.includes("/webapp") ||
|
|
653
663
|
!helpResult.stdout.includes("/safe") ||
|
|
654
664
|
helpResult.stdout.includes("helpReview") ||
|
|
655
665
|
helpResult.stdout.includes("helpRename") ||
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFile as execFileCallback, spawn } from "node:child_process";
|
|
3
|
+
import fs from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import { promisify } from "node:util";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
|
|
9
|
+
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
10
|
+
const runtimeDir = await fs.mkdtemp(path.join(os.tmpdir(), "agintiflow-webapp-command-"));
|
|
11
|
+
const execFile = promisify(execFileCallback);
|
|
12
|
+
|
|
13
|
+
function delay(ms) {
|
|
14
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
async function waitFor(predicate, child, label, output) {
|
|
18
|
+
const deadline = Date.now() + 12000;
|
|
19
|
+
while (Date.now() < deadline) {
|
|
20
|
+
if (predicate()) return true;
|
|
21
|
+
if (child.exitCode !== null) break;
|
|
22
|
+
await delay(150);
|
|
23
|
+
}
|
|
24
|
+
const { stdout, stderr } = output;
|
|
25
|
+
throw new Error(`${label} timed out. stdout=${stdout.slice(-1000)} stderr=${stderr.slice(-1000)}`);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async function killPort(port) {
|
|
29
|
+
try {
|
|
30
|
+
const { stdout: pids } = await execFile("lsof", [`-tiTCP:${port}`, "-sTCP:LISTEN"]);
|
|
31
|
+
for (const pid of pids.split(/\s+/).filter(Boolean)) {
|
|
32
|
+
try {
|
|
33
|
+
process.kill(Number(pid), "SIGTERM");
|
|
34
|
+
} catch {
|
|
35
|
+
// Ignore already-exited listeners.
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
} catch {
|
|
39
|
+
// lsof may be unavailable; the temporary port listener will otherwise be reusable by later tests.
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function runCase({ port, env = {}, expectHeader, label }) {
|
|
44
|
+
const output = { stdout: "", stderr: "" };
|
|
45
|
+
const child = spawn(process.execPath, [path.join(repoRoot, "bin/aginti-cli.js"), "chat", "--provider", "mock", "--routing", "manual", "--port", String(port)], {
|
|
46
|
+
cwd: runtimeDir,
|
|
47
|
+
env: {
|
|
48
|
+
...process.env,
|
|
49
|
+
AGINTIFLOW_NO_ANIMATION: "1",
|
|
50
|
+
AGINTIFLOW_HOME: path.join(runtimeDir, `.agintiflow-home-${label}`),
|
|
51
|
+
...env,
|
|
52
|
+
},
|
|
53
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
child.stdout.on("data", (chunk) => {
|
|
57
|
+
output.stdout += chunk.toString();
|
|
58
|
+
});
|
|
59
|
+
child.stderr.on("data", (chunk) => {
|
|
60
|
+
output.stderr += chunk.toString();
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
try {
|
|
64
|
+
await waitFor(() => output.stdout.includes(expectHeader), child, `${label} launch header`, output);
|
|
65
|
+
child.stdin.write(`/webapp ${port}\n`);
|
|
66
|
+
await waitFor(() => output.stdout.includes(`webapp=http://127.0.0.1:${port}`), child, `${label} /webapp command`, output);
|
|
67
|
+
const health = await fetch(`http://127.0.0.1:${port}/health`).then((response) => response.json());
|
|
68
|
+
if (!health.ok || health.app !== "agintiflow" || Number(health.port) !== port) {
|
|
69
|
+
throw new Error(`invalid /webapp health response for ${label}: ${JSON.stringify(health)}`);
|
|
70
|
+
}
|
|
71
|
+
} finally {
|
|
72
|
+
child.kill("SIGTERM");
|
|
73
|
+
await killPort(port);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const autoPort = 45600 + Math.floor(Math.random() * 300);
|
|
78
|
+
const manualPort = autoPort + 301;
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
await runCase({
|
|
82
|
+
port: autoPort,
|
|
83
|
+
expectHeader: `webapp: http://127.0.0.1:${autoPort}`,
|
|
84
|
+
label: "auto-start",
|
|
85
|
+
});
|
|
86
|
+
await runCase({
|
|
87
|
+
port: manualPort,
|
|
88
|
+
env: { AGINTIFLOW_NO_WEB_AUTO_START: "1" },
|
|
89
|
+
expectHeader: "webapp auto-start disabled - use /webapp to start manually",
|
|
90
|
+
label: "manual-disabled",
|
|
91
|
+
});
|
|
92
|
+
console.log(`webapp slash command smoke passed: http://127.0.0.1:${autoPort}, http://127.0.0.1:${manualPort}`);
|
|
93
|
+
} finally {
|
|
94
|
+
await killPort(autoPort);
|
|
95
|
+
await killPort(manualPort);
|
|
96
|
+
await fs.rm(runtimeDir, { recursive: true, force: true });
|
|
97
|
+
}
|
package/src/cli.js
CHANGED
|
@@ -107,6 +107,14 @@ async function maybeEnsureDefaultWebApp(args = {}, { commandCwd = process.cwd()
|
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
|
110
|
+
function webAppNotice(result) {
|
|
111
|
+
if (!result || result.ok) return "";
|
|
112
|
+
if (result.disabled) return "webapp auto-start disabled - use /webapp to start manually";
|
|
113
|
+
const error = String(result.error || "unknown").replace(/\s+/g, " ").trim();
|
|
114
|
+
const compact = error.length > 84 ? `${error.slice(0, 83)}…` : error;
|
|
115
|
+
return `webapp unavailable - use /webapp to retry; error: ${compact}`;
|
|
116
|
+
}
|
|
117
|
+
|
|
110
118
|
const CLI_VALUE_OPTIONS = new Set([
|
|
111
119
|
"--port",
|
|
112
120
|
"--host",
|
|
@@ -1755,6 +1763,7 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
1755
1763
|
packageDir,
|
|
1756
1764
|
packageVersion: packageJson.version,
|
|
1757
1765
|
webAppUrl: webLaunch.ok ? webLaunch.url : "",
|
|
1766
|
+
webAppNotice: webAppNotice(webLaunch),
|
|
1758
1767
|
});
|
|
1759
1768
|
return;
|
|
1760
1769
|
}
|
|
@@ -1783,7 +1792,12 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
1783
1792
|
|
|
1784
1793
|
if (args.interactive || (!args.goal && !args.resume && process.stdin.isTTY)) {
|
|
1785
1794
|
const webLaunch = await maybeEnsureDefaultWebApp(args, { commandCwd });
|
|
1786
|
-
await startInteractiveCli(agentDefaults(args), {
|
|
1795
|
+
await startInteractiveCli(agentDefaults(args), {
|
|
1796
|
+
packageDir,
|
|
1797
|
+
packageVersion: packageJson.version,
|
|
1798
|
+
webAppUrl: webLaunch.ok ? webLaunch.url : "",
|
|
1799
|
+
webAppNotice: webAppNotice(webLaunch),
|
|
1800
|
+
});
|
|
1787
1801
|
return;
|
|
1788
1802
|
}
|
|
1789
1803
|
|
package/src/i18n.js
CHANGED
|
@@ -139,6 +139,7 @@ const TRANSLATIONS = {
|
|
|
139
139
|
helpSkills: "List Markdown skills selected for a topic.",
|
|
140
140
|
helpSkillMesh: "Manage strict reviewed skill sharing.",
|
|
141
141
|
helpProfile: "Set task profile, e.g. code, website, latex, maintenance.",
|
|
142
|
+
helpWebapp: "Start or reuse the local webapp and print its URL.",
|
|
142
143
|
helpWebSearch: "Enable or disable the web_search tool.",
|
|
143
144
|
helpEnableScs: "Toggle Student-Committee-Supervisor gated execution.",
|
|
144
145
|
helpScouts: "Enable parallel DeepSeek scouts and set scout count.",
|
package/src/interactive-cli.js
CHANGED
|
@@ -43,6 +43,7 @@ import {
|
|
|
43
43
|
permissionModeForApprovalCategory,
|
|
44
44
|
permissionModeLabel,
|
|
45
45
|
} from "./permission-modes.js";
|
|
46
|
+
import { ensureAgintiWebApp } from "./web-autostart.js";
|
|
46
47
|
|
|
47
48
|
const useColor = Boolean(input.isTTY && output.isTTY && process.env.AGINTIFLOW_NO_COLOR !== "1");
|
|
48
49
|
const ansi = {
|
|
@@ -95,6 +96,8 @@ const SLASH_COMMANDS = [
|
|
|
95
96
|
"/skillsync",
|
|
96
97
|
"/profile",
|
|
97
98
|
"/web-search",
|
|
99
|
+
"/webapp",
|
|
100
|
+
"/web",
|
|
98
101
|
"/web-research",
|
|
99
102
|
"/image-read",
|
|
100
103
|
"/research-wrapper",
|
|
@@ -772,10 +775,19 @@ function launchTitleLines(contentWidth) {
|
|
|
772
775
|
return largeWidth <= contentWidth ? LARGE_LAUNCH_TITLE : COMPACT_LAUNCH_TITLE;
|
|
773
776
|
}
|
|
774
777
|
|
|
775
|
-
export function buildLaunchHeaderLines({
|
|
778
|
+
export function buildLaunchHeaderLines({
|
|
779
|
+
packageVersion = "",
|
|
780
|
+
frame = 2,
|
|
781
|
+
width = terminalWidth(),
|
|
782
|
+
animated = true,
|
|
783
|
+
language = cliLanguage,
|
|
784
|
+
webAppUrl = "",
|
|
785
|
+
webAppNotice = "",
|
|
786
|
+
} = {}) {
|
|
776
787
|
const subtitle = t("launchSubtitle", language);
|
|
777
788
|
const credit = t("launchCredit", language);
|
|
778
|
-
const
|
|
789
|
+
const webappLine = webAppUrl ? `webapp: ${webAppUrl}` : webAppNotice;
|
|
790
|
+
const tagline = webappLine || t("launchTagline", language);
|
|
779
791
|
const version = packageVersion ? `v${packageVersion}` : "";
|
|
780
792
|
const terminalColumns = Math.max(Number(width) || 80, 50);
|
|
781
793
|
const contentWidth = Math.min(Math.max(terminalColumns - 8, 58), 112);
|
|
@@ -794,16 +806,16 @@ export function buildLaunchHeaderLines({ packageVersion = "", frame = 2, width =
|
|
|
794
806
|
row(centerLine(subtitle, contentWidth), ansi.dim),
|
|
795
807
|
row(centerLine(credit, contentWidth), ansi.dim),
|
|
796
808
|
tagline ? mid : "",
|
|
797
|
-
tagline ? row(centerLine(tagline, contentWidth), ansi.cyan) : "",
|
|
809
|
+
tagline ? row(centerLine(compactLine(tagline, contentWidth), contentWidth), webAppUrl ? ansi.cyan : ansi.yellow) : "",
|
|
798
810
|
bottom,
|
|
799
811
|
].filter(Boolean);
|
|
800
812
|
const indent = " ".repeat(Math.max(Math.floor((terminalColumns - Math.max(...boxLines.map((line) => visualLength(line)))) / 2), 0));
|
|
801
813
|
return boxLines.map((line) => `${indent}${line}`);
|
|
802
814
|
}
|
|
803
815
|
|
|
804
|
-
async function renderLaunchHeader(packageVersion = "", language = cliLanguage, webAppUrl = "") {
|
|
816
|
+
async function renderLaunchHeader(packageVersion = "", language = cliLanguage, webAppUrl = "", webAppNotice = "") {
|
|
805
817
|
if (!useColor || process.env.AGINTIFLOW_NO_ANIMATION === "1") {
|
|
806
|
-
console.log(buildLaunchHeaderLines({ packageVersion, animated: false, language, webAppUrl }).join("\n"));
|
|
818
|
+
console.log(buildLaunchHeaderLines({ packageVersion, animated: false, language, webAppUrl, webAppNotice }).join("\n"));
|
|
807
819
|
return;
|
|
808
820
|
}
|
|
809
821
|
|
|
@@ -812,7 +824,7 @@ async function renderLaunchHeader(packageVersion = "", language = cliLanguage, w
|
|
|
812
824
|
let previousLineCount = 0;
|
|
813
825
|
output.write(ansi.cursorHide);
|
|
814
826
|
for (let frame = 0; frame < 18; frame += 1) {
|
|
815
|
-
const lines = [...paddingLines, ...buildLaunchHeaderLines({ packageVersion, frame, animated: true, language, webAppUrl })];
|
|
827
|
+
const lines = [...paddingLines, ...buildLaunchHeaderLines({ packageVersion, frame, animated: true, language, webAppUrl, webAppNotice })];
|
|
816
828
|
if (previousLineCount > 0) output.write(`\x1b[${previousLineCount}A`);
|
|
817
829
|
output.write(lines.map((line) => `\r${ansi.clearLine}${line}`).join("\n"));
|
|
818
830
|
output.write("\n");
|
|
@@ -849,6 +861,7 @@ function printHelp() {
|
|
|
849
861
|
` ${command("/skills [query]", "List Markdown skills selected for a topic.", "helpSkills")}`,
|
|
850
862
|
` ${command("/skillmesh [status|off|record|share|sync]", "Manage strict reviewed skill sharing.", "helpSkillMesh")}`,
|
|
851
863
|
` ${command("/profile <name>", "Set task profile, e.g. code, website, latex, maintenance.", "helpProfile")}`,
|
|
864
|
+
` ${command("/webapp [port]", "Start or reuse the local webapp and print its URL.", "helpWebapp")}`,
|
|
852
865
|
` ${command("/web-search on|off", "Enable or disable the web_search tool.", "helpWebSearch")}`,
|
|
853
866
|
` ${command("/web-research <query>", "Run a sourced web_research turn with persisted evidence.", "helpWebSearch")}`,
|
|
854
867
|
` ${command("/image-read <path> [question]", "Run read_image on a workspace screenshot/image.", "helpWebSearch")}`,
|
|
@@ -2170,6 +2183,8 @@ function createState(args = {}) {
|
|
|
2170
2183
|
dynamicStepHardCap: args.dynamicStepHardCap,
|
|
2171
2184
|
dynamicStepExtensionSize: args.dynamicStepExtensionSize,
|
|
2172
2185
|
sessionId: args.resume || "",
|
|
2186
|
+
webAppUrl: args.webAppUrl || "",
|
|
2187
|
+
webAppNotice: args.webAppNotice || "",
|
|
2173
2188
|
};
|
|
2174
2189
|
}
|
|
2175
2190
|
|
|
@@ -2975,6 +2990,28 @@ async function handleCommand(line, state, packageDir) {
|
|
|
2975
2990
|
);
|
|
2976
2991
|
return true;
|
|
2977
2992
|
}
|
|
2993
|
+
if (command === "webapp" || command === "web") {
|
|
2994
|
+
const port = Number(value) || Number(process.env.AGINTI_WEB_PORT || process.env.PORT || 3210);
|
|
2995
|
+
printSystemLine("webapp=starting");
|
|
2996
|
+
const result = await ensureAgintiWebApp({
|
|
2997
|
+
packageDir,
|
|
2998
|
+
cwd: state.commandCwd || process.cwd(),
|
|
2999
|
+
host: process.env.AGINTI_WEB_HOST || process.env.HOST || "127.0.0.1",
|
|
3000
|
+
preferredPort: port,
|
|
3001
|
+
language: state.language,
|
|
3002
|
+
respectAutoStartDisable: false,
|
|
3003
|
+
}).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), url: "" }));
|
|
3004
|
+
if (result.ok) {
|
|
3005
|
+
state.webAppUrl = result.url;
|
|
3006
|
+
state.webAppNotice = "";
|
|
3007
|
+
printSystemLine(`webapp=${result.url} ${result.reused ? "reused" : "started"}`);
|
|
3008
|
+
} else {
|
|
3009
|
+
state.webAppUrl = "";
|
|
3010
|
+
state.webAppNotice = `webapp unavailable - use /webapp to retry; error: ${compactLine(result.error || "unknown", 72)}`;
|
|
3011
|
+
printSystemLine(state.webAppNotice);
|
|
3012
|
+
}
|
|
3013
|
+
return true;
|
|
3014
|
+
}
|
|
2978
3015
|
if (command === "language" || command === "lang") {
|
|
2979
3016
|
if (!value) {
|
|
2980
3017
|
printSystemLine(tr("languageSet", { language: state.language || cliLanguage, label: languageLabel(state.language || cliLanguage) }));
|
|
@@ -3599,12 +3636,6 @@ async function handleCommand(line, state, packageDir) {
|
|
|
3599
3636
|
printAgentMessage(`initialized project=${result.projectRoot}\nAGINTI.md=${result.instructionsPath}\ntemplate=${result.template}`);
|
|
3600
3637
|
return true;
|
|
3601
3638
|
}
|
|
3602
|
-
if (command === "web") {
|
|
3603
|
-
const port = value || "3220";
|
|
3604
|
-
printAgentMessage(`Run in another terminal: aginti web --port ${port}`);
|
|
3605
|
-
return true;
|
|
3606
|
-
}
|
|
3607
|
-
|
|
3608
3639
|
const typed = `/${command}`;
|
|
3609
3640
|
const suggestions = SLASH_COMMANDS.filter((candidate) => candidate.startsWith(typed));
|
|
3610
3641
|
printAgentMessage(
|
|
@@ -3808,8 +3839,8 @@ async function runPrompt(prompt, state, packageDir, { approvalDepth = 0 } = {})
|
|
|
3808
3839
|
return queuedAfterFinish;
|
|
3809
3840
|
}
|
|
3810
3841
|
|
|
3811
|
-
export async function startInteractiveCli(args = {}, { packageDir, packageVersion, webAppUrl = "" } = {}) {
|
|
3812
|
-
const state = createState(args);
|
|
3842
|
+
export async function startInteractiveCli(args = {}, { packageDir, packageVersion, webAppUrl = "", webAppNotice = "" } = {}) {
|
|
3843
|
+
const state = createState({ ...args, webAppUrl, webAppNotice });
|
|
3813
3844
|
const detachProcessInterrupts = installProcessInterruptHandlers();
|
|
3814
3845
|
setCliLanguage(state.language);
|
|
3815
3846
|
const rl =
|
|
@@ -3822,7 +3853,7 @@ export async function startInteractiveCli(args = {}, { packageDir, packageVersio
|
|
|
3822
3853
|
completer: commandCompleter,
|
|
3823
3854
|
});
|
|
3824
3855
|
|
|
3825
|
-
await renderLaunchHeader(packageVersion, state.language, webAppUrl);
|
|
3856
|
+
await renderLaunchHeader(packageVersion, state.language, state.webAppUrl, state.webAppNotice);
|
|
3826
3857
|
printSystemLine(`${tr("project")}: ${process.cwd()}`);
|
|
3827
3858
|
await maybeOnboardDeepSeekKey(state);
|
|
3828
3859
|
printAgentMessage(tr("interactiveIntro"));
|
package/src/web-autostart.js
CHANGED
|
@@ -86,8 +86,9 @@ export async function ensureAgintiWebApp({
|
|
|
86
86
|
host = DEFAULT_HOST,
|
|
87
87
|
preferredPort = DEFAULT_PORT,
|
|
88
88
|
language = "",
|
|
89
|
+
respectAutoStartDisable = true,
|
|
89
90
|
} = {}) {
|
|
90
|
-
if (process.env.AGINTI_NO_WEB_AUTO_START === "1" || process.env.AGINTIFLOW_NO_WEB_AUTO_START === "1") {
|
|
91
|
+
if (respectAutoStartDisable && (process.env.AGINTI_NO_WEB_AUTO_START === "1" || process.env.AGINTIFLOW_NO_WEB_AUTO_START === "1")) {
|
|
91
92
|
return { ok: false, disabled: true, url: "" };
|
|
92
93
|
}
|
|
93
94
|
|