wildcrane-runner 0.6.3 → 0.6.5
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 +1911 -2469
- package/dist/akb/package.json +1 -1
- package/dist/launcher.mjs +9 -7
- package/dist/runner.mjs +1400 -981
- package/package.json +1 -1
package/dist/runner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// wildcrane-runner 0.6.
|
|
1
|
+
// wildcrane-runner 0.6.5 — 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(
|
|
@@ -4382,15 +4382,15 @@ var require_react_dom_server_legacy_node_production = __commonJS({
|
|
|
4382
4382
|
childState.suspenseyImages && (parentState.suspenseyImages = true);
|
|
4383
4383
|
}
|
|
4384
4384
|
function createRenderState(resumableState, generateStaticMarkup) {
|
|
4385
|
-
var
|
|
4385
|
+
var idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
|
|
4386
4386
|
void 0 !== bootstrapScriptContent && (bootstrapChunks.push("<script"), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
|
|
4387
4387
|
">",
|
|
4388
4388
|
("" + bootstrapScriptContent).replace(scriptRegex, scriptReplacer),
|
|
4389
4389
|
"</script>"
|
|
4390
4390
|
));
|
|
4391
|
-
bootstrapScriptContent =
|
|
4392
|
-
var JSCompiler_object_inline_segmentPrefix_1724 =
|
|
4393
|
-
|
|
4391
|
+
bootstrapScriptContent = idPrefix + "P:";
|
|
4392
|
+
var JSCompiler_object_inline_segmentPrefix_1724 = idPrefix + "S:";
|
|
4393
|
+
idPrefix += "B:";
|
|
4394
4394
|
var JSCompiler_object_inline_preconnects_1738 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_fontPreloads_1739 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_highImagePreloads_1740 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_styles_1741 = /* @__PURE__ */ new Map(), JSCompiler_object_inline_bootstrapScripts_1742 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_scripts_1743 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_bulkPreloads_1744 = /* @__PURE__ */ new Set(), JSCompiler_object_inline_preloads_1745 = {
|
|
4395
4395
|
images: /* @__PURE__ */ new Map(),
|
|
4396
4396
|
stylesheets: /* @__PURE__ */ new Map(),
|
|
@@ -4449,7 +4449,7 @@ var require_react_dom_server_legacy_node_production = __commonJS({
|
|
|
4449
4449
|
return {
|
|
4450
4450
|
placeholderPrefix: bootstrapScriptContent,
|
|
4451
4451
|
segmentPrefix: JSCompiler_object_inline_segmentPrefix_1724,
|
|
4452
|
-
boundaryPrefix:
|
|
4452
|
+
boundaryPrefix: idPrefix,
|
|
4453
4453
|
startInlineScript: "<script",
|
|
4454
4454
|
startInlineStyle: "<style",
|
|
4455
4455
|
preamble: { htmlChunks: null, headChunks: null, bodyChunks: null },
|
|
@@ -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();
|
|
@@ -7804,7 +7804,7 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
7804
7804
|
'<script nonce="' + escapeTextForBrowser(externalRuntimeConfig) + '"'
|
|
7805
7805
|
), nonceStyle = "string" === typeof nonce ? void 0 : nonce && nonce.style, inlineStyleWithNonce = void 0 === nonceStyle ? startInlineStyle : stringToPrecomputedChunk(
|
|
7806
7806
|
'<style nonce="' + escapeTextForBrowser(nonceStyle) + '"'
|
|
7807
|
-
),
|
|
7807
|
+
), idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
|
|
7808
7808
|
void 0 !== bootstrapScriptContent && (bootstrapChunks.push(inlineScriptWithNonce), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
|
|
7809
7809
|
endOfStartTag,
|
|
7810
7810
|
("" + bootstrapScriptContent).replace(scriptRegex, scriptReplacer),
|
|
@@ -7825,9 +7825,9 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
7825
7825
|
remainingCapacity: 2 + ("number" === typeof maxHeadersLength ? maxHeadersLength : 2e3)
|
|
7826
7826
|
} : null;
|
|
7827
7827
|
onHeaders = {
|
|
7828
|
-
placeholderPrefix: stringToPrecomputedChunk(
|
|
7829
|
-
segmentPrefix: stringToPrecomputedChunk(
|
|
7830
|
-
boundaryPrefix: stringToPrecomputedChunk(
|
|
7828
|
+
placeholderPrefix: stringToPrecomputedChunk(idPrefix + "P:"),
|
|
7829
|
+
segmentPrefix: stringToPrecomputedChunk(idPrefix + "S:"),
|
|
7830
|
+
boundaryPrefix: stringToPrecomputedChunk(idPrefix + "B:"),
|
|
7831
7831
|
startInlineScript: inlineScriptWithNonce,
|
|
7832
7832
|
startInlineStyle: inlineStyleWithNonce,
|
|
7833
7833
|
preamble: createPreambleState(),
|
|
@@ -7865,12 +7865,12 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
7865
7865
|
};
|
|
7866
7866
|
if (void 0 !== bootstrapScripts)
|
|
7867
7867
|
for (importMap = 0; importMap < bootstrapScripts.length; importMap++)
|
|
7868
|
-
|
|
7868
|
+
idPrefix = bootstrapScripts[importMap], nonceStyle = inlineScriptWithNonce = void 0, inlineStyleWithNonce = {
|
|
7869
7869
|
rel: "preload",
|
|
7870
7870
|
as: "script",
|
|
7871
7871
|
fetchPriority: "low",
|
|
7872
7872
|
nonce
|
|
7873
|
-
}, "string" === typeof
|
|
7873
|
+
}, "string" === typeof idPrefix ? inlineStyleWithNonce.href = maxHeadersLength = idPrefix : (inlineStyleWithNonce.href = maxHeadersLength = idPrefix.src, inlineStyleWithNonce.integrity = nonceStyle = "string" === typeof idPrefix.integrity ? idPrefix.integrity : void 0, inlineStyleWithNonce.crossOrigin = inlineScriptWithNonce = "string" === typeof idPrefix || null == idPrefix.crossOrigin ? void 0 : "use-credentials" === idPrefix.crossOrigin ? "use-credentials" : ""), idPrefix = resumableState, bootstrapScriptContent = maxHeadersLength, idPrefix.scriptResources[bootstrapScriptContent] = null, idPrefix.moduleScriptResources[bootstrapScriptContent] = null, idPrefix = [], pushLinkImpl(idPrefix, inlineStyleWithNonce), onHeaders.bootstrapScripts.add(idPrefix), bootstrapChunks.push(
|
|
7874
7874
|
startScriptSrc,
|
|
7875
7875
|
escapeTextForBrowser(maxHeadersLength),
|
|
7876
7876
|
attributeEnd
|
|
@@ -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();
|
|
@@ -16247,16 +16247,16 @@ var require_react_dom_server_legacy_node_development = __commonJS({
|
|
|
16247
16247
|
childState.suspenseyImages && (parentState.suspenseyImages = true);
|
|
16248
16248
|
}
|
|
16249
16249
|
function createRenderState(resumableState, generateStaticMarkup) {
|
|
16250
|
-
var
|
|
16250
|
+
var idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
|
|
16251
16251
|
void 0 !== bootstrapScriptContent && (bootstrapChunks.push("<script"), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
|
|
16252
16252
|
endOfStartTag,
|
|
16253
16253
|
escapeEntireInlineScriptContent(bootstrapScriptContent),
|
|
16254
16254
|
endInlineScript
|
|
16255
16255
|
));
|
|
16256
|
-
|
|
16257
|
-
placeholderPrefix:
|
|
16258
|
-
segmentPrefix:
|
|
16259
|
-
boundaryPrefix:
|
|
16256
|
+
idPrefix = {
|
|
16257
|
+
placeholderPrefix: idPrefix + "P:",
|
|
16258
|
+
segmentPrefix: idPrefix + "S:",
|
|
16259
|
+
boundaryPrefix: idPrefix + "B:",
|
|
16260
16260
|
startInlineScript: "<script",
|
|
16261
16261
|
startInlineStyle: "<style",
|
|
16262
16262
|
preamble: { htmlChunks: null, headChunks: null, bodyChunks: null },
|
|
@@ -16301,7 +16301,7 @@ var require_react_dom_server_legacy_node_development = __commonJS({
|
|
|
16301
16301
|
nonce: void 0
|
|
16302
16302
|
};
|
|
16303
16303
|
"string" === typeof scriptConfig ? props.href = src = scriptConfig : (props.href = src = scriptConfig.src, props.integrity = integrity = "string" === typeof scriptConfig.integrity ? scriptConfig.integrity : void 0, props.crossOrigin = crossOrigin = "string" === typeof scriptConfig || null == scriptConfig.crossOrigin ? void 0 : "use-credentials" === scriptConfig.crossOrigin ? "use-credentials" : "");
|
|
16304
|
-
preloadBootstrapScriptOrModule(resumableState,
|
|
16304
|
+
preloadBootstrapScriptOrModule(resumableState, idPrefix, src, props);
|
|
16305
16305
|
bootstrapChunks.push(
|
|
16306
16306
|
'<script src="',
|
|
16307
16307
|
escapeTextForBrowser(src),
|
|
@@ -16328,7 +16328,7 @@ var require_react_dom_server_legacy_node_development = __commonJS({
|
|
|
16328
16328
|
nonce: void 0
|
|
16329
16329
|
}, "string" === typeof bootstrapScriptContent ? integrity.href = scriptConfig = bootstrapScriptContent : (integrity.href = scriptConfig = bootstrapScriptContent.src, integrity.integrity = crossOrigin = "string" === typeof bootstrapScriptContent.integrity ? bootstrapScriptContent.integrity : void 0, integrity.crossOrigin = src = "string" === typeof bootstrapScriptContent || null == bootstrapScriptContent.crossOrigin ? void 0 : "use-credentials" === bootstrapScriptContent.crossOrigin ? "use-credentials" : ""), preloadBootstrapScriptOrModule(
|
|
16330
16330
|
resumableState,
|
|
16331
|
-
|
|
16331
|
+
idPrefix,
|
|
16332
16332
|
scriptConfig,
|
|
16333
16333
|
integrity
|
|
16334
16334
|
), bootstrapChunks.push(
|
|
@@ -16345,31 +16345,31 @@ var require_react_dom_server_legacy_node_development = __commonJS({
|
|
|
16345
16345
|
attributeEnd
|
|
16346
16346
|
), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(' async=""></script>');
|
|
16347
16347
|
return {
|
|
16348
|
-
placeholderPrefix:
|
|
16349
|
-
segmentPrefix:
|
|
16350
|
-
boundaryPrefix:
|
|
16351
|
-
startInlineScript:
|
|
16352
|
-
startInlineStyle:
|
|
16353
|
-
preamble:
|
|
16354
|
-
externalRuntimeScript:
|
|
16355
|
-
bootstrapChunks:
|
|
16356
|
-
importMapChunks:
|
|
16357
|
-
onHeaders:
|
|
16358
|
-
headers:
|
|
16359
|
-
resets:
|
|
16360
|
-
charsetChunks:
|
|
16361
|
-
viewportChunks:
|
|
16362
|
-
hoistableChunks:
|
|
16363
|
-
preconnects:
|
|
16364
|
-
fontPreloads:
|
|
16365
|
-
highImagePreloads:
|
|
16366
|
-
styles:
|
|
16367
|
-
bootstrapScripts:
|
|
16368
|
-
scripts:
|
|
16369
|
-
bulkPreloads:
|
|
16370
|
-
preloads:
|
|
16371
|
-
nonce:
|
|
16372
|
-
stylesToHoist:
|
|
16348
|
+
placeholderPrefix: idPrefix.placeholderPrefix,
|
|
16349
|
+
segmentPrefix: idPrefix.segmentPrefix,
|
|
16350
|
+
boundaryPrefix: idPrefix.boundaryPrefix,
|
|
16351
|
+
startInlineScript: idPrefix.startInlineScript,
|
|
16352
|
+
startInlineStyle: idPrefix.startInlineStyle,
|
|
16353
|
+
preamble: idPrefix.preamble,
|
|
16354
|
+
externalRuntimeScript: idPrefix.externalRuntimeScript,
|
|
16355
|
+
bootstrapChunks: idPrefix.bootstrapChunks,
|
|
16356
|
+
importMapChunks: idPrefix.importMapChunks,
|
|
16357
|
+
onHeaders: idPrefix.onHeaders,
|
|
16358
|
+
headers: idPrefix.headers,
|
|
16359
|
+
resets: idPrefix.resets,
|
|
16360
|
+
charsetChunks: idPrefix.charsetChunks,
|
|
16361
|
+
viewportChunks: idPrefix.viewportChunks,
|
|
16362
|
+
hoistableChunks: idPrefix.hoistableChunks,
|
|
16363
|
+
preconnects: idPrefix.preconnects,
|
|
16364
|
+
fontPreloads: idPrefix.fontPreloads,
|
|
16365
|
+
highImagePreloads: idPrefix.highImagePreloads,
|
|
16366
|
+
styles: idPrefix.styles,
|
|
16367
|
+
bootstrapScripts: idPrefix.bootstrapScripts,
|
|
16368
|
+
scripts: idPrefix.scripts,
|
|
16369
|
+
bulkPreloads: idPrefix.bulkPreloads,
|
|
16370
|
+
preloads: idPrefix.preloads,
|
|
16371
|
+
nonce: idPrefix.nonce,
|
|
16372
|
+
stylesToHoist: idPrefix.stylesToHoist,
|
|
16373
16373
|
generateStaticMarkup
|
|
16374
16374
|
};
|
|
16375
16375
|
}
|
|
@@ -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) {
|
|
@@ -21749,7 +21749,7 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
21749
21749
|
'<script nonce="' + escapeTextForBrowser(externalRuntimeConfig) + '"'
|
|
21750
21750
|
), nonceStyle = "string" === typeof nonce ? void 0 : nonce && nonce.style, inlineStyleWithNonce = void 0 === nonceStyle ? startInlineStyle : stringToPrecomputedChunk(
|
|
21751
21751
|
'<style nonce="' + escapeTextForBrowser(nonceStyle) + '"'
|
|
21752
|
-
),
|
|
21752
|
+
), idPrefix = resumableState.idPrefix, bootstrapChunks = [], bootstrapScriptContent = resumableState.bootstrapScriptContent, bootstrapScripts = resumableState.bootstrapScripts, bootstrapModules = resumableState.bootstrapModules;
|
|
21753
21753
|
void 0 !== bootstrapScriptContent && (bootstrapChunks.push(inlineScriptWithNonce), pushCompletedShellIdAttribute(bootstrapChunks, resumableState), bootstrapChunks.push(
|
|
21754
21754
|
endOfStartTag,
|
|
21755
21755
|
escapeEntireInlineScriptContent(bootstrapScriptContent),
|
|
@@ -21774,9 +21774,9 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
21774
21774
|
remainingCapacity: 2 + ("number" === typeof maxHeadersLength ? maxHeadersLength : 2e3)
|
|
21775
21775
|
} : null;
|
|
21776
21776
|
onHeaders = {
|
|
21777
|
-
placeholderPrefix: stringToPrecomputedChunk(
|
|
21778
|
-
segmentPrefix: stringToPrecomputedChunk(
|
|
21779
|
-
boundaryPrefix: stringToPrecomputedChunk(
|
|
21777
|
+
placeholderPrefix: stringToPrecomputedChunk(idPrefix + "P:"),
|
|
21778
|
+
segmentPrefix: stringToPrecomputedChunk(idPrefix + "S:"),
|
|
21779
|
+
boundaryPrefix: stringToPrecomputedChunk(idPrefix + "B:"),
|
|
21780
21780
|
startInlineScript: inlineScriptWithNonce,
|
|
21781
21781
|
startInlineStyle: inlineStyleWithNonce,
|
|
21782
21782
|
preamble: createPreambleState(),
|
|
@@ -21814,16 +21814,16 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
21814
21814
|
};
|
|
21815
21815
|
if (void 0 !== bootstrapScripts)
|
|
21816
21816
|
for (importMap = 0; importMap < bootstrapScripts.length; importMap++)
|
|
21817
|
-
maxHeadersLength = bootstrapScripts[importMap], inlineStyleWithNonce = nonceStyle = void 0,
|
|
21817
|
+
maxHeadersLength = bootstrapScripts[importMap], inlineStyleWithNonce = nonceStyle = void 0, idPrefix = {
|
|
21818
21818
|
rel: "preload",
|
|
21819
21819
|
as: "script",
|
|
21820
21820
|
fetchPriority: "low",
|
|
21821
21821
|
nonce
|
|
21822
|
-
}, "string" === typeof maxHeadersLength ?
|
|
21822
|
+
}, "string" === typeof maxHeadersLength ? idPrefix.href = inlineScriptWithNonce = maxHeadersLength : (idPrefix.href = inlineScriptWithNonce = maxHeadersLength.src, idPrefix.integrity = inlineStyleWithNonce = "string" === typeof maxHeadersLength.integrity ? maxHeadersLength.integrity : void 0, idPrefix.crossOrigin = nonceStyle = "string" === typeof maxHeadersLength || null == maxHeadersLength.crossOrigin ? void 0 : "use-credentials" === maxHeadersLength.crossOrigin ? "use-credentials" : ""), preloadBootstrapScriptOrModule(
|
|
21823
21823
|
resumableState,
|
|
21824
21824
|
onHeaders,
|
|
21825
21825
|
inlineScriptWithNonce,
|
|
21826
|
-
|
|
21826
|
+
idPrefix
|
|
21827
21827
|
), bootstrapChunks.push(
|
|
21828
21828
|
startScriptSrc,
|
|
21829
21829
|
escapeTextForBrowser(inlineScriptWithNonce),
|
|
@@ -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 {
|
|
@@ -84355,7 +84355,7 @@ function alive(pid) {
|
|
|
84355
84355
|
return e2.code === "EPERM";
|
|
84356
84356
|
}
|
|
84357
84357
|
}
|
|
84358
|
-
var sleep = (
|
|
84358
|
+
var sleep = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
84359
84359
|
|
|
84360
84360
|
// src/home.ts
|
|
84361
84361
|
import crypto from "node:crypto";
|
|
@@ -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.5" : "0.0.0";
|
|
84457
|
+
var AKB_VERSION = true ? "0.11.4" : "0.0.0";
|
|
84458
|
+
var AKB_CONTRACT = true ? 2 : 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.4",
|
|
85944
|
+
akbContract: 2,
|
|
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", {
|
|
@@ -86872,6 +86936,7 @@ var REPO_ROOT = "";
|
|
|
86872
86936
|
var KANBAN = "";
|
|
86873
86937
|
var TODO = "";
|
|
86874
86938
|
var ARCHIVE = "";
|
|
86939
|
+
var REJECTIONS_TO_REVIEW = ".sync";
|
|
86875
86940
|
var ARCHIVE_MD = "";
|
|
86876
86941
|
var README = "";
|
|
86877
86942
|
var MODULES_MD = "";
|
|
@@ -86879,7 +86944,6 @@ var CONFIG = "";
|
|
|
86879
86944
|
var KANBAN_GITIGNORE = "";
|
|
86880
86945
|
var RELEASES = "";
|
|
86881
86946
|
var RELEASE_SUMMARIES = "";
|
|
86882
|
-
var SETUP_CHECKLIST = "";
|
|
86883
86947
|
var AGENTS = "";
|
|
86884
86948
|
var WORKFLOWS = "";
|
|
86885
86949
|
var LEGACY_AGENTS = "";
|
|
@@ -86929,7 +86993,6 @@ function setBoard(kanban, root, flag) {
|
|
|
86929
86993
|
KANBAN_GITIGNORE = path9.join(KANBAN, ".gitignore");
|
|
86930
86994
|
RELEASES = path9.join(KANBAN, "releases.md");
|
|
86931
86995
|
RELEASE_SUMMARIES = path9.join(KANBAN, ".release-summaries");
|
|
86932
|
-
SETUP_CHECKLIST = path9.join(KANBAN, "setup-checklist.md");
|
|
86933
86996
|
AGENTS = path9.join(KANBAN, "agents");
|
|
86934
86997
|
WORKFLOWS = path9.join(KANBAN, "workflows");
|
|
86935
86998
|
LEGACY_AGENTS = path9.join(KANBAN, "skills");
|
|
@@ -87777,7 +87840,7 @@ ${text3}
|
|
|
87777
87840
|
// PROBE: on a machine that has `kimi`, run its login command's status form under a
|
|
87778
87841
|
// throwaway HOME and under the real one. If it says which state it is in, declare it here.
|
|
87779
87842
|
installs: () => [...process.env.KIMI_INSTALL_DIR ? [join5(process.env.KIMI_INSTALL_DIR, "bin", "kimi")] : [], home2(".kimi-code", "bin", "kimi")],
|
|
87780
|
-
install: "curl -
|
|
87843
|
+
install: "curl -fsSL https://code.kimi.com/kimi-code/install.sh | bash"
|
|
87781
87844
|
};
|
|
87782
87845
|
|
|
87783
87846
|
// ../cli/src/lib/agent/harnesses/opencode.ts
|
|
@@ -87979,6 +88042,7 @@ var DEFAULT_HARNESS = HARNESSES[0];
|
|
|
87979
88042
|
checkHarnesses(HARNESSES);
|
|
87980
88043
|
|
|
87981
88044
|
// ../cli/src/lib/agent/env.ts
|
|
88045
|
+
var SCHEDULED_AGENTS_ENV = "AI4KANBAN_SCHEDULED_AGENTS";
|
|
87982
88046
|
var SESSION_VARS = {
|
|
87983
88047
|
"claude-code": "CLAUDE_CODE_SESSION_ID",
|
|
87984
88048
|
codex: "CODEX_THREAD_ID"
|
|
@@ -88024,15 +88088,15 @@ function isFilled(harness, { values, secretsSet: secretsSet2 }) {
|
|
|
88024
88088
|
return setting?.kind === "secret" ? secretsSet2.includes(key) : Boolean(values[key]);
|
|
88025
88089
|
};
|
|
88026
88090
|
}
|
|
88027
|
-
function providerFor(harness,
|
|
88091
|
+
function providerFor(harness, held4) {
|
|
88028
88092
|
const setting = providerSetting(harness.settings);
|
|
88029
88093
|
if (!setting) return void 0;
|
|
88030
|
-
return pickedProvider(setting,
|
|
88094
|
+
return pickedProvider(setting, held4.values[setting.key] ?? "", isFilled(harness, held4));
|
|
88031
88095
|
}
|
|
88032
|
-
function settingArgs(harness,
|
|
88033
|
-
const { values } =
|
|
88034
|
-
const ignored =
|
|
88035
|
-
const picked = providerFor(harness,
|
|
88096
|
+
function settingArgs(harness, held4) {
|
|
88097
|
+
const { values } = held4;
|
|
88098
|
+
const ignored = held4.ignored ?? [];
|
|
88099
|
+
const picked = providerFor(harness, held4);
|
|
88036
88100
|
const list = providerSetting(harness.settings);
|
|
88037
88101
|
const byHand = !!list && ignored.includes(list.key);
|
|
88038
88102
|
const providerArgs = byHand ? [] : picked?.args ?? [];
|
|
@@ -88047,9 +88111,9 @@ function settingArgs(harness, held3) {
|
|
|
88047
88111
|
});
|
|
88048
88112
|
return [...providerArgs, ...flags, ...splitCommand(values[RAW_ARGS_KEY] ?? "")];
|
|
88049
88113
|
}
|
|
88050
|
-
function settingEnv(harness,
|
|
88051
|
-
const { values } =
|
|
88052
|
-
const picked = providerFor(harness,
|
|
88114
|
+
function settingEnv(harness, held4, secrets, cwd) {
|
|
88115
|
+
const { values } = held4;
|
|
88116
|
+
const picked = providerFor(harness, held4);
|
|
88053
88117
|
const env2 = { ...harness.env() };
|
|
88054
88118
|
for (const name of ownedVars(harness)) delete env2[name];
|
|
88055
88119
|
for (const name of Object.values(SESSION_VARS)) delete env2[name];
|
|
@@ -88076,11 +88140,11 @@ function ownedVars(harness) {
|
|
|
88076
88140
|
}
|
|
88077
88141
|
return [...names2];
|
|
88078
88142
|
}
|
|
88079
|
-
function effectiveValues(harness,
|
|
88080
|
-
const picked = providerFor(harness,
|
|
88143
|
+
function effectiveValues(harness, held4) {
|
|
88144
|
+
const picked = providerFor(harness, held4);
|
|
88081
88145
|
const out = {};
|
|
88082
88146
|
for (const setting of harness.settings) {
|
|
88083
|
-
const value =
|
|
88147
|
+
const value = held4.values[setting.key];
|
|
88084
88148
|
if (!value || setting.kind === "secret") continue;
|
|
88085
88149
|
if (!shownForProvider(harness.settings, setting.key, picked)) continue;
|
|
88086
88150
|
out[setting.key] = value;
|
|
@@ -88128,6 +88192,7 @@ __export(api_exports, {
|
|
|
88128
88192
|
readArtifact: () => readArtifact,
|
|
88129
88193
|
readBoard: () => readBoard,
|
|
88130
88194
|
readChat: () => readChat,
|
|
88195
|
+
readDecisions: () => readDecisions,
|
|
88131
88196
|
readDiscussion: () => readDiscussion,
|
|
88132
88197
|
readInbox: () => readInbox,
|
|
88133
88198
|
readPlan: () => readPlan,
|
|
@@ -88162,8 +88227,8 @@ import path12 from "node:path";
|
|
|
88162
88227
|
var file = () => path12.join(runnerHome(), "secrets.json");
|
|
88163
88228
|
function readAll() {
|
|
88164
88229
|
try {
|
|
88165
|
-
const
|
|
88166
|
-
return
|
|
88230
|
+
const held4 = JSON.parse(fs9.readFileSync(file(), "utf8"));
|
|
88231
|
+
return held4 && typeof held4 === "object" ? held4 : {};
|
|
88167
88232
|
} catch {
|
|
88168
88233
|
return {};
|
|
88169
88234
|
}
|
|
@@ -88171,12 +88236,12 @@ function readAll() {
|
|
|
88171
88236
|
var secretsOf = (runtime) => runtime ? readAll()[runtime] ?? {} : {};
|
|
88172
88237
|
function keepSecrets(runtime, given) {
|
|
88173
88238
|
const all = readAll();
|
|
88174
|
-
const
|
|
88239
|
+
const held4 = { ...all[runtime] };
|
|
88175
88240
|
for (const [key, value] of Object.entries(given)) {
|
|
88176
|
-
if (value)
|
|
88177
|
-
else delete
|
|
88241
|
+
if (value) held4[key] = value;
|
|
88242
|
+
else delete held4[key];
|
|
88178
88243
|
}
|
|
88179
|
-
if (Object.keys(
|
|
88244
|
+
if (Object.keys(held4).length) all[runtime] = held4;
|
|
88180
88245
|
else delete all[runtime];
|
|
88181
88246
|
fs9.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
|
|
88182
88247
|
const temp = `${file()}.${process.pid}.tmp`;
|
|
@@ -88190,7 +88255,7 @@ var secretsSet = () => Object.fromEntries(Object.entries(readAll()).map(([id, ke
|
|
|
88190
88255
|
var RUNTIMES = ["claude-code", "codex", "cursor", "opencode", "kimi", "dsh", "zcode", "grok"];
|
|
88191
88256
|
var PROTOCOL = 11;
|
|
88192
88257
|
var TIMEOUT_MS = 2e4;
|
|
88193
|
-
async function send(method, route, body, signedIn,
|
|
88258
|
+
async function send(method, route, body, signedIn, ms, type) {
|
|
88194
88259
|
const headers = { accept: "application/json" };
|
|
88195
88260
|
if (signedIn) {
|
|
88196
88261
|
const token = await accessToken();
|
|
@@ -88206,7 +88271,7 @@ async function send(method, route, body, signedIn, ms2, type) {
|
|
|
88206
88271
|
method,
|
|
88207
88272
|
headers,
|
|
88208
88273
|
body: body === void 0 ? void 0 : raw ? body : JSON.stringify(body),
|
|
88209
|
-
signal: AbortSignal.timeout(
|
|
88274
|
+
signal: AbortSignal.timeout(ms)
|
|
88210
88275
|
});
|
|
88211
88276
|
return { ok: true, value: response };
|
|
88212
88277
|
} catch (e2) {
|
|
@@ -88242,7 +88307,7 @@ async function upload(route, bytes2, type) {
|
|
|
88242
88307
|
const sent = await send("PUT", route, bytes2, true, FILE_TIMEOUT_MS, type);
|
|
88243
88308
|
return sent.ok ? answerOf(sent.value) : sent;
|
|
88244
88309
|
}
|
|
88245
|
-
var register = (r2) => request("POST", "/v1/runner", { ...r2, secrets: secretsSet(), protocol: PROTOCOL });
|
|
88310
|
+
var register = (r2) => request("POST", "/v1/runner", { ...r2, secrets: secretsSet(), protocol: PROTOCOL, akbContract: AKB_CONTRACT });
|
|
88246
88311
|
var readRunner = () => request("GET", "/v1/runner");
|
|
88247
88312
|
var release = (machineId2) => request("POST", "/v1/runner/release", { machineId: machineId2 });
|
|
88248
88313
|
var listJobs = (machineId2) => request("GET", `/v1/runner/jobs?machine=${encodeURIComponent(machineId2)}`);
|
|
@@ -88265,6 +88330,7 @@ var finishJob = (machineId2, job, outcome, reason = "", report2) => move(job, "f
|
|
|
88265
88330
|
var answerDiff = (machineId2, id, answer) => request("POST", `/v1/runner/diffs/${encodeURIComponent(id)}`, { machineId: machineId2, ...answer });
|
|
88266
88331
|
var listChats = (machineId2) => request("GET", `/v1/runner/chats?machine=${encodeURIComponent(machineId2)}`);
|
|
88267
88332
|
var readChat = (task) => request("GET", `/v1/tasks/${encodeURIComponent(task)}/chat`);
|
|
88333
|
+
var readDecisions = (task, after) => request("GET", `/v1/tasks/${q(task)}/decisions?limit=100${after ? `&after=${q(after)}` : ""}`);
|
|
88268
88334
|
var dispatchReview = (machineId2, project, tasks, runtime, model) => request("POST", "/v1/runner/reviews", { machineId: machineId2, project, tasks, runtime, model });
|
|
88269
88335
|
var readAgents = (machineId2, project) => request("GET", `/v1/runner/agents?machine=${encodeURIComponent(machineId2)}&project=${encodeURIComponent(project)}`);
|
|
88270
88336
|
var requestAgent = (machineId2, project, agent, workflow, seen) => request("POST", "/v1/runner/jobs", { machineId: machineId2, project, agent, workflow, seen });
|
|
@@ -88279,7 +88345,7 @@ var listFolders = (machineId2) => request("GET", `/v1/runner/folders?machine=${q
|
|
|
88279
88345
|
var listElsewhere = (machineId2) => request("GET", `/v1/runner/folders?machine=${q(machineId2)}&elsewhere=1`);
|
|
88280
88346
|
var listMachineTasks = (machineId2) => request("GET", `/v1/runner/tasks?machine=${q(machineId2)}`);
|
|
88281
88347
|
var stopTask = (task, how) => request("POST", how === "chat" ? `/v1/tasks/${q(task)}/chat/stop` : `/v1/tasks/${q(task)}/stop`, {});
|
|
88282
|
-
var addFolder = (machineId2, name,
|
|
88348
|
+
var addFolder = (machineId2, name, path34, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path34, ...project ? { project } : {} });
|
|
88283
88349
|
var removeFolder = (machineId2, project) => request("POST", `/v1/runner/folders/${q(project)}/remove`, { machineId: machineId2 });
|
|
88284
88350
|
var readPlan = () => request("GET", "/v1/billing");
|
|
88285
88351
|
var startTrial = () => request("POST", "/v1/billing/trial", {});
|
|
@@ -88352,6 +88418,7 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88352
88418
|
if (harness.client) {
|
|
88353
88419
|
const client = harness.client(effectiveValues(harness, values));
|
|
88354
88420
|
let session;
|
|
88421
|
+
let named2;
|
|
88355
88422
|
return {
|
|
88356
88423
|
command: argv[0],
|
|
88357
88424
|
args: argv.slice(1),
|
|
@@ -88367,12 +88434,12 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88367
88434
|
gotResumeId: (got, restarted) => {
|
|
88368
88435
|
if (restarted || !session) session = got;
|
|
88369
88436
|
},
|
|
88370
|
-
gotModel: () =>
|
|
88371
|
-
},
|
|
88437
|
+
gotModel: (got) => named2 = got,
|
|
88372
88438
|
event: event2
|
|
88373
88439
|
}),
|
|
88374
88440
|
quiet,
|
|
88375
|
-
session: () => session ?? resume ?? void 0
|
|
88441
|
+
session: () => session ?? resume ?? void 0,
|
|
88442
|
+
model: () => named2
|
|
88376
88443
|
};
|
|
88377
88444
|
}
|
|
88378
88445
|
const renderer = harness.renderer(cwd, argv[0], argv);
|
|
@@ -88384,7 +88451,8 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88384
88451
|
stdin: toStdin?.(prompt),
|
|
88385
88452
|
renderer,
|
|
88386
88453
|
quiet,
|
|
88387
|
-
session: () => renderer.resumeId?.() ?? resume ?? (harness.adoptsSessionId ? id : void 0)
|
|
88454
|
+
session: () => renderer.resumeId?.() ?? resume ?? (harness.adoptsSessionId ? id : void 0),
|
|
88455
|
+
model: () => renderer.model?.()
|
|
88388
88456
|
};
|
|
88389
88457
|
}
|
|
88390
88458
|
function declOf(setting) {
|
|
@@ -88742,240 +88810,6 @@ function nextDue(lastRun, cadence) {
|
|
|
88742
88810
|
return new Date(last2.getFullYear(), last2.getMonth(), last2.getDate() + c2.n, hour, minute, 0, 0);
|
|
88743
88811
|
}
|
|
88744
88812
|
|
|
88745
|
-
// ../cli/src/lib/yaml.ts
|
|
88746
|
-
function yamlScalar(s) {
|
|
88747
|
-
const text3 = String(s);
|
|
88748
|
-
if (text3 === "") return '""';
|
|
88749
|
-
if (/^[-?:,[\]{}#&*!|>'"%@`]/.test(text3) || /:\s/.test(text3) || /[\n"]/.test(text3) || /^\s|\s$/.test(text3)) {
|
|
88750
|
-
return JSON.stringify(text3);
|
|
88751
|
-
}
|
|
88752
|
-
return text3;
|
|
88753
|
-
}
|
|
88754
|
-
function unquote(v2) {
|
|
88755
|
-
const text3 = String(v2).trim();
|
|
88756
|
-
if (text3.startsWith('"') && text3.endsWith('"')) {
|
|
88757
|
-
try {
|
|
88758
|
-
return JSON.parse(text3);
|
|
88759
|
-
} catch {
|
|
88760
|
-
return text3.slice(1, -1);
|
|
88761
|
-
}
|
|
88762
|
-
}
|
|
88763
|
-
if (text3.startsWith("'") && text3.endsWith("'")) return text3.slice(1, -1);
|
|
88764
|
-
return text3;
|
|
88765
|
-
}
|
|
88766
|
-
|
|
88767
|
-
// ../cli/src/lib/question-block.ts
|
|
88768
|
-
var MODES = ["single", "multi"];
|
|
88769
|
-
var withoutTag = (text3) => text3.replace(/^\[user\]\s+/, "");
|
|
88770
|
-
function normalizeQuestion(raw) {
|
|
88771
|
-
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
88772
|
-
const source = raw;
|
|
88773
|
-
const text3 = withoutTag(String(source.question ?? source.text ?? ""));
|
|
88774
|
-
const extra = {
|
|
88775
|
-
...typeof source.agent === "string" && source.agent.trim() ? { agent: source.agent.trim() } : {},
|
|
88776
|
-
...source.skipped === true || source.skipped === "true" ? { skipped: true } : {}
|
|
88777
|
-
};
|
|
88778
|
-
const options = (Array.isArray(source.options) ? source.options : []).map((o2) => String(o2).trim()).filter(Boolean);
|
|
88779
|
-
if (options.length === 0) return { text: text3, ...extra };
|
|
88780
|
-
const mode = MODES.includes(String(source.mode)) ? String(source.mode) : "single";
|
|
88781
|
-
const recommend = (Array.isArray(source.recommend) ? source.recommend : []).map(Number).filter((n) => Number.isInteger(n) && n >= 1 && n <= options.length);
|
|
88782
|
-
return { text: text3, mode, options, recommend: mode === "single" ? recommend.slice(0, 1) : recommend, ...extra };
|
|
88783
|
-
}
|
|
88784
|
-
return { text: withoutTag(String(raw)) };
|
|
88785
|
-
}
|
|
88786
|
-
function parseQuestionsBlock(lines) {
|
|
88787
|
-
const out = [];
|
|
88788
|
-
for (let i = 0; i < lines.length; i++) {
|
|
88789
|
-
const m = lines[i].match(/^\s*-\s+([\s\S]*)$/);
|
|
88790
|
-
if (!m) continue;
|
|
88791
|
-
const head2 = m[1];
|
|
88792
|
-
const opened = head2.match(/^question:\s*(.*)$/);
|
|
88793
|
-
if (!opened) {
|
|
88794
|
-
out.push(normalizeQuestion(unquote(head2)));
|
|
88795
|
-
continue;
|
|
88796
|
-
}
|
|
88797
|
-
const q3 = {
|
|
88798
|
-
question: unquote(opened[1]),
|
|
88799
|
-
options: [],
|
|
88800
|
-
recommend: []
|
|
88801
|
-
};
|
|
88802
|
-
while (i + 1 < lines.length && !/^\s*-\s/.test(lines[i + 1])) {
|
|
88803
|
-
const field = lines[i + 1].match(/^\s*([A-Za-z_]+):\s*(.*)$/);
|
|
88804
|
-
i++;
|
|
88805
|
-
if (!field) continue;
|
|
88806
|
-
const [, key, val] = field;
|
|
88807
|
-
if (key === "options") {
|
|
88808
|
-
while (i + 1 < lines.length && /^\s*-\s+/.test(lines[i + 1])) {
|
|
88809
|
-
q3.options.push(unquote(lines[i + 1].replace(/^\s*-\s+/, "")));
|
|
88810
|
-
i++;
|
|
88811
|
-
}
|
|
88812
|
-
} else if (key === "recommend") {
|
|
88813
|
-
q3.recommend = val.replace(/^\[|\]$/g, "").split(",").map((s) => Number(s.trim())).filter((n) => Number.isInteger(n));
|
|
88814
|
-
} else if (key === "mode") {
|
|
88815
|
-
q3.mode = unquote(val);
|
|
88816
|
-
} else if (key === "agent") {
|
|
88817
|
-
q3.agent = unquote(val);
|
|
88818
|
-
} else if (key === "skipped") {
|
|
88819
|
-
q3.skipped = unquote(val) === "true";
|
|
88820
|
-
}
|
|
88821
|
-
}
|
|
88822
|
-
out.push(normalizeQuestion(q3));
|
|
88823
|
-
}
|
|
88824
|
-
return out;
|
|
88825
|
-
}
|
|
88826
|
-
|
|
88827
|
-
// ../cli/src/lib/view/rules.ts
|
|
88828
|
-
var openOf = (questions) => questions.filter((q3) => !q3.skipped);
|
|
88829
|
-
|
|
88830
|
-
// ../cli/src/lib/frontmatter.ts
|
|
88831
|
-
function parseFrontmatter(text3) {
|
|
88832
|
-
const lines = text3.split("\n");
|
|
88833
|
-
if (lines[0].trim() !== "---") return { meta: null, body: text3 };
|
|
88834
|
-
let i = 1;
|
|
88835
|
-
const fm = [];
|
|
88836
|
-
while (i < lines.length && lines[i].trim() !== "---") {
|
|
88837
|
-
fm.push(lines[i]);
|
|
88838
|
-
i++;
|
|
88839
|
-
}
|
|
88840
|
-
if (i >= lines.length) return { meta: null, body: text3 };
|
|
88841
|
-
const meta = {};
|
|
88842
|
-
for (let j2 = 0; j2 < fm.length; j2++) {
|
|
88843
|
-
const m = fm[j2].match(/^([A-Za-z_]+):\s*(.*)$/);
|
|
88844
|
-
if (!m) continue;
|
|
88845
|
-
const key = m[1];
|
|
88846
|
-
const val = m[2];
|
|
88847
|
-
if (key === "questions") {
|
|
88848
|
-
if (val === "") {
|
|
88849
|
-
const block = [];
|
|
88850
|
-
while (j2 + 1 < fm.length && /^\s/.test(fm[j2 + 1]) && fm[j2 + 1].trim() !== "") {
|
|
88851
|
-
block.push(fm[j2 + 1]);
|
|
88852
|
-
j2++;
|
|
88853
|
-
}
|
|
88854
|
-
meta.questions = parseQuestionsBlock(block);
|
|
88855
|
-
} else {
|
|
88856
|
-
meta.questions = val.trim() === "[]" ? [] : [normalizeQuestion(unquote(val))];
|
|
88857
|
-
}
|
|
88858
|
-
continue;
|
|
88859
|
-
}
|
|
88860
|
-
if (val === "") {
|
|
88861
|
-
const items = [];
|
|
88862
|
-
while (j2 + 1 < fm.length && /^\s*-\s+/.test(fm[j2 + 1])) {
|
|
88863
|
-
items.push(unquote(fm[j2 + 1].replace(/^\s*-\s+/, "")));
|
|
88864
|
-
j2++;
|
|
88865
|
-
}
|
|
88866
|
-
meta[key] = items;
|
|
88867
|
-
} else if (val.startsWith("[")) {
|
|
88868
|
-
const inner = val.slice(1, val.lastIndexOf("]"));
|
|
88869
|
-
meta[key] = inner.split(",").map((s) => s.trim()).filter(Boolean).map(unquote);
|
|
88870
|
-
} else {
|
|
88871
|
-
meta[key] = unquote(val);
|
|
88872
|
-
}
|
|
88873
|
-
}
|
|
88874
|
-
for (const k of ["blocked_by", "related"]) {
|
|
88875
|
-
const value = meta[k];
|
|
88876
|
-
if (Array.isArray(value)) {
|
|
88877
|
-
meta[k] = value.map((x2) => Number(String(x2).replace(/^#/, ""))).filter((n) => Number.isInteger(n));
|
|
88878
|
-
} else {
|
|
88879
|
-
meta[k] = [];
|
|
88880
|
-
}
|
|
88881
|
-
}
|
|
88882
|
-
if (!Array.isArray(meta.questions)) {
|
|
88883
|
-
meta.questions = meta.questions ? [normalizeQuestion(meta.questions)] : [];
|
|
88884
|
-
}
|
|
88885
|
-
for (const key of ["priority", "roi"]) {
|
|
88886
|
-
meta[key] = typeof meta[key] === "string" && meta[key].trim() ? meta[key].trim() : "";
|
|
88887
|
-
}
|
|
88888
|
-
if (!Array.isArray(meta.modules)) meta.modules = [];
|
|
88889
|
-
delete meta.channels;
|
|
88890
|
-
delete meta.decided;
|
|
88891
|
-
delete meta.verify;
|
|
88892
|
-
delete meta.release;
|
|
88893
|
-
delete meta.schedule;
|
|
88894
|
-
meta.workflow = typeof meta.workflow === "string" && meta.workflow.trim() ? meta.workflow.trim() : "";
|
|
88895
|
-
meta.triage = typeof meta.triage === "string" ? meta.triage.trim() : "";
|
|
88896
|
-
meta.source = (Array.isArray(meta.source) ? meta.source : typeof meta.source === "string" ? [meta.source] : []).map((ref) => String(ref).trim()).filter(Boolean);
|
|
88897
|
-
delete meta.phases;
|
|
88898
|
-
if (Array.isArray(meta.previews)) meta.previews = meta.previews.map((name) => String(name).trim()).filter(Boolean);
|
|
88899
|
-
else delete meta.previews;
|
|
88900
|
-
meta.stages = /^\d+$/.test(String(meta.stages ?? "").trim()) ? Number(meta.stages) : 0;
|
|
88901
|
-
meta.phase = /^\d+$/.test(String(meta.phase ?? "").trim()) ? Number(meta.phase) : 0;
|
|
88902
|
-
meta.preview_approved = meta.preview_approved === "true";
|
|
88903
|
-
meta.archived = typeof meta.archived === "string" && meta.archived.trim() ? meta.archived.trim() : "";
|
|
88904
|
-
meta.rejected = meta.rejected === "true";
|
|
88905
|
-
meta.rejected_reason = typeof meta.rejected_reason === "string" ? meta.rejected_reason : "";
|
|
88906
|
-
meta.rejected_at = typeof meta.rejected_at === "string" ? meta.rejected_at.trim() : "";
|
|
88907
|
-
meta.rejected_by = meta.rejected_by === "user" || meta.rejected_by === "agent" ? meta.rejected_by : "";
|
|
88908
|
-
return { meta, body: lines.slice(i + 1).join("\n") };
|
|
88909
|
-
}
|
|
88910
|
-
|
|
88911
|
-
// ../cli/src/lib/spec-agent-names.ts
|
|
88912
|
-
var LEGACY_SPEC_AGENT_NAMES = {
|
|
88913
|
-
"recommend-tech-stack": "tech-stack-advisor",
|
|
88914
|
-
"technology-selection": "tech-stack-advisor",
|
|
88915
|
-
"ui-design": "ui-designer",
|
|
88916
|
-
// Renamed in #945 and folded into the editor in #1057; its asset memory stays in
|
|
88917
|
-
// `memory/agents/video-assets/`.
|
|
88918
|
-
"video-assets": "hyperframes-editor",
|
|
88919
|
-
// Renamed in #1502: it reads chats, and writes memory as a result.
|
|
88920
|
-
"memory-reviewer": "chat-reviewer",
|
|
88921
|
-
// Folded into `copywriting` in #1582.
|
|
88922
|
-
"user-docs": "copywriting"
|
|
88923
|
-
};
|
|
88924
|
-
var canonicalSpecAgent = (name) => {
|
|
88925
|
-
const asked = name.trim();
|
|
88926
|
-
return LEGACY_SPEC_AGENT_NAMES[asked] ?? asked;
|
|
88927
|
-
};
|
|
88928
|
-
|
|
88929
|
-
// ../cli/src/lib/slug.ts
|
|
88930
|
-
function slugify(s) {
|
|
88931
|
-
const out = String(s).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/g, "");
|
|
88932
|
-
return out || "task";
|
|
88933
|
-
}
|
|
88934
|
-
|
|
88935
|
-
// ../cli/src/lib/memory.ts
|
|
88936
|
-
var PLANNER_MEMORY_FILES = ["decisions.md", "rejected.md", "redesign.md"];
|
|
88937
|
-
var STARTERS = {
|
|
88938
|
-
"readme.md": `# Shipped
|
|
88939
|
-
|
|
88940
|
-
User-facing work that has shipped, one line each \u2014 a link to the published doc that
|
|
88941
|
-
covers it, or a plain-words note.
|
|
88942
|
-
|
|
88943
|
-
_(nothing recorded yet \u2014 the first finished task fills it in.)_
|
|
88944
|
-
`,
|
|
88945
|
-
"decisions.md": `# Decisions
|
|
88946
|
-
|
|
88947
|
-
Settled answers to cards' open questions, grouped by topic. Keep only **user-facing**
|
|
88948
|
-
calls that guide future planning \u2014 what a user can see, do, or would care about.
|
|
88949
|
-
Internal detail stays on the card.
|
|
88950
|
-
`,
|
|
88951
|
-
"redesign.md": `# Redesign
|
|
88952
|
-
|
|
88953
|
-
Design mistakes to avoid when writing a card, grouped by topic. One entry each: the
|
|
88954
|
-
mistake, then the design we actually want. Read before writing or reviewing a card.
|
|
88955
|
-
`,
|
|
88956
|
-
"rejected.md": `# Rejected
|
|
88957
|
-
|
|
88958
|
-
Ideas we turned down, grouped by topic. One line each: the idea, and why we said no. Read
|
|
88959
|
-
before proposing so you don't re-suggest them.
|
|
88960
|
-
`,
|
|
88961
|
-
// Only a header: `describe-project` writes the body, and runs while there is none (#1268).
|
|
88962
|
-
"project.md": `# Project
|
|
88963
|
-
|
|
88964
|
-
What the project is today, from its users' side. Rewritten whole by \`akb describe-project\`;
|
|
88965
|
-
edits here do not last.
|
|
88966
|
-
`
|
|
88967
|
-
};
|
|
88968
|
-
var RESERVED_MODULE_NAMES = PLANNER_MEMORY_FILES.map((name) => name.replace(/\.md$/, ""));
|
|
88969
|
-
var PRODUCT_STARTER = STARTERS["project.md"].replaceAll("Project", "Product").replaceAll("project", "product");
|
|
88970
|
-
var SEEDED_GOAL_PARAGRAPHS = new Set(
|
|
88971
|
-
[
|
|
88972
|
-
"# Goal",
|
|
88973
|
-
"Where this is headed, in the user's own words: the long-term goal, the horizon it aims at, and the roadmap of what comes next, roughly in order. Not this week's work \u2014 that's the cards on the board. The user owns this file; the agent seeds it but does not invent the goal.",
|
|
88974
|
-
"The direction, in the user's own words \u2014 where this is headed. One short statement. The user owns this file; the agent seeds it but does not invent the goal.",
|
|
88975
|
-
"_(not filled in yet \u2014 the user writes this.)_"
|
|
88976
|
-
].map((p2) => p2.replace(/\s+/g, " "))
|
|
88977
|
-
);
|
|
88978
|
-
|
|
88979
88813
|
// ../cli/src/lib/agent/due.ts
|
|
88980
88814
|
var AUTO_GAP = "6h";
|
|
88981
88815
|
var DAY = 864e5;
|
|
@@ -89000,22 +88834,32 @@ function scheduleDue(ask, now = Date.now()) {
|
|
|
89000
88834
|
}
|
|
89001
88835
|
const newest2 = ask.attempts.reduce((a3, r2) => a3 && a3.startedAt >= r2.startedAt ? a3 : r2, null);
|
|
89002
88836
|
const retrying = isAuto(ask.cadence) && newest2?.status === "error";
|
|
89003
|
-
const wait3 = next.getTime() > now ? retrying ? "retrying" : "tooSoon" : !ask.newWork() ? "nothingNew" :
|
|
88837
|
+
const wait3 = next.getTime() > now ? retrying ? "retrying" : "tooSoon" : !ask.newWork() ? "nothingNew" : null;
|
|
89004
88838
|
const reason = !wait3 || wait3 === "tooSoon" ? void 0 : wait3 === "nothingNew" ? ask.reads : wait3;
|
|
89005
88839
|
return { next, wait: wait3, ...reason ? { reason } : {} };
|
|
89006
88840
|
}
|
|
89007
88841
|
|
|
89008
88842
|
// src/agents.ts
|
|
89009
|
-
|
|
89010
|
-
|
|
88843
|
+
function nextHour(now = Date.now()) {
|
|
88844
|
+
const at2 = new Date(now);
|
|
88845
|
+
at2.setMinutes(60, 0, 0);
|
|
88846
|
+
return at2.getTime();
|
|
88847
|
+
}
|
|
88848
|
+
function hourOf(at2) {
|
|
88849
|
+
const hour = new Date(at2 ?? NaN);
|
|
88850
|
+
if (Number.isNaN(hour.getTime())) return 0;
|
|
88851
|
+
hour.setMinutes(hour.getMinutes() + 30, 0, 0);
|
|
88852
|
+
hour.setMinutes(0, 0, 0);
|
|
88853
|
+
return hour.getTime();
|
|
88854
|
+
}
|
|
89011
88855
|
function agentDue(agent, now = Date.now()) {
|
|
89012
88856
|
if (agent.attempts.some((a3) => a3.status === "running")) return false;
|
|
89013
88857
|
const due = scheduleDue({
|
|
89014
88858
|
cadence: agent.cadence,
|
|
89015
88859
|
fallback: agent.fallback,
|
|
89016
88860
|
reads: agent.reads,
|
|
89017
|
-
from: Math.max(
|
|
89018
|
-
attempts: agent.attempts.map((a3) => ({ startedAt:
|
|
88861
|
+
from: Math.max(hourOf(agent.lastSuccess), hourOf(agent.since)),
|
|
88862
|
+
attempts: agent.attempts.map((a3) => ({ startedAt: hourOf(a3.startedAt), status: a3.status })),
|
|
89019
88863
|
newWork: () => agent.newWork
|
|
89020
88864
|
}, now);
|
|
89021
88865
|
return !due.wait;
|
|
@@ -89036,34 +88880,120 @@ async function askDueAgents(machineId2, now = Date.now()) {
|
|
|
89036
88880
|
return started;
|
|
89037
88881
|
}
|
|
89038
88882
|
|
|
88883
|
+
// src/akb-version.ts
|
|
88884
|
+
import { execFile } from "node:child_process";
|
|
88885
|
+
import fs15 from "node:fs";
|
|
88886
|
+
import path18 from "node:path";
|
|
88887
|
+
|
|
88888
|
+
// src/akb.ts
|
|
88889
|
+
import { spawn as spawn3 } from "node:child_process";
|
|
88890
|
+
import fs11 from "node:fs";
|
|
88891
|
+
import path14 from "node:path";
|
|
88892
|
+
import { fileURLToPath } from "node:url";
|
|
88893
|
+
var akbHome = () => path14.join(runnerHome(), "bin", "akb");
|
|
88894
|
+
var BUNDLED_SHIM = `bundled-${AKB_VERSION}`;
|
|
88895
|
+
var bundledAkb = () => ({
|
|
88896
|
+
command: process.execPath,
|
|
88897
|
+
args: [path14.join(path14.dirname(fileURLToPath(import.meta.url)), "akb", "bin", "ai4kanban.mjs")],
|
|
88898
|
+
version: AKB_VERSION,
|
|
88899
|
+
shim: path14.join(akbHome(), BUNDLED_SHIM)
|
|
88900
|
+
});
|
|
88901
|
+
var quote = (s) => /^[\w./:@=-]+$/.test(s) ? s : `"${s}"`;
|
|
88902
|
+
function shimDir(akb) {
|
|
88903
|
+
const dir = akb.shim;
|
|
88904
|
+
const line = [akb.command, ...akb.args].map(quote).join(" ");
|
|
88905
|
+
const [file2, text3] = process.platform === "win32" ? [path14.join(dir, "akb.cmd"), `@${line} %*\r
|
|
88906
|
+
`] : [path14.join(dir, "akb"), `#!/bin/sh
|
|
88907
|
+
exec ${line} "$@"
|
|
88908
|
+
`];
|
|
88909
|
+
try {
|
|
88910
|
+
if (fs11.readFileSync(file2, "utf8") === text3) return dir;
|
|
88911
|
+
} catch {
|
|
88912
|
+
}
|
|
88913
|
+
fs11.mkdirSync(dir, { recursive: true });
|
|
88914
|
+
fs11.writeFileSync(file2, text3, { mode: 493 });
|
|
88915
|
+
return dir;
|
|
88916
|
+
}
|
|
88917
|
+
function akbEnv(akb, board, task, line) {
|
|
88918
|
+
const env2 = {};
|
|
88919
|
+
const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
|
|
88920
|
+
for (const [k, v2] of Object.entries(process.env)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
|
|
88921
|
+
const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
88922
|
+
env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path14.delimiter);
|
|
88923
|
+
env2.AI4KANBAN_COMMAND = "akb";
|
|
88924
|
+
if (board) env2.AI4KANBAN_BOARD = board;
|
|
88925
|
+
if (task) env2.AI4KANBAN_TASK = task;
|
|
88926
|
+
if (line !== void 0) env2[LANGUAGE_LINE_ENV] = line;
|
|
88927
|
+
return env2;
|
|
88928
|
+
}
|
|
88929
|
+
var KEEP = 256 * 1024;
|
|
88930
|
+
function runAkb(akb, args, opts) {
|
|
88931
|
+
return new Promise((resolve2) => {
|
|
88932
|
+
let out = "";
|
|
88933
|
+
let last2 = "";
|
|
88934
|
+
const note = (text3) => {
|
|
88935
|
+
const line = text3.split("\n").map((l2) => l2.trim()).filter(Boolean).at(-1);
|
|
88936
|
+
if (line) last2 = line;
|
|
88937
|
+
};
|
|
88938
|
+
let child;
|
|
88939
|
+
try {
|
|
88940
|
+
child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: { ...akbEnv(akb, opts.board, opts.task, opts.line), ...opts.env }, stdio: ["ignore", "pipe", "pipe"] });
|
|
88941
|
+
} catch (e2) {
|
|
88942
|
+
return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
|
|
88943
|
+
}
|
|
88944
|
+
opts.track?.(child);
|
|
88945
|
+
child.stdout.setEncoding("utf8");
|
|
88946
|
+
child.stderr.setEncoding("utf8");
|
|
88947
|
+
child.stdout.on("data", (chunk) => {
|
|
88948
|
+
out = (out + chunk).slice(-KEEP);
|
|
88949
|
+
note(chunk);
|
|
88950
|
+
opts.show?.(chunk);
|
|
88951
|
+
});
|
|
88952
|
+
child.stderr.on("data", (chunk) => {
|
|
88953
|
+
note(chunk);
|
|
88954
|
+
opts.show?.(chunk);
|
|
88955
|
+
});
|
|
88956
|
+
child.on("error", (e2) => resolve2({ code: null, out, last: e2.message }));
|
|
88957
|
+
child.on("close", (code) => resolve2({ code, out, last: last2 }));
|
|
88958
|
+
});
|
|
88959
|
+
}
|
|
88960
|
+
function answerOf2(ran) {
|
|
88961
|
+
const line = ran.out.trim().split("\n").at(-1) ?? "";
|
|
88962
|
+
try {
|
|
88963
|
+
return JSON.parse(line);
|
|
88964
|
+
} catch {
|
|
88965
|
+
return null;
|
|
88966
|
+
}
|
|
88967
|
+
}
|
|
88968
|
+
|
|
89039
88969
|
// src/cache.ts
|
|
89040
88970
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
89041
|
-
import
|
|
89042
|
-
import
|
|
88971
|
+
import fs13 from "node:fs";
|
|
88972
|
+
import path16 from "node:path";
|
|
89043
88973
|
|
|
89044
88974
|
// src/folders.ts
|
|
89045
|
-
import
|
|
88975
|
+
import fs12 from "node:fs";
|
|
89046
88976
|
import os5 from "node:os";
|
|
89047
|
-
import
|
|
89048
|
-
var projectsFile = () =>
|
|
88977
|
+
import path15 from "node:path";
|
|
88978
|
+
var projectsFile = () => path15.join(runnerHome(), "projects.json");
|
|
89049
88979
|
function realpath(p2) {
|
|
89050
88980
|
try {
|
|
89051
|
-
return
|
|
88981
|
+
return fs12.realpathSync(p2);
|
|
89052
88982
|
} catch {
|
|
89053
88983
|
return null;
|
|
89054
88984
|
}
|
|
89055
88985
|
}
|
|
89056
88986
|
function readList() {
|
|
89057
88987
|
try {
|
|
89058
|
-
const
|
|
89059
|
-
return Array.isArray(
|
|
88988
|
+
const held4 = JSON.parse(fs12.readFileSync(projectsFile(), "utf8"));
|
|
88989
|
+
return Array.isArray(held4.projects) ? held4.projects.filter((p2) => typeof p2 === "string") : [];
|
|
89060
88990
|
} catch {
|
|
89061
88991
|
return [];
|
|
89062
88992
|
}
|
|
89063
88993
|
}
|
|
89064
88994
|
function writeList(list) {
|
|
89065
|
-
|
|
89066
|
-
|
|
88995
|
+
fs12.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
|
|
88996
|
+
fs12.writeFileSync(projectsFile(), `${JSON.stringify({ projects: [...new Set(list)] }, null, 2)}
|
|
89067
88997
|
`);
|
|
89068
88998
|
}
|
|
89069
88999
|
function allowedProjects() {
|
|
@@ -89087,7 +89017,7 @@ var SYSTEM_WIN = ["Windows", "Program Files", "Program Files (x86)", "ProgramDat
|
|
|
89087
89017
|
var here = () => ({ platform: process.platform, home: os5.homedir(), resolve: realpath });
|
|
89088
89018
|
function refusal(picked, where = here()) {
|
|
89089
89019
|
const win = where.platform === "win32";
|
|
89090
|
-
const p2 = win ?
|
|
89020
|
+
const p2 = win ? path15.win32 : path15.posix;
|
|
89091
89021
|
const real = where.resolve(picked);
|
|
89092
89022
|
if (!real || !p2.isAbsolute(real)) return "missing";
|
|
89093
89023
|
const norm = (d2) => {
|
|
@@ -89113,40 +89043,40 @@ function refusal(picked, where = here()) {
|
|
|
89113
89043
|
var IDLE_MS = 7 * 24 * 60 * 6e4;
|
|
89114
89044
|
var SWEEP_MS = 24 * 60 * 6e4;
|
|
89115
89045
|
var PROJECT_ID = /^[\w-]{1,100}$/;
|
|
89116
|
-
var cacheRoot = () =>
|
|
89046
|
+
var cacheRoot = () => path16.join(runnerHome(), "cache");
|
|
89117
89047
|
function cacheDir(project) {
|
|
89118
89048
|
if (!PROJECT_ID.test(project)) throw new Error("This job names no project.");
|
|
89119
|
-
return
|
|
89049
|
+
return path16.join(cacheRoot(), project);
|
|
89120
89050
|
}
|
|
89121
|
-
var akbDir = (dir) =>
|
|
89122
|
-
var usedFile = (dir) =>
|
|
89123
|
-
var unsentFile = (dir) =>
|
|
89051
|
+
var akbDir = (dir) => path16.join(dir, ".akb");
|
|
89052
|
+
var usedFile = (dir) => path16.join(akbDir(dir), "used.json");
|
|
89053
|
+
var unsentFile = (dir) => path16.join(akbDir(dir), "unsent");
|
|
89124
89054
|
function markUsed(dir, at2 = Date.now()) {
|
|
89125
|
-
|
|
89126
|
-
|
|
89055
|
+
fs13.mkdirSync(akbDir(dir), { recursive: true });
|
|
89056
|
+
fs13.writeFileSync(usedFile(dir), `${JSON.stringify({ at: at2 })}
|
|
89127
89057
|
`);
|
|
89128
89058
|
}
|
|
89129
89059
|
function usedAt(dir) {
|
|
89130
89060
|
try {
|
|
89131
|
-
const at2 = JSON.parse(
|
|
89061
|
+
const at2 = JSON.parse(fs13.readFileSync(usedFile(dir), "utf8")).at;
|
|
89132
89062
|
return typeof at2 === "number" ? at2 : null;
|
|
89133
89063
|
} catch {
|
|
89134
89064
|
return null;
|
|
89135
89065
|
}
|
|
89136
89066
|
}
|
|
89137
|
-
var unsent = (dir) =>
|
|
89067
|
+
var unsent = (dir) => fs13.existsSync(unsentFile(dir));
|
|
89138
89068
|
function markUnsent(dir, unsent2) {
|
|
89139
|
-
if (!unsent2) return void
|
|
89140
|
-
|
|
89141
|
-
|
|
89069
|
+
if (!unsent2) return void fs13.rmSync(unsentFile(dir), { force: true });
|
|
89070
|
+
fs13.mkdirSync(akbDir(dir), { recursive: true });
|
|
89071
|
+
fs13.writeFileSync(unsentFile(dir), "");
|
|
89142
89072
|
}
|
|
89143
89073
|
var holds = /* @__PURE__ */ new Map();
|
|
89144
89074
|
function hold(dir) {
|
|
89145
89075
|
holds.set(dir, (holds.get(dir) ?? 0) + 1);
|
|
89146
|
-
let
|
|
89076
|
+
let held4 = true;
|
|
89147
89077
|
return () => {
|
|
89148
|
-
if (!
|
|
89149
|
-
|
|
89078
|
+
if (!held4) return;
|
|
89079
|
+
held4 = false;
|
|
89150
89080
|
const left = holds.get(dir) - 1;
|
|
89151
89081
|
if (left) holds.set(dir, left);
|
|
89152
89082
|
else holds.delete(dir);
|
|
@@ -89154,9 +89084,9 @@ function hold(dir) {
|
|
|
89154
89084
|
}
|
|
89155
89085
|
function paused(dir) {
|
|
89156
89086
|
try {
|
|
89157
|
-
const file2 =
|
|
89158
|
-
const
|
|
89159
|
-
return (
|
|
89087
|
+
const file2 = path16.join(projectStateDir(path16.join(akbDir(dir), "kanban")), SESSIONS_FILE);
|
|
89088
|
+
const held4 = JSON.parse(fs13.readFileSync(file2, "utf8"));
|
|
89089
|
+
return (held4.deliveries ?? []).some((d2) => d2.status === "active");
|
|
89160
89090
|
} catch {
|
|
89161
89091
|
return false;
|
|
89162
89092
|
}
|
|
@@ -89168,11 +89098,11 @@ function clearAkb(dir) {
|
|
|
89168
89098
|
if (kept2(dir)) return false;
|
|
89169
89099
|
let entries;
|
|
89170
89100
|
try {
|
|
89171
|
-
entries =
|
|
89101
|
+
entries = fs13.readdirSync(akbDir(dir));
|
|
89172
89102
|
} catch {
|
|
89173
89103
|
return true;
|
|
89174
89104
|
}
|
|
89175
|
-
for (const name of entries)
|
|
89105
|
+
for (const name of entries) fs13.rmSync(path16.join(akbDir(dir), name), { recursive: true, force: true });
|
|
89176
89106
|
spawnSync3("git", ["-C", dir, "worktree", "prune"], { stdio: "ignore" });
|
|
89177
89107
|
return true;
|
|
89178
89108
|
}
|
|
@@ -89187,7 +89117,7 @@ async function readAccess(machineId2) {
|
|
|
89187
89117
|
}
|
|
89188
89118
|
function realpath2(p2) {
|
|
89189
89119
|
try {
|
|
89190
|
-
return
|
|
89120
|
+
return fs13.realpathSync(p2);
|
|
89191
89121
|
} catch {
|
|
89192
89122
|
return p2;
|
|
89193
89123
|
}
|
|
@@ -89202,25 +89132,25 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89202
89132
|
const swept = [];
|
|
89203
89133
|
let cached2 = [];
|
|
89204
89134
|
try {
|
|
89205
|
-
cached2 =
|
|
89135
|
+
cached2 = fs13.readdirSync(cacheRoot(), { withFileTypes: true });
|
|
89206
89136
|
} catch {
|
|
89207
89137
|
}
|
|
89208
89138
|
for (const e2 of cached2) {
|
|
89209
|
-
const dir =
|
|
89139
|
+
const dir = path16.join(cacheRoot(), e2.name);
|
|
89210
89140
|
if (!e2.isDirectory() || kept2(dir)) continue;
|
|
89211
89141
|
const gone = access && !access.projects.has(e2.name);
|
|
89212
89142
|
if (idle(dir, now) || gone) {
|
|
89213
|
-
|
|
89143
|
+
fs13.rmSync(dir, { recursive: true, force: true });
|
|
89214
89144
|
swept.push(dir);
|
|
89215
89145
|
}
|
|
89216
89146
|
}
|
|
89217
89147
|
for (const dir of allowedProjects()) {
|
|
89218
|
-
let
|
|
89148
|
+
let held4 = [];
|
|
89219
89149
|
try {
|
|
89220
|
-
|
|
89150
|
+
held4 = fs13.readdirSync(akbDir(dir));
|
|
89221
89151
|
} catch {
|
|
89222
89152
|
}
|
|
89223
|
-
if (!
|
|
89153
|
+
if (!held4.length) continue;
|
|
89224
89154
|
const gone = access && !access.folders.has(dir);
|
|
89225
89155
|
if ((idle(dir, now) || gone) && clearAkb(dir)) swept.push(dir);
|
|
89226
89156
|
}
|
|
@@ -89228,24 +89158,231 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89228
89158
|
}
|
|
89229
89159
|
function removeLegacy() {
|
|
89230
89160
|
const home4 = runnerHome();
|
|
89231
|
-
for (const name of ["boards", "akb-bin"])
|
|
89161
|
+
for (const name of ["boards", "akb-bin"]) fs13.rmSync(path16.join(home4, name), { recursive: true, force: true });
|
|
89232
89162
|
let entries = [];
|
|
89233
89163
|
try {
|
|
89234
|
-
entries =
|
|
89164
|
+
entries = fs13.readdirSync(home4, { withFileTypes: true });
|
|
89235
89165
|
} catch {
|
|
89236
89166
|
return;
|
|
89237
89167
|
}
|
|
89238
89168
|
for (const e2 of entries) {
|
|
89239
|
-
const account =
|
|
89240
|
-
if (!e2.isDirectory() || !
|
|
89241
|
-
|
|
89242
|
-
if (!
|
|
89169
|
+
const account = path16.join(home4, e2.name);
|
|
89170
|
+
if (!e2.isDirectory() || !fs13.existsSync(path16.join(account, "unfiled"))) continue;
|
|
89171
|
+
fs13.rmSync(path16.join(account, "unfiled"), { recursive: true, force: true });
|
|
89172
|
+
if (!fs13.readdirSync(account).length) fs13.rmdirSync(account);
|
|
89243
89173
|
}
|
|
89244
89174
|
}
|
|
89245
89175
|
|
|
89246
|
-
// src/
|
|
89176
|
+
// src/update.ts
|
|
89177
|
+
import crypto2 from "node:crypto";
|
|
89247
89178
|
import fs14 from "node:fs";
|
|
89248
89179
|
import path17 from "node:path";
|
|
89180
|
+
import zlib from "node:zlib";
|
|
89181
|
+
var TIMEOUT_MS2 = 6e4;
|
|
89182
|
+
var registry = () => (process.env.npm_config_registry || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
89183
|
+
async function installPackage(pkg, version, nodeVersion = process.versions.node) {
|
|
89184
|
+
const dir = pkg.dirOf(version);
|
|
89185
|
+
if (fs14.existsSync(pkg.entryOf(dir))) return { ok: true, dir };
|
|
89186
|
+
let meta;
|
|
89187
|
+
let tarball;
|
|
89188
|
+
try {
|
|
89189
|
+
const answer = await fetch(`${registry()}/${pkg.name}/${encodeURIComponent(version)}`, { signal: AbortSignal.timeout(TIMEOUT_MS2) });
|
|
89190
|
+
if (!answer.ok) return { ok: false, why: "unreachable", detail: `registry answered ${answer.status}` };
|
|
89191
|
+
meta = await answer.json();
|
|
89192
|
+
const range = meta.engines?.node;
|
|
89193
|
+
if (range && !satisfies(nodeVersion, range)) return { ok: false, why: "node", detail: range };
|
|
89194
|
+
if (!meta.dist?.tarball) return { ok: false, why: "unreachable", detail: "no tarball" };
|
|
89195
|
+
const download2 = await fetch(meta.dist.tarball, { signal: AbortSignal.timeout(TIMEOUT_MS2) });
|
|
89196
|
+
if (!download2.ok) return { ok: false, why: "unreachable", detail: `download answered ${download2.status}` };
|
|
89197
|
+
tarball = Buffer.from(await download2.arrayBuffer());
|
|
89198
|
+
} catch (e2) {
|
|
89199
|
+
return { ok: false, why: "unreachable", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89200
|
+
}
|
|
89201
|
+
const expected = /^sha512-(.+)$/.exec(meta.dist.integrity ?? "")?.[1];
|
|
89202
|
+
const actual = crypto2.createHash("sha512").update(tarball).digest("base64");
|
|
89203
|
+
if (!expected || expected !== actual) return { ok: false, why: "integrity", detail: "sha512 mismatch" };
|
|
89204
|
+
const staging = `${dir}.${process.pid}.tmp`;
|
|
89205
|
+
try {
|
|
89206
|
+
fs14.rmSync(staging, { recursive: true, force: true });
|
|
89207
|
+
extract(zlib.gunzipSync(tarball), staging);
|
|
89208
|
+
if (!fs14.existsSync(pkg.entryOf(staging))) throw new Error(`the package carries no ${path17.relative(staging, pkg.entryOf(staging))}`);
|
|
89209
|
+
fs14.rmSync(dir, { recursive: true, force: true });
|
|
89210
|
+
fs14.renameSync(staging, dir);
|
|
89211
|
+
} catch (e2) {
|
|
89212
|
+
fs14.rmSync(staging, { recursive: true, force: true });
|
|
89213
|
+
return { ok: false, why: "integrity", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89214
|
+
}
|
|
89215
|
+
return { ok: true, dir };
|
|
89216
|
+
}
|
|
89217
|
+
function extract(tar, into) {
|
|
89218
|
+
let offset = 0;
|
|
89219
|
+
let longName = null;
|
|
89220
|
+
while (offset + 512 <= tar.length) {
|
|
89221
|
+
const header = tar.subarray(offset, offset + 512);
|
|
89222
|
+
if (header.every((b2) => b2 === 0)) break;
|
|
89223
|
+
const field = (start, length) => header.subarray(start, start + length).toString("utf8").replace(/\0.*$/s, "");
|
|
89224
|
+
const size = parseInt(field(124, 12).trim() || "0", 8);
|
|
89225
|
+
const type = field(156, 1) || "0";
|
|
89226
|
+
const body = tar.subarray(offset + 512, offset + 512 + size);
|
|
89227
|
+
offset += 512 + Math.ceil(size / 512) * 512;
|
|
89228
|
+
if (type === "x") {
|
|
89229
|
+
longName = /(?:^|\n)\d+ path=([^\n]*)\n/.exec(body.toString("utf8"))?.[1] ?? null;
|
|
89230
|
+
continue;
|
|
89231
|
+
}
|
|
89232
|
+
if (type === "L") {
|
|
89233
|
+
longName = body.toString("utf8").replace(/\0.*$/s, "");
|
|
89234
|
+
continue;
|
|
89235
|
+
}
|
|
89236
|
+
const prefix = field(345, 155);
|
|
89237
|
+
const name = longName ?? (prefix ? `${prefix}/${field(0, 100)}` : field(0, 100));
|
|
89238
|
+
longName = null;
|
|
89239
|
+
if (type !== "0" && type !== "5") continue;
|
|
89240
|
+
const relative = name.replace(/^[^/]+\//, "");
|
|
89241
|
+
if (!relative) continue;
|
|
89242
|
+
const target = path17.resolve(into, relative);
|
|
89243
|
+
if (!target.startsWith(path17.resolve(into) + path17.sep)) throw new Error(`refusing ${name}`);
|
|
89244
|
+
if (type === "5") fs14.mkdirSync(target, { recursive: true });
|
|
89245
|
+
else {
|
|
89246
|
+
fs14.mkdirSync(path17.dirname(target), { recursive: true });
|
|
89247
|
+
fs14.writeFileSync(target, body);
|
|
89248
|
+
}
|
|
89249
|
+
}
|
|
89250
|
+
}
|
|
89251
|
+
var parse = (v2) => {
|
|
89252
|
+
const m = /^v?(\d+)(?:\.(\d+|x|\*))?(?:\.(\d+|x|\*))?/.exec(v2.trim());
|
|
89253
|
+
return m ? [Number(m[1]), Number(m[2]) || 0, Number(m[3]) || 0] : null;
|
|
89254
|
+
};
|
|
89255
|
+
function compare(a3, b2) {
|
|
89256
|
+
const [x2, y2] = [parse(a3) ?? [0, 0, 0], parse(b2) ?? [0, 0, 0]];
|
|
89257
|
+
for (let i = 0; i < 3; i++) if (x2[i] !== y2[i]) return x2[i] - y2[i];
|
|
89258
|
+
return 0;
|
|
89259
|
+
}
|
|
89260
|
+
function satisfies(version, range) {
|
|
89261
|
+
return range.split("||").some((alternative) => {
|
|
89262
|
+
const parts = alternative.trim().split(/\s+/).filter(Boolean);
|
|
89263
|
+
return parts.length > 0 && parts.every((part) => meets(version, part));
|
|
89264
|
+
});
|
|
89265
|
+
}
|
|
89266
|
+
function meets(version, comparator) {
|
|
89267
|
+
const m = /^(>=|<=|>|<|=|\^|~)?\s*(.+)$/.exec(comparator);
|
|
89268
|
+
const bound = m && parse(m[2]);
|
|
89269
|
+
if (!m || !bound) return false;
|
|
89270
|
+
const v2 = parse(version);
|
|
89271
|
+
const c2 = compare(version, m[2]);
|
|
89272
|
+
switch (m[1]) {
|
|
89273
|
+
case ">=":
|
|
89274
|
+
return c2 >= 0;
|
|
89275
|
+
case ">":
|
|
89276
|
+
return c2 > 0;
|
|
89277
|
+
case "<=":
|
|
89278
|
+
return c2 <= 0;
|
|
89279
|
+
case "<":
|
|
89280
|
+
return c2 < 0;
|
|
89281
|
+
case "^":
|
|
89282
|
+
return c2 >= 0 && v2[0] === bound[0];
|
|
89283
|
+
case "~":
|
|
89284
|
+
return c2 >= 0 && v2[0] === bound[0] && v2[1] === bound[1];
|
|
89285
|
+
default: {
|
|
89286
|
+
const given = m[2].split(".").filter((p2) => /^\d+$/.test(p2)).length;
|
|
89287
|
+
return [0, 1, 2].slice(0, given).every((i) => v2[i] === bound[i]);
|
|
89288
|
+
}
|
|
89289
|
+
}
|
|
89290
|
+
}
|
|
89291
|
+
|
|
89292
|
+
// src/akb-version.ts
|
|
89293
|
+
var CHECK_MS2 = 1e4;
|
|
89294
|
+
var VERSION2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
89295
|
+
var stateFile = () => path18.join(akbHome(), "state.json");
|
|
89296
|
+
var akbVersionDir = (version) => path18.join(akbHome(), version);
|
|
89297
|
+
var entryOf = (dir) => path18.join(dir, "bin", "ai4kanban.mjs");
|
|
89298
|
+
var AKB = { name: "wildcrane", dirOf: akbVersionDir, entryOf };
|
|
89299
|
+
function readAkbState() {
|
|
89300
|
+
try {
|
|
89301
|
+
const held4 = JSON.parse(fs15.readFileSync(stateFile(), "utf8"));
|
|
89302
|
+
return { current: held4.current ?? null, bad: held4.bad ?? [] };
|
|
89303
|
+
} catch {
|
|
89304
|
+
return { current: null, bad: [] };
|
|
89305
|
+
}
|
|
89306
|
+
}
|
|
89307
|
+
function writeAkbState(state) {
|
|
89308
|
+
fs15.mkdirSync(akbHome(), { recursive: true });
|
|
89309
|
+
const staging = `${stateFile()}.${process.pid}.tmp`;
|
|
89310
|
+
fs15.writeFileSync(staging, `${JSON.stringify(state, null, 2)}
|
|
89311
|
+
`);
|
|
89312
|
+
fs15.renameSync(staging, stateFile());
|
|
89313
|
+
}
|
|
89314
|
+
function contractOf(dir) {
|
|
89315
|
+
try {
|
|
89316
|
+
return JSON.parse(fs15.readFileSync(path18.join(dir, "package.json"), "utf8")).akbContract ?? null;
|
|
89317
|
+
} catch {
|
|
89318
|
+
return null;
|
|
89319
|
+
}
|
|
89320
|
+
}
|
|
89321
|
+
var usable = (dir) => fs15.existsSync(entryOf(dir)) && contractOf(dir) === AKB_CONTRACT;
|
|
89322
|
+
function currentAkb() {
|
|
89323
|
+
const { current } = readAkbState();
|
|
89324
|
+
if (!current) return bundledAkb();
|
|
89325
|
+
const dir = akbVersionDir(current);
|
|
89326
|
+
if (!usable(dir)) return bundledAkb();
|
|
89327
|
+
try {
|
|
89328
|
+
const now = /* @__PURE__ */ new Date();
|
|
89329
|
+
fs15.utimesSync(dir, now, now);
|
|
89330
|
+
} catch {
|
|
89331
|
+
}
|
|
89332
|
+
return { command: process.execPath, args: [entryOf(dir)], version: current, shim: path18.join(dir, "shim") };
|
|
89333
|
+
}
|
|
89334
|
+
var answers2 = (dir, version) => new Promise((resolve2) => {
|
|
89335
|
+
execFile(process.execPath, [entryOf(dir), "--version"], { timeout: CHECK_MS2, killSignal: "SIGKILL" }, (error, stdout) => resolve2(!error && stdout.trim().split(/\s+/).at(-1) === version));
|
|
89336
|
+
});
|
|
89337
|
+
var wanted = null;
|
|
89338
|
+
var fetching = false;
|
|
89339
|
+
function useVersion(current) {
|
|
89340
|
+
const state = readAkbState();
|
|
89341
|
+
if (state.current !== current) writeAkbState({ ...state, current });
|
|
89342
|
+
}
|
|
89343
|
+
async function fetchVersion(version) {
|
|
89344
|
+
const got = await installPackage(AKB, version);
|
|
89345
|
+
if (!got.ok) return console.error(`runner: akb ${version} was not fetched: ${got.detail}`);
|
|
89346
|
+
if (contractOf(got.dir) !== AKB_CONTRACT || !await answers2(got.dir, version)) {
|
|
89347
|
+
console.error(`runner: akb ${version} failed its check and will not be used`);
|
|
89348
|
+
const state = readAkbState();
|
|
89349
|
+
return writeAkbState({ ...state, bad: [.../* @__PURE__ */ new Set([...state.bad, version])] });
|
|
89350
|
+
}
|
|
89351
|
+
if (wanted === version) useVersion(version);
|
|
89352
|
+
}
|
|
89353
|
+
async function followAkb(named2) {
|
|
89354
|
+
if (!named2) return;
|
|
89355
|
+
const { version } = named2;
|
|
89356
|
+
try {
|
|
89357
|
+
if (version !== null && !VERSION2.test(version)) return;
|
|
89358
|
+
wanted = version;
|
|
89359
|
+
if (version === null || version === AKB_VERSION) return useVersion(null);
|
|
89360
|
+
const state = readAkbState();
|
|
89361
|
+
if (fetching || state.bad.includes(version) || state.current === version && usable(akbVersionDir(version))) return;
|
|
89362
|
+
fetching = true;
|
|
89363
|
+
await fetchVersion(version).finally(() => fetching = false);
|
|
89364
|
+
} catch (e2) {
|
|
89365
|
+
console.error(`runner: the akb version was not followed: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
89366
|
+
}
|
|
89367
|
+
}
|
|
89368
|
+
function sweepAkb(now = Date.now()) {
|
|
89369
|
+
const { current } = readAkbState();
|
|
89370
|
+
let entries = [];
|
|
89371
|
+
try {
|
|
89372
|
+
entries = fs15.readdirSync(akbHome(), { withFileTypes: true });
|
|
89373
|
+
} catch {
|
|
89374
|
+
return;
|
|
89375
|
+
}
|
|
89376
|
+
for (const e2 of entries) {
|
|
89377
|
+
if (!e2.isDirectory() || e2.name === current || e2.name === BUNDLED_SHIM) continue;
|
|
89378
|
+
const dir = path18.join(akbHome(), e2.name);
|
|
89379
|
+
if (now - fs15.statSync(dir).mtimeMs > IDLE_MS) fs15.rmSync(dir, { recursive: true, force: true });
|
|
89380
|
+
}
|
|
89381
|
+
}
|
|
89382
|
+
|
|
89383
|
+
// src/chats.ts
|
|
89384
|
+
import fs17 from "node:fs";
|
|
89385
|
+
import path20 from "node:path";
|
|
89249
89386
|
|
|
89250
89387
|
// ../cloud/src/config.ts
|
|
89251
89388
|
var CLAIM_LEASE_SECONDS = 15 * 60;
|
|
@@ -89261,18 +89398,18 @@ var CONTACT_ATTEMPT_WINDOW_SECONDS = 60 * 60;
|
|
|
89261
89398
|
var CHAT_KEEP_DAYS = 30;
|
|
89262
89399
|
|
|
89263
89400
|
// ../cli/src/lib/agent/task-chats.ts
|
|
89264
|
-
import
|
|
89265
|
-
import
|
|
89401
|
+
import fs16 from "node:fs";
|
|
89402
|
+
import path19 from "node:path";
|
|
89266
89403
|
var TASK = /^[\w-]{1,100}$/;
|
|
89267
|
-
var taskChatsDir = (home4 = machineHome()) =>
|
|
89404
|
+
var taskChatsDir = (home4 = machineHome()) => path19.join(home4, "chats");
|
|
89268
89405
|
function taskChatFile(task, home4) {
|
|
89269
89406
|
if (!TASK.test(task)) throw new Error(`${task} is not a task id.`);
|
|
89270
|
-
return
|
|
89407
|
+
return path19.join(taskChatsDir(home4), `${task}.jsonl`);
|
|
89271
89408
|
}
|
|
89272
89409
|
function readTaskChat(task, home4) {
|
|
89273
89410
|
let text3;
|
|
89274
89411
|
try {
|
|
89275
|
-
text3 =
|
|
89412
|
+
text3 = fs16.readFileSync(taskChatFile(task, home4), "utf8");
|
|
89276
89413
|
} catch {
|
|
89277
89414
|
return [];
|
|
89278
89415
|
}
|
|
@@ -89293,18 +89430,18 @@ var DAY_MS = 24 * 60 * 6e4;
|
|
|
89293
89430
|
var REVIEW_EVERY_MS = DAY_MS;
|
|
89294
89431
|
var KEEP_MS2 = CHAT_KEEP_DAYS * DAY_MS;
|
|
89295
89432
|
var home3 = () => runnerHome();
|
|
89296
|
-
var reviewedFile = () =>
|
|
89433
|
+
var reviewedFile = () => path20.join(taskChatsDir(home3()), "reviewed.json");
|
|
89297
89434
|
function readReviewed() {
|
|
89298
89435
|
try {
|
|
89299
|
-
const
|
|
89300
|
-
return { checkedAt: Number(
|
|
89436
|
+
const held4 = JSON.parse(fs17.readFileSync(reviewedFile(), "utf8"));
|
|
89437
|
+
return { checkedAt: Number(held4.checkedAt) || 0, tasks: held4.tasks ?? {} };
|
|
89301
89438
|
} catch {
|
|
89302
89439
|
return { checkedAt: 0, tasks: {} };
|
|
89303
89440
|
}
|
|
89304
89441
|
}
|
|
89305
89442
|
function writeReviewed(reviewed) {
|
|
89306
|
-
|
|
89307
|
-
|
|
89443
|
+
fs17.mkdirSync(path20.dirname(reviewedFile()), { recursive: true });
|
|
89444
|
+
fs17.writeFileSync(reviewedFile(), `${JSON.stringify(reviewed, null, 2)}
|
|
89308
89445
|
`);
|
|
89309
89446
|
}
|
|
89310
89447
|
function keepChat(job, reply, at2 = Date.now()) {
|
|
@@ -89314,21 +89451,40 @@ function keepChat(job, reply, at2 = Date.now()) {
|
|
|
89314
89451
|
{ id: job.id, role: "agent", text: reply, at: at2, runtime: job.runtime, model: job.model ?? null }
|
|
89315
89452
|
];
|
|
89316
89453
|
const file2 = taskChatFile(job.task, home3());
|
|
89317
|
-
|
|
89318
|
-
|
|
89454
|
+
fs17.mkdirSync(path20.dirname(file2), { recursive: true });
|
|
89455
|
+
fs17.appendFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89319
89456
|
`).join(""));
|
|
89320
89457
|
}
|
|
89321
89458
|
function keepCloudChat(task, messages) {
|
|
89322
89459
|
const file2 = taskChatFile(task, home3());
|
|
89323
|
-
if (!messages.length) return
|
|
89460
|
+
if (!messages.length) return fs17.rmSync(file2, { force: true });
|
|
89324
89461
|
const lines = messages.map((m) => ({ id: m.id, role: m.role, text: m.body, at: Date.parse(m.created_at) || Date.now() }));
|
|
89325
|
-
|
|
89326
|
-
|
|
89462
|
+
fs17.mkdirSync(path20.dirname(file2), { recursive: true });
|
|
89463
|
+
fs17.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89464
|
+
`).join(""));
|
|
89465
|
+
}
|
|
89466
|
+
async function keepDecisions(task, read) {
|
|
89467
|
+
const comments = [];
|
|
89468
|
+
let after = null;
|
|
89469
|
+
do {
|
|
89470
|
+
const page = await read(task, after);
|
|
89471
|
+
if (!page.ok) return;
|
|
89472
|
+
for (const d2 of page.value.data) {
|
|
89473
|
+
if (d2.comment.trim()) comments.push({ id: d2.id, role: "user", text: d2.comment, at: Date.parse(d2.created_at) || Date.now() });
|
|
89474
|
+
}
|
|
89475
|
+
after = page.value.next;
|
|
89476
|
+
} while (after);
|
|
89477
|
+
if (!comments.length) return;
|
|
89478
|
+
const ids = new Set(comments.map((c2) => c2.id));
|
|
89479
|
+
const lines = [...readTaskChat(task, home3()).filter((l2) => !ids.has(l2.id)), ...comments].sort((a3, b2) => a3.at - b2.at);
|
|
89480
|
+
const file2 = taskChatFile(task, home3());
|
|
89481
|
+
fs17.mkdirSync(path20.dirname(file2), { recursive: true });
|
|
89482
|
+
fs17.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89327
89483
|
`).join(""));
|
|
89328
89484
|
}
|
|
89329
89485
|
var tasksKept = () => {
|
|
89330
89486
|
try {
|
|
89331
|
-
return
|
|
89487
|
+
return fs17.readdirSync(taskChatsDir(home3())).map((n) => /^([\w-]{1,100})\.jsonl$/.exec(n)?.[1]).filter((t2) => !!t2);
|
|
89332
89488
|
} catch {
|
|
89333
89489
|
return [];
|
|
89334
89490
|
}
|
|
@@ -89339,9 +89495,9 @@ function pruneChats(now = Date.now()) {
|
|
|
89339
89495
|
const kept4 = lines.filter((l2) => now - l2.at < KEEP_MS2);
|
|
89340
89496
|
if (kept4.length === lines.length) continue;
|
|
89341
89497
|
const file2 = taskChatFile(task, home3());
|
|
89342
|
-
if (kept4.length)
|
|
89498
|
+
if (kept4.length) fs17.writeFileSync(file2, kept4.map((l2) => `${JSON.stringify(l2)}
|
|
89343
89499
|
`).join(""));
|
|
89344
|
-
else
|
|
89500
|
+
else fs17.rmSync(file2, { force: true });
|
|
89345
89501
|
}
|
|
89346
89502
|
}
|
|
89347
89503
|
var lastOf = (task) => readTaskChat(task, home3()).at(-1);
|
|
@@ -89374,42 +89530,43 @@ async function reviewChats(machineId2, runtimes, now = Date.now()) {
|
|
|
89374
89530
|
if (!sent.ok) console.error(`runner: the chats of ${project} were not sent for review: ${sent.error}`);
|
|
89375
89531
|
}
|
|
89376
89532
|
const listed2 = new Set(owned.value.chats.map((c2) => c2.task));
|
|
89377
|
-
const
|
|
89378
|
-
writeReviewed({ checkedAt: now, tasks: Object.fromEntries(Object.entries(
|
|
89533
|
+
const held4 = readReviewed();
|
|
89534
|
+
writeReviewed({ checkedAt: now, tasks: Object.fromEntries(Object.entries(held4.tasks).filter(([t2]) => listed2.has(t2))) });
|
|
89379
89535
|
}
|
|
89380
89536
|
|
|
89381
89537
|
// src/board-watch.ts
|
|
89382
|
-
import
|
|
89383
|
-
import
|
|
89538
|
+
import fs21 from "node:fs";
|
|
89539
|
+
import path24 from "node:path";
|
|
89384
89540
|
|
|
89385
89541
|
// ../cloud/src/board-files.ts
|
|
89386
89542
|
var ROOTS = ["todo/", ".archive/", "memory/", "workflows/", "triage/", "assets/", "rules/"];
|
|
89387
89543
|
var SETTINGS = ["modules.md", "config.md"];
|
|
89388
|
-
var isSettingsPath = (
|
|
89544
|
+
var isSettingsPath = (path34) => SETTINGS.includes(path34) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path34);
|
|
89389
89545
|
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) =>
|
|
89546
|
+
function isBoardPath(path34) {
|
|
89547
|
+
if (!path34 || path34.length > 500 || path34.startsWith("/") || path34.includes("\\") || path34.includes("\0")) return false;
|
|
89548
|
+
if (path34.split("/").some((part) => !part || part === "." || part === "..")) return false;
|
|
89549
|
+
if (path34 === "todo/README.md" || path34.split("/").includes(".sync")) return false;
|
|
89550
|
+
if (path34.startsWith("workflows/")) return true;
|
|
89551
|
+
if (SETTINGS.includes(path34)) return true;
|
|
89552
|
+
if (path34.startsWith("rules/")) return isSettingsPath(path34);
|
|
89553
|
+
if (path34.startsWith("assets/")) return path34.endsWith(".json");
|
|
89554
|
+
return ROOTS.some((root) => path34.startsWith(root)) && path34.endsWith(".md");
|
|
89399
89555
|
}
|
|
89400
89556
|
var CARD = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]*\.md$/;
|
|
89401
89557
|
var ROOT = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]+\/root\.md$/;
|
|
89402
|
-
function numberOfCard(
|
|
89403
|
-
const n = ROOT.exec(
|
|
89558
|
+
function numberOfCard(path34) {
|
|
89559
|
+
const n = ROOT.exec(path34)?.[1] ?? CARD.exec(path34)?.[1];
|
|
89404
89560
|
return n ? Number(n) : null;
|
|
89405
89561
|
}
|
|
89406
89562
|
var cardSlug = (task) => task.toLowerCase().replace(/_/g, "-");
|
|
89407
89563
|
var assetsFile = (task) => `assets/${task}.json`;
|
|
89408
89564
|
var workflowFolder = (id) => id.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
89565
|
+
var OWN_FOLDER = /^wf-(?!builtin-)[a-z0-9-]+$/;
|
|
89409
89566
|
var workflowName = (id) => id.startsWith("wf_builtin_") ? id.slice("wf_builtin_".length).replace(/_/g, "-") : workflowFolder(id);
|
|
89410
89567
|
var BUILDER = "wf_builtin_workflow_builder";
|
|
89411
89568
|
var draftFolder = (task) => cardSlug(task);
|
|
89412
|
-
var
|
|
89569
|
+
var unquote = (value) => value.trim().replace(/^(["'])(.*)\1$/, "$2");
|
|
89413
89570
|
function cardFront(body) {
|
|
89414
89571
|
const match = /^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/.exec(body);
|
|
89415
89572
|
if (!match) return {};
|
|
@@ -89418,13 +89575,13 @@ function cardFront(body) {
|
|
|
89418
89575
|
const field = /^(title|status|phase|stages|previews):\s*(.*)$/.exec(line);
|
|
89419
89576
|
if (!field) continue;
|
|
89420
89577
|
const [, key, value = ""] = field;
|
|
89421
|
-
if (key === "title" && value.trim()) out.title =
|
|
89422
|
-
else if (key === "status" && value.trim()) out.status =
|
|
89578
|
+
if (key === "title" && value.trim()) out.title = unquote(value);
|
|
89579
|
+
else if (key === "status" && value.trim()) out.status = unquote(value);
|
|
89423
89580
|
else if (key === "phase" && Number.isInteger(Number(value)) && value.trim()) out.phase = Number(value);
|
|
89424
89581
|
else if (key === "stages" && Number.isInteger(Number(value)) && value.trim()) out.stages = Number(value);
|
|
89425
89582
|
else if (key === "previews") {
|
|
89426
89583
|
const flow = /^\[(.*)\]\s*$/.exec(value.trim());
|
|
89427
|
-
if (flow) out.previews = flow[1].split(",").map(
|
|
89584
|
+
if (flow) out.previews = flow[1].split(",").map(unquote).filter(Boolean);
|
|
89428
89585
|
}
|
|
89429
89586
|
}
|
|
89430
89587
|
return out;
|
|
@@ -89432,9 +89589,9 @@ function cardFront(body) {
|
|
|
89432
89589
|
|
|
89433
89590
|
// src/task-folder.ts
|
|
89434
89591
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
89435
|
-
import
|
|
89436
|
-
import
|
|
89437
|
-
import
|
|
89592
|
+
import crypto3 from "node:crypto";
|
|
89593
|
+
import fs20 from "node:fs";
|
|
89594
|
+
import path23 from "node:path";
|
|
89438
89595
|
|
|
89439
89596
|
// node_modules/node-diff3/dist/diff3.mjs
|
|
89440
89597
|
function LCS(buffer1, buffer2) {
|
|
@@ -89649,10 +89806,32 @@ function diff3Merge(a3, o2, b2, options) {
|
|
|
89649
89806
|
return results;
|
|
89650
89807
|
}
|
|
89651
89808
|
|
|
89809
|
+
// ../cli/src/lib/yaml.ts
|
|
89810
|
+
function yamlScalar(s) {
|
|
89811
|
+
const text3 = String(s);
|
|
89812
|
+
if (text3 === "") return '""';
|
|
89813
|
+
if (/^[-?:,[\]{}#&*!|>'"%@`]/.test(text3) || /:\s/.test(text3) || /[\n"]/.test(text3) || /^\s|\s$/.test(text3)) {
|
|
89814
|
+
return JSON.stringify(text3);
|
|
89815
|
+
}
|
|
89816
|
+
return text3;
|
|
89817
|
+
}
|
|
89818
|
+
function unquote2(v2) {
|
|
89819
|
+
const text3 = String(v2).trim();
|
|
89820
|
+
if (text3.startsWith('"') && text3.endsWith('"')) {
|
|
89821
|
+
try {
|
|
89822
|
+
return JSON.parse(text3);
|
|
89823
|
+
} catch {
|
|
89824
|
+
return text3.slice(1, -1);
|
|
89825
|
+
}
|
|
89826
|
+
}
|
|
89827
|
+
if (text3.startsWith("'") && text3.endsWith("'")) return text3.slice(1, -1);
|
|
89828
|
+
return text3;
|
|
89829
|
+
}
|
|
89830
|
+
|
|
89652
89831
|
// ../cloud/src/triage-files.ts
|
|
89653
89832
|
var ITEM = /^triage\/(?:(dismissed|archived)\/)?([^/]+)\.md$/;
|
|
89654
|
-
function itemAt(
|
|
89655
|
-
const m = ITEM.exec(
|
|
89833
|
+
function itemAt(path34) {
|
|
89834
|
+
const m = ITEM.exec(path34);
|
|
89656
89835
|
if (!m) return null;
|
|
89657
89836
|
return { state: m[1] === "dismissed" ? "dismissed" : m[1] === "archived" ? "carded" : "open", name: m[2] };
|
|
89658
89837
|
}
|
|
@@ -89669,8 +89848,8 @@ function stampItem(content, fields) {
|
|
|
89669
89848
|
}
|
|
89670
89849
|
|
|
89671
89850
|
// ../cli/src/lib/agents/shared-memory.ts
|
|
89672
|
-
import
|
|
89673
|
-
import
|
|
89851
|
+
import fs18 from "node:fs";
|
|
89852
|
+
import path21 from "node:path";
|
|
89674
89853
|
|
|
89675
89854
|
// ../cli/src/agents/api-designer/AGENT.md
|
|
89676
89855
|
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 +90307,7 @@ var music_default = "# Music\n\nScore the clone with new music that follows the
|
|
|
90128
90307
|
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
90308
|
|
|
90130
90309
|
// ../cli/src/agents/workflow-writer/AGENT.md
|
|
90131
|
-
var AGENT_default25 = "---\nname: workflow-writer\ndescription: Writes a
|
|
90310
|
+
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
90311
|
|
|
90133
90312
|
// ../cli/src/lib/agents/bundled.ts
|
|
90134
90313
|
var BUNDLED_AGENT_FILES = {
|
|
@@ -90238,8 +90417,8 @@ function readMap(lines, start, indent) {
|
|
|
90238
90417
|
}
|
|
90239
90418
|
function readScalar(value) {
|
|
90240
90419
|
const flow = value.match(/^\[(.*)\]$/);
|
|
90241
|
-
if (!flow) return
|
|
90242
|
-
return flow[1].split(",").map((item) =>
|
|
90420
|
+
if (!flow) return unquote2(value);
|
|
90421
|
+
return flow[1].split(",").map((item) => unquote2(item.trim())).filter(Boolean);
|
|
90243
90422
|
}
|
|
90244
90423
|
function readBlock(lines, start, parentIndent) {
|
|
90245
90424
|
if (start >= lines.length || lines[start].indent <= parentIndent) return ["", start];
|
|
@@ -90268,7 +90447,7 @@ function readList2(lines, start, indent) {
|
|
|
90268
90447
|
}
|
|
90269
90448
|
const item = {};
|
|
90270
90449
|
const inline = stripComment(match[2].trim());
|
|
90271
|
-
if (inline) item[match[1].trim()] =
|
|
90450
|
+
if (inline) item[match[1].trim()] = unquote2(inline);
|
|
90272
90451
|
else {
|
|
90273
90452
|
const [value, next2] = readBlock(lines, i, keyIndent);
|
|
90274
90453
|
item[match[1].trim()] = value;
|
|
@@ -90399,16 +90578,16 @@ function sharedMemory(board) {
|
|
|
90399
90578
|
const at2 = /^([^/]+)\/AGENT\.md$/.exec(key);
|
|
90400
90579
|
if (at2) take(at2[1], text3, true);
|
|
90401
90580
|
}
|
|
90402
|
-
const root =
|
|
90581
|
+
const root = path21.join(board, "agents");
|
|
90403
90582
|
let folders2 = [];
|
|
90404
90583
|
try {
|
|
90405
|
-
folders2 =
|
|
90584
|
+
folders2 = fs18.readdirSync(root, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !e2.name.startsWith(".")).map((e2) => e2.name);
|
|
90406
90585
|
} catch {
|
|
90407
90586
|
}
|
|
90408
90587
|
for (const folder of folders2.sort()) {
|
|
90409
90588
|
let text3 = null;
|
|
90410
90589
|
try {
|
|
90411
|
-
text3 =
|
|
90590
|
+
text3 = fs18.readFileSync(path21.join(root, folder, "AGENT.md"), "utf8");
|
|
90412
90591
|
} catch {
|
|
90413
90592
|
}
|
|
90414
90593
|
take(folder, text3, false);
|
|
@@ -90432,16 +90611,16 @@ function openTaskFolder(job, projectDir2) {
|
|
|
90432
90611
|
projectDir2 ??= openCached(job.project);
|
|
90433
90612
|
keepOutOfGit(projectDir2);
|
|
90434
90613
|
markUsed(projectDir2);
|
|
90435
|
-
const board =
|
|
90436
|
-
|
|
90614
|
+
const board = path23.join(projectDir2, ".akb", "kanban");
|
|
90615
|
+
fs20.mkdirSync(board, { recursive: true });
|
|
90437
90616
|
return { task, cloudTask: task, board, cwd: projectDir2, project: job.project, number: job.number ?? null, workflow: job.workflow ?? job.flow?.workflow ?? null };
|
|
90438
90617
|
}
|
|
90439
90618
|
function openAgentFolder(job, projectDir2) {
|
|
90440
90619
|
if (!job.project || !job.agent) throw new Error("This job names no project.");
|
|
90441
90620
|
keepOutOfGit(projectDir2);
|
|
90442
90621
|
markUsed(projectDir2);
|
|
90443
|
-
const board =
|
|
90444
|
-
|
|
90622
|
+
const board = path23.join(projectDir2, ".akb", "kanban");
|
|
90623
|
+
fs20.mkdirSync(board, { recursive: true });
|
|
90445
90624
|
return {
|
|
90446
90625
|
task: `agent-${safe(job.agent.workflow ? `${job.agent.workflow}-${job.agent.name}` : job.agent.name)}`,
|
|
90447
90626
|
cloudTask: job.agent.tasks?.[0]?.id ?? null,
|
|
@@ -90456,13 +90635,13 @@ function openDiscussionFolder(job, projectDir2) {
|
|
|
90456
90635
|
if (!job.project) throw new Error("This job names no project.");
|
|
90457
90636
|
keepOutOfGit(projectDir2);
|
|
90458
90637
|
markUsed(projectDir2);
|
|
90459
|
-
const board =
|
|
90460
|
-
|
|
90638
|
+
const board = path23.join(projectDir2, ".akb", "kanban");
|
|
90639
|
+
fs20.mkdirSync(board, { recursive: true });
|
|
90461
90640
|
return { task: "discussion", cloudTask: null, board, cwd: projectDir2, project: job.project, number: null, workflow: null };
|
|
90462
90641
|
}
|
|
90463
90642
|
var boardFolder = (ws) => ({ task: "board", cloudTask: null, board: ws.board, cwd: ws.cwd, project: ws.project, number: null, workflow: null });
|
|
90464
90643
|
function keptBoard(cwd) {
|
|
90465
|
-
const board =
|
|
90644
|
+
const board = path23.join(cwd, ".akb", "kanban");
|
|
90466
90645
|
const base = readBase({ cwd });
|
|
90467
90646
|
const project = base.project ?? /^projects\/([^/]+)\//.exec(Object.keys(base.files).find((p2) => p2.startsWith("projects/")) ?? "")?.[1];
|
|
90468
90647
|
return base.head_seq === null || !project ? null : boardFolder({ board, cwd, project });
|
|
@@ -90470,17 +90649,17 @@ function keptBoard(cwd) {
|
|
|
90470
90649
|
var turns = /* @__PURE__ */ new Map();
|
|
90471
90650
|
function inFolder(dir, work) {
|
|
90472
90651
|
const next = (turns.get(dir) ?? Promise.resolve()).then(work, work);
|
|
90473
|
-
const
|
|
90652
|
+
const held4 = next.catch(() => {
|
|
90474
90653
|
});
|
|
90475
|
-
turns.set(dir,
|
|
90476
|
-
void
|
|
90654
|
+
turns.set(dir, held4);
|
|
90655
|
+
void held4.then(() => turns.get(dir) === held4 && turns.delete(dir));
|
|
90477
90656
|
return next;
|
|
90478
90657
|
}
|
|
90479
90658
|
var safe = (name) => name.replace(/[^\w.-]/g, "_") || "default";
|
|
90480
90659
|
function openCached(project) {
|
|
90481
90660
|
const dir = cacheDir(project);
|
|
90482
|
-
if (
|
|
90483
|
-
|
|
90661
|
+
if (fs20.existsSync(path23.join(dir, ".git"))) return dir;
|
|
90662
|
+
fs20.mkdirSync(dir, { recursive: true });
|
|
90484
90663
|
const git3 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" }).status === 0;
|
|
90485
90664
|
if (git3("init", "-q")) git3("-c", "user.name=WildCrane", "-c", "user.email=runner@wildcrane.ai", "commit", "-q", "--allow-empty", "-m", "general");
|
|
90486
90665
|
return dir;
|
|
@@ -90493,56 +90672,56 @@ function keepOutOfGit(dir, folders2 = SKILL_FOLDERS) {
|
|
|
90493
90672
|
if (inside.status !== 0) return;
|
|
90494
90673
|
const missing = [".akb/", ...folders2.map((f2) => `${f2}/`)].filter((p2) => git3("check-ignore", "-q", p2).status !== 0);
|
|
90495
90674
|
if (!missing.length) return;
|
|
90496
|
-
const exclude =
|
|
90497
|
-
|
|
90498
|
-
const
|
|
90499
|
-
|
|
90675
|
+
const exclude = path23.resolve(dir, inside.stdout.trim());
|
|
90676
|
+
fs20.mkdirSync(path23.dirname(exclude), { recursive: true });
|
|
90677
|
+
const held4 = fs20.existsSync(exclude) ? fs20.readFileSync(exclude, "utf8") : "";
|
|
90678
|
+
fs20.writeFileSync(exclude, `${held4}${held4 && !held4.endsWith("\n") ? "\n" : ""}${missing.join("\n")}
|
|
90500
90679
|
`);
|
|
90501
90680
|
}
|
|
90502
|
-
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ??
|
|
90681
|
+
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ?? path23.join(ws.board, "todo", `${ws.number ?? 0}-task.md`);
|
|
90503
90682
|
function findCard(board, number) {
|
|
90504
90683
|
const named2 = new RegExp(`^${number}-`);
|
|
90505
90684
|
const walk = (dir) => {
|
|
90506
90685
|
let entries;
|
|
90507
90686
|
try {
|
|
90508
|
-
entries =
|
|
90687
|
+
entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
90509
90688
|
} catch {
|
|
90510
90689
|
return null;
|
|
90511
90690
|
}
|
|
90512
90691
|
for (const e2 of entries) {
|
|
90513
90692
|
if (!named2.test(e2.name)) continue;
|
|
90514
|
-
if (e2.isFile() && e2.name.endsWith(".md")) return
|
|
90515
|
-
const root =
|
|
90516
|
-
if (e2.isDirectory() &&
|
|
90693
|
+
if (e2.isFile() && e2.name.endsWith(".md")) return path23.join(dir, e2.name);
|
|
90694
|
+
const root = path23.join(dir, e2.name, "root.md");
|
|
90695
|
+
if (e2.isDirectory() && fs20.existsSync(root)) return root;
|
|
90517
90696
|
}
|
|
90518
90697
|
for (const e2 of entries) if (e2.isDirectory() && !e2.name.startsWith(".")) {
|
|
90519
|
-
const hit = walk(
|
|
90698
|
+
const hit = walk(path23.join(dir, e2.name));
|
|
90520
90699
|
if (hit) return hit;
|
|
90521
90700
|
}
|
|
90522
90701
|
return null;
|
|
90523
90702
|
};
|
|
90524
|
-
return walk(
|
|
90703
|
+
return walk(path23.join(board, "todo")) ?? walk(path23.join(board, ".archive"));
|
|
90525
90704
|
}
|
|
90526
90705
|
function akbCardOf(ws) {
|
|
90527
90706
|
return ws.number && findCard(ws.board, ws.number) ? ws.number : void 0;
|
|
90528
90707
|
}
|
|
90529
|
-
var recordFile = (ws) =>
|
|
90708
|
+
var recordFile = (ws) => path23.join(ws.board, ".sync", `${ws.task}.json`);
|
|
90530
90709
|
function readRecord(ws) {
|
|
90531
90710
|
try {
|
|
90532
|
-
return { ...EMPTY, ...JSON.parse(
|
|
90711
|
+
return { ...EMPTY, ...JSON.parse(fs20.readFileSync(recordFile(ws), "utf8")) };
|
|
90533
90712
|
} catch {
|
|
90534
90713
|
return structuredClone(EMPTY);
|
|
90535
90714
|
}
|
|
90536
90715
|
}
|
|
90537
90716
|
function writeRecord(ws, record) {
|
|
90538
|
-
|
|
90539
|
-
|
|
90717
|
+
fs20.mkdirSync(path23.dirname(recordFile(ws)), { recursive: true });
|
|
90718
|
+
fs20.writeFileSync(recordFile(ws), `${JSON.stringify(record, null, 2)}
|
|
90540
90719
|
`);
|
|
90541
90720
|
}
|
|
90542
|
-
var baseFile = (ws) =>
|
|
90721
|
+
var baseFile = (ws) => path23.join(ws.cwd, ".akb", "base.json");
|
|
90543
90722
|
function readBase(ws) {
|
|
90544
90723
|
try {
|
|
90545
|
-
const base = JSON.parse(
|
|
90724
|
+
const base = JSON.parse(fs20.readFileSync(baseFile(ws), "utf8"));
|
|
90546
90725
|
if (base.layout === "workspace") return base;
|
|
90547
90726
|
} catch {
|
|
90548
90727
|
}
|
|
@@ -90550,25 +90729,25 @@ function readBase(ws) {
|
|
|
90550
90729
|
}
|
|
90551
90730
|
function writeBase(ws, base) {
|
|
90552
90731
|
const file2 = baseFile(ws);
|
|
90553
|
-
|
|
90554
|
-
|
|
90555
|
-
|
|
90732
|
+
fs20.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
90733
|
+
fs20.writeFileSync(`${file2}.tmp`, JSON.stringify(base));
|
|
90734
|
+
fs20.renameSync(`${file2}.tmp`, file2);
|
|
90556
90735
|
}
|
|
90557
|
-
var hashOf = (bytes2) =>
|
|
90736
|
+
var hashOf = (bytes2) => crypto3.createHash("sha256").update(bytes2).digest("hex");
|
|
90558
90737
|
function hashFile(file2) {
|
|
90559
90738
|
try {
|
|
90560
|
-
return hashOf(
|
|
90739
|
+
return hashOf(fs20.readFileSync(file2));
|
|
90561
90740
|
} catch {
|
|
90562
90741
|
return null;
|
|
90563
90742
|
}
|
|
90564
90743
|
}
|
|
90565
90744
|
function write(file2, bytes2) {
|
|
90566
|
-
|
|
90567
|
-
|
|
90745
|
+
fs20.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
90746
|
+
fs20.writeFileSync(file2, bytes2);
|
|
90568
90747
|
}
|
|
90569
90748
|
function readText(file2) {
|
|
90570
90749
|
try {
|
|
90571
|
-
return
|
|
90750
|
+
return fs20.readFileSync(file2, "utf8");
|
|
90572
90751
|
} catch {
|
|
90573
90752
|
return null;
|
|
90574
90753
|
}
|
|
@@ -90576,14 +90755,14 @@ function readText(file2) {
|
|
|
90576
90755
|
function filesUnder(dir, base = dir) {
|
|
90577
90756
|
let entries;
|
|
90578
90757
|
try {
|
|
90579
|
-
entries =
|
|
90758
|
+
entries = fs20.readdirSync(dir, { withFileTypes: true });
|
|
90580
90759
|
} catch {
|
|
90581
90760
|
return [];
|
|
90582
90761
|
}
|
|
90583
90762
|
return entries.flatMap((e2) => {
|
|
90584
|
-
const full =
|
|
90763
|
+
const full = path23.join(dir, e2.name);
|
|
90585
90764
|
if (e2.isDirectory()) return filesUnder(full, base);
|
|
90586
|
-
return e2.isFile() ? [
|
|
90765
|
+
return e2.isFile() ? [path23.relative(base, full).split(path23.sep).join("/")] : [];
|
|
90587
90766
|
});
|
|
90588
90767
|
}
|
|
90589
90768
|
var kept3 = isBoardPath;
|
|
@@ -90599,7 +90778,7 @@ function viewOf(ws, base, shared) {
|
|
|
90599
90778
|
}
|
|
90600
90779
|
function assetFiles(ws, list) {
|
|
90601
90780
|
const card = cardFile(ws);
|
|
90602
|
-
return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) =>
|
|
90781
|
+
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
90782
|
}
|
|
90604
90783
|
var assetsListOf = (ws, base) => base.files[rootOf(ws) + assetsFile(ws.task)]?.content;
|
|
90605
90784
|
var localFiles = (ws, base) => {
|
|
@@ -90608,9 +90787,9 @@ var localFiles = (ws, base) => {
|
|
|
90608
90787
|
};
|
|
90609
90788
|
var SKILL_PATH = /^skills\/([a-z0-9]+(?:-[a-z0-9]+)*)\/((?:[\w.-]+\/)*[\w.-]+)$/;
|
|
90610
90789
|
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) =>
|
|
90790
|
+
const held4 = record.tools?.skills ?? {};
|
|
90791
|
+
const ours = new Set(Object.keys(held4).map((name) => name.split("/")[1]));
|
|
90792
|
+
const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) => fs20.existsSync(path23.join(ws.cwd, root, skill)));
|
|
90614
90793
|
const kept4 = Object.keys(files).map((name) => SKILL_PATH.exec(name)?.[1]).filter((skill) => skill && !theirs(skill));
|
|
90615
90794
|
const skills = {};
|
|
90616
90795
|
for (const [name, text3] of Object.entries(files)) {
|
|
@@ -90618,17 +90797,17 @@ function pullTools(ws, record, files) {
|
|
|
90618
90797
|
if (!at2 || at2[1] === "kanban" || !kept4.includes(at2[1]) || at2[2].split("/").includes("..")) continue;
|
|
90619
90798
|
skills[name] = hashOf(text3);
|
|
90620
90799
|
for (const root of SKILL_ROOTS) {
|
|
90621
|
-
const file2 =
|
|
90622
|
-
if (
|
|
90800
|
+
const file2 = path23.join(ws.cwd, root, at2[1], at2[2]);
|
|
90801
|
+
if (held4[name] !== skills[name] || hashFile(file2) !== skills[name]) write(file2, text3);
|
|
90623
90802
|
}
|
|
90624
90803
|
}
|
|
90625
|
-
for (const name of Object.keys(
|
|
90804
|
+
for (const name of Object.keys(held4)) {
|
|
90626
90805
|
if (skills[name]) continue;
|
|
90627
90806
|
const [, skill, rest] = SKILL_PATH.exec(name) ?? [];
|
|
90628
90807
|
if (!skill || !rest) continue;
|
|
90629
90808
|
for (const root of SKILL_ROOTS) {
|
|
90630
|
-
|
|
90631
|
-
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`)))
|
|
90809
|
+
fs20.rmSync(path23.join(ws.cwd, root, skill, rest), { force: true });
|
|
90810
|
+
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`))) fs20.rmSync(path23.join(ws.cwd, root, skill), { recursive: true, force: true });
|
|
90632
90811
|
}
|
|
90633
90812
|
}
|
|
90634
90813
|
const names2 = [...new Set(Object.keys(skills).map((name) => name.split("/")[1]))];
|
|
@@ -90645,8 +90824,8 @@ async function pullWorkflow(ws, record, base) {
|
|
|
90645
90824
|
let files = {};
|
|
90646
90825
|
if (ws.workflow) {
|
|
90647
90826
|
const root = `workflows/${workflowFolder(ws.workflow)}/`;
|
|
90648
|
-
const
|
|
90649
|
-
files = Object.fromEntries(Object.entries(base.files).filter(([p2]) => p2.startsWith(
|
|
90827
|
+
const held4 = rootOf(ws) + root;
|
|
90828
|
+
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
90829
|
record.builtin = ws.workflow.startsWith("wf_builtin_");
|
|
90651
90830
|
let found = Object.keys(files).length > 0;
|
|
90652
90831
|
if (!found && ws.cloudTask) {
|
|
@@ -90656,7 +90835,7 @@ async function pullWorkflow(ws, record, base) {
|
|
|
90656
90835
|
files = read.value.files;
|
|
90657
90836
|
found = true;
|
|
90658
90837
|
if (!record.builtin) {
|
|
90659
|
-
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(
|
|
90838
|
+
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(path23.join(ws.board, root, name), text3);
|
|
90660
90839
|
}
|
|
90661
90840
|
}
|
|
90662
90841
|
}
|
|
@@ -90664,15 +90843,14 @@ async function pullWorkflow(ws, record, base) {
|
|
|
90664
90843
|
}
|
|
90665
90844
|
pullAgents(ws, base, ws.workflow && !record.builtin ? files : {});
|
|
90666
90845
|
const placed = readPlaced(ws);
|
|
90667
|
-
for (const name of Object.keys(record.agents ?? {})) if (!placed[name])
|
|
90846
|
+
for (const name of Object.keys(record.agents ?? {})) if (!placed[name]) fs20.rmSync(path23.join(ws.board, name), { force: true });
|
|
90668
90847
|
record.agents = {};
|
|
90669
90848
|
return { ok: true, value: void 0 };
|
|
90670
90849
|
}
|
|
90671
|
-
var
|
|
90672
|
-
var agentsRecord = (ws) => path20.join(ws.board, ".sync", "agents.json");
|
|
90850
|
+
var agentsRecord = (ws) => path23.join(ws.board, ".sync", "agents.json");
|
|
90673
90851
|
function readPlaced(ws) {
|
|
90674
90852
|
try {
|
|
90675
|
-
return JSON.parse(
|
|
90853
|
+
return JSON.parse(fs20.readFileSync(agentsRecord(ws), "utf8"));
|
|
90676
90854
|
} catch {
|
|
90677
90855
|
return {};
|
|
90678
90856
|
}
|
|
@@ -90693,8 +90871,8 @@ function pullAgents(ws, base, own) {
|
|
|
90693
90871
|
const names2 = /* @__PURE__ */ new Set();
|
|
90694
90872
|
for (const [name, text3] of Object.entries(files)) {
|
|
90695
90873
|
const agent = /^agents\/([^/]+)\//.exec(name)?.[1];
|
|
90696
|
-
const file2 =
|
|
90697
|
-
if (!agent || taken.has(agent) || !file2.startsWith(
|
|
90874
|
+
const file2 = path23.resolve(ws.board, name);
|
|
90875
|
+
if (!agent || taken.has(agent) || !file2.startsWith(path23.join(ws.board, "agents") + path23.sep)) continue;
|
|
90698
90876
|
names2.add(agent);
|
|
90699
90877
|
agents[name] = text3;
|
|
90700
90878
|
}
|
|
@@ -90704,42 +90882,42 @@ function pullAgents(ws, base, own) {
|
|
|
90704
90882
|
const hashes = {};
|
|
90705
90883
|
for (const [name, text3] of Object.entries(agents)) {
|
|
90706
90884
|
hashes[name] = hashOf(text3);
|
|
90707
|
-
if (hashFile(
|
|
90885
|
+
if (hashFile(path23.join(ws.board, name)) !== hashes[name]) write(path23.join(ws.board, name), text3);
|
|
90708
90886
|
}
|
|
90709
|
-
for (const name of Object.keys(before)) if (!hashes[name])
|
|
90887
|
+
for (const name of Object.keys(before)) if (!hashes[name]) fs20.rmSync(path23.join(ws.board, name), { force: true });
|
|
90710
90888
|
write(agentsRecord(ws), `${JSON.stringify(hashes, null, 2)}
|
|
90711
90889
|
`);
|
|
90712
90890
|
}
|
|
90713
90891
|
function pullDraftAgents(ws, record) {
|
|
90714
90892
|
if (ws.workflow !== BUILDER) return;
|
|
90715
|
-
const root =
|
|
90893
|
+
const root = path23.join(ws.board, "workflows", draftFolder(ws.task), "agents");
|
|
90716
90894
|
record.agents ??= {};
|
|
90717
90895
|
for (const name of filesUnder(root)) {
|
|
90718
|
-
const text3 =
|
|
90896
|
+
const text3 = fs20.readFileSync(path23.join(root, name));
|
|
90719
90897
|
const at2 = `agents/${name}`;
|
|
90720
90898
|
record.agents[at2] = hashOf(text3);
|
|
90721
|
-
if (hashFile(
|
|
90899
|
+
if (hashFile(path23.join(ws.board, at2)) !== record.agents[at2]) write(path23.join(ws.board, at2), text3);
|
|
90722
90900
|
}
|
|
90723
90901
|
}
|
|
90724
90902
|
function workflowFile(ws) {
|
|
90725
90903
|
if (!ws.workflow || readRecord(ws).builtin) return null;
|
|
90726
|
-
const file2 =
|
|
90727
|
-
return
|
|
90904
|
+
const file2 = path23.join(ws.board, "workflows", workflowFolder(ws.workflow), "WORKFLOW.md");
|
|
90905
|
+
return fs20.existsSync(file2) ? file2 : null;
|
|
90728
90906
|
}
|
|
90729
90907
|
function assetPath(ws, name, card) {
|
|
90730
90908
|
if (/^[a-z][\w+.-]*:/i.test(name) || name.startsWith("/") || name.startsWith("#")) return null;
|
|
90731
|
-
const
|
|
90732
|
-
if (
|
|
90909
|
+
const held4 = /^\.(assets|mockups)\//.exec(name);
|
|
90910
|
+
if (held4) {
|
|
90733
90911
|
const state = stateDir(ws);
|
|
90734
|
-
const file3 = state &&
|
|
90735
|
-
return file3 && file3.startsWith(
|
|
90912
|
+
const file3 = state && path23.resolve(state, held4[1], name.slice(held4[0].length));
|
|
90913
|
+
return file3 && file3.startsWith(path23.join(state, held4[1]) + path23.sep) ? file3 : null;
|
|
90736
90914
|
}
|
|
90737
|
-
const file2 =
|
|
90738
|
-
return file2.startsWith(ws.board +
|
|
90915
|
+
const file2 = path23.resolve(path23.dirname(card), name);
|
|
90916
|
+
return file2.startsWith(ws.board + path23.sep) ? file2 : null;
|
|
90739
90917
|
}
|
|
90740
90918
|
function cardAssetsDir(ws, id) {
|
|
90741
90919
|
const state = stateDir(ws);
|
|
90742
|
-
return state &&
|
|
90920
|
+
return state && path23.join(state, "assets", String(id));
|
|
90743
90921
|
}
|
|
90744
90922
|
function stateDir(ws) {
|
|
90745
90923
|
try {
|
|
@@ -90750,8 +90928,8 @@ function stateDir(ws) {
|
|
|
90750
90928
|
}
|
|
90751
90929
|
function assetsOf(text3) {
|
|
90752
90930
|
try {
|
|
90753
|
-
const
|
|
90754
|
-
return
|
|
90931
|
+
const held4 = JSON.parse(text3 ?? "{}");
|
|
90932
|
+
return held4 && typeof held4 === "object" && !Array.isArray(held4) ? held4 : {};
|
|
90755
90933
|
} catch {
|
|
90756
90934
|
return {};
|
|
90757
90935
|
}
|
|
@@ -90778,13 +90956,13 @@ var pullChanges = (ws) => inFolder(ws.cwd, async () => {
|
|
|
90778
90956
|
const p2 = f2.path.startsWith(root) ? f2.path.slice(root.length) : f2.path;
|
|
90779
90957
|
const isShared = p2.startsWith(MEMORY2) && shared(p2.slice(MEMORY2.length));
|
|
90780
90958
|
if (kept3(p2) && isShared === !f2.path.startsWith(root)) {
|
|
90781
|
-
const file2 =
|
|
90959
|
+
const file2 = path23.join(ws.board, p2);
|
|
90782
90960
|
const here2 = readText(file2);
|
|
90783
90961
|
if (here2 !== f2.content && here2 !== (base.files[f2.path]?.content ?? null)) {
|
|
90784
90962
|
skipped = true;
|
|
90785
90963
|
continue;
|
|
90786
90964
|
}
|
|
90787
|
-
if (f2.content === null)
|
|
90965
|
+
if (f2.content === null) fs20.rmSync(file2, { force: true });
|
|
90788
90966
|
else if (here2 !== f2.content) write(file2, f2.content);
|
|
90789
90967
|
}
|
|
90790
90968
|
if (f2.content === null) delete base.files[f2.path];
|
|
@@ -90815,13 +90993,13 @@ async function readCloud(ws) {
|
|
|
90815
90993
|
writeBase(ws, base);
|
|
90816
90994
|
const reset = (view2) => {
|
|
90817
90995
|
for (const [p2, content] of view2) {
|
|
90818
|
-
const file2 =
|
|
90996
|
+
const file2 = path23.join(ws.board, p2);
|
|
90819
90997
|
if (kept3(p2) && readText(file2) !== content) write(file2, content);
|
|
90820
90998
|
}
|
|
90821
90999
|
};
|
|
90822
91000
|
const view = viewOf(ws, base, sharedMemory(ws.board));
|
|
90823
91001
|
const first = (p2) => isSettingsPath(p2) && !known2.has(rootOf(ws) + p2);
|
|
90824
|
-
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2))
|
|
91002
|
+
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2)) fs20.rmSync(path23.join(ws.board, p2), { force: true });
|
|
90825
91003
|
reset(view);
|
|
90826
91004
|
const record = readRecord(ws);
|
|
90827
91005
|
const workflow = await pullWorkflow(ws, record, base);
|
|
@@ -90835,18 +91013,18 @@ async function readCloud(ws) {
|
|
|
90835
91013
|
return { ok: true, value: void 0 };
|
|
90836
91014
|
}
|
|
90837
91015
|
function writeIndex(board) {
|
|
90838
|
-
const todo =
|
|
91016
|
+
const todo = path23.join(board, "todo");
|
|
90839
91017
|
const cards = [];
|
|
90840
91018
|
let entries = [];
|
|
90841
91019
|
try {
|
|
90842
|
-
entries =
|
|
91020
|
+
entries = fs20.readdirSync(todo, { withFileTypes: true });
|
|
90843
91021
|
} catch {
|
|
90844
91022
|
}
|
|
90845
91023
|
for (const e2 of entries) {
|
|
90846
91024
|
const id = /^(\d+)-/.exec(e2.name)?.[1];
|
|
90847
91025
|
if (!id) continue;
|
|
90848
91026
|
const link = e2.isDirectory() ? `${e2.name}/root.md` : e2.name.endsWith(".md") ? e2.name : null;
|
|
90849
|
-
const text4 = link && readText(
|
|
91027
|
+
const text4 = link && readText(path23.join(todo, link));
|
|
90850
91028
|
if (text4 === null || !link) continue;
|
|
90851
91029
|
cards.push({ id: Number(id), title: cardFront(text4).title ?? e2.name.replace(/\.md$/, ""), link });
|
|
90852
91030
|
}
|
|
@@ -90861,7 +91039,7 @@ the number at the front of a filename is the task id.
|
|
|
90861
91039
|
|
|
90862
91040
|
${list}
|
|
90863
91041
|
`;
|
|
90864
|
-
if (readText(
|
|
91042
|
+
if (readText(path23.join(todo, "README.md")) !== text3) write(path23.join(todo, "README.md"), text3);
|
|
90865
91043
|
}
|
|
90866
91044
|
var workspaceOf = (ws) => readBase(ws).workspace ?? null;
|
|
90867
91045
|
async function pullAssets(ws, record, assets) {
|
|
@@ -90876,13 +91054,13 @@ async function pullAssets(ws, record, assets) {
|
|
|
90876
91054
|
if (!latest.ok) return latest;
|
|
90877
91055
|
version = latest.value.latest_version ?? 0;
|
|
90878
91056
|
}
|
|
90879
|
-
const
|
|
90880
|
-
if (
|
|
90881
|
-
out[name] = { ...
|
|
91057
|
+
const held4 = record.assets[name];
|
|
91058
|
+
if (held4?.kind === "html" && held4.artifact === ref.artifact) {
|
|
91059
|
+
out[name] = { ...held4, version };
|
|
90882
91060
|
continue;
|
|
90883
91061
|
}
|
|
90884
|
-
if (
|
|
90885
|
-
out[name] =
|
|
91062
|
+
if (held4?.artifact === ref.artifact && held4.version === version && hashFile(target) === held4.hash) {
|
|
91063
|
+
out[name] = held4;
|
|
90886
91064
|
continue;
|
|
90887
91065
|
}
|
|
90888
91066
|
const bytes2 = await readAsset(ref.artifact, version);
|
|
@@ -90894,10 +91072,10 @@ async function pullAssets(ws, record, assets) {
|
|
|
90894
91072
|
return { ok: true, value: void 0 };
|
|
90895
91073
|
}
|
|
90896
91074
|
async function readAsset(artifact, version) {
|
|
90897
|
-
const
|
|
90898
|
-
if (!
|
|
90899
|
-
if (
|
|
90900
|
-
const content =
|
|
91075
|
+
const held4 = await readVersion(artifact, version);
|
|
91076
|
+
if (!held4.ok) return held4;
|
|
91077
|
+
if (held4.value.file) return download(held4.value.file.url);
|
|
91078
|
+
const content = held4.value.content;
|
|
90901
91079
|
return { ok: true, value: Buffer.from(typeof content === "string" ? content : JSON.stringify(content)) };
|
|
90902
91080
|
}
|
|
90903
91081
|
var TYPES = {
|
|
@@ -90928,14 +91106,14 @@ function kindOf(ext) {
|
|
|
90928
91106
|
return type.startsWith("video/") || type.startsWith("audio/") ? "video" : "asset";
|
|
90929
91107
|
}
|
|
90930
91108
|
async function sentOf(file2) {
|
|
90931
|
-
const ext =
|
|
91109
|
+
const ext = path23.extname(file2).toLowerCase();
|
|
90932
91110
|
const kind = kindOf(ext);
|
|
90933
|
-
if (kind !== "html") return { bytes:
|
|
91111
|
+
if (kind !== "html") return { bytes: fs20.readFileSync(file2), type: TYPES[ext] ?? "application/octet-stream", kind };
|
|
90934
91112
|
let page;
|
|
90935
91113
|
try {
|
|
90936
91114
|
page = await (await Promise.resolve().then(() => (init_mockup(), mockup_exports))).drawMockup(file2);
|
|
90937
91115
|
} catch (e2) {
|
|
90938
|
-
console.error(`runner: ${
|
|
91116
|
+
console.error(`runner: ${path23.basename(file2)} could not be drawn: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
90939
91117
|
page = UNDRAWN;
|
|
90940
91118
|
}
|
|
90941
91119
|
return { bytes: Buffer.from(page), type: "text/html", kind };
|
|
@@ -90963,23 +91141,23 @@ async function pushAssets(ws, record, before) {
|
|
|
90963
91141
|
for (const [name, ref] of Object.entries(before)) {
|
|
90964
91142
|
if (!body.includes(name)) continue;
|
|
90965
91143
|
const target = assetPath(ws, name, file2);
|
|
90966
|
-
const
|
|
90967
|
-
const out = target &&
|
|
91144
|
+
const held4 = record.assets[name];
|
|
91145
|
+
const out = target && held4 && fs20.existsSync(target) ? await sentOf(target) : null;
|
|
90968
91146
|
const hash = out && hashOf(out.bytes);
|
|
90969
|
-
if (out &&
|
|
90970
|
-
if (
|
|
90971
|
-
const sent = await uploadAsset(
|
|
91147
|
+
if (out && held4 && held4.kind === "html" !== (out.kind === "html")) continue;
|
|
91148
|
+
if (held4 && out && hash !== held4.hash) {
|
|
91149
|
+
const sent = await uploadAsset(held4.artifact, out);
|
|
90972
91150
|
if (!sent.ok) return sent;
|
|
90973
|
-
assets[name] = { artifact:
|
|
90974
|
-
refs[name] = { artifact:
|
|
91151
|
+
assets[name] = { artifact: held4.artifact, version: sent.value, hash, kind: out.kind };
|
|
91152
|
+
refs[name] = { artifact: held4.artifact, version: sent.value };
|
|
90975
91153
|
} else {
|
|
90976
|
-
if (
|
|
91154
|
+
if (held4) assets[name] = held4;
|
|
90977
91155
|
refs[name] = ref;
|
|
90978
91156
|
}
|
|
90979
91157
|
}
|
|
90980
91158
|
for (const name of namedFiles(body)) {
|
|
90981
91159
|
const target = assetPath(ws, name, file2);
|
|
90982
|
-
if (refs[name] || !target || !
|
|
91160
|
+
if (refs[name] || !target || !fs20.statSync(target, { throwIfNoEntry: false })?.isFile()) continue;
|
|
90983
91161
|
const out = await sentOf(target);
|
|
90984
91162
|
if (!ws.cloudTask) continue;
|
|
90985
91163
|
const made = await createArtifact(ws.cloudTask, name.slice(0, 200), out.kind);
|
|
@@ -90990,24 +91168,24 @@ async function pushAssets(ws, record, before) {
|
|
|
90990
91168
|
refs[name] = { artifact: made.value.id, version: sent.value };
|
|
90991
91169
|
}
|
|
90992
91170
|
record.assets = assets;
|
|
90993
|
-
const list =
|
|
90994
|
-
if (Object.keys(refs).length ||
|
|
91171
|
+
const list = path23.join(ws.board, assetsFile(ws.task));
|
|
91172
|
+
if (Object.keys(refs).length || fs20.existsSync(list)) {
|
|
90995
91173
|
if (JSON.stringify(assetsOf(readText(list))) !== JSON.stringify(refs)) write(list, assetsText(refs));
|
|
90996
91174
|
}
|
|
90997
91175
|
return { ok: true, value: void 0 };
|
|
90998
91176
|
}
|
|
90999
91177
|
function resetSorted(ws) {
|
|
91000
|
-
for (const sub of ["dismissed", "archived"])
|
|
91178
|
+
for (const sub of ["dismissed", "archived"]) fs20.rmSync(path23.join(ws.board, "triage", sub), { recursive: true, force: true });
|
|
91001
91179
|
for (const [p2, content] of viewOf(ws, readBase(ws), sharedMemory(ws.board))) {
|
|
91002
|
-
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(
|
|
91180
|
+
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(path23.join(ws.board, p2), content);
|
|
91003
91181
|
}
|
|
91004
91182
|
}
|
|
91005
91183
|
function proposeItems(ws, base) {
|
|
91006
91184
|
const root = rootOf(ws);
|
|
91007
91185
|
for (const p2 of localFiles(ws, base)) {
|
|
91008
91186
|
if (itemAt(p2)?.state !== "open" || base.files[root + p2]) continue;
|
|
91009
|
-
const file2 =
|
|
91010
|
-
const content =
|
|
91187
|
+
const file2 = path23.join(ws.board, p2);
|
|
91188
|
+
const content = fs20.readFileSync(file2, "utf8");
|
|
91011
91189
|
const said = (key) => new RegExp(`^${key}:`, "m").test(content.split(/\n---/)[0] ?? "");
|
|
91012
91190
|
const fields = {
|
|
91013
91191
|
...ws.cloudTask && !said("source_task") ? { source_task: ws.cloudTask } : {},
|
|
@@ -91058,13 +91236,13 @@ async function send2(ws, job) {
|
|
|
91058
91236
|
const owed = (p2) => !job.id && busy(ws.cwd) && itemAt(p2)?.state === "open" && !base.files[rootOf(ws) + p2];
|
|
91059
91237
|
for (const p2 of local) {
|
|
91060
91238
|
if (owed(p2)) continue;
|
|
91061
|
-
const content =
|
|
91239
|
+
const content = fs20.readFileSync(path23.join(ws.board, p2), "utf8");
|
|
91062
91240
|
const remote = remoteOf(ws, shared, p2);
|
|
91063
91241
|
localOf.set(remote, p2);
|
|
91064
|
-
const
|
|
91065
|
-
if (
|
|
91242
|
+
const held4 = base.files[remote];
|
|
91243
|
+
if (held4?.content === content) continue;
|
|
91066
91244
|
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:
|
|
91245
|
+
changes.push({ path: remote, content, base_seq: held4?.seq ?? 0 });
|
|
91068
91246
|
}
|
|
91069
91247
|
for (const p2 of viewOf(ws, base, shared).keys()) {
|
|
91070
91248
|
const remote = remoteOf(ws, shared, p2);
|
|
@@ -91090,15 +91268,15 @@ async function send2(ws, job) {
|
|
|
91090
91268
|
changes.splice(at2, 1);
|
|
91091
91269
|
delete base.files[theirs.path];
|
|
91092
91270
|
writeBase(ws, base);
|
|
91093
|
-
|
|
91271
|
+
fs20.rmSync(path23.join(ws.board, p2), { force: true });
|
|
91094
91272
|
writeIndex(ws.board);
|
|
91095
91273
|
continue;
|
|
91096
91274
|
}
|
|
91097
91275
|
if (at2 < 0) continue;
|
|
91098
91276
|
const merged = itemAt(p2) ? { content: theirs.content } : mergeFile(base.files[theirs.path]?.content ?? null, changes[at2].content, theirs.content);
|
|
91099
91277
|
changes[at2] = { path: theirs.path, content: merged.content, base_seq: theirs.seq };
|
|
91100
|
-
if (merged.content === null)
|
|
91101
|
-
else write(
|
|
91278
|
+
if (merged.content === null) fs20.rmSync(path23.join(ws.board, p2), { force: true });
|
|
91279
|
+
else write(path23.join(ws.board, p2), merged.content);
|
|
91102
91280
|
}
|
|
91103
91281
|
if (!changes.length) return { ok: true, changed: false };
|
|
91104
91282
|
sent = await commitBoard(ws.project, job.id, job.machineId, changes);
|
|
@@ -91119,12 +91297,12 @@ var PULL_MS = 2e3;
|
|
|
91119
91297
|
function keptFolders() {
|
|
91120
91298
|
let cached2 = [];
|
|
91121
91299
|
try {
|
|
91122
|
-
cached2 =
|
|
91300
|
+
cached2 = fs21.readdirSync(cacheRoot()).map((name) => path24.join(cacheRoot(), name));
|
|
91123
91301
|
} catch {
|
|
91124
91302
|
}
|
|
91125
91303
|
return [.../* @__PURE__ */ new Set([...allowedProjects(), ...cached2])].flatMap((dir) => [keptBoard(dir)].filter((ws) => !!ws));
|
|
91126
91304
|
}
|
|
91127
|
-
function watchBoards(machineId2,
|
|
91305
|
+
function watchBoards(machineId2, ms, lookMs = LOOK_MS, pullMs = PULL_MS) {
|
|
91128
91306
|
const watched = /* @__PURE__ */ new Map();
|
|
91129
91307
|
const due = /* @__PURE__ */ new Map();
|
|
91130
91308
|
const afterJob = /* @__PURE__ */ new Set();
|
|
@@ -91143,12 +91321,12 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
|
|
|
91143
91321
|
const watch = (ws) => {
|
|
91144
91322
|
let watcher;
|
|
91145
91323
|
try {
|
|
91146
|
-
watcher =
|
|
91147
|
-
const p2 = name && String(name).split(
|
|
91148
|
-
const
|
|
91149
|
-
if (closed || !p2 || !isBoardPath(p2) || !
|
|
91150
|
-
clearTimeout(
|
|
91151
|
-
|
|
91324
|
+
watcher = fs21.watch(ws.board, { recursive: true }, (_event, name) => {
|
|
91325
|
+
const p2 = name && String(name).split(path24.sep).join("/");
|
|
91326
|
+
const held4 = watched.get(ws.cwd);
|
|
91327
|
+
if (closed || !p2 || !isBoardPath(p2) || !held4) return;
|
|
91328
|
+
clearTimeout(held4.timer);
|
|
91329
|
+
held4.timer = setTimeout(() => void send3(ws), ms);
|
|
91152
91330
|
});
|
|
91153
91331
|
} catch {
|
|
91154
91332
|
return false;
|
|
@@ -91192,9 +91370,9 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
|
|
|
91192
91370
|
clearInterval(timer);
|
|
91193
91371
|
for (const t2 of due.values()) clearTimeout(t2);
|
|
91194
91372
|
due.clear();
|
|
91195
|
-
for (const
|
|
91196
|
-
clearTimeout(
|
|
91197
|
-
|
|
91373
|
+
for (const held4 of watched.values()) {
|
|
91374
|
+
clearTimeout(held4.timer);
|
|
91375
|
+
held4.watcher.close();
|
|
91198
91376
|
}
|
|
91199
91377
|
watched.clear();
|
|
91200
91378
|
}
|
|
@@ -91202,16 +91380,16 @@ function watchBoards(machineId2, ms2, lookMs = LOOK_MS, pullMs = PULL_MS) {
|
|
|
91202
91380
|
}
|
|
91203
91381
|
|
|
91204
91382
|
// src/diff.ts
|
|
91205
|
-
import { execFile } from "node:child_process";
|
|
91206
|
-
import
|
|
91207
|
-
import
|
|
91383
|
+
import { execFile as execFile2 } from "node:child_process";
|
|
91384
|
+
import fs22 from "node:fs";
|
|
91385
|
+
import path25 from "node:path";
|
|
91208
91386
|
var FILE_BYTES = 256 * 1024;
|
|
91209
91387
|
var TOTAL_BYTES = 1024 * 1024;
|
|
91210
91388
|
var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
91211
91389
|
var PATHS = ["--", ".", ":(exclude).akb"];
|
|
91212
91390
|
var STATUS = { A: "added", D: "deleted" };
|
|
91213
91391
|
var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
|
|
91214
|
-
(resolve2) =>
|
|
91392
|
+
(resolve2) => execFile2(
|
|
91215
91393
|
"git",
|
|
91216
91394
|
["-C", dir, "-c", "core.quotePath=false", ...args],
|
|
91217
91395
|
{ encoding: "utf8", maxBuffer },
|
|
@@ -91221,7 +91399,7 @@ var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
|
|
|
91221
91399
|
function projectDir(placed, project) {
|
|
91222
91400
|
if (placed) {
|
|
91223
91401
|
const real = realpath3(placed);
|
|
91224
|
-
return real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
91402
|
+
return real && allowedProjects().some((root) => real === root || real.startsWith(root + path25.sep)) ? real : null;
|
|
91225
91403
|
}
|
|
91226
91404
|
let cached2;
|
|
91227
91405
|
try {
|
|
@@ -91229,11 +91407,11 @@ function projectDir(placed, project) {
|
|
|
91229
91407
|
} catch {
|
|
91230
91408
|
return null;
|
|
91231
91409
|
}
|
|
91232
|
-
return
|
|
91410
|
+
return fs22.existsSync(path25.join(cached2, ".git")) ? cached2 : null;
|
|
91233
91411
|
}
|
|
91234
91412
|
function realpath3(p2) {
|
|
91235
91413
|
try {
|
|
91236
|
-
return
|
|
91414
|
+
return fs22.realpathSync(p2);
|
|
91237
91415
|
} catch {
|
|
91238
91416
|
return null;
|
|
91239
91417
|
}
|
|
@@ -91278,98 +91456,170 @@ async function answerHint(machineId2, hint2) {
|
|
|
91278
91456
|
}
|
|
91279
91457
|
|
|
91280
91458
|
// src/flow.ts
|
|
91281
|
-
import
|
|
91282
|
-
import
|
|
91459
|
+
import fs25 from "node:fs";
|
|
91460
|
+
import path28 from "node:path";
|
|
91283
91461
|
|
|
91284
|
-
// src/
|
|
91285
|
-
|
|
91286
|
-
|
|
91287
|
-
|
|
91288
|
-
|
|
91289
|
-
|
|
91290
|
-
|
|
91291
|
-
|
|
91292
|
-
}
|
|
91293
|
-
|
|
91294
|
-
|
|
91295
|
-
|
|
91296
|
-
|
|
91297
|
-
|
|
91298
|
-
|
|
91299
|
-
|
|
91300
|
-
`];
|
|
91301
|
-
try {
|
|
91302
|
-
if (fs20.readFileSync(file2, "utf8") === text3) return dir;
|
|
91303
|
-
} catch {
|
|
91462
|
+
// ../cli/src/lib/question-block.ts
|
|
91463
|
+
var MODES = ["single", "multi"];
|
|
91464
|
+
var withoutTag = (text3) => text3.replace(/^\[user\]\s+/, "");
|
|
91465
|
+
function normalizeQuestion(raw) {
|
|
91466
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
91467
|
+
const source = raw;
|
|
91468
|
+
const text3 = withoutTag(String(source.question ?? source.text ?? ""));
|
|
91469
|
+
const extra = {
|
|
91470
|
+
...typeof source.agent === "string" && source.agent.trim() ? { agent: source.agent.trim() } : {},
|
|
91471
|
+
...source.skipped === true || source.skipped === "true" ? { skipped: true } : {}
|
|
91472
|
+
};
|
|
91473
|
+
const options = (Array.isArray(source.options) ? source.options : []).map((o2) => String(o2).trim()).filter(Boolean);
|
|
91474
|
+
if (options.length === 0) return { text: text3, ...extra };
|
|
91475
|
+
const mode = MODES.includes(String(source.mode)) ? String(source.mode) : "single";
|
|
91476
|
+
const recommend = (Array.isArray(source.recommend) ? source.recommend : []).map(Number).filter((n) => Number.isInteger(n) && n >= 1 && n <= options.length);
|
|
91477
|
+
return { text: text3, mode, options, recommend: mode === "single" ? recommend.slice(0, 1) : recommend, ...extra };
|
|
91304
91478
|
}
|
|
91305
|
-
|
|
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;
|
|
91479
|
+
return { text: withoutTag(String(raw)) };
|
|
91320
91480
|
}
|
|
91321
|
-
|
|
91322
|
-
|
|
91323
|
-
|
|
91324
|
-
|
|
91325
|
-
|
|
91326
|
-
const
|
|
91327
|
-
|
|
91328
|
-
|
|
91481
|
+
function parseQuestionsBlock(lines) {
|
|
91482
|
+
const out = [];
|
|
91483
|
+
for (let i = 0; i < lines.length; i++) {
|
|
91484
|
+
const m = lines[i].match(/^\s*-\s+([\s\S]*)$/);
|
|
91485
|
+
if (!m) continue;
|
|
91486
|
+
const head2 = m[1];
|
|
91487
|
+
const opened = head2.match(/^question:\s*(.*)$/);
|
|
91488
|
+
if (!opened) {
|
|
91489
|
+
out.push(normalizeQuestion(unquote2(head2)));
|
|
91490
|
+
continue;
|
|
91491
|
+
}
|
|
91492
|
+
const q3 = {
|
|
91493
|
+
question: unquote2(opened[1]),
|
|
91494
|
+
options: [],
|
|
91495
|
+
recommend: []
|
|
91329
91496
|
};
|
|
91330
|
-
|
|
91331
|
-
|
|
91332
|
-
|
|
91333
|
-
|
|
91334
|
-
|
|
91497
|
+
while (i + 1 < lines.length && !/^\s*-\s/.test(lines[i + 1])) {
|
|
91498
|
+
const field = lines[i + 1].match(/^\s*([A-Za-z_]+):\s*(.*)$/);
|
|
91499
|
+
i++;
|
|
91500
|
+
if (!field) continue;
|
|
91501
|
+
const [, key, val] = field;
|
|
91502
|
+
if (key === "options") {
|
|
91503
|
+
while (i + 1 < lines.length && /^\s*-\s+/.test(lines[i + 1])) {
|
|
91504
|
+
q3.options.push(unquote2(lines[i + 1].replace(/^\s*-\s+/, "")));
|
|
91505
|
+
i++;
|
|
91506
|
+
}
|
|
91507
|
+
} else if (key === "recommend") {
|
|
91508
|
+
q3.recommend = val.replace(/^\[|\]$/g, "").split(",").map((s) => Number(s.trim())).filter((n) => Number.isInteger(n));
|
|
91509
|
+
} else if (key === "mode") {
|
|
91510
|
+
q3.mode = unquote2(val);
|
|
91511
|
+
} else if (key === "agent") {
|
|
91512
|
+
q3.agent = unquote2(val);
|
|
91513
|
+
} else if (key === "skipped") {
|
|
91514
|
+
q3.skipped = unquote2(val) === "true";
|
|
91515
|
+
}
|
|
91335
91516
|
}
|
|
91336
|
-
|
|
91337
|
-
|
|
91338
|
-
|
|
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
|
-
});
|
|
91517
|
+
out.push(normalizeQuestion(q3));
|
|
91518
|
+
}
|
|
91519
|
+
return out;
|
|
91351
91520
|
}
|
|
91352
|
-
|
|
91353
|
-
|
|
91354
|
-
|
|
91355
|
-
|
|
91356
|
-
|
|
91357
|
-
|
|
91521
|
+
|
|
91522
|
+
// ../cli/src/lib/view/rules.ts
|
|
91523
|
+
var openOf = (questions) => questions.filter((q3) => !q3.skipped);
|
|
91524
|
+
|
|
91525
|
+
// ../cli/src/lib/frontmatter.ts
|
|
91526
|
+
function parseFrontmatter(text3) {
|
|
91527
|
+
const lines = text3.split("\n");
|
|
91528
|
+
if (lines[0].trim() !== "---") return { meta: null, body: text3 };
|
|
91529
|
+
let i = 1;
|
|
91530
|
+
const fm = [];
|
|
91531
|
+
while (i < lines.length && lines[i].trim() !== "---") {
|
|
91532
|
+
fm.push(lines[i]);
|
|
91533
|
+
i++;
|
|
91358
91534
|
}
|
|
91535
|
+
if (i >= lines.length) return { meta: null, body: text3 };
|
|
91536
|
+
const meta = {};
|
|
91537
|
+
for (let j2 = 0; j2 < fm.length; j2++) {
|
|
91538
|
+
const m = fm[j2].match(/^([A-Za-z_]+):\s*(.*)$/);
|
|
91539
|
+
if (!m) continue;
|
|
91540
|
+
const key = m[1];
|
|
91541
|
+
const val = m[2];
|
|
91542
|
+
if (key === "questions") {
|
|
91543
|
+
if (val === "") {
|
|
91544
|
+
const block = [];
|
|
91545
|
+
while (j2 + 1 < fm.length && /^\s/.test(fm[j2 + 1]) && fm[j2 + 1].trim() !== "") {
|
|
91546
|
+
block.push(fm[j2 + 1]);
|
|
91547
|
+
j2++;
|
|
91548
|
+
}
|
|
91549
|
+
meta.questions = parseQuestionsBlock(block);
|
|
91550
|
+
} else {
|
|
91551
|
+
meta.questions = val.trim() === "[]" ? [] : [normalizeQuestion(unquote2(val))];
|
|
91552
|
+
}
|
|
91553
|
+
continue;
|
|
91554
|
+
}
|
|
91555
|
+
if (val === "") {
|
|
91556
|
+
const items = [];
|
|
91557
|
+
while (j2 + 1 < fm.length && /^\s*-\s+/.test(fm[j2 + 1])) {
|
|
91558
|
+
items.push(unquote2(fm[j2 + 1].replace(/^\s*-\s+/, "")));
|
|
91559
|
+
j2++;
|
|
91560
|
+
}
|
|
91561
|
+
meta[key] = items;
|
|
91562
|
+
} else if (val.startsWith("[")) {
|
|
91563
|
+
const inner = val.slice(1, val.lastIndexOf("]"));
|
|
91564
|
+
meta[key] = inner.split(",").map((s) => s.trim()).filter(Boolean).map(unquote2);
|
|
91565
|
+
} else {
|
|
91566
|
+
meta[key] = unquote2(val);
|
|
91567
|
+
}
|
|
91568
|
+
}
|
|
91569
|
+
for (const k of ["blocked_by", "related"]) {
|
|
91570
|
+
const value = meta[k];
|
|
91571
|
+
if (Array.isArray(value)) {
|
|
91572
|
+
meta[k] = value.map((x2) => Number(String(x2).replace(/^#/, ""))).filter((n) => Number.isInteger(n));
|
|
91573
|
+
} else {
|
|
91574
|
+
meta[k] = [];
|
|
91575
|
+
}
|
|
91576
|
+
}
|
|
91577
|
+
if (!Array.isArray(meta.questions)) {
|
|
91578
|
+
meta.questions = meta.questions ? [normalizeQuestion(meta.questions)] : [];
|
|
91579
|
+
}
|
|
91580
|
+
meta.priority = typeof meta.priority === "string" ? meta.priority.trim() : "";
|
|
91581
|
+
if (!Array.isArray(meta.modules)) meta.modules = [];
|
|
91582
|
+
delete meta.channels;
|
|
91583
|
+
delete meta.decided;
|
|
91584
|
+
delete meta.verify;
|
|
91585
|
+
delete meta.release;
|
|
91586
|
+
delete meta.schedule;
|
|
91587
|
+
delete meta.roi;
|
|
91588
|
+
meta.workflow = typeof meta.workflow === "string" && meta.workflow.trim() ? meta.workflow.trim() : "";
|
|
91589
|
+
meta.triage = typeof meta.triage === "string" ? meta.triage.trim() : "";
|
|
91590
|
+
meta.source = (Array.isArray(meta.source) ? meta.source : typeof meta.source === "string" ? [meta.source] : []).map((ref) => String(ref).trim()).filter(Boolean);
|
|
91591
|
+
delete meta.phases;
|
|
91592
|
+
if (Array.isArray(meta.previews)) meta.previews = meta.previews.map((name) => String(name).trim()).filter(Boolean);
|
|
91593
|
+
else delete meta.previews;
|
|
91594
|
+
meta.stages = /^\d+$/.test(String(meta.stages ?? "").trim()) ? Number(meta.stages) : 0;
|
|
91595
|
+
meta.phase = /^\d+$/.test(String(meta.phase ?? "").trim()) ? Number(meta.phase) : 0;
|
|
91596
|
+
meta.preview_approved = meta.preview_approved === "true";
|
|
91597
|
+
meta.archived = typeof meta.archived === "string" && meta.archived.trim() ? meta.archived.trim() : "";
|
|
91598
|
+
meta.rejected = meta.rejected === "true";
|
|
91599
|
+
meta.rejected_reason = typeof meta.rejected_reason === "string" ? meta.rejected_reason : "";
|
|
91600
|
+
meta.rejected_at = typeof meta.rejected_at === "string" ? meta.rejected_at.trim() : "";
|
|
91601
|
+
meta.rejected_by = meta.rejected_by === "user" || meta.rejected_by === "agent" ? meta.rejected_by : "";
|
|
91602
|
+
return { meta, body: lines.slice(i + 1).join("\n") };
|
|
91359
91603
|
}
|
|
91360
91604
|
|
|
91361
91605
|
// src/triage.ts
|
|
91362
|
-
import
|
|
91363
|
-
import
|
|
91606
|
+
import fs23 from "node:fs";
|
|
91607
|
+
import path26 from "node:path";
|
|
91364
91608
|
|
|
91365
91609
|
// ../cli/src/lib/signals/identity.ts
|
|
91366
91610
|
import { createHash } from "node:crypto";
|
|
91367
91611
|
var DERIVED = "derived-";
|
|
91368
91612
|
var derivedSourceId = (seed) => `${DERIVED}${createHash("sha256").update(seed).digest("hex").slice(0, 16)}`;
|
|
91369
91613
|
|
|
91614
|
+
// ../cli/src/lib/slug.ts
|
|
91615
|
+
function slugify(s) {
|
|
91616
|
+
const out = String(s).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 60).replace(/-+$/g, "");
|
|
91617
|
+
return out || "task";
|
|
91618
|
+
}
|
|
91619
|
+
|
|
91370
91620
|
// src/triage.ts
|
|
91371
|
-
var triageDir = (board) =>
|
|
91372
|
-
var rejectedDir = (board) =>
|
|
91621
|
+
var triageDir = (board) => path26.join(board, "triage");
|
|
91622
|
+
var rejectedDir = (board) => path26.join(board, ".archive", REJECTIONS_TO_REVIEW);
|
|
91373
91623
|
var SCRATCH = ["dismissed", "archived"];
|
|
91374
91624
|
var stamp = (at2) => formatStamp(at2 ? new Date(at2) : /* @__PURE__ */ new Date());
|
|
91375
91625
|
function slugOf(title) {
|
|
@@ -91378,7 +91628,7 @@ function slugOf(title) {
|
|
|
91378
91628
|
function freeName(dir, title) {
|
|
91379
91629
|
const stem = slugOf(title);
|
|
91380
91630
|
let name = `${stem}.md`;
|
|
91381
|
-
for (let n = 2;
|
|
91631
|
+
for (let n = 2; fs23.existsSync(path26.join(dir, name)); n++) name = `${stem}-${n}.md`;
|
|
91382
91632
|
return name;
|
|
91383
91633
|
}
|
|
91384
91634
|
function itemText(item, fields = {}) {
|
|
@@ -91398,17 +91648,17 @@ ${item.text.trim()}
|
|
|
91398
91648
|
`;
|
|
91399
91649
|
}
|
|
91400
91650
|
function writeItem(dir, item, fields = {}) {
|
|
91401
|
-
|
|
91651
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
91402
91652
|
const name = freeName(dir, item.title);
|
|
91403
|
-
|
|
91653
|
+
fs23.writeFileSync(path26.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
|
|
91404
91654
|
return name;
|
|
91405
91655
|
}
|
|
91406
91656
|
function layOut(board, rejections) {
|
|
91407
91657
|
clearLaid(board);
|
|
91408
91658
|
const dir = rejectedDir(board);
|
|
91409
|
-
|
|
91659
|
+
fs23.mkdirSync(dir, { recursive: true });
|
|
91410
91660
|
for (const t2 of rejections.tasks) {
|
|
91411
|
-
|
|
91661
|
+
fs23.writeFileSync(path26.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
|
|
91412
91662
|
"---",
|
|
91413
91663
|
`title: ${yamlScalar(t2.title)}`,
|
|
91414
91664
|
"status: todo",
|
|
@@ -91423,20 +91673,38 @@ function layOut(board, rejections) {
|
|
|
91423
91673
|
].join("\n"));
|
|
91424
91674
|
}
|
|
91425
91675
|
for (const item of rejections.triage) {
|
|
91426
|
-
const sub =
|
|
91676
|
+
const sub = path26.join(triageDir(board), item.state === "dismissed" ? "dismissed" : "archived");
|
|
91427
91677
|
const fields = item.state === "dismissed" ? { dismissed_at: stamp(item.dismissed_at), dismissed_by: "user", ...item.dismissed_reason ? { dismissed_reason: item.dismissed_reason } : {} } : {};
|
|
91428
91678
|
writeItem(sub, item, fields);
|
|
91429
91679
|
}
|
|
91430
91680
|
return { tasks: rejections.tasks.map((t2) => t2.id), triage: rejections.triage.map((i) => i.id) };
|
|
91431
91681
|
}
|
|
91432
91682
|
function clearLaid(board) {
|
|
91433
|
-
|
|
91434
|
-
for (const sub of SCRATCH)
|
|
91683
|
+
fs23.rmSync(rejectedDir(board), { recursive: true, force: true });
|
|
91684
|
+
for (const sub of SCRATCH) fs23.rmSync(path26.join(triageDir(board), sub), { recursive: true, force: true });
|
|
91435
91685
|
}
|
|
91436
91686
|
|
|
91437
91687
|
// src/built.ts
|
|
91438
|
-
import
|
|
91439
|
-
import
|
|
91688
|
+
import fs24 from "node:fs";
|
|
91689
|
+
import path27 from "node:path";
|
|
91690
|
+
|
|
91691
|
+
// ../cli/src/lib/spec-agent-names.ts
|
|
91692
|
+
var LEGACY_SPEC_AGENT_NAMES = {
|
|
91693
|
+
"recommend-tech-stack": "tech-stack-advisor",
|
|
91694
|
+
"technology-selection": "tech-stack-advisor",
|
|
91695
|
+
"ui-design": "ui-designer",
|
|
91696
|
+
// Renamed in #945 and folded into the editor in #1057; its asset memory stays in
|
|
91697
|
+
// `memory/agents/video-assets/`.
|
|
91698
|
+
"video-assets": "hyperframes-editor",
|
|
91699
|
+
// Renamed in #1502: it reads chats, and writes memory as a result.
|
|
91700
|
+
"memory-reviewer": "chat-reviewer",
|
|
91701
|
+
// Folded into `copywriting` in #1582.
|
|
91702
|
+
"user-docs": "copywriting"
|
|
91703
|
+
};
|
|
91704
|
+
var canonicalSpecAgent = (name) => {
|
|
91705
|
+
const asked = name.trim();
|
|
91706
|
+
return LEGACY_SPEC_AGENT_NAMES[asked] ?? asked;
|
|
91707
|
+
};
|
|
91440
91708
|
|
|
91441
91709
|
// ../cli/src/lib/agent/workflow-def.ts
|
|
91442
91710
|
var WORKFLOW_ID = /^[a-z0-9]+(-[a-z0-9]+)*$/;
|
|
@@ -91594,26 +91862,26 @@ function checkWorkflowFiles(value, official = false) {
|
|
|
91594
91862
|
|
|
91595
91863
|
// src/built.ts
|
|
91596
91864
|
var isBuilder = (ws) => ws.workflow === BUILDER;
|
|
91597
|
-
var draftDir = (ws) =>
|
|
91598
|
-
var draftLine = (ws) => `<!-- workflow folder: ${
|
|
91865
|
+
var draftDir = (ws) => path27.join(ws.board, "workflows", draftFolder(ws.task));
|
|
91866
|
+
var draftLine = (ws) => `<!-- workflow folder: ${path27.relative(ws.cwd, draftDir(ws)).split(path27.sep).join("/")}/ -->`;
|
|
91599
91867
|
var skeleton = (name) => ["---", `name: ${/\s#/.test(name) ? JSON.stringify(name) : yamlScalar(name)}`, "needsArtifact: false", "---", ""].join("\n");
|
|
91600
91868
|
async function placeDraft(ws, read) {
|
|
91601
91869
|
const dir = draftDir(ws);
|
|
91602
|
-
if (
|
|
91870
|
+
if (fs24.existsSync(path27.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
|
|
91603
91871
|
const task = await read.readTask(ws.task);
|
|
91604
91872
|
if (!task.ok) return task;
|
|
91605
91873
|
let files = { [WORKFLOW_FILE]: skeleton(task.value.title.trim() || "Untitled") };
|
|
91606
91874
|
const changes = task.value.context?.workflow;
|
|
91607
91875
|
if (changes) {
|
|
91608
|
-
const
|
|
91609
|
-
if (!
|
|
91610
|
-
files =
|
|
91876
|
+
const held4 = await read.readWorkflow(changes);
|
|
91877
|
+
if (!held4.ok) return held4;
|
|
91878
|
+
files = held4.value.files;
|
|
91611
91879
|
}
|
|
91612
91880
|
for (const [name, text3] of Object.entries(files)) {
|
|
91613
|
-
const file2 =
|
|
91614
|
-
if (!file2.startsWith(dir +
|
|
91615
|
-
|
|
91616
|
-
|
|
91881
|
+
const file2 = path27.resolve(dir, name);
|
|
91882
|
+
if (!file2.startsWith(dir + path27.sep)) continue;
|
|
91883
|
+
fs24.mkdirSync(path27.dirname(file2), { recursive: true });
|
|
91884
|
+
fs24.writeFileSync(file2, text3);
|
|
91617
91885
|
}
|
|
91618
91886
|
return { ok: true, value: void 0 };
|
|
91619
91887
|
}
|
|
@@ -91625,19 +91893,19 @@ async function builtWorkflow(ws, akb) {
|
|
|
91625
91893
|
const dir = draftDir(ws);
|
|
91626
91894
|
let source;
|
|
91627
91895
|
try {
|
|
91628
|
-
source =
|
|
91896
|
+
source = fs24.readFileSync(path27.join(dir, WORKFLOW_FILE), "utf8");
|
|
91629
91897
|
} catch {
|
|
91630
91898
|
return fail(`workflows/${id}/${WORKFLOW_FILE} is missing.`);
|
|
91631
91899
|
}
|
|
91632
91900
|
const read = parseWorkflowFile(id, source, `workflows/${id}/${WORKFLOW_FILE}`);
|
|
91633
91901
|
if ("problem" in read) return fail(read.problem);
|
|
91634
91902
|
const names2 = named(read.def);
|
|
91635
|
-
|
|
91903
|
+
fs24.rmSync(path27.join(dir, "agents"), { recursive: true, force: true });
|
|
91636
91904
|
for (const name of names2) {
|
|
91637
|
-
const from =
|
|
91638
|
-
if (
|
|
91905
|
+
const from = path27.join(ws.board, "agents", name);
|
|
91906
|
+
if (fs24.existsSync(from)) fs24.cpSync(from, path27.join(dir, "agents", name), { recursive: true });
|
|
91639
91907
|
}
|
|
91640
|
-
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2,
|
|
91908
|
+
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs24.readFileSync(path27.join(dir, f2), "utf8")]));
|
|
91641
91909
|
const checked = checkWorkflowFiles(files);
|
|
91642
91910
|
if (!checked.ok) return fail(`${checked.file} ${checked.reason}.`);
|
|
91643
91911
|
const run2 = async (args) => answerOf2(await runAkb(akb, [...args, "--json", "--board", ws.board], { cwd: ws.cwd, board: ws.board }));
|
|
@@ -91653,10 +91921,10 @@ async function builtWorkflow(ws, akb) {
|
|
|
91653
91921
|
}
|
|
91654
91922
|
|
|
91655
91923
|
// 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[
|
|
91924
|
+
function unavailable(wanted2, reports) {
|
|
91925
|
+
const report2 = reports.find((r2) => r2.name === wanted2);
|
|
91926
|
+
if (!report2?.installed) return `${LABELS[wanted2]} is not installed on this computer.`;
|
|
91927
|
+
if (report2.loggedIn === false) return `${LABELS[wanted2]} is not signed in on this computer.`;
|
|
91660
91928
|
return null;
|
|
91661
91929
|
}
|
|
91662
91930
|
function spentBy(runs) {
|
|
@@ -91670,11 +91938,10 @@ function spentBy(runs) {
|
|
|
91670
91938
|
...context ? { context: { used: context.used, limit: context.limit } } : {}
|
|
91671
91939
|
};
|
|
91672
91940
|
}
|
|
91673
|
-
var SETUP_STEPS = ["project", "agent", "decisions", "modules", "tasks"];
|
|
91674
91941
|
function reviewOf(file2) {
|
|
91675
91942
|
let text3;
|
|
91676
91943
|
try {
|
|
91677
|
-
text3 =
|
|
91944
|
+
text3 = fs25.readFileSync(file2, "utf8");
|
|
91678
91945
|
} catch {
|
|
91679
91946
|
return void 0;
|
|
91680
91947
|
}
|
|
@@ -91688,8 +91955,8 @@ function reviewOf(file2) {
|
|
|
91688
91955
|
}
|
|
91689
91956
|
function mcpConfig(servers, file2) {
|
|
91690
91957
|
if (!Object.keys(servers).length) return null;
|
|
91691
|
-
|
|
91692
|
-
|
|
91958
|
+
fs25.mkdirSync(path28.dirname(file2), { recursive: true });
|
|
91959
|
+
fs25.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
|
|
91693
91960
|
`);
|
|
91694
91961
|
return file2;
|
|
91695
91962
|
}
|
|
@@ -91703,9 +91970,9 @@ function mcpArgs(runtime, servers, file2) {
|
|
|
91703
91970
|
]).join(" ");
|
|
91704
91971
|
}
|
|
91705
91972
|
var MCP_KEY = "mcpConfig";
|
|
91706
|
-
var wait = (
|
|
91707
|
-
async function stopRuns(akb, ws, id, since,
|
|
91708
|
-
const until = Date.now() +
|
|
91973
|
+
var wait = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
91974
|
+
async function stopRuns(akb, ws, id, since, ms) {
|
|
91975
|
+
const until = Date.now() + ms;
|
|
91709
91976
|
const call = (args) => runAkb(akb, [...args, "--board", ws.board], { cwd: ws.cwd, board: ws.board });
|
|
91710
91977
|
while (Date.now() < until) {
|
|
91711
91978
|
const runs = answerOf2(await call(["run", "list", "--card", String(id), "--all", "--json"]))?.runs;
|
|
@@ -91717,36 +91984,36 @@ async function stopRuns(akb, ws, id, since, ms2) {
|
|
|
91717
91984
|
}
|
|
91718
91985
|
var working = /* @__PURE__ */ new Map();
|
|
91719
91986
|
var workKey = (ws, id) => `${ws.board}#${id}`;
|
|
91720
|
-
async function stopLeftBehind(akb, ws, id,
|
|
91721
|
-
if (!working.has(workKey(ws, id))) await stopRuns(akb, ws, id, 0,
|
|
91987
|
+
async function stopLeftBehind(akb, ws, id, ms) {
|
|
91988
|
+
if (!working.has(workKey(ws, id))) await stopRuns(akb, ws, id, 0, ms);
|
|
91722
91989
|
}
|
|
91723
91990
|
function deliveryEnding(ws, id) {
|
|
91724
91991
|
if (!id) return null;
|
|
91725
|
-
let
|
|
91992
|
+
let held4;
|
|
91726
91993
|
try {
|
|
91727
|
-
|
|
91994
|
+
held4 = JSON.parse(fs25.readFileSync(path28.join(ws.board, "deliveries", `${path28.basename(id)}.json`), "utf8"));
|
|
91728
91995
|
} catch {
|
|
91729
91996
|
return null;
|
|
91730
91997
|
}
|
|
91731
|
-
const stopped2 =
|
|
91732
|
-
if (
|
|
91733
|
-
return
|
|
91998
|
+
const stopped2 = held4.review?.stopped;
|
|
91999
|
+
if (held4.status === "cancelled") {
|
|
92000
|
+
return held4.steps?.some((s) => s.step === "discarded") ? { ok: false, reason: "The build was discarded." } : { ok: false, reason: "", stopped: true };
|
|
91734
92001
|
}
|
|
91735
|
-
if (
|
|
92002
|
+
if (held4.status === "active" && stopped2?.reason === "landing") return { ok: false, reason: firstLine(stopped2.why) ?? "The build could not land." };
|
|
91736
92003
|
return null;
|
|
91737
92004
|
}
|
|
91738
92005
|
function checkoutsOf(ws, id) {
|
|
91739
|
-
const dir =
|
|
92006
|
+
const dir = path28.join(ws.board, "deliveries");
|
|
91740
92007
|
let names2;
|
|
91741
92008
|
try {
|
|
91742
|
-
names2 =
|
|
92009
|
+
names2 = fs25.readdirSync(dir).filter((n) => n.endsWith(".json"));
|
|
91743
92010
|
} catch {
|
|
91744
92011
|
return [];
|
|
91745
92012
|
}
|
|
91746
92013
|
return names2.flatMap((n) => {
|
|
91747
92014
|
try {
|
|
91748
|
-
const
|
|
91749
|
-
return
|
|
92015
|
+
const held4 = JSON.parse(fs25.readFileSync(path28.join(dir, n), "utf8"));
|
|
92016
|
+
return held4.cardId === id && held4.worktree && held4.deliveryId ? [held4.deliveryId] : [];
|
|
91750
92017
|
} catch {
|
|
91751
92018
|
return [];
|
|
91752
92019
|
}
|
|
@@ -91755,7 +92022,7 @@ function checkoutsOf(ws, id) {
|
|
|
91755
92022
|
var refusal2 = (ran) => ran.last.replace(/^akb( raw)?: /, "").slice(0, 300) || "akb stopped with an error.";
|
|
91756
92023
|
var firstLine = (text3) => (text3 ?? "").split("\n").map((l2) => l2.trim()).find(Boolean)?.slice(0, 300);
|
|
91757
92024
|
function logLines(show, event2) {
|
|
91758
|
-
let
|
|
92025
|
+
let held4 = "";
|
|
91759
92026
|
const said = (line) => {
|
|
91760
92027
|
if (line.startsWith('{"kind":')) {
|
|
91761
92028
|
let parsed;
|
|
@@ -91781,40 +92048,47 @@ function logLines(show, event2) {
|
|
|
91781
92048
|
};
|
|
91782
92049
|
return {
|
|
91783
92050
|
push: (chunk) => {
|
|
91784
|
-
const lines = (
|
|
91785
|
-
|
|
92051
|
+
const lines = (held4 + chunk).split("\n");
|
|
92052
|
+
held4 = lines.pop();
|
|
91786
92053
|
for (const line of lines) {
|
|
91787
92054
|
const out = said(line);
|
|
91788
92055
|
if (out) show(out);
|
|
91789
92056
|
}
|
|
91790
92057
|
},
|
|
91791
92058
|
end: () => {
|
|
91792
|
-
const out =
|
|
92059
|
+
const out = held4 ? said(held4) : "";
|
|
91793
92060
|
if (out) show(out);
|
|
91794
92061
|
}
|
|
91795
92062
|
};
|
|
91796
92063
|
}
|
|
91797
92064
|
function boardAkb(job, ws, deps, io, task) {
|
|
91798
|
-
return async (args, show = false) => {
|
|
92065
|
+
return async (args, show = false, env2) => {
|
|
91799
92066
|
const at2 = args.includes("--") ? args.indexOf("--") : args.length;
|
|
91800
92067
|
const full = [...args.slice(0, at2), "--board", ws.board, ...args.slice(at2)];
|
|
91801
92068
|
const log = show ? logLines(io.show, io.event) : void 0;
|
|
91802
|
-
const ran = await runAkb(deps.akb, full, { cwd: ws.cwd, board: ws.board, task, line: job.languageLine ?? "", show: log?.push, track: io.track });
|
|
92069
|
+
const ran = await runAkb(deps.akb, full, { cwd: ws.cwd, board: ws.board, task, line: job.languageLine ?? "", env: env2, show: log?.push, track: io.track });
|
|
91803
92070
|
log?.end();
|
|
91804
92071
|
return ran;
|
|
91805
92072
|
};
|
|
91806
92073
|
}
|
|
92074
|
+
function skillStale(dir, version) {
|
|
92075
|
+
try {
|
|
92076
|
+
const text3 = fs25.readFileSync(path28.join(dir, "SKILL.md"), "utf8");
|
|
92077
|
+
return !fs25.lstatSync(dir).isSymbolicLink() && /<!-- ai4kanban (\S+) -->\s*$/.exec(text3)?.[1] !== version;
|
|
92078
|
+
} catch {
|
|
92079
|
+
return true;
|
|
92080
|
+
}
|
|
92081
|
+
}
|
|
91807
92082
|
async function setUp(job, ws, deps, io) {
|
|
91808
92083
|
const akb = boardAkb(job, ws, deps, io);
|
|
91809
92084
|
const runtime = job.runtime;
|
|
91810
92085
|
const missing = unavailable(runtime, await deps.runtimes());
|
|
91811
92086
|
if (missing) return missing;
|
|
91812
|
-
if (!
|
|
92087
|
+
if (!fs25.existsSync(path28.join(ws.board, "config.md"))) {
|
|
91813
92088
|
const init = await akb(["raw", "init"]);
|
|
91814
92089
|
if (init.code !== 0) return refusal2(init);
|
|
91815
|
-
for (const step of SETUP_STEPS) await akb(["raw", "setup-done", step]);
|
|
91816
92090
|
}
|
|
91817
|
-
if (SKILL_FOLDERS.some((f2) =>
|
|
92091
|
+
if (SKILL_FOLDERS.some((f2) => skillStale(path28.join(ws.cwd, f2), deps.akb.version))) {
|
|
91818
92092
|
const skill = await runAkb(deps.akb, ["skill", "install", "--dir", ws.cwd], { cwd: ws.cwd, track: io.track });
|
|
91819
92093
|
if (skill.code !== 0) return refusal2(skill);
|
|
91820
92094
|
}
|
|
@@ -91823,7 +92097,7 @@ async function setUp(job, ws, deps, io) {
|
|
|
91823
92097
|
const used = await akb(["agent", "use", runtime]);
|
|
91824
92098
|
if (used.code !== 0) return refusal2(used);
|
|
91825
92099
|
const servers = mcpServersOf(ws);
|
|
91826
|
-
const mcpFile =
|
|
92100
|
+
const mcpFile = path28.join(ws.board, ".sync", `${ws.task}.mcp.json`);
|
|
91827
92101
|
const takes = new Set(settingKeys(runtime));
|
|
91828
92102
|
const given = job.settings ?? {};
|
|
91829
92103
|
const values = { ...given, model: job.model ?? "" };
|
|
@@ -91873,7 +92147,7 @@ async function reviewRejections(job, ws, deps, io) {
|
|
|
91873
92147
|
const akb = boardAkb(job, ws, deps, io);
|
|
91874
92148
|
return withBoard(ws, async (push2) => {
|
|
91875
92149
|
const laid = layOut(ws.board, read.value);
|
|
91876
|
-
const ran = await akb(["review-dismissals", "--
|
|
92150
|
+
const ran = await akb(["review-dismissals", "--follow", "--events", "--json"], true);
|
|
91877
92151
|
clearLaid(ws.board);
|
|
91878
92152
|
resetSorted(ws);
|
|
91879
92153
|
const runs = (answerOf2(await akb(["run", "list", "--all", "--json"]))?.runs ?? []).filter((r2) => (r2.startedAt ?? 0) >= since);
|
|
@@ -91890,6 +92164,15 @@ async function learnRejections(job, ws, deps, io) {
|
|
|
91890
92164
|
if (failure) console.error(`runner: rejections not learned: ${failure}`);
|
|
91891
92165
|
return runs;
|
|
91892
92166
|
}
|
|
92167
|
+
async function scheduledEnv(ws, deps) {
|
|
92168
|
+
const read = await deps.api.readAgents(deps.machineId, ws.project);
|
|
92169
|
+
if (!read.ok) {
|
|
92170
|
+
console.error(`runner: scheduled agents not read: ${read.error}`);
|
|
92171
|
+
return {};
|
|
92172
|
+
}
|
|
92173
|
+
const names2 = read.value.agents.filter((a3) => a3.workflow).map((a3) => a3.name);
|
|
92174
|
+
return { [SCHEDULED_AGENTS_ENV]: [...new Set(names2)].join(",") };
|
|
92175
|
+
}
|
|
91893
92176
|
async function runAgent(job, ws, deps, io) {
|
|
91894
92177
|
const since = Date.now();
|
|
91895
92178
|
const failed = await setUp(job, ws, deps, io);
|
|
@@ -91904,7 +92187,8 @@ async function runAgent(job, ws, deps, io) {
|
|
|
91904
92187
|
const args = workflow ? ["agent", "run", workflowName(workflow), name] : name === "reflect" ? ["reflect", "--cards", ...tasks.map((t2) => String(t2.number))] : [name];
|
|
91905
92188
|
const akb = boardAkb(job, ws, deps, io, ws.cloudTask ?? void 0);
|
|
91906
92189
|
await akb(["run", "list", "--all", "--json"]);
|
|
91907
|
-
const
|
|
92190
|
+
const env2 = name === "reflect" && !workflow ? await scheduledEnv(ws, deps) : void 0;
|
|
92191
|
+
const ran = await akb([...args, "--follow", "--events", "--json"], true, env2);
|
|
91908
92192
|
if (io.lost()) return { ok: false, reason: "" };
|
|
91909
92193
|
const answer = answerOf2(ran);
|
|
91910
92194
|
if (ran.code !== 0) return { ok: false, reason: firstLine(answer?.error?.message?.replace(/^run \S+ ended \w+: /, "")) ?? refusal2(ran) };
|
|
@@ -91913,19 +92197,19 @@ async function runAgent(job, ws, deps, io) {
|
|
|
91913
92197
|
}
|
|
91914
92198
|
function writeTranscript(job, dir) {
|
|
91915
92199
|
if (!job.transcript) return "";
|
|
91916
|
-
const file2 =
|
|
91917
|
-
|
|
91918
|
-
|
|
92200
|
+
const file2 = path28.join(dir, "discussion.md");
|
|
92201
|
+
fs25.mkdirSync(dir, { recursive: true });
|
|
92202
|
+
fs25.writeFileSync(file2, `${job.transcript}
|
|
91919
92203
|
`);
|
|
91920
92204
|
return file2;
|
|
91921
92205
|
}
|
|
91922
92206
|
function pictures(job, ws, id) {
|
|
91923
92207
|
const dir = cardAssetsDir(ws, id);
|
|
91924
92208
|
if (!job.attachments.length || !dir) return "";
|
|
91925
|
-
|
|
92209
|
+
fs25.mkdirSync(dir, { recursive: true });
|
|
91926
92210
|
return job.attachments.map((a3, i) => {
|
|
91927
|
-
const file2 = `${i + 1}-${
|
|
91928
|
-
|
|
92211
|
+
const file2 = `${i + 1}-${path28.basename(a3.name).replace(/[^\w.-]+/g, "-")}`;
|
|
92212
|
+
fs25.writeFileSync(path28.join(dir, file2), Buffer.from(a3.content, "base64"));
|
|
91929
92213
|
return `
|
|
91930
92214
|
<Asset src=".assets/${id}/${file2}" label="${a3.name.replace(/["<>]/g, "") || file2}" />
|
|
91931
92215
|
`;
|
|
@@ -91933,11 +92217,10 @@ function pictures(job, ws, id) {
|
|
|
91933
92217
|
}
|
|
91934
92218
|
function cardFlags(ws, fields) {
|
|
91935
92219
|
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(
|
|
92220
|
+
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
92221
|
const lists = [["--modules", fields.modules ?? []], ["--related", open(fields.related)], ["--blocked-by", open(fields.blocked_by)]];
|
|
91938
92222
|
return [
|
|
91939
92223
|
...fields.priority ? ["--priority", fields.priority] : [],
|
|
91940
|
-
...fields.roi ? ["--roi", fields.roi] : [],
|
|
91941
92224
|
...lists.flatMap(([flag, list]) => list.length ? [flag, list.join(",")] : [])
|
|
91942
92225
|
];
|
|
91943
92226
|
}
|
|
@@ -91968,10 +92251,10 @@ async function runFlow(job, ws, deps, io) {
|
|
|
91968
92251
|
const placed = await placeDraft(ws, deps.api);
|
|
91969
92252
|
if (!placed.ok) return fail(placed.error);
|
|
91970
92253
|
}
|
|
91971
|
-
const body =
|
|
91972
|
-
|
|
92254
|
+
const body = path28.join(ws.board, ".sync", `${ws.task}.request.md`);
|
|
92255
|
+
fs25.mkdirSync(path28.dirname(body), { recursive: true });
|
|
91973
92256
|
if (!ws.number) return fail("This task has no number yet.");
|
|
91974
|
-
|
|
92257
|
+
fs25.writeFileSync(body, `${said.request || title}
|
|
91975
92258
|
${isBuilder(ws) ? `
|
|
91976
92259
|
${draftLine(ws)}
|
|
91977
92260
|
` : ""}${pictures(job, ws, ws.number)}`);
|
|
@@ -91989,21 +92272,21 @@ ${draftLine(ws)}
|
|
|
91989
92272
|
...cardFlags(ws, flow.metadata),
|
|
91990
92273
|
"--json"
|
|
91991
92274
|
]));
|
|
91992
|
-
|
|
92275
|
+
fs25.rmSync(body, { force: true });
|
|
91993
92276
|
if (!created.ok) return fail(created.error);
|
|
91994
92277
|
id = created.value;
|
|
91995
92278
|
}
|
|
91996
92279
|
if (!id) return fail("This task has no card on this computer.");
|
|
91997
92280
|
const card = id;
|
|
91998
92281
|
const key = workKey(ws, card);
|
|
91999
|
-
const
|
|
92000
|
-
working.set(key,
|
|
92282
|
+
const held4 = working.get(key) ?? 0;
|
|
92283
|
+
working.set(key, held4 + 1);
|
|
92001
92284
|
try {
|
|
92002
|
-
if (!
|
|
92285
|
+
if (!held4) await stopRuns(deps.akb, ws, card, 0, deps.stopMs);
|
|
92003
92286
|
if (io.lost()) return fail("");
|
|
92004
92287
|
return await workOn(card);
|
|
92005
92288
|
} finally {
|
|
92006
|
-
|
|
92289
|
+
fs25.rmSync(path28.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
|
|
92007
92290
|
const left = working.get(key) - 1;
|
|
92008
92291
|
if (left) working.set(key, left);
|
|
92009
92292
|
else working.delete(key);
|
|
@@ -92055,8 +92338,8 @@ ${draftLine(ws)}
|
|
|
92055
92338
|
return { ok: true, report: { card: card2 } };
|
|
92056
92339
|
}
|
|
92057
92340
|
function carryArgs(verb) {
|
|
92058
|
-
if (!["refine", "resolve", "revise"].includes(verb)) return [];
|
|
92059
|
-
const transcript = writeTranscript(job,
|
|
92341
|
+
if (!["refine", "resolve", "revise", "implement"].includes(verb)) return [];
|
|
92342
|
+
const transcript = writeTranscript(job, path28.join(ws.board, ".sync", `${ws.task}.discussion`));
|
|
92060
92343
|
return [
|
|
92061
92344
|
...job.resume ? ["--session", job.resume, ...job.fork ? ["--fork"] : []] : [],
|
|
92062
92345
|
...transcript ? ["--transcript", transcript] : []
|
|
@@ -92065,17 +92348,17 @@ ${draftLine(ws)}
|
|
|
92065
92348
|
}
|
|
92066
92349
|
|
|
92067
92350
|
// src/lock.ts
|
|
92068
|
-
import
|
|
92069
|
-
import
|
|
92351
|
+
import crypto4 from "node:crypto";
|
|
92352
|
+
import fs26 from "node:fs";
|
|
92070
92353
|
import net from "node:net";
|
|
92071
|
-
import
|
|
92354
|
+
import path29 from "node:path";
|
|
92072
92355
|
var RETRY_MS = 5e3;
|
|
92073
92356
|
var KIND_MS = 1e3;
|
|
92074
92357
|
var HOLDERS = ["claude-code", "codex", "terminal", "desktop"];
|
|
92075
92358
|
function lockPath() {
|
|
92076
92359
|
const home4 = runnerHome();
|
|
92077
|
-
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${
|
|
92078
|
-
return
|
|
92360
|
+
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${crypto4.createHash("sha256").update(home4).digest("hex").slice(0, 16)}`;
|
|
92361
|
+
return path29.join(home4, "runner.sock");
|
|
92079
92362
|
}
|
|
92080
92363
|
function holdMachine(kind, onHeld, onWaiting) {
|
|
92081
92364
|
const where = lockPath();
|
|
@@ -92084,13 +92367,13 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92084
92367
|
let waiting = null;
|
|
92085
92368
|
let timer = null;
|
|
92086
92369
|
const peers = /* @__PURE__ */ new Set();
|
|
92087
|
-
const later = (
|
|
92088
|
-
if (!closed) timer = setTimeout(attempt,
|
|
92370
|
+
const later = (ms) => {
|
|
92371
|
+
if (!closed) timer = setTimeout(attempt, ms);
|
|
92089
92372
|
};
|
|
92090
92373
|
const attempt = () => {
|
|
92091
92374
|
timer = null;
|
|
92092
92375
|
if (closed) return;
|
|
92093
|
-
if (process.platform !== "win32")
|
|
92376
|
+
if (process.platform !== "win32") fs26.mkdirSync(path29.dirname(where), { recursive: true, mode: 448 });
|
|
92094
92377
|
const s = net.createServer((peer) => {
|
|
92095
92378
|
peers.add(peer);
|
|
92096
92379
|
peer.on("error", () => {
|
|
@@ -92138,7 +92421,7 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92138
92421
|
later(0);
|
|
92139
92422
|
});
|
|
92140
92423
|
removeIfStill.once("error", () => {
|
|
92141
|
-
|
|
92424
|
+
fs26.rmSync(where, { force: true });
|
|
92142
92425
|
later(50 + Math.random() * 200);
|
|
92143
92426
|
});
|
|
92144
92427
|
return;
|
|
@@ -92167,13 +92450,117 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92167
92450
|
|
|
92168
92451
|
// src/jobs.ts
|
|
92169
92452
|
import { spawn as spawn4 } from "node:child_process";
|
|
92170
|
-
import
|
|
92171
|
-
import
|
|
92453
|
+
import fs29 from "node:fs";
|
|
92454
|
+
import path32 from "node:path";
|
|
92455
|
+
|
|
92456
|
+
// ../cli/src/lib/agent/catalog.ts
|
|
92457
|
+
import fs27 from "node:fs";
|
|
92458
|
+
import path30 from "node:path";
|
|
92459
|
+
var CATALOGUE = "https://models.dev/api.json";
|
|
92460
|
+
var FRESH_FOR_MS = 24 * 60 * 6e4;
|
|
92461
|
+
var ANSWER_BY_MS = 2e4;
|
|
92462
|
+
function cacheFile() {
|
|
92463
|
+
return path30.join(machineHome(), "models-dev.json");
|
|
92464
|
+
}
|
|
92465
|
+
var held2;
|
|
92466
|
+
function readCache() {
|
|
92467
|
+
const file2 = cacheFile();
|
|
92468
|
+
let stamp2;
|
|
92469
|
+
try {
|
|
92470
|
+
const stat = fs27.statSync(file2);
|
|
92471
|
+
stamp2 = `${stat.mtimeMs}:${stat.size}`;
|
|
92472
|
+
} catch {
|
|
92473
|
+
return void 0;
|
|
92474
|
+
}
|
|
92475
|
+
if (held2?.stamp === stamp2) return held2.cached;
|
|
92476
|
+
try {
|
|
92477
|
+
const data = JSON.parse(fs27.readFileSync(file2, "utf8"));
|
|
92478
|
+
if (!data || typeof data.limits !== "object" || !data.limits) return void 0;
|
|
92479
|
+
const cached2 = {
|
|
92480
|
+
fetchedAt: typeof data.fetchedAt === "number" ? data.fetchedAt : 0,
|
|
92481
|
+
limits: data.limits
|
|
92482
|
+
};
|
|
92483
|
+
held2 = { stamp: stamp2, cached: cached2 };
|
|
92484
|
+
return cached2;
|
|
92485
|
+
} catch {
|
|
92486
|
+
return void 0;
|
|
92487
|
+
}
|
|
92488
|
+
}
|
|
92489
|
+
function limitsIn(data) {
|
|
92490
|
+
const limits = {};
|
|
92491
|
+
if (!data || typeof data !== "object") return limits;
|
|
92492
|
+
for (const [provider, raw] of Object.entries(data)) {
|
|
92493
|
+
const models = raw?.models;
|
|
92494
|
+
if (!models || typeof models !== "object") continue;
|
|
92495
|
+
for (const [model, entry] of Object.entries(models)) {
|
|
92496
|
+
const context = entry?.limit?.context;
|
|
92497
|
+
if (typeof context === "number" && Number.isFinite(context) && context > 0) {
|
|
92498
|
+
limits[`${provider}/${model}`] = context;
|
|
92499
|
+
}
|
|
92500
|
+
}
|
|
92501
|
+
}
|
|
92502
|
+
return limits;
|
|
92503
|
+
}
|
|
92504
|
+
var fetching2;
|
|
92505
|
+
function refreshCatalog() {
|
|
92506
|
+
if (fetching2) return fetching2;
|
|
92507
|
+
const cached2 = readCache();
|
|
92508
|
+
if (cached2 && Date.now() - cached2.fetchedAt < FRESH_FOR_MS) return Promise.resolve();
|
|
92509
|
+
fetching2 = (async () => {
|
|
92510
|
+
try {
|
|
92511
|
+
const answer = await fetch(CATALOGUE, { signal: AbortSignal.timeout(ANSWER_BY_MS) });
|
|
92512
|
+
if (!answer.ok) return;
|
|
92513
|
+
const limits = limitsIn(await answer.json());
|
|
92514
|
+
if (Object.keys(limits).length === 0) return;
|
|
92515
|
+
const file2 = cacheFile();
|
|
92516
|
+
fs27.mkdirSync(path30.dirname(file2), { recursive: true });
|
|
92517
|
+
fs27.writeFileSync(file2, JSON.stringify({ fetchedAt: Date.now(), limits }));
|
|
92518
|
+
} catch {
|
|
92519
|
+
}
|
|
92520
|
+
})();
|
|
92521
|
+
return fetching2;
|
|
92522
|
+
}
|
|
92523
|
+
var PROVIDERS = {
|
|
92524
|
+
"claude-code": ["anthropic"],
|
|
92525
|
+
zcode: ["zai", "zhipuai"],
|
|
92526
|
+
kimi: ["moonshotai", "moonshotai-cn"],
|
|
92527
|
+
opencode: ["opencode"]
|
|
92528
|
+
};
|
|
92529
|
+
function spellings(model) {
|
|
92530
|
+
const id = model.trim().toLowerCase();
|
|
92531
|
+
if (!id) return [];
|
|
92532
|
+
const undated = id.replace(/-\d{8}$/, "");
|
|
92533
|
+
return [.../* @__PURE__ */ new Set([id, undated])];
|
|
92534
|
+
}
|
|
92535
|
+
function contextLimit(harness, model) {
|
|
92536
|
+
if (!model?.trim()) return void 0;
|
|
92537
|
+
const limits = readCache()?.limits;
|
|
92538
|
+
if (!limits) return void 0;
|
|
92539
|
+
const cut2 = model.lastIndexOf("/");
|
|
92540
|
+
if (cut2 > 0) {
|
|
92541
|
+
const whole = model.trim().toLowerCase();
|
|
92542
|
+
if (limits[whole]) return limits[whole];
|
|
92543
|
+
}
|
|
92544
|
+
const bare = cut2 > 0 ? model.slice(cut2 + 1) : model;
|
|
92545
|
+
const ids = spellings(bare);
|
|
92546
|
+
for (const provider of PROVIDERS[harness] ?? []) {
|
|
92547
|
+
for (const id of ids) {
|
|
92548
|
+
const found = limits[`${provider}/${id}`];
|
|
92549
|
+
if (found) return found;
|
|
92550
|
+
}
|
|
92551
|
+
}
|
|
92552
|
+
let widest = 0;
|
|
92553
|
+
for (const [key, limit] of Object.entries(limits)) {
|
|
92554
|
+
const id = key.slice(key.indexOf("/") + 1);
|
|
92555
|
+
if (ids.includes(id) && limit > widest) widest = limit;
|
|
92556
|
+
}
|
|
92557
|
+
return widest || void 0;
|
|
92558
|
+
}
|
|
92172
92559
|
|
|
92173
92560
|
// src/ideas.ts
|
|
92174
|
-
import
|
|
92175
|
-
import
|
|
92176
|
-
var ideasFileOf = (job) =>
|
|
92561
|
+
import fs28 from "node:fs";
|
|
92562
|
+
import path31 from "node:path";
|
|
92563
|
+
var ideasFileOf = (job) => path31.join(runnerHome(), "ideas", `${job.id}.json`);
|
|
92177
92564
|
async function writeIdeas(job, list) {
|
|
92178
92565
|
const workflows = [];
|
|
92179
92566
|
let after = null;
|
|
@@ -92184,24 +92571,23 @@ async function writeIdeas(job, list) {
|
|
|
92184
92571
|
after = page.value.next;
|
|
92185
92572
|
} while (after);
|
|
92186
92573
|
const file2 = ideasFileOf(job);
|
|
92187
|
-
|
|
92188
|
-
|
|
92574
|
+
fs28.mkdirSync(path31.dirname(file2), { recursive: true });
|
|
92575
|
+
fs28.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: job.discussion.ideas }, null, 2)}
|
|
92189
92576
|
`);
|
|
92190
92577
|
return { file: file2 };
|
|
92191
92578
|
}
|
|
92192
92579
|
function readIdeas(file2) {
|
|
92193
92580
|
try {
|
|
92194
|
-
return JSON.parse(
|
|
92581
|
+
return JSON.parse(fs28.readFileSync(file2, "utf8")).ideas;
|
|
92195
92582
|
} catch {
|
|
92196
92583
|
return void 0;
|
|
92197
92584
|
} finally {
|
|
92198
|
-
|
|
92585
|
+
fs28.rmSync(file2, { force: true });
|
|
92199
92586
|
}
|
|
92200
92587
|
}
|
|
92201
92588
|
|
|
92202
92589
|
// src/jobs.ts
|
|
92203
|
-
var
|
|
92204
|
-
var QUIET_MS = 15e3;
|
|
92590
|
+
var FLUSH_MS = 2e3;
|
|
92205
92591
|
var FLUSH_CHARS = 32 * 1024;
|
|
92206
92592
|
var BATCH_EVENTS = 500;
|
|
92207
92593
|
var BATCH_CHARS = 512 * 1024;
|
|
@@ -92209,6 +92595,7 @@ var EVENT_CHARS = 64 * 1024;
|
|
|
92209
92595
|
var END_MS = 1e4;
|
|
92210
92596
|
var RECONNECT_MS = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
92211
92597
|
var RENEW_MS = 5 * 6e4;
|
|
92598
|
+
var LOG_PING_MS = 3e4;
|
|
92212
92599
|
var LEASE_MS = 15 * 6e4;
|
|
92213
92600
|
var RETRY_MS2 = 3e4;
|
|
92214
92601
|
var KILL_GRACE_MS = 5e3;
|
|
@@ -92219,7 +92606,8 @@ var defaultDeps = (machineId2) => ({
|
|
|
92219
92606
|
machineId: machineId2,
|
|
92220
92607
|
api: api_exports,
|
|
92221
92608
|
plan,
|
|
92222
|
-
flushMs:
|
|
92609
|
+
flushMs: FLUSH_MS,
|
|
92610
|
+
logPingMs: LOG_PING_MS,
|
|
92223
92611
|
endMs: END_MS,
|
|
92224
92612
|
renewMs: RENEW_MS,
|
|
92225
92613
|
leaseMs: LEASE_MS,
|
|
@@ -92227,35 +92615,35 @@ var defaultDeps = (machineId2) => ({
|
|
|
92227
92615
|
testMs: TEST_MS,
|
|
92228
92616
|
stopMs: STOP_MS,
|
|
92229
92617
|
watchMs: WATCH_MS,
|
|
92230
|
-
akb:
|
|
92618
|
+
akb: currentAkb,
|
|
92231
92619
|
runtimes: detectRuntimes
|
|
92232
92620
|
});
|
|
92233
|
-
var ownFolder = () =>
|
|
92621
|
+
var ownFolder = () => path32.join(runnerHome(), "work");
|
|
92234
92622
|
function folderFor(job) {
|
|
92235
92623
|
if (!job.projectDir) {
|
|
92236
|
-
const cwd =
|
|
92237
|
-
|
|
92624
|
+
const cwd = path32.join(ownFolder(), job.id);
|
|
92625
|
+
fs29.mkdirSync(cwd, { recursive: true });
|
|
92238
92626
|
return { cwd };
|
|
92239
92627
|
}
|
|
92240
92628
|
const real = realpath4(job.projectDir);
|
|
92241
|
-
if (real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
92629
|
+
if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path32.sep))) return { cwd: real };
|
|
92242
92630
|
return { refused: `This Runner is not allowed to work in ${job.projectDir}.` };
|
|
92243
92631
|
}
|
|
92244
92632
|
function realpath4(p2) {
|
|
92245
92633
|
try {
|
|
92246
|
-
return
|
|
92634
|
+
return fs29.realpathSync(p2);
|
|
92247
92635
|
} catch {
|
|
92248
92636
|
return null;
|
|
92249
92637
|
}
|
|
92250
92638
|
}
|
|
92251
|
-
var attachmentsOf = (job) =>
|
|
92639
|
+
var attachmentsOf = (job) => path32.join(runnerHome(), "attachments", job.id);
|
|
92252
92640
|
function writeAttachments(job) {
|
|
92253
92641
|
if (!job.attachments.length) return "";
|
|
92254
92642
|
const dir = attachmentsOf(job);
|
|
92255
|
-
|
|
92643
|
+
fs29.mkdirSync(dir, { recursive: true });
|
|
92256
92644
|
const files = job.attachments.map((a3) => {
|
|
92257
|
-
const file2 =
|
|
92258
|
-
|
|
92645
|
+
const file2 = path32.join(dir, path32.basename(a3.name));
|
|
92646
|
+
fs29.writeFileSync(file2, Buffer.from(a3.content, "base64"));
|
|
92259
92647
|
return file2;
|
|
92260
92648
|
});
|
|
92261
92649
|
return `
|
|
@@ -92292,12 +92680,13 @@ function streamOut(deps, id, lease) {
|
|
|
92292
92680
|
let ending = false;
|
|
92293
92681
|
let closed = false;
|
|
92294
92682
|
let flushedAt = Date.now();
|
|
92295
|
-
const log = { ws: null, after: null, watched: false, tries: 0, retry: void 0 };
|
|
92683
|
+
const log = { ws: null, after: null, watched: false, heard: 0, tries: 0, retry: void 0 };
|
|
92296
92684
|
let ended2 = () => {
|
|
92297
92685
|
};
|
|
92298
92686
|
const stored = new Promise((resolve2) => ended2 = resolve2);
|
|
92299
92687
|
const children = /* @__PURE__ */ new Set();
|
|
92300
92688
|
const kill = (child) => {
|
|
92689
|
+
if (!child.pid) return;
|
|
92301
92690
|
child.kill("SIGTERM");
|
|
92302
92691
|
setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS).unref();
|
|
92303
92692
|
};
|
|
@@ -92326,7 +92715,7 @@ function streamOut(deps, id, lease) {
|
|
|
92326
92715
|
const ws = log.ws;
|
|
92327
92716
|
if (!ws || ws.readyState !== WebSocket.OPEN || log.after === null) return;
|
|
92328
92717
|
const after = log.after;
|
|
92329
|
-
const unsent2 = wire.filter((e2) => e2.seq > after);
|
|
92718
|
+
const unsent2 = log.watched ? wire.filter((e2) => e2.seq > after) : [];
|
|
92330
92719
|
let batch = [];
|
|
92331
92720
|
let chars = 0;
|
|
92332
92721
|
const out = () => {
|
|
@@ -92357,7 +92746,9 @@ function streamOut(deps, id, lease) {
|
|
|
92357
92746
|
if (closed) return ws?.close();
|
|
92358
92747
|
if (!ws) return reconnect();
|
|
92359
92748
|
log.ws = ws;
|
|
92749
|
+
log.heard = Date.now();
|
|
92360
92750
|
ws.addEventListener("message", (m) => {
|
|
92751
|
+
log.heard = Date.now();
|
|
92361
92752
|
let said;
|
|
92362
92753
|
try {
|
|
92363
92754
|
said = JSON.parse(String(m.data));
|
|
@@ -92368,22 +92759,23 @@ function streamOut(deps, id, lease) {
|
|
|
92368
92759
|
log.tries = 0;
|
|
92369
92760
|
log.after = Number.isInteger(said.after) ? said.after : -1;
|
|
92370
92761
|
log.watched = said.watched === true;
|
|
92371
|
-
|
|
92762
|
+
flush();
|
|
92372
92763
|
} else if (said.type === "watched") {
|
|
92373
92764
|
log.watched = said.on === true;
|
|
92374
92765
|
if (log.watched) flush();
|
|
92375
92766
|
} else if (said.type === "ended") ended2();
|
|
92376
92767
|
else if (said.type === "stop") ask();
|
|
92377
92768
|
});
|
|
92378
|
-
ws.addEventListener("close", () =>
|
|
92379
|
-
if (log.ws !== ws) return;
|
|
92380
|
-
log.ws = null;
|
|
92381
|
-
log.after = null;
|
|
92382
|
-
reconnect();
|
|
92383
|
-
});
|
|
92769
|
+
ws.addEventListener("close", () => drop(ws));
|
|
92384
92770
|
ws.addEventListener("error", () => {
|
|
92385
92771
|
});
|
|
92386
92772
|
};
|
|
92773
|
+
const drop = (ws) => {
|
|
92774
|
+
if (log.ws !== ws) return;
|
|
92775
|
+
log.ws = null;
|
|
92776
|
+
log.after = null;
|
|
92777
|
+
reconnect();
|
|
92778
|
+
};
|
|
92387
92779
|
const reconnect = () => {
|
|
92388
92780
|
if (log.retry || lost || closed) return;
|
|
92389
92781
|
log.retry = setTimeout(() => void connect2(), RECONNECT_MS[Math.min(log.tries++, RECONNECT_MS.length - 1)]);
|
|
@@ -92393,12 +92785,18 @@ function streamOut(deps, id, lease) {
|
|
|
92393
92785
|
if (e2.kind === "message") messages.push(e2.data.text);
|
|
92394
92786
|
pending.push(e2);
|
|
92395
92787
|
size += JSON.stringify(e2.data).length;
|
|
92396
|
-
if (size >= FLUSH_CHARS) flush();
|
|
92788
|
+
if (log.watched && size >= FLUSH_CHARS) flush();
|
|
92397
92789
|
};
|
|
92398
|
-
const tick = Math.min(deps.flushMs.watched, 1e3);
|
|
92399
92790
|
const flusher = setInterval(() => {
|
|
92400
|
-
if (pending.length && Date.now() - flushedAt >=
|
|
92401
|
-
},
|
|
92791
|
+
if (log.watched && pending.length && Date.now() - flushedAt >= deps.flushMs) flush();
|
|
92792
|
+
}, Math.min(deps.flushMs, 1e3));
|
|
92793
|
+
const pinger = setInterval(() => {
|
|
92794
|
+
const ws = log.ws;
|
|
92795
|
+
if (ws?.readyState !== WebSocket.OPEN) return;
|
|
92796
|
+
if (Date.now() - log.heard <= deps.logPingMs * 2) return ws.send("ping");
|
|
92797
|
+
drop(ws);
|
|
92798
|
+
ws.close();
|
|
92799
|
+
}, deps.logPingMs);
|
|
92402
92800
|
const renewer = setInterval(async () => {
|
|
92403
92801
|
const renewed = await deps.api.renewJob(deps.machineId, id);
|
|
92404
92802
|
if (renewed.ok && !renewed.value.renewed) return void loseLease();
|
|
@@ -92432,6 +92830,7 @@ function streamOut(deps, id, lease) {
|
|
|
92432
92830
|
/** The rest sent and the log stored, or given up on after a while: `finish` comes after. */
|
|
92433
92831
|
end: async () => {
|
|
92434
92832
|
clearInterval(flusher);
|
|
92833
|
+
clearInterval(pinger);
|
|
92435
92834
|
clearInterval(renewer);
|
|
92436
92835
|
ending = !lost;
|
|
92437
92836
|
flush();
|
|
@@ -92453,12 +92852,12 @@ async function runJob(id, deps, track = () => {
|
|
|
92453
92852
|
const claim = await deps.api.claimJob(deps.machineId, id);
|
|
92454
92853
|
if (!claim.ok || !claim.value.claimed) return;
|
|
92455
92854
|
const job = claim.value.job;
|
|
92456
|
-
const
|
|
92855
|
+
const held4 = [];
|
|
92457
92856
|
try {
|
|
92458
|
-
await runClaimed(job, deps, track, (dir) =>
|
|
92857
|
+
await runClaimed(job, { ...deps, akb: deps.akb() }, track, (dir) => held4.push(hold(dir)));
|
|
92459
92858
|
} finally {
|
|
92460
|
-
for (const release2 of
|
|
92461
|
-
|
|
92859
|
+
for (const release2 of held4) release2();
|
|
92860
|
+
fs29.rmSync(attachmentsOf(job), { recursive: true, force: true });
|
|
92462
92861
|
}
|
|
92463
92862
|
}
|
|
92464
92863
|
async function runClaimed(job, deps, track, keep2) {
|
|
@@ -92502,6 +92901,7 @@ async function runClaimed(job, deps, track, keep2) {
|
|
|
92502
92901
|
ideas = wrote.file;
|
|
92503
92902
|
}
|
|
92504
92903
|
if (!job.flow && !job.review) {
|
|
92904
|
+
void refreshCatalog();
|
|
92505
92905
|
const head2 = folderLines(ws) + writeAttachments(job);
|
|
92506
92906
|
const file2 = writeTranscript(job, attachmentsOf(job));
|
|
92507
92907
|
const transcript = file2 ? `
|
|
@@ -92538,6 +92938,7 @@ ${job.prompt}` : job.prompt;
|
|
|
92538
92938
|
for (const task2 of job.review.tasks) {
|
|
92539
92939
|
const chat = await deps.api.readChat(task2);
|
|
92540
92940
|
if (chat.ok) keepCloudChat(task2, chat.value.messages);
|
|
92941
|
+
await keepDecisions(task2, deps.api.readDecisions);
|
|
92541
92942
|
}
|
|
92542
92943
|
const listed2 = await deps.api.listChats(deps.machineId);
|
|
92543
92944
|
if (!listed2.ok) {
|
|
@@ -92583,7 +92984,7 @@ ${job.prompt}` : job.prompt;
|
|
|
92583
92984
|
await stream.end();
|
|
92584
92985
|
if (stream.lost()) return;
|
|
92585
92986
|
const ok = end.ok || stream.asked();
|
|
92586
|
-
const said2 = told(stream.asked() ? cutShort(report(plan3, end), stream.said()) : report(plan3, end));
|
|
92987
|
+
const said2 = told(stream.asked() ? cutShort(report(job, plan3, end), stream.said()) : report(job, plan3, end));
|
|
92587
92988
|
if (!ok || !ws) return finish(deps, id, lease, ok ? "done" : "failed", ok ? "" : end.error ?? "", said2);
|
|
92588
92989
|
return sendBack(deps, id, lease, ws, said2, () => keepChat(job, said2.reply));
|
|
92589
92990
|
}
|
|
@@ -92624,7 +93025,7 @@ ${job.prompt}` : job.prompt;
|
|
|
92624
93025
|
await stream.end();
|
|
92625
93026
|
if (stream.lost()) return;
|
|
92626
93027
|
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));
|
|
93028
|
+
const said = told(stream.asked() ? cutShort(report(job, plan2), stream.said()) : report(job, plan2));
|
|
92628
93029
|
if (failure || !ws) return finish(deps, id, lease, failure ? "failed" : "done", failure, said);
|
|
92629
93030
|
return sendBack(deps, id, lease, ws, said, () => keepChat(job, said.reply));
|
|
92630
93031
|
}
|
|
@@ -92651,15 +93052,16 @@ async function runAgentJob(job, deps, track, keep2) {
|
|
|
92651
93052
|
var quietLines = (plan2, chunk) => chunk.split("\n").filter((line) => line && !plan2.quiet(line)).map((line) => `${line}
|
|
92652
93053
|
`).join("");
|
|
92653
93054
|
var stop = (child) => {
|
|
93055
|
+
if (!child.pid) return;
|
|
92654
93056
|
child.kill("SIGTERM");
|
|
92655
93057
|
setTimeout(() => child.kill("SIGKILL"), KILL_GRACE_MS).unref();
|
|
92656
93058
|
};
|
|
92657
|
-
var wait2 = (
|
|
92658
|
-
var
|
|
93059
|
+
var wait2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
93060
|
+
var held3 = (deps, lease) => Date.now() - lease.at < deps.leaseMs;
|
|
92659
93061
|
async function whileOffline(deps, id, lease, attempt) {
|
|
92660
93062
|
for (; ; ) {
|
|
92661
93063
|
const out = await attempt();
|
|
92662
|
-
if (!("offline" in out && out.offline) || !
|
|
93064
|
+
if (!("offline" in out && out.offline) || !held3(deps, lease)) return out;
|
|
92663
93065
|
await wait2(deps.retryMs);
|
|
92664
93066
|
const renewed = await deps.api.renewJob(deps.machineId, id);
|
|
92665
93067
|
if (renewed.ok && renewed.value.renewed) lease.at = Date.now();
|
|
@@ -92700,14 +93102,14 @@ async function runSecret(job, deps) {
|
|
|
92700
93102
|
await deps.api.finishJob(deps.machineId, job.id, "done", "");
|
|
92701
93103
|
}
|
|
92702
93104
|
async function runTest(job, deps) {
|
|
92703
|
-
const finish2 = async (outcome, reason,
|
|
92704
|
-
await deps.api.finishJob(deps.machineId, job.id, outcome, reason,
|
|
93105
|
+
const finish2 = async (outcome, reason, ms2) => {
|
|
93106
|
+
await deps.api.finishJob(deps.machineId, job.id, outcome, reason, ms2 === void 0 ? void 0 : { ms: ms2 });
|
|
92705
93107
|
};
|
|
92706
93108
|
const report2 = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
|
|
92707
93109
|
if (!report2?.installed) return finish2("failed", "not_installed");
|
|
92708
93110
|
if (report2.loggedIn === false) return finish2("failed", "signed_out");
|
|
92709
|
-
const cwd =
|
|
92710
|
-
|
|
93111
|
+
const cwd = path32.join(ownFolder(), "test");
|
|
93112
|
+
fs29.mkdirSync(cwd, { recursive: true });
|
|
92711
93113
|
const run2 = deps.plan(job.runtime, job.prompt, cwd, null, job.model, settingsOf(job));
|
|
92712
93114
|
const startedAt = Date.now();
|
|
92713
93115
|
if (run2.converse) {
|
|
@@ -92723,10 +93125,10 @@ async function runTest(job, deps) {
|
|
|
92723
93125
|
]);
|
|
92724
93126
|
clearTimeout(timer);
|
|
92725
93127
|
stop(child);
|
|
92726
|
-
const
|
|
92727
|
-
if (end === "timeout") return finish2("failed", "timeout",
|
|
92728
|
-
if (end instanceof Error) return end.code === "ENOENT" ? finish2("failed", "not_installed") : finish2("failed", end.message.slice(0, 300),
|
|
92729
|
-
return end.ok ? finish2("done", "",
|
|
93128
|
+
const ms2 = Date.now() - startedAt;
|
|
93129
|
+
if (end === "timeout") return finish2("failed", "timeout", ms2);
|
|
93130
|
+
if (end instanceof Error) return end.code === "ENOENT" ? finish2("failed", "not_installed") : finish2("failed", end.message.slice(0, 300), ms2);
|
|
93131
|
+
return end.ok ? finish2("done", "", ms2) : finish2("failed", (end.error || "The connector stopped.").slice(0, 300), ms2);
|
|
92730
93132
|
}
|
|
92731
93133
|
const renderer = run2.renderer;
|
|
92732
93134
|
const ended2 = await new Promise((resolve2) => {
|
|
@@ -92760,16 +93162,17 @@ async function runTest(job, deps) {
|
|
|
92760
93162
|
resolve2({ code, said });
|
|
92761
93163
|
});
|
|
92762
93164
|
});
|
|
92763
|
-
const
|
|
92764
|
-
if (ended2.timedOut) return finish2("failed", "timeout",
|
|
93165
|
+
const ms = Date.now() - startedAt;
|
|
93166
|
+
if (ended2.timedOut) return finish2("failed", "timeout", ms);
|
|
92765
93167
|
if (ended2.error?.code === "ENOENT") return finish2("failed", "not_installed");
|
|
92766
93168
|
renderer.flush();
|
|
92767
93169
|
const failure = ended2.error?.message ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : ended2.said.trim().split("\n").at(-1) || `Exited with code ${ended2.code}.`);
|
|
92768
|
-
if (failure) return finish2("failed", failure.slice(0, 300),
|
|
92769
|
-
return finish2("done", "",
|
|
93170
|
+
if (failure) return finish2("failed", failure.slice(0, 300), ms);
|
|
93171
|
+
return finish2("done", "", ms);
|
|
92770
93172
|
}
|
|
92771
|
-
function report(run2, turn) {
|
|
93173
|
+
function report(job, run2, turn) {
|
|
92772
93174
|
const context = turn ? turn.context : run2.renderer?.context?.();
|
|
93175
|
+
const limit = context?.limit ?? contextLimit(job.runtime, run2.model?.() ?? job.model ?? void 0);
|
|
92773
93176
|
const usage = turn ? turn.usage : run2.renderer?.usage?.();
|
|
92774
93177
|
const costUsd = turn ? turn.costUsd : run2.renderer?.costUsd?.();
|
|
92775
93178
|
return {
|
|
@@ -92777,7 +93180,7 @@ function report(run2, turn) {
|
|
|
92777
93180
|
session: run2.session(),
|
|
92778
93181
|
...usage ? { usage } : {},
|
|
92779
93182
|
...costUsd !== void 0 ? { costUsd } : {},
|
|
92780
|
-
...context?.used !== void 0 &&
|
|
93183
|
+
...context?.used !== void 0 && limit ? { context: { used: context.used, limit } } : {}
|
|
92781
93184
|
};
|
|
92782
93185
|
}
|
|
92783
93186
|
var cutShort = (said, text3) => ({ ...said, reply: said.reply || text3 || void 0, stopped: true });
|
|
@@ -92856,9 +93259,10 @@ function keepPresence(machineId2, pingMs = PING_MS) {
|
|
|
92856
93259
|
}
|
|
92857
93260
|
|
|
92858
93261
|
// src/connect.ts
|
|
92859
|
-
var HEARTBEAT_MS2 =
|
|
93262
|
+
var HEARTBEAT_MS2 = 10 * 6e4;
|
|
92860
93263
|
var POLL_MS = 6e4;
|
|
92861
93264
|
var BACKOFF_MS3 = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
93265
|
+
var LOOK_LATE_MS = 6e4;
|
|
92862
93266
|
function startRunner(options) {
|
|
92863
93267
|
let registration = null;
|
|
92864
93268
|
let connected = false;
|
|
@@ -92878,17 +93282,22 @@ function startRunner(options) {
|
|
|
92878
93282
|
const base = options.deps ?? defaultDeps(registration.machineId);
|
|
92879
93283
|
return { ...base, runtimes: () => base.runtimes().then(redetected) };
|
|
92880
93284
|
};
|
|
93285
|
+
const register2 = async () => {
|
|
93286
|
+
const answer = await register(options.notify ? { ...registration, notify: options.notify() } : registration);
|
|
93287
|
+
if (answer.ok) void followAkb(answer.value.akb);
|
|
93288
|
+
return answer;
|
|
93289
|
+
};
|
|
92881
93290
|
const redetected = async (found) => {
|
|
92882
93291
|
if (closed || !registration || JSON.stringify(found) === JSON.stringify(registration.runtimes)) return found;
|
|
92883
93292
|
registration = { ...registration, runtimes: found };
|
|
92884
|
-
await
|
|
93293
|
+
await register2();
|
|
92885
93294
|
return found;
|
|
92886
93295
|
};
|
|
92887
93296
|
const idle2 = () => running.size ? t.running(running.size) : t.connected(registration.machineName);
|
|
92888
|
-
const schedule = (
|
|
93297
|
+
const schedule = (ms) => {
|
|
92889
93298
|
if (closed) return;
|
|
92890
93299
|
if (timer) clearTimeout(timer);
|
|
92891
|
-
timer = setTimeout(tick,
|
|
93300
|
+
timer = setTimeout(tick, ms);
|
|
92892
93301
|
};
|
|
92893
93302
|
let looking = false;
|
|
92894
93303
|
const agentsDue = async () => {
|
|
@@ -92902,14 +93311,25 @@ function startRunner(options) {
|
|
|
92902
93311
|
looking = false;
|
|
92903
93312
|
}
|
|
92904
93313
|
};
|
|
92905
|
-
|
|
92906
|
-
|
|
93314
|
+
let agentsTimer = null;
|
|
93315
|
+
const lookNext = () => {
|
|
93316
|
+
if (closed) return;
|
|
93317
|
+
const at2 = (options.nextLook ?? nextHour)(Date.now());
|
|
93318
|
+
agentsTimer = setTimeout(() => {
|
|
93319
|
+
const late = Date.now() - at2;
|
|
93320
|
+
if (late >= 0 && late < LOOK_LATE_MS) void agentsDue();
|
|
93321
|
+
lookNext();
|
|
93322
|
+
}, at2 - Date.now());
|
|
93323
|
+
agentsTimer.unref?.();
|
|
93324
|
+
};
|
|
93325
|
+
lookNext();
|
|
92907
93326
|
let sweeping = false;
|
|
92908
93327
|
let swept = false;
|
|
92909
93328
|
const sweep = async () => {
|
|
92910
93329
|
if (sweeping || closed || !registration) return;
|
|
92911
93330
|
sweeping = true;
|
|
92912
93331
|
try {
|
|
93332
|
+
sweepAkb();
|
|
92913
93333
|
await sweepCache(registration.machineId);
|
|
92914
93334
|
} catch (e2) {
|
|
92915
93335
|
console.error(`runner: the cache was not cleaned: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -92934,12 +93354,12 @@ function startRunner(options) {
|
|
|
92934
93354
|
swept = true;
|
|
92935
93355
|
void sweep();
|
|
92936
93356
|
}
|
|
92937
|
-
const answer = await
|
|
93357
|
+
const answer = await register2();
|
|
92938
93358
|
if (closed) return;
|
|
92939
93359
|
if (!answer.ok) {
|
|
92940
93360
|
if (answer.code === "runner_elsewhere") {
|
|
92941
|
-
const
|
|
92942
|
-
return finish2({ reason: "elsewhere", machine:
|
|
93361
|
+
const held4 = await readRunner();
|
|
93362
|
+
return finish2({ reason: "elsewhere", machine: held4.ok && held4.value.runner?.machineName || "?" });
|
|
92943
93363
|
}
|
|
92944
93364
|
if (answer.code === "runner_outdated") return finish2({ reason: "outdated" });
|
|
92945
93365
|
if (answer.code) return finish2({ reason: "refused", message: answer.error });
|
|
@@ -92962,7 +93382,6 @@ function startRunner(options) {
|
|
|
92962
93382
|
await readJobs();
|
|
92963
93383
|
if (!live?.joined()) boards?.pullAll();
|
|
92964
93384
|
void reviewDue();
|
|
92965
|
-
void agentsDue();
|
|
92966
93385
|
schedule(live?.joined() ? options.heartbeatMs ?? HEARTBEAT_MS2 : Math.min(options.pollMs ?? POLL_MS, options.heartbeatMs ?? HEARTBEAT_MS2));
|
|
92967
93386
|
};
|
|
92968
93387
|
const openLive = () => {
|
|
@@ -93024,7 +93443,7 @@ function startRunner(options) {
|
|
|
93024
93443
|
if (folder && "refused" in folder) return;
|
|
93025
93444
|
const ws = openTaskFolder(job, folder?.cwd ?? null);
|
|
93026
93445
|
const card = akbCardOf(ws);
|
|
93027
|
-
if (card) await stopLeftBehind(deps().akb, ws, card, deps().stopMs);
|
|
93446
|
+
if (card) await stopLeftBehind(deps().akb(), ws, card, deps().stopMs);
|
|
93028
93447
|
} catch (e2) {
|
|
93029
93448
|
console.error(`runner: the runs left on job ${job.id}'s card were not stopped: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
93030
93449
|
}
|
|
@@ -93058,7 +93477,7 @@ function startRunner(options) {
|
|
|
93058
93477
|
closed = true;
|
|
93059
93478
|
lock.release();
|
|
93060
93479
|
if (timer) clearTimeout(timer);
|
|
93061
|
-
|
|
93480
|
+
if (agentsTimer) clearTimeout(agentsTimer);
|
|
93062
93481
|
clearInterval(sweepTimer);
|
|
93063
93482
|
live?.close();
|
|
93064
93483
|
presence?.close();
|
|
@@ -93080,13 +93499,13 @@ function startRunner(options) {
|
|
|
93080
93499
|
|
|
93081
93500
|
// src/desktop.ts
|
|
93082
93501
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
93083
|
-
import
|
|
93084
|
-
import
|
|
93502
|
+
import fs30 from "node:fs";
|
|
93503
|
+
import path33 from "node:path";
|
|
93085
93504
|
import readline from "node:readline";
|
|
93086
93505
|
|
|
93087
93506
|
// src/signin.ts
|
|
93088
93507
|
import { spawn as spawn5 } from "node:child_process";
|
|
93089
|
-
import
|
|
93508
|
+
import crypto5 from "node:crypto";
|
|
93090
93509
|
import http from "node:http";
|
|
93091
93510
|
var WAIT_MS = 10 * 60 * 1e3;
|
|
93092
93511
|
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 +93530,8 @@ var PAGE = (outcome, lang) => {
|
|
|
93111
93530
|
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
93531
|
};
|
|
93113
93532
|
async function signIn(options = {}) {
|
|
93114
|
-
const verifier = base64url(
|
|
93115
|
-
const challenge = base64url(
|
|
93533
|
+
const verifier = base64url(crypto5.randomBytes(32));
|
|
93534
|
+
const challenge = base64url(crypto5.createHash("sha256").update(verifier).digest());
|
|
93116
93535
|
let finish2 = () => {
|
|
93117
93536
|
};
|
|
93118
93537
|
const answered = new Promise((resolve2) => finish2 = resolve2);
|
|
@@ -93226,7 +93645,7 @@ async function runDesktop(tell2) {
|
|
|
93226
93645
|
const shown = /* @__PURE__ */ new Set();
|
|
93227
93646
|
let wake = () => {
|
|
93228
93647
|
};
|
|
93229
|
-
const
|
|
93648
|
+
const readInbox2 = () => {
|
|
93230
93649
|
if (inboxTimer) clearTimeout(inboxTimer);
|
|
93231
93650
|
inboxTimer = setTimeout(async () => {
|
|
93232
93651
|
const inbox = await readInbox();
|
|
@@ -93261,12 +93680,12 @@ async function runDesktop(tell2) {
|
|
|
93261
93680
|
const readProfile2 = async () => {
|
|
93262
93681
|
const session = readSession();
|
|
93263
93682
|
const profile = await readProfile();
|
|
93264
|
-
const
|
|
93683
|
+
const held4 = profile.ok ? profile.value.session : {};
|
|
93265
93684
|
emit({
|
|
93266
93685
|
type: "account",
|
|
93267
|
-
name:
|
|
93268
|
-
email:
|
|
93269
|
-
avatar:
|
|
93686
|
+
name: held4.name || held4.handle || session?.name || session?.handle || "",
|
|
93687
|
+
email: held4.email || session?.email || "",
|
|
93688
|
+
avatar: held4.avatarUrl || session?.avatarUrl || ""
|
|
93270
93689
|
});
|
|
93271
93690
|
};
|
|
93272
93691
|
const readPlan2 = async () => {
|
|
@@ -93288,7 +93707,7 @@ async function runDesktop(tell2) {
|
|
|
93288
93707
|
void readFolders();
|
|
93289
93708
|
void readPlan2();
|
|
93290
93709
|
void readAlerts();
|
|
93291
|
-
|
|
93710
|
+
readInbox2();
|
|
93292
93711
|
};
|
|
93293
93712
|
const onConnected = () => {
|
|
93294
93713
|
tell2({ type: "connected" });
|
|
@@ -93326,17 +93745,17 @@ async function runDesktop(tell2) {
|
|
|
93326
93745
|
notify = command.on;
|
|
93327
93746
|
return runner?.renew();
|
|
93328
93747
|
case "refresh":
|
|
93329
|
-
|
|
93748
|
+
readInbox2();
|
|
93330
93749
|
return void readAlerts();
|
|
93331
93750
|
case "read":
|
|
93332
93751
|
await readAlert(command.alert);
|
|
93333
|
-
return
|
|
93752
|
+
return readInbox2();
|
|
93334
93753
|
case "addFolder": {
|
|
93335
93754
|
const project = command.project;
|
|
93336
93755
|
const why = refusal(command.path);
|
|
93337
93756
|
if (why) return emit({ type: "folderRefused", why, project });
|
|
93338
|
-
const real =
|
|
93339
|
-
const added = await addFolder(id,
|
|
93757
|
+
const real = fs30.realpathSync(command.path);
|
|
93758
|
+
const added = await addFolder(id, path33.basename(real) || real, real, project);
|
|
93340
93759
|
if (!added.ok) {
|
|
93341
93760
|
const taken = added.code === "folder_taken";
|
|
93342
93761
|
return emit({ type: "folderRefused", why: taken ? "taken" : "failed", project, ...taken ? { taken: added.project } : {} });
|
|
@@ -93345,9 +93764,9 @@ async function runDesktop(tell2) {
|
|
|
93345
93764
|
return readFolders();
|
|
93346
93765
|
}
|
|
93347
93766
|
case "removeFolder": {
|
|
93348
|
-
const
|
|
93767
|
+
const held4 = folders2.find((f2) => f2.project === command.project);
|
|
93349
93768
|
const removed = await removeFolder(id, command.project);
|
|
93350
|
-
if (removed.ok &&
|
|
93769
|
+
if (removed.ok && held4) for (const dir of disallow(held4.path)) clearAkb(dir);
|
|
93351
93770
|
return readFolders();
|
|
93352
93771
|
}
|
|
93353
93772
|
case "folderNotify":
|
|
@@ -93400,11 +93819,11 @@ async function runDesktop(tell2) {
|
|
|
93400
93819
|
onDisconnected: () => emit({ type: "connection", state: "reconnecting" }),
|
|
93401
93820
|
onHint: (payload) => {
|
|
93402
93821
|
if (payload.alertId || !payload.taskId) void readAlerts();
|
|
93403
|
-
if (!payload.jobId)
|
|
93822
|
+
if (!payload.jobId) readInbox2();
|
|
93404
93823
|
}
|
|
93405
93824
|
});
|
|
93406
93825
|
poller = setInterval(() => {
|
|
93407
|
-
|
|
93826
|
+
readInbox2();
|
|
93408
93827
|
void readAlerts();
|
|
93409
93828
|
}, POLL_MS2);
|
|
93410
93829
|
void runner.stopped.then(wake);
|