@corenel/cli 0.2.0 → 0.2.1
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/cli.js +515 -51
- package/package.json +14 -12
package/dist/cli.js
CHANGED
|
@@ -1500,7 +1500,7 @@ var require_stringify = __commonJS({
|
|
|
1500
1500
|
props.push(doc.directives.tagString(tag));
|
|
1501
1501
|
return props.join(" ");
|
|
1502
1502
|
}
|
|
1503
|
-
function
|
|
1503
|
+
function stringify3(item, ctx, onComment, onChompKeep) {
|
|
1504
1504
|
if (identity.isPair(item))
|
|
1505
1505
|
return item.toString(ctx, onComment, onChompKeep);
|
|
1506
1506
|
if (identity.isAlias(item)) {
|
|
@@ -1529,7 +1529,7 @@ var require_stringify = __commonJS({
|
|
|
1529
1529
|
${ctx.indent}${str5}`;
|
|
1530
1530
|
}
|
|
1531
1531
|
exports.createStringifyContext = createStringifyContext;
|
|
1532
|
-
exports.stringify =
|
|
1532
|
+
exports.stringify = stringify3;
|
|
1533
1533
|
}
|
|
1534
1534
|
});
|
|
1535
1535
|
|
|
@@ -1539,7 +1539,7 @@ var require_stringifyPair = __commonJS({
|
|
|
1539
1539
|
"use strict";
|
|
1540
1540
|
var identity = require_identity();
|
|
1541
1541
|
var Scalar = require_Scalar();
|
|
1542
|
-
var
|
|
1542
|
+
var stringify3 = require_stringify();
|
|
1543
1543
|
var stringifyComment = require_stringifyComment();
|
|
1544
1544
|
function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
|
|
1545
1545
|
const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
|
|
@@ -1561,7 +1561,7 @@ var require_stringifyPair = __commonJS({
|
|
|
1561
1561
|
});
|
|
1562
1562
|
let keyCommentDone = false;
|
|
1563
1563
|
let chompKeep = false;
|
|
1564
|
-
let str5 =
|
|
1564
|
+
let str5 = stringify3.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
|
|
1565
1565
|
if (!explicitKey && !ctx.inFlow && str5.length > 1024) {
|
|
1566
1566
|
if (simpleKeys)
|
|
1567
1567
|
throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
|
|
@@ -1613,7 +1613,7 @@ ${indent}:`;
|
|
|
1613
1613
|
ctx.indent = ctx.indent.substring(2);
|
|
1614
1614
|
}
|
|
1615
1615
|
let valueCommentDone = false;
|
|
1616
|
-
const valueStr =
|
|
1616
|
+
const valueStr = stringify3.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
|
|
1617
1617
|
let ws = " ";
|
|
1618
1618
|
if (keyComment || vsb || vcb) {
|
|
1619
1619
|
ws = vsb ? "\n" : "";
|
|
@@ -1754,7 +1754,7 @@ var require_addPairToJSMap = __commonJS({
|
|
|
1754
1754
|
"use strict";
|
|
1755
1755
|
var log = require_log();
|
|
1756
1756
|
var merge = require_merge();
|
|
1757
|
-
var
|
|
1757
|
+
var stringify3 = require_stringify();
|
|
1758
1758
|
var identity = require_identity();
|
|
1759
1759
|
var toJS = require_toJS();
|
|
1760
1760
|
function addPairToJSMap(ctx, map, { key, value }) {
|
|
@@ -1790,7 +1790,7 @@ var require_addPairToJSMap = __commonJS({
|
|
|
1790
1790
|
if (typeof jsKey !== "object")
|
|
1791
1791
|
return String(jsKey);
|
|
1792
1792
|
if (identity.isNode(key) && ctx?.doc) {
|
|
1793
|
-
const strCtx =
|
|
1793
|
+
const strCtx = stringify3.createStringifyContext(ctx.doc, {});
|
|
1794
1794
|
strCtx.anchors = /* @__PURE__ */ new Set();
|
|
1795
1795
|
for (const node of ctx.anchors.keys())
|
|
1796
1796
|
strCtx.anchors.add(node.anchor);
|
|
@@ -1857,12 +1857,12 @@ var require_stringifyCollection = __commonJS({
|
|
|
1857
1857
|
"../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyCollection.js"(exports) {
|
|
1858
1858
|
"use strict";
|
|
1859
1859
|
var identity = require_identity();
|
|
1860
|
-
var
|
|
1860
|
+
var stringify3 = require_stringify();
|
|
1861
1861
|
var stringifyComment = require_stringifyComment();
|
|
1862
1862
|
function stringifyCollection(collection, ctx, options) {
|
|
1863
1863
|
const flow = ctx.inFlow ?? collection.flow;
|
|
1864
|
-
const
|
|
1865
|
-
return
|
|
1864
|
+
const stringify4 = flow ? stringifyFlowCollection : stringifyBlockCollection;
|
|
1865
|
+
return stringify4(collection, ctx, options);
|
|
1866
1866
|
}
|
|
1867
1867
|
function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
|
|
1868
1868
|
const { indent, options: { commentString } } = ctx;
|
|
@@ -1887,7 +1887,7 @@ var require_stringifyCollection = __commonJS({
|
|
|
1887
1887
|
}
|
|
1888
1888
|
}
|
|
1889
1889
|
chompKeep = false;
|
|
1890
|
-
let str6 =
|
|
1890
|
+
let str6 = stringify3.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
|
|
1891
1891
|
if (comment2)
|
|
1892
1892
|
str6 += stringifyComment.lineComment(str6, itemIndent, commentString(comment2));
|
|
1893
1893
|
if (chompKeep && comment2)
|
|
@@ -1954,7 +1954,7 @@ ${indent}${line}` : "\n";
|
|
|
1954
1954
|
}
|
|
1955
1955
|
if (comment)
|
|
1956
1956
|
reqNewline = true;
|
|
1957
|
-
let str5 =
|
|
1957
|
+
let str5 = stringify3.stringify(item, itemCtx, () => comment = null);
|
|
1958
1958
|
reqNewline || (reqNewline = lines.length > linesAtValue || str5.includes("\n"));
|
|
1959
1959
|
if (i < items.length - 1) {
|
|
1960
1960
|
str5 += ",";
|
|
@@ -3315,7 +3315,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3315
3315
|
"../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyDocument.js"(exports) {
|
|
3316
3316
|
"use strict";
|
|
3317
3317
|
var identity = require_identity();
|
|
3318
|
-
var
|
|
3318
|
+
var stringify3 = require_stringify();
|
|
3319
3319
|
var stringifyComment = require_stringifyComment();
|
|
3320
3320
|
function stringifyDocument(doc, options) {
|
|
3321
3321
|
const lines = [];
|
|
@@ -3330,7 +3330,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3330
3330
|
}
|
|
3331
3331
|
if (hasDirectives)
|
|
3332
3332
|
lines.push("---");
|
|
3333
|
-
const ctx =
|
|
3333
|
+
const ctx = stringify3.createStringifyContext(doc, options);
|
|
3334
3334
|
const { commentString } = ctx.options;
|
|
3335
3335
|
if (doc.commentBefore) {
|
|
3336
3336
|
if (lines.length !== 1)
|
|
@@ -3352,7 +3352,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3352
3352
|
contentComment = doc.contents.comment;
|
|
3353
3353
|
}
|
|
3354
3354
|
const onChompKeep = contentComment ? void 0 : () => chompKeep = true;
|
|
3355
|
-
let body =
|
|
3355
|
+
let body = stringify3.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
|
|
3356
3356
|
if (contentComment)
|
|
3357
3357
|
body += stringifyComment.lineComment(body, "", commentString(contentComment));
|
|
3358
3358
|
if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") {
|
|
@@ -3360,7 +3360,7 @@ var require_stringifyDocument = __commonJS({
|
|
|
3360
3360
|
} else
|
|
3361
3361
|
lines.push(body);
|
|
3362
3362
|
} else {
|
|
3363
|
-
lines.push(
|
|
3363
|
+
lines.push(stringify3.stringify(doc.contents, ctx));
|
|
3364
3364
|
}
|
|
3365
3365
|
if (doc.directives?.docEnd) {
|
|
3366
3366
|
if (doc.comment) {
|
|
@@ -5490,7 +5490,7 @@ var require_cst_scalar = __commonJS({
|
|
|
5490
5490
|
var require_cst_stringify = __commonJS({
|
|
5491
5491
|
"../../node_modules/.pnpm/yaml@2.9.0/node_modules/yaml/dist/parse/cst-stringify.js"(exports) {
|
|
5492
5492
|
"use strict";
|
|
5493
|
-
var
|
|
5493
|
+
var stringify3 = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst);
|
|
5494
5494
|
function stringifyToken(token) {
|
|
5495
5495
|
switch (token.type) {
|
|
5496
5496
|
case "block-scalar": {
|
|
@@ -5543,7 +5543,7 @@ var require_cst_stringify = __commonJS({
|
|
|
5543
5543
|
res += stringifyToken(value);
|
|
5544
5544
|
return res;
|
|
5545
5545
|
}
|
|
5546
|
-
exports.stringify =
|
|
5546
|
+
exports.stringify = stringify3;
|
|
5547
5547
|
}
|
|
5548
5548
|
});
|
|
5549
5549
|
|
|
@@ -7245,7 +7245,7 @@ var require_public_api = __commonJS({
|
|
|
7245
7245
|
}
|
|
7246
7246
|
return doc;
|
|
7247
7247
|
}
|
|
7248
|
-
function
|
|
7248
|
+
function parse3(src, reviver, options) {
|
|
7249
7249
|
let _reviver = void 0;
|
|
7250
7250
|
if (typeof reviver === "function") {
|
|
7251
7251
|
_reviver = reviver;
|
|
@@ -7264,7 +7264,7 @@ var require_public_api = __commonJS({
|
|
|
7264
7264
|
}
|
|
7265
7265
|
return doc.toJS(Object.assign({ reviver: _reviver }, options));
|
|
7266
7266
|
}
|
|
7267
|
-
function
|
|
7267
|
+
function stringify3(value, replacer, options) {
|
|
7268
7268
|
let _replacer = null;
|
|
7269
7269
|
if (typeof replacer === "function" || Array.isArray(replacer)) {
|
|
7270
7270
|
_replacer = replacer;
|
|
@@ -7286,10 +7286,10 @@ var require_public_api = __commonJS({
|
|
|
7286
7286
|
return value.toString(options);
|
|
7287
7287
|
return new Document.Document(value, _replacer, options).toString(options);
|
|
7288
7288
|
}
|
|
7289
|
-
exports.parse =
|
|
7289
|
+
exports.parse = parse3;
|
|
7290
7290
|
exports.parseAllDocuments = parseAllDocuments;
|
|
7291
7291
|
exports.parseDocument = parseDocument;
|
|
7292
|
-
exports.stringify =
|
|
7292
|
+
exports.stringify = stringify3;
|
|
7293
7293
|
}
|
|
7294
7294
|
});
|
|
7295
7295
|
|
|
@@ -7812,7 +7812,7 @@ var require_parse = __commonJS({
|
|
|
7812
7812
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/parse.js"(exports, module) {
|
|
7813
7813
|
"use strict";
|
|
7814
7814
|
var SemVer = require_semver();
|
|
7815
|
-
var
|
|
7815
|
+
var parse3 = (version, options, throwErrors = false) => {
|
|
7816
7816
|
if (version instanceof SemVer) {
|
|
7817
7817
|
return version;
|
|
7818
7818
|
}
|
|
@@ -7825,7 +7825,7 @@ var require_parse = __commonJS({
|
|
|
7825
7825
|
throw er;
|
|
7826
7826
|
}
|
|
7827
7827
|
};
|
|
7828
|
-
module.exports =
|
|
7828
|
+
module.exports = parse3;
|
|
7829
7829
|
}
|
|
7830
7830
|
});
|
|
7831
7831
|
|
|
@@ -7833,9 +7833,9 @@ var require_parse = __commonJS({
|
|
|
7833
7833
|
var require_valid = __commonJS({
|
|
7834
7834
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/valid.js"(exports, module) {
|
|
7835
7835
|
"use strict";
|
|
7836
|
-
var
|
|
7836
|
+
var parse3 = require_parse();
|
|
7837
7837
|
var valid = (version, options) => {
|
|
7838
|
-
const v =
|
|
7838
|
+
const v = parse3(version, options);
|
|
7839
7839
|
return v ? v.version : null;
|
|
7840
7840
|
};
|
|
7841
7841
|
module.exports = valid;
|
|
@@ -7846,9 +7846,9 @@ var require_valid = __commonJS({
|
|
|
7846
7846
|
var require_clean = __commonJS({
|
|
7847
7847
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/clean.js"(exports, module) {
|
|
7848
7848
|
"use strict";
|
|
7849
|
-
var
|
|
7849
|
+
var parse3 = require_parse();
|
|
7850
7850
|
var clean = (version, options) => {
|
|
7851
|
-
const s =
|
|
7851
|
+
const s = parse3(version.trim().replace(/^[=v]+/, ""), options);
|
|
7852
7852
|
return s ? s.version : null;
|
|
7853
7853
|
};
|
|
7854
7854
|
module.exports = clean;
|
|
@@ -7883,10 +7883,10 @@ var require_inc = __commonJS({
|
|
|
7883
7883
|
var require_diff = __commonJS({
|
|
7884
7884
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/diff.js"(exports, module) {
|
|
7885
7885
|
"use strict";
|
|
7886
|
-
var
|
|
7886
|
+
var parse3 = require_parse();
|
|
7887
7887
|
var diff = (version1, version2) => {
|
|
7888
|
-
const v1 =
|
|
7889
|
-
const v2 =
|
|
7888
|
+
const v1 = parse3(version1, null, true);
|
|
7889
|
+
const v2 = parse3(version2, null, true);
|
|
7890
7890
|
const comparison = v1.compare(v2);
|
|
7891
7891
|
if (comparison === 0) {
|
|
7892
7892
|
return null;
|
|
@@ -7957,9 +7957,9 @@ var require_patch = __commonJS({
|
|
|
7957
7957
|
var require_prerelease = __commonJS({
|
|
7958
7958
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/prerelease.js"(exports, module) {
|
|
7959
7959
|
"use strict";
|
|
7960
|
-
var
|
|
7960
|
+
var parse3 = require_parse();
|
|
7961
7961
|
var prerelease = (version, options) => {
|
|
7962
|
-
const parsed =
|
|
7962
|
+
const parsed = parse3(version, options);
|
|
7963
7963
|
return parsed && parsed.prerelease.length ? parsed.prerelease : null;
|
|
7964
7964
|
};
|
|
7965
7965
|
module.exports = prerelease;
|
|
@@ -8145,7 +8145,7 @@ var require_coerce = __commonJS({
|
|
|
8145
8145
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/coerce.js"(exports, module) {
|
|
8146
8146
|
"use strict";
|
|
8147
8147
|
var SemVer = require_semver();
|
|
8148
|
-
var
|
|
8148
|
+
var parse3 = require_parse();
|
|
8149
8149
|
var { safeRe: re, t } = require_re();
|
|
8150
8150
|
var coerce = (version, options) => {
|
|
8151
8151
|
if (version instanceof SemVer) {
|
|
@@ -8180,7 +8180,7 @@ var require_coerce = __commonJS({
|
|
|
8180
8180
|
const patch = match[4] || "0";
|
|
8181
8181
|
const prerelease = options.includePrerelease && match[5] ? `-${match[5]}` : "";
|
|
8182
8182
|
const build = options.includePrerelease && match[6] ? `+${match[6]}` : "";
|
|
8183
|
-
return
|
|
8183
|
+
return parse3(`${major}.${minor}.${patch}${prerelease}${build}`, options);
|
|
8184
8184
|
};
|
|
8185
8185
|
module.exports = coerce;
|
|
8186
8186
|
}
|
|
@@ -8190,7 +8190,7 @@ var require_coerce = __commonJS({
|
|
|
8190
8190
|
var require_truncate = __commonJS({
|
|
8191
8191
|
"../../node_modules/.pnpm/semver@7.8.5/node_modules/semver/functions/truncate.js"(exports, module) {
|
|
8192
8192
|
"use strict";
|
|
8193
|
-
var
|
|
8193
|
+
var parse3 = require_parse();
|
|
8194
8194
|
var constants = require_constants();
|
|
8195
8195
|
var SemVer = require_semver();
|
|
8196
8196
|
var truncate = (version, truncation, options) => {
|
|
@@ -8202,7 +8202,7 @@ var require_truncate = __commonJS({
|
|
|
8202
8202
|
};
|
|
8203
8203
|
var cloneInputVersion = (version, options) => {
|
|
8204
8204
|
const versionStringToParse = version instanceof SemVer ? version.version : version;
|
|
8205
|
-
return
|
|
8205
|
+
return parse3(versionStringToParse, options);
|
|
8206
8206
|
};
|
|
8207
8207
|
var doTruncation = (version, truncation) => {
|
|
8208
8208
|
if (isPrerelease(truncation)) {
|
|
@@ -9244,7 +9244,7 @@ var require_semver2 = __commonJS({
|
|
|
9244
9244
|
var constants = require_constants();
|
|
9245
9245
|
var SemVer = require_semver();
|
|
9246
9246
|
var identifiers = require_identifiers();
|
|
9247
|
-
var
|
|
9247
|
+
var parse3 = require_parse();
|
|
9248
9248
|
var valid = require_valid();
|
|
9249
9249
|
var clean = require_clean();
|
|
9250
9250
|
var inc = require_inc();
|
|
@@ -9283,7 +9283,7 @@ var require_semver2 = __commonJS({
|
|
|
9283
9283
|
var simplifyRange = require_simplify();
|
|
9284
9284
|
var subset = require_subset();
|
|
9285
9285
|
module.exports = {
|
|
9286
|
-
parse:
|
|
9286
|
+
parse: parse3,
|
|
9287
9287
|
valid,
|
|
9288
9288
|
clean,
|
|
9289
9289
|
inc,
|
|
@@ -11670,7 +11670,7 @@ var require_parser2 = __commonJS({
|
|
|
11670
11670
|
}
|
|
11671
11671
|
return buf;
|
|
11672
11672
|
};
|
|
11673
|
-
_proto.parse = function
|
|
11673
|
+
_proto.parse = function parse3() {
|
|
11674
11674
|
return new nodes.NodeList(0, 0, this.parseNodes());
|
|
11675
11675
|
};
|
|
11676
11676
|
_proto.parseAsRoot = function parseAsRoot() {
|
|
@@ -11679,7 +11679,7 @@ var require_parser2 = __commonJS({
|
|
|
11679
11679
|
return Parser2;
|
|
11680
11680
|
}(Obj);
|
|
11681
11681
|
module.exports = {
|
|
11682
|
-
parse: function
|
|
11682
|
+
parse: function parse3(src, extensions, opts) {
|
|
11683
11683
|
var p = new Parser(lexer.lex(src, opts));
|
|
11684
11684
|
if (extensions !== void 0) {
|
|
11685
11685
|
p.extensions = extensions;
|
|
@@ -15077,6 +15077,9 @@ async function streamCompletion(client, params, signal, onText) {
|
|
|
15077
15077
|
// Undefined is dropped by the SDK's JSON serialization, so an unset cap
|
|
15078
15078
|
// leaves output unbounded (unchanged behavior).
|
|
15079
15079
|
max_completion_tokens: params.max_completion_tokens,
|
|
15080
|
+
// Undefined is dropped by the SDK, so an unset temperature leaves the
|
|
15081
|
+
// provider default in place (unchanged behavior).
|
|
15082
|
+
temperature: params.temperature,
|
|
15080
15083
|
stream: true,
|
|
15081
15084
|
stream_options: { include_usage: true }
|
|
15082
15085
|
},
|
|
@@ -15380,7 +15383,25 @@ var BUILTIN_NAMESPACES = {
|
|
|
15380
15383
|
ask_user: "agent",
|
|
15381
15384
|
spawn_agent: "agent",
|
|
15382
15385
|
spawn_agents: "agent",
|
|
15383
|
-
todo_write: "agent"
|
|
15386
|
+
todo_write: "agent",
|
|
15387
|
+
// Named here as a backstop; the sidecar's own decls also carry `namespace`,
|
|
15388
|
+
// and an explicit field always wins (resolveNamespace). Both say the same
|
|
15389
|
+
// thing so a sidecar that predates this still lands in the right namespace.
|
|
15390
|
+
sidecar_fs_read_file: "sidecar",
|
|
15391
|
+
sidecar_fs_write_file: "sidecar",
|
|
15392
|
+
sidecar_fs_read_bytes: "sidecar",
|
|
15393
|
+
sidecar_fs_list_dir: "sidecar",
|
|
15394
|
+
sidecar_fs_delete: "sidecar",
|
|
15395
|
+
sidecar_shell_exec: "sidecar",
|
|
15396
|
+
// Host-side orchestration tools. They are not in allTools() - they reach the
|
|
15397
|
+
// agent as remote decls (workerFactory) - but they are still governed by the
|
|
15398
|
+
// policy, so they need a canonical address like everything else.
|
|
15399
|
+
create_strategy: "agent",
|
|
15400
|
+
edit_strategy: "agent",
|
|
15401
|
+
view_strategy: "agent",
|
|
15402
|
+
run_strategy: "agent",
|
|
15403
|
+
list_strategies: "agent",
|
|
15404
|
+
list_saved_strategies: "agent"
|
|
15384
15405
|
};
|
|
15385
15406
|
function resolveNamespace(tool) {
|
|
15386
15407
|
if (tool.namespace) return tool.namespace;
|
|
@@ -15400,6 +15421,14 @@ function toolAddress(tool) {
|
|
|
15400
15421
|
const m = new RegExp(`^${ns}__?`).exec(leaf);
|
|
15401
15422
|
if (m) leaf = leaf.slice(m[0].length);
|
|
15402
15423
|
}
|
|
15424
|
+
if (ns === "sidecar") {
|
|
15425
|
+
for (const p of ["sidecar_fs_", "sidecar_"]) {
|
|
15426
|
+
if (leaf.startsWith(p)) {
|
|
15427
|
+
leaf = leaf.slice(p.length);
|
|
15428
|
+
break;
|
|
15429
|
+
}
|
|
15430
|
+
}
|
|
15431
|
+
}
|
|
15403
15432
|
return `${ns}:${leaf}`;
|
|
15404
15433
|
}
|
|
15405
15434
|
|
|
@@ -15484,7 +15513,8 @@ async function runAgent(args) {
|
|
|
15484
15513
|
messages,
|
|
15485
15514
|
tools: toolDefs.length ? toolDefs : void 0,
|
|
15486
15515
|
tool_choice: toolDefs.length ? "auto" : void 0,
|
|
15487
|
-
max_completion_tokens: args.maxCompletionTokens
|
|
15516
|
+
max_completion_tokens: args.maxCompletionTokens,
|
|
15517
|
+
temperature: args.temperature
|
|
15488
15518
|
},
|
|
15489
15519
|
signal,
|
|
15490
15520
|
(delta) => emit({ type: "assistant-delta", delta })
|
|
@@ -15932,6 +15962,18 @@ var todoWriteTool = {
|
|
|
15932
15962
|
name: "todo_write",
|
|
15933
15963
|
noOffload: true,
|
|
15934
15964
|
// the task list is what the user wants to see — keep it inline
|
|
15965
|
+
/* DECLARED, not left to the policy's default. It is a write in name only: it
|
|
15966
|
+
* touches no file, no network and no state outside the run's own task panel,
|
|
15967
|
+
* so there is nothing for a person to approve. Without this it inherited
|
|
15968
|
+
* `policy.defaultPermission` — `ask` under any careful policy — and an agent
|
|
15969
|
+
* doing multi-step work stopped to request approval every time it ticked off a
|
|
15970
|
+
* step, which trains people to approve without reading.
|
|
15971
|
+
*
|
|
15972
|
+
* `permission` sits BELOW an explicit `policy.permissions` entry in the
|
|
15973
|
+
* precedence chain (permission-service.ts), so anyone who genuinely wants to
|
|
15974
|
+
* gate it still can; it only replaces the blanket default. And it is not
|
|
15975
|
+
* `mutates`, so a policy's mutating backstop correctly does not catch it. */
|
|
15976
|
+
permission: "allow",
|
|
15935
15977
|
description: 'Maintain a visible task list for a multi-step job. Pass the COMPLETE list each time (a rewrite). Keep exactly one task "in_progress" while you work it; mark tasks "completed" as you finish; use "blocked" + blockedBy for tasks waiting on others; nest a subtask one level with parentId. Reuse a short stable id per task across updates so its progress and activity persist. Call it when you start a multi-step task and after each meaningful step.',
|
|
15936
15978
|
parameters: {
|
|
15937
15979
|
type: "object",
|
|
@@ -16125,17 +16167,29 @@ async function prmdCompileError(content, ctx) {
|
|
|
16125
16167
|
}
|
|
16126
16168
|
var proposeEditTool = {
|
|
16127
16169
|
name: "propose_edit",
|
|
16128
|
-
description: "Propose a replacement for the
|
|
16170
|
+
description: "Propose a replacement for the CURRENTLY OPEN editor file. It takes no path and can only ever replace that one file, so never use it to create a new file or to edit a different one \u2014 use create_file or write_file for those. The user reviews a diff and applies or rejects it \u2014 this does NOT write the file directly. Provide the COMPLETE new file content (not a patch) plus a short explanation. Use the editor file shown in the system context as the basis. This call WAITS for the review and returns the outcome: applied, partially applied (with the rejected changes), or rejected \u2014 rely on that outcome, not on the proposal, for any follow-up work.",
|
|
16129
16171
|
parameters: {
|
|
16130
16172
|
type: "object",
|
|
16131
16173
|
properties: {
|
|
16132
16174
|
explanation: { type: "string", description: "One line describing the change." },
|
|
16133
|
-
new_content: { type: "string", description: "The full proposed file content." }
|
|
16175
|
+
new_content: { type: "string", description: "The full proposed file content." },
|
|
16176
|
+
path: { type: "string", description: "The file being replaced. Must be the file currently open in the editor." }
|
|
16134
16177
|
},
|
|
16135
|
-
required: ["explanation", "new_content"]
|
|
16178
|
+
required: ["explanation", "new_content", "path"]
|
|
16136
16179
|
},
|
|
16137
16180
|
async run(args, ctx) {
|
|
16138
16181
|
const explanation = str4(args, "explanation") || "Proposed an edit";
|
|
16182
|
+
if (!ctx.editorFile) {
|
|
16183
|
+
return "Cannot propose an edit: no file is open in the editor, and propose_edit only replaces the open file. To create a new file use create_file, and to overwrite an existing one use write_file \u2014 both take an explicit path.";
|
|
16184
|
+
}
|
|
16185
|
+
const target = str4(args, "path");
|
|
16186
|
+
if (!target) {
|
|
16187
|
+
return `Cannot propose an edit: propose_edit needs a path, and it must be the open file (${ctx.editorFile}). To create a new file use create_file, or to overwrite a different one use write_file.`;
|
|
16188
|
+
}
|
|
16189
|
+
const norm = (p) => p.trim().replace(/\\/g, "/").replace(/^\.\//, "");
|
|
16190
|
+
if (norm(target) !== norm(ctx.editorFile)) {
|
|
16191
|
+
return `Cannot propose an edit: the open file is ${ctx.editorFile}, but this proposal targets ${target}. propose_edit can only replace the open file. Use create_file for a new file, or write_file to overwrite a different one.`;
|
|
16192
|
+
}
|
|
16139
16193
|
if (!ctx.reviewEdit || !ctx.callId) {
|
|
16140
16194
|
return `Proposed an edit: ${explanation}. Awaiting the user's review (apply/reject).`;
|
|
16141
16195
|
}
|
|
@@ -16232,6 +16286,19 @@ var recallResultTool = {
|
|
|
16232
16286
|
name: "recall_result",
|
|
16233
16287
|
noOffload: true,
|
|
16234
16288
|
// recalling a large result must never re-offload itself
|
|
16289
|
+
/* DECLARED, like todo_write's and ask_user's. This one grants no new access at
|
|
16290
|
+
* all: it reads back a tool result THIS SESSION ALREADY PRODUCED, which means
|
|
16291
|
+
* the original call already passed the policy check that produced it. The
|
|
16292
|
+
* store is session-scoped (`<root>/<sessionId>/blobs/<id>.json`) and the id
|
|
16293
|
+
* shape is validated, so it cannot reach another session's data or escape the
|
|
16294
|
+
* directory.
|
|
16295
|
+
*
|
|
16296
|
+
* The deciding argument is that offloading is a CONTEXT-MANAGEMENT detail,
|
|
16297
|
+
* triggered by size. Gating recall means the same information costs an
|
|
16298
|
+
* approval prompt depending on how large it happened to be - a performance
|
|
16299
|
+
* heuristic leaking into governance, and an approval the user cannot act on
|
|
16300
|
+
* meaningfully because they already approved the thing that produced it. */
|
|
16301
|
+
permission: "allow",
|
|
16235
16302
|
description: 'Fetch the full content of a tool result that was offloaded to save context. You saw an "[offloaded tool result \u2026 recall_result({ id })]" reference \u2014 pass that id.',
|
|
16236
16303
|
parameters: {
|
|
16237
16304
|
type: "object",
|
|
@@ -16247,6 +16314,21 @@ var recallResultTool = {
|
|
|
16247
16314
|
var askUserTool = {
|
|
16248
16315
|
name: "ask_user",
|
|
16249
16316
|
noOffload: true,
|
|
16317
|
+
/* DECLARED, like todo_write's. Gating this behind an approval prompt is asking
|
|
16318
|
+
* the user for permission to ask the user a question — two dialogs for one
|
|
16319
|
+
* decision, the first of which carries no information.
|
|
16320
|
+
*
|
|
16321
|
+
* It changes nothing outside the run: no file, no network, no state. Its whole
|
|
16322
|
+
* effect is to put a question in front of a person who is already there.
|
|
16323
|
+
*
|
|
16324
|
+
* Nothing depended on its previous `ask` tier. The case that looks like it
|
|
16325
|
+
* might — an unattended run parking forever on a question nobody will answer —
|
|
16326
|
+
* is handled by EXCLUSION rather than by permission: CREW_EXCLUDED_TOOLS drops
|
|
16327
|
+
* ask_user from every crew agent (see @corenel/crew's capabilities.ts), and the
|
|
16328
|
+
* daemon's executor honours the same set. On a surface where it IS offered,
|
|
16329
|
+
* someone is by definition attending. And with no `ask` handler wired, `run`
|
|
16330
|
+
* already returns "unavailable in this environment" rather than hanging. */
|
|
16331
|
+
permission: "allow",
|
|
16250
16332
|
description: "Ask the user one or more questions when you need a decision you cannot make from context \u2014 to choose between approaches, get a missing requirement, or confirm direction. Prefer this over guessing. Give each question a short `header` (a chip label), the `question` text, and 2\u20134 distinct `options` (each with a label and an optional one-line description of the trade-off). Set `multiSelect: true` when more than one option may apply. The user can also type a custom answer. Returns the chosen answers per question.",
|
|
16251
16333
|
parameters: {
|
|
16252
16334
|
type: "object",
|
|
@@ -16540,7 +16622,63 @@ Add a constraint :: Add a constraint or rule to the prompt instructions (what to
|
|
|
16540
16622
|
"personas/senior-dev.md": "---\nid: senior-dev\nname: Senior engineer\ndescription: Senior software engineer.\n---\nYou are a senior software engineer. Bring that craft to every change:\n- Fit the codebase. Study neighboring code and follow its conventions before writing. Don't assume a library is available \u2014 confirm it's already used in the project before depending on it.\n- Write the minimum that solves the task. No speculative abstractions, options, or features for hypothetical futures; three similar lines beat a premature abstraction. No half-finished or stubbed implementations.\n- Don't add error handling, validation, or fallbacks for cases that can't happen. Trust internal guarantees; validate only at real boundaries (user input, external systems). No backwards-compat shims unless asked.\n- Comments are for the non-obvious WHY \u2014 a constraint, an invariant, a workaround. Don't narrate what the code already says; default to none.\n- Verify your work before calling a change done. If you couldn't verify something, say so plainly.\n- Be security-minded: no injection, no leaked secrets, least privilege.\n",
|
|
16541
16623
|
"personas/terse.md": "---\nid: terse\nname: Terse\ndescription: Extremely concise.\n---\nBe extremely concise. One sentence per update. No preamble. No summary unless asked.\n",
|
|
16542
16624
|
"memory/MEMORY.md": "# Memory index\n\nSaved notes appear here, one line each. The agent adds them with save_memory and\nreads them with recall_memory. This is the global (~/.prompd) memory; a project's\nown notes live in ./.prompd/memory.\n",
|
|
16543
|
-
"systems/system-base.md":
|
|
16625
|
+
"systems/system-base.md": `---
|
|
16626
|
+
id: system-base
|
|
16627
|
+
name: Operational system prompt
|
|
16628
|
+
version: 1.0.0
|
|
16629
|
+
description: The agent's system prompt \u2014 persona, mode, tool definitions and editor context composed by @prompd/core.
|
|
16630
|
+
parameters:
|
|
16631
|
+
- name: persona
|
|
16632
|
+
type: string
|
|
16633
|
+
description: The selected persona's voice/role text, placed first.
|
|
16634
|
+
default: ""
|
|
16635
|
+
- name: mode
|
|
16636
|
+
type: string
|
|
16637
|
+
description: Active mode id (auto / edit / plan / brainstorm).
|
|
16638
|
+
default: "auto"
|
|
16639
|
+
- name: mode_hint
|
|
16640
|
+
type: string
|
|
16641
|
+
description: Steering text for the active mode.
|
|
16642
|
+
default: ""
|
|
16643
|
+
- name: tools
|
|
16644
|
+
type: string
|
|
16645
|
+
description: Definitions of the tools available this run.
|
|
16646
|
+
default: ""
|
|
16647
|
+
- name: tool_guidance
|
|
16648
|
+
type: string
|
|
16649
|
+
description: Optional extra guidance on tool usage.
|
|
16650
|
+
default: ""
|
|
16651
|
+
- name: file_context
|
|
16652
|
+
type: string
|
|
16653
|
+
description: The editor file / selection / compiled-output context block.
|
|
16654
|
+
default: ""
|
|
16655
|
+
- name: app
|
|
16656
|
+
type: string
|
|
16657
|
+
description: Product name of the host application, used for the agent's own identity.
|
|
16658
|
+
default: "Prompd"
|
|
16659
|
+
---
|
|
16660
|
+
{% if persona %}{{ persona }}
|
|
16661
|
+
|
|
16662
|
+
{% endif %}You are the {{ app }} assistant embedded in the in-browser .prmd editor. You help the user author, compile, and improve .prmd/.md prompts (YAML frontmatter + Nunjucks body with typed parameters). When the user asks about the .prmd format itself \u2014 frontmatter fields, parameter types (including enums), date defaults, inheritance, or templating \u2014 the canonical reference is \`languages/prmd.md\` in the {{ app }} config workspace; consult it rather than guessing (it is already included in context whenever a .prmd/.md file is open).
|
|
16663
|
+
|
|
16664
|
+
To change the file open in the editor, call propose_edit with the COMPLETE new file content \u2014 the user reviews a diff and applies it. To read or change other files in the workspace, use the file tools (writes ask the user for permission first). Use compile_prompd to preview rendered output and search_packages to find registry packages. For any multi-step job, maintain a visible task list with todo_write: lay out the steps, keep one task in_progress, and mark each completed as you go. Prefer calling a tool over guessing, and be concise.
|
|
16665
|
+
|
|
16666
|
+
## Tools available this run
|
|
16667
|
+
{{ tools }}
|
|
16668
|
+
{% if tool_guidance %}
|
|
16669
|
+
|
|
16670
|
+
{{ tool_guidance }}
|
|
16671
|
+
{% endif %}
|
|
16672
|
+
{% if mode_hint %}
|
|
16673
|
+
|
|
16674
|
+
## Mode
|
|
16675
|
+
{{ mode_hint }}
|
|
16676
|
+
{% endif %}
|
|
16677
|
+
{% if file_context %}
|
|
16678
|
+
|
|
16679
|
+
{{ file_context }}
|
|
16680
|
+
{% endif %}
|
|
16681
|
+
`,
|
|
16544
16682
|
"systems/system-pdflow.md": '---\nid: system-pdflow\nname: Workflow file system prompt\nversion: 1.0.0\ndescription: Adds .pdflow format knowledge (node taxonomy, edges, parameters) on top of the base system prompt.\ninherits: system-base.md\n---\n\n## Active file format \u2014 Prompd workflow (.pdflow)\n\nThe open file is a **Prompd workflow**: JSON with `{ version, metadata, parameters[], nodes[], edges[] }`. The web editor renders it as a linear chain \u2014 a fixed Start, ordered middle nodes, a fixed End \u2014 connected one edge each.\n\nEach node is `{ id, type, position, data }`. Node types and their key `data`:\n\n- `trigger` \u2014 Start (entry point). Exactly one.\n- `prompt` \u2014 runs a `.prmd`/`.md` prompt. `data.sourceType` is `\'file\'` (`data.source` = a WORKSPACE-RELATIVE path) or `\'raw\'` (`data.rawPrompt`). Optional `data.model` / `data.providerNodeId`.\n- `user-input` \u2014 pauses to collect input. `data.prompt`, `data.inputType` (`text` / `textarea` / `choice` / `confirm` / `number`).\n- `guardrail` \u2014 validates/gates. `data.systemPrompt`, `data.passExpression` or `data.scoreThreshold`.\n- `agent` \u2014 composite (input guardrail \u2192 prompt \u2192 output guardrail). `data.systemPrompt`, `data.userPrompt`, `data.maxIterations`; internal guardrails in `data.inputGuardrail` / `data.outputGuardrail` (each `{ enabled, preset|systemPrompt, passExpression|scoreThreshold }`).\n- `transformer` \u2014 JSON\u2192JSON map. `data.mode: \'template\'` with `data.template` (`{{ input }}` substitution).\n- `callback` / `checkpoint` \u2014 debug/observation point (logs node I/O).\n- `output` \u2014 End (workflow result). Exactly one.\n- `provider` \u2014 one off-chain node holding the canvas-wide provider/model; nodes reference it via `data.providerNodeId`.\n\nEdges thread each node\'s output to the next; the runner exposes `{{ input }}` / `{{ previous_output }}` to downstream nodes.\n\n### Example (minimal chain)\n\n```\n{\n "version": "1.0",\n "metadata": { "name": "summarize" },\n "parameters": [],\n "nodes": [\n { "id": "start", "type": "trigger", "position": { "x": 0, "y": 0 }, "data": {} },\n { "id": "p1", "type": "prompt", "position": { "x": 0, "y": 120 }, "data": { "sourceType": "file", "source": "prompts/summarize.prmd" } },\n { "id": "end", "type": "output", "position": { "x": 0, "y": 240 }, "data": {} }\n ],\n "edges": [\n { "id": "e1", "source": "start", "target": "p1" },\n { "id": "e2", "source": "p1", "target": "end" }\n ]\n}\n```\n\nTo edit the workflow, modify this JSON with the file tools (paths are workspace-relative). Keep exactly one `trigger` and one `output`.\n',
|
|
16545
16683
|
"systems/system-prmd-md.md": '---\nid: system-prmd-md\nname: Prompt file system prompt (.prmd / .md)\nversion: 1.0.0\ninherits: ./system-base.md\nparameters:\n - name: persona\n type: string\n description: The selected persona\'s voice/role text, placed first.\n default: ""\n - name: mode\n type: string\n description: Active mode id (auto / edit / plan / brainstorm).\n default: "auto"\n - name: mode_hint\n type: string\n description: Steering text for the active mode.\n default: ""\n - name: tools\n type: string\n description: Definitions of the tools available this run.\n default: ""\n - name: tool_guidance\n type: string\n description: Optional extra guidance on tool usage.\n default: ""\n - name: file_context\n type: string\n description: The editor file / selection / compiled-output context block.\n default: ""\n---\n\n{% include "../languages/prmd.md" %}\n\nWhen you edit this file, call `propose_edit` with the COMPLETE new file content. Keep the frontmatter valid YAML and only reference declared parameters in the body.\n',
|
|
16546
16684
|
"templates/index.json": '[\n {\n "_comment": "EXAMPLE of a data-driven New File type. Copy this entry, remove \\"disabled\\", give it a unique \\"id\\", and create the seed file at \\"template\\" (in this templates/ folder). Tokens __ID__ / __NAME__ are substituted on create. Icon is a ui-kit name (e.g. IcFileCode, IcUser, IcFlow) or \\"svg:<markup>\\". See docs/file-types.md.",\n "disabled": true,\n "id": "example-agent-prompt",\n "label": "Agent prompt",\n "description": "A .prmd tuned for tool-using agents.",\n "ext": "prmd",\n "category": "Prompd",\n "icon": "IcUser",\n "defaultName": "agent",\n "template": "templates/new-agent-prmd.prmd",\n "accent": true\n }\n]\n',
|
|
@@ -16963,6 +17101,10 @@ Notes you've saved. Call recall_memory to read one in full; save_memory to add o
|
|
|
16963
17101
|
|
|
16964
17102
|
${memoryIdx.trim()}` : "";
|
|
16965
17103
|
return compileConfigTemplate(systemPath, {
|
|
17104
|
+
// Who the agent says it IS. Injected rather than written into the prompt,
|
|
17105
|
+
// because the same shipped default is seeded into every host's config
|
|
17106
|
+
// workspace and each one carries a different product name.
|
|
17107
|
+
app: promptHost().appName?.() || "Prompd",
|
|
16966
17108
|
persona: persona.trim(),
|
|
16967
17109
|
mode,
|
|
16968
17110
|
mode_hint,
|
|
@@ -20235,13 +20377,23 @@ async function deviceLogin(opts) {
|
|
|
20235
20377
|
const f = opts.fetchImpl ?? fetch;
|
|
20236
20378
|
const base = opts.base.replace(/\/$/, "");
|
|
20237
20379
|
const post = async (path, body) => {
|
|
20238
|
-
const
|
|
20380
|
+
const url = `${base}${path}`;
|
|
20381
|
+
const res = await f(url, {
|
|
20239
20382
|
method: "POST",
|
|
20240
20383
|
headers: { "Content-Type": "application/json" },
|
|
20241
20384
|
body: JSON.stringify(body),
|
|
20242
20385
|
signal: opts.signal
|
|
20243
20386
|
});
|
|
20244
|
-
|
|
20387
|
+
const text = await res.text();
|
|
20388
|
+
try {
|
|
20389
|
+
return JSON.parse(text);
|
|
20390
|
+
} catch {
|
|
20391
|
+
const looksLikeHtml = /^\s*</.test(text);
|
|
20392
|
+
throw new Error(
|
|
20393
|
+
`${url} answered ${res.status} with ${looksLikeHtml ? "an HTML page" : "a non-JSON body"}, not JSON.` + (res.status === 404 ? `
|
|
20394
|
+
That usually means --base is wrong. The device endpoints live under /api \u2014 try --base ${base.replace(/\/api$/, "")}/api` : "")
|
|
20395
|
+
);
|
|
20396
|
+
}
|
|
20245
20397
|
};
|
|
20246
20398
|
const dc = await post("/oauth/device/code", { client_id: "corenel-cli", scope: "agent" });
|
|
20247
20399
|
if (!dc.device_code) throw new Error("device authorization failed");
|
|
@@ -20268,11 +20420,300 @@ async function deviceLogin(opts) {
|
|
|
20268
20420
|
}
|
|
20269
20421
|
}
|
|
20270
20422
|
|
|
20423
|
+
// ../crew/frontmatter.ts
|
|
20424
|
+
var import_yaml = __toESM(require_dist(), 1);
|
|
20425
|
+
var FRONTMATTER = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/;
|
|
20426
|
+
function parseFrontmatter2(text) {
|
|
20427
|
+
const m = text.match(FRONTMATTER);
|
|
20428
|
+
if (!m) return { meta: {}, body: text };
|
|
20429
|
+
let meta = {};
|
|
20430
|
+
try {
|
|
20431
|
+
const parsed = import_yaml.default.parse(m[1]);
|
|
20432
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
20433
|
+
meta = parsed;
|
|
20434
|
+
}
|
|
20435
|
+
} catch {
|
|
20436
|
+
meta = {};
|
|
20437
|
+
}
|
|
20438
|
+
return { meta, body: m[2] };
|
|
20439
|
+
}
|
|
20440
|
+
|
|
20441
|
+
// ../crew/policy.ts
|
|
20442
|
+
var import_yaml2 = __toESM(require_dist(), 1);
|
|
20443
|
+
var LEVELS = ["allow", "ask", "deny"];
|
|
20444
|
+
var UNATTENDED = ["deny", "park", "allow"];
|
|
20445
|
+
function asLevel(v) {
|
|
20446
|
+
return typeof v === "string" && LEVELS.includes(v) ? v : void 0;
|
|
20447
|
+
}
|
|
20448
|
+
function asStringArray(v) {
|
|
20449
|
+
if (!Array.isArray(v)) return void 0;
|
|
20450
|
+
const out = v.filter((x) => typeof x === "string");
|
|
20451
|
+
return out.length ? out : void 0;
|
|
20452
|
+
}
|
|
20453
|
+
function coercePermissions(v) {
|
|
20454
|
+
const out = {};
|
|
20455
|
+
if (v && typeof v === "object" && !Array.isArray(v)) {
|
|
20456
|
+
for (const [k, val] of Object.entries(v)) {
|
|
20457
|
+
const lvl = asLevel(val);
|
|
20458
|
+
if (lvl) out[k] = lvl;
|
|
20459
|
+
}
|
|
20460
|
+
}
|
|
20461
|
+
return out;
|
|
20462
|
+
}
|
|
20463
|
+
function parsePolicyYaml(text, agentName) {
|
|
20464
|
+
let raw = {};
|
|
20465
|
+
if (text.trim()) {
|
|
20466
|
+
try {
|
|
20467
|
+
const parsed = import_yaml2.default.parse(text);
|
|
20468
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
20469
|
+
raw = parsed;
|
|
20470
|
+
}
|
|
20471
|
+
} catch {
|
|
20472
|
+
raw = {};
|
|
20473
|
+
}
|
|
20474
|
+
}
|
|
20475
|
+
const toolsAllow = raw.tools && typeof raw.tools === "object" ? asStringArray(raw.tools.allow) : void 0;
|
|
20476
|
+
const toolsDeny = raw.tools && typeof raw.tools === "object" ? asStringArray(raw.tools.deny) : void 0;
|
|
20477
|
+
const rawUnattended = raw.unattended;
|
|
20478
|
+
const unattended = typeof rawUnattended === "string" && UNATTENDED.includes(rawUnattended) ? rawUnattended : "deny";
|
|
20479
|
+
const rawPark = raw.parkTimeoutMs;
|
|
20480
|
+
const parkTimeoutMs = typeof rawPark === "number" && Number.isFinite(rawPark) && rawPark > 0 ? rawPark : void 0;
|
|
20481
|
+
const policy = {
|
|
20482
|
+
version: 1,
|
|
20483
|
+
name: typeof raw.name === "string" ? raw.name : `crew:${agentName}`,
|
|
20484
|
+
description: typeof raw.description === "string" ? raw.description : void 0,
|
|
20485
|
+
onViolation: raw.onViolation === "warn" ? "warn" : "stop",
|
|
20486
|
+
defaultPermission: asLevel(raw.defaultPermission) ?? "ask",
|
|
20487
|
+
mutatingDefault: asLevel(raw.mutatingDefault) ?? "deny",
|
|
20488
|
+
permissions: coercePermissions(raw.permissions),
|
|
20489
|
+
maxTurns: typeof raw.maxTurns === "number" ? raw.maxTurns : void 0,
|
|
20490
|
+
maxToolCalls: typeof raw.maxToolCalls === "number" ? raw.maxToolCalls : void 0,
|
|
20491
|
+
unattended,
|
|
20492
|
+
parkTimeoutMs
|
|
20493
|
+
};
|
|
20494
|
+
if (toolsAllow || toolsDeny) {
|
|
20495
|
+
policy.tools = { ...toolsAllow ? { allow: toolsAllow } : {}, ...toolsDeny ? { deny: toolsDeny } : {} };
|
|
20496
|
+
}
|
|
20497
|
+
return policy;
|
|
20498
|
+
}
|
|
20499
|
+
|
|
20500
|
+
// ../crew/paths.ts
|
|
20501
|
+
var CREW_SEG = "crew";
|
|
20502
|
+
var NAME_RE = /^[A-Za-z0-9][A-Za-z0-9_-]*$/;
|
|
20503
|
+
function isValidAgentName(name) {
|
|
20504
|
+
return NAME_RE.test(name);
|
|
20505
|
+
}
|
|
20506
|
+
|
|
20507
|
+
// ../crew/store.ts
|
|
20508
|
+
var import_yaml3 = __toESM(require_dist(), 1);
|
|
20509
|
+
var TRIGGER_TYPES = [
|
|
20510
|
+
"manual",
|
|
20511
|
+
"file-change",
|
|
20512
|
+
"run-complete",
|
|
20513
|
+
"interval-while-open",
|
|
20514
|
+
"app-init",
|
|
20515
|
+
"workspace-init",
|
|
20516
|
+
"schedule",
|
|
20517
|
+
"continuous",
|
|
20518
|
+
"self-directed",
|
|
20519
|
+
"external-webhook"
|
|
20520
|
+
];
|
|
20521
|
+
async function readOr(files, path, fallback = "") {
|
|
20522
|
+
try {
|
|
20523
|
+
return await files.read(path);
|
|
20524
|
+
} catch {
|
|
20525
|
+
return fallback;
|
|
20526
|
+
}
|
|
20527
|
+
}
|
|
20528
|
+
function parseTriggers(meta) {
|
|
20529
|
+
const raw = meta.triggers;
|
|
20530
|
+
if (!Array.isArray(raw)) return [];
|
|
20531
|
+
const out = [];
|
|
20532
|
+
for (const item of raw) {
|
|
20533
|
+
if (item && typeof item === "object") {
|
|
20534
|
+
const t = item.type;
|
|
20535
|
+
if (typeof t === "string" && TRIGGER_TYPES.includes(t)) {
|
|
20536
|
+
const cfg = item.config;
|
|
20537
|
+
out.push({
|
|
20538
|
+
type: t,
|
|
20539
|
+
config: cfg && typeof cfg === "object" && !Array.isArray(cfg) ? cfg : void 0
|
|
20540
|
+
});
|
|
20541
|
+
}
|
|
20542
|
+
}
|
|
20543
|
+
}
|
|
20544
|
+
return out;
|
|
20545
|
+
}
|
|
20546
|
+
function parseBudget(meta) {
|
|
20547
|
+
const raw = meta.budget;
|
|
20548
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
|
|
20549
|
+
const o = raw;
|
|
20550
|
+
const out = {};
|
|
20551
|
+
for (const k of ["maxUsd", "maxTokens", "maxMs"]) {
|
|
20552
|
+
const v = o[k];
|
|
20553
|
+
if (typeof v === "number" && v > 0) out[k] = v;
|
|
20554
|
+
}
|
|
20555
|
+
return out;
|
|
20556
|
+
}
|
|
20557
|
+
function parseCanCall(meta) {
|
|
20558
|
+
const raw = meta.canCall;
|
|
20559
|
+
if (!Array.isArray(raw)) return [];
|
|
20560
|
+
return raw.filter((x) => typeof x === "string" && isValidAgentName(x));
|
|
20561
|
+
}
|
|
20562
|
+
function parseSettings(text) {
|
|
20563
|
+
try {
|
|
20564
|
+
const raw = JSON.parse(text);
|
|
20565
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
20566
|
+
const o = raw;
|
|
20567
|
+
return {
|
|
20568
|
+
model: typeof o.model === "string" ? o.model : void 0,
|
|
20569
|
+
temperature: typeof o.temperature === "number" ? o.temperature : void 0
|
|
20570
|
+
};
|
|
20571
|
+
}
|
|
20572
|
+
} catch {
|
|
20573
|
+
}
|
|
20574
|
+
return {};
|
|
20575
|
+
}
|
|
20576
|
+
async function loadCrewAgentAt(files, root, name, scope = "workspace") {
|
|
20577
|
+
if (!isValidAgentName(name)) throw new Error(`invalid crew agent name: ${name}`);
|
|
20578
|
+
const dir = `${root}/${name}`;
|
|
20579
|
+
const { meta, body } = parseFrontmatter2(await readOr(files, `${dir}/AGENT.md`));
|
|
20580
|
+
return {
|
|
20581
|
+
name,
|
|
20582
|
+
jobTitle: typeof meta.jobTitle === "string" ? meta.jobTitle : "",
|
|
20583
|
+
description: typeof meta.description === "string" ? meta.description : "",
|
|
20584
|
+
scope,
|
|
20585
|
+
enabled: meta.enabled !== false,
|
|
20586
|
+
// absent/anything-but-false -> enabled
|
|
20587
|
+
triggers: parseTriggers(meta),
|
|
20588
|
+
instructions: body,
|
|
20589
|
+
soul: await readOr(files, `${dir}/SOUL.md`),
|
|
20590
|
+
persona: await readOr(files, `${dir}/PERSONA.md`),
|
|
20591
|
+
policy: parsePolicyYaml(await readOr(files, `${dir}/POLICY.yaml`), name),
|
|
20592
|
+
settings: parseSettings(await readOr(files, `${dir}/settings.json`, "{}")),
|
|
20593
|
+
budget: parseBudget(meta),
|
|
20594
|
+
canCall: parseCanCall(meta)
|
|
20595
|
+
};
|
|
20596
|
+
}
|
|
20597
|
+
async function loadCrewAgentAtIfExists(files, root, name, scope = "workspace") {
|
|
20598
|
+
if (!isValidAgentName(name)) return null;
|
|
20599
|
+
try {
|
|
20600
|
+
const st = await files.stat(`${root}/${name}/AGENT.md`);
|
|
20601
|
+
if (st?.kind !== "file") return null;
|
|
20602
|
+
return await loadCrewAgentAt(files, root, name, scope);
|
|
20603
|
+
} catch {
|
|
20604
|
+
return null;
|
|
20605
|
+
}
|
|
20606
|
+
}
|
|
20607
|
+
|
|
20608
|
+
// ../harness/guardrail/serialize.ts
|
|
20609
|
+
var import_yaml4 = __toESM(require_dist(), 1);
|
|
20610
|
+
|
|
20611
|
+
// ../crew/runtime.ts
|
|
20612
|
+
function buildSystemExtra(def) {
|
|
20613
|
+
const parts = [];
|
|
20614
|
+
if (def.jobTitle?.trim()) parts.push(`--- Role ---
|
|
20615
|
+
${def.jobTitle.trim()}`);
|
|
20616
|
+
if (def.soul.trim()) parts.push(`--- Soul ---
|
|
20617
|
+
${def.soul.trim()}`);
|
|
20618
|
+
if (def.persona.trim()) parts.push(`--- Persona ---
|
|
20619
|
+
${def.persona.trim()}`);
|
|
20620
|
+
if (def.instructions.trim()) parts.push(`--- Instructions ---
|
|
20621
|
+
${def.instructions.trim()}`);
|
|
20622
|
+
return parts.join("\n\n");
|
|
20623
|
+
}
|
|
20624
|
+
|
|
20625
|
+
// src/runAgent.ts
|
|
20626
|
+
function workspaceStateDir() {
|
|
20627
|
+
const fromEnv = process.env.CORENEL_STATE_DIR;
|
|
20628
|
+
return fromEnv && /^\.[A-Za-z0-9][A-Za-z0-9._-]*$/.test(fromEnv) ? fromEnv : stateDirName();
|
|
20629
|
+
}
|
|
20630
|
+
function eventLine(e) {
|
|
20631
|
+
try {
|
|
20632
|
+
return JSON.stringify(e);
|
|
20633
|
+
} catch {
|
|
20634
|
+
const type = e.type;
|
|
20635
|
+
return JSON.stringify({ type: typeof type === "string" ? type : "unknown", unserializable: true });
|
|
20636
|
+
}
|
|
20637
|
+
}
|
|
20638
|
+
async function runCrewAgentCli(opts) {
|
|
20639
|
+
const files = new NodeFileService(opts.cwd);
|
|
20640
|
+
const root = `${workspaceStateDir()}/${CREW_SEG}`;
|
|
20641
|
+
const def = await loadCrewAgentAtIfExists(files, root, opts.agent, "workspace");
|
|
20642
|
+
if (!def) {
|
|
20643
|
+
opts.warn(`no such agent "${opts.agent}" under ${opts.cwd}/${root}`);
|
|
20644
|
+
return 2;
|
|
20645
|
+
}
|
|
20646
|
+
if (!def.enabled) {
|
|
20647
|
+
opts.warn(`agent "${opts.agent}" is disabled; enable it before running`);
|
|
20648
|
+
return 2;
|
|
20649
|
+
}
|
|
20650
|
+
setGatewayBase(opts.base ?? process.env.CORENEL_API_BASE ?? "https://api.corenel.ai/api");
|
|
20651
|
+
const token = await nodeAuthToken().getToken();
|
|
20652
|
+
if (!token) {
|
|
20653
|
+
opts.warn("not signed in: set CORENEL_TOKEN, or run `corenel login` on this machine");
|
|
20654
|
+
return 2;
|
|
20655
|
+
}
|
|
20656
|
+
registerGuard(tokenGuard(() => token));
|
|
20657
|
+
const tools = allTools();
|
|
20658
|
+
const extra = buildSystemExtra(def);
|
|
20659
|
+
let system = extra;
|
|
20660
|
+
try {
|
|
20661
|
+
const base = await composeAgentSystem({
|
|
20662
|
+
mode: "auto",
|
|
20663
|
+
tools: tools.map((t) => ({ name: t.name, description: t.description }))
|
|
20664
|
+
});
|
|
20665
|
+
system = extra ? `${base}
|
|
20666
|
+
|
|
20667
|
+
${extra}` : base;
|
|
20668
|
+
} catch {
|
|
20669
|
+
}
|
|
20670
|
+
const realConsole = { log: console.log, info: console.info, warn: console.warn, debug: console.debug };
|
|
20671
|
+
const toStderr = (...parts) => {
|
|
20672
|
+
opts.warn(parts.map((x) => typeof x === "string" ? x : JSON.stringify(x)).join(" "));
|
|
20673
|
+
};
|
|
20674
|
+
console.log = toStderr;
|
|
20675
|
+
console.info = toStderr;
|
|
20676
|
+
console.warn = toStderr;
|
|
20677
|
+
console.debug = toStderr;
|
|
20678
|
+
const ac = new AbortController();
|
|
20679
|
+
try {
|
|
20680
|
+
const result = await runAgent({
|
|
20681
|
+
client: createChatClient({ getToken: async () => token }),
|
|
20682
|
+
model: opts.model ?? def.settings.model ?? "gpt-4o-mini",
|
|
20683
|
+
system,
|
|
20684
|
+
messages: [{ role: "user", content: opts.input }],
|
|
20685
|
+
tools,
|
|
20686
|
+
toolCtx: nodeToolCtx(ac.signal, { files }),
|
|
20687
|
+
policy: def.policy,
|
|
20688
|
+
signal: ac.signal,
|
|
20689
|
+
onEvent: (e) => opts.emit(eventLine(e))
|
|
20690
|
+
});
|
|
20691
|
+
opts.emit(eventLine({ type: "done", text: result.text }));
|
|
20692
|
+
return 0;
|
|
20693
|
+
} catch (e) {
|
|
20694
|
+
opts.warn(`run failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
20695
|
+
return 1;
|
|
20696
|
+
} finally {
|
|
20697
|
+
Object.assign(console, realConsole);
|
|
20698
|
+
}
|
|
20699
|
+
}
|
|
20700
|
+
|
|
20271
20701
|
// src/cli.ts
|
|
20272
20702
|
function flag(argv, name, fallback) {
|
|
20273
20703
|
const i = argv.indexOf(`--${name}`);
|
|
20274
20704
|
return i >= 0 && argv[i + 1] ? argv[i + 1] : fallback;
|
|
20275
20705
|
}
|
|
20706
|
+
function positional(argv) {
|
|
20707
|
+
const out = [];
|
|
20708
|
+
for (let i = 0; i < argv.length; i++) {
|
|
20709
|
+
if (argv[i].startsWith("--")) {
|
|
20710
|
+
i++;
|
|
20711
|
+
continue;
|
|
20712
|
+
}
|
|
20713
|
+
out.push(argv[i]);
|
|
20714
|
+
}
|
|
20715
|
+
return out;
|
|
20716
|
+
}
|
|
20276
20717
|
function promptOf(argv) {
|
|
20277
20718
|
const parts = [];
|
|
20278
20719
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -20323,8 +20764,28 @@ async function main() {
|
|
|
20323
20764
|
case "run":
|
|
20324
20765
|
await run(rest);
|
|
20325
20766
|
break;
|
|
20767
|
+
case "run-agent": {
|
|
20768
|
+
const agent = positional(rest)[0];
|
|
20769
|
+
if (!agent) {
|
|
20770
|
+
process.stderr.write('usage: corenel run-agent <name> --input "<text>" [--model M] [--base URL]\n');
|
|
20771
|
+
process.exit(2);
|
|
20772
|
+
}
|
|
20773
|
+
const code = await runCrewAgentCli({
|
|
20774
|
+
cwd: process.cwd(),
|
|
20775
|
+
agent,
|
|
20776
|
+
input: flag(rest, "input", ""),
|
|
20777
|
+
...rest.includes("--model") ? { model: flag(rest, "model", "") } : {},
|
|
20778
|
+
...rest.includes("--base") ? { base: flag(rest, "base", "") } : {},
|
|
20779
|
+
emit: (line) => process.stdout.write(`${line}
|
|
20780
|
+
`),
|
|
20781
|
+
warn: (line) => process.stderr.write(`corenel: ${line}
|
|
20782
|
+
`)
|
|
20783
|
+
});
|
|
20784
|
+
process.exitCode = code;
|
|
20785
|
+
break;
|
|
20786
|
+
}
|
|
20326
20787
|
case "login": {
|
|
20327
|
-
const base = flag(rest, "base", process.env.CORENEL_API_BASE || "https://api.corenel.ai");
|
|
20788
|
+
const base = flag(rest, "base", process.env.CORENEL_API_BASE || "https://api.corenel.ai/api");
|
|
20328
20789
|
await deviceLogin({ base, store: writeAuthToken });
|
|
20329
20790
|
process.stdout.write(`
|
|
20330
20791
|
Logged in. Token saved to ${authTokenPath()}
|
|
@@ -20337,6 +20798,7 @@ Logged in. Token saved to ${authTokenPath()}
|
|
|
20337
20798
|
"",
|
|
20338
20799
|
" corenel login [--base URL] OAuth device flow -> ~/.corenel/token",
|
|
20339
20800
|
' corenel run "<prompt>" [--model M] [--base URL] one-shot turn (needs a login or CORENEL_TOKEN)',
|
|
20801
|
+
' corenel run-agent <name> --input "<text>" run a crew agent; events as JSON Lines on stdout',
|
|
20340
20802
|
"",
|
|
20341
20803
|
" (ask/chat + start --sidecar to follow.)",
|
|
20342
20804
|
""
|
|
@@ -20352,5 +20814,7 @@ function friendlyError(msg) {
|
|
|
20352
20814
|
main().catch((e) => {
|
|
20353
20815
|
process.stderr.write(`corenel: ${friendlyError(e instanceof Error ? e.message : String(e))}
|
|
20354
20816
|
`);
|
|
20355
|
-
process.
|
|
20817
|
+
process.exitCode = 1;
|
|
20818
|
+
const bail = setTimeout(() => process.exit(1), 2e3);
|
|
20819
|
+
bail.unref();
|
|
20356
20820
|
});
|
package/package.json
CHANGED
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corenel/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
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": {
|
|
7
7
|
"corenel": "dist/cli.js"
|
|
8
8
|
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"typecheck": "tsc --noEmit",
|
|
11
|
+
"start": "tsx src/cli.ts",
|
|
12
|
+
"verify": "tsx src/verify.ts",
|
|
13
|
+
"build": "node build.mjs",
|
|
14
|
+
"prepublishOnly": "node build.mjs"
|
|
15
|
+
},
|
|
9
16
|
"dependencies": {
|
|
10
17
|
"openai": "^4.77.0"
|
|
11
18
|
},
|
|
12
19
|
"devDependencies": {
|
|
20
|
+
"@corenel/crew": "workspace:*",
|
|
21
|
+
"@corenel/harness": "workspace:*",
|
|
22
|
+
"@corenel/protocol": "workspace:*",
|
|
23
|
+
"@corenel/tools-node": "workspace:*",
|
|
13
24
|
"esbuild": "^0.21.5",
|
|
14
25
|
"@types/node": "^24.13.1",
|
|
15
26
|
"tsx": "^4.19.2",
|
|
16
|
-
"typescript": "^5.9.3"
|
|
17
|
-
"@corenel/harness": "0.2.0",
|
|
18
|
-
"@corenel/tools-node": "0.2.0",
|
|
19
|
-
"@corenel/protocol": "0.2.0"
|
|
27
|
+
"typescript": "^5.9.3"
|
|
20
28
|
},
|
|
21
29
|
"publishConfig": {
|
|
22
30
|
"access": "public"
|
|
@@ -28,11 +36,5 @@
|
|
|
28
36
|
],
|
|
29
37
|
"engines": {
|
|
30
38
|
"node": ">=18"
|
|
31
|
-
},
|
|
32
|
-
"scripts": {
|
|
33
|
-
"typecheck": "tsc --noEmit",
|
|
34
|
-
"start": "tsx src/cli.ts",
|
|
35
|
-
"verify": "tsx src/verify.ts",
|
|
36
|
-
"build": "node build.mjs"
|
|
37
39
|
}
|
|
38
|
-
}
|
|
40
|
+
}
|