@ai-support-agent/cli 0.0.39 → 0.0.40-beta.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/dist/agent-runner.d.ts +2 -6
- package/dist/agent-runner.d.ts.map +1 -1
- package/dist/agent-runner.js +6 -13
- package/dist/agent-runner.js.map +1 -1
- package/dist/api-client.d.ts.map +1 -1
- package/dist/api-client.js +3 -7
- package/dist/api-client.js.map +1 -1
- package/dist/commands/chat-executor.d.ts +0 -14
- package/dist/commands/chat-executor.d.ts.map +1 -1
- package/dist/commands/chat-executor.js +0 -18
- package/dist/commands/chat-executor.js.map +1 -1
- package/dist/docker/docker-runner.d.ts +16 -70
- package/dist/docker/docker-runner.d.ts.map +1 -1
- package/dist/docker/docker-runner.js +50 -989
- package/dist/docker/docker-runner.js.map +1 -1
- package/dist/docker/docker-security.d.ts +11 -0
- package/dist/docker/docker-security.d.ts.map +1 -0
- package/dist/docker/docker-security.js +25 -0
- package/dist/docker/docker-security.js.map +1 -0
- package/dist/docker/docker-supervisor.d.ts +30 -0
- package/dist/docker/docker-supervisor.d.ts.map +1 -0
- package/dist/docker/docker-supervisor.js +408 -0
- package/dist/docker/docker-supervisor.js.map +1 -0
- package/dist/docker/docker-utils.d.ts +46 -0
- package/dist/docker/docker-utils.d.ts.map +1 -0
- package/dist/docker/docker-utils.js +147 -0
- package/dist/docker/docker-utils.js.map +1 -0
- package/dist/docker/dockerfile-generator.d.ts +13 -0
- package/dist/docker/dockerfile-generator.d.ts.map +1 -0
- package/dist/docker/dockerfile-generator.js +50 -0
- package/dist/docker/dockerfile-generator.js.map +1 -0
- package/dist/docker/dockerfile-sync.d.ts +13 -0
- package/dist/docker/dockerfile-sync.d.ts.map +1 -0
- package/dist/docker/dockerfile-sync.js +76 -0
- package/dist/docker/dockerfile-sync.js.map +1 -0
- package/dist/docker/project-config.d.ts +22 -0
- package/dist/docker/project-config.d.ts.map +1 -0
- package/dist/docker/project-config.js +80 -0
- package/dist/docker/project-config.js.map +1 -0
- package/dist/docker/project-image-builder.d.ts +12 -0
- package/dist/docker/project-image-builder.d.ts.map +1 -0
- package/dist/docker/project-image-builder.js +90 -0
- package/dist/docker/project-image-builder.js.map +1 -0
- package/dist/docker/update-handler.d.ts +14 -0
- package/dist/docker/update-handler.d.ts.map +1 -0
- package/dist/docker/update-handler.js +93 -0
- package/dist/docker/update-handler.js.map +1 -0
- package/dist/docker/version-manager.d.ts +21 -0
- package/dist/docker/version-manager.d.ts.map +1 -0
- package/dist/docker/version-manager.js +67 -0
- package/dist/docker/version-manager.js.map +1 -0
- package/dist/docker/volume-mount-builder.d.ts +38 -0
- package/dist/docker/volume-mount-builder.d.ts.map +1 -0
- package/dist/docker/volume-mount-builder.js +237 -0
- package/dist/docker/volume-mount-builder.js.map +1 -0
- package/dist/project-agent.d.ts.map +1 -1
- package/dist/project-agent.js +2 -6
- package/dist/project-agent.js.map +1 -1
- package/dist/utils/token-utils.d.ts +30 -0
- package/dist/utils/token-utils.d.ts.map +1 -0
- package/dist/utils/token-utils.js +44 -0
- package/dist/utils/token-utils.js.map +1 -0
- package/dist/utils.d.ts +6 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +11 -0
- package/dist/utils.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Basic Docker utilities
|
|
3
|
+
*
|
|
4
|
+
* Availability checks, image operations, container naming.
|
|
5
|
+
*/
|
|
6
|
+
import { AGENT_VERSION } from '../constants';
|
|
7
|
+
export declare const IMAGE_NAME = "ai-support-agent";
|
|
8
|
+
export declare function checkDockerAvailable(): boolean;
|
|
9
|
+
export declare function imageExists(version: string): boolean;
|
|
10
|
+
export declare function buildImage(version: string, customDockerfile?: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Build a deterministic container name for a project.
|
|
13
|
+
* Format: ai-{tenantCode}-{projectCode}-{agentId}
|
|
14
|
+
* All components are lowercased and non-alphanumeric chars (except hyphens) are replaced with hyphens.
|
|
15
|
+
*/
|
|
16
|
+
export declare function buildContainerName(tenantCode: string, projectCode: string, agentId?: string): string;
|
|
17
|
+
/**
|
|
18
|
+
* Remove a stale container with the given name if it exists.
|
|
19
|
+
* This handles the case where a previous run crashed and left a container behind,
|
|
20
|
+
* which would prevent `docker run --name` from succeeding.
|
|
21
|
+
*/
|
|
22
|
+
export declare function removeStaleContainer(containerName: string): void;
|
|
23
|
+
export declare function dockerLogin(): void;
|
|
24
|
+
/** Convert a path.relative() result to POSIX format for container use */
|
|
25
|
+
export declare function toPosixRelative(relativePath: string): string;
|
|
26
|
+
/**
|
|
27
|
+
* Returns true when running via ts-node (i.e. `npm run dev`).
|
|
28
|
+
* In this case, local dist/ should be mounted into containers instead of
|
|
29
|
+
* relying on the npm-installed package inside the image.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isRunningViaTsNode(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Returns extra volume mount args to overlay the local dist/ into the container
|
|
34
|
+
* when running in dev mode (ts-node), so the container uses local source code.
|
|
35
|
+
* Returns an empty array when not in dev mode.
|
|
36
|
+
*/
|
|
37
|
+
export declare function buildDevMounts(): string[];
|
|
38
|
+
/**
|
|
39
|
+
* Generate a session ID from the current timestamp.
|
|
40
|
+
* Format: YYYYMMDDHHmmss
|
|
41
|
+
*/
|
|
42
|
+
export declare function makeSessionId(): string;
|
|
43
|
+
/** Check if a project-specific image tag exists; fall back to base image tag. */
|
|
44
|
+
export declare function resolveImageTag(projectTag: string, baseTag: string): string;
|
|
45
|
+
export { AGENT_VERSION };
|
|
46
|
+
//# sourceMappingURL=docker-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-utils.d.ts","sourceRoot":"","sources":["../../src/docker/docker-utils.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAI5C,eAAO,MAAM,UAAU,qBAAqB,CAAA;AAE5C,wBAAgB,oBAAoB,IAAI,OAAO,CAO9C;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAOpD;AAED,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAY3E;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,CAKpG;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,aAAa,EAAE,MAAM,GAAG,IAAI,CAMhE;AAED,wBAAgB,WAAW,IAAI,IAAI,CAWlC;AAED,yEAAyE;AACzE,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAE5D;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,IAAI,OAAO,CAG5C;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,MAAM,EAAE,CAYzC;AAED;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAWtC;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAO3E;AAED,OAAO,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Basic Docker utilities
|
|
4
|
+
*
|
|
5
|
+
* Availability checks, image operations, container naming.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.AGENT_VERSION = exports.IMAGE_NAME = void 0;
|
|
9
|
+
exports.checkDockerAvailable = checkDockerAvailable;
|
|
10
|
+
exports.imageExists = imageExists;
|
|
11
|
+
exports.buildImage = buildImage;
|
|
12
|
+
exports.buildContainerName = buildContainerName;
|
|
13
|
+
exports.removeStaleContainer = removeStaleContainer;
|
|
14
|
+
exports.dockerLogin = dockerLogin;
|
|
15
|
+
exports.toPosixRelative = toPosixRelative;
|
|
16
|
+
exports.isRunningViaTsNode = isRunningViaTsNode;
|
|
17
|
+
exports.buildDevMounts = buildDevMounts;
|
|
18
|
+
exports.makeSessionId = makeSessionId;
|
|
19
|
+
exports.resolveImageTag = resolveImageTag;
|
|
20
|
+
const child_process_1 = require("child_process");
|
|
21
|
+
const dockerfile_path_1 = require("./dockerfile-path");
|
|
22
|
+
const constants_1 = require("../constants");
|
|
23
|
+
Object.defineProperty(exports, "AGENT_VERSION", { enumerable: true, get: function () { return constants_1.AGENT_VERSION; } });
|
|
24
|
+
const i18n_1 = require("../i18n");
|
|
25
|
+
const logger_1 = require("../logger");
|
|
26
|
+
exports.IMAGE_NAME = 'ai-support-agent';
|
|
27
|
+
function checkDockerAvailable() {
|
|
28
|
+
try {
|
|
29
|
+
(0, child_process_1.execFileSync)('docker', ['info'], { stdio: 'ignore' });
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function imageExists(version) {
|
|
37
|
+
try {
|
|
38
|
+
(0, child_process_1.execFileSync)('docker', ['image', 'inspect', `${exports.IMAGE_NAME}:${version}`], { stdio: 'ignore' });
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function buildImage(version, customDockerfile) {
|
|
46
|
+
const { dockerfilePath, contextDir } = (0, dockerfile_path_1.resolveDockerfile)(customDockerfile);
|
|
47
|
+
logger_1.logger.info((0, i18n_1.t)('docker.building'));
|
|
48
|
+
if (customDockerfile) {
|
|
49
|
+
logger_1.logger.info((0, i18n_1.t)('docker.usingCustomDockerfile', { path: dockerfilePath }));
|
|
50
|
+
}
|
|
51
|
+
(0, child_process_1.execFileSync)('docker', ['build', '-t', `${exports.IMAGE_NAME}:${version}`, '--pull=false', '--build-arg', `AGENT_VERSION=${version}`, '-f', dockerfilePath, contextDir], { stdio: 'inherit' });
|
|
52
|
+
logger_1.logger.success((0, i18n_1.t)('docker.buildComplete'));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Build a deterministic container name for a project.
|
|
56
|
+
* Format: ai-{tenantCode}-{projectCode}-{agentId}
|
|
57
|
+
* All components are lowercased and non-alphanumeric chars (except hyphens) are replaced with hyphens.
|
|
58
|
+
*/
|
|
59
|
+
function buildContainerName(tenantCode, projectCode, agentId) {
|
|
60
|
+
const sanitize = (s) => s.toLowerCase().replace(/[^a-z0-9-]/g, '-');
|
|
61
|
+
const parts = ['ai', sanitize(tenantCode), sanitize(projectCode)];
|
|
62
|
+
if (agentId)
|
|
63
|
+
parts.push(sanitize(agentId));
|
|
64
|
+
return parts.join('-');
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Remove a stale container with the given name if it exists.
|
|
68
|
+
* This handles the case where a previous run crashed and left a container behind,
|
|
69
|
+
* which would prevent `docker run --name` from succeeding.
|
|
70
|
+
*/
|
|
71
|
+
function removeStaleContainer(containerName) {
|
|
72
|
+
try {
|
|
73
|
+
(0, child_process_1.execFileSync)('docker', ['rm', '-f', containerName], { stdio: 'ignore' });
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Container does not exist or docker rm failed — ignore
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function dockerLogin() {
|
|
80
|
+
logger_1.logger.info((0, i18n_1.t)('docker.loginStep1'));
|
|
81
|
+
console.log('');
|
|
82
|
+
console.log(' claude setup-token');
|
|
83
|
+
console.log('');
|
|
84
|
+
logger_1.logger.info((0, i18n_1.t)('docker.loginStep2'));
|
|
85
|
+
console.log('');
|
|
86
|
+
console.log(' export CLAUDE_CODE_OAUTH_TOKEN=<token>');
|
|
87
|
+
console.log(' ai-support-agent start');
|
|
88
|
+
console.log('');
|
|
89
|
+
logger_1.logger.info((0, i18n_1.t)('docker.loginStep3'));
|
|
90
|
+
}
|
|
91
|
+
/** Convert a path.relative() result to POSIX format for container use */
|
|
92
|
+
function toPosixRelative(relativePath) {
|
|
93
|
+
return relativePath.split(require('path').sep).join('/');
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Returns true when running via ts-node (i.e. `npm run dev`).
|
|
97
|
+
* In this case, local dist/ should be mounted into containers instead of
|
|
98
|
+
* relying on the npm-installed package inside the image.
|
|
99
|
+
*/
|
|
100
|
+
function isRunningViaTsNode() {
|
|
101
|
+
const sym = Symbol.for('ts-node.register.instance');
|
|
102
|
+
return !!process[sym];
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Returns extra volume mount args to overlay the local dist/ into the container
|
|
106
|
+
* when running in dev mode (ts-node), so the container uses local source code.
|
|
107
|
+
* Returns an empty array when not in dev mode.
|
|
108
|
+
*/
|
|
109
|
+
function buildDevMounts() {
|
|
110
|
+
if (!isRunningViaTsNode())
|
|
111
|
+
return [];
|
|
112
|
+
// __dirname is agent/src/docker — walk up two levels to get agent/
|
|
113
|
+
const path = require('path');
|
|
114
|
+
const agentRoot = path.resolve(__dirname, '..', '..');
|
|
115
|
+
const distDir = path.join(agentRoot, 'dist');
|
|
116
|
+
const localesDir = path.join(agentRoot, 'src', 'locales');
|
|
117
|
+
const containerBase = '/usr/local/lib/node_modules/@ai-support-agent/cli';
|
|
118
|
+
return [
|
|
119
|
+
'-v', `${distDir}:${containerBase}/dist:ro`,
|
|
120
|
+
'-v', `${localesDir}:${containerBase}/dist/locales:ro`,
|
|
121
|
+
];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Generate a session ID from the current timestamp.
|
|
125
|
+
* Format: YYYYMMDDHHmmss
|
|
126
|
+
*/
|
|
127
|
+
function makeSessionId() {
|
|
128
|
+
const d = new Date();
|
|
129
|
+
const pad = (n, len = 2) => String(n).padStart(len, '0');
|
|
130
|
+
return (String(d.getFullYear()) +
|
|
131
|
+
pad(d.getMonth() + 1) +
|
|
132
|
+
pad(d.getDate()) +
|
|
133
|
+
pad(d.getHours()) +
|
|
134
|
+
pad(d.getMinutes()) +
|
|
135
|
+
pad(d.getSeconds()));
|
|
136
|
+
}
|
|
137
|
+
/** Check if a project-specific image tag exists; fall back to base image tag. */
|
|
138
|
+
function resolveImageTag(projectTag, baseTag) {
|
|
139
|
+
try {
|
|
140
|
+
(0, child_process_1.execFileSync)('docker', ['image', 'inspect', projectTag], { stdio: 'ignore' });
|
|
141
|
+
return projectTag;
|
|
142
|
+
}
|
|
143
|
+
catch /* istanbul ignore next */ {
|
|
144
|
+
return baseTag;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=docker-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docker-utils.js","sourceRoot":"","sources":["../../src/docker/docker-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-project Dockerfile generation
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Generate a per-project Dockerfile that extends the base agent image.
|
|
6
|
+
*/
|
|
7
|
+
export declare function generateProjectDockerfile(baseVersion: string, aptPackages: string[], npmPackages: string[], commands?: string[], timezone?: string): string;
|
|
8
|
+
/**
|
|
9
|
+
* Returns the minimal environment variables needed for docker build.
|
|
10
|
+
* Excludes sensitive variables (API keys, tokens) that should not be available during build.
|
|
11
|
+
*/
|
|
12
|
+
export declare function buildDockerEnv(): NodeJS.ProcessEnv;
|
|
13
|
+
//# sourceMappingURL=dockerfile-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dockerfile-generator.d.ts","sourceRoot":"","sources":["../../src/docker/dockerfile-generator.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EAAE,EACrB,WAAW,EAAE,MAAM,EAAE,EACrB,QAAQ,GAAE,MAAM,EAAO,EACvB,QAAQ,CAAC,EAAE,MAAM,GAChB,MAAM,CA4BR;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAAC,UAAU,CAUlD"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-project Dockerfile generation
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateProjectDockerfile = generateProjectDockerfile;
|
|
7
|
+
exports.buildDockerEnv = buildDockerEnv;
|
|
8
|
+
const docker_utils_1 = require("./docker-utils");
|
|
9
|
+
const docker_security_1 = require("./docker-security");
|
|
10
|
+
/**
|
|
11
|
+
* Generate a per-project Dockerfile that extends the base agent image.
|
|
12
|
+
*/
|
|
13
|
+
function generateProjectDockerfile(baseVersion, aptPackages, npmPackages, commands = [], timezone) {
|
|
14
|
+
(0, docker_security_1.validatePackageNames)(aptPackages, 'apt');
|
|
15
|
+
(0, docker_security_1.validatePackageNames)(npmPackages, 'npm');
|
|
16
|
+
const lines = [`FROM ${docker_utils_1.IMAGE_NAME}:${baseVersion}`];
|
|
17
|
+
if (timezone) {
|
|
18
|
+
// Override the TZ env var set by docker run, allowing per-project custom timezone
|
|
19
|
+
lines.push(`ENV TZ=${timezone}`);
|
|
20
|
+
}
|
|
21
|
+
if (aptPackages.length > 0) {
|
|
22
|
+
lines.push(`RUN apt-get update && apt-get install -y --no-install-recommends \\`, ` ${aptPackages.join(' \\\n ')} \\`, ` && rm -rf /var/lib/apt/lists/*`);
|
|
23
|
+
}
|
|
24
|
+
if (npmPackages.length > 0) {
|
|
25
|
+
lines.push(`RUN npm install -g ${npmPackages.join(' ')} && npm cache clean --force`);
|
|
26
|
+
}
|
|
27
|
+
for (const cmd of commands) {
|
|
28
|
+
if (/[\n\r|`;$()]/.test(cmd)) {
|
|
29
|
+
throw new Error(`Invalid command (contains forbidden character): "${cmd.substring(0, 50)}"`);
|
|
30
|
+
}
|
|
31
|
+
lines.push(`RUN ${cmd}`);
|
|
32
|
+
}
|
|
33
|
+
return lines.join('\n') + '\n';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Returns the minimal environment variables needed for docker build.
|
|
37
|
+
* Excludes sensitive variables (API keys, tokens) that should not be available during build.
|
|
38
|
+
*/
|
|
39
|
+
function buildDockerEnv() {
|
|
40
|
+
const ALLOWED_KEYS = ['PATH', 'HOME', 'USER', 'TMPDIR', 'TMP', 'TEMP', 'LANG', 'LC_ALL'];
|
|
41
|
+
const env = {};
|
|
42
|
+
for (const key of ALLOWED_KEYS) {
|
|
43
|
+
if (process.env[key] !== undefined) {
|
|
44
|
+
env[key] = process.env[key];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
env['BUILDKIT_PROGRESS'] = 'plain';
|
|
48
|
+
return env;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=dockerfile-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dockerfile-generator.js","sourceRoot":"","sources":["../../src/docker/dockerfile-generator.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAQH,8DAkCC;AAMD,wCAUC;AAxDD,iDAA2C;AAC3C,uDAAwD;AAExD;;GAEG;AACH,SAAgB,yBAAyB,CACvC,WAAmB,EACnB,WAAqB,EACrB,WAAqB,EACrB,WAAqB,EAAE,EACvB,QAAiB;IAEjB,IAAA,sCAAoB,EAAC,WAAW,EAAE,KAAK,CAAC,CAAA;IACxC,IAAA,sCAAoB,EAAC,WAAW,EAAE,KAAK,CAAC,CAAA;IAExC,MAAM,KAAK,GAAG,CAAC,QAAQ,yBAAU,IAAI,WAAW,EAAE,CAAC,CAAA;IACnD,IAAI,QAAQ,EAAE,CAAC;QACb,kFAAkF;QAClF,KAAK,CAAC,IAAI,CAAC,UAAU,QAAQ,EAAE,CAAC,CAAA;IAClC,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CACR,qEAAqE,EACrE,OAAO,WAAW,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,EACzC,oCAAoC,CACrC,CAAA;IACH,CAAC;IACD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CACR,sBAAsB,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,6BAA6B,CACzE,CAAA;IACH,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,IAAI,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CAAC,oDAAoD,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAA;QAC9F,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC,CAAA;IAC1B,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,SAAgB,cAAc;IAC5B,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;IACxF,MAAM,GAAG,GAAsB,EAAE,CAAA;IACjC,KAAK,MAAM,GAAG,IAAI,YAAY,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YACnC,GAAG,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC7B,CAAC;IACH,CAAC;IACD,GAAG,CAAC,mBAAmB,CAAC,GAAG,OAAO,CAAA;IAClC,OAAO,GAAG,CAAA;AACZ,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dockerfile synchronization to config directory
|
|
3
|
+
*
|
|
4
|
+
* Copies the bundled Dockerfile to ~/.ai-support-agent/ on first run
|
|
5
|
+
* so users can customise it without modifying the package.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Copy the bundled Dockerfile (and entrypoint.sh) to the config directory
|
|
9
|
+
* on first run so users can customise it.
|
|
10
|
+
* Does NOT overwrite an existing file — user edits are preserved.
|
|
11
|
+
*/
|
|
12
|
+
export declare function syncDockerfileToConfigDir(): void;
|
|
13
|
+
//# sourceMappingURL=dockerfile-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dockerfile-sync.d.ts","sourceRoot":"","sources":["../../src/docker/dockerfile-sync.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH;;;;GAIG;AACH,wBAAgB,yBAAyB,IAAI,IAAI,CAuBhD"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Dockerfile synchronization to config directory
|
|
4
|
+
*
|
|
5
|
+
* Copies the bundled Dockerfile to ~/.ai-support-agent/ on first run
|
|
6
|
+
* so users can customise it without modifying the package.
|
|
7
|
+
*/
|
|
8
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
9
|
+
if (k2 === undefined) k2 = k;
|
|
10
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
11
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
+
}
|
|
14
|
+
Object.defineProperty(o, k2, desc);
|
|
15
|
+
}) : (function(o, m, k, k2) {
|
|
16
|
+
if (k2 === undefined) k2 = k;
|
|
17
|
+
o[k2] = m[k];
|
|
18
|
+
}));
|
|
19
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
+
}) : function(o, v) {
|
|
22
|
+
o["default"] = v;
|
|
23
|
+
});
|
|
24
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
+
var ownKeys = function(o) {
|
|
26
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
+
var ar = [];
|
|
28
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
+
return ar;
|
|
30
|
+
};
|
|
31
|
+
return ownKeys(o);
|
|
32
|
+
};
|
|
33
|
+
return function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
+
__setModuleDefault(result, mod);
|
|
38
|
+
return result;
|
|
39
|
+
};
|
|
40
|
+
})();
|
|
41
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
+
exports.syncDockerfileToConfigDir = syncDockerfileToConfigDir;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const config_manager_1 = require("../config-manager");
|
|
46
|
+
const dockerfile_path_1 = require("./dockerfile-path");
|
|
47
|
+
const i18n_1 = require("../i18n");
|
|
48
|
+
const logger_1 = require("../logger");
|
|
49
|
+
/**
|
|
50
|
+
* Copy the bundled Dockerfile (and entrypoint.sh) to the config directory
|
|
51
|
+
* on first run so users can customise it.
|
|
52
|
+
* Does NOT overwrite an existing file — user edits are preserved.
|
|
53
|
+
*/
|
|
54
|
+
function syncDockerfileToConfigDir() {
|
|
55
|
+
const configDir = (0, config_manager_1.getConfigDir)();
|
|
56
|
+
const destDockerfile = path.join(configDir, 'Dockerfile');
|
|
57
|
+
if (fs.existsSync(destDockerfile))
|
|
58
|
+
return; // preserve existing file
|
|
59
|
+
try {
|
|
60
|
+
const srcDockerfile = (0, dockerfile_path_1.getDockerfilePath)();
|
|
61
|
+
fs.mkdirSync(configDir, { recursive: true, mode: 0o700 });
|
|
62
|
+
fs.copyFileSync(srcDockerfile, destDockerfile);
|
|
63
|
+
// Also copy entrypoint.sh which the bundled Dockerfile references via COPY
|
|
64
|
+
const srcEntrypoint = path.join((0, dockerfile_path_1.getDockerContextDir)(), 'docker', 'entrypoint.sh');
|
|
65
|
+
const destEntrypoint = path.join(configDir, 'docker', 'entrypoint.sh');
|
|
66
|
+
if (fs.existsSync(srcEntrypoint)) {
|
|
67
|
+
fs.mkdirSync(path.dirname(destEntrypoint), { recursive: true });
|
|
68
|
+
fs.copyFileSync(srcEntrypoint, destEntrypoint);
|
|
69
|
+
}
|
|
70
|
+
logger_1.logger.info((0, i18n_1.t)('docker.dockerfileSynced', { path: destDockerfile }));
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
logger_1.logger.warn((0, i18n_1.t)('docker.dockerfileSyncFailed', { message: err instanceof Error ? err.message : String(err) }));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=dockerfile-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dockerfile-sync.js","sourceRoot":"","sources":["../../src/docker/dockerfile-sync.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAeH,8DAuBC;AApCD,uCAAwB;AACxB,2CAA4B;AAE5B,sDAAgD;AAChD,uDAA0E;AAC1E,kCAA2B;AAC3B,sCAAkC;AAElC;;;;GAIG;AACH,SAAgB,yBAAyB;IACvC,MAAM,SAAS,GAAG,IAAA,6BAAY,GAAE,CAAA;IAChC,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAA;IAEzD,IAAI,EAAE,CAAC,UAAU,CAAC,cAAc,CAAC;QAAE,OAAM,CAAC,yBAAyB;IAEnE,IAAI,CAAC;QACH,MAAM,aAAa,GAAG,IAAA,mCAAiB,GAAE,CAAA;QACzC,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACzD,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,cAAc,CAAC,CAAA;QAE9C,2EAA2E;QAC3E,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,IAAA,qCAAmB,GAAE,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAA;QACjF,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAA;QACtE,IAAI,EAAE,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;YACjC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAC/D,EAAE,CAAC,YAAY,CAAC,aAAa,EAAE,cAAc,CAAC,CAAA;QAChD,CAAC;QAED,eAAM,CAAC,IAAI,CAAC,IAAA,QAAC,EAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC,CAAA;IACrE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,IAAI,CAAC,IAAA,QAAC,EAAC,6BAA6B,EAAE,EAAE,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9G,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-project config directory management
|
|
3
|
+
*
|
|
4
|
+
* Handles migration from legacy layout and path resolution.
|
|
5
|
+
*/
|
|
6
|
+
import type { ProjectRegistration } from '../types';
|
|
7
|
+
/**
|
|
8
|
+
* Get the host-side per-project config directory.
|
|
9
|
+
* Located at: ~/.ai-support-agent/projects/{tenantCode}/{projectCode}/.ai-support-agent/
|
|
10
|
+
*/
|
|
11
|
+
export declare function getProjectConfigHostDir(project: ProjectRegistration): string;
|
|
12
|
+
/**
|
|
13
|
+
* Migrate per-project config directory from the legacy layout to the current layout.
|
|
14
|
+
*
|
|
15
|
+
* Legacy: ~/.ai-support-agent/projects/{projectCode}/
|
|
16
|
+
* Current: ~/.ai-support-agent/projects/{tenantCode}/{projectCode}/
|
|
17
|
+
*
|
|
18
|
+
* Older agent versions stored project data without a tenantCode path segment.
|
|
19
|
+
* This function moves the directory once so the current code finds it in the right place.
|
|
20
|
+
*/
|
|
21
|
+
export declare function migrateProjectConfigDir(project: ProjectRegistration): void;
|
|
22
|
+
//# sourceMappingURL=project-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-config.d.ts","sourceRoot":"","sources":["../../src/docker/project-config.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEnD;;;GAGG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAE5E;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAe1E"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-project config directory management
|
|
4
|
+
*
|
|
5
|
+
* Handles migration from legacy layout and path resolution.
|
|
6
|
+
*/
|
|
7
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
|
+
if (k2 === undefined) k2 = k;
|
|
9
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
10
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
11
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
12
|
+
}
|
|
13
|
+
Object.defineProperty(o, k2, desc);
|
|
14
|
+
}) : (function(o, m, k, k2) {
|
|
15
|
+
if (k2 === undefined) k2 = k;
|
|
16
|
+
o[k2] = m[k];
|
|
17
|
+
}));
|
|
18
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
19
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
20
|
+
}) : function(o, v) {
|
|
21
|
+
o["default"] = v;
|
|
22
|
+
});
|
|
23
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
24
|
+
var ownKeys = function(o) {
|
|
25
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
26
|
+
var ar = [];
|
|
27
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
28
|
+
return ar;
|
|
29
|
+
};
|
|
30
|
+
return ownKeys(o);
|
|
31
|
+
};
|
|
32
|
+
return function (mod) {
|
|
33
|
+
if (mod && mod.__esModule) return mod;
|
|
34
|
+
var result = {};
|
|
35
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
36
|
+
__setModuleDefault(result, mod);
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
39
|
+
})();
|
|
40
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
41
|
+
exports.getProjectConfigHostDir = getProjectConfigHostDir;
|
|
42
|
+
exports.migrateProjectConfigDir = migrateProjectConfigDir;
|
|
43
|
+
const fs = __importStar(require("fs"));
|
|
44
|
+
const path = __importStar(require("path"));
|
|
45
|
+
const config_manager_1 = require("../config-manager");
|
|
46
|
+
const logger_1 = require("../logger");
|
|
47
|
+
/**
|
|
48
|
+
* Get the host-side per-project config directory.
|
|
49
|
+
* Located at: ~/.ai-support-agent/projects/{tenantCode}/{projectCode}/.ai-support-agent/
|
|
50
|
+
*/
|
|
51
|
+
function getProjectConfigHostDir(project) {
|
|
52
|
+
return path.join((0, config_manager_1.getConfigDir)(), 'projects', project.tenantCode, project.projectCode, '.ai-support-agent');
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Migrate per-project config directory from the legacy layout to the current layout.
|
|
56
|
+
*
|
|
57
|
+
* Legacy: ~/.ai-support-agent/projects/{projectCode}/
|
|
58
|
+
* Current: ~/.ai-support-agent/projects/{tenantCode}/{projectCode}/
|
|
59
|
+
*
|
|
60
|
+
* Older agent versions stored project data without a tenantCode path segment.
|
|
61
|
+
* This function moves the directory once so the current code finds it in the right place.
|
|
62
|
+
*/
|
|
63
|
+
function migrateProjectConfigDir(project) {
|
|
64
|
+
const configBase = path.join((0, config_manager_1.getConfigDir)(), 'projects');
|
|
65
|
+
const legacyDir = path.join(configBase, project.projectCode);
|
|
66
|
+
const newDir = path.join(configBase, project.tenantCode, project.projectCode);
|
|
67
|
+
if (!fs.existsSync(legacyDir))
|
|
68
|
+
return; // nothing to migrate
|
|
69
|
+
if (fs.existsSync(newDir))
|
|
70
|
+
return; // already migrated
|
|
71
|
+
try {
|
|
72
|
+
fs.mkdirSync(path.join(configBase, project.tenantCode), { recursive: true, mode: 0o700 });
|
|
73
|
+
fs.renameSync(legacyDir, newDir);
|
|
74
|
+
logger_1.logger.info(`[docker] Migrated project config dir: ${legacyDir} → ${newDir}`);
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
logger_1.logger.warn(`[docker] Failed to migrate project config dir for ${project.projectCode}: ${err instanceof Error ? err.message : String(err)}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=project-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-config.js","sourceRoot":"","sources":["../../src/docker/project-config.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaH,0DAEC;AAWD,0DAeC;AAvCD,uCAAwB;AACxB,2CAA4B;AAE5B,sDAAgD;AAChD,sCAAkC;AAGlC;;;GAGG;AACH,SAAgB,uBAAuB,CAAC,OAA4B;IAClE,OAAO,IAAI,CAAC,IAAI,CAAC,IAAA,6BAAY,GAAE,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,WAAW,EAAE,mBAAmB,CAAC,CAAA;AAC5G,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,uBAAuB,CAAC,OAA4B;IAClE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAA,6BAAY,GAAE,EAAE,UAAU,CAAC,CAAA;IACxD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAC5D,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,WAAW,CAAC,CAAA;IAE7E,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAM,CAAO,qBAAqB;IACjE,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAM,CAAY,mBAAmB;IAEhE,IAAI,CAAC;QACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACzF,EAAE,CAAC,UAAU,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAChC,eAAM,CAAC,IAAI,CAAC,yCAAyC,SAAS,MAAM,MAAM,EAAE,CAAC,CAAA;IAC/E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,eAAM,CAAC,IAAI,CAAC,qDAAqD,OAAO,CAAC,WAAW,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC9I,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-project Docker image builder
|
|
3
|
+
*
|
|
4
|
+
* Builds a project-specific Docker image and streams build logs to the API.
|
|
5
|
+
*/
|
|
6
|
+
import { ApiClient } from '../api-client';
|
|
7
|
+
/**
|
|
8
|
+
* Build a per-project Docker image using the given Dockerfile.
|
|
9
|
+
* Streams stdout/stderr to both the host terminal and the API (for real-time log viewing).
|
|
10
|
+
*/
|
|
11
|
+
export declare function buildProjectImage(tenantCode: string, projectCode: string, baseVersion: string, dockerfilePath: string, apiClient?: ApiClient, agentId?: string): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=project-image-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-image-builder.d.ts","sourceRoot":"","sources":["../../src/docker/project-image-builder.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAOzC;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,EACnB,cAAc,EAAE,MAAM,EACtB,SAAS,CAAC,EAAE,SAAS,EACrB,OAAO,CAAC,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAsEf"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Per-project Docker image builder
|
|
4
|
+
*
|
|
5
|
+
* Builds a project-specific Docker image and streams build logs to the API.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.buildProjectImage = buildProjectImage;
|
|
9
|
+
const child_process_1 = require("child_process");
|
|
10
|
+
const dockerfile_path_1 = require("./dockerfile-path");
|
|
11
|
+
const dockerfile_path_2 = require("./dockerfile-path");
|
|
12
|
+
const logger_1 = require("../logger");
|
|
13
|
+
const dockerfile_generator_1 = require("./dockerfile-generator");
|
|
14
|
+
const docker_utils_1 = require("./docker-utils");
|
|
15
|
+
/** Maximum total log size kept in memory per session (2 MB). Older content is discarded. */
|
|
16
|
+
const MAX_SESSION_LOG_BYTES = 2 * 1024 * 1024;
|
|
17
|
+
/**
|
|
18
|
+
* Build a per-project Docker image using the given Dockerfile.
|
|
19
|
+
* Streams stdout/stderr to both the host terminal and the API (for real-time log viewing).
|
|
20
|
+
*/
|
|
21
|
+
async function buildProjectImage(tenantCode, projectCode, baseVersion, dockerfilePath, apiClient, agentId) {
|
|
22
|
+
const imageTag = (0, dockerfile_path_2.getProjectImageTag)(tenantCode, projectCode, baseVersion);
|
|
23
|
+
const contextDir = (0, dockerfile_path_1.getDockerContextDir)();
|
|
24
|
+
const projectKey = `${tenantCode}#${projectCode}`;
|
|
25
|
+
const color = (0, logger_1.getProjectColor)(projectKey);
|
|
26
|
+
const reset = '\x1b[0m';
|
|
27
|
+
const prefix = `${color}[${projectKey}]${reset} `;
|
|
28
|
+
logger_1.logger.info(`[docker] Building project image: ${imageTag}`);
|
|
29
|
+
const sessionId = (0, docker_utils_1.makeSessionId)();
|
|
30
|
+
let seq = 0;
|
|
31
|
+
let fullLog = '';
|
|
32
|
+
let logTruncated = false;
|
|
33
|
+
let buf = '';
|
|
34
|
+
const flush = async () => {
|
|
35
|
+
if (!buf)
|
|
36
|
+
return;
|
|
37
|
+
const text = buf;
|
|
38
|
+
buf = '';
|
|
39
|
+
if (!logTruncated) {
|
|
40
|
+
if (fullLog.length + text.length <= MAX_SESSION_LOG_BYTES) {
|
|
41
|
+
fullLog += text;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
const remaining = MAX_SESSION_LOG_BYTES - fullLog.length;
|
|
45
|
+
fullLog += remaining > 0 ? text.slice(0, remaining) : '';
|
|
46
|
+
logTruncated = true;
|
|
47
|
+
logger_1.logger.warn('[docker] Build log exceeded 2 MB limit; remaining output will not be saved to S3');
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (apiClient) {
|
|
51
|
+
await apiClient.submitLogChunk({ agentId: agentId ?? '', projectCode, logType: 'docker-build', sessionId, seq: ++seq, text })
|
|
52
|
+
.catch((e) => logger_1.logger.warn(`[docker] Failed to send log chunk: ${e}`));
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
let buildError;
|
|
56
|
+
await new Promise((resolve, reject) => {
|
|
57
|
+
const proc = (0, child_process_1.spawn)('docker', [
|
|
58
|
+
'build', '-t', imageTag, '--pull=false', '--progress=plain',
|
|
59
|
+
'--build-arg', `AGENT_VERSION=${baseVersion}`,
|
|
60
|
+
'-f', dockerfilePath, contextDir,
|
|
61
|
+
], { stdio: ['ignore', 'pipe', 'pipe'], env: (0, dockerfile_generator_1.buildDockerEnv)() });
|
|
62
|
+
const writePrefixed = (0, logger_1.makeLinePrefixer)(prefix, (s) => process.stdout.write(s));
|
|
63
|
+
const onData = (d) => {
|
|
64
|
+
const text = d.toString();
|
|
65
|
+
writePrefixed(text);
|
|
66
|
+
buf += text;
|
|
67
|
+
if (buf.length > 4096) {
|
|
68
|
+
void flush();
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
proc.stdout?.on('data', onData);
|
|
72
|
+
proc.stderr?.on('data', onData);
|
|
73
|
+
proc.on('error', (err) => reject(err));
|
|
74
|
+
proc.on('close', (code) => {
|
|
75
|
+
if (code === 0)
|
|
76
|
+
resolve();
|
|
77
|
+
else
|
|
78
|
+
reject(new Error(`docker build exited with code ${code}`));
|
|
79
|
+
});
|
|
80
|
+
}).catch((e) => { buildError = e instanceof Error ? e : new Error(String(e)); });
|
|
81
|
+
await flush();
|
|
82
|
+
if (apiClient && fullLog) {
|
|
83
|
+
await apiClient.saveSessionLog({ agentId: agentId ?? '', projectCode, logType: 'docker-build', sessionId, content: fullLog })
|
|
84
|
+
.catch((e) => logger_1.logger.warn(`[docker] Failed to upload build log to S3: ${e}`));
|
|
85
|
+
}
|
|
86
|
+
if (buildError)
|
|
87
|
+
throw buildError;
|
|
88
|
+
logger_1.logger.success(`[docker] Project image built: ${imageTag}`);
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=project-image-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project-image-builder.js","sourceRoot":"","sources":["../../src/docker/project-image-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Docker update and restart handler
|
|
3
|
+
*
|
|
4
|
+
* Called when a container exits with DOCKER_UPDATE_EXIT_CODE.
|
|
5
|
+
* Installs the new version on the host and re-execs the process.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Called on the host after a container exits with DOCKER_UPDATE_EXIT_CODE.
|
|
9
|
+
* Reads the new version from a project-specific config dir (written by the container),
|
|
10
|
+
* installs it on the host with npm, then re-execs the process so ensureImage()
|
|
11
|
+
* picks up the newly installed version and rebuilds the Docker image.
|
|
12
|
+
*/
|
|
13
|
+
export declare function installUpdateAndRestart(projectConfigDir?: string): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=update-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-handler.d.ts","sourceRoot":"","sources":["../../src/docker/update-handler.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAWH;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAAC,gBAAgB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqCtF"}
|