dhti-cli 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/commands/conch.d.ts +2 -0
- package/dist/commands/conch.js +69 -5
- package/dist/commands/docker.d.ts +2 -0
- package/dist/commands/docker.js +34 -1
- package/dist/commands/elixir.d.ts +2 -0
- package/dist/commands/elixir.js +27 -1
- package/oclif.manifest.json +52 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
|
|
14
14
|
- 🚀 *Dhanvantari rose out of the water with his four hands, holding a pot full of elixirs!*
|
|
15
15
|
|
|
16
|
-
### TL; DR: 🏥 DHTI enables rapid prototyping, sharing, and testing of GenAI healthcare applications within an EHR, facilitating the seamless transition of your experiments to practice!
|
|
16
|
+
### TL; DR: 🏥 DHTI enables rapid prototyping, sharing, and testing of GenAI healthcare applications within an EHR, facilitating the seamless transition of your experiments to practice! Moreover, DHTI comes with batteries included! It has the [skills](/.github/skills/) to generate GenAI components from simple problem oriented [prompts](/prompts/e2e-sample.md).
|
|
17
17
|
👉 [Try it out today!](#try-it-out) and give us a star ⭐️ if you like it!
|
|
18
18
|
|
|
19
19
|
### About
|
|
@@ -68,6 +68,8 @@ The essence of DHTI is *modularity* with an emphasis on *configuration!* It is n
|
|
|
68
68
|
* **Easy to use**: Can be installed in a few minutes.
|
|
69
69
|
* **Developer friendly**: Copy working files to running containers for testing.
|
|
70
70
|
* **Dry-run mode**: Preview changes before execution with the `--dry-run` flag.
|
|
71
|
+
* **Local directory installation**: Install elixirs and conches from local directories using the `-l` flag.
|
|
72
|
+
* **Monorepo support**: Install elixirs and conches from subdirectories in GitHub repositories with the `-s` flag.
|
|
71
73
|
* **Dependency Injection**: Dependency injection for models and hyperparameters for configuring elixirs.
|
|
72
74
|
* **Generate synthetic data**: [DHTI supports generating synthetic data for testing, using synthea.](/notes/SYNTHEA.md)
|
|
73
75
|
* **CQL support**: [CQL for clinical decision support](https://nuchange.ca/2025/06/v-llm-in-the-loop-cql-execution-with-unstructured-data-and-fhir-terminology-support.html).
|
|
@@ -80,6 +82,8 @@ The essence of DHTI is *modularity* with an emphasis on *configuration!* It is n
|
|
|
80
82
|
* **LLM**: Ollama for self-hosting LLM models.
|
|
81
83
|
|
|
82
84
|
## ✨ New
|
|
85
|
+
* **Local directory installation**: Install elixirs and conches from local directories using the new `-l` flag, enabling seamless integration with locally generated projects.
|
|
86
|
+
* **start-dhti skill**: New AI agent skill that orchestrates complete DHTI application development - from generating elixirs and conches to starting a fully functional DHTI server.
|
|
83
87
|
* **MCPX integration**: DHTI now includes an [MCP integrator](https://docs.lunar.dev/mcpx/) that allows other MCP servers to be "installed" and exposed seamlessly to DHTI through the MCPX gateway.
|
|
84
88
|
* **DOCKTOR module**: A new module, [DOCKTOR](/notes/DOCKTOR.md), support traditional machine learning model packaged as Docker containers, to be used as MCP tools, enabling the deployment of inference pipelines as agent-invokable tools. (in beta)
|
|
85
89
|
* **MCP aware agent**: [dhti-elixir-template](https://github.com/dermatologist/dhti-elixir-template) used in the examples now includes an [MCP aware agent](https://github.com/dermatologist/dhti-elixir-template/blob/feature/agent-2/src/dhti_elixir_template/chain.py) that can autodiscover and invoke tools from the MCPX gateway. Install it using `npx dhti-cli elixir install -g https://github.com/dermatologist/dhti-elixir-template.git -n dhti-elixir-template -b feature/agent2`.
|
|
@@ -148,11 +152,11 @@ Tools to fine-tune language models for the stack are on our roadmap. We encourag
|
|
|
148
152
|
|
|
149
153
|
* `npx dhti-cli compose add -m openmrs -m langserve` to add OpenMRS and Langserve elixirs to your docker-compose.yml at ~/dhti. Other available modules: `ollama, langfuse, cqlFhir, redis, neo4j and mcpFhir`. You can read the newly created docker-compose by: `npx dhti-cli compose read`
|
|
150
154
|
|
|
151
|
-
* `npx dhti-cli elixir install -g https://github.com/dermatologist/dhti-elixir-template.git -n dhti-elixir-template` to install a sample elixir from github. *(Optional)* You may configure the LLM and hyperparameters in `~/dhti/elixir/app/bootstrap.py`. You can install multiple elixirs.
|
|
155
|
+
* `npx dhti-cli elixir install -g https://github.com/dermatologist/dhti-elixir-template.git -n dhti-elixir-template` to install a sample elixir from github. *(Optional)* You may configure the LLM and hyperparameters in `~/dhti/elixir/app/bootstrap.py`. You can install multiple elixirs. Alternatively, use `-l <local-directory>` to install from a local directory.
|
|
152
156
|
|
|
153
157
|
* `npx dhti-cli docker -n yourdockerhandle/genai-test:1.0 -t elixir` to build a docker image for the elixir.
|
|
154
158
|
|
|
155
|
-
* `npx dhti-cli conch install -g https://github.com/dermatologist/openmrs-esm-dhti-template.git -n openmrs-esm-dhti-template` to install a simple OpenMRS ESM module (conch)from github. You can install multiple conches.
|
|
159
|
+
* `npx dhti-cli conch install -g https://github.com/dermatologist/openmrs-esm-dhti-template.git -n openmrs-esm-dhti-template` to install a simple OpenMRS ESM module (conch)from github. You can install multiple conches. Alternatively, use `-l <local-directory>` to install from a local directory.
|
|
156
160
|
|
|
157
161
|
* `npx dhti-cli docker -n yourdockerhandle/conch-test:1.0 -t conch` to build a docker image for the conches.
|
|
158
162
|
|
package/dist/commands/conch.d.ts
CHANGED
|
@@ -12,8 +12,10 @@ export default class Conch extends Command {
|
|
|
12
12
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
git: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
14
|
image: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
local: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
repoVersion: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
subdirectory: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
19
|
workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
20
|
};
|
|
19
21
|
run(): Promise<void>;
|
package/dist/commands/conch.js
CHANGED
|
@@ -5,6 +5,10 @@ import fs from 'node:fs';
|
|
|
5
5
|
import os from 'node:os';
|
|
6
6
|
import path from 'node:path';
|
|
7
7
|
import { fileURLToPath } from 'node:url';
|
|
8
|
+
// Helper function to escape shell arguments
|
|
9
|
+
function escapeShellArg(arg) {
|
|
10
|
+
return `'${arg.replaceAll("'", "'\\''")}'`;
|
|
11
|
+
}
|
|
8
12
|
export default class Conch extends Command {
|
|
9
13
|
static args = {
|
|
10
14
|
op: Args.string({ description: 'Operation to perform (install, uninstall or dev)' }),
|
|
@@ -29,8 +33,14 @@ export default class Conch extends Command {
|
|
|
29
33
|
default: 'openmrs/openmrs-reference-application-3-frontend:3.0.0-beta.17',
|
|
30
34
|
description: 'Base image to use for the conch',
|
|
31
35
|
}),
|
|
36
|
+
local: Flags.string({ char: 'l', default: 'none', description: 'Local directory to install from' }),
|
|
32
37
|
name: Flags.string({ char: 'n', description: 'Name of the elixir' }),
|
|
33
38
|
repoVersion: Flags.string({ char: 'v', default: '1.0.0', description: 'Version of the conch' }),
|
|
39
|
+
subdirectory: Flags.string({
|
|
40
|
+
char: 's',
|
|
41
|
+
default: 'none',
|
|
42
|
+
description: 'Subdirectory in the repository to install from (for monorepos)',
|
|
43
|
+
}),
|
|
34
44
|
workdir: Flags.string({
|
|
35
45
|
char: 'w',
|
|
36
46
|
default: `${os.homedir()}/dhti`,
|
|
@@ -160,12 +170,42 @@ export default class Conch extends Command {
|
|
|
160
170
|
fs.writeFileSync(`${flags.workdir}/conch/def/routes.registry.json`, JSON.stringify(registry, null, 2));
|
|
161
171
|
};
|
|
162
172
|
if (flags.git !== 'none') {
|
|
163
|
-
|
|
164
|
-
|
|
173
|
+
let cloneCommand;
|
|
174
|
+
let checkoutCommand;
|
|
175
|
+
if (flags.subdirectory === 'none') {
|
|
176
|
+
cloneCommand = `git clone ${escapeShellArg(flags.git)} ${escapeShellArg(`${flags.workdir}/conch/${flags.name}`)}`;
|
|
177
|
+
checkoutCommand = `cd ${escapeShellArg(`${flags.workdir}/conch/${flags.name}`)} && git checkout ${escapeShellArg(flags.branch)}`;
|
|
178
|
+
}
|
|
179
|
+
else {
|
|
180
|
+
// Use sparse checkout for subdirectory - broken into steps for readability and security
|
|
181
|
+
const targetDir = `${flags.workdir}/conch/${flags.name}`;
|
|
182
|
+
const escapedDir = escapeShellArg(targetDir);
|
|
183
|
+
const escapedGit = escapeShellArg(flags.git);
|
|
184
|
+
const escapedBranch = escapeShellArg(flags.branch);
|
|
185
|
+
const escapedSubdir = escapeShellArg(flags.subdirectory);
|
|
186
|
+
// Build sparse checkout command with proper escaping
|
|
187
|
+
const initCommand = `mkdir -p ${escapedDir} && cd ${escapedDir} && git init`;
|
|
188
|
+
const remoteCommand = `git remote add origin ${escapedGit}`;
|
|
189
|
+
const sparseCommand = `git config core.sparseCheckout true`;
|
|
190
|
+
// Don't escape the glob pattern itself, only the subdirectory name
|
|
191
|
+
const patternCommand = `echo ${escapedSubdir}/'*' >> .git/info/sparse-checkout`;
|
|
192
|
+
const fetchCommand = `git fetch --depth=1 origin ${escapedBranch}`;
|
|
193
|
+
const checkoutCmd = `git checkout ${escapedBranch}`;
|
|
194
|
+
// Use bash's dotglob to include hidden files, and handle the case when no files exist
|
|
195
|
+
const moveCommand = `bash -c "shopt -s dotglob; if [ -d ${escapedSubdir} ]; then mv ${escapedSubdir}/* . 2>/dev/null || true; fi"`;
|
|
196
|
+
const cleanupCommand = `rm -rf ${escapedSubdir}`;
|
|
197
|
+
cloneCommand = `${initCommand} && ${remoteCommand} && ${sparseCommand} && ${patternCommand} && ${fetchCommand} && ${checkoutCmd} && ${moveCommand} && ${cleanupCommand}`;
|
|
198
|
+
checkoutCommand = `cd ${escapedDir} && echo "Sparse checkout complete"`;
|
|
199
|
+
}
|
|
165
200
|
if (flags['dry-run']) {
|
|
166
201
|
console.log(chalk.yellow('[DRY RUN] Would execute git commands:'));
|
|
167
|
-
|
|
168
|
-
|
|
202
|
+
if (flags.subdirectory === 'none') {
|
|
203
|
+
console.log(chalk.cyan(` ${cloneCommand}`));
|
|
204
|
+
console.log(chalk.cyan(` ${checkoutCommand}`));
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
console.log(chalk.cyan(` Sparse checkout: ${flags.subdirectory} from ${flags.git}`));
|
|
208
|
+
}
|
|
169
209
|
rewrite();
|
|
170
210
|
return;
|
|
171
211
|
}
|
|
@@ -175,7 +215,7 @@ export default class Conch extends Command {
|
|
|
175
215
|
console.error(`exec error: ${error}`);
|
|
176
216
|
return;
|
|
177
217
|
}
|
|
178
|
-
// Checkout the branch
|
|
218
|
+
// Checkout the branch (or confirm sparse checkout)
|
|
179
219
|
exec(checkoutCommand, (error, stdout, stderr) => {
|
|
180
220
|
if (error) {
|
|
181
221
|
console.error(`exec error: ${error}`);
|
|
@@ -200,5 +240,29 @@ export default class Conch extends Command {
|
|
|
200
240
|
rewrite();
|
|
201
241
|
}
|
|
202
242
|
}
|
|
243
|
+
// If flags.local is not none, copy the local directory to the conch directory
|
|
244
|
+
if (flags.local !== 'none' && args.op !== 'dev') {
|
|
245
|
+
const absolutePath = path.isAbsolute(flags.local) ? flags.local : path.resolve(process.cwd(), flags.local);
|
|
246
|
+
// Validate that the path exists and is a directory (skip validation in dry-run mode)
|
|
247
|
+
if (!flags['dry-run']) {
|
|
248
|
+
if (!fs.existsSync(absolutePath)) {
|
|
249
|
+
console.error(chalk.red(`Error: Local directory does not exist: ${absolutePath}`));
|
|
250
|
+
this.exit(1);
|
|
251
|
+
}
|
|
252
|
+
const stats = fs.statSync(absolutePath);
|
|
253
|
+
if (!stats.isDirectory()) {
|
|
254
|
+
console.error(chalk.red(`Error: Path is not a directory: ${absolutePath}`));
|
|
255
|
+
this.exit(1);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
if (flags['dry-run']) {
|
|
259
|
+
console.log(chalk.yellow(`[DRY RUN] Would copy ${absolutePath} to ${flags.workdir}/conch/${flags.name}`));
|
|
260
|
+
rewrite();
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
fs.cpSync(absolutePath, `${flags.workdir}/conch/${flags.name}`, { recursive: true });
|
|
264
|
+
rewrite();
|
|
265
|
+
}
|
|
266
|
+
}
|
|
203
267
|
}
|
|
204
268
|
}
|
|
@@ -10,7 +10,9 @@ export default class Docker extends Command {
|
|
|
10
10
|
down: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
11
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
12
|
file: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
13
|
+
gateway: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
14
|
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
|
+
restart: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
16
|
type: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
17
|
up: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
16
18
|
};
|
package/dist/commands/docker.js
CHANGED
|
@@ -27,7 +27,9 @@ export default class Docker extends Command {
|
|
|
27
27
|
default: `${os.homedir()}/dhti/docker-compose.yml`,
|
|
28
28
|
description: 'Full path to the docker compose file to edit or run.',
|
|
29
29
|
}),
|
|
30
|
+
gateway: Flags.boolean({ char: 'g', default: false, description: 'Restart the gateway container' }),
|
|
30
31
|
name: Flags.string({ char: 'n', description: 'Name of the container to build' }),
|
|
32
|
+
restart: Flags.string({ char: 'r', description: 'Restart a specific container by name' }),
|
|
31
33
|
type: Flags.string({ char: 't', default: 'elixir', description: 'Type of the service (elixir/conch)' }),
|
|
32
34
|
up: Flags.boolean({ char: 'u', default: false, description: 'Run docker-compose up after building' }),
|
|
33
35
|
};
|
|
@@ -67,7 +69,38 @@ export default class Docker extends Command {
|
|
|
67
69
|
});
|
|
68
70
|
return;
|
|
69
71
|
}
|
|
70
|
-
if (
|
|
72
|
+
if (flags.gateway || flags.restart) {
|
|
73
|
+
// Validate that only one restart option is provided
|
|
74
|
+
if (flags.gateway && flags.restart) {
|
|
75
|
+
console.error('Error: Cannot use both --gateway and --restart flags at the same time');
|
|
76
|
+
this.exit(1);
|
|
77
|
+
}
|
|
78
|
+
const containerName = flags.gateway ? 'dhti-gateway-1' : flags.restart;
|
|
79
|
+
// Validate container name to prevent command injection
|
|
80
|
+
if (containerName && !/^[\w-]+$/.test(containerName)) {
|
|
81
|
+
console.error('Error: Invalid container name. Container names can only contain letters, numbers, hyphens, and underscores.');
|
|
82
|
+
this.exit(1);
|
|
83
|
+
}
|
|
84
|
+
const restartCommand = `docker restart ${containerName}`;
|
|
85
|
+
if (flags['dry-run']) {
|
|
86
|
+
console.log(chalk.yellow('[DRY RUN] Would execute:'));
|
|
87
|
+
console.log(chalk.cyan(` ${restartCommand}`));
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
exec(restartCommand, (error, stdout, stderr) => {
|
|
91
|
+
if (error) {
|
|
92
|
+
console.error(`exec error: ${error}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
console.log(`Successfully restarted container: ${containerName}`);
|
|
96
|
+
if (stdout)
|
|
97
|
+
console.log(`stdout: ${stdout}`);
|
|
98
|
+
if (stderr)
|
|
99
|
+
console.error(`stderr: ${stderr}`);
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (args.path !== 'bootstrap' && !flags.name && !flags.up && !flags.down && !flags.gateway && !flags.restart) {
|
|
71
104
|
console.log('Please provide a name for the container to build');
|
|
72
105
|
this.exit(1);
|
|
73
106
|
}
|
|
@@ -11,9 +11,11 @@ export default class Elixir extends Command {
|
|
|
11
11
|
dev: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
12
12
|
'dry-run': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
13
13
|
git: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
|
+
local: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
14
15
|
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
15
16
|
pypi: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
16
17
|
repoVersion: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
|
+
subdirectory: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
17
19
|
whl: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
18
20
|
workdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
21
|
};
|
package/dist/commands/elixir.js
CHANGED
|
@@ -24,6 +24,7 @@ export default class Elixir extends Command {
|
|
|
24
24
|
description: 'Show what changes would be made without actually making them',
|
|
25
25
|
}),
|
|
26
26
|
git: Flags.string({ char: 'g', default: 'none', description: 'Github repository to install' }),
|
|
27
|
+
local: Flags.string({ char: 'l', default: 'none', description: 'Local directory to install from' }),
|
|
27
28
|
name: Flags.string({ char: 'n', description: 'Name of the elixir' }),
|
|
28
29
|
pypi: Flags.string({
|
|
29
30
|
char: 'p',
|
|
@@ -31,6 +32,11 @@ export default class Elixir extends Command {
|
|
|
31
32
|
description: 'PyPi package to install. Ex: dhti-elixir-base = ">=0.1.0"',
|
|
32
33
|
}),
|
|
33
34
|
repoVersion: Flags.string({ char: 'v', default: '0.1.0', description: 'Version of the elixir' }),
|
|
35
|
+
subdirectory: Flags.string({
|
|
36
|
+
char: 's',
|
|
37
|
+
default: 'none',
|
|
38
|
+
description: 'Subdirectory in the repository to install from (for monorepos)',
|
|
39
|
+
}),
|
|
34
40
|
whl: Flags.string({ char: 'e', default: 'none', description: 'Whl file to install' }),
|
|
35
41
|
workdir: Flags.string({
|
|
36
42
|
char: 'w',
|
|
@@ -126,11 +132,31 @@ export default class Elixir extends Command {
|
|
|
126
132
|
lineToAdd = `${flags.name} = { file = "whl/${path.basename(flags.whl)}" }`;
|
|
127
133
|
}
|
|
128
134
|
if (flags.git !== 'none') {
|
|
129
|
-
lineToAdd =
|
|
135
|
+
lineToAdd =
|
|
136
|
+
flags.subdirectory === 'none'
|
|
137
|
+
? `${flags.name} = { git = "${flags.git}", branch = "${flags.branch}" }`
|
|
138
|
+
: `${flags.name} = { git = "${flags.git}", branch = "${flags.branch}", subdirectory = "${flags.subdirectory}" }`;
|
|
130
139
|
}
|
|
131
140
|
if (flags.pypi !== 'none') {
|
|
132
141
|
lineToAdd = flags.pypi;
|
|
133
142
|
}
|
|
143
|
+
if (flags.local !== 'none') {
|
|
144
|
+
// Use path for local directory installation
|
|
145
|
+
const absolutePath = path.isAbsolute(flags.local) ? flags.local : path.resolve(process.cwd(), flags.local);
|
|
146
|
+
// Validate that the path exists and is a directory (skip validation in dry-run mode)
|
|
147
|
+
if (!flags['dry-run']) {
|
|
148
|
+
if (!fs.existsSync(absolutePath)) {
|
|
149
|
+
console.error(chalk.red(`Error: Local directory does not exist: ${absolutePath}`));
|
|
150
|
+
this.exit(1);
|
|
151
|
+
}
|
|
152
|
+
const stats = fs.statSync(absolutePath);
|
|
153
|
+
if (!stats.isDirectory()) {
|
|
154
|
+
console.error(chalk.red(`Error: Path is not a directory: ${absolutePath}`));
|
|
155
|
+
this.exit(1);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
lineToAdd = `${flags.name} = { path = "${absolutePath}" }`;
|
|
159
|
+
}
|
|
134
160
|
if (!flags['dry-run']) {
|
|
135
161
|
pyproject = pyproject.replace('dependencies = [', `dependencies = [\n"${flags.name}",`);
|
|
136
162
|
pyproject = pyproject.replace('[tool.uv.sources]', `[tool.uv.sources]\n${lineToAdd}\n`);
|
package/oclif.manifest.json
CHANGED
|
@@ -116,6 +116,15 @@
|
|
|
116
116
|
"multiple": false,
|
|
117
117
|
"type": "option"
|
|
118
118
|
},
|
|
119
|
+
"local": {
|
|
120
|
+
"char": "l",
|
|
121
|
+
"description": "Local directory to install from",
|
|
122
|
+
"name": "local",
|
|
123
|
+
"default": "none",
|
|
124
|
+
"hasDynamicHelp": false,
|
|
125
|
+
"multiple": false,
|
|
126
|
+
"type": "option"
|
|
127
|
+
},
|
|
119
128
|
"name": {
|
|
120
129
|
"char": "n",
|
|
121
130
|
"description": "Name of the elixir",
|
|
@@ -133,6 +142,15 @@
|
|
|
133
142
|
"multiple": false,
|
|
134
143
|
"type": "option"
|
|
135
144
|
},
|
|
145
|
+
"subdirectory": {
|
|
146
|
+
"char": "s",
|
|
147
|
+
"description": "Subdirectory in the repository to install from (for monorepos)",
|
|
148
|
+
"name": "subdirectory",
|
|
149
|
+
"default": "none",
|
|
150
|
+
"hasDynamicHelp": false,
|
|
151
|
+
"multiple": false,
|
|
152
|
+
"type": "option"
|
|
153
|
+
},
|
|
136
154
|
"workdir": {
|
|
137
155
|
"char": "w",
|
|
138
156
|
"description": "Working directory to install the conch",
|
|
@@ -203,6 +221,13 @@
|
|
|
203
221
|
"multiple": false,
|
|
204
222
|
"type": "option"
|
|
205
223
|
},
|
|
224
|
+
"gateway": {
|
|
225
|
+
"char": "g",
|
|
226
|
+
"description": "Restart the gateway container",
|
|
227
|
+
"name": "gateway",
|
|
228
|
+
"allowNo": false,
|
|
229
|
+
"type": "boolean"
|
|
230
|
+
},
|
|
206
231
|
"name": {
|
|
207
232
|
"char": "n",
|
|
208
233
|
"description": "Name of the container to build",
|
|
@@ -211,6 +236,14 @@
|
|
|
211
236
|
"multiple": false,
|
|
212
237
|
"type": "option"
|
|
213
238
|
},
|
|
239
|
+
"restart": {
|
|
240
|
+
"char": "r",
|
|
241
|
+
"description": "Restart a specific container by name",
|
|
242
|
+
"name": "restart",
|
|
243
|
+
"hasDynamicHelp": false,
|
|
244
|
+
"multiple": false,
|
|
245
|
+
"type": "option"
|
|
246
|
+
},
|
|
214
247
|
"type": {
|
|
215
248
|
"char": "t",
|
|
216
249
|
"description": "Type of the service (elixir/conch)",
|
|
@@ -378,6 +411,15 @@
|
|
|
378
411
|
"multiple": false,
|
|
379
412
|
"type": "option"
|
|
380
413
|
},
|
|
414
|
+
"local": {
|
|
415
|
+
"char": "l",
|
|
416
|
+
"description": "Local directory to install from",
|
|
417
|
+
"name": "local",
|
|
418
|
+
"default": "none",
|
|
419
|
+
"hasDynamicHelp": false,
|
|
420
|
+
"multiple": false,
|
|
421
|
+
"type": "option"
|
|
422
|
+
},
|
|
381
423
|
"name": {
|
|
382
424
|
"char": "n",
|
|
383
425
|
"description": "Name of the elixir",
|
|
@@ -404,6 +446,15 @@
|
|
|
404
446
|
"multiple": false,
|
|
405
447
|
"type": "option"
|
|
406
448
|
},
|
|
449
|
+
"subdirectory": {
|
|
450
|
+
"char": "s",
|
|
451
|
+
"description": "Subdirectory in the repository to install from (for monorepos)",
|
|
452
|
+
"name": "subdirectory",
|
|
453
|
+
"default": "none",
|
|
454
|
+
"hasDynamicHelp": false,
|
|
455
|
+
"multiple": false,
|
|
456
|
+
"type": "option"
|
|
457
|
+
},
|
|
407
458
|
"whl": {
|
|
408
459
|
"char": "e",
|
|
409
460
|
"description": "Whl file to install",
|
|
@@ -741,5 +792,5 @@
|
|
|
741
792
|
]
|
|
742
793
|
}
|
|
743
794
|
},
|
|
744
|
-
"version": "0.
|
|
795
|
+
"version": "0.8.0"
|
|
745
796
|
}
|