@corenel/cli 0.9.4 → 0.10.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/main.js +67 -35
- package/package.json +7 -7
package/dist/main.js
CHANGED
|
@@ -28479,9 +28479,9 @@ ${firstUserMsg.content}`;
|
|
|
28479
28479
|
_MemoryFileSystem.MAX_PACKAGE_SIZE = 50 * 1024 * 1024;
|
|
28480
28480
|
MemoryFileSystem = _MemoryFileSystem;
|
|
28481
28481
|
HybridFileSystem = class {
|
|
28482
|
-
constructor(files = {},
|
|
28482
|
+
constructor(files = {}, backend) {
|
|
28483
28483
|
this.mem = new MemoryFileSystem(files);
|
|
28484
|
-
this.backend =
|
|
28484
|
+
this.backend = backend;
|
|
28485
28485
|
}
|
|
28486
28486
|
/** Add or update an in-memory (synchronously-served) file. */
|
|
28487
28487
|
addFile(filePath, content) {
|
|
@@ -28651,7 +28651,7 @@ var init_toolGuidance = __esm({
|
|
|
28651
28651
|
|
|
28652
28652
|
// ../tools-node/promptHost.ts
|
|
28653
28653
|
import { normalizeFilePath as normalizeFilePath2, flattenFiles as flattenFiles2 } from "@corenel/protocol";
|
|
28654
|
-
function
|
|
28654
|
+
function promptBackend(svc) {
|
|
28655
28655
|
return {
|
|
28656
28656
|
async readFile(p) {
|
|
28657
28657
|
try {
|
|
@@ -28668,9 +28668,10 @@ function backend(svc) {
|
|
|
28668
28668
|
}
|
|
28669
28669
|
};
|
|
28670
28670
|
}
|
|
28671
|
-
async function
|
|
28671
|
+
async function preloadPromptSources(svc, keep) {
|
|
28672
28672
|
const out = {};
|
|
28673
28673
|
for (const f of flattenFiles2(await svc.list())) {
|
|
28674
|
+
if (keep && !keep(f.path)) continue;
|
|
28674
28675
|
try {
|
|
28675
28676
|
out[f.path] = await svc.read(f.path);
|
|
28676
28677
|
} catch {
|
|
@@ -28702,10 +28703,10 @@ function nodePromptHost(workspace, project) {
|
|
|
28702
28703
|
parse: (source) => ({ meta: parser.parseContent(source).metadata ?? {} }),
|
|
28703
28704
|
compileBody: (source, values) => compile(source, values),
|
|
28704
28705
|
compileTemplate: async (path, liveSrc, values) => {
|
|
28705
|
-
const sources = await
|
|
28706
|
+
const sources = await preloadPromptSources(workspace);
|
|
28706
28707
|
const p = normalizeFilePath2(path);
|
|
28707
28708
|
sources[p] = liveSrc;
|
|
28708
|
-
return compile("", values, new HybridFileSystem(sources,
|
|
28709
|
+
return compile("", values, new HybridFileSystem(sources, promptBackend(workspace)), "/" + p);
|
|
28709
28710
|
},
|
|
28710
28711
|
siteIndex: () => "",
|
|
28711
28712
|
// no site index in node (the help chat is browser-only)
|
|
@@ -28982,6 +28983,14 @@ var init_approvalsStore = __esm({
|
|
|
28982
28983
|
});
|
|
28983
28984
|
|
|
28984
28985
|
// ../tools-node/deviceLogin.ts
|
|
28986
|
+
function verificationLink(dc) {
|
|
28987
|
+
const base = dc.verification_uri;
|
|
28988
|
+
const complete = dc.verification_uri_complete;
|
|
28989
|
+
if (typeof complete === "string" && complete.startsWith(base) && (complete[base.length] === "?" || complete[base.length] === "&")) {
|
|
28990
|
+
return complete;
|
|
28991
|
+
}
|
|
28992
|
+
return `${base}${base.includes("?") ? "&" : "?"}code=${encodeURIComponent(dc.user_code)}`;
|
|
28993
|
+
}
|
|
28985
28994
|
function deadlineSignal(ms, outer) {
|
|
28986
28995
|
const ac = new AbortController();
|
|
28987
28996
|
const onOuter = () => ac.abort();
|
|
@@ -29049,7 +29058,7 @@ async function deviceLogin(opts) {
|
|
|
29049
29058
|
};
|
|
29050
29059
|
const dc = await post("/oauth/device/code", { client_id: "corenel-cli", scope: "agent pair" });
|
|
29051
29060
|
if (!dc.device_code) throw new Error("device authorization failed");
|
|
29052
|
-
(opts.open ?? defaultOpen)(dc
|
|
29061
|
+
(opts.open ?? defaultOpen)(verificationLink(dc), dc.user_code);
|
|
29053
29062
|
let interval = opts.pollMs ?? Math.max(MIN_POLL_MS, (dc.interval ?? 5) * 1e3);
|
|
29054
29063
|
const lifetimeMs = (typeof dc.expires_in === "number" && dc.expires_in > 0 ? dc.expires_in : DEFAULT_LIFETIME_S) * 1e3;
|
|
29055
29064
|
const deadline = Date.now() + lifetimeMs;
|
|
@@ -32845,7 +32854,7 @@ function configWorkspaceRoot(base) {
|
|
|
32845
32854
|
import { FileRecallStore, UNATTACHED_SESSION } from "@corenel/harness/sessions/fileRecallStore";
|
|
32846
32855
|
import { makeSessionFoldStorage } from "@corenel/harness/sessions/foldStorage";
|
|
32847
32856
|
import { makeSummarizer } from "@corenel/harness/core/summarize";
|
|
32848
|
-
import { stateDirName as
|
|
32857
|
+
import { stateDirName as stateDirName6, sessionsRoot, isSourceRun } from "@corenel/protocol";
|
|
32849
32858
|
import { PermissionService as PermissionService6 } from "@corenel/harness/guardrail/permission-service";
|
|
32850
32859
|
|
|
32851
32860
|
// src/nodeContext.ts
|
|
@@ -32947,6 +32956,7 @@ var crew_exports = {};
|
|
|
32947
32956
|
__export(crew_exports, {
|
|
32948
32957
|
AUTONOMY_TOOLS: () => AUTONOMY_TOOLS,
|
|
32949
32958
|
CHECK_IN_BLOCK: () => CHECK_IN_BLOCK,
|
|
32959
|
+
COMMAND_CAPABILITIES: () => COMMAND_CAPABILITIES,
|
|
32950
32960
|
CREW_EXCLUDED_TOOLS: () => CREW_EXCLUDED_TOOLS,
|
|
32951
32961
|
CREW_SEG: () => CREW_SEG,
|
|
32952
32962
|
DEPLOYMENT_FILE: () => DEPLOYMENT_FILE,
|
|
@@ -33001,6 +33011,7 @@ __export(crew_exports, {
|
|
|
33001
33011
|
foldRoom: () => foldRoom,
|
|
33002
33012
|
globMatch: () => globMatch,
|
|
33003
33013
|
grantOfferedTools: () => grantOfferedTools,
|
|
33014
|
+
grantsCommandTools: () => grantsCommandTools,
|
|
33004
33015
|
interjectHuman: () => interjectHuman,
|
|
33005
33016
|
isAutonomyPreset: () => isAutonomyPreset,
|
|
33006
33017
|
isOrchestrator: () => isOrchestrator,
|
|
@@ -33023,6 +33034,7 @@ __export(crew_exports, {
|
|
|
33023
33034
|
newCrewDraft: () => newCrewDraft,
|
|
33024
33035
|
nextCronAfter: () => nextCronAfter,
|
|
33025
33036
|
normalizeRunStatus: () => normalizeRunStatus,
|
|
33037
|
+
offersCommandTools: () => offersCommandTools,
|
|
33026
33038
|
openLineOf: () => openLineOf,
|
|
33027
33039
|
openRoom: () => openRoom,
|
|
33028
33040
|
parseCron: () => parseCron,
|
|
@@ -33056,6 +33068,7 @@ __export(crew_exports, {
|
|
|
33056
33068
|
takeTurn: () => takeTurn,
|
|
33057
33069
|
tightenAutonomy: () => tightenAutonomy,
|
|
33058
33070
|
turnCosts: () => turnCosts,
|
|
33071
|
+
unsandboxedCommandsFact: () => unsandboxedCommandsFact,
|
|
33059
33072
|
userMemoryRoot: () => userMemoryRoot,
|
|
33060
33073
|
validateRoomRequest: () => validateRoomRequest,
|
|
33061
33074
|
writeCrewAgentAt: () => writeCrewAgentAt
|
|
@@ -33249,6 +33262,24 @@ function enforcedLevel(policy, cap) {
|
|
|
33249
33262
|
});
|
|
33250
33263
|
}
|
|
33251
33264
|
|
|
33265
|
+
// ../crew/commandTools.ts
|
|
33266
|
+
var COMMAND_CAPABILITIES = [
|
|
33267
|
+
{ tool: "sidecar_shell_exec", label: "Run shell commands", mutating: true, address: "sidecar:shell_exec", permission: "ask" },
|
|
33268
|
+
{ tool: "sidecar_run_check", label: "Run confirmed checks", mutating: true, address: "sidecar:run_check", permission: "ask" },
|
|
33269
|
+
{ tool: "proc_start", label: "Start long-running processes", mutating: true, address: "shell:spawn", permission: "ask" }
|
|
33270
|
+
];
|
|
33271
|
+
function offersCommandTools(toolNames) {
|
|
33272
|
+
const names = new Set(toolNames);
|
|
33273
|
+
return COMMAND_CAPABILITIES.some((c) => names.has(c.tool));
|
|
33274
|
+
}
|
|
33275
|
+
function grantsCommandTools(policy) {
|
|
33276
|
+
return COMMAND_CAPABILITIES.some((c) => enforcedLevel(policy, c) !== "deny");
|
|
33277
|
+
}
|
|
33278
|
+
function unsandboxedCommandsFact(policy, offeredToolNames) {
|
|
33279
|
+
const offered = new Set(offeredToolNames);
|
|
33280
|
+
return COMMAND_CAPABILITIES.some((c) => offered.has(c.tool) && enforcedLevel(policy, c) !== "deny") ? { unsandboxedCommands: true } : {};
|
|
33281
|
+
}
|
|
33282
|
+
|
|
33252
33283
|
// ../crew/autonomy.ts
|
|
33253
33284
|
import { SIDECAR_GIT_PUSH, SIDECAR_OPEN_PR } from "@corenel/protocol";
|
|
33254
33285
|
import { toolAddress, resolveNamespace } from "@corenel/harness/tools/namespaces";
|
|
@@ -35105,7 +35136,7 @@ import { createChatClient, setGatewayBase } from "@corenel/harness/providers/gat
|
|
|
35105
35136
|
// src/apiBase.ts
|
|
35106
35137
|
init_tools_node();
|
|
35107
35138
|
import { DEFAULT_API_BASE as DEFAULT_API_BASE2 } from "@corenel/protocol";
|
|
35108
|
-
import { DEV_PROFILE } from "@corenel/protocol";
|
|
35139
|
+
import { DEV_PROFILE, SANDBOX_GATEWAY_BASE_ENV } from "@corenel/protocol";
|
|
35109
35140
|
var InvalidApiBaseError = class extends Error {
|
|
35110
35141
|
constructor(value, why) {
|
|
35111
35142
|
super(`invalid API base ${JSON.stringify(value)} -- ${why}`);
|
|
@@ -35159,7 +35190,10 @@ async function resolveCliApiBase(explicit, opts = {}) {
|
|
|
35159
35190
|
if (url.protocol !== "https:" && url.protocol !== "http:") {
|
|
35160
35191
|
throw new InvalidApiBaseError(value, `the scheme must be https or http, not ${url.protocol.replace(/:$/, "")}`);
|
|
35161
35192
|
}
|
|
35162
|
-
|
|
35193
|
+
const trim2 = (s) => s.trim().replace(/\/+$/, "");
|
|
35194
|
+
const marker = env[SANDBOX_GATEWAY_BASE_ENV];
|
|
35195
|
+
const sanctioned = typeof marker === "string" && marker.trim() !== "" && trim2(marker) === trim2(value);
|
|
35196
|
+
if (url.protocol === "http:" && !isLoopback(url.hostname) && !sanctioned && !warnedCleartext) {
|
|
35163
35197
|
warnedCleartext = true;
|
|
35164
35198
|
process.stderr.write(
|
|
35165
35199
|
`corenel: warning: ${url.host} is plain http, so your access token is sent in cleartext. Use https unless this host is on a private network you trust.
|
|
@@ -35340,10 +35374,10 @@ var EXTENSIONS = [
|
|
|
35340
35374
|
}
|
|
35341
35375
|
},
|
|
35342
35376
|
{
|
|
35343
|
-
command: "
|
|
35377
|
+
command: "sandboxes",
|
|
35344
35378
|
...SIDECAR,
|
|
35345
|
-
summary: "list and
|
|
35346
|
-
argv: (rest) => ["
|
|
35379
|
+
summary: "create, list and run in local sandboxes",
|
|
35380
|
+
argv: (rest) => ["sandboxes", ...rest]
|
|
35347
35381
|
},
|
|
35348
35382
|
{
|
|
35349
35383
|
command: "crew",
|
|
@@ -35447,14 +35481,13 @@ async function runExtension(ext, rest, look = {}) {
|
|
|
35447
35481
|
}
|
|
35448
35482
|
|
|
35449
35483
|
// src/commands.ts
|
|
35450
|
-
import { stateDirName as stateDirName4 } from "@corenel/protocol";
|
|
35451
35484
|
var COMMANDS = [
|
|
35452
35485
|
{ name: "", args: "", summary: "with no command: an interactive agent in this directory" },
|
|
35453
|
-
{ name: "run", args: '"<prompt>" [--allow-mutations] | --
|
|
35486
|
+
{ name: "run", args: '"<prompt>" [--allow-mutations] | --sandbox ID "<prompt>"', summary: "one-shot turn, then exit -- refuses writes/shell unless --allow-mutations; --sandbox runs the bare prompt in a sandbox instead and ignores every other flag" },
|
|
35454
35487
|
{ name: "run-agent", args: '<name> --input "<text>" [--allow-mutations]', summary: "run a crew agent (same refuse-by-default gate as run); events as JSON Lines on stdout" },
|
|
35455
35488
|
{ name: "sidecar", args: "[start] [flags]", summary: "run the sidecar on this machine" },
|
|
35456
35489
|
{ name: "acp", args: "<agent> [flags]", summary: "proxy an external coding agent under Corenel policy" },
|
|
35457
|
-
{ name: "
|
|
35490
|
+
{ name: "sandboxes", args: "[list|show|create|run|pause|resume|destroy]", summary: "create, list and run in local sandboxes" },
|
|
35458
35491
|
{ name: "crew", args: "deployments | deploy|undeploy|resume <agent> | pause <agent> --reason R", summary: "deploy, undeploy, pause and resume crew agents on this machine" },
|
|
35459
35492
|
{ name: "login", args: "[--base URL]", summary: "sign in through your browser (device flow)" },
|
|
35460
35493
|
{ name: "auth", summary: "show whether you are signed in, and as what" },
|
|
@@ -35507,12 +35540,7 @@ function helpText(version2) {
|
|
|
35507
35540
|
" --version, -v print the version",
|
|
35508
35541
|
" --help, -h print this",
|
|
35509
35542
|
"",
|
|
35510
|
-
"
|
|
35511
|
-
`${stateDirName4()}/sessions/) -- not the same thing as \`run --session ID\` or the`,
|
|
35512
|
-
"`sessions` command below, which forward into a sandbox on the sidecar.",
|
|
35513
|
-
"Same word, two different nouns.",
|
|
35514
|
-
"",
|
|
35515
|
-
"sidecar, acp, sessions and crew are provided by @corenel/sidecar, installed separately.",
|
|
35543
|
+
"sidecar, acp, sandboxes and crew are provided by @corenel/sidecar, installed separately.",
|
|
35516
35544
|
"Each takes its own flags: `corenel sidecar --help`.",
|
|
35517
35545
|
"",
|
|
35518
35546
|
"Exit codes (corenel run, corenel run-agent):",
|
|
@@ -36625,7 +36653,7 @@ function shellTool(cwd) {
|
|
|
36625
36653
|
import { procTools } from "@corenel/harness/tools/procs";
|
|
36626
36654
|
|
|
36627
36655
|
// src/sidecarConnect.ts
|
|
36628
|
-
import { stateDirName as
|
|
36656
|
+
import { stateDirName as stateDirName4 } from "@corenel/protocol";
|
|
36629
36657
|
import { SidecarHost, isSidecarKeyMismatch, isSidecarAccountRefusal } from "@corenel/harness/sidecar/host";
|
|
36630
36658
|
|
|
36631
36659
|
// ../../node_modules/.pnpm/ws@8.21.0/node_modules/ws/wrapper.mjs
|
|
@@ -37017,7 +37045,7 @@ async function connectSidecarProcs(env = process.env, store = cliDeviceStore(),
|
|
|
37017
37045
|
const host = new SidecarHost({
|
|
37018
37046
|
channel,
|
|
37019
37047
|
...credential,
|
|
37020
|
-
stateDir:
|
|
37048
|
+
stateDir: stateDirName4(),
|
|
37021
37049
|
clientId: `corenel-cli-${process.pid}`,
|
|
37022
37050
|
clientName: cliDeviceName(),
|
|
37023
37051
|
onIdentityChallenge: identity2.answer,
|
|
@@ -37062,7 +37090,7 @@ async function connectMcpAdmin(env = process.env, store = cliDeviceStore(), iden
|
|
|
37062
37090
|
const host = new SidecarHost({
|
|
37063
37091
|
channel,
|
|
37064
37092
|
...credential,
|
|
37065
|
-
stateDir:
|
|
37093
|
+
stateDir: stateDirName4(),
|
|
37066
37094
|
clientId: `corenel-cli-${process.pid}`,
|
|
37067
37095
|
clientName: cliDeviceName(),
|
|
37068
37096
|
onIdentityChallenge: identity2.answer,
|
|
@@ -37330,7 +37358,7 @@ async function resolveStrategyPrompt(files, id) {
|
|
|
37330
37358
|
init_tools_node();
|
|
37331
37359
|
import { readFile as readFile2, stat } from "node:fs/promises";
|
|
37332
37360
|
import { join as join11 } from "node:path";
|
|
37333
|
-
import { stateDirName as
|
|
37361
|
+
import { stateDirName as stateDirName5 } from "@corenel/protocol";
|
|
37334
37362
|
import { BUILTIN_POLICIES, STANDARD_POLICY as STANDARD_POLICY3, policyFromYaml } from "@corenel/harness/guardrail";
|
|
37335
37363
|
var PolicyResolutionError = class extends Error {
|
|
37336
37364
|
detail;
|
|
@@ -37415,7 +37443,7 @@ async function resolvePolicy(opts) {
|
|
|
37415
37443
|
}
|
|
37416
37444
|
return { policy: STANDARD_POLICY3, source: { kind: "default" }, warnings };
|
|
37417
37445
|
}
|
|
37418
|
-
const workspacePath = join11(cwd,
|
|
37446
|
+
const workspacePath = join11(cwd, stateDirName5(), "policy.yaml");
|
|
37419
37447
|
if (await fileExists(workspacePath)) {
|
|
37420
37448
|
warnings.push(
|
|
37421
37449
|
`corenel: ${workspacePath} ignored -- a policy inside the workspace can be written by the agent or arrive in a cloned repo. To use it for this folder, move it to ${projectPath}, or pass --policy ${workspacePath} explicitly.`
|
|
@@ -38957,7 +38985,7 @@ async function agentSetup(argv, chosenModel) {
|
|
|
38957
38985
|
try {
|
|
38958
38986
|
const migrated = await migrateHomeLayout();
|
|
38959
38987
|
if (migrated.moved.length) {
|
|
38960
|
-
console.error(`layout: moved ${migrated.moved.length} item(s) into the current ~/${
|
|
38988
|
+
console.error(`layout: moved ${migrated.moved.length} item(s) into the current ~/${stateDirName6()} layout`);
|
|
38961
38989
|
}
|
|
38962
38990
|
for (const left of migrated.skipped) console.error(`layout: left ${left.path} alone (${left.reason})`);
|
|
38963
38991
|
} catch (e) {
|
|
@@ -39025,19 +39053,23 @@ async function buildRunPermission(opts) {
|
|
|
39025
39053
|
}) };
|
|
39026
39054
|
}
|
|
39027
39055
|
async function run(argv) {
|
|
39056
|
+
if (hasValueFlag(argv, "session")) {
|
|
39057
|
+
process.stderr.write("corenel: --session is not a flag of `run`. To run inside a sandbox use --sandbox ID.\n");
|
|
39058
|
+
process.exit(2);
|
|
39059
|
+
}
|
|
39028
39060
|
const prompt = promptOf(argv);
|
|
39029
39061
|
if (!prompt) {
|
|
39030
|
-
process.stderr.write('usage: corenel run "<prompt>" [--model M] [--base URL] [--
|
|
39062
|
+
process.stderr.write('usage: corenel run "<prompt>" [--model M] [--base URL] [--sandbox ID] [--allow-mutations]\n [--max-usd N] [--max-tokens N] [--max-ms N] [--on-budget stop|warn]\n');
|
|
39031
39063
|
process.exit(2);
|
|
39032
39064
|
}
|
|
39033
39065
|
const budget = budgetConstraintsFrom(argv);
|
|
39034
|
-
const
|
|
39035
|
-
if (
|
|
39066
|
+
const sandbox = flag(argv, "sandbox", "");
|
|
39067
|
+
if (sandbox) {
|
|
39036
39068
|
if (hasAllowMutationsFlag(argv) || hasValueFlag(argv, "model") || hasValueFlag(argv, "base") || budget) {
|
|
39037
|
-
process.stderr.write("corenel: note: --
|
|
39069
|
+
process.stderr.write("corenel: note: --sandbox ignores every other flag on this line -- the sandboxed run uses its own defaults.\n");
|
|
39038
39070
|
}
|
|
39039
|
-
const ext = findExtension("
|
|
39040
|
-
process.exitCode = ext ? await runExtension(ext, ["run",
|
|
39071
|
+
const ext = findExtension("sandboxes");
|
|
39072
|
+
process.exitCode = ext ? await runExtension(ext, ["run", sandbox, prompt]) : 2;
|
|
39041
39073
|
return;
|
|
39042
39074
|
}
|
|
39043
39075
|
const { client, model, system, tools, policy, memory, disconnect } = await agentSetup(argv);
|
|
@@ -39394,7 +39426,7 @@ async function main() {
|
|
|
39394
39426
|
}
|
|
39395
39427
|
case "sidecar":
|
|
39396
39428
|
case "acp":
|
|
39397
|
-
case "
|
|
39429
|
+
case "sandboxes":
|
|
39398
39430
|
case "crew": {
|
|
39399
39431
|
const ext = findExtension(cmd);
|
|
39400
39432
|
process.exitCode = ext ? await runExtension(ext, rest) : 2;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corenel/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Corenel CLI — runs the harness in node, in-proc, no transport. The headless proof the kernel is host-agnostic. (corenel run/ask/chat/login + start --sidecar to follow.)",
|
|
6
6
|
"bin": {
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"openai": "^4.77.0",
|
|
11
11
|
"ws": "^8.18.0",
|
|
12
|
-
"@corenel/
|
|
13
|
-
"@corenel/
|
|
14
|
-
"@corenel/harness": "0.
|
|
15
|
-
"@corenel/
|
|
16
|
-
"@corenel/
|
|
12
|
+
"@corenel/config": "0.7.4",
|
|
13
|
+
"@corenel/protocol": "0.17.0",
|
|
14
|
+
"@corenel/harness": "0.19.0",
|
|
15
|
+
"@corenel/mcp": "0.6.4",
|
|
16
|
+
"@corenel/term": "0.8.5"
|
|
17
17
|
},
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"esbuild": "^0.21.5",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"tsx": "^4.19.2",
|
|
23
23
|
"typescript": "^5.9.3",
|
|
24
24
|
"@corenel/crew": "0.0.0",
|
|
25
|
-
"@corenel/tools-node": "0.
|
|
25
|
+
"@corenel/tools-node": "0.9.0"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|
|
28
28
|
"access": "public"
|