@lazyingart/agintiflow 0.20.129 → 0.20.131
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 +5 -2
- package/package.json +1 -1
- package/scripts/smoke-webapp-command.js +24 -0
- package/src/cli.js +37 -12
- package/src/i18n.js +1 -1
- package/src/interactive-cli.js +40 -11
- package/src/web-autostart.js +79 -1
package/README.md
CHANGED
|
@@ -103,7 +103,7 @@ 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 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 by another project. The active URL is shown in the CLI launch header. If startup is blocked, stale, or unavailable, the same header row shows the recovery hint; run `/webapp [port]` inside the CLI to retry, or `/webapp restart [port]` to stop and relaunch the local webapp with the current project and canonical `~/.agintiflow` session home. After a successful `aginti update` or accepted startup auto-update, AgInTiFlow
|
|
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 by another project. The active URL is shown in the CLI launch header. If startup is blocked, stale, or unavailable, the same header row shows the recovery hint; run `/webapp [port]` inside the CLI to retry, `/webapp stop [port]` to stop the compatible local webapp, or `/webapp restart [port]` to stop and relaunch the local webapp with the current project and canonical `~/.agintiflow` session home. Use `/webapp disable` or `aginti webapp disable` to persistently disable automatic webapp startup and update-time restarts; use `/webapp enable` or `aginti webapp enable` to restore them. After a successful `aginti update` or accepted startup auto-update, AgInTiFlow restarts the compatible local webapp only when webapp auto-start is enabled.
|
|
107
107
|
|
|
108
108
|
Package installation also makes a best-effort, non-blocking webapp initialization. Install never fails because the optional local webapp could not start.
|
|
109
109
|
|
|
@@ -111,6 +111,9 @@ Launch the web UI explicitly when you want a foreground web server:
|
|
|
111
111
|
|
|
112
112
|
```bash
|
|
113
113
|
aginti webapp
|
|
114
|
+
aginti webapp disable
|
|
115
|
+
aginti webapp enable
|
|
116
|
+
aginti webapp stop
|
|
114
117
|
aginti webapp restart
|
|
115
118
|
aginti web --port 3210
|
|
116
119
|
# opens http://127.0.0.1:3210, or the next available port
|
|
@@ -145,7 +148,7 @@ aginti --language de
|
|
|
145
148
|
| Goal | Command |
|
|
146
149
|
| --- | --- |
|
|
147
150
|
| Start interactive chat | `aginti` or `aginti chat` |
|
|
148
|
-
| Start local web app | Auto-starts with `aginti`; detached command is `aginti webapp`; restart with `aginti webapp restart`; foreground mode is `aginti web --port 3210` |
|
|
151
|
+
| Start local web app | Auto-starts with `aginti`; detached command is `aginti webapp`; disable/enable auto-start with `aginti webapp disable` / `aginti webapp enable`; stop with `aginti webapp stop`; restart with `aginti webapp restart`; foreground mode is `aginti web --port 3210` |
|
|
149
152
|
| Save provider keys | `aginti auth`, `/auth`, `/login` |
|
|
150
153
|
| Review current repo | `/review [focus]` |
|
|
151
154
|
| Toggle SCS quality gate | `/scs` |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.131",
|
|
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",
|
|
@@ -14,6 +14,10 @@ function delay(ms) {
|
|
|
14
14
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
function occurrenceCount(value, pattern) {
|
|
18
|
+
return String(value || "").split(pattern).length - 1;
|
|
19
|
+
}
|
|
20
|
+
|
|
17
21
|
async function waitFor(predicate, child, label, output) {
|
|
18
22
|
const deadline = Date.now() + 12000;
|
|
19
23
|
while (Date.now() < deadline) {
|
|
@@ -74,6 +78,26 @@ async function runCase({ port, env = {}, expectHeader, label }) {
|
|
|
74
78
|
if (path.resolve(health.agintiflowHome) !== path.resolve(path.join(runtimeDir, `.agintiflow-web-home-${label}`))) {
|
|
75
79
|
throw new Error(`webapp command inherited the wrong home for ${label}: ${JSON.stringify(health)}`);
|
|
76
80
|
}
|
|
81
|
+
child.stdin.write(`/webapp disable\n`);
|
|
82
|
+
await waitFor(() => output.stdout.includes("webapp auto-start=disabled"), child, `${label} /webapp disable command`, output);
|
|
83
|
+
const disabledCount = occurrenceCount(output.stdout, "webapp auto-start=disabled");
|
|
84
|
+
child.stdin.write(`/webapp status\n`);
|
|
85
|
+
await waitFor(() => occurrenceCount(output.stdout, "webapp auto-start=disabled") > disabledCount, child, `${label} /webapp status disabled command`, output);
|
|
86
|
+
child.stdin.write(`/webapp enable\n`);
|
|
87
|
+
await waitFor(() => output.stdout.includes("webapp auto-start=enabled"), child, `${label} /webapp enable command`, output);
|
|
88
|
+
child.stdin.write(`/webapp stop ${port}\n`);
|
|
89
|
+
await waitFor(() => output.stdout.includes(`webapp=http://127.0.0.1:${port} stopped`), child, `${label} /webapp stop command`, output);
|
|
90
|
+
let stopped = false;
|
|
91
|
+
try {
|
|
92
|
+
await fetch(`http://127.0.0.1:${port}/health`);
|
|
93
|
+
} catch {
|
|
94
|
+
stopped = true;
|
|
95
|
+
}
|
|
96
|
+
if (!stopped) {
|
|
97
|
+
throw new Error(`webapp still responded after /webapp stop for ${label}`);
|
|
98
|
+
}
|
|
99
|
+
child.stdin.write(`/webapp ${port}\n`);
|
|
100
|
+
await waitFor(() => output.stdout.includes(`webapp=http://127.0.0.1:${port} started`), child, `${label} /webapp restart after stop`, output);
|
|
77
101
|
} finally {
|
|
78
102
|
child.kill("SIGTERM");
|
|
79
103
|
await killPort(port);
|
package/src/cli.js
CHANGED
|
@@ -37,7 +37,7 @@ import { handleSkillMeshCommand } from "./skillmesh.js";
|
|
|
37
37
|
import { handleAapsCliCommand } from "./aaps-adapter.js";
|
|
38
38
|
import { formatInstructionTemplateList, normalizeInstructionTemplate } from "./behavior-contract.js";
|
|
39
39
|
import { applyPermissionMode, normalizePermissionMode } from "./permission-modes.js";
|
|
40
|
-
import { ensureAgintiWebApp } from "./web-autostart.js";
|
|
40
|
+
import { ensureAgintiWebApp, readWebAppPreference, stopAgintiWebApp, writeWebAppPreference } from "./web-autostart.js";
|
|
41
41
|
import { dockerHostInstallPlan, formatDockerSetupText, summarizeDockerSetup } from "./docker-setup.js";
|
|
42
42
|
import fs from "node:fs/promises";
|
|
43
43
|
import path from "node:path";
|
|
@@ -403,9 +403,9 @@ export function parseArgs(argv) {
|
|
|
403
403
|
parts.push(...argv.slice(i + 1));
|
|
404
404
|
break;
|
|
405
405
|
}
|
|
406
|
-
if ((arg === "web" || arg === "--web") && String(argv[i + 1] || "").toLowerCase()
|
|
406
|
+
if ((arg === "web" || arg === "--web") && ["restart", "stop", "enable", "disable", "status"].includes(String(argv[i + 1] || "").toLowerCase())) {
|
|
407
407
|
result.webapp = true;
|
|
408
|
-
result.webAction = "
|
|
408
|
+
result.webAction = String(argv[i + 1] || "").toLowerCase();
|
|
409
409
|
i += 1;
|
|
410
410
|
continue;
|
|
411
411
|
}
|
|
@@ -902,7 +902,7 @@ async function restartWebAppAfterUpdate({ commandCwd = process.cwd(), language =
|
|
|
902
902
|
preferredPort: process.env.AGINTI_WEB_PORT || process.env.PORT || 3210,
|
|
903
903
|
language,
|
|
904
904
|
restart: true,
|
|
905
|
-
respectAutoStartDisable:
|
|
905
|
+
respectAutoStartDisable: true,
|
|
906
906
|
}).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), url: "" }));
|
|
907
907
|
}
|
|
908
908
|
|
|
@@ -1949,25 +1949,50 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
1949
1949
|
|
|
1950
1950
|
if (args.webapp) {
|
|
1951
1951
|
const action = String(args.webAction || "start").toLowerCase();
|
|
1952
|
-
if (!["start", "restart", "reuse"].includes(action)) {
|
|
1953
|
-
console.error("Usage: aginti webapp [start|restart] [--port 3210] [--host 127.0.0.1]");
|
|
1952
|
+
if (!["start", "stop", "restart", "reuse", "enable", "disable", "status"].includes(action)) {
|
|
1953
|
+
console.error("Usage: aginti webapp [start|stop|restart|reuse|enable|disable|status] [--port 3210] [--host 127.0.0.1]");
|
|
1954
1954
|
process.exit(1);
|
|
1955
1955
|
}
|
|
1956
|
-
const
|
|
1956
|
+
const webOptions = {
|
|
1957
1957
|
packageDir,
|
|
1958
1958
|
cwd: args.commandCwd || commandCwd,
|
|
1959
1959
|
home: args.webHome || "",
|
|
1960
1960
|
host: args.host || process.env.AGINTI_WEB_HOST || "127.0.0.1",
|
|
1961
1961
|
preferredPort: args.port || process.env.AGINTI_WEB_PORT || 3210,
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1962
|
+
};
|
|
1963
|
+
if (action === "enable" || action === "disable" || action === "status") {
|
|
1964
|
+
const preference =
|
|
1965
|
+
action === "status"
|
|
1966
|
+
? await readWebAppPreference({ home: webOptions.home })
|
|
1967
|
+
: await writeWebAppPreference({ home: webOptions.home, autoStart: action === "enable" });
|
|
1968
|
+
console.log(`webapp auto-start: ${preference.autoStart ? "enabled" : "disabled"}`);
|
|
1969
|
+
console.log(`preference: ${preference.path}`);
|
|
1970
|
+
if (!preference.autoStart) console.log("Use `aginti webapp stop` or `/webapp stop` to stop a currently running webapp.");
|
|
1971
|
+
return;
|
|
1972
|
+
}
|
|
1973
|
+
const result = await (action === "stop"
|
|
1974
|
+
? stopAgintiWebApp(webOptions)
|
|
1975
|
+
: ensureAgintiWebApp({
|
|
1976
|
+
...webOptions,
|
|
1977
|
+
language: args.language ? resolveLanguage(args.language) : "",
|
|
1978
|
+
restart: action === "restart",
|
|
1979
|
+
respectAutoStartDisable: false,
|
|
1980
|
+
})
|
|
1981
|
+
).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), url: "" }));
|
|
1966
1982
|
if (!result.ok) {
|
|
1967
1983
|
console.error(`webapp unavailable: ${result.error || "unknown"}`);
|
|
1968
1984
|
process.exit(1);
|
|
1969
1985
|
}
|
|
1970
|
-
const state =
|
|
1986
|
+
const state =
|
|
1987
|
+
action === "stop" && result.stopped
|
|
1988
|
+
? "stopped"
|
|
1989
|
+
: action === "stop" && result.alreadyStopped
|
|
1990
|
+
? "already stopped"
|
|
1991
|
+
: result.restarted
|
|
1992
|
+
? "restarted"
|
|
1993
|
+
: result.reused
|
|
1994
|
+
? "reused"
|
|
1995
|
+
: "started";
|
|
1971
1996
|
console.log(`webapp: ${result.url} ${state}`);
|
|
1972
1997
|
console.log(`project: ${result.runtimeDir || path.resolve(args.commandCwd || commandCwd)}`);
|
|
1973
1998
|
console.log(`home: ${result.agintiflowHome || ""}`);
|
package/src/i18n.js
CHANGED
|
@@ -139,7 +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, reuse,
|
|
142
|
+
helpWebapp: "Start, reuse, stop, restart, or configure the local webapp.",
|
|
143
143
|
helpWebSearch: "Enable or disable the web_search tool.",
|
|
144
144
|
helpEnableScs: "Toggle Student-Committee-Supervisor gated execution.",
|
|
145
145
|
helpScouts: "Enable parallel DeepSeek scouts and set scout count.",
|
package/src/interactive-cli.js
CHANGED
|
@@ -45,7 +45,7 @@ import {
|
|
|
45
45
|
permissionModeForApprovalCategory,
|
|
46
46
|
permissionModeLabel,
|
|
47
47
|
} from "./permission-modes.js";
|
|
48
|
-
import { ensureAgintiWebApp } from "./web-autostart.js";
|
|
48
|
+
import { ensureAgintiWebApp, readWebAppPreference, stopAgintiWebApp, writeWebAppPreference } from "./web-autostart.js";
|
|
49
49
|
|
|
50
50
|
const useColor = Boolean(input.isTTY && output.isTTY && process.env.AGINTIFLOW_NO_COLOR !== "1");
|
|
51
51
|
const ansi = {
|
|
@@ -881,7 +881,7 @@ function printHelp() {
|
|
|
881
881
|
` ${command("/skills [query]", "List Markdown skills selected for a topic.", "helpSkills")}`,
|
|
882
882
|
` ${command("/skillmesh [status|off|record|share|sync]", "Manage strict reviewed skill sharing.", "helpSkillMesh")}`,
|
|
883
883
|
` ${command("/profile <name>", "Set task profile, e.g. code, website, latex, maintenance.", "helpProfile")}`,
|
|
884
|
-
` ${command("/webapp [port|restart]", "Start, reuse,
|
|
884
|
+
` ${command("/webapp [port|start|stop|restart|reuse|enable|disable|status]", "Start, reuse, stop, restart, or configure the local webapp.", "helpWebapp")}`,
|
|
885
885
|
` ${command("/web-search on|off", "Enable or disable the web_search tool.", "helpWebSearch")}`,
|
|
886
886
|
` ${command("/web-research <query>", "Run a sourced web_research turn with persisted evidence.", "helpWebSearch")}`,
|
|
887
887
|
` ${command("/image-read <path> [question]", "Run read_image on a workspace screenshot/image.", "helpWebSearch")}`,
|
|
@@ -3011,23 +3011,52 @@ async function handleCommand(line, state, packageDir) {
|
|
|
3011
3011
|
}
|
|
3012
3012
|
if (command === "webapp" || command === "web") {
|
|
3013
3013
|
const words = value.split(/\s+/).filter(Boolean);
|
|
3014
|
+
const action = words.find((word) => ["start", "stop", "restart", "reuse", "enable", "disable", "status"].includes(word.toLowerCase()))?.toLowerCase() || "start";
|
|
3014
3015
|
const restart = words.some((word) => word.toLowerCase() === "restart");
|
|
3015
3016
|
const portValue = words.find((word) => /^\d+$/.test(word));
|
|
3016
3017
|
const port = Number(portValue) || Number(process.env.AGINTI_WEB_PORT || process.env.PORT || 3210);
|
|
3017
|
-
|
|
3018
|
-
const result = await ensureAgintiWebApp({
|
|
3018
|
+
const webOptions = {
|
|
3019
3019
|
packageDir,
|
|
3020
3020
|
cwd: state.commandCwd || process.cwd(),
|
|
3021
3021
|
host: process.env.AGINTI_WEB_HOST || process.env.HOST || "127.0.0.1",
|
|
3022
3022
|
preferredPort: port,
|
|
3023
|
-
|
|
3024
|
-
|
|
3025
|
-
|
|
3026
|
-
|
|
3023
|
+
};
|
|
3024
|
+
if (action === "enable" || action === "disable" || action === "status") {
|
|
3025
|
+
const preference =
|
|
3026
|
+
action === "status"
|
|
3027
|
+
? await readWebAppPreference()
|
|
3028
|
+
: await writeWebAppPreference({ autoStart: action === "enable" });
|
|
3029
|
+
printSystemLine(`webapp auto-start=${preference.autoStart ? "enabled" : "disabled"}`);
|
|
3030
|
+
if (!preference.autoStart) printSystemLine("webapp disabled for future starts; use /webapp stop to stop a running webapp");
|
|
3031
|
+
return true;
|
|
3032
|
+
}
|
|
3033
|
+
printSystemLine(action === "stop" ? "webapp=stopping" : restart ? "webapp=restarting" : "webapp=starting");
|
|
3034
|
+
const result = await (action === "stop"
|
|
3035
|
+
? stopAgintiWebApp(webOptions)
|
|
3036
|
+
: ensureAgintiWebApp({
|
|
3037
|
+
...webOptions,
|
|
3038
|
+
language: state.language,
|
|
3039
|
+
restart,
|
|
3040
|
+
respectAutoStartDisable: false,
|
|
3041
|
+
})
|
|
3042
|
+
).catch((error) => ({ ok: false, error: error instanceof Error ? error.message : String(error), url: "" }));
|
|
3027
3043
|
if (result.ok) {
|
|
3028
|
-
|
|
3029
|
-
|
|
3030
|
-
|
|
3044
|
+
const stateLabel = result.stopped
|
|
3045
|
+
? action === "stop"
|
|
3046
|
+
? "stopped"
|
|
3047
|
+
: result.restarted
|
|
3048
|
+
? "restarted"
|
|
3049
|
+
: "started"
|
|
3050
|
+
: action === "stop" && result.alreadyStopped
|
|
3051
|
+
? "already stopped"
|
|
3052
|
+
: result.restarted
|
|
3053
|
+
? "restarted"
|
|
3054
|
+
: result.reused
|
|
3055
|
+
? "reused"
|
|
3056
|
+
: "started";
|
|
3057
|
+
state.webAppUrl = action === "stop" ? "" : result.url;
|
|
3058
|
+
state.webAppNotice = action === "stop" ? "webapp stopped - use /webapp to start it again" : "";
|
|
3059
|
+
printSystemLine(`webapp=${result.url} ${stateLabel}`);
|
|
3031
3060
|
} else {
|
|
3032
3061
|
state.webAppUrl = "";
|
|
3033
3062
|
state.webAppNotice = `webapp unavailable - use /webapp to retry; error: ${compactLine(result.error || "unknown", 72)}`;
|
package/src/web-autostart.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { execFile, spawn } from "node:child_process";
|
|
2
|
+
import fs from "node:fs/promises";
|
|
2
3
|
import http from "node:http";
|
|
3
4
|
import net from "node:net";
|
|
4
5
|
import os from "node:os";
|
|
@@ -54,6 +55,32 @@ function resolveRuntimeDir(cwd = "") {
|
|
|
54
55
|
return path.resolve(process.env.AGINTIFLOW_WEB_RUNTIME_DIR || cwd || process.cwd());
|
|
55
56
|
}
|
|
56
57
|
|
|
58
|
+
function webPreferencePath(home = "") {
|
|
59
|
+
return path.join(resolveWebHome(home), "webapp.json");
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export async function readWebAppPreference({ home = "" } = {}) {
|
|
63
|
+
const file = webPreferencePath(home);
|
|
64
|
+
try {
|
|
65
|
+
const data = JSON.parse(await fs.readFile(file, "utf8"));
|
|
66
|
+
return { autoStart: data.autoStart !== false, path: file };
|
|
67
|
+
} catch {
|
|
68
|
+
return { autoStart: true, path: file };
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function writeWebAppPreference({ home = "", autoStart = true } = {}) {
|
|
73
|
+
const file = webPreferencePath(home);
|
|
74
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
75
|
+
await fs.writeFile(file, `${JSON.stringify({ autoStart: Boolean(autoStart), updatedAt: new Date().toISOString() }, null, 2)}\n`, "utf8");
|
|
76
|
+
return await readWebAppPreference({ home });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async function webAutoStartDisabled(home = "") {
|
|
80
|
+
if (process.env.AGINTI_NO_WEB_AUTO_START === "1" || process.env.AGINTIFLOW_NO_WEB_AUTO_START === "1") return true;
|
|
81
|
+
return (await readWebAppPreference({ home })).autoStart === false;
|
|
82
|
+
}
|
|
83
|
+
|
|
57
84
|
function fetchHealthDetails(host, port, timeoutMs = 450) {
|
|
58
85
|
return new Promise((resolve) => {
|
|
59
86
|
const req = http.get(`${webUrl(host, port)}/health`, { timeout: timeoutMs }, (res) => {
|
|
@@ -169,6 +196,57 @@ async function stopWebAppOnPort({ host, port, health = {} } = {}) {
|
|
|
169
196
|
: { ok: false, pids: [...pids], error: `AgInTiFlow webapp on ${host}:${port} did not stop.` };
|
|
170
197
|
}
|
|
171
198
|
|
|
199
|
+
export async function stopAgintiWebApp({
|
|
200
|
+
packageDir = process.cwd(),
|
|
201
|
+
cwd = process.cwd(),
|
|
202
|
+
home = "",
|
|
203
|
+
host = DEFAULT_HOST,
|
|
204
|
+
preferredPort = DEFAULT_PORT,
|
|
205
|
+
force = false,
|
|
206
|
+
} = {}) {
|
|
207
|
+
const normalizedHost = normalizeHost(host);
|
|
208
|
+
const port = normalizePort(preferredPort);
|
|
209
|
+
const url = webUrl(normalizedHost, port);
|
|
210
|
+
const runtimeDir = resolveRuntimeDir(cwd);
|
|
211
|
+
const homeDir = resolveWebHome(home);
|
|
212
|
+
const health = await fetchHealthDetails(normalizedHost, port);
|
|
213
|
+
|
|
214
|
+
if (!health.ok) {
|
|
215
|
+
if (await canListen(normalizedHost, port)) {
|
|
216
|
+
return { ok: true, stopped: false, alreadyStopped: true, host: normalizedHost, port, url, runtimeDir, agintiflowHome: homeDir };
|
|
217
|
+
}
|
|
218
|
+
return { ok: false, stopped: false, host: normalizedHost, port, url, error: `No AgInTiFlow health endpoint responded on ${url}.` };
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
if (!force && !compatibleHealth(health, { cwd: runtimeDir, home: homeDir, packageDir })) {
|
|
222
|
+
return {
|
|
223
|
+
ok: false,
|
|
224
|
+
stopped: false,
|
|
225
|
+
host: normalizedHost,
|
|
226
|
+
port,
|
|
227
|
+
url,
|
|
228
|
+
runtimeDir,
|
|
229
|
+
agintiflowHome: homeDir,
|
|
230
|
+
health,
|
|
231
|
+
error: `Refusing to stop AgInTiFlow webapp on ${url} because it belongs to a different project or home.`,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
const stopped = await stopWebAppOnPort({ host: normalizedHost, port, health });
|
|
236
|
+
return {
|
|
237
|
+
ok: Boolean(stopped.ok),
|
|
238
|
+
stopped: Boolean(stopped.ok),
|
|
239
|
+
alreadyStopped: false,
|
|
240
|
+
host: normalizedHost,
|
|
241
|
+
port,
|
|
242
|
+
url,
|
|
243
|
+
runtimeDir,
|
|
244
|
+
agintiflowHome: homeDir,
|
|
245
|
+
health,
|
|
246
|
+
...stopped,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
249
|
+
|
|
172
250
|
export async function findReusableOrFreeWebPort({
|
|
173
251
|
host = DEFAULT_HOST,
|
|
174
252
|
preferredPort = DEFAULT_PORT,
|
|
@@ -223,7 +301,7 @@ export async function ensureAgintiWebApp({
|
|
|
223
301
|
restart = false,
|
|
224
302
|
respectAutoStartDisable = true,
|
|
225
303
|
} = {}) {
|
|
226
|
-
if (respectAutoStartDisable && (
|
|
304
|
+
if (respectAutoStartDisable && (await webAutoStartDisabled(home))) {
|
|
227
305
|
return { ok: false, disabled: true, url: "" };
|
|
228
306
|
}
|
|
229
307
|
|