wildcrane-runner 0.6.3 → 0.6.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -3
- package/dist/akb/dist/kanban.mjs +2561 -2874
- package/dist/akb/package.json +1 -1
- package/dist/launcher.mjs +9 -7
- package/dist/runner.mjs +1084 -655
- package/package.json +1 -1
package/dist/runner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// wildcrane-runner 0.6.
|
|
1
|
+
// wildcrane-runner 0.6.4 — built by runner/scripts/build.mjs. Do not edit.
|
|
2
2
|
import { createRequire as __ai4kanbanRequire } from 'node:module'
|
|
3
3
|
const require = __ai4kanbanRequire(import.meta.url)
|
|
4
4
|
var __create = Object.create;
|
|
@@ -426,19 +426,19 @@ var require_react_production = __commonJS({
|
|
|
426
426
|
_init: lazyInitializer
|
|
427
427
|
};
|
|
428
428
|
};
|
|
429
|
-
exports.memo = function(type,
|
|
429
|
+
exports.memo = function(type, compare2) {
|
|
430
430
|
return {
|
|
431
431
|
$$typeof: REACT_MEMO_TYPE,
|
|
432
432
|
type,
|
|
433
|
-
compare: void 0 ===
|
|
433
|
+
compare: void 0 === compare2 ? null : compare2
|
|
434
434
|
};
|
|
435
435
|
};
|
|
436
436
|
exports.startTransition = startTransition;
|
|
437
437
|
exports.unstable_useCacheRefresh = function() {
|
|
438
438
|
return ReactSharedInternals.H.useCacheRefresh();
|
|
439
439
|
};
|
|
440
|
-
exports.use = function(
|
|
441
|
-
return ReactSharedInternals.H.use(
|
|
440
|
+
exports.use = function(usable2) {
|
|
441
|
+
return ReactSharedInternals.H.use(usable2);
|
|
442
442
|
};
|
|
443
443
|
exports.useActionState = function(action, initialState, permalink) {
|
|
444
444
|
return ReactSharedInternals.H.useActionState(action, initialState, permalink);
|
|
@@ -1386,18 +1386,18 @@ var require_react_development = __commonJS({
|
|
|
1386
1386
|
lazyType._debugInfo = [{ awaited: ioInfo }];
|
|
1387
1387
|
return lazyType;
|
|
1388
1388
|
};
|
|
1389
|
-
exports.memo = function(type,
|
|
1389
|
+
exports.memo = function(type, compare2) {
|
|
1390
1390
|
null == type && console.error(
|
|
1391
1391
|
"memo: The first argument must be a component. Instead received: %s",
|
|
1392
1392
|
null === type ? "null" : typeof type
|
|
1393
1393
|
);
|
|
1394
|
-
|
|
1394
|
+
compare2 = {
|
|
1395
1395
|
$$typeof: REACT_MEMO_TYPE,
|
|
1396
1396
|
type,
|
|
1397
|
-
compare: void 0 ===
|
|
1397
|
+
compare: void 0 === compare2 ? null : compare2
|
|
1398
1398
|
};
|
|
1399
1399
|
var ownName;
|
|
1400
|
-
Object.defineProperty(
|
|
1400
|
+
Object.defineProperty(compare2, "displayName", {
|
|
1401
1401
|
enumerable: false,
|
|
1402
1402
|
configurable: true,
|
|
1403
1403
|
get: function() {
|
|
@@ -1408,14 +1408,14 @@ var require_react_development = __commonJS({
|
|
|
1408
1408
|
type.name || type.displayName || (Object.defineProperty(type, "name", { value: name }), type.displayName = name);
|
|
1409
1409
|
}
|
|
1410
1410
|
});
|
|
1411
|
-
return
|
|
1411
|
+
return compare2;
|
|
1412
1412
|
};
|
|
1413
1413
|
exports.startTransition = startTransition;
|
|
1414
1414
|
exports.unstable_useCacheRefresh = function() {
|
|
1415
1415
|
return resolveDispatcher().useCacheRefresh();
|
|
1416
1416
|
};
|
|
1417
|
-
exports.use = function(
|
|
1418
|
-
return resolveDispatcher().use(
|
|
1417
|
+
exports.use = function(usable2) {
|
|
1418
|
+
return resolveDispatcher().use(usable2);
|
|
1419
1419
|
};
|
|
1420
1420
|
exports.useActionState = function(action, initialState, permalink) {
|
|
1421
1421
|
return resolveDispatcher().useActionState(
|
|
@@ -4909,15 +4909,15 @@ var require_react_dom_server_legacy_node_production = __commonJS({
|
|
|
4909
4909
|
readContext: function(context) {
|
|
4910
4910
|
return context._currentValue2;
|
|
4911
4911
|
},
|
|
4912
|
-
use: function(
|
|
4913
|
-
if (null !==
|
|
4914
|
-
if ("function" === typeof
|
|
4915
|
-
if (
|
|
4916
|
-
throw createRecoverableError(
|
|
4917
|
-
if (
|
|
4918
|
-
return
|
|
4919
|
-
}
|
|
4920
|
-
throw Error("An unsupported type was passed to use(): " + String(
|
|
4912
|
+
use: function(usable2) {
|
|
4913
|
+
if (null !== usable2 && "object" === typeof usable2) {
|
|
4914
|
+
if ("function" === typeof usable2.then) return unwrapThenable(usable2);
|
|
4915
|
+
if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
|
|
4916
|
+
throw createRecoverableError(usable2);
|
|
4917
|
+
if (usable2.$$typeof === REACT_CONTEXT_TYPE)
|
|
4918
|
+
return usable2._currentValue2;
|
|
4919
|
+
}
|
|
4920
|
+
throw Error("An unsupported type was passed to use(): " + String(usable2));
|
|
4921
4921
|
},
|
|
4922
4922
|
useContext: function(context) {
|
|
4923
4923
|
resolveCurrentlyRenderingComponent();
|
|
@@ -7517,7 +7517,7 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
7517
7517
|
"node_modules/react-dom/cjs/react-dom-server.node.production.js"(exports) {
|
|
7518
7518
|
"use strict";
|
|
7519
7519
|
var util = __require("util");
|
|
7520
|
-
var
|
|
7520
|
+
var crypto6 = __require("crypto");
|
|
7521
7521
|
var async_hooks = __require("async_hooks");
|
|
7522
7522
|
var React4 = require_react();
|
|
7523
7523
|
var ReactDOM = require_react_dom();
|
|
@@ -10382,7 +10382,7 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
10382
10382
|
function createPostbackActionStateKey(permalink, componentKeyPath, hookIndex) {
|
|
10383
10383
|
if (void 0 !== permalink) return "p" + permalink;
|
|
10384
10384
|
permalink = JSON.stringify([componentKeyPath, null, hookIndex]);
|
|
10385
|
-
componentKeyPath =
|
|
10385
|
+
componentKeyPath = crypto6.createHash("md5");
|
|
10386
10386
|
componentKeyPath.update(permalink);
|
|
10387
10387
|
return "k" + componentKeyPath.digest("hex");
|
|
10388
10388
|
}
|
|
@@ -10440,14 +10440,14 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
10440
10440
|
readContext: function(context) {
|
|
10441
10441
|
return context._currentValue;
|
|
10442
10442
|
},
|
|
10443
|
-
use: function(
|
|
10444
|
-
if (null !==
|
|
10445
|
-
if ("function" === typeof
|
|
10446
|
-
if (
|
|
10447
|
-
throw createRecoverableError(
|
|
10448
|
-
if (
|
|
10449
|
-
}
|
|
10450
|
-
throw Error("An unsupported type was passed to use(): " + String(
|
|
10443
|
+
use: function(usable2) {
|
|
10444
|
+
if (null !== usable2 && "object" === typeof usable2) {
|
|
10445
|
+
if ("function" === typeof usable2.then) return unwrapThenable(usable2);
|
|
10446
|
+
if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
|
|
10447
|
+
throw createRecoverableError(usable2);
|
|
10448
|
+
if (usable2.$$typeof === REACT_CONTEXT_TYPE) return usable2._currentValue;
|
|
10449
|
+
}
|
|
10450
|
+
throw Error("An unsupported type was passed to use(): " + String(usable2));
|
|
10451
10451
|
},
|
|
10452
10452
|
useContext: function(context) {
|
|
10453
10453
|
resolveCurrentlyRenderingComponent();
|
|
@@ -21050,17 +21050,17 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
21050
21050
|
"Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`."
|
|
21051
21051
|
), suspendedThenable = null, shouldCaptureSuspendedCallSite = false, suspendedCallSiteStack = null, suspendedCallSiteDebugTask = null, objectIs = "function" === typeof Object.is ? Object.is : is, currentlyRenderingComponent = null, currentlyRenderingTask = null, currentlyRenderingRequest = null, currentlyRenderingKeyPath = null, firstWorkInProgressHook = null, workInProgressHook = null, isReRender = false, didScheduleRenderPhaseUpdate = false, localIdCounter = 0, actionStateCounter = 0, actionStateMatchingIndex = -1, thenableIndexCounter = 0, thenableState = null, renderPhaseUpdates = null, numberOfReRenders = 0, isInHookUserCodeInDev = false, currentHookNameInDev, HooksDispatcher = {
|
|
21052
21052
|
readContext,
|
|
21053
|
-
use: function(
|
|
21054
|
-
if (null !==
|
|
21055
|
-
if ("function" === typeof
|
|
21056
|
-
return unwrapThenable(
|
|
21057
|
-
if (
|
|
21058
|
-
throw createRecoverableError(
|
|
21059
|
-
if (
|
|
21060
|
-
return readContext(
|
|
21053
|
+
use: function(usable2) {
|
|
21054
|
+
if (null !== usable2 && "object" === typeof usable2) {
|
|
21055
|
+
if ("function" === typeof usable2.then)
|
|
21056
|
+
return unwrapThenable(usable2);
|
|
21057
|
+
if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
|
|
21058
|
+
throw createRecoverableError(usable2);
|
|
21059
|
+
if (usable2.$$typeof === REACT_CONTEXT_TYPE)
|
|
21060
|
+
return readContext(usable2);
|
|
21061
21061
|
}
|
|
21062
21062
|
throw Error(
|
|
21063
|
-
"An unsupported type was passed to use(): " + String(
|
|
21063
|
+
"An unsupported type was passed to use(): " + String(usable2)
|
|
21064
21064
|
);
|
|
21065
21065
|
},
|
|
21066
21066
|
useContext: function(context) {
|
|
@@ -24376,7 +24376,7 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
24376
24376
|
function createPostbackActionStateKey(permalink, componentKeyPath, hookIndex) {
|
|
24377
24377
|
if (void 0 !== permalink) return "p" + permalink;
|
|
24378
24378
|
permalink = JSON.stringify([componentKeyPath, null, hookIndex]);
|
|
24379
|
-
componentKeyPath =
|
|
24379
|
+
componentKeyPath = crypto6.createHash("md5");
|
|
24380
24380
|
componentKeyPath.update(permalink);
|
|
24381
24381
|
return "k" + componentKeyPath.digest("hex");
|
|
24382
24382
|
}
|
|
@@ -28038,7 +28038,7 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
28038
28038
|
}
|
|
28039
28039
|
};
|
|
28040
28040
|
}
|
|
28041
|
-
var util = __require("util"),
|
|
28041
|
+
var util = __require("util"), crypto6 = __require("crypto"), async_hooks = __require("async_hooks"), React4 = require_react(), ReactDOM = require_react_dom(), stream = __require("stream"), REACT_ELEMENT_TYPE = /* @__PURE__ */ Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = /* @__PURE__ */ Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = /* @__PURE__ */ Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = /* @__PURE__ */ Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = /* @__PURE__ */ Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = /* @__PURE__ */ Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = /* @__PURE__ */ Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = /* @__PURE__ */ Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = /* @__PURE__ */ Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = /* @__PURE__ */ Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = /* @__PURE__ */ Symbol.for("react.memo"), REACT_LAZY_TYPE = /* @__PURE__ */ Symbol.for("react.lazy"), REACT_SCOPE_TYPE = /* @__PURE__ */ Symbol.for("react.scope"), REACT_ACTIVITY_TYPE = /* @__PURE__ */ Symbol.for("react.activity"), REACT_LEGACY_HIDDEN_TYPE = /* @__PURE__ */ Symbol.for("react.legacy_hidden"), REACT_MEMO_CACHE_SENTINEL = /* @__PURE__ */ Symbol.for("react.memo_cache_sentinel"), REACT_VIEW_TRANSITION_TYPE = /* @__PURE__ */ Symbol.for("react.view_transition"), REACT_RECOVERABLE_TYPE = /* @__PURE__ */ Symbol.for("react.recoverable"), MAYBE_ITERATOR_SYMBOL = Symbol.iterator, ASYNC_ITERATOR = Symbol.asyncIterator, REACT_OPTIMISTIC_KEY = /* @__PURE__ */ Symbol.for("react.optimistic_key"), isArrayImpl = Array.isArray, jsxPropsParents = /* @__PURE__ */ new WeakMap(), jsxChildrenParents = /* @__PURE__ */ new WeakMap(), CLIENT_REFERENCE_TAG = /* @__PURE__ */ Symbol.for("react.client.reference"), hasOwnProperty = Object.prototype.hasOwnProperty, supportsArrayBufferDetached = hasOwnProperty.call(
|
|
28042
28042
|
ArrayBuffer.prototype,
|
|
28043
28043
|
"detached"
|
|
28044
28044
|
), didWarnAboutMissingArrayBufferDetached = false, scheduleMicrotask = queueMicrotask, currentView = null, writtenBytes = 0, destinationHasCapacity$1 = true, textEncoder = new util.TextEncoder(), assign = Object.assign, VALID_ATTRIBUTE_NAME_REGEX = RegExp(
|
|
@@ -28999,17 +28999,17 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
28999
28999
|
"Suspense Exception: This is not a real error! It's an implementation detail of `use` to interrupt the current render. You must either rethrow it immediately, or move the `use` call outside of the `try/catch` block. Capturing without rethrowing will lead to unexpected behavior.\n\nTo handle async errors, wrap your component in an error boundary, or call the promise's `.catch` method and pass the result to `use`."
|
|
29000
29000
|
), suspendedThenable = null, shouldCaptureSuspendedCallSite = false, suspendedCallSiteStack = null, suspendedCallSiteDebugTask = null, objectIs = "function" === typeof Object.is ? Object.is : is, currentlyRenderingComponent = null, currentlyRenderingTask = null, currentlyRenderingRequest = null, currentlyRenderingKeyPath = null, firstWorkInProgressHook = null, workInProgressHook = null, isReRender = false, didScheduleRenderPhaseUpdate = false, localIdCounter = 0, actionStateCounter = 0, actionStateMatchingIndex = -1, thenableIndexCounter = 0, thenableState = null, renderPhaseUpdates = null, numberOfReRenders = 0, isInHookUserCodeInDev = false, currentHookNameInDev, HooksDispatcher = {
|
|
29001
29001
|
readContext,
|
|
29002
|
-
use: function(
|
|
29003
|
-
if (null !==
|
|
29004
|
-
if ("function" === typeof
|
|
29005
|
-
return unwrapThenable(
|
|
29006
|
-
if (
|
|
29007
|
-
throw createRecoverableError(
|
|
29008
|
-
if (
|
|
29009
|
-
return readContext(
|
|
29002
|
+
use: function(usable2) {
|
|
29003
|
+
if (null !== usable2 && "object" === typeof usable2) {
|
|
29004
|
+
if ("function" === typeof usable2.then)
|
|
29005
|
+
return unwrapThenable(usable2);
|
|
29006
|
+
if (usable2.$$typeof === REACT_RECOVERABLE_TYPE)
|
|
29007
|
+
throw createRecoverableError(usable2);
|
|
29008
|
+
if (usable2.$$typeof === REACT_CONTEXT_TYPE)
|
|
29009
|
+
return readContext(usable2);
|
|
29010
29010
|
}
|
|
29011
29011
|
throw Error(
|
|
29012
|
-
"An unsupported type was passed to use(): " + String(
|
|
29012
|
+
"An unsupported type was passed to use(): " + String(usable2)
|
|
29013
29013
|
);
|
|
29014
29014
|
},
|
|
29015
29015
|
useContext: function(context) {
|
|
@@ -41256,8 +41256,8 @@ var require_JSXTransformer = __commonJS({
|
|
|
41256
41256
|
}
|
|
41257
41257
|
if (this.isAutomaticRuntime) {
|
|
41258
41258
|
if (this.importProcessor) {
|
|
41259
|
-
for (const [
|
|
41260
|
-
prefix += `var ${resolvedName} = require("${
|
|
41259
|
+
for (const [path34, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
|
|
41260
|
+
prefix += `var ${resolvedName} = require("${path34}");`;
|
|
41261
41261
|
}
|
|
41262
41262
|
} else {
|
|
41263
41263
|
const { createElement: createElementResolution, ...otherResolutions } = this.esmAutomaticImportNameResolutions;
|
|
@@ -41450,11 +41450,11 @@ var require_JSXTransformer = __commonJS({
|
|
|
41450
41450
|
}
|
|
41451
41451
|
claimAutoImportedName(funcName, importPathSuffix) {
|
|
41452
41452
|
if (this.importProcessor) {
|
|
41453
|
-
const
|
|
41454
|
-
if (!this.cjsAutomaticModuleNameResolutions[
|
|
41455
|
-
this.cjsAutomaticModuleNameResolutions[
|
|
41453
|
+
const path34 = this.jsxImportSource + importPathSuffix;
|
|
41454
|
+
if (!this.cjsAutomaticModuleNameResolutions[path34]) {
|
|
41455
|
+
this.cjsAutomaticModuleNameResolutions[path34] = this.importProcessor.getFreeIdentifierForPath(path34);
|
|
41456
41456
|
}
|
|
41457
|
-
return `${this.cjsAutomaticModuleNameResolutions[
|
|
41457
|
+
return `${this.cjsAutomaticModuleNameResolutions[path34]}.${funcName}`;
|
|
41458
41458
|
} else {
|
|
41459
41459
|
if (!this.esmAutomaticImportNameResolutions[funcName]) {
|
|
41460
41460
|
this.esmAutomaticImportNameResolutions[funcName] = this.nameManager.claimFreeName(
|
|
@@ -41890,7 +41890,7 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
41890
41890
|
*/
|
|
41891
41891
|
pruneTypeOnlyImports() {
|
|
41892
41892
|
this.nonTypeIdentifiers = _getNonTypeIdentifiers.getNonTypeIdentifiers.call(void 0, this.tokens, this.options);
|
|
41893
|
-
for (const [
|
|
41893
|
+
for (const [path34, importInfo] of this.importInfoByPath.entries()) {
|
|
41894
41894
|
if (importInfo.hasBareImport || importInfo.hasStarExport || importInfo.exportStarNames.length > 0 || importInfo.namedExports.length > 0) {
|
|
41895
41895
|
continue;
|
|
41896
41896
|
}
|
|
@@ -41900,7 +41900,7 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
41900
41900
|
...importInfo.namedImports.map(({ localName }) => localName)
|
|
41901
41901
|
];
|
|
41902
41902
|
if (names2.every((name) => this.shouldAutomaticallyElideImportedName(name))) {
|
|
41903
|
-
this.importsToReplace.set(
|
|
41903
|
+
this.importsToReplace.set(path34, "");
|
|
41904
41904
|
}
|
|
41905
41905
|
}
|
|
41906
41906
|
}
|
|
@@ -41908,7 +41908,7 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
41908
41908
|
return this.isTypeScriptTransformEnabled && !this.keepUnusedImports && !this.nonTypeIdentifiers.has(name);
|
|
41909
41909
|
}
|
|
41910
41910
|
generateImportReplacements() {
|
|
41911
|
-
for (const [
|
|
41911
|
+
for (const [path34, importInfo] of this.importInfoByPath.entries()) {
|
|
41912
41912
|
const {
|
|
41913
41913
|
defaultNames,
|
|
41914
41914
|
wildcardNames,
|
|
@@ -41918,17 +41918,17 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
41918
41918
|
hasStarExport
|
|
41919
41919
|
} = importInfo;
|
|
41920
41920
|
if (defaultNames.length === 0 && wildcardNames.length === 0 && namedImports.length === 0 && namedExports.length === 0 && exportStarNames.length === 0 && !hasStarExport) {
|
|
41921
|
-
this.importsToReplace.set(
|
|
41921
|
+
this.importsToReplace.set(path34, `require('${path34}');`);
|
|
41922
41922
|
continue;
|
|
41923
41923
|
}
|
|
41924
|
-
const primaryImportName = this.getFreeIdentifierForPath(
|
|
41924
|
+
const primaryImportName = this.getFreeIdentifierForPath(path34);
|
|
41925
41925
|
let secondaryImportName;
|
|
41926
41926
|
if (this.enableLegacyTypeScriptModuleInterop) {
|
|
41927
41927
|
secondaryImportName = primaryImportName;
|
|
41928
41928
|
} else {
|
|
41929
|
-
secondaryImportName = wildcardNames.length > 0 ? wildcardNames[0] : this.getFreeIdentifierForPath(
|
|
41929
|
+
secondaryImportName = wildcardNames.length > 0 ? wildcardNames[0] : this.getFreeIdentifierForPath(path34);
|
|
41930
41930
|
}
|
|
41931
|
-
let requireCode = `var ${primaryImportName} = require('${
|
|
41931
|
+
let requireCode = `var ${primaryImportName} = require('${path34}');`;
|
|
41932
41932
|
if (wildcardNames.length > 0) {
|
|
41933
41933
|
for (const wildcardName of wildcardNames) {
|
|
41934
41934
|
const moduleExpr = this.enableLegacyTypeScriptModuleInterop ? primaryImportName : `${this.helperManager.getHelperName("interopRequireWildcard")}(${primaryImportName})`;
|
|
@@ -41956,7 +41956,7 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
41956
41956
|
"createStarExport"
|
|
41957
41957
|
)}(${primaryImportName});`;
|
|
41958
41958
|
}
|
|
41959
|
-
this.importsToReplace.set(
|
|
41959
|
+
this.importsToReplace.set(path34, requireCode);
|
|
41960
41960
|
for (const defaultName of defaultNames) {
|
|
41961
41961
|
this.identifierReplacements.set(defaultName, `${secondaryImportName}.default`);
|
|
41962
41962
|
}
|
|
@@ -41965,8 +41965,8 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
41965
41965
|
}
|
|
41966
41966
|
}
|
|
41967
41967
|
}
|
|
41968
|
-
getFreeIdentifierForPath(
|
|
41969
|
-
const components =
|
|
41968
|
+
getFreeIdentifierForPath(path34) {
|
|
41969
|
+
const components = path34.split("/");
|
|
41970
41970
|
const lastComponent = components[components.length - 1];
|
|
41971
41971
|
const baseName = lastComponent.replace(/\W/g, "");
|
|
41972
41972
|
return this.nameManager.claimFreeName(`_${baseName}`);
|
|
@@ -42011,8 +42011,8 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
42011
42011
|
if (!this.tokens.matches1AtIndex(index, _types.TokenType.string)) {
|
|
42012
42012
|
throw new Error("Expected string token at the end of import statement.");
|
|
42013
42013
|
}
|
|
42014
|
-
const
|
|
42015
|
-
const importInfo = this.getImportInfo(
|
|
42014
|
+
const path34 = this.tokens.stringValueAtIndex(index);
|
|
42015
|
+
const importInfo = this.getImportInfo(path34);
|
|
42016
42016
|
importInfo.defaultNames.push(...defaultNames);
|
|
42017
42017
|
importInfo.wildcardNames.push(...wildcardNames);
|
|
42018
42018
|
importInfo.namedImports.push(...namedImports);
|
|
@@ -42079,8 +42079,8 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
42079
42079
|
if (!this.tokens.matches1AtIndex(index, _types.TokenType.string)) {
|
|
42080
42080
|
throw new Error("Expected string token at the end of import statement.");
|
|
42081
42081
|
}
|
|
42082
|
-
const
|
|
42083
|
-
const importInfo = this.getImportInfo(
|
|
42082
|
+
const path34 = this.tokens.stringValueAtIndex(index);
|
|
42083
|
+
const importInfo = this.getImportInfo(path34);
|
|
42084
42084
|
importInfo.namedExports.push(...namedImports);
|
|
42085
42085
|
}
|
|
42086
42086
|
preprocessExportStarAtIndex(index) {
|
|
@@ -42095,8 +42095,8 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
42095
42095
|
if (!this.tokens.matches1AtIndex(index, _types.TokenType.string)) {
|
|
42096
42096
|
throw new Error("Expected string token at the end of star export statement.");
|
|
42097
42097
|
}
|
|
42098
|
-
const
|
|
42099
|
-
const importInfo = this.getImportInfo(
|
|
42098
|
+
const path34 = this.tokens.stringValueAtIndex(index);
|
|
42099
|
+
const importInfo = this.getImportInfo(path34);
|
|
42100
42100
|
if (exportedName !== null) {
|
|
42101
42101
|
importInfo.exportStarNames.push(exportedName);
|
|
42102
42102
|
} else {
|
|
@@ -42136,8 +42136,8 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
42136
42136
|
* Get a mutable import info object for this path, creating one if it doesn't
|
|
42137
42137
|
* exist yet.
|
|
42138
42138
|
*/
|
|
42139
|
-
getImportInfo(
|
|
42140
|
-
const existingInfo = this.importInfoByPath.get(
|
|
42139
|
+
getImportInfo(path34) {
|
|
42140
|
+
const existingInfo = this.importInfoByPath.get(path34);
|
|
42141
42141
|
if (existingInfo) {
|
|
42142
42142
|
return existingInfo;
|
|
42143
42143
|
}
|
|
@@ -42150,7 +42150,7 @@ var require_CJSImportProcessor = __commonJS({
|
|
|
42150
42150
|
exportStarNames: [],
|
|
42151
42151
|
hasStarExport: false
|
|
42152
42152
|
};
|
|
42153
|
-
this.importInfoByPath.set(
|
|
42153
|
+
this.importInfoByPath.set(path34, newInfo);
|
|
42154
42154
|
return newInfo;
|
|
42155
42155
|
}
|
|
42156
42156
|
addExportBinding(localName, exportedName) {
|
|
@@ -42730,16 +42730,16 @@ var require_resolve_uri_umd = __commonJS({
|
|
|
42730
42730
|
}
|
|
42731
42731
|
function parseFileUrl(input) {
|
|
42732
42732
|
const match = fileRegex.exec(input);
|
|
42733
|
-
const
|
|
42734
|
-
return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(
|
|
42733
|
+
const path34 = match[2];
|
|
42734
|
+
return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path34) ? path34 : "/" + path34, match[3] || "", match[4] || "");
|
|
42735
42735
|
}
|
|
42736
|
-
function makeUrl(scheme, user, host, port,
|
|
42736
|
+
function makeUrl(scheme, user, host, port, path34, query, hash) {
|
|
42737
42737
|
return {
|
|
42738
42738
|
scheme,
|
|
42739
42739
|
user,
|
|
42740
42740
|
host,
|
|
42741
42741
|
port,
|
|
42742
|
-
path:
|
|
42742
|
+
path: path34,
|
|
42743
42743
|
query,
|
|
42744
42744
|
hash,
|
|
42745
42745
|
type: 7
|
|
@@ -42769,11 +42769,11 @@ var require_resolve_uri_umd = __commonJS({
|
|
|
42769
42769
|
url.type = input ? input.startsWith("?") ? 3 : input.startsWith("#") ? 2 : 4 : 1;
|
|
42770
42770
|
return url;
|
|
42771
42771
|
}
|
|
42772
|
-
function stripPathFilename(
|
|
42773
|
-
if (
|
|
42774
|
-
return
|
|
42775
|
-
const index =
|
|
42776
|
-
return
|
|
42772
|
+
function stripPathFilename(path34) {
|
|
42773
|
+
if (path34.endsWith("/.."))
|
|
42774
|
+
return path34;
|
|
42775
|
+
const index = path34.lastIndexOf("/");
|
|
42776
|
+
return path34.slice(0, index + 1);
|
|
42777
42777
|
}
|
|
42778
42778
|
function mergePaths(url, base) {
|
|
42779
42779
|
normalizePath(base, base.type);
|
|
@@ -42811,14 +42811,14 @@ var require_resolve_uri_umd = __commonJS({
|
|
|
42811
42811
|
pieces[pointer++] = piece;
|
|
42812
42812
|
positive++;
|
|
42813
42813
|
}
|
|
42814
|
-
let
|
|
42814
|
+
let path34 = "";
|
|
42815
42815
|
for (let i = 1; i < pointer; i++) {
|
|
42816
|
-
|
|
42816
|
+
path34 += "/" + pieces[i];
|
|
42817
42817
|
}
|
|
42818
|
-
if (!
|
|
42819
|
-
|
|
42818
|
+
if (!path34 || addTrailingSlash && !path34.endsWith("/..")) {
|
|
42819
|
+
path34 += "/";
|
|
42820
42820
|
}
|
|
42821
|
-
url.path =
|
|
42821
|
+
url.path = path34;
|
|
42822
42822
|
}
|
|
42823
42823
|
function resolve2(input, base) {
|
|
42824
42824
|
if (!input && !base)
|
|
@@ -42859,13 +42859,13 @@ var require_resolve_uri_umd = __commonJS({
|
|
|
42859
42859
|
case 3:
|
|
42860
42860
|
return queryHash;
|
|
42861
42861
|
case 4: {
|
|
42862
|
-
const
|
|
42863
|
-
if (!
|
|
42862
|
+
const path34 = url.path.slice(1);
|
|
42863
|
+
if (!path34)
|
|
42864
42864
|
return queryHash || ".";
|
|
42865
|
-
if (isRelative(base || input) && !isRelative(
|
|
42866
|
-
return "./" +
|
|
42865
|
+
if (isRelative(base || input) && !isRelative(path34)) {
|
|
42866
|
+
return "./" + path34 + queryHash;
|
|
42867
42867
|
}
|
|
42868
|
-
return
|
|
42868
|
+
return path34 + queryHash;
|
|
42869
42869
|
}
|
|
42870
42870
|
case 5:
|
|
42871
42871
|
return url.path + queryHash;
|
|
@@ -42964,10 +42964,10 @@ var require_trace_mapping_umd = __commonJS({
|
|
|
42964
42964
|
module2.exports = __toCommonJS(trace_mapping_exports);
|
|
42965
42965
|
var import_sourcemap_codec = __toESM2(require_sourcemap_codec());
|
|
42966
42966
|
var import_resolve_uri = __toESM2(require_resolve_uri());
|
|
42967
|
-
function stripFilename(
|
|
42968
|
-
if (!
|
|
42969
|
-
const index =
|
|
42970
|
-
return
|
|
42967
|
+
function stripFilename(path34) {
|
|
42968
|
+
if (!path34) return "";
|
|
42969
|
+
const index = path34.lastIndexOf("/");
|
|
42970
|
+
return path34.slice(0, index + 1);
|
|
42971
42971
|
}
|
|
42972
42972
|
function resolver(mapUrl, sourceRoot) {
|
|
42973
42973
|
const from = stripFilename(mapUrl);
|
|
@@ -43091,11 +43091,11 @@ var require_trace_mapping_umd = __commonJS({
|
|
|
43091
43091
|
state.lastNeedle = needle;
|
|
43092
43092
|
return state.lastIndex = binarySearch(haystack, needle, low, high);
|
|
43093
43093
|
}
|
|
43094
|
-
function
|
|
43094
|
+
function parse2(map2) {
|
|
43095
43095
|
return typeof map2 === "string" ? JSON.parse(map2) : map2;
|
|
43096
43096
|
}
|
|
43097
43097
|
var FlattenMap = function(map2, mapUrl) {
|
|
43098
|
-
const parsed =
|
|
43098
|
+
const parsed = parse2(map2);
|
|
43099
43099
|
if (!("sections" in parsed)) {
|
|
43100
43100
|
return new TraceMap(parsed, mapUrl);
|
|
43101
43101
|
}
|
|
@@ -43159,7 +43159,7 @@ var require_trace_mapping_umd = __commonJS({
|
|
|
43159
43159
|
}
|
|
43160
43160
|
}
|
|
43161
43161
|
function addSection(input, mapUrl, mappings, sources, sourcesContent, names2, ignoreList, lineOffset, columnOffset, stopLine, stopColumn) {
|
|
43162
|
-
const parsed =
|
|
43162
|
+
const parsed = parse2(input);
|
|
43163
43163
|
if ("sections" in parsed) return recurse(...arguments);
|
|
43164
43164
|
const map2 = new TraceMap(parsed, mapUrl);
|
|
43165
43165
|
const sourcesOffset = sources.length;
|
|
@@ -43209,7 +43209,7 @@ var require_trace_mapping_umd = __commonJS({
|
|
|
43209
43209
|
constructor(map2, mapUrl) {
|
|
43210
43210
|
const isString = typeof map2 === "string";
|
|
43211
43211
|
if (!isString && map2._decodedMemo) return map2;
|
|
43212
|
-
const parsed =
|
|
43212
|
+
const parsed = parse2(map2);
|
|
43213
43213
|
const { version, file: file2, names: names2, sourceRoot, sources, sourcesContent } = parsed;
|
|
43214
43214
|
this.version = version;
|
|
43215
43215
|
this.file = file2;
|
|
@@ -44175,9 +44175,9 @@ var require_util2 = __commonJS({
|
|
|
44175
44175
|
/** @class */
|
|
44176
44176
|
(function(_super) {
|
|
44177
44177
|
__extends(VError2, _super);
|
|
44178
|
-
function VError2(
|
|
44178
|
+
function VError2(path34, message) {
|
|
44179
44179
|
var _this = _super.call(this, message) || this;
|
|
44180
|
-
_this.path =
|
|
44180
|
+
_this.path = path34;
|
|
44181
44181
|
Object.setPrototypeOf(_this, VError2.prototype);
|
|
44182
44182
|
return _this;
|
|
44183
44183
|
}
|
|
@@ -44237,26 +44237,26 @@ var require_util2 = __commonJS({
|
|
|
44237
44237
|
(_b = this._messages).push.apply(_b, best._messages);
|
|
44238
44238
|
}
|
|
44239
44239
|
};
|
|
44240
|
-
DetailContext2.prototype.getError = function(
|
|
44240
|
+
DetailContext2.prototype.getError = function(path34) {
|
|
44241
44241
|
var msgParts = [];
|
|
44242
44242
|
for (var i = this._propNames.length - 1; i >= 0; i--) {
|
|
44243
44243
|
var p2 = this._propNames[i];
|
|
44244
|
-
|
|
44244
|
+
path34 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
|
|
44245
44245
|
var m = this._messages[i];
|
|
44246
44246
|
if (m) {
|
|
44247
|
-
msgParts.push(
|
|
44247
|
+
msgParts.push(path34 + " " + m);
|
|
44248
44248
|
}
|
|
44249
44249
|
}
|
|
44250
|
-
return new VError(
|
|
44250
|
+
return new VError(path34, msgParts.join("; "));
|
|
44251
44251
|
};
|
|
44252
|
-
DetailContext2.prototype.getErrorDetail = function(
|
|
44252
|
+
DetailContext2.prototype.getErrorDetail = function(path34) {
|
|
44253
44253
|
var details = [];
|
|
44254
44254
|
for (var i = this._propNames.length - 1; i >= 0; i--) {
|
|
44255
44255
|
var p2 = this._propNames[i];
|
|
44256
|
-
|
|
44256
|
+
path34 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
|
|
44257
44257
|
var message = this._messages[i];
|
|
44258
44258
|
if (message) {
|
|
44259
|
-
details.push({ path:
|
|
44259
|
+
details.push({ path: path34, message });
|
|
44260
44260
|
}
|
|
44261
44261
|
}
|
|
44262
44262
|
var detail = null;
|
|
@@ -45069,8 +45069,8 @@ var require_dist = __commonJS({
|
|
|
45069
45069
|
this.checkerPlain = this.ttype.getChecker(suite, false);
|
|
45070
45070
|
this.checkerStrict = this.ttype.getChecker(suite, true);
|
|
45071
45071
|
}
|
|
45072
|
-
Checker2.prototype.setReportedPath = function(
|
|
45073
|
-
this._path =
|
|
45072
|
+
Checker2.prototype.setReportedPath = function(path34) {
|
|
45073
|
+
this._path = path34;
|
|
45074
45074
|
};
|
|
45075
45075
|
Checker2.prototype.check = function(value) {
|
|
45076
45076
|
return this._doCheck(this.checkerPlain, value);
|
|
@@ -49654,7 +49654,7 @@ var require_parser = __commonJS({
|
|
|
49654
49654
|
}
|
|
49655
49655
|
};
|
|
49656
49656
|
exports.File = File;
|
|
49657
|
-
function
|
|
49657
|
+
function parse2(input, isJSXEnabled, isTypeScriptEnabled, isFlowEnabled) {
|
|
49658
49658
|
if (isFlowEnabled && isTypeScriptEnabled) {
|
|
49659
49659
|
throw new Error("Cannot combine flow and typescript plugins.");
|
|
49660
49660
|
}
|
|
@@ -49665,7 +49665,7 @@ var require_parser = __commonJS({
|
|
|
49665
49665
|
}
|
|
49666
49666
|
return result;
|
|
49667
49667
|
}
|
|
49668
|
-
exports.parse =
|
|
49668
|
+
exports.parse = parse2;
|
|
49669
49669
|
}
|
|
49670
49670
|
});
|
|
49671
49671
|
|
|
@@ -50503,9 +50503,9 @@ var require_CJSImportTransformer = __commonJS({
|
|
|
50503
50503
|
if (shouldElideImport) {
|
|
50504
50504
|
this.tokens.removeToken();
|
|
50505
50505
|
} else {
|
|
50506
|
-
const
|
|
50507
|
-
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(
|
|
50508
|
-
this.tokens.appendCode(this.importProcessor.claimImportCode(
|
|
50506
|
+
const path34 = this.tokens.stringValue();
|
|
50507
|
+
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path34));
|
|
50508
|
+
this.tokens.appendCode(this.importProcessor.claimImportCode(path34));
|
|
50509
50509
|
}
|
|
50510
50510
|
_removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
|
|
50511
50511
|
if (this.tokens.matches1(_types.TokenType.semi)) {
|
|
@@ -51085,8 +51085,8 @@ var require_CJSImportTransformer = __commonJS({
|
|
|
51085
51085
|
}
|
|
51086
51086
|
if (this.tokens.matchesContextual(_keywords.ContextualKeyword._from)) {
|
|
51087
51087
|
this.tokens.removeToken();
|
|
51088
|
-
const
|
|
51089
|
-
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(
|
|
51088
|
+
const path34 = this.tokens.stringValue();
|
|
51089
|
+
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path34));
|
|
51090
51090
|
_removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
|
|
51091
51091
|
} else {
|
|
51092
51092
|
this.tokens.appendCode(exportStatements.join(" "));
|
|
@@ -51100,8 +51100,8 @@ var require_CJSImportTransformer = __commonJS({
|
|
|
51100
51100
|
while (!this.tokens.matches1(_types.TokenType.string)) {
|
|
51101
51101
|
this.tokens.removeToken();
|
|
51102
51102
|
}
|
|
51103
|
-
const
|
|
51104
|
-
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(
|
|
51103
|
+
const path34 = this.tokens.stringValue();
|
|
51104
|
+
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path34));
|
|
51105
51105
|
_removeMaybeImportAttributes.removeMaybeImportAttributes.call(void 0, this.tokens);
|
|
51106
51106
|
if (this.tokens.matches1(_types.TokenType.semi)) {
|
|
51107
51107
|
this.tokens.removeToken();
|
|
@@ -80745,9 +80745,9 @@ var init_bundle_mjs = __esm({
|
|
|
80745
80745
|
processClassesRecursively(value, getPart(classPartObject, key), classGroupId, theme);
|
|
80746
80746
|
}
|
|
80747
80747
|
};
|
|
80748
|
-
getPart = (classPartObject,
|
|
80748
|
+
getPart = (classPartObject, path34) => {
|
|
80749
80749
|
let current = classPartObject;
|
|
80750
|
-
const parts =
|
|
80750
|
+
const parts = path34.split(CLASS_PART_SEPARATOR);
|
|
80751
80751
|
const len = parts.length;
|
|
80752
80752
|
for (let i = 0; i < len; i++) {
|
|
80753
80753
|
const part = parts[i];
|
|
@@ -84001,8 +84001,8 @@ var mockup_exports = {};
|
|
|
84001
84001
|
__export(mockup_exports, {
|
|
84002
84002
|
drawMockup: () => drawMockup
|
|
84003
84003
|
});
|
|
84004
|
-
import
|
|
84005
|
-
import
|
|
84004
|
+
import fs19 from "node:fs";
|
|
84005
|
+
import path22 from "node:path";
|
|
84006
84006
|
import vm from "node:vm";
|
|
84007
84007
|
async function loadPackage(id) {
|
|
84008
84008
|
if (id === "react") return import_react3.default;
|
|
@@ -84015,20 +84015,20 @@ async function loadPackage(id) {
|
|
|
84015
84015
|
return { __esModule: true, ...await load() };
|
|
84016
84016
|
}
|
|
84017
84017
|
function resolveFile(id, from, folder) {
|
|
84018
|
-
const at2 =
|
|
84019
|
-
if (at2 !== folder && !at2.startsWith(folder +
|
|
84020
|
-
const tries =
|
|
84021
|
-
const file2 = tries.find((f2) =>
|
|
84018
|
+
const at2 = path22.resolve(path22.dirname(from), id);
|
|
84019
|
+
if (at2 !== folder && !at2.startsWith(folder + path22.sep)) throw new Error(`${id} is outside the mockup's folder`);
|
|
84020
|
+
const tries = path22.extname(at2) ? [at2] : [...CODE_EXTS.map((e2) => at2 + e2), ...CODE_EXTS.map((e2) => path22.join(at2, `index${e2}`))];
|
|
84021
|
+
const file2 = tries.find((f2) => fs19.statSync(f2, { throwIfNoEntry: false })?.isFile());
|
|
84022
84022
|
if (!file2) throw new Error(`no such file: ${id}`);
|
|
84023
84023
|
return file2;
|
|
84024
84024
|
}
|
|
84025
84025
|
async function readGraph(entry) {
|
|
84026
|
-
const folder =
|
|
84026
|
+
const folder = path22.dirname(entry);
|
|
84027
84027
|
const graph = { code: /* @__PURE__ */ new Map(), links: /* @__PURE__ */ new Map(), sheets: [], packages: /* @__PURE__ */ new Map() };
|
|
84028
84028
|
const walk = async (file2) => {
|
|
84029
84029
|
if (graph.code.has(file2)) return;
|
|
84030
84030
|
if (graph.code.size >= MAX_FILES) throw new Error(`a mockup imports more than ${MAX_FILES} files`);
|
|
84031
|
-
const js = (0, import_sucrase.transform)(
|
|
84031
|
+
const js = (0, import_sucrase.transform)(fs19.readFileSync(file2, "utf8"), { transforms: ["typescript", "jsx", "imports"], jsxRuntime: "automatic", production: true, filePath: file2 }).code;
|
|
84032
84032
|
graph.code.set(file2, js);
|
|
84033
84033
|
const link = /* @__PURE__ */ new Map();
|
|
84034
84034
|
graph.links.set(file2, link);
|
|
@@ -84040,7 +84040,7 @@ async function readGraph(entry) {
|
|
|
84040
84040
|
const target = resolveFile(id, file2, folder);
|
|
84041
84041
|
link.set(id, target);
|
|
84042
84042
|
if (!target.endsWith(".css")) await walk(target);
|
|
84043
|
-
else if (!graph.sheets.some((s) => s.path === target)) graph.sheets.push({ path: target, content:
|
|
84043
|
+
else if (!graph.sheets.some((s) => s.path === target)) graph.sheets.push({ path: target, content: fs19.readFileSync(target, "utf8") });
|
|
84044
84044
|
}
|
|
84045
84045
|
};
|
|
84046
84046
|
await walk(entry);
|
|
@@ -84054,25 +84054,25 @@ function run(script, context, name, deadline) {
|
|
|
84054
84054
|
async function tailwindFor(markup, sheets) {
|
|
84055
84055
|
const source = sheets.length ? sheets.map((s) => s.content).join("\n") : '@import "tailwindcss";';
|
|
84056
84056
|
const compiler = await zf(source, {
|
|
84057
|
-
base: sheets.length ?
|
|
84057
|
+
base: sheets.length ? path22.dirname(sheets[0].path) : "/",
|
|
84058
84058
|
loadStylesheet: async (id, from) => {
|
|
84059
84059
|
if (id === "tailwindcss" || id.startsWith("tailwindcss/")) return { path: "tailwindcss/index.css", base: "/", content: tailwindcss_default };
|
|
84060
84060
|
if (!id.startsWith(".")) throw new Error(`a mockup cannot import ${id}`);
|
|
84061
|
-
const at2 =
|
|
84062
|
-
return { path: at2, base:
|
|
84061
|
+
const at2 = path22.resolve(from, id);
|
|
84062
|
+
return { path: at2, base: path22.dirname(at2), content: fs19.readFileSync(at2, "utf8") };
|
|
84063
84063
|
}
|
|
84064
84064
|
});
|
|
84065
84065
|
const classes = [...markup.matchAll(/class="([^"]*)"/g)].flatMap((m) => m[1].split(/\s+/));
|
|
84066
84066
|
return compiler.build(classes.filter(Boolean));
|
|
84067
84067
|
}
|
|
84068
84068
|
function dressPage(file2) {
|
|
84069
|
-
const folder =
|
|
84070
|
-
const html =
|
|
84069
|
+
const folder = path22.dirname(file2);
|
|
84070
|
+
const html = fs19.readFileSync(file2, "utf8").replace(/<link\b[^>]*>/gi, (tag) => {
|
|
84071
84071
|
const href = /\bhref\s*=\s*["']?([^"'\s>]+)/i.exec(tag)?.[1];
|
|
84072
84072
|
if (!/\brel\s*=\s*["']?stylesheet/i.test(tag) || !href || /^[a-z][\w+.-]*:|^\/\//i.test(href)) return tag;
|
|
84073
|
-
const at3 =
|
|
84074
|
-
if (!at3.startsWith(folder +
|
|
84075
|
-
return `<style>${
|
|
84073
|
+
const at3 = path22.resolve(folder, href);
|
|
84074
|
+
if (!at3.startsWith(folder + path22.sep) || !fs19.existsSync(at3)) return tag;
|
|
84075
|
+
return `<style>${fs19.readFileSync(at3, "utf8").replace(/<\/style/gi, "<\\/style")}</style>`;
|
|
84076
84076
|
});
|
|
84077
84077
|
const at2 = /^\uFEFF?\s*(?:<!--[\s\S]*?-->\s*)*(?:<!doctype\b[^>]*>)?/i.exec(html)[0].length;
|
|
84078
84078
|
return /<!doctype\b|<html[\s>]|<head[\s>]/i.test(html) ? html.slice(0, at2) + head + html.slice(at2) : `<!doctype html><html><head>${head}</head><body>${html}</body></html>`;
|
|
@@ -84224,10 +84224,10 @@ function readSession() {
|
|
|
84224
84224
|
return null;
|
|
84225
84225
|
}
|
|
84226
84226
|
try {
|
|
84227
|
-
const
|
|
84228
|
-
if (!
|
|
84229
|
-
if (
|
|
84230
|
-
return { ...
|
|
84227
|
+
const held4 = JSON.parse(raw);
|
|
84228
|
+
if (!held4.accessToken || !held4.refreshToken || !held4.subject) return null;
|
|
84229
|
+
if (held4.supabaseUrl !== cloudEndpoints().supabaseUrl) return null;
|
|
84230
|
+
return { ...held4, version: 1, expiresAt: Number(held4.expiresAt) || 0 };
|
|
84231
84231
|
} catch {
|
|
84232
84232
|
return null;
|
|
84233
84233
|
}
|
|
@@ -84246,9 +84246,9 @@ function clearSession() {
|
|
|
84246
84246
|
}
|
|
84247
84247
|
}
|
|
84248
84248
|
async function accessToken() {
|
|
84249
|
-
const
|
|
84250
|
-
if (!
|
|
84251
|
-
if (!expiringSoon(
|
|
84249
|
+
const held4 = readSession();
|
|
84250
|
+
if (!held4) return { ok: false, reason: "signed-out" };
|
|
84251
|
+
if (!expiringSoon(held4)) return { ok: true, token: held4.accessToken, session: held4 };
|
|
84252
84252
|
return refresh();
|
|
84253
84253
|
}
|
|
84254
84254
|
var expiringSoon = (session) => session.expiresAt - REFRESH_MARGIN_MS <= Date.now();
|
|
@@ -84333,14 +84333,14 @@ async function takeLock() {
|
|
|
84333
84333
|
}
|
|
84334
84334
|
}
|
|
84335
84335
|
function stale() {
|
|
84336
|
-
let
|
|
84336
|
+
let held4;
|
|
84337
84337
|
try {
|
|
84338
84338
|
const pid = Number(fs.readFileSync(lockOwner(), "utf8").trim());
|
|
84339
|
-
|
|
84339
|
+
held4 = Number.isInteger(pid) && pid > 0 ? pid : void 0;
|
|
84340
84340
|
} catch {
|
|
84341
|
-
|
|
84341
|
+
held4 = void 0;
|
|
84342
84342
|
}
|
|
84343
|
-
if (
|
|
84343
|
+
if (held4 !== void 0 && !alive(held4)) return true;
|
|
84344
84344
|
try {
|
|
84345
84345
|
return Date.now() - fs.statSync(lockDir()).mtimeMs > LOCK_STALE_MS;
|
|
84346
84346
|
} catch {
|
|
@@ -84371,8 +84371,8 @@ function useRunnerHome() {
|
|
|
84371
84371
|
function machineId() {
|
|
84372
84372
|
const file2 = path3.join(runnerHome(), "machine.json");
|
|
84373
84373
|
try {
|
|
84374
|
-
const
|
|
84375
|
-
if (
|
|
84374
|
+
const held4 = JSON.parse(fs2.readFileSync(file2, "utf8"));
|
|
84375
|
+
if (held4.id && /^[0-9a-f-]{36}$/i.test(held4.id)) return held4.id;
|
|
84376
84376
|
} catch {
|
|
84377
84377
|
}
|
|
84378
84378
|
const id = crypto.randomUUID();
|
|
@@ -84453,7 +84453,9 @@ function status(line) {
|
|
|
84453
84453
|
}
|
|
84454
84454
|
|
|
84455
84455
|
// src/protocol.ts
|
|
84456
|
-
var VERSION = true ? "0.6.
|
|
84456
|
+
var VERSION = true ? "0.6.4" : "0.0.0";
|
|
84457
|
+
var AKB_VERSION = true ? "0.11.3" : "0.0.0";
|
|
84458
|
+
var AKB_CONTRACT = true ? 1 : 0;
|
|
84457
84459
|
var EXIT_REFUSED = 10;
|
|
84458
84460
|
var EXIT_OUTDATED = 11;
|
|
84459
84461
|
|
|
@@ -84918,16 +84920,16 @@ function createEventCollector() {
|
|
|
84918
84920
|
let queue = [];
|
|
84919
84921
|
let said = "";
|
|
84920
84922
|
const todoCalls = /* @__PURE__ */ new Set();
|
|
84921
|
-
const
|
|
84923
|
+
const held4 = /* @__PURE__ */ new Map();
|
|
84922
84924
|
let todos = [];
|
|
84923
84925
|
const close = () => {
|
|
84924
84926
|
if (said.trim()) queue.push({ kind: "message", data: { text: said.trim() } });
|
|
84925
84927
|
said = "";
|
|
84926
84928
|
};
|
|
84927
84929
|
const release2 = (id, target) => {
|
|
84928
|
-
const call =
|
|
84930
|
+
const call = held4.get(id);
|
|
84929
84931
|
if (!call) return;
|
|
84930
|
-
|
|
84932
|
+
held4.delete(id);
|
|
84931
84933
|
queue.push({ kind: "tool_call", data: { ...call, ...target ? { target } : {} } });
|
|
84932
84934
|
};
|
|
84933
84935
|
return {
|
|
@@ -84949,7 +84951,7 @@ function createEventCollector() {
|
|
|
84949
84951
|
}
|
|
84950
84952
|
const target = targetIn(u2);
|
|
84951
84953
|
const data = { toolCallId: id, title: str(u2.title) || "tool", kind: toolKind(u2.kind), status: str(u2.status) || "pending", ...target ? { target } : {} };
|
|
84952
|
-
if (u2.rawInput !== void 0 && !inputTarget(obj(u2.rawInput)))
|
|
84954
|
+
if (u2.rawInput !== void 0 && !inputTarget(obj(u2.rawInput))) held4.set(id, data);
|
|
84953
84955
|
else queue.push({ kind: "tool_call", data });
|
|
84954
84956
|
return;
|
|
84955
84957
|
}
|
|
@@ -85019,7 +85021,7 @@ function createEventCollector() {
|
|
|
85019
85021
|
/** The turn is over: a half-held message is finished off. */
|
|
85020
85022
|
end() {
|
|
85021
85023
|
close();
|
|
85022
|
-
for (const id of [...
|
|
85024
|
+
for (const id of [...held4.keys()]) release2(id);
|
|
85023
85025
|
},
|
|
85024
85026
|
/** What arrived since the last call. */
|
|
85025
85027
|
events() {
|
|
@@ -85115,12 +85117,19 @@ function promptSize(raw) {
|
|
|
85115
85117
|
const size = num(u2.input_tokens) + num(u2.cache_creation_input_tokens) + num(u2.cache_read_input_tokens);
|
|
85116
85118
|
return size > 0 ? size : void 0;
|
|
85117
85119
|
}
|
|
85120
|
+
function windowOf(raw, model) {
|
|
85121
|
+
const entries = obj(raw);
|
|
85122
|
+
const names2 = Object.keys(entries);
|
|
85123
|
+
const name = model && names2.includes(model) ? model : names2.length === 1 ? names2[0] : void 0;
|
|
85124
|
+
return name ? num(obj(entries[name]).contextWindow) || void 0 : void 0;
|
|
85125
|
+
}
|
|
85118
85126
|
function createStreamRenderer() {
|
|
85119
85127
|
let final;
|
|
85120
85128
|
let cost;
|
|
85121
85129
|
let model;
|
|
85122
85130
|
let usage;
|
|
85123
85131
|
let context;
|
|
85132
|
+
let limit;
|
|
85124
85133
|
let failure;
|
|
85125
85134
|
let offStream;
|
|
85126
85135
|
let background;
|
|
@@ -85175,6 +85184,7 @@ function createStreamRenderer() {
|
|
|
85175
85184
|
}
|
|
85176
85185
|
case "result": {
|
|
85177
85186
|
if (typeof ev.result === "string") final = ev.result;
|
|
85187
|
+
limit = windowOf(ev.modelUsage, model) ?? limit;
|
|
85178
85188
|
if (typeof ev.total_cost_usd === "number" && Number.isFinite(ev.total_cost_usd) && ev.total_cost_usd > 0) {
|
|
85179
85189
|
cost = ev.total_cost_usd;
|
|
85180
85190
|
}
|
|
@@ -85209,7 +85219,7 @@ function createStreamRenderer() {
|
|
|
85209
85219
|
result: () => final,
|
|
85210
85220
|
costUsd: () => cost,
|
|
85211
85221
|
usage: () => usage,
|
|
85212
|
-
context: () => context,
|
|
85222
|
+
context: () => context && limit ? { ...context, limit } : context,
|
|
85213
85223
|
model: () => model,
|
|
85214
85224
|
failure: () => failure,
|
|
85215
85225
|
offStream: () => offStream,
|
|
@@ -85299,10 +85309,10 @@ function findRollout(threadId) {
|
|
|
85299
85309
|
}
|
|
85300
85310
|
for (const name of names2) {
|
|
85301
85311
|
if (!name.startsWith("rollout-") || !name.endsWith(tail)) continue;
|
|
85302
|
-
const
|
|
85312
|
+
const path34 = join(dir, name);
|
|
85303
85313
|
try {
|
|
85304
|
-
const at2 = statSync(
|
|
85305
|
-
if (!newest2 || at2 > newest2.at) newest2 = { path:
|
|
85314
|
+
const at2 = statSync(path34).mtimeMs;
|
|
85315
|
+
if (!newest2 || at2 > newest2.at) newest2 = { path: path34, at: at2 };
|
|
85306
85316
|
} catch {
|
|
85307
85317
|
}
|
|
85308
85318
|
}
|
|
@@ -85310,11 +85320,11 @@ function findRollout(threadId) {
|
|
|
85310
85320
|
return newest2?.path;
|
|
85311
85321
|
}
|
|
85312
85322
|
function readCodexRunFacts(threadId) {
|
|
85313
|
-
const
|
|
85314
|
-
if (!
|
|
85323
|
+
const path34 = findRollout(threadId);
|
|
85324
|
+
if (!path34) return void 0;
|
|
85315
85325
|
let raw;
|
|
85316
85326
|
try {
|
|
85317
|
-
raw = readFileSync(
|
|
85327
|
+
raw = readFileSync(path34, "utf8");
|
|
85318
85328
|
} catch {
|
|
85319
85329
|
return void 0;
|
|
85320
85330
|
}
|
|
@@ -85422,8 +85432,8 @@ function renderCompleted(item) {
|
|
|
85422
85432
|
const changes = Array.isArray(item.changes) ? item.changes : [];
|
|
85423
85433
|
return changes.map((raw) => {
|
|
85424
85434
|
const change = obj(raw);
|
|
85425
|
-
const
|
|
85426
|
-
return
|
|
85435
|
+
const path34 = str(change.path);
|
|
85436
|
+
return path34 ? `\u23FA ${str(change.kind) || "change"}(${path34})
|
|
85427
85437
|
` : "";
|
|
85428
85438
|
}).join("");
|
|
85429
85439
|
}
|
|
@@ -85671,10 +85681,10 @@ function readKimiRunFacts(sessionId) {
|
|
|
85671
85681
|
const total = { input: 0, cacheCreation: 0, cacheRead: 0, output: 0 };
|
|
85672
85682
|
let model;
|
|
85673
85683
|
let holding = 0;
|
|
85674
|
-
for (const { path:
|
|
85684
|
+
for (const { path: path34, main: main2 } of wireFiles(entry.sessionDir)) {
|
|
85675
85685
|
let raw;
|
|
85676
85686
|
try {
|
|
85677
|
-
raw = readFileSync2(
|
|
85687
|
+
raw = readFileSync2(path34, "utf8");
|
|
85678
85688
|
} catch {
|
|
85679
85689
|
continue;
|
|
85680
85690
|
}
|
|
@@ -85927,8 +85937,62 @@ function createTail(log) {
|
|
|
85927
85937
|
};
|
|
85928
85938
|
}
|
|
85929
85939
|
|
|
85940
|
+
// ../cli/package.json
|
|
85941
|
+
var package_default = {
|
|
85942
|
+
name: "wildcrane",
|
|
85943
|
+
version: "0.11.3",
|
|
85944
|
+
akbContract: 1,
|
|
85945
|
+
description: "WildCrane's `akb` command \u2014 scaffold the Markdown board under docs/kanban/, put an agent on a card, and carry the flows the agent works by.",
|
|
85946
|
+
keywords: [
|
|
85947
|
+
"kanban",
|
|
85948
|
+
"claude",
|
|
85949
|
+
"claude-code",
|
|
85950
|
+
"codex",
|
|
85951
|
+
"agent",
|
|
85952
|
+
"skill",
|
|
85953
|
+
"markdown",
|
|
85954
|
+
"board"
|
|
85955
|
+
],
|
|
85956
|
+
license: "FSL-1.1-ALv2",
|
|
85957
|
+
homepage: "https://wildcrane.ai/",
|
|
85958
|
+
repository: {
|
|
85959
|
+
type: "git",
|
|
85960
|
+
url: "git+https://github.com/ai4kanban/ai4kanban.git",
|
|
85961
|
+
directory: "cli"
|
|
85962
|
+
},
|
|
85963
|
+
type: "module",
|
|
85964
|
+
bin: {
|
|
85965
|
+
akb: "bin/ai4kanban.mjs",
|
|
85966
|
+
wildcrane: "bin/ai4kanban.mjs"
|
|
85967
|
+
},
|
|
85968
|
+
files: [
|
|
85969
|
+
"bin/",
|
|
85970
|
+
"dist/"
|
|
85971
|
+
],
|
|
85972
|
+
engines: {
|
|
85973
|
+
node: ">=18.0.0"
|
|
85974
|
+
},
|
|
85975
|
+
scripts: {
|
|
85976
|
+
build: "node scripts/build.mjs",
|
|
85977
|
+
prepare: "node scripts/build.mjs",
|
|
85978
|
+
typecheck: "tsc -p tsconfig.json --noEmit",
|
|
85979
|
+
test: "node scripts/test.mjs",
|
|
85980
|
+
lint: "npm run typecheck",
|
|
85981
|
+
prepublishOnly: "npm run build",
|
|
85982
|
+
"eval:qa": "node scripts/qa-eval.mjs"
|
|
85983
|
+
},
|
|
85984
|
+
devDependencies: {
|
|
85985
|
+
"@types/node": "^22.20.1",
|
|
85986
|
+
esbuild: "^0.28.2",
|
|
85987
|
+
typescript: "^5.9.3"
|
|
85988
|
+
},
|
|
85989
|
+
dependencies: {
|
|
85990
|
+
commander: "^13.1.0"
|
|
85991
|
+
}
|
|
85992
|
+
};
|
|
85993
|
+
|
|
85930
85994
|
// ../cli/src/version.ts
|
|
85931
|
-
var SKILL_VERSION =
|
|
85995
|
+
var SKILL_VERSION = package_default.version;
|
|
85932
85996
|
|
|
85933
85997
|
// ../cli/src/lib/agent/wire/acp.ts
|
|
85934
85998
|
var PROTOCOL_VERSION = 1;
|
|
@@ -85938,8 +86002,8 @@ var CLIENT_CAPABILITIES = {
|
|
|
85938
86002
|
};
|
|
85939
86003
|
function whereHint(update2, title) {
|
|
85940
86004
|
const locations = Array.isArray(update2.locations) ? update2.locations : [];
|
|
85941
|
-
const
|
|
85942
|
-
return
|
|
86005
|
+
const path34 = str(obj(locations[0]).path);
|
|
86006
|
+
return path34 && !title.includes(path34) ? hint(path34) : "";
|
|
85943
86007
|
}
|
|
85944
86008
|
function saidBy(update2) {
|
|
85945
86009
|
const content = Array.isArray(update2.content) ? update2.content : [];
|
|
@@ -85967,9 +86031,9 @@ function modelsIn(answer) {
|
|
|
85967
86031
|
return modelId ? [{ modelId, name: str(m.name) || modelId }] : [];
|
|
85968
86032
|
});
|
|
85969
86033
|
}
|
|
85970
|
-
function pickedModel(answer,
|
|
86034
|
+
function pickedModel(answer, wanted2) {
|
|
85971
86035
|
const list = modelsIn(answer);
|
|
85972
|
-
return list.find((m) => m.modelId ===
|
|
86036
|
+
return list.find((m) => m.modelId === wanted2) ?? list.find((m) => m.name === wanted2 || m.modelId.split("[")[0] === wanted2);
|
|
85973
86037
|
}
|
|
85974
86038
|
function usageOf2(value, grossInput = false) {
|
|
85975
86039
|
const usage = obj(value);
|
|
@@ -86370,9 +86434,9 @@ async function oneTurn2(io, options) {
|
|
|
86370
86434
|
}
|
|
86371
86435
|
let model = modelOf2(obj(opened.session).model);
|
|
86372
86436
|
if (options.model) {
|
|
86373
|
-
const
|
|
86374
|
-
await rpc.call("session/setModel", { sessionId, model:
|
|
86375
|
-
model = modelOf2(
|
|
86437
|
+
const wanted2 = options.model.includes("/") ? { providerId: options.model.split("/")[0], modelId: options.model.split("/").slice(1).join("/") } : { providerId: str(obj(obj(opened.session).model).providerId) || "zai", modelId: options.model };
|
|
86438
|
+
await rpc.call("session/setModel", { sessionId, model: wanted2 });
|
|
86439
|
+
model = modelOf2(wanted2);
|
|
86376
86440
|
}
|
|
86377
86441
|
if (model) io.gotModel(model);
|
|
86378
86442
|
await rpc.call("session/subscribe", {
|
|
@@ -86879,7 +86943,6 @@ var CONFIG = "";
|
|
|
86879
86943
|
var KANBAN_GITIGNORE = "";
|
|
86880
86944
|
var RELEASES = "";
|
|
86881
86945
|
var RELEASE_SUMMARIES = "";
|
|
86882
|
-
var SETUP_CHECKLIST = "";
|
|
86883
86946
|
var AGENTS = "";
|
|
86884
86947
|
var WORKFLOWS = "";
|
|
86885
86948
|
var LEGACY_AGENTS = "";
|
|
@@ -86929,7 +86992,6 @@ function setBoard(kanban, root, flag) {
|
|
|
86929
86992
|
KANBAN_GITIGNORE = path9.join(KANBAN, ".gitignore");
|
|
86930
86993
|
RELEASES = path9.join(KANBAN, "releases.md");
|
|
86931
86994
|
RELEASE_SUMMARIES = path9.join(KANBAN, ".release-summaries");
|
|
86932
|
-
SETUP_CHECKLIST = path9.join(KANBAN, "setup-checklist.md");
|
|
86933
86995
|
AGENTS = path9.join(KANBAN, "agents");
|
|
86934
86996
|
WORKFLOWS = path9.join(KANBAN, "workflows");
|
|
86935
86997
|
LEGACY_AGENTS = path9.join(KANBAN, "skills");
|
|
@@ -87777,7 +87839,7 @@ ${text3}
|
|
|
87777
87839
|
// PROBE: on a machine that has `kimi`, run its login command's status form under a
|
|
87778
87840
|
// throwaway HOME and under the real one. If it says which state it is in, declare it here.
|
|
87779
87841
|
installs: () => [...process.env.KIMI_INSTALL_DIR ? [join5(process.env.KIMI_INSTALL_DIR, "bin", "kimi")] : [], home2(".kimi-code", "bin", "kimi")],
|
|
87780
|
-
install: "curl -
|
|
87842
|
+
install: "curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash"
|
|
87781
87843
|
};
|
|
87782
87844
|
|
|
87783
87845
|
// ../cli/src/lib/agent/harnesses/opencode.ts
|
|
@@ -88024,15 +88086,15 @@ function isFilled(harness, { values, secretsSet: secretsSet2 }) {
|
|
|
88024
88086
|
return setting?.kind === "secret" ? secretsSet2.includes(key) : Boolean(values[key]);
|
|
88025
88087
|
};
|
|
88026
88088
|
}
|
|
88027
|
-
function providerFor(harness,
|
|
88089
|
+
function providerFor(harness, held4) {
|
|
88028
88090
|
const setting = providerSetting(harness.settings);
|
|
88029
88091
|
if (!setting) return void 0;
|
|
88030
|
-
return pickedProvider(setting,
|
|
88092
|
+
return pickedProvider(setting, held4.values[setting.key] ?? "", isFilled(harness, held4));
|
|
88031
88093
|
}
|
|
88032
|
-
function settingArgs(harness,
|
|
88033
|
-
const { values } =
|
|
88034
|
-
const ignored =
|
|
88035
|
-
const picked = providerFor(harness,
|
|
88094
|
+
function settingArgs(harness, held4) {
|
|
88095
|
+
const { values } = held4;
|
|
88096
|
+
const ignored = held4.ignored ?? [];
|
|
88097
|
+
const picked = providerFor(harness, held4);
|
|
88036
88098
|
const list = providerSetting(harness.settings);
|
|
88037
88099
|
const byHand = !!list && ignored.includes(list.key);
|
|
88038
88100
|
const providerArgs = byHand ? [] : picked?.args ?? [];
|
|
@@ -88047,9 +88109,9 @@ function settingArgs(harness, held3) {
|
|
|
88047
88109
|
});
|
|
88048
88110
|
return [...providerArgs, ...flags, ...splitCommand(values[RAW_ARGS_KEY] ?? "")];
|
|
88049
88111
|
}
|
|
88050
|
-
function settingEnv(harness,
|
|
88051
|
-
const { values } =
|
|
88052
|
-
const picked = providerFor(harness,
|
|
88112
|
+
function settingEnv(harness, held4, secrets, cwd) {
|
|
88113
|
+
const { values } = held4;
|
|
88114
|
+
const picked = providerFor(harness, held4);
|
|
88053
88115
|
const env2 = { ...harness.env() };
|
|
88054
88116
|
for (const name of ownedVars(harness)) delete env2[name];
|
|
88055
88117
|
for (const name of Object.values(SESSION_VARS)) delete env2[name];
|
|
@@ -88076,11 +88138,11 @@ function ownedVars(harness) {
|
|
|
88076
88138
|
}
|
|
88077
88139
|
return [...names2];
|
|
88078
88140
|
}
|
|
88079
|
-
function effectiveValues(harness,
|
|
88080
|
-
const picked = providerFor(harness,
|
|
88141
|
+
function effectiveValues(harness, held4) {
|
|
88142
|
+
const picked = providerFor(harness, held4);
|
|
88081
88143
|
const out = {};
|
|
88082
88144
|
for (const setting of harness.settings) {
|
|
88083
|
-
const value =
|
|
88145
|
+
const value = held4.values[setting.key];
|
|
88084
88146
|
if (!value || setting.kind === "secret") continue;
|
|
88085
88147
|
if (!shownForProvider(harness.settings, setting.key, picked)) continue;
|
|
88086
88148
|
out[setting.key] = value;
|
|
@@ -88128,6 +88190,7 @@ __export(api_exports, {
|
|
|
88128
88190
|
readArtifact: () => readArtifact,
|
|
88129
88191
|
readBoard: () => readBoard,
|
|
88130
88192
|
readChat: () => readChat,
|
|
88193
|
+
readDecisions: () => readDecisions,
|
|
88131
88194
|
readDiscussion: () => readDiscussion,
|
|
88132
88195
|
readInbox: () => readInbox,
|
|
88133
88196
|
readPlan: () => readPlan,
|
|
@@ -88162,8 +88225,8 @@ import path12 from "node:path";
|
|
|
88162
88225
|
var file = () => path12.join(runnerHome(), "secrets.json");
|
|
88163
88226
|
function readAll() {
|
|
88164
88227
|
try {
|
|
88165
|
-
const
|
|
88166
|
-
return
|
|
88228
|
+
const held4 = JSON.parse(fs9.readFileSync(file(), "utf8"));
|
|
88229
|
+
return held4 && typeof held4 === "object" ? held4 : {};
|
|
88167
88230
|
} catch {
|
|
88168
88231
|
return {};
|
|
88169
88232
|
}
|
|
@@ -88171,12 +88234,12 @@ function readAll() {
|
|
|
88171
88234
|
var secretsOf = (runtime) => runtime ? readAll()[runtime] ?? {} : {};
|
|
88172
88235
|
function keepSecrets(runtime, given) {
|
|
88173
88236
|
const all = readAll();
|
|
88174
|
-
const
|
|
88237
|
+
const held4 = { ...all[runtime] };
|
|
88175
88238
|
for (const [key, value] of Object.entries(given)) {
|
|
88176
|
-
if (value)
|
|
88177
|
-
else delete
|
|
88239
|
+
if (value) held4[key] = value;
|
|
88240
|
+
else delete held4[key];
|
|
88178
88241
|
}
|
|
88179
|
-
if (Object.keys(
|
|
88242
|
+
if (Object.keys(held4).length) all[runtime] = held4;
|
|
88180
88243
|
else delete all[runtime];
|
|
88181
88244
|
fs9.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
|
|
88182
88245
|
const temp = `${file()}.${process.pid}.tmp`;
|
|
@@ -88242,7 +88305,7 @@ async function upload(route, bytes2, type) {
|
|
|
88242
88305
|
const sent = await send("PUT", route, bytes2, true, FILE_TIMEOUT_MS, type);
|
|
88243
88306
|
return sent.ok ? answerOf(sent.value) : sent;
|
|
88244
88307
|
}
|
|
88245
|
-
var register = (r2) => request("POST", "/v1/runner", { ...r2, secrets: secretsSet(), protocol: PROTOCOL });
|
|
88308
|
+
var register = (r2) => request("POST", "/v1/runner", { ...r2, secrets: secretsSet(), protocol: PROTOCOL, akbContract: AKB_CONTRACT });
|
|
88246
88309
|
var readRunner = () => request("GET", "/v1/runner");
|
|
88247
88310
|
var release = (machineId2) => request("POST", "/v1/runner/release", { machineId: machineId2 });
|
|
88248
88311
|
var listJobs = (machineId2) => request("GET", `/v1/runner/jobs?machine=${encodeURIComponent(machineId2)}`);
|
|
@@ -88265,6 +88328,7 @@ var finishJob = (machineId2, job, outcome, reason = "", report2) => move(job, "f
|
|
|
88265
88328
|
var answerDiff = (machineId2, id, answer) => request("POST", `/v1/runner/diffs/${encodeURIComponent(id)}`, { machineId: machineId2, ...answer });
|
|
88266
88329
|
var listChats = (machineId2) => request("GET", `/v1/runner/chats?machine=${encodeURIComponent(machineId2)}`);
|
|
88267
88330
|
var readChat = (task) => request("GET", `/v1/tasks/${encodeURIComponent(task)}/chat`);
|
|
88331
|
+
var readDecisions = (task, after) => request("GET", `/v1/tasks/${q(task)}/decisions?limit=100${after ? `&after=${q(after)}` : ""}`);
|
|
88268
88332
|
var dispatchReview = (machineId2, project, tasks, runtime, model) => request("POST", "/v1/runner/reviews", { machineId: machineId2, project, tasks, runtime, model });
|
|
88269
88333
|
var readAgents = (machineId2, project) => request("GET", `/v1/runner/agents?machine=${encodeURIComponent(machineId2)}&project=${encodeURIComponent(project)}`);
|
|
88270
88334
|
var requestAgent = (machineId2, project, agent, workflow, seen) => request("POST", "/v1/runner/jobs", { machineId: machineId2, project, agent, workflow, seen });
|
|
@@ -88279,7 +88343,7 @@ var listFolders = (machineId2) => request("GET", `/v1/runner/folders?machine=${q
|
|
|
88279
88343
|
var listElsewhere = (machineId2) => request("GET", `/v1/runner/folders?machine=${q(machineId2)}&elsewhere=1`);
|
|
88280
88344
|
var listMachineTasks = (machineId2) => request("GET", `/v1/runner/tasks?machine=${q(machineId2)}`);
|
|
88281
88345
|
var stopTask = (task, how) => request("POST", how === "chat" ? `/v1/tasks/${q(task)}/chat/stop` : `/v1/tasks/${q(task)}/stop`, {});
|
|
88282
|
-
var addFolder = (machineId2, name,
|
|
88346
|
+
var addFolder = (machineId2, name, path34, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path34, ...project ? { project } : {} });
|
|
88283
88347
|
var removeFolder = (machineId2, project) => request("POST", `/v1/runner/folders/${q(project)}/remove`, { machineId: machineId2 });
|
|
88284
88348
|
var readPlan = () => request("GET", "/v1/billing");
|
|
88285
88349
|
var startTrial = () => request("POST", "/v1/billing/trial", {});
|
|
@@ -88352,6 +88416,7 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88352
88416
|
if (harness.client) {
|
|
88353
88417
|
const client = harness.client(effectiveValues(harness, values));
|
|
88354
88418
|
let session;
|
|
88419
|
+
let named2;
|
|
88355
88420
|
return {
|
|
88356
88421
|
command: argv[0],
|
|
88357
88422
|
args: argv.slice(1),
|
|
@@ -88367,12 +88432,12 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88367
88432
|
gotResumeId: (got, restarted) => {
|
|
88368
88433
|
if (restarted || !session) session = got;
|
|
88369
88434
|
},
|
|
88370
|
-
gotModel: () =>
|
|
88371
|
-
},
|
|
88435
|
+
gotModel: (got) => named2 = got,
|
|
88372
88436
|
event: event2
|
|
88373
88437
|
}),
|
|
88374
88438
|
quiet,
|
|
88375
|
-
session: () => session ?? resume ?? void 0
|
|
88439
|
+
session: () => session ?? resume ?? void 0,
|
|
88440
|
+
model: () => named2
|
|
88376
88441
|
};
|
|
88377
88442
|
}
|
|
88378
88443
|
const renderer = harness.renderer(cwd, argv[0], argv);
|
|
@@ -88384,7 +88449,8 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88384
88449
|
stdin: toStdin?.(prompt),
|
|
88385
88450
|
renderer,
|
|
88386
88451
|
quiet,
|
|
88387
|
-
session: () => renderer.resumeId?.() ?? resume ?? (harness.adoptsSessionId ? id : void 0)
|
|
88452
|
+
session: () => renderer.resumeId?.() ?? resume ?? (harness.adoptsSessionId ? id : void 0),
|
|
88453
|
+
model: () => renderer.model?.()
|
|
88388
88454
|
};
|
|
88389
88455
|
}
|
|
88390
88456
|
function declOf(setting) {
|
|
@@ -88882,15 +88948,14 @@ function parseFrontmatter(text3) {
|
|
|
88882
88948
|
if (!Array.isArray(meta.questions)) {
|
|
88883
88949
|
meta.questions = meta.questions ? [normalizeQuestion(meta.questions)] : [];
|
|
88884
88950
|
}
|
|
88885
|
-
|
|
88886
|
-
meta[key] = typeof meta[key] === "string" && meta[key].trim() ? meta[key].trim() : "";
|
|
88887
|
-
}
|
|
88951
|
+
meta.priority = typeof meta.priority === "string" ? meta.priority.trim() : "";
|
|
88888
88952
|
if (!Array.isArray(meta.modules)) meta.modules = [];
|
|
88889
88953
|
delete meta.channels;
|
|
88890
88954
|
delete meta.decided;
|
|
88891
88955
|
delete meta.verify;
|
|
88892
88956
|
delete meta.release;
|
|
88893
88957
|
delete meta.schedule;
|
|
88958
|
+
delete meta.roi;
|
|
88894
88959
|
meta.workflow = typeof meta.workflow === "string" && meta.workflow.trim() ? meta.workflow.trim() : "";
|
|
88895
88960
|
meta.triage = typeof meta.triage === "string" ? meta.triage.trim() : "";
|
|
88896
88961
|
meta.source = (Array.isArray(meta.source) ? meta.source : typeof meta.source === "string" ? [meta.source] : []).map((ref) => String(ref).trim()).filter(Boolean);
|
|
@@ -89036,34 +89101,120 @@ async function askDueAgents(machineId2, now = Date.now()) {
|
|
|
89036
89101
|
return started;
|
|
89037
89102
|
}
|
|
89038
89103
|
|
|
89104
|
+
// src/akb-version.ts
|
|
89105
|
+
import { execFile } from "node:child_process";
|
|
89106
|
+
import fs15 from "node:fs";
|
|
89107
|
+
import path18 from "node:path";
|
|
89108
|
+
|
|
89109
|
+
// src/akb.ts
|
|
89110
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
89111
|
+
import fs11 from "node:fs";
|
|
89112
|
+
import path14 from "node:path";
|
|
89113
|
+
import { fileURLToPath } from "node:url";
|
|
89114
|
+
var akbHome = () => path14.join(runnerHome(), "bin", "akb");
|
|
89115
|
+
var BUNDLED_SHIM = `bundled-${AKB_VERSION}`;
|
|
89116
|
+
var bundledAkb = () => ({
|
|
89117
|
+
command: process.execPath,
|
|
89118
|
+
args: [path14.join(path14.dirname(fileURLToPath(import.meta.url)), "akb", "bin", "ai4kanban.mjs")],
|
|
89119
|
+
version: AKB_VERSION,
|
|
89120
|
+
shim: path14.join(akbHome(), BUNDLED_SHIM)
|
|
89121
|
+
});
|
|
89122
|
+
var quote = (s) => /^[\w./:@=-]+$/.test(s) ? s : `"${s}"`;
|
|
89123
|
+
function shimDir(akb) {
|
|
89124
|
+
const dir = akb.shim;
|
|
89125
|
+
const line = [akb.command, ...akb.args].map(quote).join(" ");
|
|
89126
|
+
const [file2, text3] = process.platform === "win32" ? [path14.join(dir, "akb.cmd"), `@${line} %*\r
|
|
89127
|
+
`] : [path14.join(dir, "akb"), `#!/bin/sh
|
|
89128
|
+
exec ${line} "$@"
|
|
89129
|
+
`];
|
|
89130
|
+
try {
|
|
89131
|
+
if (fs11.readFileSync(file2, "utf8") === text3) return dir;
|
|
89132
|
+
} catch {
|
|
89133
|
+
}
|
|
89134
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
89135
|
+
fs11.writeFileSync(file2, text3, { mode: 493 });
|
|
89136
|
+
return dir;
|
|
89137
|
+
}
|
|
89138
|
+
function akbEnv(akb, board, task, line) {
|
|
89139
|
+
const env2 = {};
|
|
89140
|
+
const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV];
|
|
89141
|
+
for (const [k, v2] of Object.entries(process.env)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
|
|
89142
|
+
const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
89143
|
+
env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path14.delimiter);
|
|
89144
|
+
env2.AI4KANBAN_COMMAND = "akb";
|
|
89145
|
+
if (board) env2.AI4KANBAN_BOARD = board;
|
|
89146
|
+
if (task) env2.AI4KANBAN_TASK = task;
|
|
89147
|
+
if (line !== void 0) env2[LANGUAGE_LINE_ENV] = line;
|
|
89148
|
+
return env2;
|
|
89149
|
+
}
|
|
89150
|
+
var KEEP = 256 * 1024;
|
|
89151
|
+
function runAkb(akb, args, opts) {
|
|
89152
|
+
return new Promise((resolve2) => {
|
|
89153
|
+
let out = "";
|
|
89154
|
+
let last2 = "";
|
|
89155
|
+
const note = (text3) => {
|
|
89156
|
+
const line = text3.split("\n").map((l2) => l2.trim()).filter(Boolean).at(-1);
|
|
89157
|
+
if (line) last2 = line;
|
|
89158
|
+
};
|
|
89159
|
+
let child;
|
|
89160
|
+
try {
|
|
89161
|
+
child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: akbEnv(akb, opts.board, opts.task, opts.line), stdio: ["ignore", "pipe", "pipe"] });
|
|
89162
|
+
} catch (e2) {
|
|
89163
|
+
return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
|
|
89164
|
+
}
|
|
89165
|
+
opts.track?.(child);
|
|
89166
|
+
child.stdout.setEncoding("utf8");
|
|
89167
|
+
child.stderr.setEncoding("utf8");
|
|
89168
|
+
child.stdout.on("data", (chunk) => {
|
|
89169
|
+
out = (out + chunk).slice(-KEEP);
|
|
89170
|
+
note(chunk);
|
|
89171
|
+
opts.show?.(chunk);
|
|
89172
|
+
});
|
|
89173
|
+
child.stderr.on("data", (chunk) => {
|
|
89174
|
+
note(chunk);
|
|
89175
|
+
opts.show?.(chunk);
|
|
89176
|
+
});
|
|
89177
|
+
child.on("error", (e2) => resolve2({ code: null, out, last: e2.message }));
|
|
89178
|
+
child.on("close", (code) => resolve2({ code, out, last: last2 }));
|
|
89179
|
+
});
|
|
89180
|
+
}
|
|
89181
|
+
function answerOf2(ran) {
|
|
89182
|
+
const line = ran.out.trim().split("\n").at(-1) ?? "";
|
|
89183
|
+
try {
|
|
89184
|
+
return JSON.parse(line);
|
|
89185
|
+
} catch {
|
|
89186
|
+
return null;
|
|
89187
|
+
}
|
|
89188
|
+
}
|
|
89189
|
+
|
|
89039
89190
|
// src/cache.ts
|
|
89040
89191
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
89041
|
-
import
|
|
89042
|
-
import
|
|
89192
|
+
import fs13 from "node:fs";
|
|
89193
|
+
import path16 from "node:path";
|
|
89043
89194
|
|
|
89044
89195
|
// src/folders.ts
|
|
89045
|
-
import
|
|
89196
|
+
import fs12 from "node:fs";
|
|
89046
89197
|
import os5 from "node:os";
|
|
89047
|
-
import
|
|
89048
|
-
var projectsFile = () =>
|
|
89198
|
+
import path15 from "node:path";
|
|
89199
|
+
var projectsFile = () => path15.join(runnerHome(), "projects.json");
|
|
89049
89200
|
function realpath(p2) {
|
|
89050
89201
|
try {
|
|
89051
|
-
return
|
|
89202
|
+
return fs12.realpathSync(p2);
|
|
89052
89203
|
} catch {
|
|
89053
89204
|
return null;
|
|
89054
89205
|
}
|
|
89055
89206
|
}
|
|
89056
89207
|
function readList() {
|
|
89057
89208
|
try {
|
|
89058
|
-
const
|
|
89059
|
-
return Array.isArray(
|
|
89209
|
+
const held4 = JSON.parse(fs12.readFileSync(projectsFile(), "utf8"));
|
|
89210
|
+
return Array.isArray(held4.projects) ? held4.projects.filter((p2) => typeof p2 === "string") : [];
|
|
89060
89211
|
} catch {
|
|
89061
89212
|
return [];
|
|
89062
89213
|
}
|
|
89063
89214
|
}
|
|
89064
89215
|
function writeList(list) {
|
|
89065
|
-
|
|
89066
|
-
|
|
89216
|
+
fs12.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
|
|
89217
|
+
fs12.writeFileSync(projectsFile(), `${JSON.stringify({ projects: [...new Set(list)] }, null, 2)}
|
|
89067
89218
|
`);
|
|
89068
89219
|
}
|
|
89069
89220
|
function allowedProjects() {
|
|
@@ -89087,7 +89238,7 @@ var SYSTEM_WIN = ["Windows", "Program Files", "Program Files (x86)", "ProgramDat
|
|
|
89087
89238
|
var here = () => ({ platform: process.platform, home: os5.homedir(), resolve: realpath });
|
|
89088
89239
|
function refusal(picked, where = here()) {
|
|
89089
89240
|
const win = where.platform === "win32";
|
|
89090
|
-
const p2 = win ?
|
|
89241
|
+
const p2 = win ? path15.win32 : path15.posix;
|
|
89091
89242
|
const real = where.resolve(picked);
|
|
89092
89243
|
if (!real || !p2.isAbsolute(real)) return "missing";
|
|
89093
89244
|
const norm = (d2) => {
|
|
@@ -89113,40 +89264,40 @@ function refusal(picked, where = here()) {
|
|
|
89113
89264
|
var IDLE_MS = 7 * 24 * 60 * 6e4;
|
|
89114
89265
|
var SWEEP_MS = 24 * 60 * 6e4;
|
|
89115
89266
|
var PROJECT_ID = /^[\w-]{1,100}$/;
|
|
89116
|
-
var cacheRoot = () =>
|
|
89267
|
+
var cacheRoot = () => path16.join(runnerHome(), "cache");
|
|
89117
89268
|
function cacheDir(project) {
|
|
89118
89269
|
if (!PROJECT_ID.test(project)) throw new Error("This job names no project.");
|
|
89119
|
-
return
|
|
89270
|
+
return path16.join(cacheRoot(), project);
|
|
89120
89271
|
}
|
|
89121
|
-
var akbDir = (dir) =>
|
|
89122
|
-
var usedFile = (dir) =>
|
|
89123
|
-
var unsentFile = (dir) =>
|
|
89272
|
+
var akbDir = (dir) => path16.join(dir, ".akb");
|
|
89273
|
+
var usedFile = (dir) => path16.join(akbDir(dir), "used.json");
|
|
89274
|
+
var unsentFile = (dir) => path16.join(akbDir(dir), "unsent");
|
|
89124
89275
|
function markUsed(dir, at2 = Date.now()) {
|
|
89125
|
-
|
|
89126
|
-
|
|
89276
|
+
fs13.mkdirSync(akbDir(dir), { recursive: true });
|
|
89277
|
+
fs13.writeFileSync(usedFile(dir), `${JSON.stringify({ at: at2 })}
|
|
89127
89278
|
`);
|
|
89128
89279
|
}
|
|
89129
89280
|
function usedAt(dir) {
|
|
89130
89281
|
try {
|
|
89131
|
-
const at2 = JSON.parse(
|
|
89282
|
+
const at2 = JSON.parse(fs13.readFileSync(usedFile(dir), "utf8")).at;
|
|
89132
89283
|
return typeof at2 === "number" ? at2 : null;
|
|
89133
89284
|
} catch {
|
|
89134
89285
|
return null;
|
|
89135
89286
|
}
|
|
89136
89287
|
}
|
|
89137
|
-
var unsent = (dir) =>
|
|
89288
|
+
var unsent = (dir) => fs13.existsSync(unsentFile(dir));
|
|
89138
89289
|
function markUnsent(dir, unsent2) {
|
|
89139
|
-
if (!unsent2) return void
|
|
89140
|
-
|
|
89141
|
-
|
|
89290
|
+
if (!unsent2) return void fs13.rmSync(unsentFile(dir), { force: true });
|
|
89291
|
+
fs13.mkdirSync(akbDir(dir), { recursive: true });
|
|
89292
|
+
fs13.writeFileSync(unsentFile(dir), "");
|
|
89142
89293
|
}
|
|
89143
89294
|
var holds = /* @__PURE__ */ new Map();
|
|
89144
89295
|
function hold(dir) {
|
|
89145
89296
|
holds.set(dir, (holds.get(dir) ?? 0) + 1);
|
|
89146
|
-
let
|
|
89297
|
+
let held4 = true;
|
|
89147
89298
|
return () => {
|
|
89148
|
-
if (!
|
|
89149
|
-
|
|
89299
|
+
if (!held4) return;
|
|
89300
|
+
held4 = false;
|
|
89150
89301
|
const left = holds.get(dir) - 1;
|
|
89151
89302
|
if (left) holds.set(dir, left);
|
|
89152
89303
|
else holds.delete(dir);
|
|
@@ -89154,9 +89305,9 @@ function hold(dir) {
|
|
|
89154
89305
|
}
|
|
89155
89306
|
function paused(dir) {
|
|
89156
89307
|
try {
|
|
89157
|
-
const file2 =
|
|
89158
|
-
const
|
|
89159
|
-
return (
|
|
89308
|
+
const file2 = path16.join(projectStateDir(path16.join(akbDir(dir), "kanban")), SESSIONS_FILE);
|
|
89309
|
+
const held4 = JSON.parse(fs13.readFileSync(file2, "utf8"));
|
|
89310
|
+
return (held4.deliveries ?? []).some((d2) => d2.status === "active");
|
|
89160
89311
|
} catch {
|
|
89161
89312
|
return false;
|
|
89162
89313
|
}
|
|
@@ -89168,11 +89319,11 @@ function clearAkb(dir) {
|
|
|
89168
89319
|
if (kept2(dir)) return false;
|
|
89169
89320
|
let entries;
|
|
89170
89321
|
try {
|
|
89171
|
-
entries =
|
|
89322
|
+
entries = fs13.readdirSync(akbDir(dir));
|
|
89172
89323
|
} catch {
|
|
89173
89324
|
return true;
|
|
89174
89325
|
}
|
|
89175
|
-
for (const name of entries)
|
|
89326
|
+
for (const name of entries) fs13.rmSync(path16.join(akbDir(dir), name), { recursive: true, force: true });
|
|
89176
89327
|
spawnSync3("git", ["-C", dir, "worktree", "prune"], { stdio: "ignore" });
|
|
89177
89328
|
return true;
|
|
89178
89329
|
}
|
|
@@ -89187,7 +89338,7 @@ async function readAccess(machineId2) {
|
|
|
89187
89338
|
}
|
|
89188
89339
|
function realpath2(p2) {
|
|
89189
89340
|
try {
|
|
89190
|
-
return
|
|
89341
|
+
return fs13.realpathSync(p2);
|
|
89191
89342
|
} catch {
|
|
89192
89343
|
return p2;
|
|
89193
89344
|
}
|
|
@@ -89202,25 +89353,25 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89202
89353
|
const swept = [];
|
|
89203
89354
|
let cached2 = [];
|
|
89204
89355
|
try {
|
|
89205
|
-
cached2 =
|
|
89356
|
+
cached2 = fs13.readdirSync(cacheRoot(), { withFileTypes: true });
|
|
89206
89357
|
} catch {
|
|
89207
89358
|
}
|
|
89208
89359
|
for (const e2 of cached2) {
|
|
89209
|
-
const dir =
|
|
89360
|
+
const dir = path16.join(cacheRoot(), e2.name);
|
|
89210
89361
|
if (!e2.isDirectory() || kept2(dir)) continue;
|
|
89211
89362
|
const gone = access && !access.projects.has(e2.name);
|
|
89212
89363
|
if (idle(dir, now) || gone) {
|
|
89213
|
-
|
|
89364
|
+
fs13.rmSync(dir, { recursive: true, force: true });
|
|
89214
89365
|
swept.push(dir);
|
|
89215
89366
|
}
|
|
89216
89367
|
}
|
|
89217
89368
|
for (const dir of allowedProjects()) {
|
|
89218
|
-
let
|
|
89369
|
+
let held4 = [];
|
|
89219
89370
|
try {
|
|
89220
|
-
|
|
89371
|
+
held4 = fs13.readdirSync(akbDir(dir));
|
|
89221
89372
|
} catch {
|
|
89222
89373
|
}
|
|
89223
|
-
if (!
|
|
89374
|
+
if (!held4.length) continue;
|
|
89224
89375
|
const gone = access && !access.folders.has(dir);
|
|
89225
89376
|
if ((idle(dir, now) || gone) && clearAkb(dir)) swept.push(dir);
|
|
89226
89377
|
}
|
|
@@ -89228,24 +89379,231 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89228
89379
|
}
|
|
89229
89380
|
function removeLegacy() {
|
|
89230
89381
|
const home4 = runnerHome();
|
|
89231
|
-
for (const name of ["boards", "akb-bin"])
|
|
89382
|
+
for (const name of ["boards", "akb-bin"]) fs13.rmSync(path16.join(home4, name), { recursive: true, force: true });
|
|
89232
89383
|
let entries = [];
|
|
89233
89384
|
try {
|
|
89234
|
-
entries =
|
|
89385
|
+
entries = fs13.readdirSync(home4, { withFileTypes: true });
|
|
89235
89386
|
} catch {
|
|
89236
89387
|
return;
|
|
89237
89388
|
}
|
|
89238
89389
|
for (const e2 of entries) {
|
|
89239
|
-
const account =
|
|
89240
|
-
if (!e2.isDirectory() || !
|
|
89241
|
-
|
|
89242
|
-
if (!
|
|
89390
|
+
const account = path16.join(home4, e2.name);
|
|
89391
|
+
if (!e2.isDirectory() || !fs13.existsSync(path16.join(account, "unfiled"))) continue;
|
|
89392
|
+
fs13.rmSync(path16.join(account, "unfiled"), { recursive: true, force: true });
|
|
89393
|
+
if (!fs13.readdirSync(account).length) fs13.rmdirSync(account);
|
|
89243
89394
|
}
|
|
89244
89395
|
}
|
|
89245
89396
|
|
|
89246
|
-
// src/
|
|
89397
|
+
// src/update.ts
|
|
89398
|
+
import crypto2 from "node:crypto";
|
|
89247
89399
|
import fs14 from "node:fs";
|
|
89248
89400
|
import path17 from "node:path";
|
|
89401
|
+
import zlib from "node:zlib";
|
|
89402
|
+
var TIMEOUT_MS2 = 6e4;
|
|
89403
|
+
var registry = () => (process.env.npm_config_registry || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
89404
|
+
async function installPackage(pkg, version, nodeVersion = process.versions.node) {
|
|
89405
|
+
const dir = pkg.dirOf(version);
|
|
89406
|
+
if (fs14.existsSync(pkg.entryOf(dir))) return { ok: true, dir };
|
|
89407
|
+
let meta;
|
|
89408
|
+
let tarball;
|
|
89409
|
+
try {
|
|
89410
|
+
const answer = await fetch(`${registry()}/${pkg.name}/${encodeURIComponent(version)}`, { signal: AbortSignal.timeout(TIMEOUT_MS2) });
|
|
89411
|
+
if (!answer.ok) return { ok: false, why: "unreachable", detail: `registry answered ${answer.status}` };
|
|
89412
|
+
meta = await answer.json();
|
|
89413
|
+
const range = meta.engines?.node;
|
|
89414
|
+
if (range && !satisfies(nodeVersion, range)) return { ok: false, why: "node", detail: range };
|
|
89415
|
+
if (!meta.dist?.tarball) return { ok: false, why: "unreachable", detail: "no tarball" };
|
|
89416
|
+
const download2 = await fetch(meta.dist.tarball, { signal: AbortSignal.timeout(TIMEOUT_MS2) });
|
|
89417
|
+
if (!download2.ok) return { ok: false, why: "unreachable", detail: `download answered ${download2.status}` };
|
|
89418
|
+
tarball = Buffer.from(await download2.arrayBuffer());
|
|
89419
|
+
} catch (e2) {
|
|
89420
|
+
return { ok: false, why: "unreachable", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89421
|
+
}
|
|
89422
|
+
const expected = /^sha512-(.+)$/.exec(meta.dist.integrity ?? "")?.[1];
|
|
89423
|
+
const actual = crypto2.createHash("sha512").update(tarball).digest("base64");
|
|
89424
|
+
if (!expected || expected !== actual) return { ok: false, why: "integrity", detail: "sha512 mismatch" };
|
|
89425
|
+
const staging = `${dir}.${process.pid}.tmp`;
|
|
89426
|
+
try {
|
|
89427
|
+
fs14.rmSync(staging, { recursive: true, force: true });
|
|
89428
|
+
extract(zlib.gunzipSync(tarball), staging);
|
|
89429
|
+
if (!fs14.existsSync(pkg.entryOf(staging))) throw new Error(`the package carries no ${path17.relative(staging, pkg.entryOf(staging))}`);
|
|
89430
|
+
fs14.rmSync(dir, { recursive: true, force: true });
|
|
89431
|
+
fs14.renameSync(staging, dir);
|
|
89432
|
+
} catch (e2) {
|
|
89433
|
+
fs14.rmSync(staging, { recursive: true, force: true });
|
|
89434
|
+
return { ok: false, why: "integrity", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89435
|
+
}
|
|
89436
|
+
return { ok: true, dir };
|
|
89437
|
+
}
|
|
89438
|
+
function extract(tar, into) {
|
|
89439
|
+
let offset = 0;
|
|
89440
|
+
let longName = null;
|
|
89441
|
+
while (offset + 512 <= tar.length) {
|
|
89442
|
+
const header = tar.subarray(offset, offset + 512);
|
|
89443
|
+
if (header.every((b2) => b2 === 0)) break;
|
|
89444
|
+
const field = (start, length) => header.subarray(start, start + length).toString("utf8").replace(/\0.*$/s, "");
|
|
89445
|
+
const size = parseInt(field(124, 12).trim() || "0", 8);
|
|
89446
|
+
const type = field(156, 1) || "0";
|
|
89447
|
+
const body = tar.subarray(offset + 512, offset + 512 + size);
|
|
89448
|
+
offset += 512 + Math.ceil(size / 512) * 512;
|
|
89449
|
+
if (type === "x") {
|
|
89450
|
+
longName = /(?:^|\n)\d+ path=([^\n]*)\n/.exec(body.toString("utf8"))?.[1] ?? null;
|
|
89451
|
+
continue;
|
|
89452
|
+
}
|
|
89453
|
+
if (type === "L") {
|
|
89454
|
+
longName = body.toString("utf8").replace(/\0.*$/s, "");
|
|
89455
|
+
continue;
|
|
89456
|
+
}
|
|
89457
|
+
const prefix = field(345, 155);
|
|
89458
|
+
const name = longName ?? (prefix ? `${prefix}/${field(0, 100)}` : field(0, 100));
|
|
89459
|
+
longName = null;
|
|
89460
|
+
if (type !== "0" && type !== "5") continue;
|
|
89461
|
+
const relative = name.replace(/^[^/]+\//, "");
|
|
89462
|
+
if (!relative) continue;
|
|
89463
|
+
const target = path17.resolve(into, relative);
|
|
89464
|
+
if (!target.startsWith(path17.resolve(into) + path17.sep)) throw new Error(`refusing ${name}`);
|
|
89465
|
+
if (type === "5") fs14.mkdirSync(target, { recursive: true });
|
|
89466
|
+
else {
|
|
89467
|
+
fs14.mkdirSync(path17.dirname(target), { recursive: true });
|
|
89468
|
+
fs14.writeFileSync(target, body);
|
|
89469
|
+
}
|
|
89470
|
+
}
|
|
89471
|
+
}
|
|
89472
|
+
var parse = (v2) => {
|
|
89473
|
+
const m = /^v?(\d+)(?:\.(\d+|x|\*))?(?:\.(\d+|x|\*))?/.exec(v2.trim());
|
|
89474
|
+
return m ? [Number(m[1]), Number(m[2]) || 0, Number(m[3]) || 0] : null;
|
|
89475
|
+
};
|
|
89476
|
+
function compare(a3, b2) {
|
|
89477
|
+
const [x2, y2] = [parse(a3) ?? [0, 0, 0], parse(b2) ?? [0, 0, 0]];
|
|
89478
|
+
for (let i = 0; i < 3; i++) if (x2[i] !== y2[i]) return x2[i] - y2[i];
|
|
89479
|
+
return 0;
|
|
89480
|
+
}
|
|
89481
|
+
function satisfies(version, range) {
|
|
89482
|
+
return range.split("||").some((alternative) => {
|
|
89483
|
+
const parts = alternative.trim().split(/\s+/).filter(Boolean);
|
|
89484
|
+
return parts.length > 0 && parts.every((part) => meets(version, part));
|
|
89485
|
+
});
|
|
89486
|
+
}
|
|
89487
|
+
function meets(version, comparator) {
|
|
89488
|
+
const m = /^(>=|<=|>|<|=|\^|~)?\s*(.+)$/.exec(comparator);
|
|
89489
|
+
const bound = m && parse(m[2]);
|
|
89490
|
+
if (!m || !bound) return false;
|
|
89491
|
+
const v2 = parse(version);
|
|
89492
|
+
const c2 = compare(version, m[2]);
|
|
89493
|
+
switch (m[1]) {
|
|
89494
|
+
case ">=":
|
|
89495
|
+
return c2 >= 0;
|
|
89496
|
+
case ">":
|
|
89497
|
+
return c2 > 0;
|
|
89498
|
+
case "<=":
|
|
89499
|
+
return c2 <= 0;
|
|
89500
|
+
case "<":
|
|
89501
|
+
return c2 < 0;
|
|
89502
|
+
case "^":
|
|
89503
|
+
return c2 >= 0 && v2[0] === bound[0];
|
|
89504
|
+
case "~":
|
|
89505
|
+
return c2 >= 0 && v2[0] === bound[0] && v2[1] === bound[1];
|
|
89506
|
+
default: {
|
|
89507
|
+
const given = m[2].split(".").filter((p2) => /^\d+$/.test(p2)).length;
|
|
89508
|
+
return [0, 1, 2].slice(0, given).every((i) => v2[i] === bound[i]);
|
|
89509
|
+
}
|
|
89510
|
+
}
|
|
89511
|
+
}
|
|
89512
|
+
|
|
89513
|
+
// src/akb-version.ts
|
|
89514
|
+
var CHECK_MS2 = 1e4;
|
|
89515
|
+
var VERSION2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
89516
|
+
var stateFile = () => path18.join(akbHome(), "state.json");
|
|
89517
|
+
var akbVersionDir = (version) => path18.join(akbHome(), version);
|
|
89518
|
+
var entryOf = (dir) => path18.join(dir, "bin", "ai4kanban.mjs");
|
|
89519
|
+
var AKB = { name: "wildcrane", dirOf: akbVersionDir, entryOf };
|
|
89520
|
+
function readAkbState() {
|
|
89521
|
+
try {
|
|
89522
|
+
const held4 = JSON.parse(fs15.readFileSync(stateFile(), "utf8"));
|
|
89523
|
+
return { current: held4.current ?? null, bad: held4.bad ?? [] };
|
|
89524
|
+
} catch {
|
|
89525
|
+
return { current: null, bad: [] };
|
|
89526
|
+
}
|
|
89527
|
+
}
|
|
89528
|
+
function writeAkbState(state) {
|
|
89529
|
+
fs15.mkdirSync(akbHome(), { recursive: true });
|
|
89530
|
+
const staging = `${stateFile()}.${process.pid}.tmp`;
|
|
89531
|
+
fs15.writeFileSync(staging, `${JSON.stringify(state, null, 2)}
|
|
89532
|
+
`);
|
|
89533
|
+
fs15.renameSync(staging, stateFile());
|
|
89534
|
+
}
|
|
89535
|
+
function contractOf(dir) {
|
|
89536
|
+
try {
|
|
89537
|
+
return JSON.parse(fs15.readFileSync(path18.join(dir, "package.json"), "utf8")).akbContract ?? null;
|
|
89538
|
+
} catch {
|
|
89539
|
+
return null;
|
|
89540
|
+
}
|
|
89541
|
+
}
|
|
89542
|
+
var usable = (dir) => fs15.existsSync(entryOf(dir)) && contractOf(dir) === AKB_CONTRACT;
|
|
89543
|
+
function currentAkb() {
|
|
89544
|
+
const { current } = readAkbState();
|
|
89545
|
+
if (!current) return bundledAkb();
|
|
89546
|
+
const dir = akbVersionDir(current);
|
|
89547
|
+
if (!usable(dir)) return bundledAkb();
|
|
89548
|
+
try {
|
|
89549
|
+
const now = /* @__PURE__ */ new Date();
|
|
89550
|
+
fs15.utimesSync(dir, now, now);
|
|
89551
|
+
} catch {
|
|
89552
|
+
}
|
|
89553
|
+
return { command: process.execPath, args: [entryOf(dir)], version: current, shim: path18.join(dir, "shim") };
|
|
89554
|
+
}
|
|
89555
|
+
var answers2 = (dir, version) => new Promise((resolve2) => {
|
|
89556
|
+
execFile(process.execPath, [entryOf(dir), "--version"], { timeout: CHECK_MS2, killSignal: "SIGKILL" }, (error, stdout) => resolve2(!error && stdout.trim().split(/\s+/).at(-1) === version));
|
|
89557
|
+
});
|
|
89558
|
+
var wanted = null;
|
|
89559
|
+
var fetching = false;
|
|
89560
|
+
function useVersion(current) {
|
|
89561
|
+
const state = readAkbState();
|
|
89562
|
+
if (state.current !== current) writeAkbState({ ...state, current });
|
|
89563
|
+
}
|
|
89564
|
+
async function fetchVersion(version) {
|
|
89565
|
+
const got = await installPackage(AKB, version);
|
|
89566
|
+
if (!got.ok) return console.error(`runner: akb ${version} was not fetched: ${got.detail}`);
|
|
89567
|
+
if (contractOf(got.dir) !== AKB_CONTRACT || !await answers2(got.dir, version)) {
|
|
89568
|
+
console.error(`runner: akb ${version} failed its check and will not be used`);
|
|
89569
|
+
const state = readAkbState();
|
|
89570
|
+
return writeAkbState({ ...state, bad: [.../* @__PURE__ */ new Set([...state.bad, version])] });
|
|
89571
|
+
}
|
|
89572
|
+
if (wanted === version) useVersion(version);
|
|
89573
|
+
}
|
|
89574
|
+
async function followAkb(named2) {
|
|
89575
|
+
if (!named2) return;
|
|
89576
|
+
const { version } = named2;
|
|
89577
|
+
try {
|
|
89578
|
+
if (version !== null && !VERSION2.test(version)) return;
|
|
89579
|
+
wanted = version;
|
|
89580
|
+
if (version === null || version === AKB_VERSION) return useVersion(null);
|
|
89581
|
+
const state = readAkbState();
|
|
89582
|
+
if (fetching || state.bad.includes(version) || state.current === version && usable(akbVersionDir(version))) return;
|
|
89583
|
+
fetching = true;
|
|
89584
|
+
await fetchVersion(version).finally(() => fetching = false);
|
|
89585
|
+
} catch (e2) {
|
|
89586
|
+
console.error(`runner: the akb version was not followed: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
89587
|
+
}
|
|
89588
|
+
}
|
|
89589
|
+
function sweepAkb(now = Date.now()) {
|
|
89590
|
+
const { current } = readAkbState();
|
|
89591
|
+
let entries = [];
|
|
89592
|
+
try {
|
|
89593
|
+
entries = fs15.readdirSync(akbHome(), { withFileTypes: true });
|
|
89594
|
+
} catch {
|
|
89595
|
+
return;
|
|
89596
|
+
}
|
|
89597
|
+
for (const e2 of entries) {
|
|
89598
|
+
if (!e2.isDirectory() || e2.name === current || e2.name === BUNDLED_SHIM) continue;
|
|
89599
|
+
const dir = path18.join(akbHome(), e2.name);
|
|
89600
|
+
if (now - fs15.statSync(dir).mtimeMs > IDLE_MS) fs15.rmSync(dir, { recursive: true, force: true });
|
|
89601
|
+
}
|
|
89602
|
+
}
|
|
89603
|
+
|
|
89604
|
+
// src/chats.ts
|
|
89605
|
+
import fs17 from "node:fs";
|
|
89606
|
+
import path20 from "node:path";
|
|
89249
89607
|
|
|
89250
89608
|
// ../cloud/src/config.ts
|
|
89251
89609
|
var CLAIM_LEASE_SECONDS = 15 * 60;
|
|
@@ -89261,18 +89619,18 @@ var CONTACT_ATTEMPT_WINDOW_SECONDS = 60 * 60;
|
|
|
89261
89619
|
var CHAT_KEEP_DAYS = 30;
|
|
89262
89620
|
|
|
89263
89621
|
// ../cli/src/lib/agent/task-chats.ts
|
|
89264
|
-
import
|
|
89265
|
-
import
|
|
89622
|
+
import fs16 from "node:fs";
|
|
89623
|
+
import path19 from "node:path";
|
|
89266
89624
|
var TASK = /^[\w-]{1,100}$/;
|
|
89267
|
-
var taskChatsDir = (home4 = machineHome()) =>
|
|
89625
|
+
var taskChatsDir = (home4 = machineHome()) => path19.join(home4, "chats");
|
|
89268
89626
|
function taskChatFile(task, home4) {
|
|
89269
89627
|
if (!TASK.test(task)) throw new Error(`${task} is not a task id.`);
|
|
89270
|
-
return
|
|
89628
|
+
return path19.join(taskChatsDir(home4), `${task}.jsonl`);
|
|
89271
89629
|
}
|
|
89272
89630
|
function readTaskChat(task, home4) {
|
|
89273
89631
|
let text3;
|
|
89274
89632
|
try {
|
|
89275
|
-
text3 =
|
|
89633
|
+
text3 = fs16.readFileSync(taskChatFile(task, home4), "utf8");
|
|
89276
89634
|
} catch {
|
|
89277
89635
|
return [];
|
|
89278
89636
|
}
|
|
@@ -89293,18 +89651,18 @@ var DAY_MS = 24 * 60 * 6e4;
|
|
|
89293
89651
|
var REVIEW_EVERY_MS = DAY_MS;
|
|
89294
89652
|
var KEEP_MS2 = CHAT_KEEP_DAYS * DAY_MS;
|
|
89295
89653
|
var home3 = () => runnerHome();
|
|
89296
|
-
var reviewedFile = () =>
|
|
89654
|
+
var reviewedFile = () => path20.join(taskChatsDir(home3()), "reviewed.json");
|
|
89297
89655
|
function readReviewed() {
|
|
89298
89656
|
try {
|
|
89299
|
-
const
|
|
89300
|
-
return { checkedAt: Number(
|
|
89657
|
+
const held4 = JSON.parse(fs17.readFileSync(reviewedFile(), "utf8"));
|
|
89658
|
+
return { checkedAt: Number(held4.checkedAt) || 0, tasks: held4.tasks ?? {} };
|
|
89301
89659
|
} catch {
|
|
89302
89660
|
return { checkedAt: 0, tasks: {} };
|
|
89303
89661
|
}
|
|
89304
89662
|
}
|
|
89305
89663
|
function writeReviewed(reviewed) {
|
|
89306
|
-
|
|
89307
|
-
|
|
89664
|
+
fs17.mkdirSync(path20.dirname(reviewedFile()), { recursive: true });
|
|
89665
|
+
fs17.writeFileSync(reviewedFile(), `${JSON.stringify(reviewed, null, 2)}
|
|
89308
89666
|
`);
|
|
89309
89667
|
}
|
|
89310
89668
|
function keepChat(job, reply, at2 = Date.now()) {
|
|
@@ -89314,21 +89672,40 @@ function keepChat(job, reply, at2 = Date.now()) {
|
|
|
89314
89672
|
{ id: job.id, role: "agent", text: reply, at: at2, runtime: job.runtime, model: job.model ?? null }
|
|
89315
89673
|
];
|
|
89316
89674
|
const file2 = taskChatFile(job.task, home3());
|
|
89317
|
-
|
|
89318
|
-
|
|
89675
|
+
fs17.mkdirSync(path20.dirname(file2), { recursive: true });
|
|
89676
|
+
fs17.appendFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89319
89677
|
`).join(""));
|
|
89320
89678
|
}
|
|
89321
89679
|
function keepCloudChat(task, messages) {
|
|
89322
89680
|
const file2 = taskChatFile(task, home3());
|
|
89323
|
-
if (!messages.length) return
|
|
89681
|
+
if (!messages.length) return fs17.rmSync(file2, { force: true });
|
|
89324
89682
|
const lines = messages.map((m) => ({ id: m.id, role: m.role, text: m.body, at: Date.parse(m.created_at) || Date.now() }));
|
|
89325
|
-
|
|
89326
|
-
|
|
89683
|
+
fs17.mkdirSync(path20.dirname(file2), { recursive: true });
|
|
89684
|
+
fs17.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89685
|
+
`).join(""));
|
|
89686
|
+
}
|
|
89687
|
+
async function keepDecisions(task, read) {
|
|
89688
|
+
const comments = [];
|
|
89689
|
+
let after = null;
|
|
89690
|
+
do {
|
|
89691
|
+
const page = await read(task, after);
|
|
89692
|
+
if (!page.ok) return;
|
|
89693
|
+
for (const d2 of page.value.data) {
|
|
89694
|
+
if (d2.comment.trim()) comments.push({ id: d2.id, role: "user", text: d2.comment, at: Date.parse(d2.created_at) || Date.now() });
|
|
89695
|
+
}
|
|
89696
|
+
after = page.value.next;
|
|
89697
|
+
} while (after);
|
|
89698
|
+
if (!comments.length) return;
|
|
89699
|
+
const ids = new Set(comments.map((c2) => c2.id));
|
|
89700
|
+
const lines = [...readTaskChat(task, home3()).filter((l2) => !ids.has(l2.id)), ...comments].sort((a3, b2) => a3.at - b2.at);
|
|
89701
|
+
const file2 = taskChatFile(task, home3());
|
|
89702
|
+
fs17.mkdirSync(path20.dirname(file2), { recursive: true });
|
|
89703
|
+
fs17.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89327
89704
|
`).join(""));
|
|
89328
89705
|
}
|
|
89329
89706
|
var tasksKept = () => {
|
|
89330
89707
|
try {
|
|
89331
|
-
return
|
|
89708
|
+
return fs17.readdirSync(taskChatsDir(home3())).map((n) => /^([\w-]{1,100})\.jsonl$/.exec(n)?.[1]).filter((t2) => !!t2);
|
|
89332
89709
|
} catch {
|
|
89333
89710
|
return [];
|
|
89334
89711
|
}
|
|
@@ -89339,9 +89716,9 @@ function pruneChats(now = Date.now()) {
|
|
|
89339
89716
|
const kept4 = lines.filter((l2) => now - l2.at < KEEP_MS2);
|
|
89340
89717
|
if (kept4.length === lines.length) continue;
|
|
89341
89718
|
const file2 = taskChatFile(task, home3());
|
|
89342
|
-
if (kept4.length)
|
|
89719
|
+
if (kept4.length) fs17.writeFileSync(file2, kept4.map((l2) => `${JSON.stringify(l2)}
|
|
89343
89720
|
`).join(""));
|
|
89344
|
-
else
|
|
89721
|
+
else fs17.rmSync(file2, { force: true });
|
|
89345
89722
|
}
|
|
89346
89723
|
}
|
|
89347
89724
|
var lastOf = (task) => readTaskChat(task, home3()).at(-1);
|
|
@@ -89374,33 +89751,33 @@ async function reviewChats(machineId2, runtimes, now = Date.now()) {
|
|
|
89374
89751
|
if (!sent.ok) console.error(`runner: the chats of ${project} were not sent for review: ${sent.error}`);
|
|
89375
89752
|
}
|
|
89376
89753
|
const listed2 = new Set(owned.value.chats.map((c2) => c2.task));
|
|
89377
|
-
const
|
|
89378
|
-
writeReviewed({ checkedAt: now, tasks: Object.fromEntries(Object.entries(
|
|
89754
|
+
const held4 = readReviewed();
|
|
89755
|
+
writeReviewed({ checkedAt: now, tasks: Object.fromEntries(Object.entries(held4.tasks).filter(([t2]) => listed2.has(t2))) });
|
|
89379
89756
|
}
|
|
89380
89757
|
|
|
89381
89758
|
// src/board-watch.ts
|
|
89382
|
-
import
|
|
89383
|
-
import
|
|
89759
|
+
import fs21 from "node:fs";
|
|
89760
|
+
import path24 from "node:path";
|
|
89384
89761
|
|
|
89385
89762
|
// ../cloud/src/board-files.ts
|
|
89386
89763
|
var ROOTS = ["todo/", ".archive/", "memory/", "workflows/", "triage/", "assets/", "rules/"];
|
|
89387
89764
|
var SETTINGS = ["modules.md", "config.md"];
|
|
89388
|
-
var isSettingsPath = (
|
|
89765
|
+
var isSettingsPath = (path34) => SETTINGS.includes(path34) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path34);
|
|
89389
89766
|
var BOARD_FILE_LIMIT = 256 * 1024;
|
|
89390
|
-
function isBoardPath(
|
|
89391
|
-
if (!
|
|
89392
|
-
if (
|
|
89393
|
-
if (
|
|
89394
|
-
if (
|
|
89395
|
-
if (SETTINGS.includes(
|
|
89396
|
-
if (
|
|
89397
|
-
if (
|
|
89398
|
-
return ROOTS.some((root) =>
|
|
89767
|
+
function isBoardPath(path34) {
|
|
89768
|
+
if (!path34 || path34.length > 500 || path34.startsWith("/") || path34.includes("\\") || path34.includes("\0")) return false;
|
|
89769
|
+
if (path34.split("/").some((part) => !part || part === "." || part === "..")) return false;
|
|
89770
|
+
if (path34 === "todo/README.md" || path34.split("/").includes(".sync")) return false;
|
|
89771
|
+
if (path34.startsWith("workflows/")) return true;
|
|
89772
|
+
if (SETTINGS.includes(path34)) return true;
|
|
89773
|
+
if (path34.startsWith("rules/")) return isSettingsPath(path34);
|
|
89774
|
+
if (path34.startsWith("assets/")) return path34.endsWith(".json");
|
|
89775
|
+
return ROOTS.some((root) => path34.startsWith(root)) && path34.endsWith(".md");
|
|
89399
89776
|
}
|
|
89400
89777
|
var CARD = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]*\.md$/;
|
|
89401
89778
|
var ROOT = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]+\/root\.md$/;
|
|
89402
|
-
function numberOfCard(
|
|
89403
|
-
const n = ROOT.exec(
|
|
89779
|
+
function numberOfCard(path34) {
|
|
89780
|
+
const n = ROOT.exec(path34)?.[1] ?? CARD.exec(path34)?.[1];
|
|
89404
89781
|
return n ? Number(n) : null;
|
|
89405
89782
|
}
|
|
89406
89783
|
var cardSlug = (task) => task.toLowerCase().replace(/_/g, "-");
|
|
@@ -89432,9 +89809,9 @@ function cardFront(body) {
|
|
|
89432
89809
|
|
|
89433
89810
|
// src/task-folder.ts
|
|
89434
89811
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
89435
|
-
import
|
|
89436
|
-
import
|
|
89437
|
-
import
|
|
89812
|
+
import crypto3 from "node:crypto";
|
|
89813
|
+
import fs20 from "node:fs";
|
|
89814
|
+
import path23 from "node:path";
|
|
89438
89815
|
|
|
89439
89816
|
// node_modules/node-diff3/dist/diff3.mjs
|
|
89440
89817
|
function LCS(buffer1, buffer2) {
|
|
@@ -89651,8 +90028,8 @@ function diff3Merge(a3, o2, b2, options) {
|
|
|
89651
90028
|
|
|
89652
90029
|
// ../cloud/src/triage-files.ts
|
|
89653
90030
|
var ITEM = /^triage\/(?:(dismissed|archived)\/)?([^/]+)\.md$/;
|
|
89654
|
-
function itemAt(
|
|
89655
|
-
const m = ITEM.exec(
|
|
90031
|
+
function itemAt(path34) {
|
|
90032
|
+
const m = ITEM.exec(path34);
|
|
89656
90033
|
if (!m) return null;
|
|
89657
90034
|
return { state: m[1] === "dismissed" ? "dismissed" : m[1] === "archived" ? "carded" : "open", name: m[2] };
|
|
89658
90035
|
}
|
|
@@ -89669,8 +90046,8 @@ function stampItem(content, fields) {
|
|
|
89669
90046
|
}
|
|
89670
90047
|
|
|
89671
90048
|
// ../cli/src/lib/agents/shared-memory.ts
|
|
89672
|
-
import
|
|
89673
|
-
import
|
|
90049
|
+
import fs18 from "node:fs";
|
|
90050
|
+
import path21 from "node:path";
|
|
89674
90051
|
|
|
89675
90052
|
// ../cli/src/agents/api-designer/AGENT.md
|
|
89676
90053
|
var AGENT_default = "---\nname: api-designer\ndescription: Writes the caller's documentation for the APIs a card changes.\nakb:\n when: A card adds or changes a surface a user or third party calls directly, such as HTTP routes, WebSocket messages, MCP tools, or CLI commands and flags. Not a protocol between the project's own components.\n i18n:\n en:\n title: API docs\n zh:\n title: \u63A5\u53E3\u6587\u6863\n description: \u4E3A\u5361\u7247\u6539\u52A8\u7684\u63A5\u53E3\u5199\u51FA\u8C03\u7528\u65B9\u6587\u6863\u3002\n when: \u5361\u7247\u65B0\u589E\u6216\u4FEE\u6539\u7528\u6237\u6216\u7B2C\u4E09\u65B9\u76F4\u63A5\u8C03\u7528\u7684\u63A5\u53E3\u65F6\uFF0C\u5982 HTTP \u8DEF\u7531\u3001WebSocket \u6D88\u606F\u3001MCP \u5DE5\u5177\u3001CLI \u547D\u4EE4\u548C\u53C2\u6570\u3002\u4E0D\u542B\u9879\u76EE\u81EA\u8EAB\u7EC4\u4EF6\u4E4B\u95F4\u7684\u534F\u8BAE\u3002\n---\n\nWrite each surface this card changes as the documentation entry that will be committed, in\nthe project's existing docs style: inputs, outputs, errors and one example call. Use a\n`diff` when an entry already exists, and a `mermaid` `sequenceDiagram` for a message\nexchange. One design, no alternatives, nothing else in the section.\n\n- **Glanceable**: a junior engineer understands each entry in one read. Plain names, short\n lines, no field or error the card does not change.\n";
|
|
@@ -90128,7 +90505,7 @@ var music_default = "# Music\n\nScore the clone with new music that follows the
|
|
|
90128
90505
|
var AGENT_default24 = "---\nname: video-template-builder\ndescription: Builds a video clone's reusable beat-table template from its approved drafts, renders it once and checks it against the source beat by beat.\nakb:\n after: [video-cloner]\n session: new\n i18n:\n en:\n title: Video template\n zh:\n title: \u89C6\u9891\u6A21\u677F\n description: \u6309\u786E\u8BA4\u7684\u590D\u523B\u5206\u955C\u505A\u6210\u4FDD\u7559\u62CD\u6CD5\u3001\u53EF\u6362\u5185\u5BB9\u7684 beat \u8868\u6A21\u677F\uFF0C\u6E32\u67D3\u4E00\u652F\u5E76\u4E0E\u539F\u7247\u9010\u955C\u5BF9\u6BD4\u3002\n---\n\nBuild the template the approved drafts in ``## By `video-cloner` agent`` describe: it reproduces the source's craft and renders the user's content in place of the source's. You are done, with no further question, when the clone's comparison with the source and the render command are recorded on the card.\n\nFollow Terms, Deciding, Files and Memory in `akb raw agent-file video-cloner AGENT.md`; its memory folder is yours.\n\n## Steps\n\n- **Recipe**: write the format (size, frame rate, length, fonts, colours) to `recipe.md` in the files folder; it is your working file, never shown on the card.\n- **Template**: build a project that renders `clone.json` beat by beat, picking for each motion an animation library that fits its style; one project may combine several. The beat table and all content live in one file, holding the user's content from the start, so a beat can be removed or reordered and the content swapped without code changes; the code holds only craft and props. Its `template.md` states that the content in that file is to be replaced with the user's own and that the template reproduces only the source's craft.\n- **Cached clips**: render each beat to its own cached clip and splice the clips into the full video; a change re-renders only the clips it touches.\n- **Check**: render it once and compare it with the source beat by beat side by side on rhythm, motion and layout, and check every on-screen step makes sense to a viewer. A beat that misses the source's structure means the template is wrong: fix it and render again, never hand over the breakdown instead.\n- **Music**: in the template and check, also follow `akb raw agent-file video-cloner references/music.md`.\n- **Card**: under your section heading, show only the clone against the source as a `<Compare>` with `breakdown.json` as `shots`, and each difference left in one line, naming its beat id; append a ticked todo with the template folder's absolute path and, in backticks, its render command.\n- **Changes**: a change to a beat updates only that beat in the template.\n";
|
|
90129
90506
|
|
|
90130
90507
|
// ../cli/src/agents/workflow-writer/AGENT.md
|
|
90131
|
-
var AGENT_default25 = "---\nname: workflow-writer\ndescription: Writes a
|
|
90508
|
+
var AGENT_default25 = "---\nname: workflow-writer\ndescription: Writes or changes a workflow, one of its preview agents or a scheduled agent, as a `WORKFLOW.md` and the agents it names.\nakb:\n i18n:\n en:\n title: Workflow\n zh:\n title: \u5DE5\u4F5C\u6D41\n description: \u6309\u4F60\u7684\u63CF\u8FF0\u5199\u51FA\u6216\u4FEE\u6539\u5DE5\u4F5C\u6D41\u53CA\u5176 Preview Agent\uFF0C\u6216\u628A\u91CD\u590D\u6027\u5DE5\u4F5C\u5199\u6210\u5B9A\u65F6 agent\u3002\n---\n\nYou write a workflow from the user's request: a kind of work the user runs again and again, where each task shows a person previews to approve before the work goes on. A request may also change one preview agent in a workflow, or ask for work that repeats on a schedule.\n\n## Read first\n\n- **The project**: when the board belongs to a project folder, read its README and agent instruction files (such as `AGENTS.md` or `CLAUDE.md`) for what it makes, and its existing outputs of this kind for their format and destination.\n- **This board**: run `akb workflow list` and read `docs/kanban/agents/`, so a new workflow does not repeat one the board already has.\n\n## What to write\n\n- **The workflow**: when the card names a workflow folder, the workflow is that folder: keep its id and change it in place. Otherwise create it with `akb workflow new`. Name it with `akb workflow rename`, and list its agents in its `WORKFLOW.md`: `previews` the agents whose drafts a person approves, `land` the agents that run unattended in order after the last approval, and `scheduled`. Its body is how a card of this kind is written.\n- **Its agents**: write each agent it names as `akb guide write-agent` says.\n- **Approvals**: default to previews a person approves once. Give an agent `after` only when its preview is too costly to make before another is approved, such as a video before its script; it then waits for that approval.\n- **Previews**: give each part a person must see its own agent, such as the screens of a UI change or the script of a video. Show only what the person decides on, and keep previews from overlapping: a UI preview already shows its text, so add no separate copy preview.\n- **Land**: add agents to `land` only for work that needs no review, such as building and merging an approved change; leave it empty when the last approved preview is the deliverable.\n- **Memory**: for each agent, decide whether a user's correction should change its next output, such as a writer's tone or a designer's look; if so, declare its memory as `akb guide write-agent` says, otherwise give it none.\n- **Changing a workflow**: edit its `WORKFLOW.md` and its agents under `docs/kanban/agents/` in place, and keep what the request does not ask to change.\n- **Preview agents it does not hold**: when the request changes a preview agent of a built-in or another workflow, run `akb workflow duplicate <id>` on that workflow and change the copy of that agent.\n- **Saving a copy**: when the card names a folder, move the copy's `WORKFLOW.md` over the one there and remove the copy's empty folder, because only that folder is saved. Never run `akb workflow delete` on the copy: it deletes the agents too.\n- **Copied schedules**: remove the copy's `scheduled` entries and their agents unless the request is about them, so that work does not run twice.\n- **Repeating work**: write a scheduled agent as `akb guide write-agent` says. It goes in this workflow, which may hold nothing else.\n\n## Check it\n\nRun `akb spec` and `akb workflow list`, and fix every problem reported for this workflow or its agents before finishing.\n\n## Card\n\nUnder your section heading, say in a few lines, for a reader who has never seen a workflow file, what the workflow is for, what each approval shows, what runs after the last one, what runs on a schedule, and what each agent remembers; then embed each file you wrote as an `<Asset>`. When the work is a copy, say that new tasks must pick the copy and that open cards stay on the original.\n";
|
|
90132
90509
|
|
|
90133
90510
|
// ../cli/src/lib/agents/bundled.ts
|
|
90134
90511
|
var BUNDLED_AGENT_FILES = {
|
|
@@ -90399,16 +90776,16 @@ function sharedMemory(board) {
|
|
|
90399
90776
|
const at2 = /^([^/]+)\/AGENT\.md$/.exec(key);
|
|
90400
90777
|
if (at2) take(at2[1], text3, true);
|
|
90401
90778
|
}
|
|
90402
|
-
const root =
|
|
90779
|
+
const root = path21.join(board, "agents");
|
|
90403
90780
|
let folders2 = [];
|
|
90404
90781
|
try {
|
|
90405
|
-
folders2 =
|
|
90782
|
+
folders2 = fs18.readdirSync(root, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !e2.name.startsWith(".")).map((e2) => e2.name);
|
|
90406
90783
|
} catch {
|
|
90407
90784
|
}
|
|
90408
90785
|
for (const folder of folders2.sort()) {
|
|
90409
90786
|
let text3 = null;
|
|
90410
90787
|
try {
|
|
90411
|
-
text3 =
|
|
90788
|
+
text3 = fs18.readFileSync(path21.join(root, folder, "AGENT.md"), "utf8");
|
|
90412
90789
|
} catch {
|
|
90413
90790
|
}
|
|
90414
90791
|
take(folder, text3, false);
|
|
@@ -90432,16 +90809,16 @@ function openTaskFolder(job, projectDir2) {
|
|
|
90432
90809
|
projectDir2 ??= openCached(job.project);
|
|
90433
90810
|
keepOutOfGit(projectDir2);
|
|
90434
90811
|
markUsed(projectDir2);
|
|
90435
|
-
const board =
|
|
90436
|
-
|
|
90812
|
+
const board = path23.join(projectDir2, ".akb", "kanban");
|
|
90813
|
+
fs20.mkdirSync(board, { recursive: true });
|
|
90437
90814
|
return { task, cloudTask: task, board, cwd: projectDir2, project: job.project, number: job.number ?? null, workflow: job.workflow ?? job.flow?.workflow ?? null };
|
|
90438
90815
|
}
|
|
90439
90816
|
function openAgentFolder(job, projectDir2) {
|
|
90440
90817
|
if (!job.project || !job.agent) throw new Error("This job names no project.");
|
|
90441
90818
|
keepOutOfGit(projectDir2);
|
|
90442
90819
|
markUsed(projectDir2);
|
|
90443
|
-
const board =
|
|
90444
|
-
|
|
90820
|
+
const board = path23.join(projectDir2, ".akb", "kanban");
|
|
90821
|
+
fs20.mkdirSync(board, { recursive: true });
|
|
90445
90822
|
return {
|
|
90446
90823
|
task: `agent-${safe(job.agent.workflow ? `${job.agent.workflow}-${job.agent.name}` : job.agent.name)}`,
|
|
90447
90824
|
cloudTask: job.agent.tasks?.[0]?.id ?? null,
|
|
@@ -90456,13 +90833,13 @@ function openDiscussionFolder(job, projectDir2) {
|
|
|
90456
90833
|
if (!job.project) throw new Error("This job names no project.");
|
|
90457
90834
|
keepOutOfGit(projectDir2);
|
|
90458
90835
|
markUsed(projectDir2);
|
|
90459
|
-
const board =
|
|
90460
|
-
|
|
90836
|
+
const board = path23.join(projectDir2, ".akb", "kanban");
|
|
90837
|
+
fs20.mkdirSync(board, { recursive: true });
|
|
90461
90838
|
return { task: "discussion", cloudTask: null, board, cwd: projectDir2, project: job.project, number: null, workflow: null };
|
|
90462
90839
|
}
|
|
90463
90840
|
var boardFolder = (ws) => ({ task: "board", cloudTask: null, board: ws.board, cwd: ws.cwd, project: ws.project, number: null, workflow: null });
|
|
90464
90841
|
function keptBoard(cwd) {
|
|
90465
|
-
const board =
|
|
90842
|
+
const board = path23.join(cwd, ".akb", "kanban");
|
|
90466
90843
|
const base = readBase({ cwd });
|
|
90467
90844
|
const project = base.project ?? /^projects\/([^/]+)\//.exec(Object.keys(base.files).find((p2) => p2.startsWith("projects/")) ?? "")?.[1];
|
|
90468
90845
|
return base.head_seq === null || !project ? null : boardFolder({ board, cwd, project });
|
|
@@ -90470,17 +90847,17 @@ function keptBoard(cwd) {
|
|
|
90470
90847
|
var turns = /* @__PURE__ */ new Map();
|
|
90471
90848
|
function inFolder(dir, work) {
|
|
90472
90849
|
const next = (turns.get(dir) ?? Promise.resolve()).then(work, work);
|
|
90473
|
-
const
|
|
90850
|
+
const held4 = next.catch(() => {
|
|
90474
90851
|
});
|
|
90475
|
-
turns.set(dir,
|
|
90476
|
-
void
|
|
90852
|
+
turns.set(dir, held4);
|
|
90853
|
+
void held4.then(() => turns.get(dir) === held4 && turns.delete(dir));
|
|
90477
90854
|
return next;
|
|
90478
90855
|
}
|
|
90479
90856
|
var safe = (name) => name.replace(/[^\w.-]/g, "_") || "default";
|
|
90480
90857
|
function openCached(project) {
|
|
90481
90858
|
const dir = cacheDir(project);
|
|
90482
|
-
if (
|
|
90483
|
-
|
|
90859
|
+
if (fs20.existsSync(path23.join(dir, ".git"))) return dir;
|
|
90860
|
+
fs20.mkdirSync(dir, { recursive: true });
|
|
90484
90861
|
const git3 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" }).status === 0;
|
|
90485
90862
|
if (git3("init", "-q")) git3("-c", "user.name=WildCrane", "-c", "user.email=runner@wildcrane.ai", "commit", "-q", "--allow-empty", "-m", "general");
|
|
90486
90863
|
return dir;
|
|
@@ -90493,56 +90870,56 @@ function keepOutOfGit(dir, folders2 = SKILL_FOLDERS) {
|
|
|
90493
90870
|
if (inside.status !== 0) return;
|
|
90494
90871
|
const missing = [".akb/", ...folders2.map((f2) => `${f2}/`)].filter((p2) => git3("check-ignore", "-q", p2).status !== 0);
|
|
90495
90872
|
if (!missing.length) return;
|
|
90496
|
-
const exclude =
|
|
90497
|
-
|
|
90498
|
-
const
|
|
90499
|
-
|
|
90873
|
+
const exclude = path23.resolve(dir, inside.stdout.trim());
|
|
90874
|
+
fs20.mkdirSync(path23.dirname(exclude), { recursive: true });
|
|
90875
|
+
const held4 = fs20.existsSync(exclude) ? fs20.readFileSync(exclude, "utf8") : "";
|
|
90876
|
+
fs20.writeFileSync(exclude, `${held4}${held4 && !held4.endsWith("\n") ? "\n" : ""}${missing.join("\n")}
|
|
90500
90877
|
`);
|
|
90501
90878
|
}
|
|
90502
|
-
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ??
|
|
90879
|
+
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ?? path23.join(ws.board, "todo", `${ws.number ?? 0}-task.md`);
|
|
90503
90880
|
function findCard(board, number) {
|
|
90504
90881
|
const named2 = new RegExp(`^${number}-`);
|
|
90505
90882
|
const walk = (dir) => {
|
|
90506
90883
|
let entries;
|
|
90507
90884
|
try {
|
|
90508
|
-
entries =
|
|
90885
|
+
entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
90509
90886
|
} catch {
|
|
90510
90887
|
return null;
|
|
90511
90888
|
}
|
|
90512
90889
|
for (const e2 of entries) {
|
|
90513
90890
|
if (!named2.test(e2.name)) continue;
|
|
90514
|
-
if (e2.isFile() && e2.name.endsWith(".md")) return
|
|
90515
|
-
const root =
|
|
90516
|
-
if (e2.isDirectory() &&
|
|
90891
|
+
if (e2.isFile() && e2.name.endsWith(".md")) return path23.join(dir, e2.name);
|
|
90892
|
+
const root = path23.join(dir, e2.name, "root.md");
|
|
90893
|
+
if (e2.isDirectory() && fs20.existsSync(root)) return root;
|
|
90517
90894
|
}
|
|
90518
90895
|
for (const e2 of entries) if (e2.isDirectory() && !e2.name.startsWith(".")) {
|
|
90519
|
-
const hit = walk(
|
|
90896
|
+
const hit = walk(path23.join(dir, e2.name));
|
|
90520
90897
|
if (hit) return hit;
|
|
90521
90898
|
}
|
|
90522
90899
|
return null;
|
|
90523
90900
|
};
|
|
90524
|
-
return walk(
|
|
90901
|
+
return walk(path23.join(board, "todo")) ?? walk(path23.join(board, ".archive"));
|
|
90525
90902
|
}
|
|
90526
90903
|
function akbCardOf(ws) {
|
|
90527
90904
|
return ws.number && findCard(ws.board, ws.number) ? ws.number : void 0;
|
|
90528
90905
|
}
|
|
90529
|
-
var recordFile = (ws) =>
|
|
90906
|
+
var recordFile = (ws) => path23.join(ws.board, ".sync", `${ws.task}.json`);
|
|
90530
90907
|
function readRecord(ws) {
|
|
90531
90908
|
try {
|
|
90532
|
-
return { ...EMPTY, ...JSON.parse(
|
|
90909
|
+
return { ...EMPTY, ...JSON.parse(fs20.readFileSync(recordFile(ws), "utf8")) };
|
|
90533
90910
|
} catch {
|
|
90534
90911
|
return structuredClone(EMPTY);
|
|
90535
90912
|
}
|
|
90536
90913
|
}
|
|
90537
90914
|
function writeRecord(ws, record) {
|
|
90538
|
-
|
|
90539
|
-
|
|
90915
|
+
fs20.mkdirSync(path23.dirname(recordFile(ws)), { recursive: true });
|
|
90916
|
+
fs20.writeFileSync(recordFile(ws), `${JSON.stringify(record, null, 2)}
|
|
90540
90917
|
`);
|
|
90541
90918
|
}
|
|
90542
|
-
var baseFile = (ws) =>
|
|
90919
|
+
var baseFile = (ws) => path23.join(ws.cwd, ".akb", "base.json");
|
|
90543
90920
|
function readBase(ws) {
|
|
90544
90921
|
try {
|
|
90545
|
-
const base = JSON.parse(
|
|
90922
|
+
const base = JSON.parse(fs20.readFileSync(baseFile(ws), "utf8"));
|
|
90546
90923
|
if (base.layout === "workspace") return base;
|
|
90547
90924
|
} catch {
|
|
90548
90925
|
}
|
|
@@ -90550,25 +90927,25 @@ function readBase(ws) {
|
|
|
90550
90927
|
}
|
|
90551
90928
|
function writeBase(ws, base) {
|
|
90552
90929
|
const file2 = baseFile(ws);
|
|
90553
|
-
|
|
90554
|
-
|
|
90555
|
-
|
|
90930
|
+
fs20.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
90931
|
+
fs20.writeFileSync(`${file2}.tmp`, JSON.stringify(base));
|
|
90932
|
+
fs20.renameSync(`${file2}.tmp`, file2);
|
|
90556
90933
|
}
|
|
90557
|
-
var hashOf = (bytes2) =>
|
|
90934
|
+
var hashOf = (bytes2) => crypto3.createHash("sha256").update(bytes2).digest("hex");
|
|
90558
90935
|
function hashFile(file2) {
|
|
90559
90936
|
try {
|
|
90560
|
-
return hashOf(
|
|
90937
|
+
return hashOf(fs20.readFileSync(file2));
|
|
90561
90938
|
} catch {
|
|
90562
90939
|
return null;
|
|
90563
90940
|
}
|
|
90564
90941
|
}
|
|
90565
90942
|
function write(file2, bytes2) {
|
|
90566
|
-
|
|
90567
|
-
|
|
90943
|
+
fs20.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
90944
|
+
fs20.writeFileSync(file2, bytes2);
|
|
90568
90945
|
}
|
|
90569
90946
|
function readText(file2) {
|
|
90570
90947
|
try {
|
|
90571
|
-
return
|
|
90948
|
+
return fs20.readFileSync(file2, "utf8");
|
|
90572
90949
|
} catch {
|
|
90573
90950
|
return null;
|
|
90574
90951
|
}
|
|
@@ -90576,14 +90953,14 @@ function readText(file2) {
|
|
|
90576
90953
|
function filesUnder(dir, base = dir) {
|
|
90577
90954
|
let entries;
|
|
90578
90955
|
try {
|
|
90579
|
-
entries =
|
|
90956
|
+
entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
90580
90957
|
} catch {
|
|
90581
90958
|
return [];
|
|
90582
90959
|
}
|
|
90583
90960
|
return entries.flatMap((e2) => {
|
|
90584
|
-
const full =
|
|
90961
|
+
const full = path23.join(dir, e2.name);
|
|
90585
90962
|
if (e2.isDirectory()) return filesUnder(full, base);
|
|
90586
|
-
return e2.isFile() ? [
|
|
90963
|
+
return e2.isFile() ? [path23.relative(base, full).split(path23.sep).join("/")] : [];
|
|
90587
90964
|
});
|
|
90588
90965
|
}
|
|
90589
90966
|
var kept3 = isBoardPath;
|
|
@@ -90599,7 +90976,7 @@ function viewOf(ws, base, shared) {
|
|
|
90599
90976
|
}
|
|
90600
90977
|
function assetFiles(ws, list) {
|
|
90601
90978
|
const card = cardFile(ws);
|
|
90602
|
-
return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) =>
|
|
90979
|
+
return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) => path23.relative(ws.board, f2).split(path23.sep).join("/")));
|
|
90603
90980
|
}
|
|
90604
90981
|
var assetsListOf = (ws, base) => base.files[rootOf(ws) + assetsFile(ws.task)]?.content;
|
|
90605
90982
|
var localFiles = (ws, base) => {
|
|
@@ -90608,9 +90985,9 @@ var localFiles = (ws, base) => {
|
|
|
90608
90985
|
};
|
|
90609
90986
|
var SKILL_PATH = /^skills\/([a-z0-9]+(?:-[a-z0-9]+)*)\/((?:[\w.-]+\/)*[\w.-]+)$/;
|
|
90610
90987
|
function pullTools(ws, record, files) {
|
|
90611
|
-
const
|
|
90612
|
-
const ours = new Set(Object.keys(
|
|
90613
|
-
const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) =>
|
|
90988
|
+
const held4 = record.tools?.skills ?? {};
|
|
90989
|
+
const ours = new Set(Object.keys(held4).map((name) => name.split("/")[1]));
|
|
90990
|
+
const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) => fs20.existsSync(path23.join(ws.cwd, root, skill)));
|
|
90614
90991
|
const kept4 = Object.keys(files).map((name) => SKILL_PATH.exec(name)?.[1]).filter((skill) => skill && !theirs(skill));
|
|
90615
90992
|
const skills = {};
|
|
90616
90993
|
for (const [name, text3] of Object.entries(files)) {
|
|
@@ -90618,17 +90995,17 @@ function pullTools(ws, record, files) {
|
|
|
90618
90995
|
if (!at2 || at2[1] === "kanban" || !kept4.includes(at2[1]) || at2[2].split("/").includes("..")) continue;
|
|
90619
90996
|
skills[name] = hashOf(text3);
|
|
90620
90997
|
for (const root of SKILL_ROOTS) {
|
|
90621
|
-
const file2 =
|
|
90622
|
-
if (
|
|
90998
|
+
const file2 = path23.join(ws.cwd, root, at2[1], at2[2]);
|
|
90999
|
+
if (held4[name] !== skills[name] || hashFile(file2) !== skills[name]) write(file2, text3);
|
|
90623
91000
|
}
|
|
90624
91001
|
}
|
|
90625
|
-
for (const name of Object.keys(
|
|
91002
|
+
for (const name of Object.keys(held4)) {
|
|
90626
91003
|
if (skills[name]) continue;
|
|
90627
91004
|
const [, skill, rest] = SKILL_PATH.exec(name) ?? [];
|
|
90628
91005
|
if (!skill || !rest) continue;
|
|
90629
91006
|
for (const root of SKILL_ROOTS) {
|
|
90630
|
-
|
|
90631
|
-
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`)))
|
|
91007
|
+
fs20.rmSync(path23.join(ws.cwd, root, skill, rest), { force: true });
|
|
91008
|
+
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`))) fs20.rmSync(path23.join(ws.cwd, root, skill), { recursive: true, force: true });
|
|
90632
91009
|
}
|
|
90633
91010
|
}
|
|
90634
91011
|
const names2 = [...new Set(Object.keys(skills).map((name) => name.split("/")[1]))];
|
|
@@ -90645,8 +91022,8 @@ async function pullWorkflow(ws, record, base) {
|
|
|
90645
91022
|
let files = {};
|
|
90646
91023
|
if (ws.workflow) {
|
|
90647
91024
|
const root = `workflows/${workflowFolder(ws.workflow)}/`;
|
|
90648
|
-
const
|
|
90649
|
-
files = Object.fromEntries(Object.entries(base.files).filter(([p2]) => p2.startsWith(
|
|
91025
|
+
const held4 = rootOf(ws) + root;
|
|
91026
|
+
files = Object.fromEntries(Object.entries(base.files).filter(([p2]) => p2.startsWith(held4) && isBoardPath(p2.slice(rootOf(ws).length))).map(([p2, f2]) => [p2.slice(held4.length), f2.content]));
|
|
90650
91027
|
record.builtin = ws.workflow.startsWith("wf_builtin_");
|
|
90651
91028
|
let found = Object.keys(files).length > 0;
|
|
90652
91029
|
if (!found && ws.cloudTask) {
|
|
@@ -90656,7 +91033,7 @@ async function pullWorkflow(ws, record, base) {
|
|
|
90656
91033
|
files = read.value.files;
|
|
90657
91034
|
found = true;
|
|
90658
91035
|
if (!record.builtin) {
|
|
90659
|
-
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(
|
|
91036
|
+
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(path23.join(ws.board, root, name), text3);
|
|
90660
91037
|
}
|
|
90661
91038
|
}
|
|
90662
91039
|
}
|
|
@@ -90664,15 +91041,15 @@ async function pullWorkflow(ws, record, base) {
|
|
|
90664
91041
|
}
|
|
90665
91042
|
pullAgents(ws, base, ws.workflow && !record.builtin ? files : {});
|
|
90666
91043
|
const placed = readPlaced(ws);
|
|
90667
|
-
for (const name of Object.keys(record.agents ?? {})) if (!placed[name])
|
|
91044
|
+
for (const name of Object.keys(record.agents ?? {})) if (!placed[name]) fs20.rmSync(path23.join(ws.board, name), { force: true });
|
|
90668
91045
|
record.agents = {};
|
|
90669
91046
|
return { ok: true, value: void 0 };
|
|
90670
91047
|
}
|
|
90671
91048
|
var OWN_FOLDER = /^wf-(?!builtin-)[a-z0-9-]+$/;
|
|
90672
|
-
var agentsRecord = (ws) =>
|
|
91049
|
+
var agentsRecord = (ws) => path23.join(ws.board, ".sync", "agents.json");
|
|
90673
91050
|
function readPlaced(ws) {
|
|
90674
91051
|
try {
|
|
90675
|
-
return JSON.parse(
|
|
91052
|
+
return JSON.parse(fs20.readFileSync(agentsRecord(ws), "utf8"));
|
|
90676
91053
|
} catch {
|
|
90677
91054
|
return {};
|
|
90678
91055
|
}
|
|
@@ -90693,8 +91070,8 @@ function pullAgents(ws, base, own) {
|
|
|
90693
91070
|
const names2 = /* @__PURE__ */ new Set();
|
|
90694
91071
|
for (const [name, text3] of Object.entries(files)) {
|
|
90695
91072
|
const agent = /^agents\/([^/]+)\//.exec(name)?.[1];
|
|
90696
|
-
const file2 =
|
|
90697
|
-
if (!agent || taken.has(agent) || !file2.startsWith(
|
|
91073
|
+
const file2 = path23.resolve(ws.board, name);
|
|
91074
|
+
if (!agent || taken.has(agent) || !file2.startsWith(path23.join(ws.board, "agents") + path23.sep)) continue;
|
|
90698
91075
|
names2.add(agent);
|
|
90699
91076
|
agents[name] = text3;
|
|
90700
91077
|
}
|
|
@@ -90704,42 +91081,42 @@ function pullAgents(ws, base, own) {
|
|
|
90704
91081
|
const hashes = {};
|
|
90705
91082
|
for (const [name, text3] of Object.entries(agents)) {
|
|
90706
91083
|
hashes[name] = hashOf(text3);
|
|
90707
|
-
if (hashFile(
|
|
91084
|
+
if (hashFile(path23.join(ws.board, name)) !== hashes[name]) write(path23.join(ws.board, name), text3);
|
|
90708
91085
|
}
|
|
90709
|
-
for (const name of Object.keys(before)) if (!hashes[name])
|
|
91086
|
+
for (const name of Object.keys(before)) if (!hashes[name]) fs20.rmSync(path23.join(ws.board, name), { force: true });
|
|
90710
91087
|
write(agentsRecord(ws), `${JSON.stringify(hashes, null, 2)}
|
|
90711
91088
|
`);
|
|
90712
91089
|
}
|
|
90713
91090
|
function pullDraftAgents(ws, record) {
|
|
90714
91091
|
if (ws.workflow !== BUILDER) return;
|
|
90715
|
-
const root =
|
|
91092
|
+
const root = path23.join(ws.board, "workflows", draftFolder(ws.task), "agents");
|
|
90716
91093
|
record.agents ??= {};
|
|
90717
91094
|
for (const name of filesUnder(root)) {
|
|
90718
|
-
const text3 =
|
|
91095
|
+
const text3 = fs20.readFileSync(path23.join(root, name));
|
|
90719
91096
|
const at2 = `agents/${name}`;
|
|
90720
91097
|
record.agents[at2] = hashOf(text3);
|
|
90721
|
-
if (hashFile(
|
|
91098
|
+
if (hashFile(path23.join(ws.board, at2)) !== record.agents[at2]) write(path23.join(ws.board, at2), text3);
|
|
90722
91099
|
}
|
|
90723
91100
|
}
|
|
90724
91101
|
function workflowFile(ws) {
|
|
90725
91102
|
if (!ws.workflow || readRecord(ws).builtin) return null;
|
|
90726
|
-
const file2 =
|
|
90727
|
-
return
|
|
91103
|
+
const file2 = path23.join(ws.board, "workflows", workflowFolder(ws.workflow), "WORKFLOW.md");
|
|
91104
|
+
return fs20.existsSync(file2) ? file2 : null;
|
|
90728
91105
|
}
|
|
90729
91106
|
function assetPath(ws, name, card) {
|
|
90730
91107
|
if (/^[a-z][\w+.-]*:/i.test(name) || name.startsWith("/") || name.startsWith("#")) return null;
|
|
90731
|
-
const
|
|
90732
|
-
if (
|
|
91108
|
+
const held4 = /^\.(assets|mockups)\//.exec(name);
|
|
91109
|
+
if (held4) {
|
|
90733
91110
|
const state = stateDir(ws);
|
|
90734
|
-
const file3 = state &&
|
|
90735
|
-
return file3 && file3.startsWith(
|
|
91111
|
+
const file3 = state && path23.resolve(state, held4[1], name.slice(held4[0].length));
|
|
91112
|
+
return file3 && file3.startsWith(path23.join(state, held4[1]) + path23.sep) ? file3 : null;
|
|
90736
91113
|
}
|
|
90737
|
-
const file2 =
|
|
90738
|
-
return file2.startsWith(ws.board +
|
|
91114
|
+
const file2 = path23.resolve(path23.dirname(card), name);
|
|
91115
|
+
return file2.startsWith(ws.board + path23.sep) ? file2 : null;
|
|
90739
91116
|
}
|
|
90740
91117
|
function cardAssetsDir(ws, id) {
|
|
90741
91118
|
const state = stateDir(ws);
|
|
90742
|
-
return state &&
|
|
91119
|
+
return state && path23.join(state, "assets", String(id));
|
|
90743
91120
|
}
|
|
90744
91121
|
function stateDir(ws) {
|
|
90745
91122
|
try {
|
|
@@ -90750,8 +91127,8 @@ function stateDir(ws) {
|
|
|
90750
91127
|
}
|
|
90751
91128
|
function assetsOf(text3) {
|
|
90752
91129
|
try {
|
|
90753
|
-
const
|
|
90754
|
-
return
|
|
91130
|
+
const held4 = JSON.parse(text3 ?? "{}");
|
|
91131
|
+
return held4 && typeof held4 === "object" && !Array.isArray(held4) ? held4 : {};
|
|
90755
91132
|
} catch {
|
|
90756
91133
|
return {};
|
|
90757
91134
|
}
|
|
@@ -90778,13 +91155,13 @@ var pullChanges = (ws) => inFolder(ws.cwd, async () => {
|
|
|
90778
91155
|
const p2 = f2.path.startsWith(root) ? f2.path.slice(root.length) : f2.path;
|
|
90779
91156
|
const isShared = p2.startsWith(MEMORY2) && shared(p2.slice(MEMORY2.length));
|
|
90780
91157
|
if (kept3(p2) && isShared === !f2.path.startsWith(root)) {
|
|
90781
|
-
const file2 =
|
|
91158
|
+
const file2 = path23.join(ws.board, p2);
|
|
90782
91159
|
const here2 = readText(file2);
|
|
90783
91160
|
if (here2 !== f2.content && here2 !== (base.files[f2.path]?.content ?? null)) {
|
|
90784
91161
|
skipped = true;
|
|
90785
91162
|
continue;
|
|
90786
91163
|
}
|
|
90787
|
-
if (f2.content === null)
|
|
91164
|
+
if (f2.content === null) fs20.rmSync(file2, { force: true });
|
|
90788
91165
|
else if (here2 !== f2.content) write(file2, f2.content);
|
|
90789
91166
|
}
|
|
90790
91167
|
if (f2.content === null) delete base.files[f2.path];
|
|
@@ -90815,13 +91192,13 @@ async function readCloud(ws) {
|
|
|
90815
91192
|
writeBase(ws, base);
|
|
90816
91193
|
const reset = (view2) => {
|
|
90817
91194
|
for (const [p2, content] of view2) {
|
|
90818
|
-
const file2 =
|
|
91195
|
+
const file2 = path23.join(ws.board, p2);
|
|
90819
91196
|
if (kept3(p2) && readText(file2) !== content) write(file2, content);
|
|
90820
91197
|
}
|
|
90821
91198
|
};
|
|
90822
91199
|
const view = viewOf(ws, base, sharedMemory(ws.board));
|
|
90823
91200
|
const first = (p2) => isSettingsPath(p2) && !known2.has(rootOf(ws) + p2);
|
|
90824
|
-
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2))
|
|
91201
|
+
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2)) fs20.rmSync(path23.join(ws.board, p2), { force: true });
|
|
90825
91202
|
reset(view);
|
|
90826
91203
|
const record = readRecord(ws);
|
|
90827
91204
|
const workflow = await pullWorkflow(ws, record, base);
|
|
@@ -90835,18 +91212,18 @@ async function readCloud(ws) {
|
|
|
90835
91212
|
return { ok: true, value: void 0 };
|
|
90836
91213
|
}
|
|
90837
91214
|
function writeIndex(board) {
|
|
90838
|
-
const todo =
|
|
91215
|
+
const todo = path23.join(board, "todo");
|
|
90839
91216
|
const cards = [];
|
|
90840
91217
|
let entries = [];
|
|
90841
91218
|
try {
|
|
90842
|
-
entries =
|
|
91219
|
+
entries = fs20.readdirSync(todo, { withFileTypes: true });
|
|
90843
91220
|
} catch {
|
|
90844
91221
|
}
|
|
90845
91222
|
for (const e2 of entries) {
|
|
90846
91223
|
const id = /^(\d+)-/.exec(e2.name)?.[1];
|
|
90847
91224
|
if (!id) continue;
|
|
90848
91225
|
const link = e2.isDirectory() ? `${e2.name}/root.md` : e2.name.endsWith(".md") ? e2.name : null;
|
|
90849
|
-
const text4 = link && readText(
|
|
91226
|
+
const text4 = link && readText(path23.join(todo, link));
|
|
90850
91227
|
if (text4 === null || !link) continue;
|
|
90851
91228
|
cards.push({ id: Number(id), title: cardFront(text4).title ?? e2.name.replace(/\.md$/, ""), link });
|
|
90852
91229
|
}
|
|
@@ -90861,7 +91238,7 @@ the number at the front of a filename is the task id.
|
|
|
90861
91238
|
|
|
90862
91239
|
${list}
|
|
90863
91240
|
`;
|
|
90864
|
-
if (readText(
|
|
91241
|
+
if (readText(path23.join(todo, "README.md")) !== text3) write(path23.join(todo, "README.md"), text3);
|
|
90865
91242
|
}
|
|
90866
91243
|
var workspaceOf = (ws) => readBase(ws).workspace ?? null;
|
|
90867
91244
|
async function pullAssets(ws, record, assets) {
|
|
@@ -90876,13 +91253,13 @@ async function pullAssets(ws, record, assets) {
|
|
|
90876
91253
|
if (!latest.ok) return latest;
|
|
90877
91254
|
version = latest.value.latest_version ?? 0;
|
|
90878
91255
|
}
|
|
90879
|
-
const
|
|
90880
|
-
if (
|
|
90881
|
-
out[name] = { ...
|
|
91256
|
+
const held4 = record.assets[name];
|
|
91257
|
+
if (held4?.kind === "html" && held4.artifact === ref.artifact) {
|
|
91258
|
+
out[name] = { ...held4, version };
|
|
90882
91259
|
continue;
|
|
90883
91260
|
}
|
|
90884
|
-
if (
|
|
90885
|
-
out[name] =
|
|
91261
|
+
if (held4?.artifact === ref.artifact && held4.version === version && hashFile(target) === held4.hash) {
|
|
91262
|
+
out[name] = held4;
|
|
90886
91263
|
continue;
|
|
90887
91264
|
}
|
|
90888
91265
|
const bytes2 = await readAsset(ref.artifact, version);
|
|
@@ -90894,10 +91271,10 @@ async function pullAssets(ws, record, assets) {
|
|
|
90894
91271
|
return { ok: true, value: void 0 };
|
|
90895
91272
|
}
|
|
90896
91273
|
async function readAsset(artifact, version) {
|
|
90897
|
-
const
|
|
90898
|
-
if (!
|
|
90899
|
-
if (
|
|
90900
|
-
const content =
|
|
91274
|
+
const held4 = await readVersion(artifact, version);
|
|
91275
|
+
if (!held4.ok) return held4;
|
|
91276
|
+
if (held4.value.file) return download(held4.value.file.url);
|
|
91277
|
+
const content = held4.value.content;
|
|
90901
91278
|
return { ok: true, value: Buffer.from(typeof content === "string" ? content : JSON.stringify(content)) };
|
|
90902
91279
|
}
|
|
90903
91280
|
var TYPES = {
|
|
@@ -90928,14 +91305,14 @@ function kindOf(ext) {
|
|
|
90928
91305
|
return type.startsWith("video/") || type.startsWith("audio/") ? "video" : "asset";
|
|
90929
91306
|
}
|
|
90930
91307
|
async function sentOf(file2) {
|
|
90931
|
-
const ext =
|
|
91308
|
+
const ext = path23.extname(file2).toLowerCase();
|
|
90932
91309
|
const kind = kindOf(ext);
|
|
90933
|
-
if (kind !== "html") return { bytes:
|
|
91310
|
+
if (kind !== "html") return { bytes: fs20.readFileSync(file2), type: TYPES[ext] ?? "application/octet-stream", kind };
|
|
90934
91311
|
let page;
|
|
90935
91312
|
try {
|
|
90936
91313
|
page = await (await Promise.resolve().then(() => (init_mockup(), mockup_exports))).drawMockup(file2);
|
|
90937
91314
|
} catch (e2) {
|
|
90938
|
-
console.error(`runner: ${
|
|
91315
|
+
console.error(`runner: ${path23.basename(file2)} could not be drawn: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
90939
91316
|
page = UNDRAWN;
|
|
90940
91317
|
}
|
|
90941
91318
|
return { bytes: Buffer.from(page), type: "text/html", kind };
|
|
@@ -90963,23 +91340,23 @@ async function pushAssets(ws, record, before) {
|
|
|
90963
91340
|
for (const [name, ref] of Object.entries(before)) {
|
|
90964
91341
|
if (!body.includes(name)) continue;
|
|
90965
91342
|
const target = assetPath(ws, name, file2);
|
|
90966
|
-
const
|
|
90967
|
-
const out = target &&
|
|
91343
|
+
const held4 = record.assets[name];
|
|
91344
|
+
const out = target && held4 && fs20.existsSync(target) ? await sentOf(target) : null;
|
|
90968
91345
|
const hash = out && hashOf(out.bytes);
|
|
90969
|
-
if (out &&
|
|
90970
|
-
if (
|
|
90971
|
-
const sent = await uploadAsset(
|
|
91346
|
+
if (out && held4 && held4.kind === "html" !== (out.kind === "html")) continue;
|
|
91347
|
+
if (held4 && out && hash !== held4.hash) {
|
|
91348
|
+
const sent = await uploadAsset(held4.artifact, out);
|
|
90972
91349
|
if (!sent.ok) return sent;
|
|
90973
|
-
assets[name] = { artifact:
|
|
90974
|
-
refs[name] = { artifact:
|
|
91350
|
+
assets[name] = { artifact: held4.artifact, version: sent.value, hash, kind: out.kind };
|
|
91351
|
+
refs[name] = { artifact: held4.artifact, version: sent.value };
|
|
90975
91352
|
} else {
|
|
90976
|
-
if (
|
|
91353
|
+
if (held4) assets[name] = held4;
|
|
90977
91354
|
refs[name] = ref;
|
|
90978
91355
|
}
|
|
90979
91356
|
}
|
|
90980
91357
|
for (const name of namedFiles(body)) {
|
|
90981
91358
|
const target = assetPath(ws, name, file2);
|
|
90982
|
-
if (refs[name] || !target || !
|
|
91359
|
+
if (refs[name] || !target || !fs20.statSync(target, { throwIfNoEntry: false })?.isFile()) continue;
|
|
90983
91360
|
const out = await sentOf(target);
|
|
90984
91361
|
if (!ws.cloudTask) continue;
|
|
90985
91362
|
const made = await createArtifact(ws.cloudTask, name.slice(0, 200), out.kind);
|
|
@@ -90990,24 +91367,24 @@ async function pushAssets(ws, record, before) {
|
|
|
90990
91367
|
refs[name] = { artifact: made.value.id, version: sent.value };
|
|
90991
91368
|
}
|
|
90992
91369
|
record.assets = assets;
|
|
90993
|
-
const list =
|
|
90994
|
-
if (Object.keys(refs).length ||
|
|
91370
|
+
const list = path23.join(ws.board, assetsFile(ws.task));
|
|
91371
|
+
if (Object.keys(refs).length || fs20.existsSync(list)) {
|
|
90995
91372
|
if (JSON.stringify(assetsOf(readText(list))) !== JSON.stringify(refs)) write(list, assetsText(refs));
|
|
90996
91373
|
}
|
|
90997
91374
|
return { ok: true, value: void 0 };
|
|
90998
91375
|
}
|
|
90999
91376
|
function resetSorted(ws) {
|
|
91000
|
-
for (const sub of ["dismissed", "archived"])
|
|
91377
|
+
for (const sub of ["dismissed", "archived"]) fs20.rmSync(path23.join(ws.board, "triage", sub), { recursive: true, force: true });
|
|
91001
91378
|
for (const [p2, content] of viewOf(ws, readBase(ws), sharedMemory(ws.board))) {
|
|
91002
|
-
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(
|
|
91379
|
+
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(path23.join(ws.board, p2), content);
|
|
91003
91380
|
}
|
|
91004
91381
|
}
|
|
91005
91382
|
function proposeItems(ws, base) {
|
|
91006
91383
|
const root = rootOf(ws);
|
|
91007
91384
|
for (const p2 of localFiles(ws, base)) {
|
|
91008
91385
|
if (itemAt(p2)?.state !== "open" || base.files[root + p2]) continue;
|
|
91009
|
-
const file2 =
|
|
91010
|
-
const content =
|
|
91386
|
+
const file2 = path23.join(ws.board, p2);
|
|
91387
|
+
const content = fs20.readFileSync(file2, "utf8");
|
|
91011
91388
|
const said = (key) => new RegExp(`^${key}:`, "m").test(content.split(/\n---/)[0] ?? "");
|
|
91012
91389
|
const fields = {
|
|
91013
91390
|
...ws.cloudTask && !said("source_task") ? { source_task: ws.cloudTask } : {},
|
|
@@ -91058,13 +91435,13 @@ async function send2(ws, job) {
|
|
|
91058
91435
|
const owed = (p2) => !job.id && busy(ws.cwd) && itemAt(p2)?.state === "open" && !base.files[rootOf(ws) + p2];
|
|
91059
91436
|
for (const p2 of local) {
|
|
91060
91437
|
if (owed(p2)) continue;
|
|
91061
|
-
const content =
|
|
91438
|
+
const content = fs20.readFileSync(path23.join(ws.board, p2), "utf8");
|
|
91062
91439
|
const remote = remoteOf(ws, shared, p2);
|
|
91063
91440
|
localOf.set(remote, p2);
|
|
91064
|
-
const
|
|
91065
|
-
if (
|
|
91441
|
+
const held4 = base.files[remote];
|
|
91442
|
+
if (held4?.content === content) continue;
|
|
91066
91443
|
if (Buffer.byteLength(content) > BOARD_FILE_LIMIT) return fail(`${p2} is over ${BOARD_FILE_LIMIT / 1024} KB; keep large files as assets.`, false, "too_large");
|
|
91067
|
-
changes.push({ path: remote, content, base_seq:
|
|
91444
|
+
changes.push({ path: remote, content, base_seq: held4?.seq ?? 0 });
|
|
91068
91445
|
}
|
|
91069
91446
|
for (const p2 of viewOf(ws, base, shared).keys()) {
|
|
91070
91447
|
const remote = remoteOf(ws, shared, p2);
|
|
@@ -91090,15 +91467,15 @@ async function send2(ws, job) {
|
|
|
91090
91467
|
changes.splice(at2, 1);
|
|
91091
91468
|
delete base.files[theirs.path];
|
|
91092
91469
|
writeBase(ws, base);
|
|
91093
|
-
|
|
91470
|
+
fs20.rmSync(path23.join(ws.board, p2), { force: true });
|
|
91094
91471
|
writeIndex(ws.board);
|
|
91095
91472
|
continue;
|
|
91096
91473
|
}
|
|
91097
91474
|
if (at2 < 0) continue;
|
|
91098
91475
|
const merged = itemAt(p2) ? { content: theirs.content } : mergeFile(base.files[theirs.path]?.content ?? null, changes[at2].content, theirs.content);
|
|
91099
91476
|
changes[at2] = { path: theirs.path, content: merged.content, base_seq: theirs.seq };
|
|
91100
|
-
if (merged.content === null)
|
|
91101
|
-
else write(
|
|
91477
|
+
if (merged.content === null) fs20.rmSync(path23.join(ws.board, p2), { force: true });
|
|
91478
|
+
else write(path23.join(ws.board, p2), merged.content);
|
|
91102
91479
|
}
|
|
91103
91480
|
if (!changes.length) return { ok: true, changed: false };
|
|
91104
91481
|
sent = await commitBoard(ws.project, job.id, job.machineId, changes);
|
|
@@ -91119,7 +91496,7 @@ var PULL_MS = 2e3;
|
|
|
91119
91496
|
function keptFolders() {
|
|
91120
91497
|
let cached2 = [];
|
|
91121
91498
|
try {
|
|
91122
|
-
cached2 =
|
|
91499
|
+
cached2 = fs21.readdirSync(cacheRoot()).map((name) => path24.join(cacheRoot(), name));
|
|
91123
91500
|
} catch {
|
|
91124
91501
|
}
|
|
91125
91502
|
return [.../* @__PURE__ */ new Set([...allowedProjects(), ...cached2])].flatMap((dir) => [keptBoard(dir)].filter((ws) => !!ws));
|
|
@@ -91143,12 +91520,12 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
|
|
|
91143
91520
|
const watch = (ws) => {
|
|
91144
91521
|
let watcher;
|
|
91145
91522
|
try {
|
|
91146
|
-
watcher =
|
|
91147
|
-
const p2 = name && String(name).split(
|
|
91148
|
-
const
|
|
91149
|
-
if (closed || !p2 || !isBoardPath(p2) || !
|
|
91150
|
-
clearTimeout(
|
|
91151
|
-
|
|
91523
|
+
watcher = fs21.watch(ws.board, { recursive: true }, (_event, name) => {
|
|
91524
|
+
const p2 = name && String(name).split(path24.sep).join("/");
|
|
91525
|
+
const held4 = watched.get(ws.cwd);
|
|
91526
|
+
if (closed || !p2 || !isBoardPath(p2) || !held4) return;
|
|
91527
|
+
clearTimeout(held4.timer);
|
|
91528
|
+
held4.timer = setTimeout(() => void send3(ws), ms2);
|
|
91152
91529
|
});
|
|
91153
91530
|
} catch {
|
|
91154
91531
|
return false;
|
|
@@ -91192,9 +91569,9 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
|
|
|
91192
91569
|
clearInterval(timer);
|
|
91193
91570
|
for (const t2 of due.values()) clearTimeout(t2);
|
|
91194
91571
|
due.clear();
|
|
91195
|
-
for (const
|
|
91196
|
-
clearTimeout(
|
|
91197
|
-
|
|
91572
|
+
for (const held4 of watched.values()) {
|
|
91573
|
+
clearTimeout(held4.timer);
|
|
91574
|
+
held4.watcher.close();
|
|
91198
91575
|
}
|
|
91199
91576
|
watched.clear();
|
|
91200
91577
|
}
|
|
@@ -91202,16 +91579,16 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
|
|
|
91202
91579
|
}
|
|
91203
91580
|
|
|
91204
91581
|
// src/diff.ts
|
|
91205
|
-
import { execFile } from "node:child_process";
|
|
91206
|
-
import
|
|
91207
|
-
import
|
|
91582
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
91583
|
+
import fs22 from "node:fs";
|
|
91584
|
+
import path25 from "node:path";
|
|
91208
91585
|
var FILE_BYTES = 256 * 1024;
|
|
91209
91586
|
var TOTAL_BYTES = 1024 * 1024;
|
|
91210
91587
|
var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
91211
91588
|
var PATHS = ["--", ".", ":(exclude).akb"];
|
|
91212
91589
|
var STATUS = { A: "added", D: "deleted" };
|
|
91213
91590
|
var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
|
|
91214
|
-
(resolve2) =>
|
|
91591
|
+
(resolve2) => execFile2(
|
|
91215
91592
|
"git",
|
|
91216
91593
|
["-C", dir, "-c", "core.quotePath=false", ...args],
|
|
91217
91594
|
{ encoding: "utf8", maxBuffer },
|
|
@@ -91221,7 +91598,7 @@ var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
|
|
|
91221
91598
|
function projectDir(placed, project) {
|
|
91222
91599
|
if (placed) {
|
|
91223
91600
|
const real = realpath3(placed);
|
|
91224
|
-
return real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
91601
|
+
return real && allowedProjects().some((root) => real === root || real.startsWith(root + path25.sep)) ? real : null;
|
|
91225
91602
|
}
|
|
91226
91603
|
let cached2;
|
|
91227
91604
|
try {
|
|
@@ -91229,11 +91606,11 @@ function projectDir(placed, project) {
|
|
|
91229
91606
|
} catch {
|
|
91230
91607
|
return null;
|
|
91231
91608
|
}
|
|
91232
|
-
return
|
|
91609
|
+
return fs22.existsSync(path25.join(cached2, ".git")) ? cached2 : null;
|
|
91233
91610
|
}
|
|
91234
91611
|
function realpath3(p2) {
|
|
91235
91612
|
try {
|
|
91236
|
-
return
|
|
91613
|
+
return fs22.realpathSync(p2);
|
|
91237
91614
|
} catch {
|
|
91238
91615
|
return null;
|
|
91239
91616
|
}
|
|
@@ -91278,89 +91655,12 @@ async function answerHint(machineId2, hint2) {
|
|
|
91278
91655
|
}
|
|
91279
91656
|
|
|
91280
91657
|
// src/flow.ts
|
|
91281
|
-
import
|
|
91282
|
-
import
|
|
91283
|
-
|
|
91284
|
-
// src/akb.ts
|
|
91285
|
-
import { spawn as spawn3 } from "node:child_process";
|
|
91286
|
-
import fs20 from "node:fs";
|
|
91287
|
-
import path23 from "node:path";
|
|
91288
|
-
import { fileURLToPath } from "node:url";
|
|
91289
|
-
var bundledAkb = () => ({
|
|
91290
|
-
command: process.execPath,
|
|
91291
|
-
args: [path23.join(path23.dirname(fileURLToPath(import.meta.url)), "akb", "bin", "ai4kanban.mjs")]
|
|
91292
|
-
});
|
|
91293
|
-
var quote = (s) => /^[\w./:@=-]+$/.test(s) ? s : `"${s}"`;
|
|
91294
|
-
function shimDir(akb) {
|
|
91295
|
-
const dir = path23.join(runnerHome(), "bin", "akb");
|
|
91296
|
-
const line = [akb.command, ...akb.args].map(quote).join(" ");
|
|
91297
|
-
const [file2, text3] = process.platform === "win32" ? [path23.join(dir, "akb.cmd"), `@${line} %*\r
|
|
91298
|
-
`] : [path23.join(dir, "akb"), `#!/bin/sh
|
|
91299
|
-
exec ${line} "$@"
|
|
91300
|
-
`];
|
|
91301
|
-
try {
|
|
91302
|
-
if (fs20.readFileSync(file2, "utf8") === text3) return dir;
|
|
91303
|
-
} catch {
|
|
91304
|
-
}
|
|
91305
|
-
fs20.mkdirSync(dir, { recursive: true });
|
|
91306
|
-
fs20.writeFileSync(file2, text3, { mode: 493 });
|
|
91307
|
-
return dir;
|
|
91308
|
-
}
|
|
91309
|
-
function akbEnv(akb, board, task, line) {
|
|
91310
|
-
const env2 = {};
|
|
91311
|
-
const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV];
|
|
91312
|
-
for (const [k, v2] of Object.entries(process.env)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
|
|
91313
|
-
const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
91314
|
-
env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path23.delimiter);
|
|
91315
|
-
env2.AI4KANBAN_COMMAND = "akb";
|
|
91316
|
-
if (board) env2.AI4KANBAN_BOARD = board;
|
|
91317
|
-
if (task) env2.AI4KANBAN_TASK = task;
|
|
91318
|
-
if (line !== void 0) env2[LANGUAGE_LINE_ENV] = line;
|
|
91319
|
-
return env2;
|
|
91320
|
-
}
|
|
91321
|
-
var KEEP = 256 * 1024;
|
|
91322
|
-
function runAkb(akb, args, opts) {
|
|
91323
|
-
return new Promise((resolve2) => {
|
|
91324
|
-
let out = "";
|
|
91325
|
-
let last2 = "";
|
|
91326
|
-
const note = (text3) => {
|
|
91327
|
-
const line = text3.split("\n").map((l2) => l2.trim()).filter(Boolean).at(-1);
|
|
91328
|
-
if (line) last2 = line;
|
|
91329
|
-
};
|
|
91330
|
-
let child;
|
|
91331
|
-
try {
|
|
91332
|
-
child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: akbEnv(akb, opts.board, opts.task, opts.line), stdio: ["ignore", "pipe", "pipe"] });
|
|
91333
|
-
} catch (e2) {
|
|
91334
|
-
return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
|
|
91335
|
-
}
|
|
91336
|
-
opts.track?.(child);
|
|
91337
|
-
child.stdout.setEncoding("utf8");
|
|
91338
|
-
child.stderr.setEncoding("utf8");
|
|
91339
|
-
child.stdout.on("data", (chunk) => {
|
|
91340
|
-
out = (out + chunk).slice(-KEEP);
|
|
91341
|
-
note(chunk);
|
|
91342
|
-
opts.show?.(chunk);
|
|
91343
|
-
});
|
|
91344
|
-
child.stderr.on("data", (chunk) => {
|
|
91345
|
-
note(chunk);
|
|
91346
|
-
opts.show?.(chunk);
|
|
91347
|
-
});
|
|
91348
|
-
child.on("error", (e2) => resolve2({ code: null, out, last: e2.message }));
|
|
91349
|
-
child.on("close", (code) => resolve2({ code, out, last: last2 }));
|
|
91350
|
-
});
|
|
91351
|
-
}
|
|
91352
|
-
function answerOf2(ran) {
|
|
91353
|
-
const line = ran.out.trim().split("\n").at(-1) ?? "";
|
|
91354
|
-
try {
|
|
91355
|
-
return JSON.parse(line);
|
|
91356
|
-
} catch {
|
|
91357
|
-
return null;
|
|
91358
|
-
}
|
|
91359
|
-
}
|
|
91658
|
+
import fs25 from "node:fs";
|
|
91659
|
+
import path28 from "node:path";
|
|
91360
91660
|
|
|
91361
91661
|
// src/triage.ts
|
|
91362
|
-
import
|
|
91363
|
-
import
|
|
91662
|
+
import fs23 from "node:fs";
|
|
91663
|
+
import path26 from "node:path";
|
|
91364
91664
|
|
|
91365
91665
|
// ../cli/src/lib/signals/identity.ts
|
|
91366
91666
|
import { createHash } from "node:crypto";
|
|
@@ -91368,8 +91668,8 @@ var DERIVED = "derived-";
|
|
|
91368
91668
|
var derivedSourceId = (seed) => `${DERIVED}${createHash("sha256").update(seed).digest("hex").slice(0, 16)}`;
|
|
91369
91669
|
|
|
91370
91670
|
// src/triage.ts
|
|
91371
|
-
var triageDir = (board) =>
|
|
91372
|
-
var rejectedDir = (board) =>
|
|
91671
|
+
var triageDir = (board) => path26.join(board, "triage");
|
|
91672
|
+
var rejectedDir = (board) => path26.join(board, ".archive", ".sync");
|
|
91373
91673
|
var SCRATCH = ["dismissed", "archived"];
|
|
91374
91674
|
var stamp = (at2) => formatStamp(at2 ? new Date(at2) : /* @__PURE__ */ new Date());
|
|
91375
91675
|
function slugOf(title) {
|
|
@@ -91378,7 +91678,7 @@ function slugOf(title) {
|
|
|
91378
91678
|
function freeName(dir, title) {
|
|
91379
91679
|
const stem = slugOf(title);
|
|
91380
91680
|
let name = `${stem}.md`;
|
|
91381
|
-
for (let n = 2;
|
|
91681
|
+
for (let n = 2; fs23.existsSync(path26.join(dir, name)); n++) name = `${stem}-${n}.md`;
|
|
91382
91682
|
return name;
|
|
91383
91683
|
}
|
|
91384
91684
|
function itemText(item, fields = {}) {
|
|
@@ -91398,17 +91698,17 @@ ${item.text.trim()}
|
|
|
91398
91698
|
`;
|
|
91399
91699
|
}
|
|
91400
91700
|
function writeItem(dir, item, fields = {}) {
|
|
91401
|
-
|
|
91701
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
91402
91702
|
const name = freeName(dir, item.title);
|
|
91403
|
-
|
|
91703
|
+
fs23.writeFileSync(path26.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
|
|
91404
91704
|
return name;
|
|
91405
91705
|
}
|
|
91406
91706
|
function layOut(board, rejections) {
|
|
91407
91707
|
clearLaid(board);
|
|
91408
91708
|
const dir = rejectedDir(board);
|
|
91409
|
-
|
|
91709
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
91410
91710
|
for (const t2 of rejections.tasks) {
|
|
91411
|
-
|
|
91711
|
+
fs23.writeFileSync(path26.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
|
|
91412
91712
|
"---",
|
|
91413
91713
|
`title: ${yamlScalar(t2.title)}`,
|
|
91414
91714
|
"status: todo",
|
|
@@ -91423,20 +91723,20 @@ function layOut(board, rejections) {
|
|
|
91423
91723
|
].join("\n"));
|
|
91424
91724
|
}
|
|
91425
91725
|
for (const item of rejections.triage) {
|
|
91426
|
-
const sub =
|
|
91726
|
+
const sub = path26.join(triageDir(board), item.state === "dismissed" ? "dismissed" : "archived");
|
|
91427
91727
|
const fields = item.state === "dismissed" ? { dismissed_at: stamp(item.dismissed_at), dismissed_by: "user", ...item.dismissed_reason ? { dismissed_reason: item.dismissed_reason } : {} } : {};
|
|
91428
91728
|
writeItem(sub, item, fields);
|
|
91429
91729
|
}
|
|
91430
91730
|
return { tasks: rejections.tasks.map((t2) => t2.id), triage: rejections.triage.map((i) => i.id) };
|
|
91431
91731
|
}
|
|
91432
91732
|
function clearLaid(board) {
|
|
91433
|
-
|
|
91434
|
-
for (const sub of SCRATCH)
|
|
91733
|
+
fs23.rmSync(rejectedDir(board), { recursive: true, force: true });
|
|
91734
|
+
for (const sub of SCRATCH) fs23.rmSync(path26.join(triageDir(board), sub), { recursive: true, force: true });
|
|
91435
91735
|
}
|
|
91436
91736
|
|
|
91437
91737
|
// src/built.ts
|
|
91438
|
-
import
|
|
91439
|
-
import
|
|
91738
|
+
import fs24 from "node:fs";
|
|
91739
|
+
import path27 from "node:path";
|
|
91440
91740
|
|
|
91441
91741
|
// ../cli/src/lib/agent/workflow-def.ts
|
|
91442
91742
|
var WORKFLOW_ID = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
@@ -91594,26 +91894,26 @@ function checkWorkflowFiles(value, official = false) {
|
|
|
91594
91894
|
|
|
91595
91895
|
// src/built.ts
|
|
91596
91896
|
var isBuilder = (ws) => ws.workflow === BUILDER;
|
|
91597
|
-
var draftDir = (ws) =>
|
|
91598
|
-
var draftLine = (ws) => `<!-- workflow folder: ${
|
|
91897
|
+
var draftDir = (ws) => path27.join(ws.board, "workflows", draftFolder(ws.task));
|
|
91898
|
+
var draftLine = (ws) => `<!-- workflow folder: ${path27.relative(ws.cwd, draftDir(ws)).split(path27.sep).join("/")}/ -->`;
|
|
91599
91899
|
var skeleton = (name) => ["---", `name: ${/\s#/.test(name) ? JSON.stringify(name) : yamlScalar(name)}`, "needsArtifact: false", "---", ""].join("\n");
|
|
91600
91900
|
async function placeDraft(ws, read) {
|
|
91601
91901
|
const dir = draftDir(ws);
|
|
91602
|
-
if (
|
|
91902
|
+
if (fs24.existsSync(path27.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
|
|
91603
91903
|
const task = await read.readTask(ws.task);
|
|
91604
91904
|
if (!task.ok) return task;
|
|
91605
91905
|
let files = { [WORKFLOW_FILE]: skeleton(task.value.title.trim() || "Untitled") };
|
|
91606
91906
|
const changes = task.value.context?.workflow;
|
|
91607
91907
|
if (changes) {
|
|
91608
|
-
const
|
|
91609
|
-
if (!
|
|
91610
|
-
files =
|
|
91908
|
+
const held4 = await read.readWorkflow(changes);
|
|
91909
|
+
if (!held4.ok) return held4;
|
|
91910
|
+
files = held4.value.files;
|
|
91611
91911
|
}
|
|
91612
91912
|
for (const [name, text3] of Object.entries(files)) {
|
|
91613
|
-
const file2 =
|
|
91614
|
-
if (!file2.startsWith(dir +
|
|
91615
|
-
|
|
91616
|
-
|
|
91913
|
+
const file2 = path27.resolve(dir, name);
|
|
91914
|
+
if (!file2.startsWith(dir + path27.sep)) continue;
|
|
91915
|
+
fs24.mkdirSync(path27.dirname(file2), { recursive: true });
|
|
91916
|
+
fs24.writeFileSync(file2, text3);
|
|
91617
91917
|
}
|
|
91618
91918
|
return { ok: true, value: void 0 };
|
|
91619
91919
|
}
|
|
@@ -91625,19 +91925,19 @@ async function builtWorkflow(ws, akb) {
|
|
|
91625
91925
|
const dir = draftDir(ws);
|
|
91626
91926
|
let source;
|
|
91627
91927
|
try {
|
|
91628
|
-
source =
|
|
91928
|
+
source = fs24.readFileSync(path27.join(dir, WORKFLOW_FILE), "utf8");
|
|
91629
91929
|
} catch {
|
|
91630
91930
|
return fail(`workflows/${id}/${WORKFLOW_FILE} is missing.`);
|
|
91631
91931
|
}
|
|
91632
91932
|
const read = parseWorkflowFile(id, source, `workflows/${id}/${WORKFLOW_FILE}`);
|
|
91633
91933
|
if ("problem" in read) return fail(read.problem);
|
|
91634
91934
|
const names2 = named(read.def);
|
|
91635
|
-
|
|
91935
|
+
fs24.rmSync(path27.join(dir, "agents"), { recursive: true, force: true });
|
|
91636
91936
|
for (const name of names2) {
|
|
91637
|
-
const from =
|
|
91638
|
-
if (
|
|
91937
|
+
const from = path27.join(ws.board, "agents", name);
|
|
91938
|
+
if (fs24.existsSync(from)) fs24.cpSync(from, path27.join(dir, "agents", name), { recursive: true });
|
|
91639
91939
|
}
|
|
91640
|
-
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2,
|
|
91940
|
+
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs24.readFileSync(path27.join(dir, f2), "utf8")]));
|
|
91641
91941
|
const checked = checkWorkflowFiles(files);
|
|
91642
91942
|
if (!checked.ok) return fail(`${checked.file} ${checked.reason}.`);
|
|
91643
91943
|
const run2 = async (args) => answerOf2(await runAkb(akb, [...args, "--json", "--board", ws.board], { cwd: ws.cwd, board: ws.board }));
|
|
@@ -91653,10 +91953,10 @@ async function builtWorkflow(ws, akb) {
|
|
|
91653
91953
|
}
|
|
91654
91954
|
|
|
91655
91955
|
// src/flow.ts
|
|
91656
|
-
function unavailable(
|
|
91657
|
-
const report2 = reports.find((r2) => r2.name ===
|
|
91658
|
-
if (!report2?.installed) return `${LABELS[
|
|
91659
|
-
if (report2.loggedIn === false) return `${LABELS[
|
|
91956
|
+
function unavailable(wanted2, reports) {
|
|
91957
|
+
const report2 = reports.find((r2) => r2.name === wanted2);
|
|
91958
|
+
if (!report2?.installed) return `${LABELS[wanted2]} is not installed on this computer.`;
|
|
91959
|
+
if (report2.loggedIn === false) return `${LABELS[wanted2]} is not signed in on this computer.`;
|
|
91660
91960
|
return null;
|
|
91661
91961
|
}
|
|
91662
91962
|
function spentBy(runs) {
|
|
@@ -91670,11 +91970,10 @@ function spentBy(runs) {
|
|
|
91670
91970
|
...context ? { context: { used: context.used, limit: context.limit } } : {}
|
|
91671
91971
|
};
|
|
91672
91972
|
}
|
|
91673
|
-
var SETUP_STEPS = ["project", "agent", "decisions", "modules", "tasks"];
|
|
91674
91973
|
function reviewOf(file2) {
|
|
91675
91974
|
let text3;
|
|
91676
91975
|
try {
|
|
91677
|
-
text3 =
|
|
91976
|
+
text3 = fs25.readFileSync(file2, "utf8");
|
|
91678
91977
|
} catch {
|
|
91679
91978
|
return void 0;
|
|
91680
91979
|
}
|
|
@@ -91688,8 +91987,8 @@ function reviewOf(file2) {
|
|
|
91688
91987
|
}
|
|
91689
91988
|
function mcpConfig(servers, file2) {
|
|
91690
91989
|
if (!Object.keys(servers).length) return null;
|
|
91691
|
-
|
|
91692
|
-
|
|
91990
|
+
fs25.mkdirSync(path28.dirname(file2), { recursive: true });
|
|
91991
|
+
fs25.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
|
|
91693
91992
|
`);
|
|
91694
91993
|
return file2;
|
|
91695
91994
|
}
|
|
@@ -91722,31 +92021,31 @@ async function stopLeftBehind(akb, ws, id, ms2) {
|
|
|
91722
92021
|
}
|
|
91723
92022
|
function deliveryEnding(ws, id) {
|
|
91724
92023
|
if (!id) return null;
|
|
91725
|
-
let
|
|
92024
|
+
let held4;
|
|
91726
92025
|
try {
|
|
91727
|
-
|
|
92026
|
+
held4 = JSON.parse(fs25.readFileSync(path28.join(ws.board, "deliveries", `${path28.basename(id)}.json`), "utf8"));
|
|
91728
92027
|
} catch {
|
|
91729
92028
|
return null;
|
|
91730
92029
|
}
|
|
91731
|
-
const stopped2 =
|
|
91732
|
-
if (
|
|
91733
|
-
return
|
|
92030
|
+
const stopped2 = held4.review?.stopped;
|
|
92031
|
+
if (held4.status === "cancelled") {
|
|
92032
|
+
return held4.steps?.some((s) => s.step === "discarded") ? { ok: false, reason: "The build was discarded." } : { ok: false, reason: "", stopped: true };
|
|
91734
92033
|
}
|
|
91735
|
-
if (
|
|
92034
|
+
if (held4.status === "active" && stopped2?.reason === "landing") return { ok: false, reason: firstLine(stopped2.why) ?? "The build could not land." };
|
|
91736
92035
|
return null;
|
|
91737
92036
|
}
|
|
91738
92037
|
function checkoutsOf(ws, id) {
|
|
91739
|
-
const dir =
|
|
92038
|
+
const dir = path28.join(ws.board, "deliveries");
|
|
91740
92039
|
let names2;
|
|
91741
92040
|
try {
|
|
91742
|
-
names2 =
|
|
92041
|
+
names2 = fs25.readdirSync(dir).filter((n) => n.endsWith(".json"));
|
|
91743
92042
|
} catch {
|
|
91744
92043
|
return [];
|
|
91745
92044
|
}
|
|
91746
92045
|
return names2.flatMap((n) => {
|
|
91747
92046
|
try {
|
|
91748
|
-
const
|
|
91749
|
-
return
|
|
92047
|
+
const held4 = JSON.parse(fs25.readFileSync(path28.join(dir, n), "utf8"));
|
|
92048
|
+
return held4.cardId === id && held4.worktree && held4.deliveryId ? [held4.deliveryId] : [];
|
|
91750
92049
|
} catch {
|
|
91751
92050
|
return [];
|
|
91752
92051
|
}
|
|
@@ -91755,7 +92054,7 @@ function checkoutsOf(ws, id) {
|
|
|
91755
92054
|
var refusal2 = (ran) => ran.last.replace(/^akb( raw)?: /, "").slice(0, 300) || "akb stopped with an error.";
|
|
91756
92055
|
var firstLine = (text3) => (text3 ?? "").split("\n").map((l2) => l2.trim()).find(Boolean)?.slice(0, 300);
|
|
91757
92056
|
function logLines(show, event2) {
|
|
91758
|
-
let
|
|
92057
|
+
let held4 = "";
|
|
91759
92058
|
const said = (line) => {
|
|
91760
92059
|
if (line.startsWith('{"kind":')) {
|
|
91761
92060
|
let parsed;
|
|
@@ -91781,15 +92080,15 @@ function logLines(show, event2) {
|
|
|
91781
92080
|
};
|
|
91782
92081
|
return {
|
|
91783
92082
|
push: (chunk) => {
|
|
91784
|
-
const lines = (
|
|
91785
|
-
|
|
92083
|
+
const lines = (held4 + chunk).split("\n");
|
|
92084
|
+
held4 = lines.pop();
|
|
91786
92085
|
for (const line of lines) {
|
|
91787
92086
|
const out = said(line);
|
|
91788
92087
|
if (out) show(out);
|
|
91789
92088
|
}
|
|
91790
92089
|
},
|
|
91791
92090
|
end: () => {
|
|
91792
|
-
const out =
|
|
92091
|
+
const out = held4 ? said(held4) : "";
|
|
91793
92092
|
if (out) show(out);
|
|
91794
92093
|
}
|
|
91795
92094
|
};
|
|
@@ -91804,17 +92103,24 @@ function boardAkb(job, ws, deps, io, task) {
|
|
|
91804
92103
|
return ran;
|
|
91805
92104
|
};
|
|
91806
92105
|
}
|
|
92106
|
+
function skillStale(dir, version) {
|
|
92107
|
+
try {
|
|
92108
|
+
const text3 = fs25.readFileSync(path28.join(dir, "SKILL.md"), "utf8");
|
|
92109
|
+
return !fs25.lstatSync(dir).isSymbolicLink() && /<!-- ai4kanban (\S+) -->\s*$/.exec(text3)?.[1] !== version;
|
|
92110
|
+
} catch {
|
|
92111
|
+
return true;
|
|
92112
|
+
}
|
|
92113
|
+
}
|
|
91807
92114
|
async function setUp(job, ws, deps, io) {
|
|
91808
92115
|
const akb = boardAkb(job, ws, deps, io);
|
|
91809
92116
|
const runtime = job.runtime;
|
|
91810
92117
|
const missing = unavailable(runtime, await deps.runtimes());
|
|
91811
92118
|
if (missing) return missing;
|
|
91812
|
-
if (!
|
|
92119
|
+
if (!fs25.existsSync(path28.join(ws.board, "config.md"))) {
|
|
91813
92120
|
const init = await akb(["raw", "init"]);
|
|
91814
92121
|
if (init.code !== 0) return refusal2(init);
|
|
91815
|
-
for (const step of SETUP_STEPS) await akb(["raw", "setup-done", step]);
|
|
91816
92122
|
}
|
|
91817
|
-
if (SKILL_FOLDERS.some((f2) =>
|
|
92123
|
+
if (SKILL_FOLDERS.some((f2) => skillStale(path28.join(ws.cwd, f2), deps.akb.version))) {
|
|
91818
92124
|
const skill = await runAkb(deps.akb, ["skill", "install", "--dir", ws.cwd], { cwd: ws.cwd, track: io.track });
|
|
91819
92125
|
if (skill.code !== 0) return refusal2(skill);
|
|
91820
92126
|
}
|
|
@@ -91823,7 +92129,7 @@ async function setUp(job, ws, deps, io) {
|
|
|
91823
92129
|
const used = await akb(["agent", "use", runtime]);
|
|
91824
92130
|
if (used.code !== 0) return refusal2(used);
|
|
91825
92131
|
const servers = mcpServersOf(ws);
|
|
91826
|
-
const mcpFile =
|
|
92132
|
+
const mcpFile = path28.join(ws.board, ".sync", `${ws.task}.mcp.json`);
|
|
91827
92133
|
const takes = new Set(settingKeys(runtime));
|
|
91828
92134
|
const given = job.settings ?? {};
|
|
91829
92135
|
const values = { ...given, model: job.model ?? "" };
|
|
@@ -91913,19 +92219,19 @@ async function runAgent(job, ws, deps, io) {
|
|
|
91913
92219
|
}
|
|
91914
92220
|
function writeTranscript(job, dir) {
|
|
91915
92221
|
if (!job.transcript) return "";
|
|
91916
|
-
const file2 =
|
|
91917
|
-
|
|
91918
|
-
|
|
92222
|
+
const file2 = path28.join(dir, "discussion.md");
|
|
92223
|
+
fs25.mkdirSync(dir, { recursive: true });
|
|
92224
|
+
fs25.writeFileSync(file2, `${job.transcript}
|
|
91919
92225
|
`);
|
|
91920
92226
|
return file2;
|
|
91921
92227
|
}
|
|
91922
92228
|
function pictures(job, ws, id) {
|
|
91923
92229
|
const dir = cardAssetsDir(ws, id);
|
|
91924
92230
|
if (!job.attachments.length || !dir) return "";
|
|
91925
|
-
|
|
92231
|
+
fs25.mkdirSync(dir, { recursive: true });
|
|
91926
92232
|
return job.attachments.map((a3, i) => {
|
|
91927
|
-
const file2 = `${i + 1}-${
|
|
91928
|
-
|
|
92233
|
+
const file2 = `${i + 1}-${path28.basename(a3.name).replace(/[^\w.-]+/g, "-")}`;
|
|
92234
|
+
fs25.writeFileSync(path28.join(dir, file2), Buffer.from(a3.content, "base64"));
|
|
91929
92235
|
return `
|
|
91930
92236
|
<Asset src=".assets/${id}/${file2}" label="${a3.name.replace(/["<>]/g, "") || file2}" />
|
|
91931
92237
|
`;
|
|
@@ -91933,11 +92239,10 @@ function pictures(job, ws, id) {
|
|
|
91933
92239
|
}
|
|
91934
92240
|
function cardFlags(ws, fields) {
|
|
91935
92241
|
if (!fields) return [];
|
|
91936
|
-
const open = (keys) => (keys ?? []).map((k) => Number(/(\d+)$/.exec(k)?.[1])).filter((n) => n > 0 && n !== ws.number && findCard(ws.board, n)?.startsWith(
|
|
92242
|
+
const open = (keys) => (keys ?? []).map((k) => Number(/(\d+)$/.exec(k)?.[1])).filter((n) => n > 0 && n !== ws.number && findCard(ws.board, n)?.startsWith(path28.join(ws.board, "todo") + path28.sep));
|
|
91937
92243
|
const lists = [["--modules", fields.modules ?? []], ["--related", open(fields.related)], ["--blocked-by", open(fields.blocked_by)]];
|
|
91938
92244
|
return [
|
|
91939
92245
|
...fields.priority ? ["--priority", fields.priority] : [],
|
|
91940
|
-
...fields.roi ? ["--roi", fields.roi] : [],
|
|
91941
92246
|
...lists.flatMap(([flag, list]) => list.length ? [flag, list.join(",")] : [])
|
|
91942
92247
|
];
|
|
91943
92248
|
}
|
|
@@ -91968,10 +92273,10 @@ async function runFlow(job, ws, deps, io) {
|
|
|
91968
92273
|
const placed = await placeDraft(ws, deps.api);
|
|
91969
92274
|
if (!placed.ok) return fail(placed.error);
|
|
91970
92275
|
}
|
|
91971
|
-
const body =
|
|
91972
|
-
|
|
92276
|
+
const body = path28.join(ws.board, ".sync", `${ws.task}.request.md`);
|
|
92277
|
+
fs25.mkdirSync(path28.dirname(body), { recursive: true });
|
|
91973
92278
|
if (!ws.number) return fail("This task has no number yet.");
|
|
91974
|
-
|
|
92279
|
+
fs25.writeFileSync(body, `${said.request || title}
|
|
91975
92280
|
${isBuilder(ws) ? `
|
|
91976
92281
|
${draftLine(ws)}
|
|
91977
92282
|
` : ""}${pictures(job, ws, ws.number)}`);
|
|
@@ -91989,21 +92294,21 @@ ${draftLine(ws)}
|
|
|
91989
92294
|
...cardFlags(ws, flow.metadata),
|
|
91990
92295
|
"--json"
|
|
91991
92296
|
]));
|
|
91992
|
-
|
|
92297
|
+
fs25.rmSync(body, { force: true });
|
|
91993
92298
|
if (!created.ok) return fail(created.error);
|
|
91994
92299
|
id = created.value;
|
|
91995
92300
|
}
|
|
91996
92301
|
if (!id) return fail("This task has no card on this computer.");
|
|
91997
92302
|
const card = id;
|
|
91998
92303
|
const key = workKey(ws, card);
|
|
91999
|
-
const
|
|
92000
|
-
working.set(key,
|
|
92304
|
+
const held4 = working.get(key) ?? 0;
|
|
92305
|
+
working.set(key, held4 + 1);
|
|
92001
92306
|
try {
|
|
92002
|
-
if (!
|
|
92307
|
+
if (!held4) await stopRuns(deps.akb, ws, card, 0, deps.stopMs);
|
|
92003
92308
|
if (io.lost()) return fail("");
|
|
92004
92309
|
return await workOn(card);
|
|
92005
92310
|
} finally {
|
|
92006
|
-
|
|
92311
|
+
fs25.rmSync(path28.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
|
|
92007
92312
|
const left = working.get(key) - 1;
|
|
92008
92313
|
if (left) working.set(key, left);
|
|
92009
92314
|
else working.delete(key);
|
|
@@ -92056,7 +92361,7 @@ ${draftLine(ws)}
|
|
|
92056
92361
|
}
|
|
92057
92362
|
function carryArgs(verb) {
|
|
92058
92363
|
if (!["refine", "resolve", "revise"].includes(verb)) return [];
|
|
92059
|
-
const transcript = writeTranscript(job,
|
|
92364
|
+
const transcript = writeTranscript(job, path28.join(ws.board, ".sync", `${ws.task}.discussion`));
|
|
92060
92365
|
return [
|
|
92061
92366
|
...job.resume ? ["--session", job.resume, ...job.fork ? ["--fork"] : []] : [],
|
|
92062
92367
|
...transcript ? ["--transcript", transcript] : []
|
|
@@ -92065,17 +92370,17 @@ ${draftLine(ws)}
|
|
|
92065
92370
|
}
|
|
92066
92371
|
|
|
92067
92372
|
// src/lock.ts
|
|
92068
|
-
import
|
|
92069
|
-
import
|
|
92373
|
+
import crypto4 from "node:crypto";
|
|
92374
|
+
import fs26 from "node:fs";
|
|
92070
92375
|
import net from "node:net";
|
|
92071
|
-
import
|
|
92376
|
+
import path29 from "node:path";
|
|
92072
92377
|
var RETRY_MS = 5e3;
|
|
92073
92378
|
var KIND_MS = 1e3;
|
|
92074
92379
|
var HOLDERS = ["claude-code", "codex", "terminal", "desktop"];
|
|
92075
92380
|
function lockPath() {
|
|
92076
92381
|
const home4 = runnerHome();
|
|
92077
|
-
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${
|
|
92078
|
-
return
|
|
92382
|
+
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${crypto4.createHash("sha256").update(home4).digest("hex").slice(0, 16)}`;
|
|
92383
|
+
return path29.join(home4, "runner.sock");
|
|
92079
92384
|
}
|
|
92080
92385
|
function holdMachine(kind, onHeld, onWaiting) {
|
|
92081
92386
|
const where = lockPath();
|
|
@@ -92090,7 +92395,7 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92090
92395
|
const attempt = () => {
|
|
92091
92396
|
timer = null;
|
|
92092
92397
|
if (closed) return;
|
|
92093
|
-
if (process.platform !== "win32")
|
|
92398
|
+
if (process.platform !== "win32") fs26.mkdirSync(path29.dirname(where), { recursive: true, mode: 448 });
|
|
92094
92399
|
const s = net.createServer((peer) => {
|
|
92095
92400
|
peers.add(peer);
|
|
92096
92401
|
peer.on("error", () => {
|
|
@@ -92138,7 +92443,7 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92138
92443
|
later(0);
|
|
92139
92444
|
});
|
|
92140
92445
|
removeIfStill.once("error", () => {
|
|
92141
|
-
|
|
92446
|
+
fs26.rmSync(where, { force: true });
|
|
92142
92447
|
later(50 + Math.random() * 200);
|
|
92143
92448
|
});
|
|
92144
92449
|
return;
|
|
@@ -92167,13 +92472,117 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92167
92472
|
|
|
92168
92473
|
// src/jobs.ts
|
|
92169
92474
|
import { spawn as spawn4 } from "node:child_process";
|
|
92170
|
-
import
|
|
92171
|
-
import
|
|
92475
|
+
import fs29 from "node:fs";
|
|
92476
|
+
import path32 from "node:path";
|
|
92477
|
+
|
|
92478
|
+
// ../cli/src/lib/agent/catalog.ts
|
|
92479
|
+
import fs27 from "node:fs";
|
|
92480
|
+
import path30 from "node:path";
|
|
92481
|
+
var CATALOGUE = "https://models.dev/api.json";
|
|
92482
|
+
var FRESH_FOR_MS = 24 * 60 * 6e4;
|
|
92483
|
+
var ANSWER_BY_MS = 2e4;
|
|
92484
|
+
function cacheFile() {
|
|
92485
|
+
return path30.join(machineHome(), "models-dev.json");
|
|
92486
|
+
}
|
|
92487
|
+
var held2;
|
|
92488
|
+
function readCache() {
|
|
92489
|
+
const file2 = cacheFile();
|
|
92490
|
+
let stamp2;
|
|
92491
|
+
try {
|
|
92492
|
+
const stat = fs27.statSync(file2);
|
|
92493
|
+
stamp2 = `${stat.mtimeMs}:${stat.size}`;
|
|
92494
|
+
} catch {
|
|
92495
|
+
return void 0;
|
|
92496
|
+
}
|
|
92497
|
+
if (held2?.stamp === stamp2) return held2.cached;
|
|
92498
|
+
try {
|
|
92499
|
+
const data = JSON.parse(fs27.readFileSync(file2, "utf8"));
|
|
92500
|
+
if (!data || typeof data.limits !== "object" || !data.limits) return void 0;
|
|
92501
|
+
const cached2 = {
|
|
92502
|
+
fetchedAt: typeof data.fetchedAt === "number" ? data.fetchedAt : 0,
|
|
92503
|
+
limits: data.limits
|
|
92504
|
+
};
|
|
92505
|
+
held2 = { stamp: stamp2, cached: cached2 };
|
|
92506
|
+
return cached2;
|
|
92507
|
+
} catch {
|
|
92508
|
+
return void 0;
|
|
92509
|
+
}
|
|
92510
|
+
}
|
|
92511
|
+
function limitsIn(data) {
|
|
92512
|
+
const limits = {};
|
|
92513
|
+
if (!data || typeof data !== "object") return limits;
|
|
92514
|
+
for (const [provider, raw] of Object.entries(data)) {
|
|
92515
|
+
const models = raw?.models;
|
|
92516
|
+
if (!models || typeof models !== "object") continue;
|
|
92517
|
+
for (const [model, entry] of Object.entries(models)) {
|
|
92518
|
+
const context = entry?.limit?.context;
|
|
92519
|
+
if (typeof context === "number" && Number.isFinite(context) && context > 0) {
|
|
92520
|
+
limits[`${provider}/${model}`] = context;
|
|
92521
|
+
}
|
|
92522
|
+
}
|
|
92523
|
+
}
|
|
92524
|
+
return limits;
|
|
92525
|
+
}
|
|
92526
|
+
var fetching2;
|
|
92527
|
+
function refreshCatalog() {
|
|
92528
|
+
if (fetching2) return fetching2;
|
|
92529
|
+
const cached2 = readCache();
|
|
92530
|
+
if (cached2 && Date.now() - cached2.fetchedAt < FRESH_FOR_MS) return Promise.resolve();
|
|
92531
|
+
fetching2 = (async () => {
|
|
92532
|
+
try {
|
|
92533
|
+
const answer = await fetch(CATALOGUE, { signal: AbortSignal.timeout(ANSWER_BY_MS) });
|
|
92534
|
+
if (!answer.ok) return;
|
|
92535
|
+
const limits = limitsIn(await answer.json());
|
|
92536
|
+
if (Object.keys(limits).length === 0) return;
|
|
92537
|
+
const file2 = cacheFile();
|
|
92538
|
+
fs27.mkdirSync(path30.dirname(file2), { recursive: true });
|
|
92539
|
+
fs27.writeFileSync(file2, JSON.stringify({ fetchedAt: Date.now(), limits }));
|
|
92540
|
+
} catch {
|
|
92541
|
+
}
|
|
92542
|
+
})();
|
|
92543
|
+
return fetching2;
|
|
92544
|
+
}
|
|
92545
|
+
var PROVIDERS = {
|
|
92546
|
+
"claude-code": ["anthropic"],
|
|
92547
|
+
zcode: ["zai", "zhipuai"],
|
|
92548
|
+
kimi: ["moonshotai", "moonshotai-cn"],
|
|
92549
|
+
opencode: ["opencode"]
|
|
92550
|
+
};
|
|
92551
|
+
function spellings(model) {
|
|
92552
|
+
const id = model.trim().toLowerCase();
|
|
92553
|
+
if (!id) return [];
|
|
92554
|
+
const undated = id.replace(/-\d{8}$/, "");
|
|
92555
|
+
return [.../* @__PURE__ */ new Set([id, undated])];
|
|
92556
|
+
}
|
|
92557
|
+
function contextLimit(harness, model) {
|
|
92558
|
+
if (!model?.trim()) return void 0;
|
|
92559
|
+
const limits = readCache()?.limits;
|
|
92560
|
+
if (!limits) return void 0;
|
|
92561
|
+
const cut2 = model.lastIndexOf("/");
|
|
92562
|
+
if (cut2 > 0) {
|
|
92563
|
+
const whole = model.trim().toLowerCase();
|
|
92564
|
+
if (limits[whole]) return limits[whole];
|
|
92565
|
+
}
|
|
92566
|
+
const bare = cut2 > 0 ? model.slice(cut2 + 1) : model;
|
|
92567
|
+
const ids = spellings(bare);
|
|
92568
|
+
for (const provider of PROVIDERS[harness] ?? []) {
|
|
92569
|
+
for (const id of ids) {
|
|
92570
|
+
const found = limits[`${provider}/${id}`];
|
|
92571
|
+
if (found) return found;
|
|
92572
|
+
}
|
|
92573
|
+
}
|
|
92574
|
+
let widest = 0;
|
|
92575
|
+
for (const [key, limit] of Object.entries(limits)) {
|
|
92576
|
+
const id = key.slice(key.indexOf("/") + 1);
|
|
92577
|
+
if (ids.includes(id) && limit > widest) widest = limit;
|
|
92578
|
+
}
|
|
92579
|
+
return widest || void 0;
|
|
92580
|
+
}
|
|
92172
92581
|
|
|
92173
92582
|
// src/ideas.ts
|
|
92174
|
-
import
|
|
92175
|
-
import
|
|
92176
|
-
var ideasFileOf = (job) =>
|
|
92583
|
+
import fs28 from "node:fs";
|
|
92584
|
+
import path31 from "node:path";
|
|
92585
|
+
var ideasFileOf = (job) => path31.join(runnerHome(), "ideas", `${job.id}.json`);
|
|
92177
92586
|
async function writeIdeas(job, list) {
|
|
92178
92587
|
const workflows = [];
|
|
92179
92588
|
let after = null;
|
|
@@ -92184,24 +92593,23 @@ async function writeIdeas(job, list) {
|
|
|
92184
92593
|
after = page.value.next;
|
|
92185
92594
|
} while (after);
|
|
92186
92595
|
const file2 = ideasFileOf(job);
|
|
92187
|
-
|
|
92188
|
-
|
|
92596
|
+
fs28.mkdirSync(path31.dirname(file2), { recursive: true });
|
|
92597
|
+
fs28.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: job.discussion.ideas }, null, 2)}
|
|
92189
92598
|
`);
|
|
92190
92599
|
return { file: file2 };
|
|
92191
92600
|
}
|
|
92192
92601
|
function readIdeas(file2) {
|
|
92193
92602
|
try {
|
|
92194
|
-
return JSON.parse(
|
|
92603
|
+
return JSON.parse(fs28.readFileSync(file2, "utf8")).ideas;
|
|
92195
92604
|
} catch {
|
|
92196
92605
|
return void 0;
|
|
92197
92606
|
} finally {
|
|
92198
|
-
|
|
92607
|
+
fs28.rmSync(file2, { force: true });
|
|
92199
92608
|
}
|
|
92200
92609
|
}
|
|
92201
92610
|
|
|
92202
92611
|
// src/jobs.ts
|
|
92203
|
-
var
|
|
92204
|
-
var QUIET_MS = 15e3;
|
|
92612
|
+
var FLUSH_MS = 2e3;
|
|
92205
92613
|
var FLUSH_CHARS = 32 * 1024;
|
|
92206
92614
|
var BATCH_EVENTS = 500;
|
|
92207
92615
|
var BATCH_CHARS = 512 * 1024;
|
|
@@ -92209,6 +92617,7 @@ var EVENT_CHARS = 64 * 1024;
|
|
|
92209
92617
|
var END_MS = 1e4;
|
|
92210
92618
|
var RECONNECT_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
92211
92619
|
var RENEW_MS = 5 * 6e4;
|
|
92620
|
+
var LOG_PING_MS = 3e4;
|
|
92212
92621
|
var LEASE_MS = 15 * 6e4;
|
|
92213
92622
|
var RETRY_MS2 = 3e4;
|
|
92214
92623
|
var KILL_GRACE_MS = 5e3;
|
|
@@ -92219,7 +92628,8 @@ var defaultDeps = (machineId2) => ({
|
|
|
92219
92628
|
machineId: machineId2,
|
|
92220
92629
|
api: api_exports,
|
|
92221
92630
|
plan,
|
|
92222
|
-
flushMs:
|
|
92631
|
+
flushMs: FLUSH_MS,
|
|
92632
|
+
logPingMs: LOG_PING_MS,
|
|
92223
92633
|
endMs: END_MS,
|
|
92224
92634
|
renewMs: RENEW_MS,
|
|
92225
92635
|
leaseMs: LEASE_MS,
|
|
@@ -92227,35 +92637,35 @@ var defaultDeps = (machineId2) => ({
|
|
|
92227
92637
|
testMs: TEST_MS,
|
|
92228
92638
|
stopMs: STOP_MS,
|
|
92229
92639
|
watchMs: WATCH_MS,
|
|
92230
|
-
akb:
|
|
92640
|
+
akb: currentAkb,
|
|
92231
92641
|
runtimes: detectRuntimes
|
|
92232
92642
|
});
|
|
92233
|
-
var ownFolder = () =>
|
|
92643
|
+
var ownFolder = () => path32.join(runnerHome(), "work");
|
|
92234
92644
|
function folderFor(job) {
|
|
92235
92645
|
if (!job.projectDir) {
|
|
92236
|
-
const cwd =
|
|
92237
|
-
|
|
92646
|
+
const cwd = path32.join(ownFolder(), job.id);
|
|
92647
|
+
fs29.mkdirSync(cwd, { recursive: true });
|
|
92238
92648
|
return { cwd };
|
|
92239
92649
|
}
|
|
92240
92650
|
const real = realpath4(job.projectDir);
|
|
92241
|
-
if (real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
92651
|
+
if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path32.sep))) return { cwd: real };
|
|
92242
92652
|
return { refused: `This Runner is not allowed to work in ${job.projectDir}.` };
|
|
92243
92653
|
}
|
|
92244
92654
|
function realpath4(p2) {
|
|
92245
92655
|
try {
|
|
92246
|
-
return
|
|
92656
|
+
return fs29.realpathSync(p2);
|
|
92247
92657
|
} catch {
|
|
92248
92658
|
return null;
|
|
92249
92659
|
}
|
|
92250
92660
|
}
|
|
92251
|
-
var attachmentsOf = (job) =>
|
|
92661
|
+
var attachmentsOf = (job) => path32.join(runnerHome(), "attachments", job.id);
|
|
92252
92662
|
function writeAttachments(job) {
|
|
92253
92663
|
if (!job.attachments.length) return "";
|
|
92254
92664
|
const dir = attachmentsOf(job);
|
|
92255
|
-
|
|
92665
|
+
fs29.mkdirSync(dir, { recursive: true });
|
|
92256
92666
|
const files = job.attachments.map((a3) => {
|
|
92257
|
-
const file2 =
|
|
92258
|
-
|
|
92667
|
+
const file2 = path32.join(dir, path32.basename(a3.name));
|
|
92668
|
+
fs29.writeFileSync(file2, Buffer.from(a3.content, "base64"));
|
|
92259
92669
|
return file2;
|
|
92260
92670
|
});
|
|
92261
92671
|
return `
|
|
@@ -92292,7 +92702,7 @@ function streamOut(deps, id, lease) {
|
|
|
92292
92702
|
let ending = false;
|
|
92293
92703
|
let closed = false;
|
|
92294
92704
|
let flushedAt = Date.now();
|
|
92295
|
-
const log = { ws: null, after: null, watched: false, tries: 0, retry: void 0 };
|
|
92705
|
+
const log = { ws: null, after: null, watched: false, heard: 0, tries: 0, retry: void 0 };
|
|
92296
92706
|
let ended2 = () => {
|
|
92297
92707
|
};
|
|
92298
92708
|
const stored = new Promise((resolve2) => ended2 = resolve2);
|
|
@@ -92326,7 +92736,7 @@ function streamOut(deps, id, lease) {
|
|
|
92326
92736
|
const ws = log.ws;
|
|
92327
92737
|
if (!ws || ws.readyState !== WebSocket.OPEN || log.after === null) return;
|
|
92328
92738
|
const after = log.after;
|
|
92329
|
-
const unsent2 = wire.filter((e2) => e2.seq > after);
|
|
92739
|
+
const unsent2 = log.watched ? wire.filter((e2) => e2.seq > after) : [];
|
|
92330
92740
|
let batch = [];
|
|
92331
92741
|
let chars = 0;
|
|
92332
92742
|
const out = () => {
|
|
@@ -92357,7 +92767,9 @@ function streamOut(deps, id, lease) {
|
|
|
92357
92767
|
if (closed) return ws?.close();
|
|
92358
92768
|
if (!ws) return reconnect();
|
|
92359
92769
|
log.ws = ws;
|
|
92770
|
+
log.heard = Date.now();
|
|
92360
92771
|
ws.addEventListener("message", (m) => {
|
|
92772
|
+
log.heard = Date.now();
|
|
92361
92773
|
let said;
|
|
92362
92774
|
try {
|
|
92363
92775
|
said = JSON.parse(String(m.data));
|
|
@@ -92368,22 +92780,23 @@ function streamOut(deps, id, lease) {
|
|
|
92368
92780
|
log.tries = 0;
|
|
92369
92781
|
log.after = Number.isInteger(said.after) ? said.after : -1;
|
|
92370
92782
|
log.watched = said.watched === true;
|
|
92371
|
-
|
|
92783
|
+
flush();
|
|
92372
92784
|
} else if (said.type === "watched") {
|
|
92373
92785
|
log.watched = said.on === true;
|
|
92374
92786
|
if (log.watched) flush();
|
|
92375
92787
|
} else if (said.type === "ended") ended2();
|
|
92376
92788
|
else if (said.type === "stop") ask();
|
|
92377
92789
|
});
|
|
92378
|
-
ws.addEventListener("close", () =>
|
|
92379
|
-
if (log.ws !== ws) return;
|
|
92380
|
-
log.ws = null;
|
|
92381
|
-
log.after = null;
|
|
92382
|
-
reconnect();
|
|
92383
|
-
});
|
|
92790
|
+
ws.addEventListener("close", () => drop(ws));
|
|
92384
92791
|
ws.addEventListener("error", () => {
|
|
92385
92792
|
});
|
|
92386
92793
|
};
|
|
92794
|
+
const drop = (ws) => {
|
|
92795
|
+
if (log.ws !== ws) return;
|
|
92796
|
+
log.ws = null;
|
|
92797
|
+
log.after = null;
|
|
92798
|
+
reconnect();
|
|
92799
|
+
};
|
|
92387
92800
|
const reconnect = () => {
|
|
92388
92801
|
if (log.retry || lost || closed) return;
|
|
92389
92802
|
log.retry = setTimeout(() => void connect2(), RECONNECT_MS[Math.min(log.tries++, RECONNECT_MS.length - 1)]);
|
|
@@ -92393,12 +92806,18 @@ function streamOut(deps, id, lease) {
|
|
|
92393
92806
|
if (e2.kind === "message") messages.push(e2.data.text);
|
|
92394
92807
|
pending.push(e2);
|
|
92395
92808
|
size += JSON.stringify(e2.data).length;
|
|
92396
|
-
if (size >= FLUSH_CHARS) flush();
|
|
92809
|
+
if (log.watched && size >= FLUSH_CHARS) flush();
|
|
92397
92810
|
};
|
|
92398
|
-
const tick = Math.min(deps.flushMs.watched, 1e3);
|
|
92399
92811
|
const flusher = setInterval(() => {
|
|
92400
|
-
if (pending.length && Date.now() - flushedAt >=
|
|
92401
|
-
},
|
|
92812
|
+
if (log.watched && pending.length && Date.now() - flushedAt >= deps.flushMs) flush();
|
|
92813
|
+
}, Math.min(deps.flushMs, 1e3));
|
|
92814
|
+
const pinger = setInterval(() => {
|
|
92815
|
+
const ws = log.ws;
|
|
92816
|
+
if (ws?.readyState !== WebSocket.OPEN) return;
|
|
92817
|
+
if (Date.now() - log.heard <= deps.logPingMs * 2) return ws.send("ping");
|
|
92818
|
+
drop(ws);
|
|
92819
|
+
ws.close();
|
|
92820
|
+
}, deps.logPingMs);
|
|
92402
92821
|
const renewer = setInterval(async () => {
|
|
92403
92822
|
const renewed = await deps.api.renewJob(deps.machineId, id);
|
|
92404
92823
|
if (renewed.ok && !renewed.value.renewed) return void loseLease();
|
|
@@ -92432,6 +92851,7 @@ function streamOut(deps, id, lease) {
|
|
|
92432
92851
|
/** The rest sent and the log stored, or given up on after a while: `finish` comes after. */
|
|
92433
92852
|
end: async () => {
|
|
92434
92853
|
clearInterval(flusher);
|
|
92854
|
+
clearInterval(pinger);
|
|
92435
92855
|
clearInterval(renewer);
|
|
92436
92856
|
ending = !lost;
|
|
92437
92857
|
flush();
|
|
@@ -92453,12 +92873,12 @@ async function runJob(id, deps, track = () => {
|
|
|
92453
92873
|
const claim = await deps.api.claimJob(deps.machineId, id);
|
|
92454
92874
|
if (!claim.ok || !claim.value.claimed) return;
|
|
92455
92875
|
const job = claim.value.job;
|
|
92456
|
-
const
|
|
92876
|
+
const held4 = [];
|
|
92457
92877
|
try {
|
|
92458
|
-
await runClaimed(job, deps, track, (dir) =>
|
|
92878
|
+
await runClaimed(job, { ...deps, akb: deps.akb() }, track, (dir) => held4.push(hold(dir)));
|
|
92459
92879
|
} finally {
|
|
92460
|
-
for (const release2 of
|
|
92461
|
-
|
|
92880
|
+
for (const release2 of held4) release2();
|
|
92881
|
+
fs29.rmSync(attachmentsOf(job), { recursive: true, force: true });
|
|
92462
92882
|
}
|
|
92463
92883
|
}
|
|
92464
92884
|
async function runClaimed(job, deps, track, keep2) {
|
|
@@ -92502,6 +92922,7 @@ async function runClaimed(job, deps, track, keep2) {
|
|
|
92502
92922
|
ideas = wrote.file;
|
|
92503
92923
|
}
|
|
92504
92924
|
if (!job.flow && !job.review) {
|
|
92925
|
+
void refreshCatalog();
|
|
92505
92926
|
const head2 = folderLines(ws) + writeAttachments(job);
|
|
92506
92927
|
const file2 = writeTranscript(job, attachmentsOf(job));
|
|
92507
92928
|
const transcript = file2 ? `
|
|
@@ -92538,6 +92959,7 @@ ${job.prompt}` : job.prompt;
|
|
|
92538
92959
|
for (const task2 of job.review.tasks) {
|
|
92539
92960
|
const chat = await deps.api.readChat(task2);
|
|
92540
92961
|
if (chat.ok) keepCloudChat(task2, chat.value.messages);
|
|
92962
|
+
await keepDecisions(task2, deps.api.readDecisions);
|
|
92541
92963
|
}
|
|
92542
92964
|
const listed2 = await deps.api.listChats(deps.machineId);
|
|
92543
92965
|
if (!listed2.ok) {
|
|
@@ -92583,7 +93005,7 @@ ${job.prompt}` : job.prompt;
|
|
|
92583
93005
|
await stream.end();
|
|
92584
93006
|
if (stream.lost()) return;
|
|
92585
93007
|
const ok = end.ok || stream.asked();
|
|
92586
|
-
const said2 = told(stream.asked() ? cutShort(report(plan3, end), stream.said()) : report(plan3, end));
|
|
93008
|
+
const said2 = told(stream.asked() ? cutShort(report(job, plan3, end), stream.said()) : report(job, plan3, end));
|
|
92587
93009
|
if (!ok || !ws) return finish(deps, id, lease, ok ? "done" : "failed", ok ? "" : end.error ?? "", said2);
|
|
92588
93010
|
return sendBack(deps, id, lease, ws, said2, () => keepChat(job, said2.reply));
|
|
92589
93011
|
}
|
|
@@ -92624,7 +93046,7 @@ ${job.prompt}` : job.prompt;
|
|
|
92624
93046
|
await stream.end();
|
|
92625
93047
|
if (stream.lost()) return;
|
|
92626
93048
|
const failure = stream.asked() ? void 0 : ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`);
|
|
92627
|
-
const said = told(stream.asked() ? cutShort(report(plan2), stream.said()) : report(plan2));
|
|
93049
|
+
const said = told(stream.asked() ? cutShort(report(job, plan2), stream.said()) : report(job, plan2));
|
|
92628
93050
|
if (failure || !ws) return finish(deps, id, lease, failure ? "failed" : "done", failure, said);
|
|
92629
93051
|
return sendBack(deps, id, lease, ws, said, () => keepChat(job, said.reply));
|
|
92630
93052
|
}
|
|
@@ -92655,11 +93077,11 @@ var stop = (child) => {
|
|
|
92655
93077
|
setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS).unref();
|
|
92656
93078
|
};
|
|
92657
93079
|
var wait2 = (ms2) => new Promise((resolve2) => setTimeout(resolve2, ms2));
|
|
92658
|
-
var
|
|
93080
|
+
var held3 = (deps, lease) => Date.now() - lease.at < deps.leaseMs;
|
|
92659
93081
|
async function whileOffline(deps, id, lease, attempt) {
|
|
92660
93082
|
for (; ; ) {
|
|
92661
93083
|
const out = await attempt();
|
|
92662
|
-
if (!("offline" in out && out.offline) || !
|
|
93084
|
+
if (!("offline" in out && out.offline) || !held3(deps, lease)) return out;
|
|
92663
93085
|
await wait2(deps.retryMs);
|
|
92664
93086
|
const renewed = await deps.api.renewJob(deps.machineId, id);
|
|
92665
93087
|
if (renewed.ok && renewed.value.renewed) lease.at = Date.now();
|
|
@@ -92706,8 +93128,8 @@ async function runTest(job, deps) {
|
|
|
92706
93128
|
const report2 = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
|
|
92707
93129
|
if (!report2?.installed) return finish2("failed", "not_installed");
|
|
92708
93130
|
if (report2.loggedIn === false) return finish2("failed", "signed_out");
|
|
92709
|
-
const cwd =
|
|
92710
|
-
|
|
93131
|
+
const cwd = path32.join(ownFolder(), "test");
|
|
93132
|
+
fs29.mkdirSync(cwd, { recursive: true });
|
|
92711
93133
|
const run2 = deps.plan(job.runtime, job.prompt, cwd, null, job.model, settingsOf(job));
|
|
92712
93134
|
const startedAt = Date.now();
|
|
92713
93135
|
if (run2.converse) {
|
|
@@ -92768,8 +93190,9 @@ async function runTest(job, deps) {
|
|
|
92768
93190
|
if (failure) return finish2("failed", failure.slice(0, 300), ms2);
|
|
92769
93191
|
return finish2("done", "", ms2);
|
|
92770
93192
|
}
|
|
92771
|
-
function report(run2, turn) {
|
|
93193
|
+
function report(job, run2, turn) {
|
|
92772
93194
|
const context = turn ? turn.context : run2.renderer?.context?.();
|
|
93195
|
+
const limit = context?.limit ?? contextLimit(job.runtime, run2.model?.() ?? job.model ?? void 0);
|
|
92773
93196
|
const usage = turn ? turn.usage : run2.renderer?.usage?.();
|
|
92774
93197
|
const costUsd = turn ? turn.costUsd : run2.renderer?.costUsd?.();
|
|
92775
93198
|
return {
|
|
@@ -92777,7 +93200,7 @@ function report(run2, turn) {
|
|
|
92777
93200
|
session: run2.session(),
|
|
92778
93201
|
...usage ? { usage } : {},
|
|
92779
93202
|
...costUsd !== void 0 ? { costUsd } : {},
|
|
92780
|
-
...context?.used !== void 0 &&
|
|
93203
|
+
...context?.used !== void 0 && limit ? { context: { used: context.used, limit } } : {}
|
|
92781
93204
|
};
|
|
92782
93205
|
}
|
|
92783
93206
|
var cutShort = (said, text3) => ({ ...said, reply: said.reply || text3 || void 0, stopped: true });
|
|
@@ -92878,10 +93301,15 @@ function startRunner(options) {
|
|
|
92878
93301
|
const base = options.deps ?? defaultDeps(registration.machineId);
|
|
92879
93302
|
return { ...base, runtimes: () => base.runtimes().then(redetected) };
|
|
92880
93303
|
};
|
|
93304
|
+
const register2 = async () => {
|
|
93305
|
+
const answer = await register(options.notify ? { ...registration, notify: options.notify() } : registration);
|
|
93306
|
+
if (answer.ok) void followAkb(answer.value.akb);
|
|
93307
|
+
return answer;
|
|
93308
|
+
};
|
|
92881
93309
|
const redetected = async (found) => {
|
|
92882
93310
|
if (closed || !registration || JSON.stringify(found) === JSON.stringify(registration.runtimes)) return found;
|
|
92883
93311
|
registration = { ...registration, runtimes: found };
|
|
92884
|
-
await
|
|
93312
|
+
await register2();
|
|
92885
93313
|
return found;
|
|
92886
93314
|
};
|
|
92887
93315
|
const idle2 = () => running.size ? t.running(running.size) : t.connected(registration.machineName);
|
|
@@ -92910,6 +93338,7 @@ function startRunner(options) {
|
|
|
92910
93338
|
if (sweeping || closed || !registration) return;
|
|
92911
93339
|
sweeping = true;
|
|
92912
93340
|
try {
|
|
93341
|
+
sweepAkb();
|
|
92913
93342
|
await sweepCache(registration.machineId);
|
|
92914
93343
|
} catch (e2) {
|
|
92915
93344
|
console.error(`runner: the cache was not cleaned: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -92934,12 +93363,12 @@ function startRunner(options) {
|
|
|
92934
93363
|
swept = true;
|
|
92935
93364
|
void sweep();
|
|
92936
93365
|
}
|
|
92937
|
-
const answer = await
|
|
93366
|
+
const answer = await register2();
|
|
92938
93367
|
if (closed) return;
|
|
92939
93368
|
if (!answer.ok) {
|
|
92940
93369
|
if (answer.code === "runner_elsewhere") {
|
|
92941
|
-
const
|
|
92942
|
-
return finish2({ reason: "elsewhere", machine:
|
|
93370
|
+
const held4 = await readRunner();
|
|
93371
|
+
return finish2({ reason: "elsewhere", machine: held4.ok && held4.value.runner?.machineName || "?" });
|
|
92943
93372
|
}
|
|
92944
93373
|
if (answer.code === "runner_outdated") return finish2({ reason: "outdated" });
|
|
92945
93374
|
if (answer.code) return finish2({ reason: "refused", message: answer.error });
|
|
@@ -93024,7 +93453,7 @@ function startRunner(options) {
|
|
|
93024
93453
|
if (folder && "refused" in folder) return;
|
|
93025
93454
|
const ws = openTaskFolder(job, folder?.cwd ?? null);
|
|
93026
93455
|
const card = akbCardOf(ws);
|
|
93027
|
-
if (card) await stopLeftBehind(deps().akb, ws, card, deps().stopMs);
|
|
93456
|
+
if (card) await stopLeftBehind(deps().akb(), ws, card, deps().stopMs);
|
|
93028
93457
|
} catch (e2) {
|
|
93029
93458
|
console.error(`runner: the runs left on job ${job.id}'s card were not stopped: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
93030
93459
|
}
|
|
@@ -93080,13 +93509,13 @@ function startRunner(options) {
|
|
|
93080
93509
|
|
|
93081
93510
|
// src/desktop.ts
|
|
93082
93511
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
93083
|
-
import
|
|
93084
|
-
import
|
|
93512
|
+
import fs30 from "node:fs";
|
|
93513
|
+
import path33 from "node:path";
|
|
93085
93514
|
import readline from "node:readline";
|
|
93086
93515
|
|
|
93087
93516
|
// src/signin.ts
|
|
93088
93517
|
import { spawn as spawn5 } from "node:child_process";
|
|
93089
|
-
import
|
|
93518
|
+
import crypto5 from "node:crypto";
|
|
93090
93519
|
import http from "node:http";
|
|
93091
93520
|
var WAIT_MS = 10 * 60 * 1e3;
|
|
93092
93521
|
var CRANE = "M2 55.75C2 55.69 2.69 55.09 3.55 54.37L5.09 53.1L6.61 53.1L8.13 53.1L12.49 49.87C14.9 48.07 16.83 46.58 16.77 46.53C16.75 46.47 15.56 46.64 14.15 46.89C12.74 47.13 11.55 47.3 11.53 47.24C11.47 47.19 12.02 46.22 12.71 45.06L14.01 42.96L18.21 41.34C20.53 40.45 22.41 39.65 22.41 39.57C22.41 39.49 21.27 38.55 19.92 37.5C15.92 34.4 13.13 31.31 10.86 27.47L10.01 26.01L10.53 26.18C10.84 26.26 12.96 27.2 15.28 28.25C17.6 29.32 19.53 30.12 19.59 30.07C19.64 30.01 17.68 28.69 15.25 27.11C12.8 25.57 10.56 23.97 10.31 23.58C9.15 21.95 7.25 17.5 7.25 16.46C7.25 16.26 10.01 17.95 13.38 20.18C16.77 22.45 19.73 24.38 19.95 24.49C20.42 24.74 20.25 24.57 13.9 19.02L9.18 14.88L8.6 13.36C7.72 10.96 6.97 7.54 6.97 5.77L6.97 4.14L9.4 6.46C12.66 9.61 15.56 12.01 23.57 18.25C27.32 21.18 30.5 23.72 30.64 23.91C30.8 24.08 31.68 26.51 32.6 29.3L34.28 34.35L35.72 35.65C37.54 37.3 37.98 37.47 36.85 36.09L35.96 35.01L37.12 34.71C39.11 34.21 40.16 33.52 42.54 31.12L44.8 28.8L46.02 28.96C46.71 29.07 47.56 29.07 47.95 28.96L48.67 28.8L48.67 28.25L48.67 27.69L49.27 27.69C49.63 27.69 50.1 27.58 50.32 27.42L50.71 27.17L51.01 27.42C51.18 27.56 52.78 27.86 54.58 28.08C56.37 28.3 57.86 28.52 57.94 28.58C58 28.63 56.73 28.85 55.13 29.05C53.53 29.24 50.96 29.77 49.44 30.21C47.92 30.65 46.57 31.01 46.43 31.01C46.29 31.01 44.22 32.97 41.85 35.37C37.57 39.62 34.42 42.14 30.83 44.15L29.14 45.09L25.97 45.73L22.77 46.39L14.59 51.11L6.42 55.86L4.21 55.86C2.99 55.86 2 55.8 2 55.75Z";
|
|
@@ -93111,8 +93540,8 @@ var PAGE = (outcome, lang) => {
|
|
|
93111
93540
|
return `<!doctype html><html lang="${lang === "zh" ? "zh-CN" : "en"}"><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${title} \xB7 WildCrane</title><style>*{margin:0;box-sizing:border-box}body{display:flex;flex-direction:column;min-height:100dvh;background:#fff;color:#24231f;font-family:ui-sans-serif,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif}header{padding:16px 36px 0}main{flex:1;display:flex;align-items:center;justify-content:center;padding:0 36px 64px;text-align:center}.icon{display:flex;margin:0 auto;width:44px;height:44px;border-radius:50%;align-items:center;justify-content:center;background:${ok ? "#e4f3ea" : "#f7ddce"};color:${ok ? "#2f6b46" : "#b83a12"}}h1{margin-top:16px;font-size:24px;font-weight:850;line-height:1.25;letter-spacing:-0.02em}p{margin:8px auto 0;max-width:38ch;font-size:13px;line-height:19px;color:#565550}</style><header><svg viewBox="2 4 56 52" width="23.7" height="22" aria-hidden="true"><path d="${CRANE}" fill="#24231f"/><path d="${CREST}" fill="#dd4f1e"/></svg></header><main><div><span class="icon"><svg viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${icon}</svg></span><h1>${title}</h1><p>${body}</p></div></main></html>`;
|
|
93112
93541
|
};
|
|
93113
93542
|
async function signIn(options = {}) {
|
|
93114
|
-
const verifier = base64url(
|
|
93115
|
-
const challenge = base64url(
|
|
93543
|
+
const verifier = base64url(crypto5.randomBytes(32));
|
|
93544
|
+
const challenge = base64url(crypto5.createHash("sha256").update(verifier).digest());
|
|
93116
93545
|
let finish2 = () => {
|
|
93117
93546
|
};
|
|
93118
93547
|
const answered = new Promise((resolve2) => finish2 = resolve2);
|
|
@@ -93261,12 +93690,12 @@ async function runDesktop(tell2) {
|
|
|
93261
93690
|
const readProfile2 = async () => {
|
|
93262
93691
|
const session = readSession();
|
|
93263
93692
|
const profile = await readProfile();
|
|
93264
|
-
const
|
|
93693
|
+
const held4 = profile.ok ? profile.value.session : {};
|
|
93265
93694
|
emit({
|
|
93266
93695
|
type: "account",
|
|
93267
|
-
name:
|
|
93268
|
-
email:
|
|
93269
|
-
avatar:
|
|
93696
|
+
name: held4.name || held4.handle || session?.name || session?.handle || "",
|
|
93697
|
+
email: held4.email || session?.email || "",
|
|
93698
|
+
avatar: held4.avatarUrl || session?.avatarUrl || ""
|
|
93270
93699
|
});
|
|
93271
93700
|
};
|
|
93272
93701
|
const readPlan2 = async () => {
|
|
@@ -93335,8 +93764,8 @@ async function runDesktop(tell2) {
|
|
|
93335
93764
|
const project = command.project;
|
|
93336
93765
|
const why = refusal(command.path);
|
|
93337
93766
|
if (why) return emit({ type: "folderRefused", why, project });
|
|
93338
|
-
const real =
|
|
93339
|
-
const added = await addFolder(id,
|
|
93767
|
+
const real = fs30.realpathSync(command.path);
|
|
93768
|
+
const added = await addFolder(id, path33.basename(real) || real, real, project);
|
|
93340
93769
|
if (!added.ok) {
|
|
93341
93770
|
const taken = added.code === "folder_taken";
|
|
93342
93771
|
return emit({ type: "folderRefused", why: taken ? "taken" : "failed", project, ...taken ? { taken: added.project } : {} });
|
|
@@ -93345,9 +93774,9 @@ async function runDesktop(tell2) {
|
|
|
93345
93774
|
return readFolders();
|
|
93346
93775
|
}
|
|
93347
93776
|
case "removeFolder": {
|
|
93348
|
-
const
|
|
93777
|
+
const held4 = folders2.find((f2) => f2.project === command.project);
|
|
93349
93778
|
const removed = await removeFolder(id, command.project);
|
|
93350
|
-
if (removed.ok &&
|
|
93779
|
+
if (removed.ok && held4) for (const dir of disallow(held4.path)) clearAkb(dir);
|
|
93351
93780
|
return readFolders();
|
|
93352
93781
|
}
|
|
93353
93782
|
case "folderNotify":
|