nomoreide 0.1.90 → 0.1.91
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/core/agent-terminal.d.ts +9 -1
- package/dist/core/agent-terminal.js +26 -5
- package/dist/core/agent-terminal.js.map +1 -1
- package/dist/core/agent-transcripts.d.ts +27 -0
- package/dist/core/agent-transcripts.js +240 -0
- package/dist/core/agent-transcripts.js.map +1 -0
- package/dist/core/config-store.d.ts +18 -0
- package/dist/core/config-store.js +53 -0
- package/dist/core/config-store.js.map +1 -1
- package/dist/core/docker-inspect.d.ts +34 -0
- package/dist/core/docker-inspect.js +108 -0
- package/dist/core/docker-inspect.js.map +1 -0
- package/dist/core/docker-resources.d.ts +28 -0
- package/dist/core/docker-resources.js +59 -0
- package/dist/core/docker-resources.js.map +1 -0
- package/dist/core/docker-stats.d.ts +22 -0
- package/dist/core/docker-stats.js +52 -0
- package/dist/core/docker-stats.js.map +1 -0
- package/dist/core/docker.d.ts +15 -0
- package/dist/core/docker.js +38 -1
- package/dist/core/docker.js.map +1 -1
- package/dist/core/repo-create.d.ts +11 -0
- package/dist/core/repo-create.js +54 -0
- package/dist/core/repo-create.js.map +1 -0
- package/dist/core/terminal-manager.d.ts +2 -0
- package/dist/core/terminal-manager.js +6 -0
- package/dist/core/terminal-manager.js.map +1 -1
- package/dist/core/terminal-session.d.ts +9 -1
- package/dist/core/terminal-session.js +24 -1
- package/dist/core/terminal-session.js.map +1 -1
- package/dist/core/types.d.ts +6 -0
- package/dist/web/client/assets/SymbolsNerdFontMono-Regular-DDncdh2F.ttf +0 -0
- package/dist/web/client/assets/{code-editor-B6KniYQs.js → code-editor-CRI31ZMh.js} +1 -1
- package/dist/web/client/assets/index-CQU15q2M.css +1 -0
- package/dist/web/client/assets/index-hu3LqMhU.js +228 -0
- package/dist/web/client/index.html +2 -2
- package/dist/web/routes/docker-routes.js +29 -2
- package/dist/web/routes/docker-routes.js.map +1 -1
- package/dist/web/routes/git-routes.js +36 -0
- package/dist/web/routes/git-routes.js.map +1 -1
- package/dist/web/routes/service-routes.js +21 -0
- package/dist/web/routes/service-routes.js.map +1 -1
- package/dist/web/routes/terminal-routes.js +37 -7
- package/dist/web/routes/terminal-routes.js.map +1 -1
- package/package.json +1 -1
- package/dist/web/client/assets/index-C2DM01M9.js +0 -228
- package/dist/web/client/assets/index-D971Mghq.css +0 -1
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `docker inspect` for a single container, flattened to what the detail panel
|
|
3
|
+
* actually renders. Raw inspect output is a deeply nested ~200-key document;
|
|
4
|
+
* shipping it wholesale to the client would be both noisy and a needless
|
|
5
|
+
* disclosure surface, so this picks fields deliberately.
|
|
6
|
+
*/
|
|
7
|
+
import { execDocker, validateContainerId } from "./docker.js";
|
|
8
|
+
/**
|
|
9
|
+
* Env values are masked when the key looks like a credential. This is a local
|
|
10
|
+
* dashboard, but the same daemon port is what MCP agents talk to — a container
|
|
11
|
+
* password shouldn't land in an agent transcript just because someone opened a
|
|
12
|
+
* detail panel.
|
|
13
|
+
*/
|
|
14
|
+
const SECRET_KEY_PATTERN = /(pass|secret|token|key|credential|auth)/i;
|
|
15
|
+
export async function inspectDockerContainer(id) {
|
|
16
|
+
validateContainerId(id);
|
|
17
|
+
const stdout = await execDocker(["inspect", id]);
|
|
18
|
+
const parsed = JSON.parse(stdout);
|
|
19
|
+
const raw = Array.isArray(parsed) ? parsed[0] : parsed;
|
|
20
|
+
if (!raw || typeof raw !== "object") {
|
|
21
|
+
throw new Error(`No inspect output for container "${id}"`);
|
|
22
|
+
}
|
|
23
|
+
return mapInspectDocument(raw);
|
|
24
|
+
}
|
|
25
|
+
export function mapInspectDocument(raw) {
|
|
26
|
+
const config = asRecord(raw.Config);
|
|
27
|
+
const state = asRecord(raw.State);
|
|
28
|
+
const hostConfig = asRecord(raw.NetworkSettings);
|
|
29
|
+
return {
|
|
30
|
+
id: asString(raw.Id),
|
|
31
|
+
// Docker prefixes container names with a slash; nobody wants to read that.
|
|
32
|
+
name: asString(raw.Name).replace(/^\//, ""),
|
|
33
|
+
image: asString(config.Image),
|
|
34
|
+
command: [asString(config.Entrypoint), ...asStringArray(config.Cmd)]
|
|
35
|
+
.filter(Boolean)
|
|
36
|
+
.join(" "),
|
|
37
|
+
created: asString(raw.Created),
|
|
38
|
+
state: asString(state.Status),
|
|
39
|
+
startedAt: asString(state.StartedAt),
|
|
40
|
+
restartCount: typeof raw.RestartCount === "number" ? raw.RestartCount : 0,
|
|
41
|
+
env: parseEnvList(asStringArray(config.Env)),
|
|
42
|
+
mounts: parseMounts(raw.Mounts),
|
|
43
|
+
ports: parsePortBindings(hostConfig.Ports),
|
|
44
|
+
networks: Object.keys(asRecord(hostConfig.Networks)),
|
|
45
|
+
labels: parseLabels(config.Labels),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
export function parseEnvList(entries) {
|
|
49
|
+
return entries.map((entry) => {
|
|
50
|
+
const separator = entry.indexOf("=");
|
|
51
|
+
const key = separator === -1 ? entry : entry.slice(0, separator);
|
|
52
|
+
const value = separator === -1 ? "" : entry.slice(separator + 1);
|
|
53
|
+
const secret = SECRET_KEY_PATTERN.test(key) && value.length > 0;
|
|
54
|
+
return { key, value: secret ? "••••••••" : value, secret };
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
function parseMounts(raw) {
|
|
58
|
+
if (!Array.isArray(raw))
|
|
59
|
+
return [];
|
|
60
|
+
return raw.filter(isRecord).map((mount) => ({
|
|
61
|
+
type: asString(mount.Type),
|
|
62
|
+
// Named volumes report Name; bind mounts report Source.
|
|
63
|
+
source: asString(mount.Name) || asString(mount.Source),
|
|
64
|
+
destination: asString(mount.Destination),
|
|
65
|
+
readOnly: mount.RW === false,
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
/** NetworkSettings.Ports maps "5432/tcp" to a list of host bindings, or null. */
|
|
69
|
+
function parsePortBindings(raw) {
|
|
70
|
+
if (!isRecord(raw))
|
|
71
|
+
return [];
|
|
72
|
+
const bindings = [];
|
|
73
|
+
for (const [containerPort, hostList] of Object.entries(raw)) {
|
|
74
|
+
if (!Array.isArray(hostList) || hostList.length === 0) {
|
|
75
|
+
bindings.push({ containerPort, hostPort: "" });
|
|
76
|
+
continue;
|
|
77
|
+
}
|
|
78
|
+
for (const host of hostList.filter(isRecord)) {
|
|
79
|
+
const ip = asString(host.HostIp);
|
|
80
|
+
const port = asString(host.HostPort);
|
|
81
|
+
bindings.push({ containerPort, hostPort: ip ? `${ip}:${port}` : port });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return bindings;
|
|
85
|
+
}
|
|
86
|
+
function parseLabels(raw) {
|
|
87
|
+
if (!isRecord(raw))
|
|
88
|
+
return {};
|
|
89
|
+
const labels = {};
|
|
90
|
+
for (const [key, value] of Object.entries(raw)) {
|
|
91
|
+
if (typeof value === "string")
|
|
92
|
+
labels[key] = value;
|
|
93
|
+
}
|
|
94
|
+
return labels;
|
|
95
|
+
}
|
|
96
|
+
function isRecord(value) {
|
|
97
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
98
|
+
}
|
|
99
|
+
function asRecord(value) {
|
|
100
|
+
return isRecord(value) ? value : {};
|
|
101
|
+
}
|
|
102
|
+
function asString(value) {
|
|
103
|
+
return typeof value === "string" ? value : "";
|
|
104
|
+
}
|
|
105
|
+
function asStringArray(value) {
|
|
106
|
+
return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=docker-inspect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-inspect.js","sourceRoot":"","sources":["../../src/core/docker-inspect.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export interface DockerImageSummary {
|
|
2
|
+
id: string;
|
|
3
|
+
repository: string;
|
|
4
|
+
tag: string;
|
|
5
|
+
/** Human size string straight from Docker, e.g. "417MB". */
|
|
6
|
+
size: string;
|
|
7
|
+
createdSince: string;
|
|
8
|
+
/** True for untagged layers left behind by rebuilds (`<none>:<none>`). */
|
|
9
|
+
dangling: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function listDockerImages(): Promise<DockerImageSummary[]>;
|
|
12
|
+
export declare function parseDockerImageLines(stdout: string): DockerImageSummary[];
|
|
13
|
+
export interface DockerVolumeSummary {
|
|
14
|
+
name: string;
|
|
15
|
+
driver: string;
|
|
16
|
+
mountpoint: string;
|
|
17
|
+
scope: string;
|
|
18
|
+
}
|
|
19
|
+
export declare function listDockerVolumes(): Promise<DockerVolumeSummary[]>;
|
|
20
|
+
export declare function parseDockerVolumeLines(stdout: string): DockerVolumeSummary[];
|
|
21
|
+
export interface DockerNetworkSummary {
|
|
22
|
+
id: string;
|
|
23
|
+
name: string;
|
|
24
|
+
driver: string;
|
|
25
|
+
scope: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function listDockerNetworks(): Promise<DockerNetworkSummary[]>;
|
|
28
|
+
export declare function parseDockerNetworkLines(stdout: string): DockerNetworkSummary[];
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The non-container half of a Docker host: images, volumes, and networks.
|
|
3
|
+
* Read-only by design — pruning and removal are destructive and belong behind
|
|
4
|
+
* an explicit guard, mirroring the git-manager / git-actions split.
|
|
5
|
+
*/
|
|
6
|
+
import { execDocker, parseDockerJsonLines, readString } from "./docker.js";
|
|
7
|
+
export async function listDockerImages() {
|
|
8
|
+
return parseDockerImageLines(await execDocker(["images", "--format", "{{json .}}"]));
|
|
9
|
+
}
|
|
10
|
+
export function parseDockerImageLines(stdout) {
|
|
11
|
+
return parseDockerJsonLines(stdout, (raw) => {
|
|
12
|
+
const id = readString(raw, "ID");
|
|
13
|
+
if (!id)
|
|
14
|
+
return null;
|
|
15
|
+
const repository = readString(raw, "Repository");
|
|
16
|
+
const tag = readString(raw, "Tag");
|
|
17
|
+
return {
|
|
18
|
+
id,
|
|
19
|
+
repository,
|
|
20
|
+
tag,
|
|
21
|
+
size: readString(raw, "Size"),
|
|
22
|
+
createdSince: readString(raw, "CreatedSince"),
|
|
23
|
+
dangling: repository === "<none>" || tag === "<none>",
|
|
24
|
+
};
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
export async function listDockerVolumes() {
|
|
28
|
+
return parseDockerVolumeLines(await execDocker(["volume", "ls", "--format", "{{json .}}"]));
|
|
29
|
+
}
|
|
30
|
+
export function parseDockerVolumeLines(stdout) {
|
|
31
|
+
return parseDockerJsonLines(stdout, (raw) => {
|
|
32
|
+
const name = readString(raw, "Name");
|
|
33
|
+
if (!name)
|
|
34
|
+
return null;
|
|
35
|
+
return {
|
|
36
|
+
name,
|
|
37
|
+
driver: readString(raw, "Driver"),
|
|
38
|
+
mountpoint: readString(raw, "Mountpoint"),
|
|
39
|
+
scope: readString(raw, "Scope"),
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
export async function listDockerNetworks() {
|
|
44
|
+
return parseDockerNetworkLines(await execDocker(["network", "ls", "--format", "{{json .}}"]));
|
|
45
|
+
}
|
|
46
|
+
export function parseDockerNetworkLines(stdout) {
|
|
47
|
+
return parseDockerJsonLines(stdout, (raw) => {
|
|
48
|
+
const id = readString(raw, "ID");
|
|
49
|
+
if (!id)
|
|
50
|
+
return null;
|
|
51
|
+
return {
|
|
52
|
+
id,
|
|
53
|
+
name: readString(raw, "Name"),
|
|
54
|
+
driver: readString(raw, "Driver"),
|
|
55
|
+
scope: readString(raw, "Scope"),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=docker-resources.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-resources.js","sourceRoot":"","sources":["../../src/core/docker-resources.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAa3E,MAAM,CAAC,KAAK,UAAU,gBAAgB;IACpC,OAAO,qBAAqB,CAAC,MAAM,UAAU,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1C,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACrB,MAAM,UAAU,GAAG,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;QACjD,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,OAAO;YACL,EAAE;YACF,UAAU;YACV,GAAG;YACH,IAAI,EAAE,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;YAC7B,YAAY,EAAE,UAAU,CAAC,GAAG,EAAE,cAAc,CAAC;YAC7C,QAAQ,EAAE,UAAU,KAAK,QAAQ,IAAI,GAAG,KAAK,QAAQ;SACtD,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,OAAO,sBAAsB,CAAC,MAAM,UAAU,CAAC,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,MAAc;IACnD,OAAO,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1C,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAC;QACvB,OAAO;YACL,IAAI;YACJ,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;YACjC,UAAU,EAAE,UAAU,CAAC,GAAG,EAAE,YAAY,CAAC;YACzC,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SAChC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AASD,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,OAAO,uBAAuB,CAAC,MAAM,UAAU,CAAC,CAAC,SAAS,EAAE,IAAI,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;AAChG,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1C,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACrB,OAAO;YACL,EAAE;YACF,IAAI,EAAE,UAAU,CAAC,GAAG,EAAE,MAAM,CAAC;YAC7B,MAAM,EAAE,UAAU,CAAC,GAAG,EAAE,QAAQ,CAAC;YACjC,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;SAChC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export interface DockerContainerStats {
|
|
2
|
+
id: string;
|
|
3
|
+
/** Null when Docker reports a non-numeric value (e.g. "--" for a stopped container). */
|
|
4
|
+
cpuPercent: number | null;
|
|
5
|
+
memoryPercent: number | null;
|
|
6
|
+
/** Raw "184MiB / 2GiB" string — shown verbatim, Docker already picked sane units. */
|
|
7
|
+
memoryUsage: string;
|
|
8
|
+
/** Raw "1.2kB / 648B" network I/O string. */
|
|
9
|
+
netIo: string;
|
|
10
|
+
blockIo: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function listDockerStats(): Promise<DockerContainerStats[]>;
|
|
13
|
+
export declare function parseDockerStatsLines(stdout: string): DockerContainerStats[];
|
|
14
|
+
/** Docker formats percentages as "2.43%", or "--" when it has no sample. */
|
|
15
|
+
export declare function parsePercent(value: string): number | null;
|
|
16
|
+
/**
|
|
17
|
+
* `docker stats` keys rows by the short (12-char) ID while `docker ps` reports
|
|
18
|
+
* the same short form — but callers may hold either, so match on prefix in
|
|
19
|
+
* whichever direction is longer.
|
|
20
|
+
*/
|
|
21
|
+
export declare function indexStatsById(stats: DockerContainerStats[]): Map<string, DockerContainerStats>;
|
|
22
|
+
export declare function findStatsFor(index: Map<string, DockerContainerStats>, containerId: string): DockerContainerStats | undefined;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-container resource usage via `docker stats --no-stream`. Kept out of
|
|
3
|
+
* `docker.ts` because it's the one Docker read that is genuinely expensive —
|
|
4
|
+
* the daemon samples every running container before it answers — so the UI
|
|
5
|
+
* polls it on its own cadence rather than folding it into the container list.
|
|
6
|
+
*/
|
|
7
|
+
import { execDocker, parseDockerJsonLines, readString } from "./docker.js";
|
|
8
|
+
export async function listDockerStats() {
|
|
9
|
+
return parseDockerStatsLines(await execDocker(["stats", "--no-stream", "--format", "{{json .}}"]));
|
|
10
|
+
}
|
|
11
|
+
export function parseDockerStatsLines(stdout) {
|
|
12
|
+
return parseDockerJsonLines(stdout, (raw) => {
|
|
13
|
+
const id = readString(raw, "ID") || readString(raw, "Container");
|
|
14
|
+
if (!id)
|
|
15
|
+
return null;
|
|
16
|
+
return {
|
|
17
|
+
id,
|
|
18
|
+
cpuPercent: parsePercent(readString(raw, "CPUPerc")),
|
|
19
|
+
memoryPercent: parsePercent(readString(raw, "MemPerc")),
|
|
20
|
+
memoryUsage: readString(raw, "MemUsage"),
|
|
21
|
+
netIo: readString(raw, "NetIO"),
|
|
22
|
+
blockIo: readString(raw, "BlockIO"),
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/** Docker formats percentages as "2.43%", or "--" when it has no sample. */
|
|
27
|
+
export function parsePercent(value) {
|
|
28
|
+
const parsed = Number.parseFloat(value.replace("%", "").trim());
|
|
29
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* `docker stats` keys rows by the short (12-char) ID while `docker ps` reports
|
|
33
|
+
* the same short form — but callers may hold either, so match on prefix in
|
|
34
|
+
* whichever direction is longer.
|
|
35
|
+
*/
|
|
36
|
+
export function indexStatsById(stats) {
|
|
37
|
+
const index = new Map();
|
|
38
|
+
for (const entry of stats)
|
|
39
|
+
index.set(entry.id, entry);
|
|
40
|
+
return index;
|
|
41
|
+
}
|
|
42
|
+
export function findStatsFor(index, containerId) {
|
|
43
|
+
const exact = index.get(containerId);
|
|
44
|
+
if (exact)
|
|
45
|
+
return exact;
|
|
46
|
+
for (const [id, entry] of index) {
|
|
47
|
+
if (id.startsWith(containerId) || containerId.startsWith(id))
|
|
48
|
+
return entry;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=docker-stats.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-stats.js","sourceRoot":"","sources":["../../src/core/docker-stats.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,oBAAoB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAc3E,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,OAAO,qBAAqB,CAC1B,MAAM,UAAU,CAAC,CAAC,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,CACrE,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,OAAO,oBAAoB,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;QAC1C,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,UAAU,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACjE,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAC;QACrB,OAAO;YACL,EAAE;YACF,UAAU,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACpD,aAAa,EAAE,YAAY,CAAC,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;YACvD,WAAW,EAAE,UAAU,CAAC,GAAG,EAAE,UAAU,CAAC;YACxC,KAAK,EAAE,UAAU,CAAC,GAAG,EAAE,OAAO,CAAC;YAC/B,OAAO,EAAE,UAAU,CAAC,GAAG,EAAE,SAAS,CAAC;SACpC,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACjD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAC5B,KAA6B;IAE7B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAgC,CAAC;IACtD,KAAK,MAAM,KAAK,IAAI,KAAK;QAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IACtD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,YAAY,CAC1B,KAAwC,EACxC,WAAmB;IAEnB,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IACrC,IAAI,KAAK;QAAE,OAAO,KAAK,CAAC;IACxB,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,KAAK,EAAE,CAAC;QAChC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAC;IAC7E,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/core/docker.d.ts
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single entry point for every `docker` invocation in this feature. Sibling
|
|
3
|
+
* modules (stats/resources/inspect) go through here so argument handling and
|
|
4
|
+
* the no-shell-interpolation guarantee stay in one place.
|
|
5
|
+
*/
|
|
6
|
+
export declare function execDocker(args: string[]): Promise<string>;
|
|
7
|
+
/**
|
|
8
|
+
* Most `docker ... --format "{{json .}}"` commands emit one JSON object per
|
|
9
|
+
* line. Parse leniently: a single malformed line shouldn't blank the view.
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseDockerJsonLines<T>(stdout: string, map: (raw: Record<string, unknown>) => T | null): T[];
|
|
12
|
+
/** Read a string field off a `docker ... --format "{{json .}}"` row. */
|
|
13
|
+
export declare function readString(raw: Record<string, unknown>, key: string): string;
|
|
1
14
|
export interface DockerStatus {
|
|
2
15
|
available: boolean;
|
|
3
16
|
version?: string;
|
|
@@ -31,3 +44,5 @@ export declare function readDockerContainerLogs(id: string, tail?: number): Prom
|
|
|
31
44
|
* combined lines reconstructs chronological order.
|
|
32
45
|
*/
|
|
33
46
|
export declare function mergeTimestampedLogLines(stdout: string, stderr: string): string;
|
|
47
|
+
/** Docker container IDs/names are alphanumeric plus `_.-`; reject anything else. */
|
|
48
|
+
export declare function validateContainerId(id: string): void;
|
package/dist/core/docker.js
CHANGED
|
@@ -8,6 +8,43 @@
|
|
|
8
8
|
import { execFile } from "node:child_process";
|
|
9
9
|
import { promisify } from "node:util";
|
|
10
10
|
const execFileAsync = promisify(execFile);
|
|
11
|
+
/**
|
|
12
|
+
* Single entry point for every `docker` invocation in this feature. Sibling
|
|
13
|
+
* modules (stats/resources/inspect) go through here so argument handling and
|
|
14
|
+
* the no-shell-interpolation guarantee stay in one place.
|
|
15
|
+
*/
|
|
16
|
+
export async function execDocker(args) {
|
|
17
|
+
// Docker can emit a lot on `inspect`/`logs`; the default 1MB buffer truncates.
|
|
18
|
+
const { stdout } = await execFileAsync("docker", args, { maxBuffer: 32 * 1024 * 1024 });
|
|
19
|
+
return stdout;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Most `docker ... --format "{{json .}}"` commands emit one JSON object per
|
|
23
|
+
* line. Parse leniently: a single malformed line shouldn't blank the view.
|
|
24
|
+
*/
|
|
25
|
+
export function parseDockerJsonLines(stdout, map) {
|
|
26
|
+
const rows = [];
|
|
27
|
+
for (const line of stdout.split(/\r?\n/)) {
|
|
28
|
+
const trimmed = line.trim();
|
|
29
|
+
if (!trimmed)
|
|
30
|
+
continue;
|
|
31
|
+
let raw;
|
|
32
|
+
try {
|
|
33
|
+
raw = JSON.parse(trimmed);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
const mapped = map(raw);
|
|
39
|
+
if (mapped !== null)
|
|
40
|
+
rows.push(mapped);
|
|
41
|
+
}
|
|
42
|
+
return rows;
|
|
43
|
+
}
|
|
44
|
+
/** Read a string field off a `docker ... --format "{{json .}}"` row. */
|
|
45
|
+
export function readString(raw, key) {
|
|
46
|
+
return typeof raw[key] === "string" ? raw[key] : "";
|
|
47
|
+
}
|
|
11
48
|
/** Whether the `docker` CLI/daemon is reachable at all, for the page's empty state. */
|
|
12
49
|
export async function getDockerStatus() {
|
|
13
50
|
try {
|
|
@@ -102,7 +139,7 @@ function splitNonEmptyLines(text) {
|
|
|
102
139
|
return text.split(/\r?\n/).filter((line) => line.length > 0);
|
|
103
140
|
}
|
|
104
141
|
/** Docker container IDs/names are alphanumeric plus `_.-`; reject anything else. */
|
|
105
|
-
function validateContainerId(id) {
|
|
142
|
+
export function validateContainerId(id) {
|
|
106
143
|
if (!/^[a-zA-Z0-9][a-zA-Z0-9_.-]*$/.test(id)) {
|
|
107
144
|
throw new Error(`Invalid container id: "${id}"`);
|
|
108
145
|
}
|
package/dist/core/docker.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/core/docker.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"docker.js","sourceRoot":"","sources":["../../src/core/docker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Sanitise a user-typed project name into a safe single directory segment. */
|
|
2
|
+
export declare function sanitizeProjectName(raw: string): string;
|
|
3
|
+
export interface CreateRepoResult {
|
|
4
|
+
name: string;
|
|
5
|
+
path: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Create `<parentDir>/<name>` as an initialised Git repository. `parentDir`
|
|
9
|
+
* defaults to the managed repos dir, the same place clones land.
|
|
10
|
+
*/
|
|
11
|
+
export declare function createRepository(rawName: string, parentDir?: string): Promise<CreateRepoResult>;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { mkdir, readdir, writeFile } from "node:fs/promises";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { defaultReposDir } from "./repo-onboard.js";
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
/**
|
|
8
|
+
* Create a brand-new Git project from nothing: make the directory, `git init`
|
|
9
|
+
* it, and seed a README so the folder is not empty.
|
|
10
|
+
*
|
|
11
|
+
* Like cloning, this is an additive write that deliberately lives outside the
|
|
12
|
+
* read-safe GitManager. It only ever creates a *new* directory — it refuses to
|
|
13
|
+
* touch one that already has contents — so it can never clobber existing work.
|
|
14
|
+
*/
|
|
15
|
+
const UNSAFE_NAME = /[^a-zA-Z0-9._-]+/g;
|
|
16
|
+
/** Sanitise a user-typed project name into a safe single directory segment. */
|
|
17
|
+
export function sanitizeProjectName(raw) {
|
|
18
|
+
const name = raw
|
|
19
|
+
.trim()
|
|
20
|
+
.replace(UNSAFE_NAME, "-")
|
|
21
|
+
.replace(/^[-.]+|-+$/g, "");
|
|
22
|
+
if (!name)
|
|
23
|
+
throw new Error("Project name is required.");
|
|
24
|
+
return name;
|
|
25
|
+
}
|
|
26
|
+
async function isNonEmptyDir(path) {
|
|
27
|
+
try {
|
|
28
|
+
return (await readdir(path)).length > 0;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error.code === "ENOENT")
|
|
32
|
+
return false;
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Create `<parentDir>/<name>` as an initialised Git repository. `parentDir`
|
|
38
|
+
* defaults to the managed repos dir, the same place clones land.
|
|
39
|
+
*/
|
|
40
|
+
export async function createRepository(rawName, parentDir = defaultReposDir()) {
|
|
41
|
+
const name = sanitizeProjectName(rawName);
|
|
42
|
+
const parent = resolve(parentDir);
|
|
43
|
+
if (!parent.startsWith("/"))
|
|
44
|
+
throw new Error("Parent directory must be an absolute path.");
|
|
45
|
+
const path = join(parent, name);
|
|
46
|
+
if (await isNonEmptyDir(path)) {
|
|
47
|
+
throw new Error(`Destination already exists and is not empty: ${path}.`);
|
|
48
|
+
}
|
|
49
|
+
await mkdir(path, { recursive: true });
|
|
50
|
+
await execFileAsync("git", ["init", "-b", "main"], { cwd: path });
|
|
51
|
+
await writeFile(join(path, "README.md"), `# ${name}\n`, "utf8");
|
|
52
|
+
return { name, path };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=repo-create.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-create.js","sourceRoot":"","sources":["../../src/core/repo-create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C;;;;;;;GAOG;AAEH,MAAM,WAAW,GAAG,mBAAmB,CAAC;AAExC,+EAA+E;AAC/E,MAAM,UAAU,mBAAmB,CAAC,GAAW;IAC7C,MAAM,IAAI,GAAG,GAAG;SACb,IAAI,EAAE;SACN,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;SACzB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC9B,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;IACxD,OAAO,IAAI,CAAC;AACd,CAAC;AAOD,KAAK,UAAU,aAAa,CAAC,IAAY;IACvC,IAAI,CAAC;QACH,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC1C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACrE,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,OAAe,EACf,YAAoB,eAAe,EAAE;IAErC,MAAM,IAAI,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC3F,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAChC,IAAI,MAAM,aAAa,CAAC,IAAI,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,gDAAgD,IAAI,GAAG,CAAC,CAAC;IAC3E,CAAC;IACD,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,MAAM,aAAa,CAAC,KAAK,EAAE,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IAClE,MAAM,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,KAAK,IAAI,IAAI,EAAE,MAAM,CAAC,CAAC;IAChE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxB,CAAC"}
|
|
@@ -26,6 +26,7 @@ export interface TerminalSessionManagerLike {
|
|
|
26
26
|
touch(id: string): void;
|
|
27
27
|
/** A client socket disconnected; reap the session after the grace window. */
|
|
28
28
|
detach(id: string): void;
|
|
29
|
+
rename(id: string, label: string): TerminalSessionInfo | undefined;
|
|
29
30
|
close(id: string): boolean;
|
|
30
31
|
disposeAll(): void;
|
|
31
32
|
}
|
|
@@ -71,6 +72,7 @@ export declare class TerminalSessionManager implements TerminalSessionManagerLik
|
|
|
71
72
|
ensure(id: string, size?: Partial<TerminalSize>): TerminalSessionLike;
|
|
72
73
|
touch(id: string): void;
|
|
73
74
|
detach(id: string): void;
|
|
75
|
+
rename(id: string, label: string): TerminalSessionInfo | undefined;
|
|
74
76
|
close(id: string): boolean;
|
|
75
77
|
disposeAll(): void;
|
|
76
78
|
private spawn;
|
|
@@ -85,6 +85,12 @@ export class TerminalSessionManager {
|
|
|
85
85
|
// process shutdown disposes everything (see `disposeAll`).
|
|
86
86
|
managed.connections = Math.max(0, managed.connections - 1);
|
|
87
87
|
}
|
|
88
|
+
rename(id, label) {
|
|
89
|
+
const managed = this.sessions.get(id);
|
|
90
|
+
if (!managed)
|
|
91
|
+
return undefined;
|
|
92
|
+
return { id, ...managed.session.setLabel(label) };
|
|
93
|
+
}
|
|
88
94
|
close(id) {
|
|
89
95
|
const managed = this.sessions.get(id);
|
|
90
96
|
if (!managed)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-manager.js","sourceRoot":"","sources":["../../src/core/terminal-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,GAIhB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"terminal-manager.js","sourceRoot":"","sources":["../../src/core/terminal-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -51,6 +51,12 @@ export interface TerminalSessionOptions {
|
|
|
51
51
|
provider?: InteractiveAgentProvider;
|
|
52
52
|
}
|
|
53
53
|
type Listener<T> = (value: T) => void;
|
|
54
|
+
/**
|
|
55
|
+
* Every xterm-backed PTY should advertise its real capabilities even when
|
|
56
|
+
* NoMoreIDE itself was launched by a parent process that suppresses colour.
|
|
57
|
+
* This also covers Claude or Codex launched later from an ordinary shell.
|
|
58
|
+
*/
|
|
59
|
+
export declare function interactiveTerminalEnv(inherited: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
54
60
|
export interface TerminalSessionLike {
|
|
55
61
|
dispose(): void;
|
|
56
62
|
onOutput(listener: Listener<string>): {
|
|
@@ -59,6 +65,7 @@ export interface TerminalSessionLike {
|
|
|
59
65
|
onState(listener: Listener<TerminalSnapshot>): {
|
|
60
66
|
dispose(): void;
|
|
61
67
|
};
|
|
68
|
+
setLabel(label: string): TerminalSnapshot;
|
|
62
69
|
resize(cols: number, rows: number): TerminalSnapshot;
|
|
63
70
|
restart(size?: Partial<TerminalSize>): TerminalSnapshot;
|
|
64
71
|
snapshot(): TerminalSnapshot;
|
|
@@ -72,7 +79,7 @@ export declare class TerminalSession implements TerminalSessionLike {
|
|
|
72
79
|
private readonly env;
|
|
73
80
|
private readonly shell;
|
|
74
81
|
private readonly args;
|
|
75
|
-
private
|
|
82
|
+
private label;
|
|
76
83
|
private readonly kind;
|
|
77
84
|
private readonly provider;
|
|
78
85
|
private cols;
|
|
@@ -92,6 +99,7 @@ export declare class TerminalSession implements TerminalSessionLike {
|
|
|
92
99
|
onState(listener: Listener<TerminalSnapshot>): {
|
|
93
100
|
dispose(): void;
|
|
94
101
|
};
|
|
102
|
+
setLabel(label: string): TerminalSnapshot;
|
|
95
103
|
start(size?: Partial<TerminalSize>): TerminalSnapshot;
|
|
96
104
|
restart(size?: Partial<TerminalSize>): TerminalSnapshot;
|
|
97
105
|
stop(signal?: string): TerminalSnapshot;
|
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
const require = createRequire(import.meta.url);
|
|
3
|
+
/**
|
|
4
|
+
* Every xterm-backed PTY should advertise its real capabilities even when
|
|
5
|
+
* NoMoreIDE itself was launched by a parent process that suppresses colour.
|
|
6
|
+
* This also covers Claude or Codex launched later from an ordinary shell.
|
|
7
|
+
*/
|
|
8
|
+
export function interactiveTerminalEnv(inherited) {
|
|
9
|
+
const env = {
|
|
10
|
+
...inherited,
|
|
11
|
+
COLORTERM: "truecolor",
|
|
12
|
+
TERM: "xterm-256color",
|
|
13
|
+
};
|
|
14
|
+
delete env.NO_COLOR;
|
|
15
|
+
// The machine-global daemon may be auto-started by the Claude Code MCP.
|
|
16
|
+
// That parent exports CLAUDECODE=1, but a terminal opened in NoMoreIDE is a
|
|
17
|
+
// new top-level session. Forwarding the marker makes Claude reject its own
|
|
18
|
+
// launch as a nested session before the terminal can render.
|
|
19
|
+
delete env.CLAUDECODE;
|
|
20
|
+
return env;
|
|
21
|
+
}
|
|
3
22
|
export class TerminalSession {
|
|
4
23
|
adapter;
|
|
5
24
|
cwd;
|
|
@@ -21,7 +40,7 @@ export class TerminalSession {
|
|
|
21
40
|
constructor(options) {
|
|
22
41
|
this.adapter = options.adapter ?? new NodePtyAdapter();
|
|
23
42
|
this.cwd = options.cwd;
|
|
24
|
-
this.env = options.env ?? process.env;
|
|
43
|
+
this.env = interactiveTerminalEnv(options.env ?? process.env);
|
|
25
44
|
this.shell = options.shell ?? defaultShell();
|
|
26
45
|
this.args = options.args ?? [];
|
|
27
46
|
this.label = options.label;
|
|
@@ -58,6 +77,10 @@ export class TerminalSession {
|
|
|
58
77
|
},
|
|
59
78
|
};
|
|
60
79
|
}
|
|
80
|
+
setLabel(label) {
|
|
81
|
+
this.label = label;
|
|
82
|
+
return this.snapshot();
|
|
83
|
+
}
|
|
61
84
|
start(size = {}) {
|
|
62
85
|
if (this.process && this.state === "running") {
|
|
63
86
|
if (size.cols && size.rows)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal-session.js","sourceRoot":"","sources":["../../src/core/terminal-session.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAG5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"terminal-session.js","sourceRoot":"","sources":["../../src/core/terminal-session.ts"],"names":[],"mappings":"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"}
|