@rosthq/cli 0.7.68 → 0.7.69
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/generated/command-manifest.d.ts.map +1 -1
- package/dist/generator/flags.d.ts.map +1 -1
- package/dist/generator/groups.d.ts.map +1 -1
- package/dist/index.js +343 -158
- package/dist/index.js.map +4 -4
- package/dist/update-check.d.ts +11 -1
- package/dist/update-check.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -472,13 +472,13 @@ function __disposeResources(env) {
|
|
|
472
472
|
}
|
|
473
473
|
return next();
|
|
474
474
|
}
|
|
475
|
-
function __rewriteRelativeImportExtension(
|
|
476
|
-
if (typeof
|
|
477
|
-
return
|
|
475
|
+
function __rewriteRelativeImportExtension(path8, preserveJsx) {
|
|
476
|
+
if (typeof path8 === "string" && /^\.\.?\//.test(path8)) {
|
|
477
|
+
return path8.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
|
|
478
478
|
return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
|
|
479
479
|
});
|
|
480
480
|
}
|
|
481
|
-
return
|
|
481
|
+
return path8;
|
|
482
482
|
}
|
|
483
483
|
var extendStatics, __assign, __createBinding, __setModuleDefault, ownKeys, _SuppressedError, tslib_es6_default;
|
|
484
484
|
var init_tslib_es6 = __esm({
|
|
@@ -14027,10 +14027,10 @@ function mergeDefs(...defs) {
|
|
|
14027
14027
|
function cloneDef(schema) {
|
|
14028
14028
|
return mergeDefs(schema._zod.def);
|
|
14029
14029
|
}
|
|
14030
|
-
function getElementAtPath(obj,
|
|
14031
|
-
if (!
|
|
14030
|
+
function getElementAtPath(obj, path8) {
|
|
14031
|
+
if (!path8)
|
|
14032
14032
|
return obj;
|
|
14033
|
-
return
|
|
14033
|
+
return path8.reduce((acc, key) => acc?.[key], obj);
|
|
14034
14034
|
}
|
|
14035
14035
|
function promiseAllObject(promisesObj) {
|
|
14036
14036
|
const keys = Object.keys(promisesObj);
|
|
@@ -14439,11 +14439,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
14439
14439
|
}
|
|
14440
14440
|
return false;
|
|
14441
14441
|
}
|
|
14442
|
-
function prefixIssues(
|
|
14442
|
+
function prefixIssues(path8, issues) {
|
|
14443
14443
|
return issues.map((iss) => {
|
|
14444
14444
|
var _a3;
|
|
14445
14445
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
14446
|
-
iss.path.unshift(
|
|
14446
|
+
iss.path.unshift(path8);
|
|
14447
14447
|
return iss;
|
|
14448
14448
|
});
|
|
14449
14449
|
}
|
|
@@ -14590,16 +14590,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
14590
14590
|
}
|
|
14591
14591
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
14592
14592
|
const fieldErrors = { _errors: [] };
|
|
14593
|
-
const processError = (error52,
|
|
14593
|
+
const processError = (error52, path8 = []) => {
|
|
14594
14594
|
for (const issue2 of error52.issues) {
|
|
14595
14595
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
14596
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
14596
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
14597
14597
|
} else if (issue2.code === "invalid_key") {
|
|
14598
|
-
processError({ issues: issue2.issues }, [...
|
|
14598
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14599
14599
|
} else if (issue2.code === "invalid_element") {
|
|
14600
|
-
processError({ issues: issue2.issues }, [...
|
|
14600
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14601
14601
|
} else {
|
|
14602
|
-
const fullpath = [...
|
|
14602
|
+
const fullpath = [...path8, ...issue2.path];
|
|
14603
14603
|
if (fullpath.length === 0) {
|
|
14604
14604
|
fieldErrors._errors.push(mapper(issue2));
|
|
14605
14605
|
} else {
|
|
@@ -14626,17 +14626,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
14626
14626
|
}
|
|
14627
14627
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
14628
14628
|
const result = { errors: [] };
|
|
14629
|
-
const processError = (error52,
|
|
14629
|
+
const processError = (error52, path8 = []) => {
|
|
14630
14630
|
var _a3, _b;
|
|
14631
14631
|
for (const issue2 of error52.issues) {
|
|
14632
14632
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
14633
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
14633
|
+
issue2.errors.map((issues) => processError({ issues }, [...path8, ...issue2.path]));
|
|
14634
14634
|
} else if (issue2.code === "invalid_key") {
|
|
14635
|
-
processError({ issues: issue2.issues }, [...
|
|
14635
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14636
14636
|
} else if (issue2.code === "invalid_element") {
|
|
14637
|
-
processError({ issues: issue2.issues }, [...
|
|
14637
|
+
processError({ issues: issue2.issues }, [...path8, ...issue2.path]);
|
|
14638
14638
|
} else {
|
|
14639
|
-
const fullpath = [...
|
|
14639
|
+
const fullpath = [...path8, ...issue2.path];
|
|
14640
14640
|
if (fullpath.length === 0) {
|
|
14641
14641
|
result.errors.push(mapper(issue2));
|
|
14642
14642
|
continue;
|
|
@@ -14668,8 +14668,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
14668
14668
|
}
|
|
14669
14669
|
function toDotPath(_path) {
|
|
14670
14670
|
const segs = [];
|
|
14671
|
-
const
|
|
14672
|
-
for (const seg of
|
|
14671
|
+
const path8 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
14672
|
+
for (const seg of path8) {
|
|
14673
14673
|
if (typeof seg === "number")
|
|
14674
14674
|
segs.push(`[${seg}]`);
|
|
14675
14675
|
else if (typeof seg === "symbol")
|
|
@@ -27361,13 +27361,13 @@ function resolveRef(ref, ctx) {
|
|
|
27361
27361
|
if (!ref.startsWith("#")) {
|
|
27362
27362
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
27363
27363
|
}
|
|
27364
|
-
const
|
|
27365
|
-
if (
|
|
27364
|
+
const path8 = ref.slice(1).split("/").filter(Boolean);
|
|
27365
|
+
if (path8.length === 0) {
|
|
27366
27366
|
return ctx.rootSchema;
|
|
27367
27367
|
}
|
|
27368
27368
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
27369
|
-
if (
|
|
27370
|
-
const key =
|
|
27369
|
+
if (path8[0] === defsKey) {
|
|
27370
|
+
const key = path8[1];
|
|
27371
27371
|
if (!key || !ctx.defs[key]) {
|
|
27372
27372
|
throw new Error(`Reference not found: ${ref}`);
|
|
27373
27373
|
}
|
|
@@ -27829,7 +27829,7 @@ var CommandClient = class {
|
|
|
27829
27829
|
this.fetchImpl = options.fetchImpl ?? fetch;
|
|
27830
27830
|
}
|
|
27831
27831
|
async execute(commandId, body = {}, options = {}) {
|
|
27832
|
-
const
|
|
27832
|
+
const path8 = `/api/commands/${encodeURIComponent(commandId)}`;
|
|
27833
27833
|
const headers = {
|
|
27834
27834
|
authorization: `Bearer ${this.token}`,
|
|
27835
27835
|
"content-type": "application/json"
|
|
@@ -27837,7 +27837,7 @@ var CommandClient = class {
|
|
|
27837
27837
|
if (options.targetSeatId !== void 0 && options.targetSeatId.length > 0) {
|
|
27838
27838
|
headers["x-rost-seat"] = options.targetSeatId;
|
|
27839
27839
|
}
|
|
27840
|
-
const response = await this.fetchImpl(`${this.appUrl}${
|
|
27840
|
+
const response = await this.fetchImpl(`${this.appUrl}${path8}`, {
|
|
27841
27841
|
method: "POST",
|
|
27842
27842
|
headers,
|
|
27843
27843
|
body: JSON.stringify(body)
|
|
@@ -27850,7 +27850,7 @@ var CommandClient = class {
|
|
|
27850
27850
|
const snippet = redactSecrets(text.replace(/\s+/g, " ").trim()).slice(0, 200);
|
|
27851
27851
|
throw new CommandClientError(
|
|
27852
27852
|
response.status,
|
|
27853
|
-
`server returned HTTP ${response.status} (non-JSON) from ${
|
|
27853
|
+
`server returned HTTP ${response.status} (non-JSON) from ${path8}` + (snippet ? ` \u2014 ${snippet}` : "") + " \u2014 the deployment may be unhealthy"
|
|
27854
27854
|
);
|
|
27855
27855
|
}
|
|
27856
27856
|
const parsed = commandResponseSchema.parse(raw);
|
|
@@ -33181,8 +33181,8 @@ var IcebergError = class extends Error {
|
|
|
33181
33181
|
return this.status === 419;
|
|
33182
33182
|
}
|
|
33183
33183
|
};
|
|
33184
|
-
function buildUrl(baseUrl,
|
|
33185
|
-
const url2 = new URL(
|
|
33184
|
+
function buildUrl(baseUrl, path8, query) {
|
|
33185
|
+
const url2 = new URL(path8, baseUrl);
|
|
33186
33186
|
if (query) {
|
|
33187
33187
|
for (const [key, value] of Object.entries(query)) {
|
|
33188
33188
|
if (value !== void 0) {
|
|
@@ -33212,12 +33212,12 @@ function createFetchClient(options) {
|
|
|
33212
33212
|
return {
|
|
33213
33213
|
async request({
|
|
33214
33214
|
method,
|
|
33215
|
-
path:
|
|
33215
|
+
path: path8,
|
|
33216
33216
|
query,
|
|
33217
33217
|
body,
|
|
33218
33218
|
headers
|
|
33219
33219
|
}) {
|
|
33220
|
-
const url2 = buildUrl(options.baseUrl,
|
|
33220
|
+
const url2 = buildUrl(options.baseUrl, path8, query);
|
|
33221
33221
|
const authHeaders = await buildAuthHeaders(options.auth);
|
|
33222
33222
|
const res = await fetchFn(url2, {
|
|
33223
33223
|
method,
|
|
@@ -34079,7 +34079,7 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34079
34079
|
* @param path The relative file path. Should be of the format `folder/subfolder/filename.png`. The bucket must already exist before attempting to upload.
|
|
34080
34080
|
* @param fileBody The body of the file to be stored in the bucket.
|
|
34081
34081
|
*/
|
|
34082
|
-
async uploadOrUpdate(method,
|
|
34082
|
+
async uploadOrUpdate(method, path8, fileBody, fileOptions) {
|
|
34083
34083
|
var _this = this;
|
|
34084
34084
|
return _this.handleOperation(async () => {
|
|
34085
34085
|
let body;
|
|
@@ -34103,7 +34103,7 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34103
34103
|
if ((typeof ReadableStream !== "undefined" && body instanceof ReadableStream || body && typeof body === "object" && "pipe" in body && typeof body.pipe === "function") && !options.duplex) options.duplex = "half";
|
|
34104
34104
|
}
|
|
34105
34105
|
if (fileOptions === null || fileOptions === void 0 ? void 0 : fileOptions.headers) for (const [key, value] of Object.entries(fileOptions.headers)) headers = setHeader(headers, key, value);
|
|
34106
|
-
const cleanPath = _this._removeEmptyFolders(
|
|
34106
|
+
const cleanPath = _this._removeEmptyFolders(path8);
|
|
34107
34107
|
const _path = _this._getFinalPath(cleanPath);
|
|
34108
34108
|
const data = await (method == "PUT" ? put : post)(_this.fetch, `${_this.url}/object/${_path}`, body, _objectSpread22({ headers }, (options === null || options === void 0 ? void 0 : options.duplex) ? { duplex: options.duplex } : {}));
|
|
34109
34109
|
return {
|
|
@@ -34180,8 +34180,8 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34180
34180
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34181
34181
|
* - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Upload file using `ArrayBuffer` from base64 file data instead, see example below.
|
|
34182
34182
|
*/
|
|
34183
|
-
async upload(
|
|
34184
|
-
return this.uploadOrUpdate("POST",
|
|
34183
|
+
async upload(path8, fileBody, fileOptions) {
|
|
34184
|
+
return this.uploadOrUpdate("POST", path8, fileBody, fileOptions);
|
|
34185
34185
|
}
|
|
34186
34186
|
/**
|
|
34187
34187
|
* Upload a file with a token generated from `createSignedUploadUrl`.
|
|
@@ -34221,9 +34221,9 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34221
34221
|
* - `objects` table permissions: none
|
|
34222
34222
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34223
34223
|
*/
|
|
34224
|
-
async uploadToSignedUrl(
|
|
34224
|
+
async uploadToSignedUrl(path8, token, fileBody, fileOptions) {
|
|
34225
34225
|
var _this3 = this;
|
|
34226
|
-
const cleanPath = _this3._removeEmptyFolders(
|
|
34226
|
+
const cleanPath = _this3._removeEmptyFolders(path8);
|
|
34227
34227
|
const _path = _this3._getFinalPath(cleanPath);
|
|
34228
34228
|
const url2 = new URL(_this3.url + `/object/upload/sign/${_path}`);
|
|
34229
34229
|
url2.searchParams.set("token", token);
|
|
@@ -34292,10 +34292,10 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34292
34292
|
* - `objects` table permissions: `insert`
|
|
34293
34293
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34294
34294
|
*/
|
|
34295
|
-
async createSignedUploadUrl(
|
|
34295
|
+
async createSignedUploadUrl(path8, options) {
|
|
34296
34296
|
var _this4 = this;
|
|
34297
34297
|
return _this4.handleOperation(async () => {
|
|
34298
|
-
let _path = _this4._getFinalPath(
|
|
34298
|
+
let _path = _this4._getFinalPath(path8);
|
|
34299
34299
|
const headers = _objectSpread22({}, _this4.headers);
|
|
34300
34300
|
if (options === null || options === void 0 ? void 0 : options.upsert) headers["x-upsert"] = "true";
|
|
34301
34301
|
const data = await post(_this4.fetch, `${_this4.url}/object/upload/sign/${_path}`, {}, { headers });
|
|
@@ -34304,7 +34304,7 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34304
34304
|
if (!token) throw new StorageError("No token returned by API");
|
|
34305
34305
|
return {
|
|
34306
34306
|
signedUrl: url2.toString(),
|
|
34307
|
-
path:
|
|
34307
|
+
path: path8,
|
|
34308
34308
|
token
|
|
34309
34309
|
};
|
|
34310
34310
|
});
|
|
@@ -34364,8 +34364,8 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34364
34364
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34365
34365
|
* - For React Native, using either `Blob`, `File` or `FormData` does not work as intended. Update file using `ArrayBuffer` from base64 file data instead, see example below.
|
|
34366
34366
|
*/
|
|
34367
|
-
async update(
|
|
34368
|
-
return this.uploadOrUpdate("PUT",
|
|
34367
|
+
async update(path8, fileBody, fileOptions) {
|
|
34368
|
+
return this.uploadOrUpdate("PUT", path8, fileBody, fileOptions);
|
|
34369
34369
|
}
|
|
34370
34370
|
/**
|
|
34371
34371
|
* Moves an existing file to a new path in the same bucket.
|
|
@@ -34516,10 +34516,10 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34516
34516
|
* - `objects` table permissions: `select`
|
|
34517
34517
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34518
34518
|
*/
|
|
34519
|
-
async createSignedUrl(
|
|
34519
|
+
async createSignedUrl(path8, expiresIn, options) {
|
|
34520
34520
|
var _this8 = this;
|
|
34521
34521
|
return _this8.handleOperation(async () => {
|
|
34522
|
-
let _path = _this8._getFinalPath(
|
|
34522
|
+
let _path = _this8._getFinalPath(path8);
|
|
34523
34523
|
const hasTransform = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0;
|
|
34524
34524
|
let data = await post(_this8.fetch, `${_this8.url}/object/sign/${_path}`, _objectSpread22({ expiresIn }, hasTransform ? { transform: options.transform } : {}), { headers: _this8.headers });
|
|
34525
34525
|
const query = new URLSearchParams();
|
|
@@ -34655,13 +34655,13 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34655
34655
|
* - `objects` table permissions: `select`
|
|
34656
34656
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34657
34657
|
*/
|
|
34658
|
-
download(
|
|
34658
|
+
download(path8, options, parameters) {
|
|
34659
34659
|
const renderPath = typeof (options === null || options === void 0 ? void 0 : options.transform) === "object" && options.transform !== null && Object.keys(options.transform).length > 0 ? "render/image/authenticated" : "object";
|
|
34660
34660
|
const query = new URLSearchParams();
|
|
34661
34661
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
34662
34662
|
if ((options === null || options === void 0 ? void 0 : options.cacheNonce) != null) query.set("cacheNonce", String(options.cacheNonce));
|
|
34663
34663
|
const queryString = query.toString();
|
|
34664
|
-
const _path = this._getFinalPath(
|
|
34664
|
+
const _path = this._getFinalPath(path8);
|
|
34665
34665
|
const downloadFn = () => get(this.fetch, `${this.url}/${renderPath}/${_path}${queryString ? `?${queryString}` : ""}`, {
|
|
34666
34666
|
headers: this.headers,
|
|
34667
34667
|
noResolveJson: true
|
|
@@ -34692,9 +34692,9 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34692
34692
|
* }
|
|
34693
34693
|
* ```
|
|
34694
34694
|
*/
|
|
34695
|
-
async info(
|
|
34695
|
+
async info(path8) {
|
|
34696
34696
|
var _this10 = this;
|
|
34697
|
-
const _path = _this10._getFinalPath(
|
|
34697
|
+
const _path = _this10._getFinalPath(path8);
|
|
34698
34698
|
return _this10.handleOperation(async () => {
|
|
34699
34699
|
return recursiveToCamel(await get(_this10.fetch, `${_this10.url}/object/info/${_path}`, { headers: _this10.headers }));
|
|
34700
34700
|
});
|
|
@@ -34715,9 +34715,9 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34715
34715
|
* .exists('folder/avatar1.png')
|
|
34716
34716
|
* ```
|
|
34717
34717
|
*/
|
|
34718
|
-
async exists(
|
|
34718
|
+
async exists(path8) {
|
|
34719
34719
|
var _this11 = this;
|
|
34720
|
-
const _path = _this11._getFinalPath(
|
|
34720
|
+
const _path = _this11._getFinalPath(path8);
|
|
34721
34721
|
try {
|
|
34722
34722
|
await head(_this11.fetch, `${_this11.url}/object/${_path}`, { headers: _this11.headers });
|
|
34723
34723
|
return {
|
|
@@ -34796,8 +34796,8 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34796
34796
|
* - `objects` table permissions: none
|
|
34797
34797
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34798
34798
|
*/
|
|
34799
|
-
getPublicUrl(
|
|
34800
|
-
const _path = this._getFinalPath(
|
|
34799
|
+
getPublicUrl(path8, options) {
|
|
34800
|
+
const _path = this._getFinalPath(path8);
|
|
34801
34801
|
const query = new URLSearchParams();
|
|
34802
34802
|
if (options === null || options === void 0 ? void 0 : options.download) query.set("download", options.download === true ? "" : options.download);
|
|
34803
34803
|
if (options === null || options === void 0 ? void 0 : options.transform) this.applyTransformOptsToQuery(query, options.transform);
|
|
@@ -34936,10 +34936,10 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
34936
34936
|
* - `objects` table permissions: `select`
|
|
34937
34937
|
* - Refer to the [Storage guide](/docs/guides/storage/security/access-control) on how access control works
|
|
34938
34938
|
*/
|
|
34939
|
-
async list(
|
|
34939
|
+
async list(path8, options, parameters) {
|
|
34940
34940
|
var _this13 = this;
|
|
34941
34941
|
return _this13.handleOperation(async () => {
|
|
34942
|
-
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix:
|
|
34942
|
+
const body = _objectSpread22(_objectSpread22(_objectSpread22({}, DEFAULT_SEARCH_OPTIONS), options), {}, { prefix: path8 || "" });
|
|
34943
34943
|
return await post(_this13.fetch, `${_this13.url}/object/list/${_this13.bucketId}`, body, { headers: _this13.headers }, parameters);
|
|
34944
34944
|
});
|
|
34945
34945
|
}
|
|
@@ -35004,11 +35004,11 @@ var StorageFileApi = class extends BaseApiClient {
|
|
|
35004
35004
|
if (typeof Buffer !== "undefined") return Buffer.from(data).toString("base64");
|
|
35005
35005
|
return btoa(data);
|
|
35006
35006
|
}
|
|
35007
|
-
_getFinalPath(
|
|
35008
|
-
return `${this.bucketId}/${
|
|
35007
|
+
_getFinalPath(path8) {
|
|
35008
|
+
return `${this.bucketId}/${path8.replace(/^\/+/, "")}`;
|
|
35009
35009
|
}
|
|
35010
|
-
_removeEmptyFolders(
|
|
35011
|
-
return
|
|
35010
|
+
_removeEmptyFolders(path8) {
|
|
35011
|
+
return path8.replace(/^\/|\/$/g, "").replace(/\/+/g, "/");
|
|
35012
35012
|
}
|
|
35013
35013
|
/** Modifies the `query`, appending values the from `transform` */
|
|
35014
35014
|
applyTransformOptsToQuery(query, transform2) {
|
|
@@ -40919,6 +40919,23 @@ var goalListMeasurablesOutputSchema = external_exports.object({
|
|
|
40919
40919
|
goal_id: uuidSchema8,
|
|
40920
40920
|
bindings: external_exports.array(goalMeasurableBindingSchema)
|
|
40921
40921
|
}).strict();
|
|
40922
|
+
var goalCoreSchema = external_exports.object({
|
|
40923
|
+
id: uuidSchema8,
|
|
40924
|
+
title: external_exports.string(),
|
|
40925
|
+
kind: external_exports.enum(["objective", "cycle_goal", "company_objective", "seat_goal", "milestone"]),
|
|
40926
|
+
status: goalStatusSchema,
|
|
40927
|
+
status_source: goalStatusSourceSchema,
|
|
40928
|
+
progress_pct: external_exports.number().int().min(0).max(100).nullable(),
|
|
40929
|
+
seat_id: uuidSchema8.nullable(),
|
|
40930
|
+
parent_goal_id: uuidSchema8.nullable(),
|
|
40931
|
+
definition_of_done: external_exports.string()
|
|
40932
|
+
}).strict();
|
|
40933
|
+
var goalGetInputSchema = external_exports.object({
|
|
40934
|
+
goal_id: uuidSchema8
|
|
40935
|
+
}).strict();
|
|
40936
|
+
var goalGetOutputSchema = external_exports.object({
|
|
40937
|
+
goal: goalCoreSchema
|
|
40938
|
+
}).strict();
|
|
40922
40939
|
var issueStatusSchema = external_exports.enum(["open", "diagnosing", "resolved", "dropped"]);
|
|
40923
40940
|
var frictionListInputSchema = external_exports.object({
|
|
40924
40941
|
status: external_exports.enum(["open", "diagnosing", "resolved", "dropped", "active", "all"]).optional()
|
|
@@ -40941,6 +40958,28 @@ var frictionIssueSummarySchema = external_exports.object({
|
|
|
40941
40958
|
var frictionListOutputSchema = external_exports.object({
|
|
40942
40959
|
issues: external_exports.array(frictionIssueSummarySchema)
|
|
40943
40960
|
}).strict();
|
|
40961
|
+
var frictionIssueDetailSchema = frictionIssueSummarySchema.extend({
|
|
40962
|
+
raised_by_seat_type: external_exports.enum(["human", "agent", "hybrid"]),
|
|
40963
|
+
raised_by_seat_steward_name: external_exports.string().nullable(),
|
|
40964
|
+
origin_actor_kind: external_exports.enum(["user", "agent", "system"]).nullable(),
|
|
40965
|
+
origin_actor_id: uuidSchema8.nullable(),
|
|
40966
|
+
evidence: external_exports.unknown(),
|
|
40967
|
+
action_task_title: external_exports.string().nullable(),
|
|
40968
|
+
action_task_owner_seat_id: uuidSchema8.nullable(),
|
|
40969
|
+
action_task_owner_seat_name: external_exports.string().nullable(),
|
|
40970
|
+
action_task_due_on: external_exports.string().nullable(),
|
|
40971
|
+
decision_id: uuidSchema8.nullable(),
|
|
40972
|
+
decision_title: external_exports.string().nullable(),
|
|
40973
|
+
decision_summary: external_exports.string().nullable(),
|
|
40974
|
+
decided_by_name: external_exports.string().nullable(),
|
|
40975
|
+
updated_at: external_exports.string()
|
|
40976
|
+
}).strict();
|
|
40977
|
+
var frictionGetInputSchema = external_exports.object({
|
|
40978
|
+
issue_id: uuidSchema8
|
|
40979
|
+
}).strict();
|
|
40980
|
+
var frictionGetOutputSchema = external_exports.object({
|
|
40981
|
+
issue: frictionIssueDetailSchema
|
|
40982
|
+
}).strict();
|
|
40944
40983
|
var frictionUpdateStatusInputSchema = external_exports.object({
|
|
40945
40984
|
issue_id: uuidSchema8,
|
|
40946
40985
|
status: external_exports.enum(["open", "diagnosing"])
|
|
@@ -40952,17 +40991,34 @@ var frictionUpdateStatusOutputSchema = external_exports.object({
|
|
|
40952
40991
|
}).strict();
|
|
40953
40992
|
var frictionResolveInputSchema = external_exports.object({
|
|
40954
40993
|
issue_id: uuidSchema8,
|
|
40994
|
+
resolution_mode: external_exports.enum(["ids", "already_fixed"]).default("ids"),
|
|
40955
40995
|
root_cause: external_exports.string().trim().min(1),
|
|
40956
|
-
owner_seat_id: uuidSchema8,
|
|
40957
|
-
task_title: external_exports.string().trim().min(1),
|
|
40958
|
-
task_description: external_exports.string().trim().min(1),
|
|
40959
|
-
done_by: dateOnlySchema,
|
|
40996
|
+
owner_seat_id: uuidSchema8.optional(),
|
|
40997
|
+
task_title: external_exports.string().trim().min(1).optional(),
|
|
40998
|
+
task_description: external_exports.string().trim().min(1).optional(),
|
|
40999
|
+
done_by: dateOnlySchema.optional(),
|
|
40960
41000
|
resolving_seat_id: uuidSchema8.optional()
|
|
40961
|
-
}).strict()
|
|
41001
|
+
}).strict().superRefine((value, ctx) => {
|
|
41002
|
+
if (value.resolution_mode !== "ids") {
|
|
41003
|
+
return;
|
|
41004
|
+
}
|
|
41005
|
+
if (value.owner_seat_id === void 0) {
|
|
41006
|
+
ctx.addIssue({ code: "custom", path: ["owner_seat_id"], message: 'Required for resolution_mode "ids".' });
|
|
41007
|
+
}
|
|
41008
|
+
if (value.task_title === void 0) {
|
|
41009
|
+
ctx.addIssue({ code: "custom", path: ["task_title"], message: 'Required for resolution_mode "ids".' });
|
|
41010
|
+
}
|
|
41011
|
+
if (value.task_description === void 0) {
|
|
41012
|
+
ctx.addIssue({ code: "custom", path: ["task_description"], message: 'Required for resolution_mode "ids".' });
|
|
41013
|
+
}
|
|
41014
|
+
if (value.done_by === void 0) {
|
|
41015
|
+
ctx.addIssue({ code: "custom", path: ["done_by"], message: 'Required for resolution_mode "ids".' });
|
|
41016
|
+
}
|
|
41017
|
+
});
|
|
40962
41018
|
var frictionResolveOutputSchema = external_exports.object({
|
|
40963
41019
|
issue_id: uuidSchema8,
|
|
40964
41020
|
status: external_exports.literal("resolved"),
|
|
40965
|
-
action_task_id: uuidSchema8,
|
|
41021
|
+
action_task_id: uuidSchema8.nullable(),
|
|
40966
41022
|
decision_id: uuidSchema8
|
|
40967
41023
|
}).strict();
|
|
40968
41024
|
var frictionLinkTaskInputSchema = external_exports.object({
|
|
@@ -41565,6 +41621,18 @@ var compassShowMarkdownInputSchema = external_exports.object({}).strict();
|
|
|
41565
41621
|
var charterShowMarkdownInputSchema = external_exports.object({
|
|
41566
41622
|
seat_id: uuidSchema9
|
|
41567
41623
|
}).strict();
|
|
41624
|
+
var charterShowMarkdownOutputSchema = external_exports.object({
|
|
41625
|
+
markdown: external_exports.string().min(1),
|
|
41626
|
+
charter_version_id: uuidSchema9.nullable(),
|
|
41627
|
+
seat_id: uuidSchema9,
|
|
41628
|
+
version: external_exports.number().int().nonnegative().nullable(),
|
|
41629
|
+
status: external_exports.string().nullable(),
|
|
41630
|
+
doc: external_exports.unknown().nullable(),
|
|
41631
|
+
dry_run: external_exports.object({
|
|
41632
|
+
status: external_exports.enum(["passed", "failed"]),
|
|
41633
|
+
summary: external_exports.string()
|
|
41634
|
+
}).strict().nullable()
|
|
41635
|
+
}).strict();
|
|
41568
41636
|
var agentShowMarkdownInputSchema = external_exports.object({
|
|
41569
41637
|
seat_id: uuidSchema9
|
|
41570
41638
|
}).strict();
|
|
@@ -41799,6 +41867,27 @@ var confirmationRejectOutputSchema = external_exports.object({
|
|
|
41799
41867
|
command_id: external_exports.string().min(1),
|
|
41800
41868
|
rejected: external_exports.literal(true)
|
|
41801
41869
|
}).strict();
|
|
41870
|
+
var confirmationListInputSchema = external_exports.object({
|
|
41871
|
+
limit: external_exports.number().int().min(1).max(200).optional()
|
|
41872
|
+
}).strict();
|
|
41873
|
+
var confirmationSummarySchema = external_exports.object({
|
|
41874
|
+
id: uuidSchema10,
|
|
41875
|
+
command_id: external_exports.string(),
|
|
41876
|
+
redacted_args: external_exports.unknown(),
|
|
41877
|
+
actor_kind: external_exports.enum(["user", "agent", "system"]),
|
|
41878
|
+
source: external_exports.string(),
|
|
41879
|
+
scope_kind: external_exports.enum(["tenant_admin", "tenant", "seat"]),
|
|
41880
|
+
seat_id: uuidSchema10.nullable(),
|
|
41881
|
+
seat_name: external_exports.string().nullable(),
|
|
41882
|
+
seat_type: external_exports.enum(["human", "agent", "hybrid"]).nullable(),
|
|
41883
|
+
risk_level: external_exports.enum(["normal", "sensitive", "dangerous"]),
|
|
41884
|
+
summary: external_exports.string(),
|
|
41885
|
+
expires_at: external_exports.string(),
|
|
41886
|
+
created_at: external_exports.string()
|
|
41887
|
+
}).strict();
|
|
41888
|
+
var confirmationListOutputSchema = external_exports.object({
|
|
41889
|
+
confirmations: external_exports.array(confirmationSummarySchema)
|
|
41890
|
+
}).strict();
|
|
41802
41891
|
var credentialIngressInputSchema = external_exports.object({
|
|
41803
41892
|
seat_id: uuidSchema10.optional(),
|
|
41804
41893
|
provider: external_exports.string().trim().min(1),
|
|
@@ -46261,7 +46350,7 @@ External connectors are being rolled out provider by provider, conservatively (r
|
|
|
46261
46350
|
order: 48,
|
|
46262
46351
|
title: "CLI and MCP installation guide",
|
|
46263
46352
|
summary: "Install the public CLI, register remote token-backed MCP clients, and find the full command and tool catalog.",
|
|
46264
|
-
version: "2026-07-12.
|
|
46353
|
+
version: "2026-07-12.3",
|
|
46265
46354
|
public: true,
|
|
46266
46355
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
46267
46356
|
stages: ["company_setup", "staffing"],
|
|
@@ -46834,6 +46923,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
|
|
|
46834
46923
|
| \`rost_skip_charter_draft\` | \`charter.skip\` | Mark a Charter draft as skipped. | Seat or tenant-admin | Call only when a human defers the seat. |
|
|
46835
46924
|
| \`rost_apply_charter_seat_type_recommendation\` | \`charter.apply_seat_type_recommendation\` | Apply a Charter's seat-type recommendation. | Seat or tenant-admin | Call after reviewing the draft. |
|
|
46836
46925
|
| \`rost_sign_charter_manifest\` | \`charter.sign_manifest\` | Request human confirmation for a permission manifest. | Seat or tenant-admin | Use after tool permissions are reviewed. |
|
|
46926
|
+
| \`rost_list_pending_confirmations\` | \`confirmation.list\` | List in-flight confirmations awaiting a human decision, scoped to the caller's authority (owner sees all; a member sees seats they occupy; an agent sees its own seat). | Seat or tenant-admin | Call with \`{}\`. |
|
|
46837
46927
|
| \`rost_draft_compass\` | \`compass.draft\` | Create a Compass draft. | Tenant | Call with a concise Compass document. |
|
|
46838
46928
|
| \`rost_update_compass_draft\` | \`compass.update_draft\` | Replace a Compass draft document. | Tenant | Call with the \`compass_version_id\` from \`compass.draft\` as \`draft_id\` and the updated document. |
|
|
46839
46929
|
| \`rost_approve_compass_version\` | \`compass.approve_version\` | Activate a Compass version by supersession. | Tenant | Call after human review. |
|
|
@@ -46934,6 +47024,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
|
|
|
46934
47024
|
| \`rost_import_rocks_from_a_ninety_rocks_export\` | \`cascade.import\` | Bulk-import Rocks as Cascade cycle goals under a company objective in the active cycle (from a ninety Rocks export). Owners resolve to seats; idempotent re-import skips a cycle goal already imported for the same objective + seat + title. | Tenant | Call with the parsed \`rocks\` array. |
|
|
46935
47025
|
| \`rost_import_a_ninety_v_to_into_a_compass_draft\` | \`compass.import\` | AI-draft a Compass from a ninety V/TO (Core Values \u2192 principles, 10/3/1-Year \u2192 horizon goals, Rocks \u2192 cycle objectives), landed as a draft a human confirms by supersession \u2014 never an accepted Compass. Idempotent by document content (a re-upload of the same V/TO short-circuits without re-drafting). | Tenant | Call with the extracted V/TO \`text\` (and optional \`source_name\`). |
|
|
46936
47026
|
| \`rost_list_cascade_goals\` | \`goal.list\` | List Cascade goals, optionally by cycle or seat. | Seat or tenant-admin | Call with \`{}\` or \`{"cycle_id":"<id>"}\`. |
|
|
47027
|
+
| \`rost_get_cascade_goal\` | \`goal.get\` | Get one goal's core detail and status by id. Seat-scoped callers may only read their own seat's goals. | Seat or tenant-admin | Call with \`{"goal_id":"<id>"}\`. |
|
|
46937
47028
|
| \`rost_list_a_cascade_goals_signals\` | \`goal.list_measurables\` | List the goal's status-driving Signal binding (role drives_status; 0-or-1 per goal) with its current indicator and latest confirmed reading. Driver-only \u2014 informs bindings (direct indicators) are not returned. Read-only. | Seat or tenant-admin | Call with \`{"goal_id":"<id>"}\`. |
|
|
46938
47029
|
| \`rost_create_cascade_goal\` | \`goal.create\` | Create a cycle goal under an objective. | Tenant | Call with cycle, seat, parent, title, definition of done. |
|
|
46939
47030
|
| \`rost_update_cascade_goal\` | \`goal.update\` | Update a goal's title or definition of done. | Tenant | Call with \`goal_id\` and the changed fields. |
|
|
@@ -46946,6 +47037,7 @@ Several rows here are seat-operating commands (\`task.create\`, the \`signal.*\`
|
|
|
46946
47037
|
| \`rost_reparent_cascade_goal\` | \`goal.reparent\` | Move a goal under a new parent. | Tenant | Authority change; expect confirmation. |
|
|
46947
47038
|
| \`rost_drop_cascade_goal\` | \`goal.drop\` | Drop (retire) a goal, retained for audit. | Tenant | Expect confirmation. |
|
|
46948
47039
|
| \`rost_list_friction_issues\` | \`friction.list\` | List Friction issues ranked by impact and severity. | Seat or tenant-admin | Call with \`{}\` or \`{"status":"active"}\`. |
|
|
47040
|
+
| \`rost_get_friction_issue\` | \`friction.get\` | Get full detail for one Friction issue by id. | Seat or tenant-admin | Call with \`{"issue_id":"<id>"}\`. |
|
|
46949
47041
|
| \`rost_assist_friction_issue\` | \`friction.assist\` | Advisory IDS assist: the most-similar prior resolved issues with their root causes and decisions, a recurring-pattern flag, and recommended options. Read-only \u2014 it never resolves the issue. | Tenant | Call with \`{"issue_id":"<id>"}\`. |
|
|
46950
47042
|
| \`rost_update_friction_issue_status\` | \`friction.update_status\` | Move a non-terminal issue between open and diagnosing. | Seat or tenant-admin | Call with \`issue_id\` and \`status\`. |
|
|
46951
47043
|
| \`rost_resolve_friction_issue\` | \`friction.resolve\` | Resolve an issue with a root cause and remediation task. | Tenant | Human decision; expect confirmation. |
|
|
@@ -47516,6 +47608,7 @@ Retrieve the narrowest relevant guide before making a setup recommendation. Pref
|
|
|
47516
47608
|
"compass.approve_version",
|
|
47517
47609
|
"onboarding.finish",
|
|
47518
47610
|
"goal.list",
|
|
47611
|
+
"goal.get",
|
|
47519
47612
|
"goal.create",
|
|
47520
47613
|
"goal.update",
|
|
47521
47614
|
"goal.set_status",
|
|
@@ -47735,6 +47828,7 @@ Agents may record readings when the Charter allows it. Agent-reported readings s
|
|
|
47735
47828
|
"compass.answer_gap",
|
|
47736
47829
|
"friction.file_issue",
|
|
47737
47830
|
"friction.list",
|
|
47831
|
+
"friction.get",
|
|
47738
47832
|
"friction.assist",
|
|
47739
47833
|
"friction.update_status",
|
|
47740
47834
|
"friction.resolve",
|
|
@@ -47881,7 +47975,7 @@ Keep agent scope tight at first. Approve more autonomy only after evidence. Use
|
|
|
47881
47975
|
public: true,
|
|
47882
47976
|
audiences: ["human", "cli", "mcp", "in_app_agent"],
|
|
47883
47977
|
stages: ["graph_design", "charter_design", "staffing", "operating_rhythm"],
|
|
47884
|
-
relatedCommandIds: ["confirmation.approve", "confirmation.reject", "charter.approve", "agent.go_live", "credential.ingress", "mcp_token.create", "staffing.assign_user", "goal.reparent", "friction.resolve"],
|
|
47978
|
+
relatedCommandIds: ["confirmation.approve", "confirmation.list", "confirmation.reject", "charter.approve", "agent.go_live", "credential.ingress", "mcp_token.create", "staffing.assign_user", "goal.reparent", "friction.resolve"],
|
|
47885
47979
|
legal: { publicRisk: "low", notes: ["{{brand}}-native human-gate guidance."] },
|
|
47886
47980
|
sources: [
|
|
47887
47981
|
{
|
|
@@ -50026,6 +50120,11 @@ function helpText() {
|
|
|
50026
50120
|
].join("\n");
|
|
50027
50121
|
}
|
|
50028
50122
|
|
|
50123
|
+
// src/update-check.ts
|
|
50124
|
+
import { mkdir as mkdir2, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
|
|
50125
|
+
import { homedir as homedir2 } from "node:os";
|
|
50126
|
+
import path2 from "node:path";
|
|
50127
|
+
|
|
50029
50128
|
// src/cli-version.ts
|
|
50030
50129
|
import { readFile as readFile2 } from "node:fs/promises";
|
|
50031
50130
|
import { dirname as dirname2, resolve } from "node:path";
|
|
@@ -50047,15 +50146,23 @@ async function readCliVersion() {
|
|
|
50047
50146
|
var latestPackageSchema = external_exports.object({
|
|
50048
50147
|
version: external_exports.string()
|
|
50049
50148
|
});
|
|
50050
|
-
|
|
50051
|
-
|
|
50149
|
+
var updateCheckStateSchema = external_exports.object({ lastNaggedOn: external_exports.string() }).strict();
|
|
50150
|
+
async function maybePrintUpgradeNudge(io, options = {}) {
|
|
50151
|
+
if (!options.skipEnvGuard && (process.env.CI || process.env.VITEST || process.env.CLI_SKIP_UPDATE_CHECK === "1")) {
|
|
50152
|
+
return;
|
|
50153
|
+
}
|
|
50154
|
+
const statePath = options.statePath ?? defaultUpdateCheckStatePath();
|
|
50155
|
+
const today = toUtcDateOnly(options.now ?? /* @__PURE__ */ new Date());
|
|
50156
|
+
const state = await readUpdateCheckState(statePath);
|
|
50157
|
+
if (state?.lastNaggedOn === today) {
|
|
50052
50158
|
return;
|
|
50053
50159
|
}
|
|
50054
50160
|
const currentVersion = await readCliVersion();
|
|
50055
50161
|
if (!currentVersion || currentVersion === "0.0.0") {
|
|
50056
50162
|
return;
|
|
50057
50163
|
}
|
|
50058
|
-
const
|
|
50164
|
+
const fetchLatest = options.fetchLatest ?? fetchLatestVersion;
|
|
50165
|
+
const latestVersion = await fetchLatest(cliBrand.packageName);
|
|
50059
50166
|
if (!latestVersion || !isSemverBehind(currentVersion, latestVersion)) {
|
|
50060
50167
|
return;
|
|
50061
50168
|
}
|
|
@@ -50063,6 +50170,28 @@ async function maybePrintUpgradeNudge(io) {
|
|
|
50063
50170
|
`A newer ${cliBrand.binName} CLI is available: ${currentVersion} -> ${latestVersion}. Upgrade with npm i -g ${cliBrand.packageName}@latest.
|
|
50064
50171
|
`
|
|
50065
50172
|
);
|
|
50173
|
+
await writeUpdateCheckStateBestEffort(statePath, { lastNaggedOn: today });
|
|
50174
|
+
}
|
|
50175
|
+
function defaultUpdateCheckStatePath() {
|
|
50176
|
+
return path2.join(homedir2(), ".config", cliBrand.binName, "update-check.json");
|
|
50177
|
+
}
|
|
50178
|
+
function toUtcDateOnly(date5) {
|
|
50179
|
+
return date5.toISOString().slice(0, 10);
|
|
50180
|
+
}
|
|
50181
|
+
async function readUpdateCheckState(statePath) {
|
|
50182
|
+
try {
|
|
50183
|
+
return updateCheckStateSchema.parse(JSON.parse(await readFile3(statePath, "utf8")));
|
|
50184
|
+
} catch {
|
|
50185
|
+
return null;
|
|
50186
|
+
}
|
|
50187
|
+
}
|
|
50188
|
+
async function writeUpdateCheckStateBestEffort(statePath, state) {
|
|
50189
|
+
try {
|
|
50190
|
+
await mkdir2(path2.dirname(statePath), { recursive: true, mode: 448 });
|
|
50191
|
+
await writeFile2(statePath, `${JSON.stringify(state)}
|
|
50192
|
+
`, { mode: 384 });
|
|
50193
|
+
} catch {
|
|
50194
|
+
}
|
|
50066
50195
|
}
|
|
50067
50196
|
async function fetchLatestVersion(packageName) {
|
|
50068
50197
|
const controller = new AbortController();
|
|
@@ -50168,6 +50297,7 @@ var COMMAND_MANIFEST = [
|
|
|
50168
50297
|
{ "id": "compass.show_markdown", "namespace": "compass", "action": "show_markdown", "title": "Show Compass as markdown", "description": "Compose the current Compass and its open gaps into a clean, human-skimmable markdown card for review.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "Render the current Compass and its open gaps as a clean markdown card to show your human a quick review." },
|
|
50169
50298
|
{ "id": "compass.update_draft", "namespace": "compass", "action": "update_draft", "title": "Update Compass draft", "description": "Replace a draft Compass document.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "draft_id", "flag": "draft-id", "type": "string", "required": true }], "hasComplexInput": true, "help": "Pass the compass_version_id returned by compass.draft as draft_id; update_draft replaces only an unpublished draft in this tenant." },
|
|
50170
50299
|
{ "id": "confirmation.approve", "namespace": "confirmation", "action": "approve", "title": "Approve pending confirmation", "description": "Approve an in-flight confirmation and execute the original command as the approving human.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "confirmation_id", "flag": "confirmation-id", "type": "string", "required": true }, { "name": "reviewed", "flag": "reviewed", "type": "boolean", "required": false }], "hasComplexInput": false, "help": "Approve pending confirmations only when the requested durable change is clear to the human owner." },
|
|
50300
|
+
{ "id": "confirmation.list", "namespace": "confirmation", "action": "list", "title": "List pending confirmations", "description": "List in-flight confirmations awaiting a human decision, scoped to the caller's authority (owner sees all; a member sees seats they occupy; an agent sees its own seat).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "List pending confirmations awaiting a human decision before approving or rejecting them." },
|
|
50171
50301
|
{ "id": "confirmation.reject", "namespace": "confirmation", "action": "reject", "title": "Reject pending confirmation", "description": "Reject an in-flight confirmation without executing the original command.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "confirmation_id", "flag": "confirmation-id", "type": "string", "required": true }, { "name": "reason", "flag": "reason", "type": "string", "required": false }], "hasComplexInput": false, "help": "Reject pending confirmations when authority, evidence, or human intent is unclear." },
|
|
50172
50302
|
{ "id": "credential.ingress", "namespace": "credential", "action": "ingress", "title": "Store credential", "description": "Store a secret through the vault and persist only the credential vault reference.", "requiredScope": "seat", "confirmation": "credential_flow", "exposeOverMcp": false, "fields": [{ "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }, { "name": "provider", "flag": "provider", "type": "string", "required": true }, { "name": "scope_description", "flag": "scope-description", "type": "string", "required": true }, { "name": "secret_name", "flag": "secret-name", "type": "string", "required": true }], "hasComplexInput": false, "secretBlocked": true, "help": "Ingress credentials only through vault-backed flows; never place raw secrets in prompts, logs, or docs." },
|
|
50173
50303
|
{ "id": "deliverable.accept", "namespace": "deliverable", "action": "accept", "title": "Accept deliverable value", "description": "Record a human-confirmed accepted value (USD) on a deliverable. Humans decide; agents cannot self-accept. Re-accepting records a correction as a new event; prior events are never mutated.", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "deliverable_id", "flag": "deliverable-id", "type": "string", "required": true }, { "name": "impact_value_usd", "flag": "impact-value-usd", "type": "number", "required": true }], "hasComplexInput": false, "help": "Record a human-confirmed accepted value (USD) on a deliverable; owner-only and human-gated. Humans decide \u2014 agents cannot self-accept. Re-accepting records a correction as a new event." },
|
|
@@ -50185,14 +50315,16 @@ var COMMAND_MANIFEST = [
|
|
|
50185
50315
|
{ "id": "escalation.resolve", "namespace": "escalation", "action": "resolve", "title": "Resolve escalation", "description": "Approve an open escalation (or convert it to Friction). Writes a human decision; agents cannot resolve.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": false, "fields": [{ "name": "id", "flag": "id", "type": "string", "required": true }, { "name": "action", "flag": "action", "type": "enum", "required": false, "enumValues": ["approve", "convert_to_issue"] }, { "name": "rationale", "flag": "rationale", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resolve an escalation as a human Steward; the decision records decided_by as the approving human. Agents cannot resolve." },
|
|
50186
50316
|
{ "id": "friction.assist", "namespace": "friction", "action": "assist", "title": "Assist Friction issue", "description": "Advisory IDS assist for an issue: the most-similar prior resolved issues with their root causes and decisions, a recurring-pattern flag, and recommended options. Read-only \u2014 it never resolves the issue.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "limit", "flag": "limit", "type": "integer", "required": false }], "hasComplexInput": false, "help": "Advisory IDS assist: the most-similar prior resolved issues with their root causes and decisions, plus a recurring-pattern flag. Read-only \u2014 it never resolves the issue." },
|
|
50187
50317
|
{ "id": "friction.file_issue", "namespace": "friction", "action": "file_issue", "title": "File Friction issue", "description": "Emit an issue event and open a Friction issue raised by the acting seat.", "requiredScope": "seat", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "summary", "flag": "summary", "type": "string", "required": true }, { "name": "blocking_goal_id", "flag": "blocking-goal-id", "type": "string", "required": false }, { "name": "broken_measurable_id", "flag": "broken-measurable-id", "type": "string", "required": false }, { "name": "severity", "flag": "severity", "type": "enum", "required": true, "enumValues": ["low", "med", "high", "critical"] }], "hasComplexInput": true, "help": "File a Friction issue with evidence when a goal or measurable is blocked or broken." },
|
|
50318
|
+
{ "id": "friction.get", "namespace": "friction", "action": "get", "title": "Get Friction issue", "description": "Get full detail for one Friction issue by id.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Get full detail for one Friction issue by id, including its root cause, action task, and resolution decision when present." },
|
|
50188
50319
|
{ "id": "friction.import", "namespace": "friction", "action": "import", "title": "Import Friction issues from a ninety Issues List", "description": "Bulk-import a ninety Issues List export into Friction. Owners are seat names resolved to seats; each issue is raised by the resolved seat and attributed to the importing human. Idempotent \u2014 re-importing the same export is a no-op, and an existing open issue with the same seat + summary is skipped.", "requiredScope": "tenant_admin", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "dry_run", "flag": "dry-run", "type": "boolean", "required": false }], "hasComplexInput": true, "help": "Import a ninety Issues List export into Friction; owners resolve to seats, idempotent by file + seat/summary." },
|
|
50189
50320
|
{ "id": "friction.link_task", "namespace": "friction", "action": "link_task", "title": "Link task to Friction issue", "description": "Attach an existing tenant task as the action task for a non-terminal issue. Both ids must belong to the tenant.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "task_id", "flag": "task-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Attach an existing task as the action task for a non-terminal issue." },
|
|
50190
50321
|
{ "id": "friction.list", "namespace": "friction", "action": "list", "title": "List Friction issues", "description": "List Friction issues ranked by status, impact, and severity. Defaults to active (open + diagnosing).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["open", "diagnosing", "resolved", "dropped", "active", "all"] }], "hasComplexInput": false, "help": "List Friction issues ranked by impact and severity to find the issue id before updating or resolving it." },
|
|
50191
|
-
{ "id": "friction.resolve", "namespace": "friction", "action": "resolve", "title": "Resolve Friction issue", "description":
|
|
50322
|
+
{ "id": "friction.resolve", "namespace": "friction", "action": "resolve", "title": "Resolve Friction issue", "description": 'Resolve an issue with a root cause. In the default "ids" resolution_mode this also creates a remediation follow-up task; "already_fixed" records only the root cause (no follow-up task). Always records a human decision (decided_by) in the same transaction.', "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "resolution_mode", "flag": "resolution-mode", "type": "enum", "required": false, "enumValues": ["ids", "already_fixed"] }, { "name": "root_cause", "flag": "root-cause", "type": "string", "required": true }, { "name": "owner_seat_id", "flag": "owner-seat-id", "type": "string", "required": false }, { "name": "task_title", "flag": "task-title", "type": "string", "required": false }, { "name": "task_description", "flag": "task-description", "type": "string", "required": false }, { "name": "done_by", "flag": "done-by", "type": "string", "required": false }, { "name": "resolving_seat_id", "flag": "resolving-seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "Resolve an issue with a root cause and remediation task; resolution is a human decision." },
|
|
50192
50323
|
{ "id": "friction.update_status", "namespace": "friction", "action": "update_status", "title": "Update Friction issue status", "description": "Move a non-terminal issue between open and diagnosing. Terminal issues (resolved/dropped) cannot be reopened here.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "issue_id", "flag": "issue-id", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": true, "enumValues": ["open", "diagnosing"] }], "hasComplexInput": false, "help": "Move a non-terminal issue between open and diagnosing while it is being worked." },
|
|
50193
50324
|
{ "id": "goal.bind_measurable", "namespace": "goal", "action": "bind_measurable", "title": "Bind a Signal to a Cascade goal", "description": "Bind a measurable to a goal. Role defaults to 'informs' \u2014 a conservative informative indicator allowed at any goal level (many per goal) that never changes goal status. Role 'drives_status' makes it the goal's status driver: allowed only on a childless seat goal or milestone, at most one per goal, and auto-status starts OFF until a steward opts in with goal.set_auto_status. Binding is human-gated.", "requiredScope": "seat", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }, { "name": "measurable_id", "flag": "measurable-id", "type": "string", "required": true }, { "name": "role", "flag": "role", "type": "enum", "required": false, "enumValues": ["drives_status", "informs"] }], "hasComplexInput": false, "help": "Bind a Signal to a goal. Defaults to role informs (a conservative indicator at any level that never changes status); pass role drives_status to make it a childless leaf goal's status driver (auto-status starts OFF until a steward opts in)." },
|
|
50194
50325
|
{ "id": "goal.create", "namespace": "goal", "action": "create", "title": "Create Cascade goal", "description": "Create a cycle goal under an existing objective. The parent chain must terminate at a Compass objective in the same cycle (enforced server-side).", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cycle_id", "flag": "cycle-id", "type": "string", "required": true }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": true }, { "name": "parent_goal_id", "flag": "parent-goal-id", "type": "string", "required": true }, { "name": "title", "flag": "title", "type": "string", "required": true }, { "name": "definition_of_done", "flag": "definition-of-done", "type": "string", "required": true }, { "name": "status", "flag": "status", "type": "enum", "required": false, "enumValues": ["on", "off"] }], "hasComplexInput": false, "help": "Create cycle goals under an existing objective; the parent chain must terminate at a Compass objective." },
|
|
50195
50326
|
{ "id": "goal.drop", "namespace": "goal", "action": "drop", "title": "Drop Cascade goal", "description": "Drop (retire) a goal by setting status to dropped. Dropping retires the commitment, so it is human-gated. The row is retained for audit (never deleted).", "requiredScope": "tenant_admin", "confirmation": "human_required", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Drop a goal to retire a commitment; the goal is retained for audit and dropping is human-gated." },
|
|
50327
|
+
{ "id": "goal.get", "namespace": "goal", "action": "get", "title": "Get Cascade goal", "description": "Get one goal's core detail and status by id. Seat-scoped callers may only read their own seat's goals.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "Get one goal's core detail and status by id; seat tokens may only read their own goals." },
|
|
50196
50328
|
{ "id": "goal.list", "namespace": "goal", "action": "list", "title": "List Cascade goals", "description": "List goals in the tenant, optionally filtered by cycle or seat. Seat-scoped callers see only their own seat's goals.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "cycle_id", "flag": "cycle-id", "type": "string", "required": false }, { "name": "seat_id", "flag": "seat-id", "type": "string", "required": false }], "hasComplexInput": false, "help": "List Cascade goals to find goal ids, parentage, and seat ownership before mutating the tree." },
|
|
50197
50329
|
{ "id": "goal.list_at_risk", "namespace": "goal", "action": "list_at_risk", "title": "List at-risk Cascade goals", "description": "List goals projected to miss their cycle pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals (no progress) are excluded.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [], "hasComplexInput": false, "help": "List goals projected off pace (at-risk or projected-miss), with how many days behind pace. Read-only; status-only goals are excluded." },
|
|
50198
50330
|
{ "id": "goal.list_measurables", "namespace": "goal", "action": "list_measurables", "title": "List a Cascade goal's Signals", "description": "List the status-driver Signal bound to a Cascade goal (role drives_status), with its current signal indicator and latest confirmed reading. Read-only. Informative (informs) bindings appear in the goal-detail panel's Direct indicators, not here.", "requiredScope": "tenant", "confirmation": "none", "exposeOverMcp": true, "fields": [{ "name": "goal_id", "flag": "goal-id", "type": "string", "required": true }], "hasComplexInput": false, "help": "List the Signals bound to a goal (role drives_status) with each one's current indicator and latest confirmed reading." },
|
|
@@ -50497,6 +50629,19 @@ function execute(context, parsed, commandId, body, format) {
|
|
|
50497
50629
|
}
|
|
50498
50630
|
|
|
50499
50631
|
// src/generator/flags.ts
|
|
50632
|
+
var SEAT_FLAG_FILLS_REQUIRED_SEAT_ID = /* @__PURE__ */ new Set([
|
|
50633
|
+
"agent.status",
|
|
50634
|
+
"agent.show_markdown",
|
|
50635
|
+
"agent.get_run",
|
|
50636
|
+
"agent.list_runs",
|
|
50637
|
+
"agent.list_tool_calls",
|
|
50638
|
+
"charter.show_markdown",
|
|
50639
|
+
"seat.get",
|
|
50640
|
+
"seat.decommission_preview",
|
|
50641
|
+
"deliverable.get",
|
|
50642
|
+
"deliverable.list",
|
|
50643
|
+
"skill.check_dependencies"
|
|
50644
|
+
]);
|
|
50500
50645
|
function booleanFlagsFor(entry, overrides = {}) {
|
|
50501
50646
|
const booleanFields = new Set(entry.fields.filter((field3) => field3.type === "boolean").map((field3) => field3.name));
|
|
50502
50647
|
const flags = /* @__PURE__ */ new Set(["yes", "y"]);
|
|
@@ -50586,6 +50731,9 @@ function buildBodyFromFlags(entry, parsed, positional, overrides = {}) {
|
|
|
50586
50731
|
if (raw === void 0 && positional !== void 0 && overrides.primaryPositional === field3.name) {
|
|
50587
50732
|
raw = positional;
|
|
50588
50733
|
}
|
|
50734
|
+
if (raw === void 0 && field3.name === "seat_id" && (!field3.required || SEAT_FLAG_FILLS_REQUIRED_SEAT_ID.has(entry.id))) {
|
|
50735
|
+
raw = parsed.seat;
|
|
50736
|
+
}
|
|
50589
50737
|
if (raw === void 0 || raw.length === 0) {
|
|
50590
50738
|
continue;
|
|
50591
50739
|
}
|
|
@@ -50990,6 +51138,15 @@ function renderGoalStatus(output) {
|
|
|
50990
51138
|
const record2 = asRecord(output);
|
|
50991
51139
|
return `Goal ${field(record2, "goal_id")} status set to ${field(record2, "status")}.`;
|
|
50992
51140
|
}
|
|
51141
|
+
function renderGoalGet(output) {
|
|
51142
|
+
const record2 = asRecord(asRecord(output).goal);
|
|
51143
|
+
return [
|
|
51144
|
+
`${field(record2, "id")} ${field(record2, "status")} ${field(record2, "title")}`,
|
|
51145
|
+
`kind: ${field(record2, "kind")} status source: ${field(record2, "status_source")}`,
|
|
51146
|
+
`progress: ${field(record2, "progress_pct")}`,
|
|
51147
|
+
`definition of done: ${field(record2, "definition_of_done")}`
|
|
51148
|
+
].join("\n");
|
|
51149
|
+
}
|
|
50993
51150
|
function renderGoalReparent(output) {
|
|
50994
51151
|
const record2 = asRecord(output);
|
|
50995
51152
|
return `Goal ${field(record2, "goal_id")} reparented under ${field(record2, "parent_goal_id")}.`;
|
|
@@ -51020,6 +51177,27 @@ function renderFrictionLink(output) {
|
|
|
51020
51177
|
const record2 = asRecord(output);
|
|
51021
51178
|
return `Linked task ${field(record2, "action_task_id")} to issue ${field(record2, "issue_id")}.`;
|
|
51022
51179
|
}
|
|
51180
|
+
function renderFrictionGet(output) {
|
|
51181
|
+
const record2 = asRecord(asRecord(output).issue);
|
|
51182
|
+
return [
|
|
51183
|
+
`${field(record2, "issue_id")} ${field(record2, "status")} ${field(record2, "severity")}`,
|
|
51184
|
+
`summary: ${field(record2, "summary")}`,
|
|
51185
|
+
`raised by: ${field(record2, "raised_by_seat_name")}`,
|
|
51186
|
+
`impact score: ${field(record2, "impact_score")}`,
|
|
51187
|
+
`root cause: ${field(record2, "root_cause")}`,
|
|
51188
|
+
`action task: ${field(record2, "action_task_id")}`
|
|
51189
|
+
].join("\n");
|
|
51190
|
+
}
|
|
51191
|
+
function renderConfirmationList(output) {
|
|
51192
|
+
const confirmations = asArray(asRecord(output).confirmations);
|
|
51193
|
+
if (confirmations.length === 0) {
|
|
51194
|
+
return "No pending confirmations.";
|
|
51195
|
+
}
|
|
51196
|
+
return confirmations.map((entry) => {
|
|
51197
|
+
const record2 = asRecord(entry);
|
|
51198
|
+
return `${field(record2, "id")} ${field(record2, "risk_level")} ${field(record2, "command_id")} ${field(record2, "summary")}`;
|
|
51199
|
+
}).join("\n");
|
|
51200
|
+
}
|
|
51023
51201
|
function renderEscalationList(output) {
|
|
51024
51202
|
const escalations = asArray(asRecord(output).escalations);
|
|
51025
51203
|
if (escalations.length === 0) {
|
|
@@ -51922,7 +52100,8 @@ var GROUP_SPECS = {
|
|
|
51922
52100
|
list: { commandId: "goal.list", render: renderGoalList },
|
|
51923
52101
|
create: { commandId: "goal.create", render: renderGoalCreate },
|
|
51924
52102
|
update: { commandId: "goal.update", handler: goalUpdateHandler, render: renderGoalUpdate },
|
|
51925
|
-
status: { commandId: "goal.
|
|
52103
|
+
status: { commandId: "goal.get", render: renderGoalGet, primaryPositional: "goal_id" },
|
|
52104
|
+
"set-status": { commandId: "goal.set_status", render: renderGoalStatus },
|
|
51926
52105
|
reparent: { commandId: "goal.reparent", render: renderGoalReparent },
|
|
51927
52106
|
drop: { commandId: "goal.drop", render: renderGoalDrop }
|
|
51928
52107
|
}
|
|
@@ -51946,6 +52125,7 @@ var GROUP_SPECS = {
|
|
|
51946
52125
|
friction: {
|
|
51947
52126
|
verbs: {
|
|
51948
52127
|
list: { commandId: "friction.list", render: renderFrictionList },
|
|
52128
|
+
get: { commandId: "friction.get", render: renderFrictionGet, primaryPositional: "issue_id" },
|
|
51949
52129
|
file: { commandId: "friction.file_issue", handler: frictionFileHandler, render: renderFrictionFile },
|
|
51950
52130
|
resolve: { commandId: "friction.resolve", render: renderFrictionResolve },
|
|
51951
52131
|
link: { commandId: "friction.link_task", render: renderFrictionLink },
|
|
@@ -51967,7 +52147,7 @@ var GROUP_SPECS = {
|
|
|
51967
52147
|
verbs: {
|
|
51968
52148
|
list: { commandId: "escalation.list", render: renderEscalationList },
|
|
51969
52149
|
get: { commandId: "escalation.get", render: renderEscalationGet, primaryPositional: "id" },
|
|
51970
|
-
resolve: { commandId: "escalation.resolve", render: renderEscalationResolve },
|
|
52150
|
+
resolve: { commandId: "escalation.resolve", render: renderEscalationResolve, primaryPositional: "id" },
|
|
51971
52151
|
reject: { commandId: "escalation.reject", render: renderEscalationReject }
|
|
51972
52152
|
}
|
|
51973
52153
|
},
|
|
@@ -52089,6 +52269,11 @@ var GROUP_SPECS = {
|
|
|
52089
52269
|
verbs: {
|
|
52090
52270
|
health: { commandId: "system.health", handler: systemHealthHandler, render: formatSystemHealth }
|
|
52091
52271
|
}
|
|
52272
|
+
},
|
|
52273
|
+
confirmation: {
|
|
52274
|
+
verbs: {
|
|
52275
|
+
list: { commandId: "confirmation.list", render: renderConfirmationList }
|
|
52276
|
+
}
|
|
52092
52277
|
}
|
|
52093
52278
|
};
|
|
52094
52279
|
|
|
@@ -52378,7 +52563,7 @@ function ensureTrailingSlash2(value) {
|
|
|
52378
52563
|
// src/skills.ts
|
|
52379
52564
|
import { existsSync, mkdirSync, readFileSync as readFileSync3, rmSync, writeFileSync } from "node:fs";
|
|
52380
52565
|
import os from "node:os";
|
|
52381
|
-
import
|
|
52566
|
+
import path3 from "node:path";
|
|
52382
52567
|
var UsageError2 = class extends Error {
|
|
52383
52568
|
};
|
|
52384
52569
|
var CLIENTS = /* @__PURE__ */ new Set(["claude-code", "codex", "cursor"]);
|
|
@@ -52573,8 +52758,8 @@ function writeInstalls(output, root) {
|
|
|
52573
52758
|
const slug2 = safeLocalSlug(String(install.slug ?? ""));
|
|
52574
52759
|
const metadata = asRecord2(install.metadata);
|
|
52575
52760
|
const files = asArray2(install.files).map(asRecord2);
|
|
52576
|
-
const dir =
|
|
52577
|
-
const metadataPath =
|
|
52761
|
+
const dir = path3.join(root, slug2);
|
|
52762
|
+
const metadataPath = path3.join(dir, ".rost-skill.json");
|
|
52578
52763
|
const expectedHash = String(metadata.content_sha256 ?? "");
|
|
52579
52764
|
if (existingHash(metadataPath) === expectedHash) {
|
|
52580
52765
|
return { slug: slug2, dir, status: "unchanged", files: files.length };
|
|
@@ -52584,8 +52769,8 @@ function writeInstalls(output, root) {
|
|
|
52584
52769
|
for (const file2 of files) {
|
|
52585
52770
|
const relativePath = safeRelativePath(String(file2.path ?? ""));
|
|
52586
52771
|
const content = String(file2.content ?? "");
|
|
52587
|
-
const target =
|
|
52588
|
-
mkdirSync(
|
|
52772
|
+
const target = path3.join(dir, relativePath);
|
|
52773
|
+
mkdirSync(path3.dirname(target), { recursive: true });
|
|
52589
52774
|
writeFileSync(target, content, "utf8");
|
|
52590
52775
|
}
|
|
52591
52776
|
writeFileSync(metadataPath, `${JSON.stringify(metadata, null, 2)}
|
|
@@ -52605,7 +52790,7 @@ function removeRevokedInstalls(output, root) {
|
|
|
52605
52790
|
if (installs.has(slug2)) {
|
|
52606
52791
|
continue;
|
|
52607
52792
|
}
|
|
52608
|
-
const dir =
|
|
52793
|
+
const dir = path3.join(root, slug2);
|
|
52609
52794
|
if (!existsSync(dir)) {
|
|
52610
52795
|
continue;
|
|
52611
52796
|
}
|
|
@@ -52617,15 +52802,15 @@ function removeRevokedInstalls(output, root) {
|
|
|
52617
52802
|
function installRoot(client, env) {
|
|
52618
52803
|
const override = env.ROST_SKILL_INSTALL_ROOT;
|
|
52619
52804
|
if (override && override.length > 0) {
|
|
52620
|
-
return
|
|
52805
|
+
return path3.resolve(override, client);
|
|
52621
52806
|
}
|
|
52622
52807
|
if (client === "codex") {
|
|
52623
|
-
return
|
|
52808
|
+
return path3.join(env.CODEX_HOME ?? path3.join(os.homedir(), ".codex"), "skills", "rost");
|
|
52624
52809
|
}
|
|
52625
52810
|
if (client === "claude-code") {
|
|
52626
|
-
return
|
|
52811
|
+
return path3.join(env.CLAUDE_HOME ?? path3.join(os.homedir(), ".claude"), "skills", "rost");
|
|
52627
52812
|
}
|
|
52628
|
-
return
|
|
52813
|
+
return path3.join(os.homedir(), ".cursor", "skills", "rost");
|
|
52629
52814
|
}
|
|
52630
52815
|
function safeRelativePath(value) {
|
|
52631
52816
|
const normalized = value.trim().replaceAll("\\", "/").replace(/^\.\/+/, "");
|
|
@@ -52834,9 +53019,9 @@ import { promisify as promisify3 } from "node:util";
|
|
|
52834
53019
|
import { existsSync as existsSync2, realpathSync } from "node:fs";
|
|
52835
53020
|
import { readdir, rm as rm2, stat as stat2 } from "node:fs/promises";
|
|
52836
53021
|
import { tmpdir } from "node:os";
|
|
52837
|
-
import
|
|
53022
|
+
import path4 from "node:path";
|
|
52838
53023
|
var SANDBOX_EXEC_PATH = "/usr/bin/sandbox-exec";
|
|
52839
|
-
var RUNNER_ASKPASS_DIR =
|
|
53024
|
+
var RUNNER_ASKPASS_DIR = path4.join(tmpdir(), "rost-runner-askpass");
|
|
52840
53025
|
var RUNNER_TEMP_PREFIXES = [
|
|
52841
53026
|
"rost-runner-mcp-",
|
|
52842
53027
|
"rost-runner-sandbox-",
|
|
@@ -53006,7 +53191,7 @@ function canonical(p) {
|
|
|
53006
53191
|
}
|
|
53007
53192
|
}
|
|
53008
53193
|
function canonicalFile(p) {
|
|
53009
|
-
return
|
|
53194
|
+
return path4.join(canonical(path4.dirname(p)), path4.basename(p));
|
|
53010
53195
|
}
|
|
53011
53196
|
function isSandboxExecAvailable() {
|
|
53012
53197
|
try {
|
|
@@ -53089,7 +53274,7 @@ async function sweepStaleRunnerTempFiles(dir, options = {}) {
|
|
|
53089
53274
|
if (!RUNNER_TEMP_PREFIXES.some((prefix) => name.startsWith(prefix))) {
|
|
53090
53275
|
return;
|
|
53091
53276
|
}
|
|
53092
|
-
const full =
|
|
53277
|
+
const full = path4.join(dir, name);
|
|
53093
53278
|
try {
|
|
53094
53279
|
const info = await stat2(full);
|
|
53095
53280
|
if (now - info.mtimeMs < maxAgeMs) {
|
|
@@ -53107,9 +53292,9 @@ async function sweepStaleRunnerTempFiles(dir, options = {}) {
|
|
|
53107
53292
|
// src/runner-service.ts
|
|
53108
53293
|
import { execFile as execFileCallback2 } from "node:child_process";
|
|
53109
53294
|
import { realpathSync as realpathSync2 } from "node:fs";
|
|
53110
|
-
import { access, mkdir as
|
|
53111
|
-
import { homedir as
|
|
53112
|
-
import
|
|
53295
|
+
import { access, mkdir as mkdir3, readFile as readFile4, readdir as readdir2, rm as rm3, writeFile as writeFile3 } from "node:fs/promises";
|
|
53296
|
+
import { homedir as homedir3 } from "node:os";
|
|
53297
|
+
import path5 from "node:path";
|
|
53113
53298
|
import { promisify as promisify2 } from "node:util";
|
|
53114
53299
|
var execFile2 = promisify2(execFileCallback2);
|
|
53115
53300
|
var SERVICE_VERBS = ["install-service", "start", "stop", "restart", "status", "logs", "uninstall"];
|
|
@@ -53126,9 +53311,9 @@ function isRunnerServiceInvocation(args) {
|
|
|
53126
53311
|
function runnerServicePaths(homeDir, runnerName) {
|
|
53127
53312
|
const safeName = safeRunnerName(runnerName);
|
|
53128
53313
|
return {
|
|
53129
|
-
launchAgentPath:
|
|
53130
|
-
stateFile:
|
|
53131
|
-
logDir:
|
|
53314
|
+
launchAgentPath: path5.join(homeDir, "Library", "LaunchAgents", `${serviceLabel(safeName)}.plist`),
|
|
53315
|
+
stateFile: path5.join(homeDir, "Library", "Application Support", cliBrand.name, `runner-${safeName}.json`),
|
|
53316
|
+
logDir: path5.join(homeDir, "Library", "Logs", cliBrand.name, "runner", safeName)
|
|
53132
53317
|
};
|
|
53133
53318
|
}
|
|
53134
53319
|
function renderLaunchdPlist(config2) {
|
|
@@ -53170,9 +53355,9 @@ ${config2.allowDevelopmentAppUrl === true ? ` <key>${allowInsecureAppUrlEnv}<
|
|
|
53170
53355
|
<key>RunAtLoad</key>
|
|
53171
53356
|
<true/>
|
|
53172
53357
|
<key>StandardOutPath</key>
|
|
53173
|
-
<string>${escapePlist(
|
|
53358
|
+
<string>${escapePlist(path5.join(config2.logDir, "stdout.log"))}</string>
|
|
53174
53359
|
<key>StandardErrorPath</key>
|
|
53175
|
-
<string>${escapePlist(
|
|
53360
|
+
<string>${escapePlist(path5.join(config2.logDir, "stderr.log"))}</string>
|
|
53176
53361
|
</dict>
|
|
53177
53362
|
</plist>
|
|
53178
53363
|
`;
|
|
@@ -53208,7 +53393,7 @@ ${serviceUsage()}
|
|
|
53208
53393
|
userCode: parsed.userCode,
|
|
53209
53394
|
nodePath: options.nodePath ?? resolveNodePath(),
|
|
53210
53395
|
binPath: options.binPath ?? resolveBinPath(),
|
|
53211
|
-
homeDir: options.homeDir ??
|
|
53396
|
+
homeDir: options.homeDir ?? homedir3(),
|
|
53212
53397
|
platform: options.platform ?? process.platform,
|
|
53213
53398
|
exec: options.exec ?? defaultExec,
|
|
53214
53399
|
uid: options.uid ?? (process.getuid ? process.getuid() : 0)
|
|
@@ -53239,9 +53424,9 @@ async function installService(options) {
|
|
|
53239
53424
|
const safeName = safeRunnerName(options.runnerName);
|
|
53240
53425
|
const paths = runnerServicePaths(options.homeDir, safeName);
|
|
53241
53426
|
const label = serviceLabel(safeName);
|
|
53242
|
-
await
|
|
53243
|
-
await
|
|
53244
|
-
await
|
|
53427
|
+
await mkdir3(paths.logDir, { recursive: true });
|
|
53428
|
+
await mkdir3(path5.dirname(paths.stateFile), { recursive: true });
|
|
53429
|
+
await mkdir3(path5.dirname(paths.launchAgentPath), { recursive: true });
|
|
53245
53430
|
if (options.userCode !== void 0) {
|
|
53246
53431
|
const paired = await pairRunnerOnce(options, safeName, paths.stateFile, options.userCode);
|
|
53247
53432
|
if (!paired) {
|
|
@@ -53259,7 +53444,7 @@ async function installService(options) {
|
|
|
53259
53444
|
servicePath: buildServicePath(options.nodePath, options.homeDir),
|
|
53260
53445
|
execute: options.execute
|
|
53261
53446
|
});
|
|
53262
|
-
await
|
|
53447
|
+
await writeFile3(paths.launchAgentPath, plist, { mode: 420 });
|
|
53263
53448
|
await bootoutQuietly(options.exec, options.uid, paths.launchAgentPath);
|
|
53264
53449
|
try {
|
|
53265
53450
|
const bootstrapped = await bootstrapService(options.exec, options.uid, paths.launchAgentPath);
|
|
@@ -53396,8 +53581,8 @@ async function logsService(options) {
|
|
|
53396
53581
|
const safeName = safeRunnerName(options.runnerName);
|
|
53397
53582
|
const paths = runnerServicePaths(options.homeDir, safeName);
|
|
53398
53583
|
const label = serviceLabel(safeName);
|
|
53399
|
-
const stdoutLog =
|
|
53400
|
-
const stderrLog =
|
|
53584
|
+
const stdoutLog = path5.join(paths.logDir, "stdout.log");
|
|
53585
|
+
const stderrLog = path5.join(paths.logDir, "stderr.log");
|
|
53401
53586
|
options.io.stdout.write(
|
|
53402
53587
|
`${[
|
|
53403
53588
|
`runner service logs for ${label}:`,
|
|
@@ -53500,8 +53685,8 @@ function serviceTargets(uid, label) {
|
|
|
53500
53685
|
return launchdDomains(uid).map((domain2) => `${domain2}/${label}`);
|
|
53501
53686
|
}
|
|
53502
53687
|
async function inspectRunnerServiceInstallations(options = {}) {
|
|
53503
|
-
const homeDir = options.homeDir ??
|
|
53504
|
-
const launchAgentsDir =
|
|
53688
|
+
const homeDir = options.homeDir ?? homedir3();
|
|
53689
|
+
const launchAgentsDir = path5.join(homeDir, "Library", "LaunchAgents");
|
|
53505
53690
|
let names = [];
|
|
53506
53691
|
try {
|
|
53507
53692
|
const entries = await readdir2(launchAgentsDir);
|
|
@@ -53521,7 +53706,7 @@ async function inspectRunnerService(options) {
|
|
|
53521
53706
|
const paths = runnerServicePaths(options.homeDir, safeName);
|
|
53522
53707
|
const label = serviceLabel(safeName);
|
|
53523
53708
|
const installed = await fileExists(paths.launchAgentPath);
|
|
53524
|
-
const plist = installed ? await
|
|
53709
|
+
const plist = installed ? await readFile4(paths.launchAgentPath, "utf8").catch(() => null) : null;
|
|
53525
53710
|
const programArgs = plist ? extractProgramArguments(plist) : [];
|
|
53526
53711
|
const appUrl2 = plist ? extractPlistEnvironmentValue(plist, `${cliBrand.envPrefix}_APP_URL`) : null;
|
|
53527
53712
|
const urlPolicyEnv = extractPlistEnvironmentValue(plist ?? "", allowInsecureAppUrlEnv) === "1" ? "set" : "unset";
|
|
@@ -53630,11 +53815,11 @@ function resolveNodePath() {
|
|
|
53630
53815
|
}
|
|
53631
53816
|
function buildServicePath(nodePath, homeDir) {
|
|
53632
53817
|
const entries = [
|
|
53633
|
-
|
|
53818
|
+
path5.dirname(nodePath),
|
|
53634
53819
|
"/opt/homebrew/bin",
|
|
53635
53820
|
"/usr/local/bin",
|
|
53636
|
-
|
|
53637
|
-
|
|
53821
|
+
path5.join(homeDir, ".local", "bin"),
|
|
53822
|
+
path5.join(homeDir, "bin"),
|
|
53638
53823
|
"/usr/bin",
|
|
53639
53824
|
"/bin",
|
|
53640
53825
|
"/usr/sbin",
|
|
@@ -53789,7 +53974,7 @@ async function fileExists(file2) {
|
|
|
53789
53974
|
}
|
|
53790
53975
|
async function readTail(file2, maxBytes) {
|
|
53791
53976
|
try {
|
|
53792
|
-
const content = await
|
|
53977
|
+
const content = await readFile4(file2, "utf8");
|
|
53793
53978
|
return content.length > maxBytes ? content.slice(content.length - maxBytes) : content;
|
|
53794
53979
|
} catch {
|
|
53795
53980
|
return null;
|
|
@@ -53936,17 +54121,17 @@ function parseSemver2(value) {
|
|
|
53936
54121
|
// src/runner-serve.ts
|
|
53937
54122
|
import { execFile as execFileCallback5, spawn } from "node:child_process";
|
|
53938
54123
|
import { createHash as createHash2 } from "node:crypto";
|
|
53939
|
-
import { chmod as chmod2, mkdir as
|
|
53940
|
-
import { cpus, homedir as
|
|
53941
|
-
import
|
|
54124
|
+
import { chmod as chmod2, mkdir as mkdir5, readFile as readFile5, rename, rm as rm5, statfs, writeFile as writeFile5 } from "node:fs/promises";
|
|
54125
|
+
import { cpus, homedir as homedir4, hostname as hostname3, platform, totalmem, tmpdir as tmpdir2 } from "node:os";
|
|
54126
|
+
import path7 from "node:path";
|
|
53942
54127
|
import { setTimeout as sleep3 } from "node:timers/promises";
|
|
53943
54128
|
import { promisify as promisify5 } from "node:util";
|
|
53944
54129
|
|
|
53945
54130
|
// src/forge-workspace.ts
|
|
53946
54131
|
import { execFile as execFileCallback4 } from "node:child_process";
|
|
53947
54132
|
import { createHash } from "node:crypto";
|
|
53948
|
-
import { chmod, lstat, mkdir as
|
|
53949
|
-
import
|
|
54133
|
+
import { chmod, lstat, mkdir as mkdir4, mkdtemp, realpath, rm as rm4, stat as stat3, writeFile as writeFile4 } from "node:fs/promises";
|
|
54134
|
+
import path6 from "node:path";
|
|
53950
54135
|
import { setTimeout as sleep2 } from "node:timers/promises";
|
|
53951
54136
|
import { promisify as promisify4 } from "node:util";
|
|
53952
54137
|
|
|
@@ -54083,20 +54268,20 @@ function shortRequestId(buildRequestId) {
|
|
|
54083
54268
|
return slice.length > 0 ? slice : createHash("sha1").update(buildRequestId).digest("hex").slice(0, 8);
|
|
54084
54269
|
}
|
|
54085
54270
|
function requestRoot(baseDir, buildRequestId) {
|
|
54086
|
-
return
|
|
54271
|
+
return path6.join(baseDir, "work", shortRequestId(buildRequestId));
|
|
54087
54272
|
}
|
|
54088
54273
|
function baseRepoDir(baseDir, buildRequestId) {
|
|
54089
|
-
return
|
|
54274
|
+
return path6.join(requestRoot(baseDir, buildRequestId), "base");
|
|
54090
54275
|
}
|
|
54091
54276
|
function branchName(buildRequestId, changeset) {
|
|
54092
54277
|
const short = shortRequestId(buildRequestId);
|
|
54093
54278
|
return changeset.total > 1 ? `forge/${short}-cs${changeset.ordinal}` : `forge/${short}`;
|
|
54094
54279
|
}
|
|
54095
54280
|
function buildWorktreeDir(baseDir, buildRequestId, ordinal) {
|
|
54096
|
-
return
|
|
54281
|
+
return path6.join(requestRoot(baseDir, buildRequestId), `cs${ordinal}`);
|
|
54097
54282
|
}
|
|
54098
54283
|
function reviewWorktreeDir(baseDir, buildRequestId, ordinal) {
|
|
54099
|
-
return
|
|
54284
|
+
return path6.join(requestRoot(baseDir, buildRequestId), `review-cs${ordinal}`);
|
|
54100
54285
|
}
|
|
54101
54286
|
function remoteUrlFor(options) {
|
|
54102
54287
|
if (options.remoteUrl) {
|
|
@@ -54113,7 +54298,7 @@ async function pathExists(target) {
|
|
|
54113
54298
|
}
|
|
54114
54299
|
}
|
|
54115
54300
|
async function isGitRepo(dir) {
|
|
54116
|
-
return await pathExists(
|
|
54301
|
+
return await pathExists(path6.join(dir, ".git")) || await pathExists(path6.join(dir, "HEAD"));
|
|
54117
54302
|
}
|
|
54118
54303
|
async function runGit(args, cwd, timeoutMs = LOCAL_GIT_TIMEOUT_MS) {
|
|
54119
54304
|
try {
|
|
@@ -54166,10 +54351,10 @@ async function withNetworkRetries(op, fn, retryCounter) {
|
|
|
54166
54351
|
throw new Error(`${op} exhausted retries: ${lastError instanceof Error ? redactSecrets(lastError.message) : redactSecrets(String(lastError))}`);
|
|
54167
54352
|
}
|
|
54168
54353
|
async function canonicalAskpassBase(baseDir) {
|
|
54169
|
-
return
|
|
54354
|
+
return path6.join(await realpath(path6.dirname(baseDir)), path6.basename(baseDir));
|
|
54170
54355
|
}
|
|
54171
54356
|
async function prepareAskpassTurnDir(baseDir) {
|
|
54172
|
-
await
|
|
54357
|
+
await mkdir4(baseDir, { recursive: true, mode: 448 });
|
|
54173
54358
|
const baseInfo = await lstat(baseDir);
|
|
54174
54359
|
if (baseInfo.isSymbolicLink() || !baseInfo.isDirectory()) {
|
|
54175
54360
|
throw new Error(`refusing to use askpass dir ${baseDir}: not a real directory (possible symlink attack)`);
|
|
@@ -54178,10 +54363,10 @@ async function prepareAskpassTurnDir(baseDir) {
|
|
|
54178
54363
|
throw new Error(`refusing to use askpass dir ${baseDir}: not owned by this user (possible pre-planted dir)`);
|
|
54179
54364
|
}
|
|
54180
54365
|
await chmod(baseDir, 448);
|
|
54181
|
-
const turnDir = await mkdtemp(
|
|
54366
|
+
const turnDir = await mkdtemp(path6.join(baseDir, "rost-runner-askpass-"));
|
|
54182
54367
|
const canonicalBase = await canonicalAskpassBase(baseDir);
|
|
54183
54368
|
const realTurn = await realpath(turnDir);
|
|
54184
|
-
if (
|
|
54369
|
+
if (path6.dirname(realTurn) !== canonicalBase) {
|
|
54185
54370
|
await rm4(turnDir, { recursive: true, force: true });
|
|
54186
54371
|
throw new Error(`refusing to use askpass dir ${turnDir}: resolved outside ${canonicalBase} (possible symlink attack)`);
|
|
54187
54372
|
}
|
|
@@ -54189,7 +54374,7 @@ async function prepareAskpassTurnDir(baseDir) {
|
|
|
54189
54374
|
}
|
|
54190
54375
|
async function openAskpassSession(credential, baseDir = RUNNER_ASKPASS_DIR) {
|
|
54191
54376
|
const turnDir = await prepareAskpassTurnDir(baseDir);
|
|
54192
|
-
const helperPath =
|
|
54377
|
+
const helperPath = path6.join(turnDir, "askpass.sh");
|
|
54193
54378
|
const helper = [
|
|
54194
54379
|
"#!/bin/sh",
|
|
54195
54380
|
"# One-shot Forge GIT_ASKPASS helper. Contains no secret; reads the token from env.",
|
|
@@ -54199,7 +54384,7 @@ async function openAskpassSession(credential, baseDir = RUNNER_ASKPASS_DIR) {
|
|
|
54199
54384
|
"esac",
|
|
54200
54385
|
""
|
|
54201
54386
|
].join("\n");
|
|
54202
|
-
await
|
|
54387
|
+
await writeFile4(helperPath, helper, { mode: 448 });
|
|
54203
54388
|
await chmod(helperPath, 448);
|
|
54204
54389
|
const env = {
|
|
54205
54390
|
...process.env,
|
|
@@ -54250,8 +54435,8 @@ async function localBranchExists(baseRepo, branch) {
|
|
|
54250
54435
|
async function worktreeRegistered(baseRepo, worktreeDir) {
|
|
54251
54436
|
try {
|
|
54252
54437
|
const listing = await runGit(["worktree", "list", "--porcelain"], baseRepo);
|
|
54253
|
-
const target =
|
|
54254
|
-
return listing.split("\n").some((line) => line.startsWith("worktree ") &&
|
|
54438
|
+
const target = path6.resolve(worktreeDir);
|
|
54439
|
+
return listing.split("\n").some((line) => line.startsWith("worktree ") && path6.resolve(line.slice("worktree ".length).trim()) === target);
|
|
54255
54440
|
} catch {
|
|
54256
54441
|
return false;
|
|
54257
54442
|
}
|
|
@@ -54262,7 +54447,7 @@ async function configureForgeIdentity(baseRepo) {
|
|
|
54262
54447
|
}
|
|
54263
54448
|
async function ensureBaseClone(input) {
|
|
54264
54449
|
const baseRepo = baseRepoDir(input.baseDir, input.buildRequestId);
|
|
54265
|
-
await
|
|
54450
|
+
await mkdir4(path6.dirname(baseRepo), { recursive: true, mode: 448 });
|
|
54266
54451
|
await withLedgerStep(input.ledger, "clone", (retryCounter) => withAskpass(input.credential, async (netEnv) => {
|
|
54267
54452
|
if (await isGitRepo(baseRepo)) {
|
|
54268
54453
|
await runGitNetwork("git fetch", ["fetch", "--prune", "--quiet", input.url, "+refs/heads/*:refs/remotes/origin/*"], netEnv, baseRepo, FETCH_TIMEOUT_MS, retryCounter);
|
|
@@ -54311,7 +54496,7 @@ async function prepareMergeWorkspace(options) {
|
|
|
54311
54496
|
ledger: options.ledger
|
|
54312
54497
|
});
|
|
54313
54498
|
const branch = options.headBranch;
|
|
54314
|
-
const worktreeDir =
|
|
54499
|
+
const worktreeDir = path6.join(requestRoot(options.baseDir, options.buildRequestId), "merge");
|
|
54315
54500
|
const originDefault = `origin/${options.repo.default_branch}`;
|
|
54316
54501
|
const originHead = `origin/${branch}`;
|
|
54317
54502
|
await withLedgerStep(options.ledger, "branch", async () => {
|
|
@@ -54789,7 +54974,7 @@ async function runRunnerServe(options) {
|
|
|
54789
54974
|
const env = options.env ?? process.env;
|
|
54790
54975
|
const fetchImpl = options.fetchImpl ?? fetch;
|
|
54791
54976
|
const cliVersion = await readCliVersion();
|
|
54792
|
-
const homeDir = options.homeDir ??
|
|
54977
|
+
const homeDir = options.homeDir ?? homedir4();
|
|
54793
54978
|
let config2;
|
|
54794
54979
|
try {
|
|
54795
54980
|
config2 = parseServeArgs(options.args, options.appUrl, env, homeDir);
|
|
@@ -54975,7 +55160,7 @@ function detectTelemetry(capabilities, env, activeSessions, cliVersion) {
|
|
|
54975
55160
|
}
|
|
54976
55161
|
function parseServeArgs(args, appUrl2, env, homeDir) {
|
|
54977
55162
|
let name = env.RUNNER_NAME ?? `headless-${hostname3()}`;
|
|
54978
|
-
let stateFile = env.RUNNER_STATE_FILE ??
|
|
55163
|
+
let stateFile = env.RUNNER_STATE_FILE ?? path7.join(tmpdir2(), `rost-runner-${createHash2("sha1").update(appUrl2).digest("hex").slice(0, 8)}.json`);
|
|
54979
55164
|
let heartbeatMs = Number(env.RUNNER_HEARTBEAT_MS ?? 3e4);
|
|
54980
55165
|
let interactiveClaimMs = Number(env.RUNNER_INTERACTIVE_CLAIM_MS ?? 1e3);
|
|
54981
55166
|
let execute2 = env.RUNNER_EXECUTE === "1";
|
|
@@ -55026,7 +55211,7 @@ function parseServeArgs(args, appUrl2, env, homeDir) {
|
|
|
55026
55211
|
tmpDir: tmpdir2(),
|
|
55027
55212
|
homeDir,
|
|
55028
55213
|
stateFile,
|
|
55029
|
-
runnerBaseDir:
|
|
55214
|
+
runnerBaseDir: path7.join(homeDir, ".rost"),
|
|
55030
55215
|
allowNetwork: network.allowNetwork
|
|
55031
55216
|
});
|
|
55032
55217
|
return {
|
|
@@ -55132,7 +55317,7 @@ async function pairIfNeeded(client, fetchImpl, appUrl2, config2, io) {
|
|
|
55132
55317
|
}
|
|
55133
55318
|
async function loadState(filePath, expectedTenantId) {
|
|
55134
55319
|
try {
|
|
55135
|
-
const parsed = JSON.parse(await
|
|
55320
|
+
const parsed = JSON.parse(await readFile5(filePath, "utf8"));
|
|
55136
55321
|
if (typeof parsed.runner_id === "string" && typeof parsed.runner_secret === "string") {
|
|
55137
55322
|
if (expectedTenantId && parsed.tenant_id !== expectedTenantId) {
|
|
55138
55323
|
return null;
|
|
@@ -55163,10 +55348,10 @@ function isRuntimeSessionMap(value) {
|
|
|
55163
55348
|
});
|
|
55164
55349
|
}
|
|
55165
55350
|
async function saveState(filePath, state) {
|
|
55166
|
-
await
|
|
55351
|
+
await mkdir5(path7.dirname(filePath), { recursive: true, mode: 448 });
|
|
55167
55352
|
const tempPath = `${filePath}.${process.pid}.${createHash2("sha1").update(`${Date.now()}:${Math.random()}`).digest("hex").slice(0, 8)}.tmp`;
|
|
55168
55353
|
try {
|
|
55169
|
-
await
|
|
55354
|
+
await writeFile5(tempPath, `${JSON.stringify(state)}
|
|
55170
55355
|
`, { mode: 384 });
|
|
55171
55356
|
await chmod2(tempPath, 384);
|
|
55172
55357
|
await rename(tempPath, filePath);
|
|
@@ -55216,8 +55401,8 @@ function resolveSandboxKind(env, homeDir) {
|
|
|
55216
55401
|
workspaceDir: tmpdir2(),
|
|
55217
55402
|
tmpDir: tmpdir2(),
|
|
55218
55403
|
homeDir,
|
|
55219
|
-
stateFile:
|
|
55220
|
-
runnerBaseDir:
|
|
55404
|
+
stateFile: path7.join(tmpdir2(), "runner-sandbox-probe.json"),
|
|
55405
|
+
runnerBaseDir: path7.join(homeDir, ".rost"),
|
|
55221
55406
|
allowNetwork: resolveSandboxNetworkFlag(env) === "allow"
|
|
55222
55407
|
}).kind;
|
|
55223
55408
|
}
|
|
@@ -55316,9 +55501,9 @@ async function probeGhAuth() {
|
|
|
55316
55501
|
}
|
|
55317
55502
|
}
|
|
55318
55503
|
async function probeForgeDiskFreeMb(homeDir) {
|
|
55319
|
-
const dir =
|
|
55504
|
+
const dir = path7.join(homeDir, ".rost", "forge");
|
|
55320
55505
|
try {
|
|
55321
|
-
await
|
|
55506
|
+
await mkdir5(dir, { recursive: true, mode: 448 });
|
|
55322
55507
|
const stats = await statfs(dir);
|
|
55323
55508
|
return Math.floor(stats.bavail * stats.bsize / (1024 * 1024));
|
|
55324
55509
|
} catch {
|
|
@@ -55650,7 +55835,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55650
55835
|
let workspace;
|
|
55651
55836
|
try {
|
|
55652
55837
|
workspace = await prepareForgeWorkspace({
|
|
55653
|
-
baseDir:
|
|
55838
|
+
baseDir: path7.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
|
|
55654
55839
|
tenantId,
|
|
55655
55840
|
buildRequestId,
|
|
55656
55841
|
changeset: { id: buildRequestId, ordinal: 1, total: 1 },
|
|
@@ -55670,7 +55855,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55670
55855
|
tmpDir: tmpdir2(),
|
|
55671
55856
|
homeDir: ctx.config.homeDir,
|
|
55672
55857
|
stateFile: ctx.config.stateFile,
|
|
55673
|
-
runnerBaseDir:
|
|
55858
|
+
runnerBaseDir: path7.join(ctx.config.homeDir, ".rost"),
|
|
55674
55859
|
allowWritePaths: [workspace.baseRepo],
|
|
55675
55860
|
// Re-allow the shared object store for local commits, but DENY the model writing the
|
|
55676
55861
|
// repo's hook + config (and the worktree's gitdir pointer). The harness runs git
|
|
@@ -55678,9 +55863,9 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55678
55863
|
// hook or `ext::`/`insteadOf` config would otherwise exfiltrate it (DER-1327 review).
|
|
55679
55864
|
// `.git/{objects,refs,worktrees,logs,index,HEAD}` stay writable so the model can commit.
|
|
55680
55865
|
denyWritePaths: [
|
|
55681
|
-
`${
|
|
55682
|
-
|
|
55683
|
-
|
|
55866
|
+
`${path7.join(workspace.baseRepo, ".git", "hooks")}/`,
|
|
55867
|
+
path7.join(workspace.baseRepo, ".git", "config"),
|
|
55868
|
+
path7.join(workspace.worktreeDir, ".git")
|
|
55684
55869
|
],
|
|
55685
55870
|
allowNetwork: ctx.config.sandboxAllowNetwork
|
|
55686
55871
|
});
|
|
@@ -55699,7 +55884,7 @@ async function prepareForgeTurn(ctx, workOrder, execution) {
|
|
|
55699
55884
|
var FORGE_MAX_CHANGED_PATHS = 2e3;
|
|
55700
55885
|
var FORGE_MAX_CHANGED_PATH_LENGTH = 500;
|
|
55701
55886
|
function forgeChangedPathsField(changedPaths) {
|
|
55702
|
-
const withinCaps = changedPaths.length > 0 && changedPaths.length <= FORGE_MAX_CHANGED_PATHS && changedPaths.every((
|
|
55887
|
+
const withinCaps = changedPaths.length > 0 && changedPaths.length <= FORGE_MAX_CHANGED_PATHS && changedPaths.every((path8) => path8.length >= 1 && path8.length <= FORGE_MAX_CHANGED_PATH_LENGTH);
|
|
55703
55888
|
return withinCaps ? { changedPaths: [...changedPaths] } : {};
|
|
55704
55889
|
}
|
|
55705
55890
|
async function finalizeForgeBuildPush(ctx, prep, result) {
|
|
@@ -55840,9 +56025,9 @@ async function spawnRunnerTurn(ctx, workOrder, runtime, kind) {
|
|
|
55840
56025
|
const token = typeof mcp.token === "string" ? mcp.token : "";
|
|
55841
56026
|
const url2 = typeof mcp.url === "string" ? `${ctx.appUrl.replace(/\/+$/, "")}${mcp.url}` : `${ctx.appUrl.replace(/\/+$/, "")}/mcp`;
|
|
55842
56027
|
const mcpConfig = JSON.stringify({ mcpServers: { rost: { type: "http", url: url2, headers: { Authorization: `Bearer ${token}` } } } });
|
|
55843
|
-
const configPath =
|
|
56028
|
+
const configPath = path7.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
|
|
55844
56029
|
const prompt = buildTurnPrompt({ kind, workOrder, execution, hasWorkspace: forgePrep !== null });
|
|
55845
|
-
await
|
|
56030
|
+
await writeFile5(configPath, `${mcpConfig}
|
|
55846
56031
|
`, { mode: 384 });
|
|
55847
56032
|
await chmod2(configPath, 384);
|
|
55848
56033
|
const resumeSessionId = runtime === "claude" ? getClaudeResumeSessionId(ctx.state, workOrder) : void 0;
|
|
@@ -55857,11 +56042,11 @@ async function spawnRunnerTurn(ctx, workOrder, runtime, kind) {
|
|
|
55857
56042
|
});
|
|
55858
56043
|
let sandboxProfilePath = null;
|
|
55859
56044
|
if (sandbox.kind === "seatbelt") {
|
|
55860
|
-
sandboxProfilePath =
|
|
56045
|
+
sandboxProfilePath = path7.join(
|
|
55861
56046
|
tmpdir2(),
|
|
55862
56047
|
`rost-runner-sandbox-${createHash2("sha256").update(`${configPath}:${Math.random()}`).digest("hex").slice(0, 16)}.sb`
|
|
55863
56048
|
);
|
|
55864
|
-
await
|
|
56049
|
+
await writeFile5(sandboxProfilePath, sandbox.profile, { mode: 384 });
|
|
55865
56050
|
await chmod2(sandboxProfilePath, 384);
|
|
55866
56051
|
}
|
|
55867
56052
|
const { command, args } = wrapCommandWithSandbox(sandbox, built.command, built.args, sandboxProfilePath);
|
|
@@ -55992,7 +56177,7 @@ async function resolveMergeConflictTurn(ctx, input) {
|
|
|
55992
56177
|
let workspace;
|
|
55993
56178
|
try {
|
|
55994
56179
|
workspace = await prepareMergeWorkspace({
|
|
55995
|
-
baseDir:
|
|
56180
|
+
baseDir: path7.join(ctx.config.homeDir, ".rost", "forge", ctx.state.runner_id),
|
|
55996
56181
|
tenantId,
|
|
55997
56182
|
buildRequestId: input.buildRequestId,
|
|
55998
56183
|
repo: input.repo,
|
|
@@ -56010,12 +56195,12 @@ async function resolveMergeConflictTurn(ctx, input) {
|
|
|
56010
56195
|
tmpDir: tmpdir2(),
|
|
56011
56196
|
homeDir: ctx.config.homeDir,
|
|
56012
56197
|
stateFile: ctx.config.stateFile,
|
|
56013
|
-
runnerBaseDir:
|
|
56198
|
+
runnerBaseDir: path7.join(ctx.config.homeDir, ".rost"),
|
|
56014
56199
|
allowWritePaths: [workspace.baseRepo],
|
|
56015
56200
|
denyWritePaths: [
|
|
56016
|
-
`${
|
|
56017
|
-
|
|
56018
|
-
|
|
56201
|
+
`${path7.join(workspace.baseRepo, ".git", "hooks")}/`,
|
|
56202
|
+
path7.join(workspace.baseRepo, ".git", "config"),
|
|
56203
|
+
path7.join(workspace.worktreeDir, ".git")
|
|
56019
56204
|
],
|
|
56020
56205
|
allowNetwork: ctx.config.sandboxAllowNetwork
|
|
56021
56206
|
});
|
|
@@ -56045,8 +56230,8 @@ async function spawnMergeConflictModel(ctx, input) {
|
|
|
56045
56230
|
const token = typeof mcp.token === "string" ? mcp.token : "";
|
|
56046
56231
|
const url2 = typeof mcp.url === "string" ? `${ctx.appUrl.replace(/\/+$/, "")}${mcp.url}` : `${ctx.appUrl.replace(/\/+$/, "")}/mcp`;
|
|
56047
56232
|
const mcpConfig = JSON.stringify({ mcpServers: { rost: { type: "http", url: url2, headers: { Authorization: `Bearer ${token}` } } } });
|
|
56048
|
-
const configPath =
|
|
56049
|
-
await
|
|
56233
|
+
const configPath = path7.join(tmpdir2(), `rost-runner-mcp-${createHash2("sha256").update(`${url2}:${Date.now()}:${Math.random()}`).digest("hex").slice(0, 16)}.json`);
|
|
56234
|
+
await writeFile5(configPath, `${mcpConfig}
|
|
56050
56235
|
`, { mode: 384 });
|
|
56051
56236
|
await chmod2(configPath, 384);
|
|
56052
56237
|
const plan = resolveTurnPlan({ kind: "work_order", execution: input.execution, repoDir: input.workspace.worktreeDir });
|
|
@@ -56058,8 +56243,8 @@ async function spawnMergeConflictModel(ctx, input) {
|
|
|
56058
56243
|
].join("\n");
|
|
56059
56244
|
let sandboxProfilePath = null;
|
|
56060
56245
|
if (input.sandbox.kind === "seatbelt") {
|
|
56061
|
-
sandboxProfilePath =
|
|
56062
|
-
await
|
|
56246
|
+
sandboxProfilePath = path7.join(tmpdir2(), `rost-runner-sandbox-${createHash2("sha256").update(`${configPath}:${Math.random()}`).digest("hex").slice(0, 16)}.sb`);
|
|
56247
|
+
await writeFile5(sandboxProfilePath, input.sandbox.profile, { mode: 384 });
|
|
56063
56248
|
await chmod2(sandboxProfilePath, 384);
|
|
56064
56249
|
}
|
|
56065
56250
|
const built = buildTurnCommand({
|