wildcrane-runner 0.6.17 → 0.6.19
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 +12 -0
- package/dist/akb/dist/kanban.mjs +569 -455
- package/dist/akb/package.json +1 -1
- package/dist/launcher.mjs +4927 -31
- package/dist/runner.mjs +1022 -652
- package/package.json +1 -1
package/dist/runner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// wildcrane-runner 0.6.
|
|
1
|
+
// wildcrane-runner 0.6.19 — 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;
|
|
@@ -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 crypto8 = __require("crypto");
|
|
7521
7521
|
var async_hooks = __require("async_hooks");
|
|
7522
7522
|
var React4 = require_react();
|
|
7523
7523
|
var ReactDOM = require_react_dom();
|
|
@@ -10382,7 +10382,7 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
10382
10382
|
function createPostbackActionStateKey(permalink, componentKeyPath, hookIndex) {
|
|
10383
10383
|
if (void 0 !== permalink) return "p" + permalink;
|
|
10384
10384
|
permalink = JSON.stringify([componentKeyPath, null, hookIndex]);
|
|
10385
|
-
componentKeyPath =
|
|
10385
|
+
componentKeyPath = crypto8.createHash("md5");
|
|
10386
10386
|
componentKeyPath.update(permalink);
|
|
10387
10387
|
return "k" + componentKeyPath.digest("hex");
|
|
10388
10388
|
}
|
|
@@ -11493,8 +11493,8 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
11493
11493
|
0
|
|
11494
11494
|
);
|
|
11495
11495
|
}
|
|
11496
|
-
var autoName = JSCompiler_inline_result$jscomp$2, resumableState$jscomp$1 = request2.resumableState,
|
|
11497
|
-
null ==
|
|
11496
|
+
var autoName = JSCompiler_inline_result$jscomp$2, resumableState$jscomp$1 = request2.resumableState, update3 = getViewTransitionClassName(props.default, props.update), enter = getViewTransitionClassName(props.default, props.enter), exit = getViewTransitionClassName(props.default, props.exit), share = getViewTransitionClassName(props.default, props.share), name = props.name;
|
|
11497
|
+
null == update3 && (update3 = "auto");
|
|
11498
11498
|
null == enter && (enter = "auto");
|
|
11499
11499
|
null == exit && (exit = "auto");
|
|
11500
11500
|
if (null == name) {
|
|
@@ -11505,7 +11505,7 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
11505
11505
|
prevContext$jscomp$0.tagScope & 8 ? resumableState$jscomp$1.instructions |= 128 : exit = "none";
|
|
11506
11506
|
prevContext$jscomp$0.tagScope & 16 ? resumableState$jscomp$1.instructions |= 128 : enter = "none";
|
|
11507
11507
|
var viewTransition = {
|
|
11508
|
-
update:
|
|
11508
|
+
update: update3,
|
|
11509
11509
|
enter,
|
|
11510
11510
|
exit,
|
|
11511
11511
|
share,
|
|
@@ -11515,7 +11515,7 @@ var require_react_dom_server_node_production = __commonJS({
|
|
|
11515
11515
|
autoName,
|
|
11516
11516
|
nameIdx: 0
|
|
11517
11517
|
}, subtreeScope = prevContext$jscomp$0.tagScope & -25;
|
|
11518
|
-
subtreeScope = "none" !==
|
|
11518
|
+
subtreeScope = "none" !== update3 ? subtreeScope | 32 : subtreeScope & -33;
|
|
11519
11519
|
"none" !== enter && (subtreeScope |= 64);
|
|
11520
11520
|
var JSCompiler_inline_result$jscomp$3 = createFormatContext(
|
|
11521
11521
|
prevContext$jscomp$0.insertionMode,
|
|
@@ -13136,15 +13136,15 @@ A.finished.finally(function(){document.__reactViewTransition===A&&(document.__re
|
|
|
13136
13136
|
request2 = request2.renderLifetimeController;
|
|
13137
13137
|
null !== request2 && request2.abort("The render ended.");
|
|
13138
13138
|
}
|
|
13139
|
-
function attachAbortSignal(request2,
|
|
13140
|
-
if (
|
|
13139
|
+
function attachAbortSignal(request2, signal2) {
|
|
13140
|
+
if (signal2.aborted) abort(request2, signal2.reason);
|
|
13141
13141
|
else {
|
|
13142
13142
|
var renderLifetimeController = new AbortController();
|
|
13143
13143
|
request2.renderLifetimeController = renderLifetimeController;
|
|
13144
|
-
|
|
13144
|
+
signal2.addEventListener(
|
|
13145
13145
|
"abort",
|
|
13146
13146
|
function() {
|
|
13147
|
-
abort(request2,
|
|
13147
|
+
abort(request2, signal2.reason);
|
|
13148
13148
|
},
|
|
13149
13149
|
{ signal: renderLifetimeController.signal }
|
|
13150
13150
|
);
|
|
@@ -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 = crypto8.createHash("md5");
|
|
24380
24380
|
componentKeyPath.update(permalink);
|
|
24381
24381
|
return "k" + componentKeyPath.digest("hex");
|
|
24382
24382
|
}
|
|
@@ -25837,8 +25837,8 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
25837
25837
|
var treeId = getTreeId(task.treeContext);
|
|
25838
25838
|
autoName = makeId(resumableState$jscomp$0, treeId, 0);
|
|
25839
25839
|
}
|
|
25840
|
-
var resumableState$jscomp$1 = request2.resumableState,
|
|
25841
|
-
null ==
|
|
25840
|
+
var resumableState$jscomp$1 = request2.resumableState, update3 = getViewTransitionClassName(props.default, props.update), enter = getViewTransitionClassName(props.default, props.enter), exit = getViewTransitionClassName(props.default, props.exit), share = getViewTransitionClassName(props.default, props.share), name$jscomp$0 = props.name, autoName$jscomp$0 = autoName;
|
|
25841
|
+
null == update3 && (update3 = "auto");
|
|
25842
25842
|
null == enter && (enter = "auto");
|
|
25843
25843
|
null == exit && (exit = "auto");
|
|
25844
25844
|
if (null == name$jscomp$0) {
|
|
@@ -25849,7 +25849,7 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
25849
25849
|
prevContext$jscomp$0.tagScope & 8 ? resumableState$jscomp$1.instructions |= NeedUpgradeToViewTransitions : exit = "none";
|
|
25850
25850
|
prevContext$jscomp$0.tagScope & 16 ? resumableState$jscomp$1.instructions |= NeedUpgradeToViewTransitions : enter = "none";
|
|
25851
25851
|
var viewTransition = {
|
|
25852
|
-
update:
|
|
25852
|
+
update: update3,
|
|
25853
25853
|
enter,
|
|
25854
25854
|
exit,
|
|
25855
25855
|
share,
|
|
@@ -25859,7 +25859,7 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
25859
25859
|
autoName: autoName$jscomp$0,
|
|
25860
25860
|
nameIdx: 0
|
|
25861
25861
|
}, subtreeScope = prevContext$jscomp$0.tagScope & -25;
|
|
25862
|
-
subtreeScope = "none" !==
|
|
25862
|
+
subtreeScope = "none" !== update3 ? subtreeScope | 32 : subtreeScope & -33;
|
|
25863
25863
|
"none" !== enter && (subtreeScope |= 64);
|
|
25864
25864
|
var JSCompiler_inline_result$jscomp$0 = createFormatContext(
|
|
25865
25865
|
prevContext$jscomp$0.insertionMode,
|
|
@@ -27848,15 +27848,15 @@ var require_react_dom_server_node_development = __commonJS({
|
|
|
27848
27848
|
request2 = request2.renderLifetimeController;
|
|
27849
27849
|
null !== request2 && request2.abort(RENDER_ENDED);
|
|
27850
27850
|
}
|
|
27851
|
-
function attachAbortSignal(request2,
|
|
27852
|
-
if (
|
|
27851
|
+
function attachAbortSignal(request2, signal2) {
|
|
27852
|
+
if (signal2.aborted) abort(request2, signal2.reason);
|
|
27853
27853
|
else {
|
|
27854
27854
|
var renderLifetimeController = new AbortController();
|
|
27855
27855
|
request2.renderLifetimeController = renderLifetimeController;
|
|
27856
|
-
|
|
27856
|
+
signal2.addEventListener(
|
|
27857
27857
|
"abort",
|
|
27858
27858
|
function() {
|
|
27859
|
-
abort(request2,
|
|
27859
|
+
abort(request2, signal2.reason);
|
|
27860
27860
|
},
|
|
27861
27861
|
{ signal: renderLifetimeController.signal }
|
|
27862
27862
|
);
|
|
@@ -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"), crypto8 = __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(
|
|
@@ -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 [path40, resolvedName] of Object.entries(this.cjsAutomaticModuleNameResolutions)) {
|
|
41260
|
+
prefix += `var ${resolvedName} = require("${path40}");`;
|
|
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 path40 = this.jsxImportSource + importPathSuffix;
|
|
41454
|
+
if (!this.cjsAutomaticModuleNameResolutions[path40]) {
|
|
41455
|
+
this.cjsAutomaticModuleNameResolutions[path40] = this.importProcessor.getFreeIdentifierForPath(path40);
|
|
41456
41456
|
}
|
|
41457
|
-
return `${this.cjsAutomaticModuleNameResolutions[
|
|
41457
|
+
return `${this.cjsAutomaticModuleNameResolutions[path40]}.${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 [path40, 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(path40, "");
|
|
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 [path40, 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(path40, `require('${path40}');`);
|
|
41922
41922
|
continue;
|
|
41923
41923
|
}
|
|
41924
|
-
const primaryImportName = this.getFreeIdentifierForPath(
|
|
41924
|
+
const primaryImportName = this.getFreeIdentifierForPath(path40);
|
|
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(path40);
|
|
41930
41930
|
}
|
|
41931
|
-
let requireCode = `var ${primaryImportName} = require('${
|
|
41931
|
+
let requireCode = `var ${primaryImportName} = require('${path40}');`;
|
|
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(path40, 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(path40) {
|
|
41969
|
+
const components = path40.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 path40 = this.tokens.stringValueAtIndex(index);
|
|
42015
|
+
const importInfo = this.getImportInfo(path40);
|
|
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 path40 = this.tokens.stringValueAtIndex(index);
|
|
42083
|
+
const importInfo = this.getImportInfo(path40);
|
|
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 path40 = this.tokens.stringValueAtIndex(index);
|
|
42099
|
+
const importInfo = this.getImportInfo(path40);
|
|
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(path40) {
|
|
42140
|
+
const existingInfo = this.importInfoByPath.get(path40);
|
|
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(path40, 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 path40 = match[2];
|
|
42734
|
+
return makeUrl("file:", "", match[1] || "", "", isAbsolutePath(path40) ? path40 : "/" + path40, match[3] || "", match[4] || "");
|
|
42735
42735
|
}
|
|
42736
|
-
function makeUrl(scheme, user, host, port,
|
|
42736
|
+
function makeUrl(scheme, user, host, port, path40, query, hash) {
|
|
42737
42737
|
return {
|
|
42738
42738
|
scheme,
|
|
42739
42739
|
user,
|
|
42740
42740
|
host,
|
|
42741
42741
|
port,
|
|
42742
|
-
path:
|
|
42742
|
+
path: path40,
|
|
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(path40) {
|
|
42773
|
+
if (path40.endsWith("/.."))
|
|
42774
|
+
return path40;
|
|
42775
|
+
const index = path40.lastIndexOf("/");
|
|
42776
|
+
return path40.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 path40 = "";
|
|
42815
42815
|
for (let i = 1; i < pointer; i++) {
|
|
42816
|
-
|
|
42816
|
+
path40 += "/" + pieces[i];
|
|
42817
42817
|
}
|
|
42818
|
-
if (!
|
|
42819
|
-
|
|
42818
|
+
if (!path40 || addTrailingSlash && !path40.endsWith("/..")) {
|
|
42819
|
+
path40 += "/";
|
|
42820
42820
|
}
|
|
42821
|
-
url.path =
|
|
42821
|
+
url.path = path40;
|
|
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 path40 = url.path.slice(1);
|
|
42863
|
+
if (!path40)
|
|
42864
42864
|
return queryHash || ".";
|
|
42865
|
-
if (isRelative(base || input) && !isRelative(
|
|
42866
|
-
return "./" +
|
|
42865
|
+
if (isRelative(base || input) && !isRelative(path40)) {
|
|
42866
|
+
return "./" + path40 + queryHash;
|
|
42867
42867
|
}
|
|
42868
|
-
return
|
|
42868
|
+
return path40 + 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(path40) {
|
|
42968
|
+
if (!path40) return "";
|
|
42969
|
+
const index = path40.lastIndexOf("/");
|
|
42970
|
+
return path40.slice(0, index + 1);
|
|
42971
42971
|
}
|
|
42972
42972
|
function resolver(mapUrl, sourceRoot) {
|
|
42973
42973
|
const from = stripFilename(mapUrl);
|
|
@@ -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(path40, message) {
|
|
44179
44179
|
var _this = _super.call(this, message) || this;
|
|
44180
|
-
_this.path =
|
|
44180
|
+
_this.path = path40;
|
|
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(path40) {
|
|
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
|
+
path40 += typeof p2 === "number" ? "[" + p2 + "]" : p2 ? "." + p2 : "";
|
|
44245
44245
|
var m = this._messages[i];
|
|
44246
44246
|
if (m) {
|
|
44247
|
-
msgParts.push(
|
|
44247
|
+
msgParts.push(path40 + " " + m);
|
|
44248
44248
|
}
|
|
44249
44249
|
}
|
|
44250
|
-
return new VError(
|
|
44250
|
+
return new VError(path40, msgParts.join("; "));
|
|
44251
44251
|
};
|
|
44252
|
-
DetailContext2.prototype.getErrorDetail = function(
|
|
44252
|
+
DetailContext2.prototype.getErrorDetail = function(path40) {
|
|
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
|
+
path40 += 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: path40, 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(path40) {
|
|
45073
|
+
this._path = path40;
|
|
45074
45074
|
};
|
|
45075
45075
|
Checker2.prototype.check = function(value) {
|
|
45076
45076
|
return this._doCheck(this.checkerPlain, value);
|
|
@@ -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 path40 = this.tokens.stringValue();
|
|
50507
|
+
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path40));
|
|
50508
|
+
this.tokens.appendCode(this.importProcessor.claimImportCode(path40));
|
|
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 path40 = this.tokens.stringValue();
|
|
51089
|
+
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path40));
|
|
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 path40 = this.tokens.stringValue();
|
|
51104
|
+
this.tokens.replaceTokenTrimmingLeftWhitespace(this.importProcessor.claimImportCode(path40));
|
|
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, path40) => {
|
|
80749
80749
|
let current = classPartObject;
|
|
80750
|
-
const parts =
|
|
80750
|
+
const parts = path40.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];
|
|
@@ -80772,7 +80772,7 @@ var init_bundle_mjs = __esm({
|
|
|
80772
80772
|
let cacheSize = 0;
|
|
80773
80773
|
let cache = /* @__PURE__ */ Object.create(null);
|
|
80774
80774
|
let previousCache = /* @__PURE__ */ Object.create(null);
|
|
80775
|
-
const
|
|
80775
|
+
const update3 = (key, value) => {
|
|
80776
80776
|
cache[key] = value;
|
|
80777
80777
|
cacheSize++;
|
|
80778
80778
|
if (cacheSize > maxCacheSize) {
|
|
@@ -80788,7 +80788,7 @@ var init_bundle_mjs = __esm({
|
|
|
80788
80788
|
return value;
|
|
80789
80789
|
}
|
|
80790
80790
|
if ((value = previousCache[key]) !== void 0) {
|
|
80791
|
-
|
|
80791
|
+
update3(key, value);
|
|
80792
80792
|
return value;
|
|
80793
80793
|
}
|
|
80794
80794
|
},
|
|
@@ -80796,7 +80796,7 @@ var init_bundle_mjs = __esm({
|
|
|
80796
80796
|
if (key in cache) {
|
|
80797
80797
|
cache[key] = value;
|
|
80798
80798
|
} else {
|
|
80799
|
-
|
|
80799
|
+
update3(key, value);
|
|
80800
80800
|
}
|
|
80801
80801
|
}
|
|
80802
80802
|
};
|
|
@@ -84001,8 +84001,8 @@ var mockup_exports = {};
|
|
|
84001
84001
|
__export(mockup_exports, {
|
|
84002
84002
|
drawMockup: () => drawMockup
|
|
84003
84003
|
});
|
|
84004
|
-
import
|
|
84005
|
-
import
|
|
84004
|
+
import fs21 from "node:fs";
|
|
84005
|
+
import path25 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 = path25.resolve(path25.dirname(from), id);
|
|
84019
|
+
if (at2 !== folder && !at2.startsWith(folder + path25.sep)) throw new Error(`${id} is outside the mockup's folder`);
|
|
84020
|
+
const tries = path25.extname(at2) ? [at2] : [...CODE_EXTS.map((e2) => at2 + e2), ...CODE_EXTS.map((e2) => path25.join(at2, `index${e2}`))];
|
|
84021
|
+
const file2 = tries.find((f2) => fs21.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 = path25.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)(fs21.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: fs21.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 ? path25.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 = path25.resolve(from, id);
|
|
84062
|
+
return { path: at2, base: path25.dirname(at2), content: fs21.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 = path25.dirname(file2);
|
|
84070
|
+
const html = fs21.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 = path25.resolve(folder, href);
|
|
84074
|
+
if (!at3.startsWith(folder + path25.sep) || !fs21.existsSync(at3)) return tag;
|
|
84075
|
+
return `<style>${fs21.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>`;
|
|
@@ -84272,6 +84272,9 @@ async function refresh() {
|
|
|
84272
84272
|
}
|
|
84273
84273
|
const fresh = sessionFrom(await response.json(), now);
|
|
84274
84274
|
if (!fresh) return { ok: false, reason: "expired" };
|
|
84275
|
+
const current = readSession();
|
|
84276
|
+
if (!current || current.subject !== now.subject) return { ok: false, reason: "expired" };
|
|
84277
|
+
if (current.refreshToken !== now.refreshToken) return { ok: true, token: current.accessToken, session: current };
|
|
84275
84278
|
writeSession(fresh);
|
|
84276
84279
|
return { ok: true, token: fresh.accessToken, session: fresh };
|
|
84277
84280
|
} finally {
|
|
@@ -84435,8 +84438,8 @@ function status(line) {
|
|
|
84435
84438
|
}
|
|
84436
84439
|
|
|
84437
84440
|
// src/protocol.ts
|
|
84438
|
-
var VERSION = true ? "0.6.
|
|
84439
|
-
var AKB_VERSION = true ? "0.11.
|
|
84441
|
+
var VERSION = true ? "0.6.19" : "0.0.0";
|
|
84442
|
+
var AKB_VERSION = true ? "0.11.17" : "0.0.0";
|
|
84440
84443
|
var AKB_CONTRACT = true ? 5 : 0;
|
|
84441
84444
|
var EXIT_REFUSED = 10;
|
|
84442
84445
|
var EXIT_OUTDATED = 11;
|
|
@@ -84447,7 +84450,40 @@ import { spawn as spawn2 } from "node:child_process";
|
|
|
84447
84450
|
import { randomUUID } from "node:crypto";
|
|
84448
84451
|
import fs11 from "node:fs";
|
|
84449
84452
|
import os4 from "node:os";
|
|
84450
|
-
import
|
|
84453
|
+
import path15 from "node:path";
|
|
84454
|
+
|
|
84455
|
+
// ../cli/src/lib/agent/language.ts
|
|
84456
|
+
var LANGUAGE_ENV = "AI4KANBAN_LANGUAGE";
|
|
84457
|
+
var LANGUAGE_LINE_ENV = "AI4KANBAN_LANGUAGE_LINE";
|
|
84458
|
+
var SYSTEM_LANGUAGE_ZH = "\u7528\u4E2D\u6587\u56DE\u590D\u3002\u6210\u679C\u8BED\u8A00\u4F9D\u6B21\u9075\u5FAA\u7528\u6237\u660E\u786E\u8981\u6C42\u3001\u6210\u679C\u4E13\u7528\u6307\u4EE4\u3001\u65E2\u6709\u6210\u679C\u6216\u9879\u76EE\u60EF\u4F8B\uFF0C\u6700\u540E\u91C7\u7528\u672C\u6B21\u8BF7\u6C42\u7684\u8BED\u8A00\u3002\u4EE3\u7801\u3001\u547D\u4EE4\u3001\u6587\u4EF6\u540D\u548C\u5B57\u6BB5\u540D\u4FDD\u6301\u539F\u6587\u3002";
|
|
84459
|
+
var SYSTEM_LANGUAGE_EN = "Reply in English. Artifact language follows explicit user requests, artifact instructions, existing or project conventions, then the current request's language. Keep code, commands, filenames, and field names unchanged.";
|
|
84460
|
+
var systemLanguages = /* @__PURE__ */ new Set([
|
|
84461
|
+
SYSTEM_LANGUAGE_ZH,
|
|
84462
|
+
SYSTEM_LANGUAGE_EN,
|
|
84463
|
+
"\u65E0\u8BBA\u5BF9\u8BDD\u91CC\u7684\u5361\u7247\u3001\u4EE3\u7801\u548C\u8D34\u8FDB\u6765\u7684\u5185\u5BB9\u662F\u4EC0\u4E48\u8BED\u8A00\uFF0C\u56DE\u590D\u548C\u5199\u4E0B\u7684\u5185\u5BB9\u90FD\u7528\u4E2D\u6587\u3002\u4EE3\u7801\u3001\u547D\u4EE4\u3001\u6587\u4EF6\u540D\u548C\u5B57\u6BB5\u540D\u4FDD\u6301\u539F\u6587\u3002",
|
|
84464
|
+
"\u5BF9\u8BDD\u548C\u89E3\u91CA\u4F7F\u7528\u4E2D\u6587\uFF1B\u4EA7\u7269\u4F7F\u7528\u7528\u6237\u660E\u786E\u6307\u5B9A\u7684\u8BED\u8A00\uFF0C\u5426\u5219\u4F7F\u7528\u6240\u5C5E agent \u660E\u786E\u6307\u5B9A\u7684\u8BED\u8A00\uFF0C\u5747\u672A\u6307\u5B9A\u65F6\u4F7F\u7528\u4E2D\u6587\u3002\u4EE3\u7801\u3001\u547D\u4EE4\u3001\u6587\u4EF6\u540D\u548C\u5B57\u6BB5\u540D\u4FDD\u6301\u539F\u6587\u3002",
|
|
84465
|
+
"Use English for conversation and explanations. For artifacts, use the language explicitly specified by the user, otherwise the responsible agent, otherwise English. Keep code, commands, filenames, and field names unchanged."
|
|
84466
|
+
]);
|
|
84467
|
+
var isSystemLanguage = (text3) => systemLanguages.has(text3);
|
|
84468
|
+
var legacy = /* @__PURE__ */ new Map([
|
|
84469
|
+
["\u8BF7\u7528\u4E2D\u6587\u56DE\u590D\u548C\u5199\u4F5C\u3002", "zh"],
|
|
84470
|
+
["Reply and write in English.", "en"]
|
|
84471
|
+
]);
|
|
84472
|
+
var languageCode = (value) => value === "zh" || value === "en" ? value : null;
|
|
84473
|
+
var legacyLanguage = (line) => typeof line === "string" ? legacy.get(line) ?? null : null;
|
|
84474
|
+
var systemLanguage = (language) => language === "zh" ? SYSTEM_LANGUAGE_ZH : language === "en" ? SYSTEM_LANGUAGE_EN : "";
|
|
84475
|
+
function cloudLanguage(input) {
|
|
84476
|
+
if (input.test) return null;
|
|
84477
|
+
return "language" in input ? languageCode(input.language) : legacyLanguage(input.languageLine);
|
|
84478
|
+
}
|
|
84479
|
+
function cloudPrompt(input) {
|
|
84480
|
+
if ("language" in input || input.test || input.flow || input.review || input.agent || !legacyLanguage(input.languageLine)) return input.prompt;
|
|
84481
|
+
if (input.prompt === input.languageLine) return "";
|
|
84482
|
+
const suffix = `
|
|
84483
|
+
|
|
84484
|
+
${input.languageLine}`;
|
|
84485
|
+
return input.prompt.endsWith(suffix) ? input.prompt.slice(0, -suffix.length) : input.prompt;
|
|
84486
|
+
}
|
|
84451
84487
|
|
|
84452
84488
|
// ../cli/src/lib/agent/argv.ts
|
|
84453
84489
|
function splitCommand(command) {
|
|
@@ -84483,6 +84519,7 @@ function quoteArg(arg) {
|
|
|
84483
84519
|
}
|
|
84484
84520
|
|
|
84485
84521
|
// ../cli/src/lib/agent/harnesses/types.ts
|
|
84522
|
+
import { createHash } from "node:crypto";
|
|
84486
84523
|
import fs3 from "node:fs";
|
|
84487
84524
|
import path4 from "node:path";
|
|
84488
84525
|
var SKILL_SENTENCE = "Use the kanban skill";
|
|
@@ -84506,7 +84543,8 @@ var MCP_CONFIG = {
|
|
|
84506
84543
|
help: "A JSON file of `mcpServers`, as Claude Code's --mcp-config takes. Empty opens no servers."
|
|
84507
84544
|
};
|
|
84508
84545
|
function machineFile(name, text3) {
|
|
84509
|
-
const
|
|
84546
|
+
const suffix = createHash("sha256").update(text3).digest("hex").slice(0, 16);
|
|
84547
|
+
const file2 = path4.join(machineHome(), "prompts", `${path4.parse(name).name}-${suffix}${path4.extname(name)}`);
|
|
84510
84548
|
try {
|
|
84511
84549
|
if (fs3.readFileSync(file2, "utf8") === text3) return file2;
|
|
84512
84550
|
} catch {
|
|
@@ -85292,10 +85330,10 @@ function findRollout(threadId) {
|
|
|
85292
85330
|
}
|
|
85293
85331
|
for (const name of names2) {
|
|
85294
85332
|
if (!name.startsWith("rollout-") || !name.endsWith(tail)) continue;
|
|
85295
|
-
const
|
|
85333
|
+
const path40 = join(dir, name);
|
|
85296
85334
|
try {
|
|
85297
|
-
const at2 = statSync(
|
|
85298
|
-
if (!newest2 || at2 > newest2.at) newest2 = { path:
|
|
85335
|
+
const at2 = statSync(path40).mtimeMs;
|
|
85336
|
+
if (!newest2 || at2 > newest2.at) newest2 = { path: path40, at: at2 };
|
|
85299
85337
|
} catch {
|
|
85300
85338
|
}
|
|
85301
85339
|
}
|
|
@@ -85303,11 +85341,11 @@ function findRollout(threadId) {
|
|
|
85303
85341
|
return newest2?.path;
|
|
85304
85342
|
}
|
|
85305
85343
|
function readCodexRunFacts(threadId) {
|
|
85306
|
-
const
|
|
85307
|
-
if (!
|
|
85344
|
+
const path40 = findRollout(threadId);
|
|
85345
|
+
if (!path40) return void 0;
|
|
85308
85346
|
let raw;
|
|
85309
85347
|
try {
|
|
85310
|
-
raw = readFileSync(
|
|
85348
|
+
raw = readFileSync(path40, "utf8");
|
|
85311
85349
|
} catch {
|
|
85312
85350
|
return void 0;
|
|
85313
85351
|
}
|
|
@@ -85415,14 +85453,19 @@ function renderCompleted(item) {
|
|
|
85415
85453
|
const changes = Array.isArray(item.changes) ? item.changes : [];
|
|
85416
85454
|
return changes.map((raw) => {
|
|
85417
85455
|
const change = obj(raw);
|
|
85418
|
-
const
|
|
85419
|
-
return
|
|
85456
|
+
const path40 = str(change.path);
|
|
85457
|
+
return path40 ? `\u23FA ${str(change.kind) || "change"}(${path40})
|
|
85420
85458
|
` : "";
|
|
85421
85459
|
}).join("");
|
|
85422
85460
|
}
|
|
85423
85461
|
case "error":
|
|
85424
85462
|
return `[error] ${str(item.message)}
|
|
85425
85463
|
`;
|
|
85464
|
+
case "mcp_tool_call": {
|
|
85465
|
+
const error = str(obj(item.error).message);
|
|
85466
|
+
return error ? `[MCP ${str(item.server)}.${str(item.tool)}] ${error}
|
|
85467
|
+
` : "";
|
|
85468
|
+
}
|
|
85426
85469
|
default:
|
|
85427
85470
|
return "";
|
|
85428
85471
|
}
|
|
@@ -85538,16 +85581,13 @@ function createCodexStreamRenderer(carried = false) {
|
|
|
85538
85581
|
return renderCompleted(item);
|
|
85539
85582
|
}
|
|
85540
85583
|
case "turn.completed":
|
|
85584
|
+
failure = void 0;
|
|
85541
85585
|
total = codexUsage(ev.usage) ?? total;
|
|
85542
85586
|
return "";
|
|
85543
|
-
//
|
|
85544
|
-
// stream itself failing. Kept as the run's failure (#525), because `codex exec`
|
|
85545
|
-
// reports its reason on this stream and nowhere else, and a retry has to read it.
|
|
85546
|
-
// An item's own `error` is not one of them: a tool that failed is the agent's
|
|
85547
|
-
// problem to work around, and the turn around it may still finish.
|
|
85587
|
+
// 最终失败保留;连接提示只在没有后续成功完成时才作为失败。
|
|
85548
85588
|
case "turn.failed": {
|
|
85549
|
-
const said = str(obj(ev.error).message);
|
|
85550
|
-
failure = said
|
|
85589
|
+
const said = str(obj(ev.error).message) || failure || "Codex \u6267\u884C\u5931\u8D25";
|
|
85590
|
+
failure = said;
|
|
85551
85591
|
events.error(said);
|
|
85552
85592
|
return `[error] ${said}
|
|
85553
85593
|
`;
|
|
@@ -85555,8 +85595,9 @@ function createCodexStreamRenderer(carried = false) {
|
|
|
85555
85595
|
case "error": {
|
|
85556
85596
|
const said = str(ev.message);
|
|
85557
85597
|
failure = said || failure;
|
|
85558
|
-
events.
|
|
85559
|
-
|
|
85598
|
+
events.log(`[Codex] ${said}
|
|
85599
|
+
`);
|
|
85600
|
+
return `[Codex] ${said}
|
|
85560
85601
|
`;
|
|
85561
85602
|
}
|
|
85562
85603
|
default:
|
|
@@ -85664,10 +85705,10 @@ function readKimiRunFacts(sessionId) {
|
|
|
85664
85705
|
const total = { input: 0, cacheCreation: 0, cacheRead: 0, output: 0 };
|
|
85665
85706
|
let model;
|
|
85666
85707
|
let holding = 0;
|
|
85667
|
-
for (const { path:
|
|
85708
|
+
for (const { path: path40, main: main2 } of wireFiles(entry.sessionDir)) {
|
|
85668
85709
|
let raw;
|
|
85669
85710
|
try {
|
|
85670
|
-
raw = readFileSync2(
|
|
85711
|
+
raw = readFileSync2(path40, "utf8");
|
|
85671
85712
|
} catch {
|
|
85672
85713
|
continue;
|
|
85673
85714
|
}
|
|
@@ -85923,7 +85964,7 @@ function createTail(log) {
|
|
|
85923
85964
|
// ../cli/package.json
|
|
85924
85965
|
var package_default = {
|
|
85925
85966
|
name: "wildcrane",
|
|
85926
|
-
version: "0.11.
|
|
85967
|
+
version: "0.11.17",
|
|
85927
85968
|
akbContract: 5,
|
|
85928
85969
|
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.",
|
|
85929
85970
|
keywords: [
|
|
@@ -85983,13 +86024,13 @@ var CLIENT_CAPABILITIES = {
|
|
|
85983
86024
|
fs: { readTextFile: false, writeTextFile: false },
|
|
85984
86025
|
terminal: false
|
|
85985
86026
|
};
|
|
85986
|
-
function whereHint(
|
|
85987
|
-
const locations = Array.isArray(
|
|
85988
|
-
const
|
|
85989
|
-
return
|
|
86027
|
+
function whereHint(update3, title) {
|
|
86028
|
+
const locations = Array.isArray(update3.locations) ? update3.locations : [];
|
|
86029
|
+
const path40 = str(obj(locations[0]).path);
|
|
86030
|
+
return path40 && !title.includes(path40) ? hint(path40) : "";
|
|
85990
86031
|
}
|
|
85991
|
-
function saidBy(
|
|
85992
|
-
const content = Array.isArray(
|
|
86032
|
+
function saidBy(update3) {
|
|
86033
|
+
const content = Array.isArray(update3.content) ? update3.content : [];
|
|
85993
86034
|
for (const raw of content) {
|
|
85994
86035
|
const part = obj(raw);
|
|
85995
86036
|
const text3 = str(obj(part.content).text) || str(part.text);
|
|
@@ -86631,9 +86672,12 @@ var CLAUDE_CODE = {
|
|
|
86631
86672
|
forkArgs(argv, resumeId, sessionId) {
|
|
86632
86673
|
return [...claudeStreamArgs(argv), "--resume", resumeId, "--fork-session", "--session-id", sessionId];
|
|
86633
86674
|
},
|
|
86634
|
-
//
|
|
86675
|
+
// 默认快照会忽略续跑传入的新规则;仅显式关闭快照的会话支持更新。
|
|
86635
86676
|
systemPrompt(text3, argv) {
|
|
86636
|
-
|
|
86677
|
+
if (namesFlag(argv, ["--append-system-prompt", "--append-system-prompt-file"])) return {};
|
|
86678
|
+
const snapshot = argv.flatMap((arg, i) => arg === "--system-prompt-snapshot" ? [argv[i + 1]] : arg.startsWith("--system-prompt-snapshot=") ? [arg.slice("--system-prompt-snapshot=".length)] : []).at(-1);
|
|
86679
|
+
if (namesFlag(argv, ["--resume", "-r", "--continue", "-c"]) && snapshot !== "off") return {};
|
|
86680
|
+
return { args: ["--append-system-prompt", text3] };
|
|
86637
86681
|
},
|
|
86638
86682
|
// What Claude Code takes: who pays for the run, where that run goes, a model id, and how
|
|
86639
86683
|
// hard that model thinks. The provider comes first because it decides the rest — which
|
|
@@ -87015,6 +87059,40 @@ function setBoardRoot(root, named2 = false) {
|
|
|
87015
87059
|
}
|
|
87016
87060
|
setBoardRoot(process.cwd());
|
|
87017
87061
|
|
|
87062
|
+
// ../cli/src/lib/agent/proxy.ts
|
|
87063
|
+
import { execFileSync } from "node:child_process";
|
|
87064
|
+
var PROXY_KEYS = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy", "ALL_PROXY", "all_proxy"];
|
|
87065
|
+
function codexProxyEnv(env2 = process.env, platform = process.platform, read2 = () => execFileSync("/usr/sbin/scutil", ["--proxy"], { encoding: "utf8", timeout: 1e3, stdio: ["ignore", "pipe", "ignore"] })) {
|
|
87066
|
+
const out = { ...env2 };
|
|
87067
|
+
if (platform !== "darwin" || PROXY_KEYS.some((key) => env2[key] !== void 0)) return out;
|
|
87068
|
+
let raw;
|
|
87069
|
+
try {
|
|
87070
|
+
raw = read2();
|
|
87071
|
+
} catch {
|
|
87072
|
+
return out;
|
|
87073
|
+
}
|
|
87074
|
+
const value = (key) => new RegExp(`^\\s*${key}\\s*:\\s*(.*?)\\s*$`, "m").exec(raw)?.[1];
|
|
87075
|
+
for (const [name, key, scheme] of [["HTTP", "HTTP_PROXY", "http"], ["HTTPS", "HTTPS_PROXY", "http"], ["SOCKS", "ALL_PROXY", "socks5"]]) {
|
|
87076
|
+
if (value(`${name}Enable`) !== "1") continue;
|
|
87077
|
+
const host = value(`${name}Proxy`);
|
|
87078
|
+
const port = Number(value(`${name}Port`));
|
|
87079
|
+
if (!host || /[\s/@?#]/.test(host) || !Number.isInteger(port) || port < 1 || port > 65535) continue;
|
|
87080
|
+
try {
|
|
87081
|
+
out[key] = new URL(`${scheme}://${host.includes(":") && !host.startsWith("[") ? `[${host}]` : host}:${port}`).href.replace(/\/$/, "");
|
|
87082
|
+
} catch {
|
|
87083
|
+
}
|
|
87084
|
+
}
|
|
87085
|
+
if (PROXY_KEYS.some((key) => out[key]) && env2.NO_PROXY === void 0 && env2.no_proxy === void 0) {
|
|
87086
|
+
const exceptions = /ExceptionsList\s*:\s*<array>\s*\{([^}]+)\}/.exec(raw)?.[1];
|
|
87087
|
+
const bypass = exceptions?.split("\n").flatMap((line) => {
|
|
87088
|
+
const host = /^\s*\d+\s*:\s*(\S+)\s*$/.exec(line)?.[1];
|
|
87089
|
+
return host ? [host.startsWith("*.") ? host.slice(1) : host] : [];
|
|
87090
|
+
});
|
|
87091
|
+
if (bypass?.length) out.NO_PROXY = bypass.join(",");
|
|
87092
|
+
}
|
|
87093
|
+
return out;
|
|
87094
|
+
}
|
|
87095
|
+
|
|
87018
87096
|
// ../cli/src/lib/agent/worktree.ts
|
|
87019
87097
|
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
87020
87098
|
var MAX_OUTPUT = 64 * 1024 * 1024;
|
|
@@ -87174,10 +87252,15 @@ var CODEX = {
|
|
|
87174
87252
|
forkArgs(argv, resumeId, _sessionId, cwd) {
|
|
87175
87253
|
return [...codexExtraArgs(argv, cwd), "fork", resumeId];
|
|
87176
87254
|
},
|
|
87177
|
-
//
|
|
87178
|
-
// `developer_instructions` in the user's config.toml, which is then left out of board runs.
|
|
87255
|
+
// 自设系统指令保持原样;无法追加时由调用方明确提示。
|
|
87179
87256
|
systemPrompt(text3, argv) {
|
|
87180
|
-
|
|
87257
|
+
if (namesFlag(argv, ["developer_instructions", "model_instructions_file"])) return {};
|
|
87258
|
+
try {
|
|
87259
|
+
const config = fs7.readFileSync(path10.join(process.env.CODEX_HOME || home2(".codex"), "config.toml"), "utf8");
|
|
87260
|
+
if (/^\s*(?:developer_instructions|model_instructions_file)\s*=/m.test(config)) return {};
|
|
87261
|
+
} catch {
|
|
87262
|
+
}
|
|
87263
|
+
return { args: ["-c", `developer_instructions=${JSON.stringify(text3)}`] };
|
|
87181
87264
|
},
|
|
87182
87265
|
// What Codex takes, in the order Claude Code's dialog draws the same four: who pays for
|
|
87183
87266
|
// the run and where it goes, that endpoint's address, the key, a model, and how hard that
|
|
@@ -87305,7 +87388,7 @@ var CODEX = {
|
|
|
87305
87388
|
// No `providerEnv` either: the pick already drops and sets OPENAI_API_KEY, and there is
|
|
87306
87389
|
// no second variable to drop. Codex reads no base URL from the environment — an exported
|
|
87307
87390
|
// OPENAI_BASE_URL moves nothing — and where a run goes is settled on its command line.
|
|
87308
|
-
env: () => (
|
|
87391
|
+
env: () => codexProxyEnv(),
|
|
87309
87392
|
// A completed turn carries its token counts and nothing else. The model comes from the
|
|
87310
87393
|
// session's rollout on disk instead, and the price is worked out from the two
|
|
87311
87394
|
// (agent/wire/codex-stream.ts). A model whose rates the board doesn't know shows no price.
|
|
@@ -87498,9 +87581,9 @@ var DSH = {
|
|
|
87498
87581
|
// dsh-acp's persona IS its system prompt, so the ask is added to the one in effect: the
|
|
87499
87582
|
// user's own `DSH_SYSTEM_PROMPT`, else the bridge's default. A `--persona` on the command
|
|
87500
87583
|
// line outranks both, and is left alone.
|
|
87501
|
-
systemPrompt(text3, argv) {
|
|
87584
|
+
systemPrompt(text3, argv, env2) {
|
|
87502
87585
|
if (namesFlag(argv, ["--persona"])) return {};
|
|
87503
|
-
return { env: { DSH_SYSTEM_PROMPT: `${
|
|
87586
|
+
return { env: { DSH_SYSTEM_PROMPT: `${env2.DSH_SYSTEM_PROMPT || DSH_PERSONA}
|
|
87504
87587
|
|
|
87505
87588
|
${text3}` } };
|
|
87506
87589
|
},
|
|
@@ -87891,12 +87974,12 @@ var OPENCODE = {
|
|
|
87891
87974
|
env: () => ({ ...process.env }),
|
|
87892
87975
|
// `instructions` files join the system prompt, and OpenCode adds this config's list to the
|
|
87893
87976
|
// user's own rather than replacing it.
|
|
87894
|
-
systemPrompt(text3) {
|
|
87977
|
+
systemPrompt(text3, _argv, env2) {
|
|
87895
87978
|
const file2 = machineFile("opencode-language.md", `${text3}
|
|
87896
87979
|
`);
|
|
87897
87980
|
let own = {};
|
|
87898
87981
|
try {
|
|
87899
|
-
own = obj2(JSON.parse(
|
|
87982
|
+
own = obj2(JSON.parse(env2.OPENCODE_CONFIG_CONTENT ?? "{}"));
|
|
87900
87983
|
} catch {
|
|
87901
87984
|
}
|
|
87902
87985
|
const instructions = [...Array.isArray(own.instructions) ? own.instructions : [], file2];
|
|
@@ -88039,26 +88122,18 @@ var HARNESSES = [CLAUDE_CODE, CODEX, CURSOR, OPENCODE, KIMI, DSH, ZCODE, GROK].m
|
|
|
88039
88122
|
var DEFAULT_HARNESS = HARNESSES[0];
|
|
88040
88123
|
checkHarnesses(HARNESSES);
|
|
88041
88124
|
|
|
88125
|
+
// ../cli/src/lib/agent/run-settings.ts
|
|
88126
|
+
import path12 from "node:path";
|
|
88127
|
+
|
|
88042
88128
|
// ../cli/src/lib/agent/env.ts
|
|
88043
88129
|
var RUN_ENV = "KANBAN_RUN";
|
|
88044
88130
|
var SCHEDULED_AGENTS_ENV = "AI4KANBAN_SCHEDULED_AGENTS";
|
|
88131
|
+
var STOP_ENV = "KANBAN_STOP_ID";
|
|
88045
88132
|
var SESSION_VARS = {
|
|
88046
88133
|
"claude-code": "CLAUDE_CODE_SESSION_ID",
|
|
88047
88134
|
codex: "CODEX_THREAD_ID"
|
|
88048
88135
|
};
|
|
88049
88136
|
|
|
88050
|
-
// ../cli/src/lib/agent/language.ts
|
|
88051
|
-
var LANGUAGE_LINE_ENV = "AI4KANBAN_LANGUAGE_LINE";
|
|
88052
|
-
var LINES = {
|
|
88053
|
-
en: "",
|
|
88054
|
-
zh: "\u8BF7\u7528\u4E2D\u6587\u56DE\u590D\u548C\u5199\u4F5C\u3002"
|
|
88055
|
-
};
|
|
88056
|
-
var SYSTEM = {
|
|
88057
|
-
[LINES.zh]: "\u65E0\u8BBA\u5BF9\u8BDD\u91CC\u7684\u5361\u7247\u3001\u4EE3\u7801\u548C\u8D34\u8FDB\u6765\u7684\u5185\u5BB9\u662F\u4EC0\u4E48\u8BED\u8A00\uFF0C\u56DE\u590D\u548C\u5199\u4E0B\u7684\u5185\u5BB9\u90FD\u7528\u4E2D\u6587\u3002\u4EE3\u7801\u3001\u547D\u4EE4\u3001\u6587\u4EF6\u540D\u548C\u5B57\u6BB5\u540D\u4FDD\u6301\u539F\u6587\u3002"
|
|
88058
|
-
};
|
|
88059
|
-
var asksForTranslation = (line) => line !== "" && !/\bEnglish\b/.test(line);
|
|
88060
|
-
var systemLanguage = (line) => asksForTranslation(line) ? SYSTEM[line] ?? line : "";
|
|
88061
|
-
|
|
88062
88137
|
// ../cli/src/lib/agent/providers.ts
|
|
88063
88138
|
function providerSetting(settings) {
|
|
88064
88139
|
return settings.find((s) => s.kind === "provider");
|
|
@@ -88150,11 +88225,34 @@ function effectiveValues(harness, held4) {
|
|
|
88150
88225
|
}
|
|
88151
88226
|
return out;
|
|
88152
88227
|
}
|
|
88153
|
-
function
|
|
88154
|
-
const
|
|
88155
|
-
|
|
88156
|
-
|
|
88157
|
-
|
|
88228
|
+
function languageEnv(given) {
|
|
88229
|
+
const env2 = { ...given };
|
|
88230
|
+
if (env2.DSH_SYSTEM_PROMPT) {
|
|
88231
|
+
const parts = env2.DSH_SYSTEM_PROMPT.split("\n\n");
|
|
88232
|
+
while (isSystemLanguage(parts.at(-1) ?? "")) parts.pop();
|
|
88233
|
+
env2.DSH_SYSTEM_PROMPT = parts.join("\n\n");
|
|
88234
|
+
}
|
|
88235
|
+
try {
|
|
88236
|
+
const config = JSON.parse(env2.OPENCODE_CONFIG_CONTENT ?? "{}");
|
|
88237
|
+
if (Array.isArray(config.instructions)) {
|
|
88238
|
+
config.instructions = config.instructions.filter((file2) => typeof file2 !== "string" || path12.dirname(file2) !== path12.join(machineHome(), "prompts") || !/^opencode-language(?:-[a-f0-9]{16})?\.md$/.test(path12.basename(file2)));
|
|
88239
|
+
env2.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
|
|
88240
|
+
}
|
|
88241
|
+
} catch {
|
|
88242
|
+
}
|
|
88243
|
+
return env2;
|
|
88244
|
+
}
|
|
88245
|
+
function withSystemLanguage(harness, argv, env2, language) {
|
|
88246
|
+
env2 = languageEnv(env2);
|
|
88247
|
+
const text3 = systemLanguage(language);
|
|
88248
|
+
if (!text3) return { argv, env: env2 };
|
|
88249
|
+
const added = argv.length ? harness.systemPrompt?.(text3, argv, env2) : void 0;
|
|
88250
|
+
if (!added?.args?.length && !Object.keys(added?.env ?? {}).length) {
|
|
88251
|
+
const note = language === "zh" ? "\u8BED\u8A00\u89C4\u5219\u672A\u80FD\u66F4\u65B0\uFF1A\u8FDE\u63A5\u5668\u3001\u5DF2\u6709\u4F1A\u8BDD\u6216\u81EA\u8BBE\u7CFB\u7EDF\u63D0\u793A\u8BCD\u4E0D\u652F\u6301\u6CE8\u5165\u3002\u8BF7\u81EA\u884C\u53E6\u5F00\u652F\u6301\u7684\u4F1A\u8BDD\u4EE5\u91C7\u7528\u65B0\u89C4\u5219\u3002" : "Language rules could not be updated: the connector, existing session, or custom system prompt prevents injection. Open a supported new session to apply them.";
|
|
88252
|
+
return { argv, env: env2, note };
|
|
88253
|
+
}
|
|
88254
|
+
const at2 = /^node(?:\.exe)?$/.test(path12.basename(argv[0])) && argv[1] && !argv[1].startsWith("-") ? 2 : 1;
|
|
88255
|
+
return { argv: [...argv.slice(0, at2), ...added?.args ?? [], ...argv.slice(at2)], env: { ...env2, ...added?.env } };
|
|
88158
88256
|
}
|
|
88159
88257
|
|
|
88160
88258
|
// src/api.ts
|
|
@@ -88167,6 +88265,7 @@ __export(api_exports, {
|
|
|
88167
88265
|
claimJob: () => claimJob,
|
|
88168
88266
|
commitBoard: () => commitBoard,
|
|
88169
88267
|
createArtifact: () => createArtifact,
|
|
88268
|
+
createProject: () => createProject,
|
|
88170
88269
|
createUpload: () => createUpload,
|
|
88171
88270
|
createVersion: () => createVersion,
|
|
88172
88271
|
dispatchReview: () => dispatchReview,
|
|
@@ -88216,14 +88315,14 @@ __export(api_exports, {
|
|
|
88216
88315
|
|
|
88217
88316
|
// src/goals.ts
|
|
88218
88317
|
import fs9 from "node:fs";
|
|
88219
|
-
import
|
|
88318
|
+
import path13 from "node:path";
|
|
88220
88319
|
function goalsOf(held4) {
|
|
88221
88320
|
if (held4.goals !== void 0 && held4.ideas !== void 0 && JSON.stringify(held4.goals) !== JSON.stringify(held4.ideas)) throw new Error("goals and ideas do not match.");
|
|
88222
88321
|
const goals = held4.goals ?? held4.ideas;
|
|
88223
88322
|
if (!Array.isArray(goals)) throw new Error("The goals array is missing or invalid.");
|
|
88224
88323
|
return goals;
|
|
88225
88324
|
}
|
|
88226
|
-
var goalsFileOf = (job) =>
|
|
88325
|
+
var goalsFileOf = (job) => path13.join(runnerHome(), "ideas", `${job.id}.json`);
|
|
88227
88326
|
async function writeGoals(job, list) {
|
|
88228
88327
|
let goals;
|
|
88229
88328
|
try {
|
|
@@ -88240,7 +88339,7 @@ async function writeGoals(job, list) {
|
|
|
88240
88339
|
after = page.value.next;
|
|
88241
88340
|
} while (after);
|
|
88242
88341
|
const file2 = goalsFileOf(job);
|
|
88243
|
-
fs9.mkdirSync(
|
|
88342
|
+
fs9.mkdirSync(path13.dirname(file2), { recursive: true });
|
|
88244
88343
|
fs9.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: goals }, null, 2)}
|
|
88245
88344
|
`);
|
|
88246
88345
|
return { file: file2 };
|
|
@@ -88257,8 +88356,8 @@ function readGoals(file2) {
|
|
|
88257
88356
|
|
|
88258
88357
|
// src/secrets.ts
|
|
88259
88358
|
import fs10 from "node:fs";
|
|
88260
|
-
import
|
|
88261
|
-
var file = () =>
|
|
88359
|
+
import path14 from "node:path";
|
|
88360
|
+
var file = () => path14.join(runnerHome(), "secrets.json");
|
|
88262
88361
|
function readAll() {
|
|
88263
88362
|
try {
|
|
88264
88363
|
const held4 = JSON.parse(fs10.readFileSync(file(), "utf8"));
|
|
@@ -88287,10 +88386,10 @@ var secretsSet = () => Object.fromEntries(Object.entries(readAll()).map(([id, ke
|
|
|
88287
88386
|
|
|
88288
88387
|
// src/api.ts
|
|
88289
88388
|
var RUNTIMES = ["claude-code", "codex", "cursor", "opencode", "kimi", "dsh", "zcode", "grok"];
|
|
88290
|
-
var PROTOCOL =
|
|
88389
|
+
var PROTOCOL = 15;
|
|
88291
88390
|
var TIMEOUT_MS = 2e4;
|
|
88292
|
-
async function send(method, route, body, signedIn, ms, type) {
|
|
88293
|
-
const headers = { accept: "application/json" };
|
|
88391
|
+
async function send(method, route, body, signedIn, ms, type, extra = {}) {
|
|
88392
|
+
const headers = { accept: "application/json", ...extra };
|
|
88294
88393
|
if (signedIn) {
|
|
88295
88394
|
const token = await accessToken();
|
|
88296
88395
|
if (!token.ok) {
|
|
@@ -88374,7 +88473,11 @@ var listFolders = (machineId2) => request("GET", `/v1/runner/folders?machine=${q
|
|
|
88374
88473
|
var listElsewhere = (machineId2) => request("GET", `/v1/runner/folders?machine=${q(machineId2)}&elsewhere=1`);
|
|
88375
88474
|
var listMachineTasks = (machineId2) => request("GET", `/v1/runner/tasks?machine=${q(machineId2)}`);
|
|
88376
88475
|
var stopTask = (task, how) => request("POST", how === "chat" ? `/v1/tasks/${q(task)}/chat/stop` : `/v1/tasks/${q(task)}/stop`, {});
|
|
88377
|
-
var addFolder = (machineId2, name,
|
|
88476
|
+
var addFolder = (machineId2, name, path40, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path40, ...project ? { project } : {} });
|
|
88477
|
+
async function createProject(name, workspace, key) {
|
|
88478
|
+
const sent = await send("POST", "/v1/projects", { name, workspace }, true, TIMEOUT_MS, void 0, { "idempotency-key": key });
|
|
88479
|
+
return sent.ok ? answerOf(sent.value) : sent;
|
|
88480
|
+
}
|
|
88378
88481
|
var removeFolder = (machineId2, project) => request("POST", `/v1/runner/folders/${q(project)}/remove`, { machineId: machineId2 });
|
|
88379
88482
|
var readBoard = (project, since) => request("GET", `/v1/projects/${q(project)}/board${since === null ? "" : `?since=${since}`}`);
|
|
88380
88483
|
async function commitBoard(project, job, machine, files) {
|
|
@@ -88448,7 +88551,7 @@ function commandOf(harness) {
|
|
|
88448
88551
|
const [binary, ...flags] = splitCommand(harness.command);
|
|
88449
88552
|
return [spawnName(chooseCopy(harness, SPAWN_MS), binary), ...flags];
|
|
88450
88553
|
}
|
|
88451
|
-
function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false,
|
|
88554
|
+
function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, language = null) {
|
|
88452
88555
|
const harness = HARNESSES2[runtime];
|
|
88453
88556
|
const values = held(runtime, model, given);
|
|
88454
88557
|
const [binary, ...flags] = commandOf(harness);
|
|
@@ -88457,21 +88560,22 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88457
88560
|
const copied = fork && resume && harness.forkArgs ? harness.forkArgs(base, resume, id, cwd) : null;
|
|
88458
88561
|
if (fork) resume = null;
|
|
88459
88562
|
const extra = copied ?? (resume ? harness.resumeArgs(base, resume, cwd) : harness.extraArgs(base, id, cwd));
|
|
88460
|
-
const quiet = (
|
|
88461
|
-
const { argv, env: env2 } = withSystemLanguage(harness, [...base, ...extra], copyEnv(binary, { ...process.env, ...settingEnv(harness, values, given.secrets ?? {}, cwd), WILDCRANE_JOB: "1" }),
|
|
88563
|
+
const quiet = (line) => harness.quietStderr?.(line) ?? false;
|
|
88564
|
+
const { argv, env: env2, note } = withSystemLanguage(harness, [...base, ...extra], copyEnv(binary, { ...process.env, ...settingEnv(harness, values, given.secrets ?? {}, cwd), WILDCRANE_JOB: "1", [LANGUAGE_ENV]: language ?? "", [LANGUAGE_LINE_ENV]: void 0 }), language);
|
|
88462
88565
|
if (harness.client) {
|
|
88463
88566
|
const client = harness.client(effectiveValues(harness, values));
|
|
88464
88567
|
let session;
|
|
88465
88568
|
let named2;
|
|
88466
88569
|
return {
|
|
88570
|
+
startNote: note,
|
|
88467
88571
|
command: argv[0],
|
|
88468
88572
|
args: argv.slice(1),
|
|
88469
88573
|
env: env2,
|
|
88470
|
-
converse: (child, event2) => client.turn({
|
|
88574
|
+
converse: (child, event2, restart = true) => client.turn({
|
|
88471
88575
|
stdout: child.stdout,
|
|
88472
88576
|
stdin: child.stdin,
|
|
88473
88577
|
prompt,
|
|
88474
|
-
restartPrompt: prompt,
|
|
88578
|
+
restartPrompt: restart ? prompt : void 0,
|
|
88475
88579
|
cwd,
|
|
88476
88580
|
resumeId: resume ?? void 0,
|
|
88477
88581
|
log: () => {
|
|
@@ -88490,6 +88594,7 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88490
88594
|
const renderer = harness.renderer(cwd, argv[0], argv);
|
|
88491
88595
|
const toStdin = harness.stdinPrompt?.(argv);
|
|
88492
88596
|
return {
|
|
88597
|
+
startNote: note,
|
|
88493
88598
|
command: argv[0],
|
|
88494
88599
|
args: [...argv.slice(1), ...toStdin ? [] : [prompt]],
|
|
88495
88600
|
env: env2,
|
|
@@ -88541,14 +88646,14 @@ var listed = (harness) => async () => (harness.models?.() ?? []).map((id) => ({
|
|
|
88541
88646
|
var readModels = (name) => (MODELS[name] ?? listed(HARNESSES2[name]))().catch(() => []);
|
|
88542
88647
|
var MODELS = {
|
|
88543
88648
|
"claude-code": async () => {
|
|
88544
|
-
const cached2 = claudeModels(
|
|
88649
|
+
const cached2 = claudeModels(path15.join(process.env.CLAUDE_CONFIG_DIR || path15.join(os4.homedir(), ".claude"), "cache", "model-catalog"));
|
|
88545
88650
|
return cached2.length ? cached2 : [
|
|
88546
88651
|
{ id: "opus", name: "Opus" },
|
|
88547
88652
|
{ id: "sonnet", name: "Sonnet" },
|
|
88548
88653
|
{ id: "haiku", name: "Haiku" }
|
|
88549
88654
|
];
|
|
88550
88655
|
},
|
|
88551
|
-
codex: async () => codexModels(
|
|
88656
|
+
codex: async () => codexModels(path15.join(process.env.CODEX_HOME || path15.join(os4.homedir(), ".codex"), "models_cache.json")),
|
|
88552
88657
|
opencode: async () => opencodeModels(await output(commandOf(HARNESSES2.opencode)[0], ["models"])),
|
|
88553
88658
|
cursor: () => cursorModels()
|
|
88554
88659
|
};
|
|
@@ -88620,7 +88725,7 @@ function claudeModels(dir) {
|
|
|
88620
88725
|
}
|
|
88621
88726
|
const catalogs = files.flatMap((f2) => {
|
|
88622
88727
|
try {
|
|
88623
|
-
const data = obj(JSON.parse(fs11.readFileSync(
|
|
88728
|
+
const data = obj(JSON.parse(fs11.readFileSync(path15.join(dir, f2), "utf8")));
|
|
88624
88729
|
const catalog = obj(data.catalog);
|
|
88625
88730
|
const surface = str(catalog.surface);
|
|
88626
88731
|
return surface === "cc" || surface === "ccd" ? [{ surface, at: Number(data.fetchedAt) || 0, config: obj(catalog.config) }] : [];
|
|
@@ -88812,6 +88917,114 @@ function connectCloudLive(handlers) {
|
|
|
88812
88917
|
};
|
|
88813
88918
|
}
|
|
88814
88919
|
|
|
88920
|
+
// src/folders.ts
|
|
88921
|
+
import fs12 from "node:fs";
|
|
88922
|
+
import path16 from "node:path";
|
|
88923
|
+
var projectsFile = () => path16.join(runnerHome(), "projects.json");
|
|
88924
|
+
function realpath(p2) {
|
|
88925
|
+
try {
|
|
88926
|
+
return fs12.realpathSync(p2);
|
|
88927
|
+
} catch {
|
|
88928
|
+
return null;
|
|
88929
|
+
}
|
|
88930
|
+
}
|
|
88931
|
+
function readGrants() {
|
|
88932
|
+
try {
|
|
88933
|
+
const held4 = JSON.parse(fs12.readFileSync(projectsFile(), "utf8"));
|
|
88934
|
+
if (!Array.isArray(held4.projects)) throw new Error("invalid_projects");
|
|
88935
|
+
return held4;
|
|
88936
|
+
} catch (error) {
|
|
88937
|
+
if (error.code === "ENOENT") return { projects: [] };
|
|
88938
|
+
throw error;
|
|
88939
|
+
}
|
|
88940
|
+
}
|
|
88941
|
+
function listOf(held4) {
|
|
88942
|
+
const subject = readSession()?.subject;
|
|
88943
|
+
if (!held4.accounts) return held4.projects;
|
|
88944
|
+
return subject ? held4.accounts[subject] ?? [] : [];
|
|
88945
|
+
}
|
|
88946
|
+
function update2(change) {
|
|
88947
|
+
fs12.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
|
|
88948
|
+
const lock = `${projectsFile()}.lock`;
|
|
88949
|
+
let fd;
|
|
88950
|
+
const until = Date.now() + 2e3;
|
|
88951
|
+
for (; ; ) {
|
|
88952
|
+
try {
|
|
88953
|
+
fd = fs12.openSync(lock, "wx", 384);
|
|
88954
|
+
fs12.writeFileSync(fd, String(process.pid));
|
|
88955
|
+
break;
|
|
88956
|
+
} catch {
|
|
88957
|
+
try {
|
|
88958
|
+
const pid = Number(fs12.readFileSync(lock, "utf8"));
|
|
88959
|
+
if (pid > 0) {
|
|
88960
|
+
try {
|
|
88961
|
+
process.kill(pid, 0);
|
|
88962
|
+
} catch {
|
|
88963
|
+
fs12.rmSync(lock, { force: true });
|
|
88964
|
+
}
|
|
88965
|
+
}
|
|
88966
|
+
} catch {
|
|
88967
|
+
}
|
|
88968
|
+
if (Date.now() > until) throw new Error("authorization_busy");
|
|
88969
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 10);
|
|
88970
|
+
}
|
|
88971
|
+
}
|
|
88972
|
+
try {
|
|
88973
|
+
const held4 = readGrants();
|
|
88974
|
+
const subject = readSession()?.subject;
|
|
88975
|
+
const before = listOf(held4);
|
|
88976
|
+
const after = [...new Set(change(before))];
|
|
88977
|
+
if (subject) {
|
|
88978
|
+
if (!held4.accounts) {
|
|
88979
|
+
held4.accounts = { [subject]: held4.projects };
|
|
88980
|
+
held4.legacyOwner = subject;
|
|
88981
|
+
}
|
|
88982
|
+
held4.accounts[subject] = after;
|
|
88983
|
+
held4.projects = after;
|
|
88984
|
+
} else held4.projects = after;
|
|
88985
|
+
const tmp = `${projectsFile()}.${process.pid}.tmp`;
|
|
88986
|
+
fs12.writeFileSync(tmp, `${JSON.stringify(held4, null, 2)}
|
|
88987
|
+
`, { mode: 384 });
|
|
88988
|
+
fs12.renameSync(tmp, projectsFile());
|
|
88989
|
+
return before.filter((p2) => !after.includes(p2));
|
|
88990
|
+
} finally {
|
|
88991
|
+
fs12.closeSync(fd);
|
|
88992
|
+
fs12.rmSync(lock, { force: true });
|
|
88993
|
+
}
|
|
88994
|
+
}
|
|
88995
|
+
function adoptLegacy() {
|
|
88996
|
+
if (readSession() && !readGrants().accounts) update2((list) => list);
|
|
88997
|
+
}
|
|
88998
|
+
function allowedProjects() {
|
|
88999
|
+
return listOf(readGrants()).flatMap((p2) => {
|
|
89000
|
+
const real = realpath(p2);
|
|
89001
|
+
return real && fs12.statSync(real).isDirectory() ? [real] : [];
|
|
89002
|
+
});
|
|
89003
|
+
}
|
|
89004
|
+
|
|
89005
|
+
// src/connect.ts
|
|
89006
|
+
import fs36 from "node:fs";
|
|
89007
|
+
import path39 from "node:path";
|
|
89008
|
+
|
|
89009
|
+
// src/settings-control.ts
|
|
89010
|
+
import fs13 from "node:fs";
|
|
89011
|
+
import path17 from "node:path";
|
|
89012
|
+
var directory = () => path17.join(runnerHome(), "executors");
|
|
89013
|
+
var epochFile = () => path17.join(runnerHome(), "account-generation");
|
|
89014
|
+
function accountGeneration() {
|
|
89015
|
+
try {
|
|
89016
|
+
return fs13.readFileSync(epochFile(), "utf8");
|
|
89017
|
+
} catch {
|
|
89018
|
+
return "";
|
|
89019
|
+
}
|
|
89020
|
+
}
|
|
89021
|
+
function executorRecord() {
|
|
89022
|
+
fs13.mkdirSync(directory(), { recursive: true, mode: 448 });
|
|
89023
|
+
const file2 = path17.join(directory(), `${process.pid}.json`);
|
|
89024
|
+
fs13.writeFileSync(file2, "{}", { mode: 384 });
|
|
89025
|
+
return () => fs13.rmSync(file2, { force: true });
|
|
89026
|
+
}
|
|
89027
|
+
|
|
88815
89028
|
// ../cli/src/lib/cadence.ts
|
|
88816
89029
|
var AUTO_CADENCE = "auto";
|
|
88817
89030
|
var isAuto = (cadence) => cadence.trim().toLowerCase() === AUTO_CADENCE;
|
|
@@ -88927,48 +89140,48 @@ async function askDueAgents(machineId2, now = Date.now()) {
|
|
|
88927
89140
|
|
|
88928
89141
|
// src/akb-version.ts
|
|
88929
89142
|
import { execFile } from "node:child_process";
|
|
88930
|
-
import
|
|
88931
|
-
import
|
|
89143
|
+
import fs17 from "node:fs";
|
|
89144
|
+
import path21 from "node:path";
|
|
88932
89145
|
|
|
88933
89146
|
// src/akb.ts
|
|
88934
89147
|
import { spawn as spawn3 } from "node:child_process";
|
|
88935
|
-
import
|
|
88936
|
-
import
|
|
89148
|
+
import fs14 from "node:fs";
|
|
89149
|
+
import path18 from "node:path";
|
|
88937
89150
|
import { fileURLToPath } from "node:url";
|
|
88938
|
-
var akbHome = () =>
|
|
89151
|
+
var akbHome = () => path18.join(runnerHome(), "bin", "akb");
|
|
88939
89152
|
var BUNDLED_SHIM = `bundled-${AKB_VERSION}`;
|
|
88940
89153
|
var bundledAkb = () => ({
|
|
88941
89154
|
command: process.execPath,
|
|
88942
|
-
args: [
|
|
89155
|
+
args: [path18.join(path18.dirname(fileURLToPath(import.meta.url)), "akb", "bin", "ai4kanban.mjs")],
|
|
88943
89156
|
version: AKB_VERSION,
|
|
88944
|
-
shim:
|
|
89157
|
+
shim: path18.join(akbHome(), BUNDLED_SHIM)
|
|
88945
89158
|
});
|
|
88946
89159
|
var quote = (s) => /^[\w./:@=-]+$/.test(s) ? s : `"${s}"`;
|
|
88947
89160
|
function shimDir(akb) {
|
|
88948
89161
|
const dir = akb.shim;
|
|
88949
89162
|
const line = [akb.command, ...akb.args].map(quote).join(" ");
|
|
88950
|
-
const [file2, text3] = process.platform === "win32" ? [
|
|
88951
|
-
`] : [
|
|
89163
|
+
const [file2, text3] = process.platform === "win32" ? [path18.join(dir, "akb.cmd"), `@${line} %*\r
|
|
89164
|
+
`] : [path18.join(dir, "akb"), `#!/bin/sh
|
|
88952
89165
|
exec ${line} "$@"
|
|
88953
89166
|
`];
|
|
88954
89167
|
try {
|
|
88955
|
-
if (
|
|
89168
|
+
if (fs14.readFileSync(file2, "utf8") === text3) return dir;
|
|
88956
89169
|
} catch {
|
|
88957
89170
|
}
|
|
88958
|
-
|
|
88959
|
-
|
|
89171
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
89172
|
+
fs14.writeFileSync(file2, text3, { mode: 493 });
|
|
88960
89173
|
return dir;
|
|
88961
89174
|
}
|
|
88962
|
-
function akbEnv(akb, board, task,
|
|
89175
|
+
function akbEnv(akb, board, task, language, base = process.env) {
|
|
88963
89176
|
const env2 = {};
|
|
88964
|
-
const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", "AI4KANBAN_EXECUTION", LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
|
|
88965
|
-
for (const [k, v2] of Object.entries(
|
|
89177
|
+
const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", "AI4KANBAN_EXECUTION", LANGUAGE_ENV, LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
|
|
89178
|
+
for (const [k, v2] of Object.entries(base)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
|
|
88966
89179
|
const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
88967
|
-
env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(
|
|
89180
|
+
env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path18.delimiter);
|
|
88968
89181
|
env2.AI4KANBAN_COMMAND = "akb";
|
|
88969
89182
|
if (board) env2.AI4KANBAN_BOARD = board;
|
|
88970
89183
|
if (task) env2.AI4KANBAN_TASK = task;
|
|
88971
|
-
if (
|
|
89184
|
+
if (language !== void 0) env2[LANGUAGE_ENV] = language ?? "";
|
|
88972
89185
|
return env2;
|
|
88973
89186
|
}
|
|
88974
89187
|
var KEEP = 256 * 1024;
|
|
@@ -88982,7 +89195,7 @@ function runAkb(akb, args, opts) {
|
|
|
88982
89195
|
};
|
|
88983
89196
|
let child;
|
|
88984
89197
|
try {
|
|
88985
|
-
child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: { ...akbEnv(akb, opts.board, opts.task, opts.
|
|
89198
|
+
child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: { ...akbEnv(akb, opts.board, opts.task, opts.language), ...opts.env }, detached: process.platform !== "win32", stdio: ["ignore", "pipe", "pipe"] });
|
|
88986
89199
|
} catch (e2) {
|
|
88987
89200
|
return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
|
|
88988
89201
|
}
|
|
@@ -89013,65 +89226,45 @@ function answerOf2(ran) {
|
|
|
89013
89226
|
|
|
89014
89227
|
// src/cache.ts
|
|
89015
89228
|
import { spawnSync as spawnSync3 } from "node:child_process";
|
|
89016
|
-
import
|
|
89017
|
-
import
|
|
89018
|
-
|
|
89019
|
-
// src/folders.ts
|
|
89020
|
-
import fs13 from "node:fs";
|
|
89021
|
-
import path16 from "node:path";
|
|
89022
|
-
var projectsFile = () => path16.join(runnerHome(), "projects.json");
|
|
89023
|
-
function realpath(p2) {
|
|
89024
|
-
try {
|
|
89025
|
-
return fs13.realpathSync(p2);
|
|
89026
|
-
} catch {
|
|
89027
|
-
return null;
|
|
89028
|
-
}
|
|
89029
|
-
}
|
|
89030
|
-
function readList() {
|
|
89031
|
-
try {
|
|
89032
|
-
const held4 = JSON.parse(fs13.readFileSync(projectsFile(), "utf8"));
|
|
89033
|
-
return Array.isArray(held4.projects) ? held4.projects.filter((p2) => typeof p2 === "string") : [];
|
|
89034
|
-
} catch {
|
|
89035
|
-
return [];
|
|
89036
|
-
}
|
|
89037
|
-
}
|
|
89038
|
-
function allowedProjects() {
|
|
89039
|
-
return readList().flatMap((p2) => [realpath(p2)].filter((r2) => !!r2));
|
|
89040
|
-
}
|
|
89041
|
-
|
|
89042
|
-
// src/cache.ts
|
|
89229
|
+
import crypto2 from "node:crypto";
|
|
89230
|
+
import fs15 from "node:fs";
|
|
89231
|
+
import path19 from "node:path";
|
|
89043
89232
|
var IDLE_MS = 7 * 24 * 60 * 6e4;
|
|
89044
89233
|
var SWEEP_MS = 24 * 60 * 6e4;
|
|
89045
89234
|
var PROJECT_ID = /^[\w-]{1,100}$/;
|
|
89046
|
-
var cacheRoot = () =>
|
|
89235
|
+
var cacheRoot = () => path19.join(runnerHome(), "cache");
|
|
89047
89236
|
function cacheDir(project) {
|
|
89048
89237
|
if (!PROJECT_ID.test(project)) throw new Error("This job names no project.");
|
|
89049
|
-
return
|
|
89238
|
+
return path19.join(cacheRoot(), project);
|
|
89050
89239
|
}
|
|
89051
|
-
var akbDir = (dir) =>
|
|
89052
|
-
var usedFile = (dir) =>
|
|
89053
|
-
var unsentFile = (dir) =>
|
|
89240
|
+
var akbDir = (dir) => path19.join(dir, ".akb");
|
|
89241
|
+
var usedFile = (dir) => path19.join(akbDir(dir), "used.json");
|
|
89242
|
+
var unsentFile = (dir) => path19.join(akbDir(dir), "unsent");
|
|
89054
89243
|
function markUsed(dir, at2 = Date.now()) {
|
|
89055
|
-
|
|
89056
|
-
|
|
89244
|
+
fs15.mkdirSync(akbDir(dir), { recursive: true });
|
|
89245
|
+
fs15.writeFileSync(usedFile(dir), `${JSON.stringify({ at: at2 })}
|
|
89057
89246
|
`);
|
|
89058
89247
|
}
|
|
89059
89248
|
function usedAt(dir) {
|
|
89060
89249
|
try {
|
|
89061
|
-
const at2 = JSON.parse(
|
|
89250
|
+
const at2 = JSON.parse(fs15.readFileSync(usedFile(dir), "utf8")).at;
|
|
89062
89251
|
return typeof at2 === "number" ? at2 : null;
|
|
89063
89252
|
} catch {
|
|
89064
89253
|
return null;
|
|
89065
89254
|
}
|
|
89066
89255
|
}
|
|
89067
|
-
var unsent = (dir) =>
|
|
89256
|
+
var unsent = (dir) => fs15.existsSync(unsentFile(dir));
|
|
89068
89257
|
function markUnsent(dir, unsent2) {
|
|
89069
|
-
if (!unsent2) return void
|
|
89070
|
-
|
|
89071
|
-
|
|
89258
|
+
if (!unsent2) return void fs15.rmSync(unsentFile(dir), { force: true });
|
|
89259
|
+
fs15.mkdirSync(akbDir(dir), { recursive: true });
|
|
89260
|
+
fs15.writeFileSync(unsentFile(dir), "");
|
|
89072
89261
|
}
|
|
89073
89262
|
var holds = /* @__PURE__ */ new Map();
|
|
89263
|
+
var holdsDir = () => path19.join(runnerHome(), "holds");
|
|
89264
|
+
var holdFile = (dir) => path19.join(holdsDir(), `${crypto2.createHash("sha256").update(dir).digest("hex")}.${process.pid}`);
|
|
89074
89265
|
function hold(dir) {
|
|
89266
|
+
fs15.mkdirSync(holdsDir(), { recursive: true, mode: 448 });
|
|
89267
|
+
fs15.writeFileSync(holdFile(dir), "", { mode: 384 });
|
|
89075
89268
|
holds.set(dir, (holds.get(dir) ?? 0) + 1);
|
|
89076
89269
|
let held4 = true;
|
|
89077
89270
|
return () => {
|
|
@@ -89079,30 +89272,49 @@ function hold(dir) {
|
|
|
89079
89272
|
held4 = false;
|
|
89080
89273
|
const left = holds.get(dir) - 1;
|
|
89081
89274
|
if (left) holds.set(dir, left);
|
|
89082
|
-
else
|
|
89275
|
+
else {
|
|
89276
|
+
holds.delete(dir);
|
|
89277
|
+
fs15.rmSync(holdFile(dir), { force: true });
|
|
89278
|
+
}
|
|
89083
89279
|
};
|
|
89084
89280
|
}
|
|
89085
89281
|
function paused(dir) {
|
|
89086
89282
|
try {
|
|
89087
|
-
const file2 =
|
|
89088
|
-
const held4 = JSON.parse(
|
|
89283
|
+
const file2 = path19.join(projectStateDir(path19.join(akbDir(dir), "kanban")), SESSIONS_FILE);
|
|
89284
|
+
const held4 = JSON.parse(fs15.readFileSync(file2, "utf8"));
|
|
89089
89285
|
return (held4.deliveries ?? []).some((d2) => d2.status === "active");
|
|
89090
89286
|
} catch {
|
|
89091
89287
|
return false;
|
|
89092
89288
|
}
|
|
89093
89289
|
}
|
|
89094
|
-
|
|
89290
|
+
function busy(dir) {
|
|
89291
|
+
if (holds.has(dir)) return true;
|
|
89292
|
+
const prefix = path19.basename(holdFile(dir)).split(".")[0] + ".";
|
|
89293
|
+
try {
|
|
89294
|
+
return fs15.readdirSync(holdsDir()).filter((file2) => file2.startsWith(prefix)).some((file2) => {
|
|
89295
|
+
try {
|
|
89296
|
+
process.kill(Number(file2.split(".")[1]), 0);
|
|
89297
|
+
return true;
|
|
89298
|
+
} catch {
|
|
89299
|
+
fs15.rmSync(path19.join(holdsDir(), file2), { force: true });
|
|
89300
|
+
return false;
|
|
89301
|
+
}
|
|
89302
|
+
});
|
|
89303
|
+
} catch {
|
|
89304
|
+
return false;
|
|
89305
|
+
}
|
|
89306
|
+
}
|
|
89095
89307
|
var kept2 = (dir) => busy(dir) || unsent(dir) || paused(dir);
|
|
89096
89308
|
function clearAkb(dir) {
|
|
89097
89309
|
dir = realpath2(dir);
|
|
89098
89310
|
if (kept2(dir)) return false;
|
|
89099
89311
|
let entries;
|
|
89100
89312
|
try {
|
|
89101
|
-
entries =
|
|
89313
|
+
entries = fs15.readdirSync(akbDir(dir));
|
|
89102
89314
|
} catch {
|
|
89103
89315
|
return true;
|
|
89104
89316
|
}
|
|
89105
|
-
for (const name of entries)
|
|
89317
|
+
for (const name of entries) fs15.rmSync(path19.join(akbDir(dir), name), { recursive: true, force: true });
|
|
89106
89318
|
spawnSync3("git", ["-C", dir, "worktree", "prune"], { stdio: "ignore" });
|
|
89107
89319
|
return true;
|
|
89108
89320
|
}
|
|
@@ -89117,7 +89329,7 @@ async function readAccess(machineId2) {
|
|
|
89117
89329
|
}
|
|
89118
89330
|
function realpath2(p2) {
|
|
89119
89331
|
try {
|
|
89120
|
-
return
|
|
89332
|
+
return fs15.realpathSync(p2);
|
|
89121
89333
|
} catch {
|
|
89122
89334
|
return p2;
|
|
89123
89335
|
}
|
|
@@ -89132,22 +89344,22 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89132
89344
|
const swept = [];
|
|
89133
89345
|
let cached2 = [];
|
|
89134
89346
|
try {
|
|
89135
|
-
cached2 =
|
|
89347
|
+
cached2 = fs15.readdirSync(cacheRoot(), { withFileTypes: true });
|
|
89136
89348
|
} catch {
|
|
89137
89349
|
}
|
|
89138
89350
|
for (const e2 of cached2) {
|
|
89139
|
-
const dir =
|
|
89351
|
+
const dir = path19.join(cacheRoot(), e2.name);
|
|
89140
89352
|
if (!e2.isDirectory() || kept2(dir)) continue;
|
|
89141
89353
|
const gone = access && !access.projects.has(e2.name);
|
|
89142
89354
|
if (idle(dir, now) || gone) {
|
|
89143
|
-
|
|
89355
|
+
fs15.rmSync(dir, { recursive: true, force: true });
|
|
89144
89356
|
swept.push(dir);
|
|
89145
89357
|
}
|
|
89146
89358
|
}
|
|
89147
89359
|
for (const dir of allowedProjects()) {
|
|
89148
89360
|
let held4 = [];
|
|
89149
89361
|
try {
|
|
89150
|
-
held4 =
|
|
89362
|
+
held4 = fs15.readdirSync(akbDir(dir));
|
|
89151
89363
|
} catch {
|
|
89152
89364
|
}
|
|
89153
89365
|
if (!held4.length) continue;
|
|
@@ -89158,31 +89370,31 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89158
89370
|
}
|
|
89159
89371
|
function removeLegacy() {
|
|
89160
89372
|
const home4 = runnerHome();
|
|
89161
|
-
for (const name of ["boards", "akb-bin"])
|
|
89373
|
+
for (const name of ["boards", "akb-bin"]) fs15.rmSync(path19.join(home4, name), { recursive: true, force: true });
|
|
89162
89374
|
let entries = [];
|
|
89163
89375
|
try {
|
|
89164
|
-
entries =
|
|
89376
|
+
entries = fs15.readdirSync(home4, { withFileTypes: true });
|
|
89165
89377
|
} catch {
|
|
89166
89378
|
return;
|
|
89167
89379
|
}
|
|
89168
89380
|
for (const e2 of entries) {
|
|
89169
|
-
const account =
|
|
89170
|
-
if (!e2.isDirectory() || !
|
|
89171
|
-
|
|
89172
|
-
if (!
|
|
89381
|
+
const account = path19.join(home4, e2.name);
|
|
89382
|
+
if (!e2.isDirectory() || !fs15.existsSync(path19.join(account, "unfiled"))) continue;
|
|
89383
|
+
fs15.rmSync(path19.join(account, "unfiled"), { recursive: true, force: true });
|
|
89384
|
+
if (!fs15.readdirSync(account).length) fs15.rmdirSync(account);
|
|
89173
89385
|
}
|
|
89174
89386
|
}
|
|
89175
89387
|
|
|
89176
89388
|
// src/update.ts
|
|
89177
|
-
import
|
|
89178
|
-
import
|
|
89179
|
-
import
|
|
89389
|
+
import crypto3 from "node:crypto";
|
|
89390
|
+
import fs16 from "node:fs";
|
|
89391
|
+
import path20 from "node:path";
|
|
89180
89392
|
import zlib from "node:zlib";
|
|
89181
89393
|
var TIMEOUT_MS2 = 6e4;
|
|
89182
89394
|
var registry = () => (process.env.npm_config_registry || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
89183
89395
|
async function installPackage(pkg, version, nodeVersion = process.versions.node) {
|
|
89184
89396
|
const dir = pkg.dirOf(version);
|
|
89185
|
-
if (
|
|
89397
|
+
if (fs16.existsSync(pkg.entryOf(dir))) return { ok: true, dir };
|
|
89186
89398
|
let meta;
|
|
89187
89399
|
let tarball;
|
|
89188
89400
|
try {
|
|
@@ -89199,17 +89411,17 @@ async function installPackage(pkg, version, nodeVersion = process.versions.node)
|
|
|
89199
89411
|
return { ok: false, why: "unreachable", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89200
89412
|
}
|
|
89201
89413
|
const expected = /^sha512-(.+)$/.exec(meta.dist.integrity ?? "")?.[1];
|
|
89202
|
-
const actual =
|
|
89414
|
+
const actual = crypto3.createHash("sha512").update(tarball).digest("base64");
|
|
89203
89415
|
if (!expected || expected !== actual) return { ok: false, why: "integrity", detail: "sha512 mismatch" };
|
|
89204
89416
|
const staging = `${dir}.${process.pid}.tmp`;
|
|
89205
89417
|
try {
|
|
89206
|
-
|
|
89418
|
+
fs16.rmSync(staging, { recursive: true, force: true });
|
|
89207
89419
|
extract(zlib.gunzipSync(tarball), staging);
|
|
89208
|
-
if (!
|
|
89209
|
-
|
|
89210
|
-
|
|
89420
|
+
if (!fs16.existsSync(pkg.entryOf(staging))) throw new Error(`the package carries no ${path20.relative(staging, pkg.entryOf(staging))}`);
|
|
89421
|
+
fs16.rmSync(dir, { recursive: true, force: true });
|
|
89422
|
+
fs16.renameSync(staging, dir);
|
|
89211
89423
|
} catch (e2) {
|
|
89212
|
-
|
|
89424
|
+
fs16.rmSync(staging, { recursive: true, force: true });
|
|
89213
89425
|
return { ok: false, why: "integrity", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89214
89426
|
}
|
|
89215
89427
|
return { ok: true, dir };
|
|
@@ -89239,12 +89451,12 @@ function extract(tar, into) {
|
|
|
89239
89451
|
if (type !== "0" && type !== "5") continue;
|
|
89240
89452
|
const relative = name.replace(/^[^/]+\//, "");
|
|
89241
89453
|
if (!relative) continue;
|
|
89242
|
-
const target =
|
|
89243
|
-
if (!target.startsWith(
|
|
89244
|
-
if (type === "5")
|
|
89454
|
+
const target = path20.resolve(into, relative);
|
|
89455
|
+
if (!target.startsWith(path20.resolve(into) + path20.sep)) throw new Error(`refusing ${name}`);
|
|
89456
|
+
if (type === "5") fs16.mkdirSync(target, { recursive: true });
|
|
89245
89457
|
else {
|
|
89246
|
-
|
|
89247
|
-
|
|
89458
|
+
fs16.mkdirSync(path20.dirname(target), { recursive: true });
|
|
89459
|
+
fs16.writeFileSync(target, body);
|
|
89248
89460
|
}
|
|
89249
89461
|
}
|
|
89250
89462
|
}
|
|
@@ -89292,33 +89504,33 @@ function meets(version, comparator) {
|
|
|
89292
89504
|
// src/akb-version.ts
|
|
89293
89505
|
var CHECK_MS2 = 1e4;
|
|
89294
89506
|
var VERSION2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
89295
|
-
var stateFile = () =>
|
|
89296
|
-
var akbVersionDir = (version) =>
|
|
89297
|
-
var entryOf = (dir) =>
|
|
89507
|
+
var stateFile = () => path21.join(akbHome(), "state.json");
|
|
89508
|
+
var akbVersionDir = (version) => path21.join(akbHome(), version);
|
|
89509
|
+
var entryOf = (dir) => path21.join(dir, "bin", "ai4kanban.mjs");
|
|
89298
89510
|
var AKB = { name: "wildcrane", dirOf: akbVersionDir, entryOf };
|
|
89299
89511
|
function readAkbState() {
|
|
89300
89512
|
try {
|
|
89301
|
-
const held4 = JSON.parse(
|
|
89513
|
+
const held4 = JSON.parse(fs17.readFileSync(stateFile(), "utf8"));
|
|
89302
89514
|
return { current: held4.current ?? null, bad: held4.bad ?? [] };
|
|
89303
89515
|
} catch {
|
|
89304
89516
|
return { current: null, bad: [] };
|
|
89305
89517
|
}
|
|
89306
89518
|
}
|
|
89307
89519
|
function writeAkbState(state) {
|
|
89308
|
-
|
|
89520
|
+
fs17.mkdirSync(akbHome(), { recursive: true });
|
|
89309
89521
|
const staging = `${stateFile()}.${process.pid}.tmp`;
|
|
89310
|
-
|
|
89522
|
+
fs17.writeFileSync(staging, `${JSON.stringify(state, null, 2)}
|
|
89311
89523
|
`);
|
|
89312
|
-
|
|
89524
|
+
fs17.renameSync(staging, stateFile());
|
|
89313
89525
|
}
|
|
89314
89526
|
function contractOf(dir) {
|
|
89315
89527
|
try {
|
|
89316
|
-
return JSON.parse(
|
|
89528
|
+
return JSON.parse(fs17.readFileSync(path21.join(dir, "package.json"), "utf8")).akbContract ?? null;
|
|
89317
89529
|
} catch {
|
|
89318
89530
|
return null;
|
|
89319
89531
|
}
|
|
89320
89532
|
}
|
|
89321
|
-
var usable = (dir) =>
|
|
89533
|
+
var usable = (dir) => fs17.existsSync(entryOf(dir)) && contractOf(dir) === AKB_CONTRACT;
|
|
89322
89534
|
function currentAkb() {
|
|
89323
89535
|
const { current } = readAkbState();
|
|
89324
89536
|
if (!current) return bundledAkb();
|
|
@@ -89326,10 +89538,10 @@ function currentAkb() {
|
|
|
89326
89538
|
if (!usable(dir)) return bundledAkb();
|
|
89327
89539
|
try {
|
|
89328
89540
|
const now = /* @__PURE__ */ new Date();
|
|
89329
|
-
|
|
89541
|
+
fs17.utimesSync(dir, now, now);
|
|
89330
89542
|
} catch {
|
|
89331
89543
|
}
|
|
89332
|
-
return { command: process.execPath, args: [entryOf(dir)], version: current, shim:
|
|
89544
|
+
return { command: process.execPath, args: [entryOf(dir)], version: current, shim: path21.join(dir, "shim") };
|
|
89333
89545
|
}
|
|
89334
89546
|
var answers2 = (dir, version) => new Promise((resolve2) => {
|
|
89335
89547
|
execFile(process.execPath, [entryOf(dir), "--version"], { timeout: CHECK_MS2, killSignal: "SIGKILL" }, (error, stdout) => resolve2(!error && stdout.trim().split(/\s+/).at(-1) === version));
|
|
@@ -89369,20 +89581,20 @@ function sweepAkb(now = Date.now()) {
|
|
|
89369
89581
|
const { current } = readAkbState();
|
|
89370
89582
|
let entries = [];
|
|
89371
89583
|
try {
|
|
89372
|
-
entries =
|
|
89584
|
+
entries = fs17.readdirSync(akbHome(), { withFileTypes: true });
|
|
89373
89585
|
} catch {
|
|
89374
89586
|
return;
|
|
89375
89587
|
}
|
|
89376
89588
|
for (const e2 of entries) {
|
|
89377
89589
|
if (!e2.isDirectory() || e2.name === current || e2.name === BUNDLED_SHIM) continue;
|
|
89378
|
-
const dir =
|
|
89379
|
-
if (now -
|
|
89590
|
+
const dir = path21.join(akbHome(), e2.name);
|
|
89591
|
+
if (now - fs17.statSync(dir).mtimeMs > IDLE_MS) fs17.rmSync(dir, { recursive: true, force: true });
|
|
89380
89592
|
}
|
|
89381
89593
|
}
|
|
89382
89594
|
|
|
89383
89595
|
// src/chats.ts
|
|
89384
|
-
import
|
|
89385
|
-
import
|
|
89596
|
+
import fs19 from "node:fs";
|
|
89597
|
+
import path23 from "node:path";
|
|
89386
89598
|
|
|
89387
89599
|
// ../cloud/src/config.ts
|
|
89388
89600
|
var CLAIM_LEASE_SECONDS = 15 * 60;
|
|
@@ -89398,18 +89610,18 @@ var CONTACT_ATTEMPT_WINDOW_SECONDS = 60 * 60;
|
|
|
89398
89610
|
var CHAT_KEEP_DAYS = 30;
|
|
89399
89611
|
|
|
89400
89612
|
// ../cli/src/lib/agent/task-chats.ts
|
|
89401
|
-
import
|
|
89402
|
-
import
|
|
89613
|
+
import fs18 from "node:fs";
|
|
89614
|
+
import path22 from "node:path";
|
|
89403
89615
|
var TASK = /^[\w-]{1,100}$/;
|
|
89404
|
-
var taskChatsDir = (home4 = machineHome()) =>
|
|
89616
|
+
var taskChatsDir = (home4 = machineHome()) => path22.join(home4, "chats");
|
|
89405
89617
|
function taskChatFile(task, home4) {
|
|
89406
89618
|
if (!TASK.test(task)) throw new Error(`${task} is not a task id.`);
|
|
89407
|
-
return
|
|
89619
|
+
return path22.join(taskChatsDir(home4), `${task}.jsonl`);
|
|
89408
89620
|
}
|
|
89409
89621
|
function readTaskChat(task, home4) {
|
|
89410
89622
|
let text3;
|
|
89411
89623
|
try {
|
|
89412
|
-
text3 =
|
|
89624
|
+
text3 = fs18.readFileSync(taskChatFile(task, home4), "utf8");
|
|
89413
89625
|
} catch {
|
|
89414
89626
|
return [];
|
|
89415
89627
|
}
|
|
@@ -89430,18 +89642,18 @@ var DAY_MS = 24 * 60 * 6e4;
|
|
|
89430
89642
|
var REVIEW_EVERY_MS = DAY_MS;
|
|
89431
89643
|
var KEEP_MS2 = CHAT_KEEP_DAYS * DAY_MS;
|
|
89432
89644
|
var home3 = () => runnerHome();
|
|
89433
|
-
var reviewedFile = () =>
|
|
89645
|
+
var reviewedFile = () => path23.join(taskChatsDir(home3()), "reviewed.json");
|
|
89434
89646
|
function readReviewed() {
|
|
89435
89647
|
try {
|
|
89436
|
-
const held4 = JSON.parse(
|
|
89648
|
+
const held4 = JSON.parse(fs19.readFileSync(reviewedFile(), "utf8"));
|
|
89437
89649
|
return { checkedAt: Number(held4.checkedAt) || 0, tasks: held4.tasks ?? {} };
|
|
89438
89650
|
} catch {
|
|
89439
89651
|
return { checkedAt: 0, tasks: {} };
|
|
89440
89652
|
}
|
|
89441
89653
|
}
|
|
89442
89654
|
function writeReviewed(reviewed) {
|
|
89443
|
-
|
|
89444
|
-
|
|
89655
|
+
fs19.mkdirSync(path23.dirname(reviewedFile()), { recursive: true });
|
|
89656
|
+
fs19.writeFileSync(reviewedFile(), `${JSON.stringify(reviewed, null, 2)}
|
|
89445
89657
|
`);
|
|
89446
89658
|
}
|
|
89447
89659
|
function keepChat(job, reply, at2 = Date.now()) {
|
|
@@ -89451,16 +89663,16 @@ function keepChat(job, reply, at2 = Date.now()) {
|
|
|
89451
89663
|
{ id: job.id, role: "agent", text: reply, at: at2, runtime: job.runtime, model: job.model ?? null }
|
|
89452
89664
|
];
|
|
89453
89665
|
const file2 = taskChatFile(job.task, home3());
|
|
89454
|
-
|
|
89455
|
-
|
|
89666
|
+
fs19.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
89667
|
+
fs19.appendFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89456
89668
|
`).join(""));
|
|
89457
89669
|
}
|
|
89458
89670
|
function keepCloudChat(task, messages) {
|
|
89459
89671
|
const file2 = taskChatFile(task, home3());
|
|
89460
|
-
if (!messages.length) return
|
|
89672
|
+
if (!messages.length) return fs19.rmSync(file2, { force: true });
|
|
89461
89673
|
const lines = messages.map((m) => ({ id: m.id, role: m.role, text: m.body, at: Date.parse(m.created_at) || Date.now() }));
|
|
89462
|
-
|
|
89463
|
-
|
|
89674
|
+
fs19.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
89675
|
+
fs19.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89464
89676
|
`).join(""));
|
|
89465
89677
|
}
|
|
89466
89678
|
async function keepDecisions(task, read2) {
|
|
@@ -89478,13 +89690,13 @@ async function keepDecisions(task, read2) {
|
|
|
89478
89690
|
const ids = new Set(comments.map((c2) => c2.id));
|
|
89479
89691
|
const lines = [...readTaskChat(task, home3()).filter((l2) => !ids.has(l2.id)), ...comments].sort((a3, b2) => a3.at - b2.at);
|
|
89480
89692
|
const file2 = taskChatFile(task, home3());
|
|
89481
|
-
|
|
89482
|
-
|
|
89693
|
+
fs19.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
89694
|
+
fs19.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89483
89695
|
`).join(""));
|
|
89484
89696
|
}
|
|
89485
89697
|
var tasksKept = () => {
|
|
89486
89698
|
try {
|
|
89487
|
-
return
|
|
89699
|
+
return fs19.readdirSync(taskChatsDir(home3())).map((n) => /^([\w-]{1,100})\.jsonl$/.exec(n)?.[1]).filter((t2) => !!t2);
|
|
89488
89700
|
} catch {
|
|
89489
89701
|
return [];
|
|
89490
89702
|
}
|
|
@@ -89495,9 +89707,9 @@ function pruneChats(now = Date.now()) {
|
|
|
89495
89707
|
const kept4 = lines.filter((l2) => now - l2.at < KEEP_MS2);
|
|
89496
89708
|
if (kept4.length === lines.length) continue;
|
|
89497
89709
|
const file2 = taskChatFile(task, home3());
|
|
89498
|
-
if (kept4.length)
|
|
89710
|
+
if (kept4.length) fs19.writeFileSync(file2, kept4.map((l2) => `${JSON.stringify(l2)}
|
|
89499
89711
|
`).join(""));
|
|
89500
|
-
else
|
|
89712
|
+
else fs19.rmSync(file2, { force: true });
|
|
89501
89713
|
}
|
|
89502
89714
|
}
|
|
89503
89715
|
var lastOf = (task) => readTaskChat(task, home3()).at(-1);
|
|
@@ -89535,28 +89747,28 @@ async function reviewChats(machineId2, runtimes, now = Date.now()) {
|
|
|
89535
89747
|
}
|
|
89536
89748
|
|
|
89537
89749
|
// src/board-watch.ts
|
|
89538
|
-
import
|
|
89539
|
-
import
|
|
89750
|
+
import fs23 from "node:fs";
|
|
89751
|
+
import path27 from "node:path";
|
|
89540
89752
|
|
|
89541
89753
|
// ../cloud/src/board-files.ts
|
|
89542
89754
|
var ROOTS = ["todo/", ".archive/", "memory/", "workflows/", "triage/", "assets/", "rules/"];
|
|
89543
89755
|
var SETTINGS = ["modules.md", "config.md"];
|
|
89544
|
-
var isSettingsPath = (
|
|
89756
|
+
var isSettingsPath = (path40) => SETTINGS.includes(path40) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path40);
|
|
89545
89757
|
var BOARD_FILE_LIMIT = 256 * 1024;
|
|
89546
|
-
function isBoardPath(
|
|
89547
|
-
if (!
|
|
89548
|
-
if (
|
|
89549
|
-
if (
|
|
89550
|
-
if (
|
|
89551
|
-
if (SETTINGS.includes(
|
|
89552
|
-
if (
|
|
89553
|
-
if (
|
|
89554
|
-
return ROOTS.some((root) =>
|
|
89758
|
+
function isBoardPath(path40) {
|
|
89759
|
+
if (!path40 || path40.length > 500 || path40.startsWith("/") || path40.includes("\\") || path40.includes("\0")) return false;
|
|
89760
|
+
if (path40.split("/").some((part) => !part || part === "." || part === "..")) return false;
|
|
89761
|
+
if (path40 === "todo/README.md" || path40.split("/").includes(".sync")) return false;
|
|
89762
|
+
if (path40.startsWith("workflows/")) return true;
|
|
89763
|
+
if (SETTINGS.includes(path40)) return true;
|
|
89764
|
+
if (path40.startsWith("rules/")) return isSettingsPath(path40);
|
|
89765
|
+
if (path40.startsWith("assets/")) return path40.endsWith(".json");
|
|
89766
|
+
return ROOTS.some((root) => path40.startsWith(root)) && path40.endsWith(".md");
|
|
89555
89767
|
}
|
|
89556
89768
|
var CARD = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]*\.md$/;
|
|
89557
89769
|
var ROOT = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]+\/root\.md$/;
|
|
89558
|
-
function numberOfCard(
|
|
89559
|
-
const n = ROOT.exec(
|
|
89770
|
+
function numberOfCard(path40) {
|
|
89771
|
+
const n = ROOT.exec(path40)?.[1] ?? CARD.exec(path40)?.[1];
|
|
89560
89772
|
return n ? Number(n) : null;
|
|
89561
89773
|
}
|
|
89562
89774
|
var cardSlug = (task) => task.toLowerCase().replace(/_/g, "-");
|
|
@@ -89764,9 +89976,9 @@ function collect(body, card, host) {
|
|
|
89764
89976
|
|
|
89765
89977
|
// src/task-folder.ts
|
|
89766
89978
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
89767
|
-
import
|
|
89768
|
-
import
|
|
89769
|
-
import
|
|
89979
|
+
import crypto4 from "node:crypto";
|
|
89980
|
+
import fs22 from "node:fs";
|
|
89981
|
+
import path26 from "node:path";
|
|
89770
89982
|
|
|
89771
89983
|
// node_modules/node-diff3/dist/diff3.mjs
|
|
89772
89984
|
function LCS(buffer1, buffer2) {
|
|
@@ -90005,8 +90217,8 @@ function unquote2(v2) {
|
|
|
90005
90217
|
|
|
90006
90218
|
// ../cloud/src/triage-files.ts
|
|
90007
90219
|
var ITEM = /^triage\/(?:(dismissed|archived)\/)?([^/]+)\.md$/;
|
|
90008
|
-
function itemAt(
|
|
90009
|
-
const m = ITEM.exec(
|
|
90220
|
+
function itemAt(path40) {
|
|
90221
|
+
const m = ITEM.exec(path40);
|
|
90010
90222
|
if (!m) return null;
|
|
90011
90223
|
return { state: m[1] === "dismissed" ? "dismissed" : m[1] === "archived" ? "carded" : "open", name: m[2] };
|
|
90012
90224
|
}
|
|
@@ -90023,11 +90235,11 @@ function stampItem(content, fields) {
|
|
|
90023
90235
|
}
|
|
90024
90236
|
|
|
90025
90237
|
// ../cli/src/lib/agents/shared-memory.ts
|
|
90026
|
-
import
|
|
90027
|
-
import
|
|
90238
|
+
import fs20 from "node:fs";
|
|
90239
|
+
import path24 from "node:path";
|
|
90028
90240
|
|
|
90029
90241
|
// ../cli/src/agents/builder/AGENT.md
|
|
90030
|
-
var AGENT_default = "---\nname: builder\ndescription:
|
|
90242
|
+
var AGENT_default = "---\nname: builder\ndescription: Implement and land approved software changes.\n---\n\n- **Autonomy**: Decide technical details within the approved scope and existing permissions. Diagnose build problems, fix them, verify the result, and continue; do not repeat the same failed attempt instead of investigating. Ask the user only for decisions or blockers only they can resolve.\n- **Approved UI previews**: Implement every screen in the approved previews, compare desktop and mobile layouts, and correct differences.\n- **Approved API previews**: Implement every approved endpoint and document it.\n- **Approved database previews**: Write migrations that match the approved structure.\n- **Completion**: Finish when changes have landed and checks pass, unless deployment or publication is the task's goal. Do not push, deploy, or publish merely to finish a task.\n- **Production steps**: Hand the user any steps or validation that require production access. Mention them only in the final response; create no follow-up tasks and ask no questions.\n- **Checks**: Nobody reviews the implementation after you. Run targeted checks for the affected paths and all checks the repository requires for the changes.\n";
|
|
90031
90243
|
|
|
90032
90244
|
// ../cli/src/agents/api-designer/AGENT.md
|
|
90033
90245
|
var AGENT_default2 = "---\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";
|
|
@@ -90602,10 +90814,10 @@ function readScalar(value) {
|
|
|
90602
90814
|
function readBlock(lines, start, parentIndent) {
|
|
90603
90815
|
if (start >= lines.length || lines[start].indent <= parentIndent) return ["", start];
|
|
90604
90816
|
const indent = lines[start].indent;
|
|
90605
|
-
if (lines[start].text.startsWith("-")) return
|
|
90817
|
+
if (lines[start].text.startsWith("-")) return readList(lines, start, indent);
|
|
90606
90818
|
return readMap(lines, start, indent);
|
|
90607
90819
|
}
|
|
90608
|
-
function
|
|
90820
|
+
function readList(lines, start, indent) {
|
|
90609
90821
|
const out = [];
|
|
90610
90822
|
let i = start;
|
|
90611
90823
|
while (i < lines.length && lines[i].indent === indent && lines[i].text.startsWith("-")) {
|
|
@@ -90757,16 +90969,16 @@ function sharedMemory(board) {
|
|
|
90757
90969
|
const at2 = /^([^/]+)\/AGENT\.md$/.exec(key);
|
|
90758
90970
|
if (at2) take(at2[1], text3, true);
|
|
90759
90971
|
}
|
|
90760
|
-
const root =
|
|
90972
|
+
const root = path24.join(board, "agents");
|
|
90761
90973
|
let folders2 = [];
|
|
90762
90974
|
try {
|
|
90763
|
-
folders2 =
|
|
90975
|
+
folders2 = fs20.readdirSync(root, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !e2.name.startsWith(".")).map((e2) => e2.name);
|
|
90764
90976
|
} catch {
|
|
90765
90977
|
}
|
|
90766
90978
|
for (const folder of folders2.sort()) {
|
|
90767
90979
|
let text3 = null;
|
|
90768
90980
|
try {
|
|
90769
|
-
text3 =
|
|
90981
|
+
text3 = fs20.readFileSync(path24.join(root, folder, "AGENT.md"), "utf8");
|
|
90770
90982
|
} catch {
|
|
90771
90983
|
}
|
|
90772
90984
|
take(folder, text3, false);
|
|
@@ -90790,16 +91002,16 @@ function openTaskFolder(job, projectDir2) {
|
|
|
90790
91002
|
projectDir2 ??= openCached(job.project);
|
|
90791
91003
|
keepOutOfGit(projectDir2);
|
|
90792
91004
|
markUsed(projectDir2);
|
|
90793
|
-
const board =
|
|
90794
|
-
|
|
91005
|
+
const board = path26.join(projectDir2, ".akb", "kanban");
|
|
91006
|
+
fs22.mkdirSync(board, { recursive: true });
|
|
90795
91007
|
return { task, cloudTask: task, board, cwd: projectDir2, project: job.project, number: job.number ?? null, workflow: job.workflow ?? job.flow?.workflow ?? null };
|
|
90796
91008
|
}
|
|
90797
91009
|
function openAgentFolder(job, projectDir2) {
|
|
90798
91010
|
if (!job.project || !job.agent) throw new Error("This job names no project.");
|
|
90799
91011
|
keepOutOfGit(projectDir2);
|
|
90800
91012
|
markUsed(projectDir2);
|
|
90801
|
-
const board =
|
|
90802
|
-
|
|
91013
|
+
const board = path26.join(projectDir2, ".akb", "kanban");
|
|
91014
|
+
fs22.mkdirSync(board, { recursive: true });
|
|
90803
91015
|
return {
|
|
90804
91016
|
task: `agent-${safe(job.agent.workflow ? `${job.agent.workflow}-${job.agent.name}` : job.agent.name)}`,
|
|
90805
91017
|
cloudTask: job.agent.tasks?.[0]?.id ?? null,
|
|
@@ -90814,13 +91026,13 @@ function openDiscussionFolder(job, projectDir2) {
|
|
|
90814
91026
|
if (!job.project) throw new Error("This job names no project.");
|
|
90815
91027
|
keepOutOfGit(projectDir2);
|
|
90816
91028
|
markUsed(projectDir2);
|
|
90817
|
-
const board =
|
|
90818
|
-
|
|
91029
|
+
const board = path26.join(projectDir2, ".akb", "kanban");
|
|
91030
|
+
fs22.mkdirSync(board, { recursive: true });
|
|
90819
91031
|
return { task: "discussion", cloudTask: null, board, cwd: projectDir2, project: job.project, number: null, workflow: null };
|
|
90820
91032
|
}
|
|
90821
91033
|
var boardFolder = (ws) => ({ task: "board", cloudTask: null, board: ws.board, cwd: ws.cwd, project: ws.project, number: null, workflow: null });
|
|
90822
91034
|
function keptBoard(cwd) {
|
|
90823
|
-
const board =
|
|
91035
|
+
const board = path26.join(cwd, ".akb", "kanban");
|
|
90824
91036
|
const base = readBase({ cwd });
|
|
90825
91037
|
const project = base.project ?? /^projects\/([^/]+)\//.exec(Object.keys(base.files).find((p2) => p2.startsWith("projects/")) ?? "")?.[1];
|
|
90826
91038
|
return base.head_seq === null || !project ? null : boardFolder({ board, cwd, project });
|
|
@@ -90837,8 +91049,8 @@ function inFolder(dir, work) {
|
|
|
90837
91049
|
var safe = (name) => name.replace(/[^\w.-]/g, "_") || "default";
|
|
90838
91050
|
function openCached(project) {
|
|
90839
91051
|
const dir = cacheDir(project);
|
|
90840
|
-
if (
|
|
90841
|
-
|
|
91052
|
+
if (fs22.existsSync(path26.join(dir, ".git"))) return dir;
|
|
91053
|
+
fs22.mkdirSync(dir, { recursive: true });
|
|
90842
91054
|
const git4 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" }).status === 0;
|
|
90843
91055
|
if (git4("init", "-q")) git4("-c", "user.name=WildCrane", "-c", "user.email=runner@wildcrane.ai", "commit", "-q", "--allow-empty", "-m", "general");
|
|
90844
91056
|
return dir;
|
|
@@ -90851,56 +91063,56 @@ function keepOutOfGit(dir, folders2 = SKILL_FOLDERS) {
|
|
|
90851
91063
|
if (inside.status !== 0) return;
|
|
90852
91064
|
const missing = [".akb/", ...folders2.map((f2) => `${f2}/`)].filter((p2) => git4("check-ignore", "-q", p2).status !== 0);
|
|
90853
91065
|
if (!missing.length) return;
|
|
90854
|
-
const exclude =
|
|
90855
|
-
|
|
90856
|
-
const held4 =
|
|
90857
|
-
|
|
91066
|
+
const exclude = path26.resolve(dir, inside.stdout.trim());
|
|
91067
|
+
fs22.mkdirSync(path26.dirname(exclude), { recursive: true });
|
|
91068
|
+
const held4 = fs22.existsSync(exclude) ? fs22.readFileSync(exclude, "utf8") : "";
|
|
91069
|
+
fs22.writeFileSync(exclude, `${held4}${held4 && !held4.endsWith("\n") ? "\n" : ""}${missing.join("\n")}
|
|
90858
91070
|
`);
|
|
90859
91071
|
}
|
|
90860
|
-
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ??
|
|
91072
|
+
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ?? path26.join(ws.board, "todo", `${ws.number ?? 0}-task.md`);
|
|
90861
91073
|
function findCard(board, number) {
|
|
90862
91074
|
const named2 = new RegExp(`^${number}-`);
|
|
90863
91075
|
const walk = (dir) => {
|
|
90864
91076
|
let entries;
|
|
90865
91077
|
try {
|
|
90866
|
-
entries =
|
|
91078
|
+
entries = fs22.readdirSync(dir, { withFileTypes: true });
|
|
90867
91079
|
} catch {
|
|
90868
91080
|
return null;
|
|
90869
91081
|
}
|
|
90870
91082
|
for (const e2 of entries) {
|
|
90871
91083
|
if (!named2.test(e2.name)) continue;
|
|
90872
|
-
if (e2.isFile() && e2.name.endsWith(".md")) return
|
|
90873
|
-
const root =
|
|
90874
|
-
if (e2.isDirectory() &&
|
|
91084
|
+
if (e2.isFile() && e2.name.endsWith(".md")) return path26.join(dir, e2.name);
|
|
91085
|
+
const root = path26.join(dir, e2.name, "root.md");
|
|
91086
|
+
if (e2.isDirectory() && fs22.existsSync(root)) return root;
|
|
90875
91087
|
}
|
|
90876
91088
|
for (const e2 of entries) if (e2.isDirectory() && !e2.name.startsWith(".")) {
|
|
90877
|
-
const hit = walk(
|
|
91089
|
+
const hit = walk(path26.join(dir, e2.name));
|
|
90878
91090
|
if (hit) return hit;
|
|
90879
91091
|
}
|
|
90880
91092
|
return null;
|
|
90881
91093
|
};
|
|
90882
|
-
return walk(
|
|
91094
|
+
return walk(path26.join(board, "todo")) ?? walk(path26.join(board, ".archive"));
|
|
90883
91095
|
}
|
|
90884
91096
|
function akbCardOf(ws) {
|
|
90885
91097
|
return ws.number && findCard(ws.board, ws.number) ? ws.number : void 0;
|
|
90886
91098
|
}
|
|
90887
|
-
var recordFile = (ws) =>
|
|
91099
|
+
var recordFile = (ws) => path26.join(ws.board, ".sync", `${ws.task}.json`);
|
|
90888
91100
|
function readRecord(ws) {
|
|
90889
91101
|
try {
|
|
90890
|
-
return { ...EMPTY, ...JSON.parse(
|
|
91102
|
+
return { ...EMPTY, ...JSON.parse(fs22.readFileSync(recordFile(ws), "utf8")) };
|
|
90891
91103
|
} catch {
|
|
90892
91104
|
return structuredClone(EMPTY);
|
|
90893
91105
|
}
|
|
90894
91106
|
}
|
|
90895
91107
|
function writeRecord(ws, record) {
|
|
90896
|
-
|
|
90897
|
-
|
|
91108
|
+
fs22.mkdirSync(path26.dirname(recordFile(ws)), { recursive: true });
|
|
91109
|
+
fs22.writeFileSync(recordFile(ws), `${JSON.stringify(record, null, 2)}
|
|
90898
91110
|
`);
|
|
90899
91111
|
}
|
|
90900
|
-
var baseFile = (ws) =>
|
|
91112
|
+
var baseFile = (ws) => path26.join(ws.cwd, ".akb", "base.json");
|
|
90901
91113
|
function readBase(ws) {
|
|
90902
91114
|
try {
|
|
90903
|
-
const base = JSON.parse(
|
|
91115
|
+
const base = JSON.parse(fs22.readFileSync(baseFile(ws), "utf8"));
|
|
90904
91116
|
if (base.layout === "workspace") return base;
|
|
90905
91117
|
} catch {
|
|
90906
91118
|
}
|
|
@@ -90908,25 +91120,25 @@ function readBase(ws) {
|
|
|
90908
91120
|
}
|
|
90909
91121
|
function writeBase(ws, base) {
|
|
90910
91122
|
const file2 = baseFile(ws);
|
|
90911
|
-
|
|
90912
|
-
|
|
90913
|
-
|
|
91123
|
+
fs22.mkdirSync(path26.dirname(file2), { recursive: true });
|
|
91124
|
+
fs22.writeFileSync(`${file2}.tmp`, JSON.stringify(base));
|
|
91125
|
+
fs22.renameSync(`${file2}.tmp`, file2);
|
|
90914
91126
|
}
|
|
90915
|
-
var hashOf = (bytes2) =>
|
|
91127
|
+
var hashOf = (bytes2) => crypto4.createHash("sha256").update(bytes2).digest("hex");
|
|
90916
91128
|
function hashFile(file2) {
|
|
90917
91129
|
try {
|
|
90918
|
-
return hashOf(
|
|
91130
|
+
return hashOf(fs22.readFileSync(file2));
|
|
90919
91131
|
} catch {
|
|
90920
91132
|
return null;
|
|
90921
91133
|
}
|
|
90922
91134
|
}
|
|
90923
91135
|
function write(file2, bytes2) {
|
|
90924
|
-
|
|
90925
|
-
|
|
91136
|
+
fs22.mkdirSync(path26.dirname(file2), { recursive: true });
|
|
91137
|
+
fs22.writeFileSync(file2, bytes2);
|
|
90926
91138
|
}
|
|
90927
91139
|
function readText(file2) {
|
|
90928
91140
|
try {
|
|
90929
|
-
return
|
|
91141
|
+
return fs22.readFileSync(file2, "utf8");
|
|
90930
91142
|
} catch {
|
|
90931
91143
|
return null;
|
|
90932
91144
|
}
|
|
@@ -90934,14 +91146,14 @@ function readText(file2) {
|
|
|
90934
91146
|
function filesUnder(dir, base = dir) {
|
|
90935
91147
|
let entries;
|
|
90936
91148
|
try {
|
|
90937
|
-
entries =
|
|
91149
|
+
entries = fs22.readdirSync(dir, { withFileTypes: true });
|
|
90938
91150
|
} catch {
|
|
90939
91151
|
return [];
|
|
90940
91152
|
}
|
|
90941
91153
|
return entries.flatMap((e2) => {
|
|
90942
|
-
const full =
|
|
91154
|
+
const full = path26.join(dir, e2.name);
|
|
90943
91155
|
if (e2.isDirectory()) return filesUnder(full, base);
|
|
90944
|
-
return e2.isFile() ? [
|
|
91156
|
+
return e2.isFile() ? [path26.relative(base, full).split(path26.sep).join("/")] : [];
|
|
90945
91157
|
});
|
|
90946
91158
|
}
|
|
90947
91159
|
var kept3 = isBoardPath;
|
|
@@ -90957,18 +91169,18 @@ function viewOf(ws, base, shared) {
|
|
|
90957
91169
|
}
|
|
90958
91170
|
function assetFiles(ws, list) {
|
|
90959
91171
|
const card = cardFile(ws);
|
|
90960
|
-
return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) =>
|
|
91172
|
+
return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) => path26.relative(ws.board, f2).split(path26.sep).join("/")));
|
|
90961
91173
|
}
|
|
90962
91174
|
var assetsListOf = (ws, base) => base.files[rootOf(ws) + assetsFile(ws.task)]?.content;
|
|
90963
91175
|
var localFiles = (ws, base) => {
|
|
90964
|
-
const assets = /* @__PURE__ */ new Set([...assetFiles(ws, assetsListOf(ws, base)), ...assetFiles(ws, readText(
|
|
91176
|
+
const assets = /* @__PURE__ */ new Set([...assetFiles(ws, assetsListOf(ws, base)), ...assetFiles(ws, readText(path26.join(ws.board, assetsFile(ws.task))))]);
|
|
90965
91177
|
return filesUnder(ws.board).filter((p2) => kept3(p2) && !assets.has(p2));
|
|
90966
91178
|
};
|
|
90967
91179
|
var SKILL_PATH = /^skills\/([a-z0-9]+(?:-[a-z0-9]+)*)\/((?:[\w.-]+\/)*[\w.-]+)$/;
|
|
90968
91180
|
function pullTools(ws, record, files) {
|
|
90969
91181
|
const held4 = record.tools?.skills ?? {};
|
|
90970
91182
|
const ours = new Set(Object.keys(held4).map((name) => name.split("/")[1]));
|
|
90971
|
-
const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) =>
|
|
91183
|
+
const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) => fs22.existsSync(path26.join(ws.cwd, root, skill)));
|
|
90972
91184
|
const kept4 = Object.keys(files).map((name) => SKILL_PATH.exec(name)?.[1]).filter((skill) => skill && !theirs(skill));
|
|
90973
91185
|
const skills = {};
|
|
90974
91186
|
for (const [name, text3] of Object.entries(files)) {
|
|
@@ -90976,7 +91188,7 @@ function pullTools(ws, record, files) {
|
|
|
90976
91188
|
if (!at2 || at2[1] === "kanban" || !kept4.includes(at2[1]) || at2[2].split("/").includes("..")) continue;
|
|
90977
91189
|
skills[name] = hashOf(text3);
|
|
90978
91190
|
for (const root of SKILL_ROOTS) {
|
|
90979
|
-
const file2 =
|
|
91191
|
+
const file2 = path26.join(ws.cwd, root, at2[1], at2[2]);
|
|
90980
91192
|
if (held4[name] !== skills[name] || hashFile(file2) !== skills[name]) write(file2, text3);
|
|
90981
91193
|
}
|
|
90982
91194
|
}
|
|
@@ -90985,8 +91197,8 @@ function pullTools(ws, record, files) {
|
|
|
90985
91197
|
const [, skill, rest] = SKILL_PATH.exec(name) ?? [];
|
|
90986
91198
|
if (!skill || !rest) continue;
|
|
90987
91199
|
for (const root of SKILL_ROOTS) {
|
|
90988
|
-
|
|
90989
|
-
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`)))
|
|
91200
|
+
fs22.rmSync(path26.join(ws.cwd, root, skill, rest), { force: true });
|
|
91201
|
+
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`))) fs22.rmSync(path26.join(ws.cwd, root, skill), { recursive: true, force: true });
|
|
90990
91202
|
}
|
|
90991
91203
|
}
|
|
90992
91204
|
const names2 = [...new Set(Object.keys(skills).map((name) => name.split("/")[1]))];
|
|
@@ -91014,7 +91226,7 @@ async function pullWorkflow(ws, record, base) {
|
|
|
91014
91226
|
files = read2.value.files;
|
|
91015
91227
|
found = true;
|
|
91016
91228
|
if (!record.builtin) {
|
|
91017
|
-
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(
|
|
91229
|
+
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(path26.join(ws.board, root, name), text3);
|
|
91018
91230
|
}
|
|
91019
91231
|
}
|
|
91020
91232
|
}
|
|
@@ -91022,14 +91234,14 @@ async function pullWorkflow(ws, record, base) {
|
|
|
91022
91234
|
}
|
|
91023
91235
|
pullAgents(ws, base, ws.workflow && !record.builtin ? files : {});
|
|
91024
91236
|
const placed = readPlaced(ws);
|
|
91025
|
-
for (const name of Object.keys(record.agents ?? {})) if (!placed[name])
|
|
91237
|
+
for (const name of Object.keys(record.agents ?? {})) if (!placed[name]) fs22.rmSync(path26.join(ws.board, name), { force: true });
|
|
91026
91238
|
record.agents = {};
|
|
91027
91239
|
return { ok: true, value: void 0 };
|
|
91028
91240
|
}
|
|
91029
|
-
var agentsRecord = (ws) =>
|
|
91241
|
+
var agentsRecord = (ws) => path26.join(ws.board, ".sync", "agents.json");
|
|
91030
91242
|
function readPlaced(ws) {
|
|
91031
91243
|
try {
|
|
91032
|
-
return JSON.parse(
|
|
91244
|
+
return JSON.parse(fs22.readFileSync(agentsRecord(ws), "utf8"));
|
|
91033
91245
|
} catch {
|
|
91034
91246
|
return {};
|
|
91035
91247
|
}
|
|
@@ -91050,8 +91262,8 @@ function pullAgents(ws, base, own) {
|
|
|
91050
91262
|
const names2 = /* @__PURE__ */ new Set();
|
|
91051
91263
|
for (const [name, text3] of Object.entries(files)) {
|
|
91052
91264
|
const agent = /^agents\/([^/]+)\//.exec(name)?.[1];
|
|
91053
|
-
const file2 =
|
|
91054
|
-
if (!agent || taken.has(agent) || !file2.startsWith(
|
|
91265
|
+
const file2 = path26.resolve(ws.board, name);
|
|
91266
|
+
if (!agent || taken.has(agent) || !file2.startsWith(path26.join(ws.board, "agents") + path26.sep)) continue;
|
|
91055
91267
|
names2.add(agent);
|
|
91056
91268
|
agents[name] = text3;
|
|
91057
91269
|
}
|
|
@@ -91061,51 +91273,51 @@ function pullAgents(ws, base, own) {
|
|
|
91061
91273
|
const hashes = {};
|
|
91062
91274
|
for (const [name, text3] of Object.entries(agents)) {
|
|
91063
91275
|
hashes[name] = hashOf(text3);
|
|
91064
|
-
if (hashFile(
|
|
91276
|
+
if (hashFile(path26.join(ws.board, name)) !== hashes[name]) write(path26.join(ws.board, name), text3);
|
|
91065
91277
|
}
|
|
91066
|
-
for (const name of Object.keys(before)) if (!hashes[name])
|
|
91278
|
+
for (const name of Object.keys(before)) if (!hashes[name]) fs22.rmSync(path26.join(ws.board, name), { force: true });
|
|
91067
91279
|
write(agentsRecord(ws), `${JSON.stringify(hashes, null, 2)}
|
|
91068
91280
|
`);
|
|
91069
91281
|
}
|
|
91070
91282
|
function pullDraftAgents(ws, record) {
|
|
91071
91283
|
if (ws.workflow !== BUILDER) return;
|
|
91072
|
-
const root =
|
|
91284
|
+
const root = path26.join(ws.board, "workflows", draftFolder(ws.task), "agents");
|
|
91073
91285
|
record.agents ??= {};
|
|
91074
91286
|
for (const name of filesUnder(root)) {
|
|
91075
|
-
const text3 =
|
|
91287
|
+
const text3 = fs22.readFileSync(path26.join(root, name));
|
|
91076
91288
|
const at2 = `agents/${name}`;
|
|
91077
91289
|
record.agents[at2] = hashOf(text3);
|
|
91078
|
-
if (hashFile(
|
|
91290
|
+
if (hashFile(path26.join(ws.board, at2)) !== record.agents[at2]) write(path26.join(ws.board, at2), text3);
|
|
91079
91291
|
}
|
|
91080
91292
|
}
|
|
91081
91293
|
function workflowFile(ws) {
|
|
91082
91294
|
if (!ws.workflow || readRecord(ws).builtin) return null;
|
|
91083
|
-
const file2 =
|
|
91084
|
-
return
|
|
91295
|
+
const file2 = path26.join(ws.board, "workflows", workflowFolder(ws.workflow), "WORKFLOW.md");
|
|
91296
|
+
return fs22.existsSync(file2) ? file2 : null;
|
|
91085
91297
|
}
|
|
91086
91298
|
function assetPath(ws, name, owner) {
|
|
91087
91299
|
if (/^[a-z][\w+.-]*:/i.test(name) || name.startsWith("#") || name.startsWith("//")) return null;
|
|
91088
|
-
if (
|
|
91300
|
+
if (path26.isAbsolute(name)) throw new Error("\u8D44\u6E90\u8DEF\u5F84\u4E0D\u80FD\u662F\u7EDD\u5BF9\u8DEF\u5F84");
|
|
91089
91301
|
const held4 = /^\.(assets|mockups)\//.exec(name);
|
|
91090
91302
|
const state = stateDir(ws);
|
|
91091
|
-
const root = held4 && state ?
|
|
91092
|
-
const file2 = held4 && state ?
|
|
91093
|
-
const roots = [ws.board, ...state ? ["assets", "mockups"].map((folder) =>
|
|
91094
|
-
const inside = (file3, root2) => file3.startsWith(root2 +
|
|
91303
|
+
const root = held4 && state ? path26.join(state, held4[1]) : ws.board;
|
|
91304
|
+
const file2 = held4 && state ? path26.resolve(root, name.slice(held4[0].length)) : path26.resolve(path26.dirname(owner), name);
|
|
91305
|
+
const roots = [ws.board, ...state ? ["assets", "mockups"].map((folder) => path26.join(state, folder, ...ws.number ? [String(ws.number)] : [])) : []];
|
|
91306
|
+
const inside = (file3, root2) => file3.startsWith(root2 + path26.sep);
|
|
91095
91307
|
if (!roots.some((root2) => inside(file2, root2))) throw new Error("\u8D44\u6E90\u8DEF\u5F84\u8D8A\u754C");
|
|
91096
91308
|
let existing = file2;
|
|
91097
|
-
while (!
|
|
91098
|
-
const real =
|
|
91309
|
+
while (!fs22.existsSync(existing) && path26.dirname(existing) !== existing) existing = path26.dirname(existing);
|
|
91310
|
+
const real = fs22.realpathSync(existing);
|
|
91099
91311
|
let stateParent = state;
|
|
91100
|
-
while (stateParent && !
|
|
91101
|
-
const realState = state && stateParent ?
|
|
91102
|
-
const realRoots = [
|
|
91312
|
+
while (stateParent && !fs22.existsSync(stateParent) && path26.dirname(stateParent) !== stateParent) stateParent = path26.dirname(stateParent);
|
|
91313
|
+
const realState = state && stateParent ? path26.resolve(fs22.realpathSync(stateParent), path26.relative(stateParent, state)) : null;
|
|
91314
|
+
const realRoots = [fs22.realpathSync(ws.board), ...realState ? ["assets", "mockups"].map((folder) => path26.join(realState, folder, ...ws.number ? [String(ws.number)] : [])) : []];
|
|
91103
91315
|
if (!realRoots.some((root2) => real === root2 || inside(real, root2))) throw new Error("\u7B26\u53F7\u94FE\u63A5\u8D8A\u754C");
|
|
91104
91316
|
return file2;
|
|
91105
91317
|
}
|
|
91106
91318
|
function cardAssetsDir(ws, id) {
|
|
91107
91319
|
const state = stateDir(ws);
|
|
91108
|
-
return state &&
|
|
91320
|
+
return state && path26.join(state, "assets", String(id));
|
|
91109
91321
|
}
|
|
91110
91322
|
function stateDir(ws) {
|
|
91111
91323
|
try {
|
|
@@ -91144,13 +91356,13 @@ var pullChanges = (ws) => inFolder(ws.cwd, async () => {
|
|
|
91144
91356
|
const p2 = f2.path.startsWith(root) ? f2.path.slice(root.length) : f2.path;
|
|
91145
91357
|
const isShared = p2.startsWith(MEMORY2) && shared(p2.slice(MEMORY2.length));
|
|
91146
91358
|
if (kept3(p2) && isShared === !f2.path.startsWith(root)) {
|
|
91147
|
-
const file2 =
|
|
91359
|
+
const file2 = path26.join(ws.board, p2);
|
|
91148
91360
|
const here = readText(file2);
|
|
91149
91361
|
if (here !== f2.content && here !== (base.files[f2.path]?.content ?? null)) {
|
|
91150
91362
|
skipped = true;
|
|
91151
91363
|
continue;
|
|
91152
91364
|
}
|
|
91153
|
-
if (f2.content === null)
|
|
91365
|
+
if (f2.content === null) fs22.rmSync(file2, { force: true });
|
|
91154
91366
|
else if (here !== f2.content) write(file2, f2.content);
|
|
91155
91367
|
}
|
|
91156
91368
|
if (f2.content === null) delete base.files[f2.path];
|
|
@@ -91181,13 +91393,13 @@ async function readCloud(ws) {
|
|
|
91181
91393
|
writeBase(ws, base);
|
|
91182
91394
|
const reset = (view2) => {
|
|
91183
91395
|
for (const [p2, content] of view2) {
|
|
91184
|
-
const file2 =
|
|
91396
|
+
const file2 = path26.join(ws.board, p2);
|
|
91185
91397
|
if (kept3(p2) && readText(file2) !== content) write(file2, content);
|
|
91186
91398
|
}
|
|
91187
91399
|
};
|
|
91188
91400
|
const view = viewOf(ws, base, sharedMemory(ws.board));
|
|
91189
91401
|
const first = (p2) => isSettingsPath(p2) && !known2.has(rootOf(ws) + p2);
|
|
91190
|
-
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2))
|
|
91402
|
+
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2)) fs22.rmSync(path26.join(ws.board, p2), { force: true });
|
|
91191
91403
|
reset(view);
|
|
91192
91404
|
const record = readRecord(ws);
|
|
91193
91405
|
const workflow = await pullWorkflow(ws, record, base);
|
|
@@ -91201,18 +91413,18 @@ async function readCloud(ws) {
|
|
|
91201
91413
|
return { ok: true, value: void 0 };
|
|
91202
91414
|
}
|
|
91203
91415
|
function writeIndex(board) {
|
|
91204
|
-
const todo =
|
|
91416
|
+
const todo = path26.join(board, "todo");
|
|
91205
91417
|
const cards = [];
|
|
91206
91418
|
let entries = [];
|
|
91207
91419
|
try {
|
|
91208
|
-
entries =
|
|
91420
|
+
entries = fs22.readdirSync(todo, { withFileTypes: true });
|
|
91209
91421
|
} catch {
|
|
91210
91422
|
}
|
|
91211
91423
|
for (const e2 of entries) {
|
|
91212
91424
|
const id = /^(\d+)-/.exec(e2.name)?.[1];
|
|
91213
91425
|
if (!id) continue;
|
|
91214
91426
|
const link = e2.isDirectory() ? `${e2.name}/root.md` : e2.name.endsWith(".md") ? e2.name : null;
|
|
91215
|
-
const text4 = link && readText(
|
|
91427
|
+
const text4 = link && readText(path26.join(todo, link));
|
|
91216
91428
|
if (text4 === null || !link) continue;
|
|
91217
91429
|
cards.push({ id: Number(id), title: cardFront(text4).title ?? e2.name.replace(/\.md$/, ""), link });
|
|
91218
91430
|
}
|
|
@@ -91227,7 +91439,7 @@ the number at the front of a filename is the task id.
|
|
|
91227
91439
|
|
|
91228
91440
|
${list}
|
|
91229
91441
|
`;
|
|
91230
|
-
if (readText(
|
|
91442
|
+
if (readText(path26.join(todo, "README.md")) !== text3) write(path26.join(todo, "README.md"), text3);
|
|
91231
91443
|
}
|
|
91232
91444
|
var workspaceOf = (ws) => readBase(ws).workspace ?? null;
|
|
91233
91445
|
async function pullAssets(ws, record, assets) {
|
|
@@ -91235,51 +91447,74 @@ async function pullAssets(ws, record, assets) {
|
|
|
91235
91447
|
record.task = ws.cloudTask;
|
|
91236
91448
|
record.number = ws.number;
|
|
91237
91449
|
}
|
|
91238
|
-
const isCompare = (value) => !!value && typeof value === "object" && "a" in value && "b" in value;
|
|
91239
91450
|
const file2 = cardFile(ws);
|
|
91240
91451
|
const out = {};
|
|
91241
91452
|
for (const [name, ref] of Object.entries(assets)) {
|
|
91242
91453
|
const target = assetPath(ws, name, file2);
|
|
91243
91454
|
if (!target) continue;
|
|
91455
|
+
const held4 = record.assets[name];
|
|
91456
|
+
let kind = held4?.artifact === ref.artifact ? held4.kind : void 0;
|
|
91244
91457
|
let version = ref.version;
|
|
91245
|
-
|
|
91458
|
+
const localHash = hashFile(target);
|
|
91459
|
+
const current = held4?.artifact === ref.artifact && held4.version === version && localHash === (held4.localHash ?? held4.hash);
|
|
91460
|
+
if (version === void 0 || !kind || !current && kind !== "html") {
|
|
91246
91461
|
const latest = await readArtifact(ref.artifact);
|
|
91247
91462
|
if (!latest.ok) return latest;
|
|
91248
|
-
version
|
|
91463
|
+
version ??= latest.value.latest_version ?? 0;
|
|
91464
|
+
kind = latest.value.type;
|
|
91465
|
+
if (!kind) return { ok: false, code: "bad_request", error: `${name}: \u8D44\u6E90\u7C7B\u578B\u7F3A\u5931` };
|
|
91249
91466
|
}
|
|
91250
|
-
|
|
91251
|
-
|
|
91252
|
-
out[name] = { ...held4, version };
|
|
91467
|
+
if (kind === "html" && held4?.artifact === ref.artifact) {
|
|
91468
|
+
out[name] = { ...held4, kind, version };
|
|
91253
91469
|
continue;
|
|
91254
91470
|
}
|
|
91255
|
-
if (held4?.artifact === ref.artifact && held4.version === version &&
|
|
91256
|
-
out[name] = held4;
|
|
91471
|
+
if (held4?.artifact === ref.artifact && held4.version === version && current) {
|
|
91472
|
+
out[name] = { ...held4, kind };
|
|
91257
91473
|
continue;
|
|
91258
91474
|
}
|
|
91259
91475
|
const bytes2 = await readAsset(ref.artifact, version);
|
|
91260
91476
|
if (!bytes2.ok) return bytes2;
|
|
91261
91477
|
let local = bytes2.value;
|
|
91262
|
-
let kind = held4?.kind;
|
|
91263
91478
|
const dependencies = [];
|
|
91264
|
-
if (
|
|
91479
|
+
if (kind === "storyboard" || kind === "compare") {
|
|
91480
|
+
let data;
|
|
91265
91481
|
try {
|
|
91266
|
-
|
|
91482
|
+
data = JSON.parse(Buffer.from(local).toString());
|
|
91483
|
+
} catch {
|
|
91484
|
+
}
|
|
91485
|
+
if (data !== void 0) {
|
|
91486
|
+
let changed = false;
|
|
91267
91487
|
const restore = (src) => {
|
|
91268
91488
|
const name2 = Object.entries(assets).find(([, r2]) => r2.artifact === src)?.[0];
|
|
91269
|
-
if (name2) dependencies.push(name2);
|
|
91270
91489
|
if (!name2) return src;
|
|
91271
|
-
if (/^\.(assets|mockups)\//.test(name2)) return name2;
|
|
91272
91490
|
const child = assetPath(ws, name2, file2);
|
|
91273
|
-
|
|
91491
|
+
if (!child) return src;
|
|
91492
|
+
dependencies.push(name2);
|
|
91493
|
+
const restored2 = /^\.(assets|mockups)\//.test(name2) ? name2 : path26.relative(path26.dirname(target), child).split(path26.sep).join("/");
|
|
91494
|
+
if (restored2 !== src) changed = true;
|
|
91495
|
+
return restored2;
|
|
91274
91496
|
};
|
|
91275
|
-
const restored = mapReferences(
|
|
91276
|
-
if (
|
|
91277
|
-
|
|
91278
|
-
|
|
91497
|
+
const restored = mapReferences(data, kind, restore);
|
|
91498
|
+
if (changed) local = Buffer.from(JSON.stringify(restored));
|
|
91499
|
+
}
|
|
91500
|
+
}
|
|
91501
|
+
if (held4?.artifact === ref.artifact && held4.version === version && !held4.localHash && (kind === "storyboard" || kind === "compare")) {
|
|
91502
|
+
const source = readText(target);
|
|
91503
|
+
if (source !== null) {
|
|
91504
|
+
let same = false;
|
|
91505
|
+
try {
|
|
91506
|
+
same = JSON.stringify(JSON.parse(source)) === JSON.stringify(JSON.parse(Buffer.from(local).toString()));
|
|
91507
|
+
} catch {
|
|
91508
|
+
}
|
|
91509
|
+
if (!same) {
|
|
91510
|
+
out[name] = { ...held4, kind };
|
|
91511
|
+
continue;
|
|
91512
|
+
}
|
|
91513
|
+
local = Buffer.from(source);
|
|
91279
91514
|
}
|
|
91280
91515
|
}
|
|
91281
91516
|
write(target, local);
|
|
91282
|
-
out[name] = { ...held4, kind, dependencies:
|
|
91517
|
+
out[name] = { ...held4, kind, dependencies: [...new Set(dependencies)], artifact: ref.artifact, version, hash: hashOf(bytes2.value), localHash: hashOf(local) };
|
|
91283
91518
|
}
|
|
91284
91519
|
record.assets = out;
|
|
91285
91520
|
return { ok: true, value: void 0 };
|
|
@@ -91292,14 +91527,14 @@ async function readAsset(artifact, version) {
|
|
|
91292
91527
|
return { ok: true, value: Buffer.from(typeof content === "string" ? content : JSON.stringify(content)) };
|
|
91293
91528
|
}
|
|
91294
91529
|
async function sentOf(file2) {
|
|
91295
|
-
const ext =
|
|
91530
|
+
const ext = path26.extname(file2).toLowerCase();
|
|
91296
91531
|
const kind = kindOf(ext);
|
|
91297
|
-
if (kind !== "html") return { bytes:
|
|
91532
|
+
if (kind !== "html") return { bytes: fs22.readFileSync(file2), type: TYPES[ext] ?? "application/octet-stream", kind };
|
|
91298
91533
|
let page;
|
|
91299
91534
|
try {
|
|
91300
91535
|
page = await (await Promise.resolve().then(() => (init_mockup(), mockup_exports))).drawMockup(file2);
|
|
91301
91536
|
} catch (e2) {
|
|
91302
|
-
console.error(`runner: ${
|
|
91537
|
+
console.error(`runner: ${path26.basename(file2)} could not be drawn: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
91303
91538
|
page = UNDRAWN;
|
|
91304
91539
|
}
|
|
91305
91540
|
return { bytes: Buffer.from(page), type: "text/html", kind };
|
|
@@ -91324,14 +91559,14 @@ async function pushAssets(ws, record, before) {
|
|
|
91324
91559
|
if (body === null) return { ok: true, value: void 0 };
|
|
91325
91560
|
const refs = {};
|
|
91326
91561
|
const canonical = (target) => {
|
|
91327
|
-
const real = (file3) =>
|
|
91562
|
+
const real = (file3) => fs22.existsSync(file3) ? fs22.realpathSync(file3) : file3;
|
|
91328
91563
|
target = real(target);
|
|
91329
91564
|
const state = stateDir(ws);
|
|
91330
91565
|
for (const folder of ["assets", "mockups"]) {
|
|
91331
|
-
const root = state && real(
|
|
91332
|
-
if (root && target.startsWith(root +
|
|
91566
|
+
const root = state && real(path26.join(state, folder));
|
|
91567
|
+
if (root && target.startsWith(root + path26.sep)) return `.${folder}/${path26.relative(root, target).split(path26.sep).join("/")}`;
|
|
91333
91568
|
}
|
|
91334
|
-
return
|
|
91569
|
+
return path26.relative(real(path26.dirname(file2)), target).split(path26.sep).join("/");
|
|
91335
91570
|
};
|
|
91336
91571
|
try {
|
|
91337
91572
|
const graph = collect(body, file2, {
|
|
@@ -91341,13 +91576,13 @@ async function pushAssets(ws, record, before) {
|
|
|
91341
91576
|
const target = assetPath(ws, src, owner);
|
|
91342
91577
|
if (!target) return null;
|
|
91343
91578
|
const key = owner === file2 && before[src] ? src : canonical(target);
|
|
91344
|
-
if (!
|
|
91579
|
+
if (!fs22.statSync(target, { throwIfNoEntry: false })?.isFile()) {
|
|
91345
91580
|
if (before[key]) return { key, file: null };
|
|
91346
91581
|
throw new Error("\u660E\u786E\u5F15\u7528\u7684\u8D44\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
91347
91582
|
}
|
|
91348
|
-
return { key: canonical(
|
|
91583
|
+
return { key: canonical(fs22.realpathSync(target)), file: target };
|
|
91349
91584
|
},
|
|
91350
|
-
readJSON: (target) => JSON.parse(
|
|
91585
|
+
readJSON: (target) => JSON.parse(fs22.readFileSync(target, "utf8")),
|
|
91351
91586
|
retained: (key) => (record.assets[key]?.dependencies ?? []).map((src) => {
|
|
91352
91587
|
const kind = record.assets[src]?.kind;
|
|
91353
91588
|
return { src, purpose: kind === "storyboard" || kind === "compare" ? kind : "asset" };
|
|
@@ -91368,6 +91603,13 @@ async function pushAssets(ws, record, before) {
|
|
|
91368
91603
|
}
|
|
91369
91604
|
continue;
|
|
91370
91605
|
}
|
|
91606
|
+
const kind = node.kind === "asset" ? kindOf(path26.extname(node.file).toLowerCase()) : node.kind;
|
|
91607
|
+
if (previous && previous.kind !== kind) {
|
|
91608
|
+
const artifact = await readArtifact(previous.artifact);
|
|
91609
|
+
if (!artifact.ok) return artifact;
|
|
91610
|
+
if (!artifact.value.type) return { ok: false, code: "bad_request", error: `${node.key}: \u8D44\u6E90\u7C7B\u578B\u7F3A\u5931` };
|
|
91611
|
+
previous.kind = artifact.value.type;
|
|
91612
|
+
}
|
|
91371
91613
|
let out = await sentOf(node.file);
|
|
91372
91614
|
if (node.kind !== "asset") {
|
|
91373
91615
|
const data = mapReferences(node.data, node.kind, (src) => {
|
|
@@ -91378,9 +91620,12 @@ async function pushAssets(ws, record, before) {
|
|
|
91378
91620
|
}
|
|
91379
91621
|
const hash = hashOf(out.bytes);
|
|
91380
91622
|
let entry = previous;
|
|
91381
|
-
|
|
91623
|
+
const localHash = hashFile(node.file);
|
|
91624
|
+
const restored = node.kind !== "asset" || out.kind === "html" && previous?.hash === localHash;
|
|
91625
|
+
const unchanged = restored && previous && (previous.kind ?? out.kind) === out.kind && localHash === (previous.localHash ?? previous.hash) && [...node.dependencies.values()].every((key) => refs[key]?.artifact === before[key]?.artifact);
|
|
91626
|
+
if (!entry || !unchanged && entry.hash !== hash || entry.kind && entry.kind !== out.kind) {
|
|
91382
91627
|
if (!ws.cloudTask) continue;
|
|
91383
|
-
let artifact = previous && (previous.kind ?? kindOf(
|
|
91628
|
+
let artifact = previous && (previous.kind ?? kindOf(path26.extname(node.file).toLowerCase())) === out.kind ? previous.artifact : void 0;
|
|
91384
91629
|
if (!artifact) {
|
|
91385
91630
|
const made = await createArtifact(ws.cloudTask, node.key.slice(0, 200), out.kind);
|
|
91386
91631
|
if (!made.ok) return { ...made, error: `${node.key}: ${made.error}` };
|
|
@@ -91390,7 +91635,7 @@ async function pushAssets(ws, record, before) {
|
|
|
91390
91635
|
if (!sent.ok) return { ...sent, error: `${node.key}: ${sent.error}` };
|
|
91391
91636
|
entry = { artifact, version: sent.value, hash, kind: out.kind };
|
|
91392
91637
|
}
|
|
91393
|
-
entry = { ...entry, localHash:
|
|
91638
|
+
entry = { ...entry, localHash: localHash ?? void 0, dependencies: [...node.dependencies.values()] };
|
|
91394
91639
|
for (const alias of node.aliases) {
|
|
91395
91640
|
record.assets[alias] = entry;
|
|
91396
91641
|
refs[alias] = { artifact: entry.artifact, version: entry.version };
|
|
@@ -91400,24 +91645,24 @@ async function pushAssets(ws, record, before) {
|
|
|
91400
91645
|
} catch (error) {
|
|
91401
91646
|
return { ok: false, code: "bad_request", error: error instanceof Error ? error.message : String(error) };
|
|
91402
91647
|
}
|
|
91403
|
-
const list =
|
|
91404
|
-
if (Object.keys(refs).length ||
|
|
91648
|
+
const list = path26.join(ws.board, assetsFile(ws.task));
|
|
91649
|
+
if (Object.keys(refs).length || fs22.existsSync(list)) {
|
|
91405
91650
|
if (JSON.stringify(assetsOf(readText(list))) !== JSON.stringify(refs)) write(list, assetsText(refs));
|
|
91406
91651
|
}
|
|
91407
91652
|
return { ok: true, value: void 0 };
|
|
91408
91653
|
}
|
|
91409
91654
|
function resetSorted(ws) {
|
|
91410
|
-
for (const sub of ["dismissed", "archived"])
|
|
91655
|
+
for (const sub of ["dismissed", "archived"]) fs22.rmSync(path26.join(ws.board, "triage", sub), { recursive: true, force: true });
|
|
91411
91656
|
for (const [p2, content] of viewOf(ws, readBase(ws), sharedMemory(ws.board))) {
|
|
91412
|
-
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(
|
|
91657
|
+
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(path26.join(ws.board, p2), content);
|
|
91413
91658
|
}
|
|
91414
91659
|
}
|
|
91415
91660
|
function proposeItems(ws, base) {
|
|
91416
91661
|
const root = rootOf(ws);
|
|
91417
91662
|
for (const p2 of localFiles(ws, base)) {
|
|
91418
91663
|
if (itemAt(p2)?.state !== "open" || base.files[root + p2]) continue;
|
|
91419
|
-
const file2 =
|
|
91420
|
-
const content =
|
|
91664
|
+
const file2 = path26.join(ws.board, p2);
|
|
91665
|
+
const content = fs22.readFileSync(file2, "utf8");
|
|
91421
91666
|
const said = (key) => new RegExp(`^${key}:`, "m").test(content.split(/\n---/)[0] ?? "");
|
|
91422
91667
|
const fields = {
|
|
91423
91668
|
...ws.cloudTask && !said("source_task") ? { source_task: ws.cloudTask } : {},
|
|
@@ -91457,9 +91702,9 @@ async function send2(ws, job) {
|
|
|
91457
91702
|
const record = readRecord(ws);
|
|
91458
91703
|
const base = readBase(ws);
|
|
91459
91704
|
const fail = (error, conflict = false, code) => ({ ok: false, conflict, error, ...code ? {} : { offline: true } });
|
|
91460
|
-
const tasks = ws.cloudTask ? [{ folder: ws, record }] : filesUnder(
|
|
91705
|
+
const tasks = ws.cloudTask ? [{ folder: ws, record }] : filesUnder(path26.join(ws.board, ".sync")).filter((name) => name.endsWith(".json")).flatMap((name) => {
|
|
91461
91706
|
try {
|
|
91462
|
-
const held4 = JSON.parse(
|
|
91707
|
+
const held4 = JSON.parse(fs22.readFileSync(path26.join(ws.board, ".sync", name), "utf8"));
|
|
91463
91708
|
if (!held4.task || !TASK_ID.test(held4.task) || !held4.number) return [];
|
|
91464
91709
|
return [{ folder: { ...ws, task: held4.task, cloudTask: held4.task, number: held4.number }, record: held4 }];
|
|
91465
91710
|
} catch {
|
|
@@ -91479,7 +91724,7 @@ async function send2(ws, job) {
|
|
|
91479
91724
|
const owed = (p2) => !job.id && busy(ws.cwd) && itemAt(p2)?.state === "open" && !base.files[rootOf(ws) + p2];
|
|
91480
91725
|
for (const p2 of local) {
|
|
91481
91726
|
if (owed(p2)) continue;
|
|
91482
|
-
const content =
|
|
91727
|
+
const content = fs22.readFileSync(path26.join(ws.board, p2), "utf8");
|
|
91483
91728
|
const remote = remoteOf(ws, shared, p2);
|
|
91484
91729
|
localOf.set(remote, p2);
|
|
91485
91730
|
const held4 = base.files[remote];
|
|
@@ -91511,15 +91756,15 @@ async function send2(ws, job) {
|
|
|
91511
91756
|
changes.splice(at2, 1);
|
|
91512
91757
|
delete base.files[theirs.path];
|
|
91513
91758
|
writeBase(ws, base);
|
|
91514
|
-
|
|
91759
|
+
fs22.rmSync(path26.join(ws.board, p2), { force: true });
|
|
91515
91760
|
writeIndex(ws.board);
|
|
91516
91761
|
continue;
|
|
91517
91762
|
}
|
|
91518
91763
|
if (at2 < 0) continue;
|
|
91519
91764
|
const merged = itemAt(p2) ? { content: theirs.content } : mergeFile(base.files[theirs.path]?.content ?? null, changes[at2].content, theirs.content);
|
|
91520
91765
|
changes[at2] = { path: theirs.path, content: merged.content, base_seq: theirs.seq };
|
|
91521
|
-
if (merged.content === null)
|
|
91522
|
-
else write(
|
|
91766
|
+
if (merged.content === null) fs22.rmSync(path26.join(ws.board, p2), { force: true });
|
|
91767
|
+
else write(path26.join(ws.board, p2), merged.content);
|
|
91523
91768
|
}
|
|
91524
91769
|
if (!changes.length) return { ok: true, changed: false };
|
|
91525
91770
|
sent = await commitBoard(ws.project, job.id, job.machineId, changes);
|
|
@@ -91541,7 +91786,7 @@ var BUSY_MS = 3e4;
|
|
|
91541
91786
|
function keptFolders() {
|
|
91542
91787
|
let cached2 = [];
|
|
91543
91788
|
try {
|
|
91544
|
-
cached2 =
|
|
91789
|
+
cached2 = fs23.readdirSync(cacheRoot()).map((name) => path27.join(cacheRoot(), name));
|
|
91545
91790
|
} catch {
|
|
91546
91791
|
}
|
|
91547
91792
|
return [.../* @__PURE__ */ new Set([...allowedProjects(), ...cached2])].flatMap((dir) => [keptBoard(dir)].filter((ws) => !!ws));
|
|
@@ -91577,8 +91822,8 @@ function watchBoards(machineId2, ms, lookMs = LOOK_MS, pullMs = PULL_MS, busyMs
|
|
|
91577
91822
|
const watch = (ws) => {
|
|
91578
91823
|
let watcher;
|
|
91579
91824
|
try {
|
|
91580
|
-
watcher =
|
|
91581
|
-
const p2 = name && String(name).split(
|
|
91825
|
+
watcher = fs23.watch(ws.board, { recursive: true }, (_event, name) => {
|
|
91826
|
+
const p2 = name && String(name).split(path27.sep).join("/");
|
|
91582
91827
|
const held4 = watched.get(ws.cwd);
|
|
91583
91828
|
if (closed || !p2 || !isBoardPath(p2) || !held4) return;
|
|
91584
91829
|
const job = busy(ws.cwd);
|
|
@@ -91641,8 +91886,8 @@ function watchBoards(machineId2, ms, lookMs = LOOK_MS, pullMs = PULL_MS, busyMs
|
|
|
91641
91886
|
|
|
91642
91887
|
// src/diff.ts
|
|
91643
91888
|
import { execFile as execFile2 } from "node:child_process";
|
|
91644
|
-
import
|
|
91645
|
-
import
|
|
91889
|
+
import fs24 from "node:fs";
|
|
91890
|
+
import path28 from "node:path";
|
|
91646
91891
|
var FILE_BYTES = 256 * 1024;
|
|
91647
91892
|
var TOTAL_BYTES = 1024 * 1024;
|
|
91648
91893
|
var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
@@ -91659,7 +91904,7 @@ var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
|
|
|
91659
91904
|
function projectDir(placed, project) {
|
|
91660
91905
|
if (placed) {
|
|
91661
91906
|
const real = realpath3(placed);
|
|
91662
|
-
return real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
91907
|
+
return real && allowedProjects().some((root) => real === root || real.startsWith(root + path28.sep)) ? real : null;
|
|
91663
91908
|
}
|
|
91664
91909
|
let cached2;
|
|
91665
91910
|
try {
|
|
@@ -91667,11 +91912,11 @@ function projectDir(placed, project) {
|
|
|
91667
91912
|
} catch {
|
|
91668
91913
|
return null;
|
|
91669
91914
|
}
|
|
91670
|
-
return
|
|
91915
|
+
return fs24.existsSync(path28.join(cached2, ".git")) ? cached2 : null;
|
|
91671
91916
|
}
|
|
91672
91917
|
function realpath3(p2) {
|
|
91673
91918
|
try {
|
|
91674
|
-
return
|
|
91919
|
+
return fs24.realpathSync(p2);
|
|
91675
91920
|
} catch {
|
|
91676
91921
|
return null;
|
|
91677
91922
|
}
|
|
@@ -91717,18 +91962,21 @@ async function answerHint(machineId2, hint2) {
|
|
|
91717
91962
|
|
|
91718
91963
|
// ../cli/src/lib/agent/stop.ts
|
|
91719
91964
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
91720
|
-
import
|
|
91965
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
91966
|
+
import fs25 from "node:fs";
|
|
91721
91967
|
var runMark = (sessionId) => ({ name: RUN_ENV, value: sessionId });
|
|
91968
|
+
var stopMark = () => ({ name: STOP_ENV, value: randomUUID2() });
|
|
91969
|
+
var markEnv = (env2, mark) => ({ ...env2, [mark.name]: mark.value });
|
|
91722
91970
|
var WINDOWS3 = process.platform === "win32";
|
|
91723
91971
|
function markedInProc(entry, strict = false) {
|
|
91724
91972
|
const pids = [];
|
|
91725
|
-
for (const name of
|
|
91973
|
+
for (const name of fs25.readdirSync("/proc")) {
|
|
91726
91974
|
if (!/^\d+$/.test(name)) continue;
|
|
91727
91975
|
try {
|
|
91728
|
-
if (
|
|
91976
|
+
if (fs25.readFileSync(`/proc/${name}/environ`, "utf8").split("\0").includes(entry)) pids.push(Number(name));
|
|
91729
91977
|
} catch (error) {
|
|
91730
91978
|
if (strict && !["ENOENT", "ESRCH"].includes(error.code ?? "")) {
|
|
91731
|
-
const stat =
|
|
91979
|
+
const stat = fs25.statSync(`/proc/${name}`, { throwIfNoEntry: false });
|
|
91732
91980
|
if (stat?.uid === process.getuid?.()) throw error;
|
|
91733
91981
|
}
|
|
91734
91982
|
}
|
|
@@ -91761,6 +92009,24 @@ function markedInPs(entry, roots) {
|
|
|
91761
92009
|
}
|
|
91762
92010
|
return [...found];
|
|
91763
92011
|
}
|
|
92012
|
+
function marked(mark, roots = []) {
|
|
92013
|
+
if (WINDOWS3 || !mark.value) return [];
|
|
92014
|
+
const entry = `${mark.name}=${mark.value}`;
|
|
92015
|
+
try {
|
|
92016
|
+
const pids = process.platform === "linux" ? markedInProc(entry) : markedInPs(entry, roots);
|
|
92017
|
+
return pids.filter((pid) => pid !== process.pid);
|
|
92018
|
+
} catch {
|
|
92019
|
+
return [];
|
|
92020
|
+
}
|
|
92021
|
+
}
|
|
92022
|
+
function signal(pids, sig) {
|
|
92023
|
+
for (const pid of pids) {
|
|
92024
|
+
try {
|
|
92025
|
+
process.kill(pid, sig);
|
|
92026
|
+
} catch {
|
|
92027
|
+
}
|
|
92028
|
+
}
|
|
92029
|
+
}
|
|
91764
92030
|
function startedUnder(list, root, since) {
|
|
91765
92031
|
const self2 = list.procs.find((p2) => p2.pid === root);
|
|
91766
92032
|
const from = since ?? self2?.startedAt;
|
|
@@ -91804,6 +92070,21 @@ function procsOnWindows() {
|
|
|
91804
92070
|
});
|
|
91805
92071
|
return ps.status === 0 && ps.stdout ? readProcList(ps.stdout) : void 0;
|
|
91806
92072
|
}
|
|
92073
|
+
function killUnderOnWindows(pid, since) {
|
|
92074
|
+
if (!WINDOWS3 || !pid) return;
|
|
92075
|
+
const list = procsOnWindows();
|
|
92076
|
+
if (!list) return;
|
|
92077
|
+
const pids = startedUnder(list, pid, since).filter((p2) => p2 !== process.pid);
|
|
92078
|
+
if (!pids.length) return;
|
|
92079
|
+
spawnSync5("taskkill", ["/F", ...pids.flatMap((p2) => ["/PID", String(p2)])], { stdio: "ignore", windowsHide: true, timeout: 1e4 });
|
|
92080
|
+
}
|
|
92081
|
+
function killMarked(mark, agent) {
|
|
92082
|
+
if (WINDOWS3) {
|
|
92083
|
+
if (agent) killUnderOnWindows(agent.pid, agent.since);
|
|
92084
|
+
return;
|
|
92085
|
+
}
|
|
92086
|
+
signal(marked(mark), "SIGKILL");
|
|
92087
|
+
}
|
|
91807
92088
|
function processesStopped(mark, root) {
|
|
91808
92089
|
try {
|
|
91809
92090
|
if (WINDOWS3) {
|
|
@@ -91821,8 +92102,8 @@ function processesStopped(mark, root) {
|
|
|
91821
92102
|
}
|
|
91822
92103
|
|
|
91823
92104
|
// src/flow.ts
|
|
91824
|
-
import
|
|
91825
|
-
import
|
|
92105
|
+
import fs30 from "node:fs";
|
|
92106
|
+
import path33 from "node:path";
|
|
91826
92107
|
|
|
91827
92108
|
// ../cli/src/lib/question-block.ts
|
|
91828
92109
|
var MODES = ["single", "multi"];
|
|
@@ -91980,13 +92261,13 @@ function reviewOf(meta) {
|
|
|
91980
92261
|
}
|
|
91981
92262
|
|
|
91982
92263
|
// src/triage.ts
|
|
91983
|
-
import
|
|
91984
|
-
import
|
|
92264
|
+
import fs26 from "node:fs";
|
|
92265
|
+
import path29 from "node:path";
|
|
91985
92266
|
|
|
91986
92267
|
// ../cli/src/lib/signals/identity.ts
|
|
91987
|
-
import { createHash } from "node:crypto";
|
|
92268
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
91988
92269
|
var DERIVED = "derived-";
|
|
91989
|
-
var derivedSourceId = (seed) => `${DERIVED}${
|
|
92270
|
+
var derivedSourceId = (seed) => `${DERIVED}${createHash2("sha256").update(seed).digest("hex").slice(0, 16)}`;
|
|
91990
92271
|
|
|
91991
92272
|
// ../cli/src/lib/slug.ts
|
|
91992
92273
|
function slugify(s) {
|
|
@@ -91995,8 +92276,8 @@ function slugify(s) {
|
|
|
91995
92276
|
}
|
|
91996
92277
|
|
|
91997
92278
|
// src/triage.ts
|
|
91998
|
-
var triageDir = (board) =>
|
|
91999
|
-
var rejectedDir = (board) =>
|
|
92279
|
+
var triageDir = (board) => path29.join(board, "triage");
|
|
92280
|
+
var rejectedDir = (board) => path29.join(board, ".archive", REJECTIONS_TO_REVIEW);
|
|
92000
92281
|
var SCRATCH = ["dismissed", "archived"];
|
|
92001
92282
|
var stamp = (at2) => formatStamp(at2 ? new Date(at2) : /* @__PURE__ */ new Date());
|
|
92002
92283
|
function slugOf(title) {
|
|
@@ -92005,7 +92286,7 @@ function slugOf(title) {
|
|
|
92005
92286
|
function freeName(dir, title) {
|
|
92006
92287
|
const stem = slugOf(title);
|
|
92007
92288
|
let name = `${stem}.md`;
|
|
92008
|
-
for (let n = 2;
|
|
92289
|
+
for (let n = 2; fs26.existsSync(path29.join(dir, name)); n++) name = `${stem}-${n}.md`;
|
|
92009
92290
|
return name;
|
|
92010
92291
|
}
|
|
92011
92292
|
function itemText(item, fields = {}) {
|
|
@@ -92025,17 +92306,17 @@ ${item.text.trim()}
|
|
|
92025
92306
|
`;
|
|
92026
92307
|
}
|
|
92027
92308
|
function writeItem(dir, item, fields = {}) {
|
|
92028
|
-
|
|
92309
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
92029
92310
|
const name = freeName(dir, item.title);
|
|
92030
|
-
|
|
92311
|
+
fs26.writeFileSync(path29.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
|
|
92031
92312
|
return name;
|
|
92032
92313
|
}
|
|
92033
92314
|
function layOut(board, rejections) {
|
|
92034
92315
|
clearLaid(board);
|
|
92035
92316
|
const dir = rejectedDir(board);
|
|
92036
|
-
|
|
92317
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
92037
92318
|
for (const t2 of rejections.tasks) {
|
|
92038
|
-
|
|
92319
|
+
fs26.writeFileSync(path29.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
|
|
92039
92320
|
"---",
|
|
92040
92321
|
`title: ${yamlScalar(t2.title)}`,
|
|
92041
92322
|
"status: todo",
|
|
@@ -92050,20 +92331,20 @@ function layOut(board, rejections) {
|
|
|
92050
92331
|
].join("\n"));
|
|
92051
92332
|
}
|
|
92052
92333
|
for (const item of rejections.triage) {
|
|
92053
|
-
const sub =
|
|
92334
|
+
const sub = path29.join(triageDir(board), item.state === "dismissed" ? "dismissed" : "archived");
|
|
92054
92335
|
const fields = item.state === "dismissed" ? { dismissed_at: stamp(item.dismissed_at), dismissed_by: "user", ...item.dismissed_reason ? { dismissed_reason: item.dismissed_reason } : {} } : {};
|
|
92055
92336
|
writeItem(sub, item, fields);
|
|
92056
92337
|
}
|
|
92057
92338
|
return { tasks: rejections.tasks.map((t2) => t2.id), triage: rejections.triage.map((i) => i.id) };
|
|
92058
92339
|
}
|
|
92059
92340
|
function clearLaid(board) {
|
|
92060
|
-
|
|
92061
|
-
for (const sub of SCRATCH)
|
|
92341
|
+
fs26.rmSync(rejectedDir(board), { recursive: true, force: true });
|
|
92342
|
+
for (const sub of SCRATCH) fs26.rmSync(path29.join(triageDir(board), sub), { recursive: true, force: true });
|
|
92062
92343
|
}
|
|
92063
92344
|
|
|
92064
92345
|
// src/kanban-skill.ts
|
|
92065
|
-
import
|
|
92066
|
-
import
|
|
92346
|
+
import fs27 from "node:fs";
|
|
92347
|
+
import path30 from "node:path";
|
|
92067
92348
|
|
|
92068
92349
|
// ../skill/SKILL.md
|
|
92069
92350
|
var SKILL_default = '---\nname: kanban\ndescription: Manage the file-based task board with akb. Use for creating and planning tasks, revising or implementing cards, and managing background runs; also for "what\'s running".\n---\n\n# Kanban board\n\nThe board is worked only through `akb`. Find the command for the job in `akb help` and run\nit; never do its work by hand or from memory.\n\n- **`--print` does it here**: `akb card revise 12 --print "drop the export"` prints the whole\n flow for that card on this board; follow it to its closing steps. Without `--print` the\n same command starts a separate agent.\n- **Keys**: never read or write API keys; the user sets them with `akb agent set apiKey`.\n';
|
|
@@ -92076,24 +92357,24 @@ var CONTENT = `${SKILL_default.trimEnd()}
|
|
|
92076
92357
|
var MANAGED = /^<!-- ai4kanban \S+ -->$/m;
|
|
92077
92358
|
function prepareKanbanSkill(root) {
|
|
92078
92359
|
for (const folder of SKILL_FOLDERS) {
|
|
92079
|
-
const dir =
|
|
92080
|
-
const file2 =
|
|
92360
|
+
const dir = path30.join(root, folder);
|
|
92361
|
+
const file2 = path30.join(dir, "SKILL.md");
|
|
92081
92362
|
try {
|
|
92082
92363
|
let linked = false;
|
|
92083
92364
|
let at2 = root;
|
|
92084
92365
|
for (const name of `${folder}/SKILL.md`.split("/")) {
|
|
92085
|
-
at2 =
|
|
92086
|
-
if (
|
|
92366
|
+
at2 = path30.join(at2, name);
|
|
92367
|
+
if (fs27.lstatSync(at2, { throwIfNoEntry: false })?.isSymbolicLink()) linked = true;
|
|
92087
92368
|
}
|
|
92088
|
-
const held4 =
|
|
92089
|
-
const exists =
|
|
92369
|
+
const held4 = fs27.existsSync(file2) ? fs27.readFileSync(file2, "utf8") : null;
|
|
92370
|
+
const exists = fs27.lstatSync(dir, { throwIfNoEntry: false }) !== void 0;
|
|
92090
92371
|
if (linked || exists && !MANAGED.test(held4 ?? "")) {
|
|
92091
92372
|
if (!held4?.trim()) throw new Error("\u7528\u6237\u81EA\u6709\u76EE\u5F55\u6216\u7B26\u53F7\u94FE\u63A5\u4E2D\u7F3A\u5C11\u53EF\u8BFB\u7684 SKILL.md");
|
|
92092
92373
|
continue;
|
|
92093
92374
|
}
|
|
92094
92375
|
if (held4 !== CONTENT) {
|
|
92095
|
-
|
|
92096
|
-
|
|
92376
|
+
fs27.mkdirSync(dir, { recursive: true });
|
|
92377
|
+
fs27.writeFileSync(file2, CONTENT);
|
|
92097
92378
|
}
|
|
92098
92379
|
} catch (e2) {
|
|
92099
92380
|
throw new Error(`\u65E0\u6CD5\u51C6\u5907 ${folder}\uFF1A${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -92103,8 +92384,8 @@ function prepareKanbanSkill(root) {
|
|
|
92103
92384
|
|
|
92104
92385
|
// ../cli/src/lib/skill/hook.ts
|
|
92105
92386
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
92106
|
-
import
|
|
92107
|
-
import
|
|
92387
|
+
import fs28 from "node:fs";
|
|
92388
|
+
import path31 from "node:path";
|
|
92108
92389
|
|
|
92109
92390
|
// ../cli/src/lib/agent/landing-lock.ts
|
|
92110
92391
|
var landingLimits = { staleMs: 5 * 6e4 };
|
|
@@ -92131,7 +92412,7 @@ var CHECK = [
|
|
|
92131
92412
|
"}catch(e){process.exit(0)}"
|
|
92132
92413
|
].join("");
|
|
92133
92414
|
var quoted = (p2) => `"${p2.replace(/(["$`\\])/g, "\\$1")}"`;
|
|
92134
|
-
var guardLine = (sessions) => `if command -v node >/dev/null 2>&1; then node -e '${CHECK}' ${quoted(sessions)} ${quoted(
|
|
92415
|
+
var guardLine = (sessions) => `if command -v node >/dev/null 2>&1; then node -e '${CHECK}' ${quoted(sessions)} ${quoted(path31.join(path31.dirname(sessions), SESSIONS_FOLDER, ".landing.lock"))} || exit 1; fi`;
|
|
92135
92416
|
function hookScript(sessions) {
|
|
92136
92417
|
return [
|
|
92137
92418
|
"#!/bin/sh",
|
|
@@ -92147,7 +92428,7 @@ function hookScript(sessions) {
|
|
|
92147
92428
|
}
|
|
92148
92429
|
var read = (file2) => {
|
|
92149
92430
|
try {
|
|
92150
|
-
return
|
|
92431
|
+
return fs28.readFileSync(file2, "utf8");
|
|
92151
92432
|
} catch {
|
|
92152
92433
|
return null;
|
|
92153
92434
|
}
|
|
@@ -92159,7 +92440,7 @@ function hooksDir(root) {
|
|
|
92159
92440
|
windowsHide: true
|
|
92160
92441
|
});
|
|
92161
92442
|
if (out.error || out.status !== 0 || !out.stdout.trim()) return null;
|
|
92162
|
-
return
|
|
92443
|
+
return path31.resolve(root, out.stdout.trim());
|
|
92163
92444
|
}
|
|
92164
92445
|
function hasOwnHooksPath(root) {
|
|
92165
92446
|
const out = spawnSync6("git", ["config", "--get", "core.hooksPath"], {
|
|
@@ -92169,21 +92450,21 @@ function hasOwnHooksPath(root) {
|
|
|
92169
92450
|
});
|
|
92170
92451
|
return !out.error && out.status === 0 && !!out.stdout.trim();
|
|
92171
92452
|
}
|
|
92172
|
-
var sessionsPath = (root, board) =>
|
|
92173
|
-
function readCommitHook(root, board =
|
|
92453
|
+
var sessionsPath = (root, board) => path31.join(projectStateDir(board, root), SESSIONS_FILE);
|
|
92454
|
+
function readCommitHook(root, board = path31.join(root, "docs", "kanban")) {
|
|
92174
92455
|
const dir = hooksDir(root);
|
|
92175
92456
|
if (!dir) return { state: "no-git" };
|
|
92176
|
-
const where = shown(root,
|
|
92457
|
+
const where = shown(root, path31.join(dir, "pre-commit"));
|
|
92177
92458
|
const line = guardLine(sessionsPath(root, board));
|
|
92178
92459
|
if (hasOwnHooksPath(root)) return { state: "hooks-path", path: where, line };
|
|
92179
|
-
const file2 =
|
|
92180
|
-
if (
|
|
92460
|
+
const file2 = path31.join(dir, "pre-commit");
|
|
92461
|
+
if (fs28.lstatSync(file2, { throwIfNoEntry: false })?.isSymbolicLink()) return { state: "foreign", path: where, line };
|
|
92181
92462
|
const text3 = read(file2);
|
|
92182
92463
|
if (text3 === null) return { state: "absent", path: where };
|
|
92183
92464
|
return MARKER_LINE.test(text3) ? { state: "ours", path: where } : { state: "foreign", path: where, line };
|
|
92184
92465
|
}
|
|
92185
|
-
var shown = (root, p2) => (
|
|
92186
|
-
function installCommitHook(root, board =
|
|
92466
|
+
var shown = (root, p2) => (path31.relative(root, p2) || p2).split(path31.sep).join("/");
|
|
92467
|
+
function installCommitHook(root, board = path31.join(root, "docs", "kanban")) {
|
|
92187
92468
|
try {
|
|
92188
92469
|
return placeCommitHook(root, board);
|
|
92189
92470
|
} catch (e2) {
|
|
@@ -92200,12 +92481,12 @@ function placeCommitHook(root, board) {
|
|
|
92200
92481
|
${hook.line}`
|
|
92201
92482
|
};
|
|
92202
92483
|
}
|
|
92203
|
-
const file2 =
|
|
92484
|
+
const file2 = path31.join(root, hook.path);
|
|
92204
92485
|
try {
|
|
92205
|
-
|
|
92486
|
+
fs28.mkdirSync(path31.dirname(file2), { recursive: true });
|
|
92206
92487
|
const text3 = hookScript(sessionsPath(root, board));
|
|
92207
|
-
if (read(file2) !== text3)
|
|
92208
|
-
|
|
92488
|
+
if (read(file2) !== text3) fs28.writeFileSync(file2, text3, { mode: 493 });
|
|
92489
|
+
fs28.chmodSync(file2, 493);
|
|
92209
92490
|
} catch (e2) {
|
|
92210
92491
|
return { note: `${hook.path} could not be written \u2014 ${e2 instanceof Error ? e2.message : String(e2)}` };
|
|
92211
92492
|
}
|
|
@@ -92213,8 +92494,8 @@ ${hook.line}`
|
|
|
92213
92494
|
}
|
|
92214
92495
|
|
|
92215
92496
|
// src/built.ts
|
|
92216
|
-
import
|
|
92217
|
-
import
|
|
92497
|
+
import fs29 from "node:fs";
|
|
92498
|
+
import path32 from "node:path";
|
|
92218
92499
|
|
|
92219
92500
|
// ../cli/src/lib/spec-agent-names.ts
|
|
92220
92501
|
var LEGACY_SPEC_AGENT_NAMES = {
|
|
@@ -92390,12 +92671,12 @@ function checkWorkflowFiles(value, official = false) {
|
|
|
92390
92671
|
|
|
92391
92672
|
// src/built.ts
|
|
92392
92673
|
var isBuilder = (ws) => ws.workflow === BUILDER;
|
|
92393
|
-
var draftDir = (ws) =>
|
|
92394
|
-
var draftLine = (ws) => `<!-- workflow folder: ${
|
|
92674
|
+
var draftDir = (ws) => path32.join(ws.board, "workflows", draftFolder(ws.task));
|
|
92675
|
+
var draftLine = (ws) => `<!-- workflow folder: ${path32.relative(ws.cwd, draftDir(ws)).split(path32.sep).join("/")}/ -->`;
|
|
92395
92676
|
var skeleton = (name) => ["---", `name: ${/\s#/.test(name) ? JSON.stringify(name) : yamlScalar(name)}`, "needsArtifact: false", "---", ""].join("\n");
|
|
92396
92677
|
async function placeDraft(ws, read2) {
|
|
92397
92678
|
const dir = draftDir(ws);
|
|
92398
|
-
if (
|
|
92679
|
+
if (fs29.existsSync(path32.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
|
|
92399
92680
|
const task = await read2.readTask(ws.task);
|
|
92400
92681
|
if (!task.ok) return task;
|
|
92401
92682
|
let files = { [WORKFLOW_FILE]: skeleton(task.value.title.trim() || "Untitled") };
|
|
@@ -92406,10 +92687,10 @@ async function placeDraft(ws, read2) {
|
|
|
92406
92687
|
files = held4.value.files;
|
|
92407
92688
|
}
|
|
92408
92689
|
for (const [name, text3] of Object.entries(files)) {
|
|
92409
|
-
const file2 =
|
|
92410
|
-
if (!file2.startsWith(dir +
|
|
92411
|
-
|
|
92412
|
-
|
|
92690
|
+
const file2 = path32.resolve(dir, name);
|
|
92691
|
+
if (!file2.startsWith(dir + path32.sep)) continue;
|
|
92692
|
+
fs29.mkdirSync(path32.dirname(file2), { recursive: true });
|
|
92693
|
+
fs29.writeFileSync(file2, text3);
|
|
92413
92694
|
}
|
|
92414
92695
|
return { ok: true, value: void 0 };
|
|
92415
92696
|
}
|
|
@@ -92421,19 +92702,19 @@ async function builtWorkflow(ws, akb) {
|
|
|
92421
92702
|
const dir = draftDir(ws);
|
|
92422
92703
|
let source;
|
|
92423
92704
|
try {
|
|
92424
|
-
source =
|
|
92705
|
+
source = fs29.readFileSync(path32.join(dir, WORKFLOW_FILE), "utf8");
|
|
92425
92706
|
} catch {
|
|
92426
92707
|
return fail(`workflows/${id}/${WORKFLOW_FILE} is missing.`);
|
|
92427
92708
|
}
|
|
92428
92709
|
const read2 = parseWorkflowFile(id, source, `workflows/${id}/${WORKFLOW_FILE}`);
|
|
92429
92710
|
if ("problem" in read2) return fail(read2.problem);
|
|
92430
92711
|
const names2 = named(read2.def);
|
|
92431
|
-
|
|
92712
|
+
fs29.rmSync(path32.join(dir, "agents"), { recursive: true, force: true });
|
|
92432
92713
|
for (const name of names2) {
|
|
92433
|
-
const from =
|
|
92434
|
-
if (
|
|
92714
|
+
const from = path32.join(ws.board, "agents", name);
|
|
92715
|
+
if (fs29.existsSync(from)) fs29.cpSync(from, path32.join(dir, "agents", name), { recursive: true });
|
|
92435
92716
|
}
|
|
92436
|
-
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2,
|
|
92717
|
+
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs29.readFileSync(path32.join(dir, f2), "utf8")]));
|
|
92437
92718
|
const checked = checkWorkflowFiles(files);
|
|
92438
92719
|
if (!checked.ok) return fail(`${checked.file} ${checked.reason}.`);
|
|
92439
92720
|
const run2 = async (args) => answerOf2(await runAkb(akb, [...args, "--json", "--board", ws.board], { cwd: ws.cwd, board: ws.board }));
|
|
@@ -92468,7 +92749,7 @@ function spentBy(runs) {
|
|
|
92468
92749
|
}
|
|
92469
92750
|
function reviewOf2(file2) {
|
|
92470
92751
|
try {
|
|
92471
|
-
const meta = parseFrontmatter(
|
|
92752
|
+
const meta = parseFrontmatter(fs30.readFileSync(file2, "utf8")).meta;
|
|
92472
92753
|
return meta ? reviewOf(meta) : null;
|
|
92473
92754
|
} catch {
|
|
92474
92755
|
return null;
|
|
@@ -92476,8 +92757,8 @@ function reviewOf2(file2) {
|
|
|
92476
92757
|
}
|
|
92477
92758
|
function mcpConfig(servers, file2) {
|
|
92478
92759
|
if (!Object.keys(servers).length) return null;
|
|
92479
|
-
|
|
92480
|
-
|
|
92760
|
+
fs30.mkdirSync(path33.dirname(file2), { recursive: true });
|
|
92761
|
+
fs30.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
|
|
92481
92762
|
`);
|
|
92482
92763
|
return file2;
|
|
92483
92764
|
}
|
|
@@ -92516,7 +92797,7 @@ function deliveryEnding(ws, id) {
|
|
|
92516
92797
|
if (!id) return null;
|
|
92517
92798
|
let held4;
|
|
92518
92799
|
try {
|
|
92519
|
-
held4 = JSON.parse(
|
|
92800
|
+
held4 = JSON.parse(fs30.readFileSync(path33.join(ws.board, "deliveries", `${path33.basename(id)}.json`), "utf8"));
|
|
92520
92801
|
} catch {
|
|
92521
92802
|
return null;
|
|
92522
92803
|
}
|
|
@@ -92528,16 +92809,16 @@ function deliveryEnding(ws, id) {
|
|
|
92528
92809
|
return null;
|
|
92529
92810
|
}
|
|
92530
92811
|
function checkoutsOf(ws, id) {
|
|
92531
|
-
const dir =
|
|
92812
|
+
const dir = path33.join(ws.board, "deliveries");
|
|
92532
92813
|
let names2;
|
|
92533
92814
|
try {
|
|
92534
|
-
names2 =
|
|
92815
|
+
names2 = fs30.readdirSync(dir).filter((n) => n.endsWith(".json"));
|
|
92535
92816
|
} catch {
|
|
92536
92817
|
return [];
|
|
92537
92818
|
}
|
|
92538
92819
|
return names2.flatMap((n) => {
|
|
92539
92820
|
try {
|
|
92540
|
-
const held4 = JSON.parse(
|
|
92821
|
+
const held4 = JSON.parse(fs30.readFileSync(path33.join(dir, n), "utf8"));
|
|
92541
92822
|
return held4.cardId === id && held4.worktree && held4.deliveryId ? [held4.deliveryId] : [];
|
|
92542
92823
|
} catch {
|
|
92543
92824
|
return [];
|
|
@@ -92591,7 +92872,7 @@ function boardAkb(job, ws, deps, io, task) {
|
|
|
92591
92872
|
const at2 = args.includes("--") ? args.indexOf("--") : args.length;
|
|
92592
92873
|
const full = [...args.slice(0, at2), "--board", ws.board, ...args.slice(at2)];
|
|
92593
92874
|
const log = show ? logLines(io.show, io.event) : void 0;
|
|
92594
|
-
const ran = await runAkb(deps.akb, full, { cwd: ws.cwd, board: ws.board, task,
|
|
92875
|
+
const ran = await runAkb(deps.akb, full, { cwd: ws.cwd, board: ws.board, task, language: cloudLanguage(job), env: { ...env2, AI4KANBAN_EXECUTION: JSON.stringify({ job: job.id, machine: deps.machineId }) }, show: log?.push, track: io.track });
|
|
92595
92876
|
log?.end();
|
|
92596
92877
|
return ran;
|
|
92597
92878
|
};
|
|
@@ -92601,7 +92882,7 @@ async function setUp(job, ws, deps, io) {
|
|
|
92601
92882
|
const runtime = job.runtime;
|
|
92602
92883
|
const missing = unavailable(runtime, await deps.runtimes());
|
|
92603
92884
|
if (missing) return missing;
|
|
92604
|
-
if (!
|
|
92885
|
+
if (!fs30.existsSync(path33.join(ws.board, "config.md"))) {
|
|
92605
92886
|
const init = await akb(["raw", "init"]);
|
|
92606
92887
|
if (init.code !== 0) return refusal(init);
|
|
92607
92888
|
}
|
|
@@ -92618,7 +92899,7 @@ async function setUp(job, ws, deps, io) {
|
|
|
92618
92899
|
const used = await akb(["agent", "use", runtime]);
|
|
92619
92900
|
if (used.code !== 0) return refusal(used);
|
|
92620
92901
|
const servers = mcpServersOf(ws);
|
|
92621
|
-
const mcpFile =
|
|
92902
|
+
const mcpFile = path33.join(ws.board, ".sync", `${ws.task}.mcp.json`);
|
|
92622
92903
|
const takes = new Set(settingKeys(runtime));
|
|
92623
92904
|
const given = job.settings ?? {};
|
|
92624
92905
|
const values = { ...given, model: job.model ?? "" };
|
|
@@ -92676,8 +92957,8 @@ async function reviewRejections(job, ws, deps, io) {
|
|
|
92676
92957
|
if (ran.code !== 0) return { runs, failure: refusal(ran) };
|
|
92677
92958
|
const sent = await push2({ id: job.id, machineId: deps.machineId });
|
|
92678
92959
|
if (!sent.ok) return { runs, failure: sent.error };
|
|
92679
|
-
const
|
|
92680
|
-
return
|
|
92960
|
+
const marked2 = await deps.api.markReviewed(laid.tasks, laid.triage);
|
|
92961
|
+
return marked2.ok ? { runs } : { runs, failure: marked2.error };
|
|
92681
92962
|
});
|
|
92682
92963
|
}
|
|
92683
92964
|
async function learnRejections(job, ws, deps, io) {
|
|
@@ -92718,19 +92999,19 @@ async function runAgent(job, ws, deps, io) {
|
|
|
92718
92999
|
}
|
|
92719
93000
|
function writeTranscript(job, dir) {
|
|
92720
93001
|
if (!job.transcript) return "";
|
|
92721
|
-
const file2 =
|
|
92722
|
-
|
|
92723
|
-
|
|
93002
|
+
const file2 = path33.join(dir, "discussion.md");
|
|
93003
|
+
fs30.mkdirSync(dir, { recursive: true });
|
|
93004
|
+
fs30.writeFileSync(file2, `${job.transcript}
|
|
92724
93005
|
`);
|
|
92725
93006
|
return file2;
|
|
92726
93007
|
}
|
|
92727
93008
|
function pictures(job, ws, id) {
|
|
92728
93009
|
const dir = cardAssetsDir(ws, id);
|
|
92729
93010
|
if (!job.attachments.length || !dir) return "";
|
|
92730
|
-
|
|
93011
|
+
fs30.mkdirSync(dir, { recursive: true });
|
|
92731
93012
|
return job.attachments.map((a3, i) => {
|
|
92732
|
-
const file2 = `${i + 1}-${
|
|
92733
|
-
|
|
93013
|
+
const file2 = `${i + 1}-${path33.basename(a3.name).replace(/[^\w.-]+/g, "-")}`;
|
|
93014
|
+
fs30.writeFileSync(path33.join(dir, file2), Buffer.from(a3.content, "base64"));
|
|
92734
93015
|
return `
|
|
92735
93016
|
<Asset src=".assets/${id}/${file2}" label="${a3.name.replace(/["<>]/g, "") || file2}" />
|
|
92736
93017
|
`;
|
|
@@ -92738,7 +93019,7 @@ function pictures(job, ws, id) {
|
|
|
92738
93019
|
}
|
|
92739
93020
|
function cardFlags(ws, fields) {
|
|
92740
93021
|
if (!fields) return [];
|
|
92741
|
-
const open = (keys) => (keys ?? []).map((k) => Number(/(\d+)$/.exec(k)?.[1])).filter((n) => n > 0 && n !== ws.number && findCard(ws.board, n)?.startsWith(
|
|
93022
|
+
const open = (keys) => (keys ?? []).map((k) => Number(/(\d+)$/.exec(k)?.[1])).filter((n) => n > 0 && n !== ws.number && findCard(ws.board, n)?.startsWith(path33.join(ws.board, "todo") + path33.sep));
|
|
92742
93023
|
const lists = [["--modules", fields.modules ?? []], ["--related", open(fields.related)], ["--blocked-by", open(fields.blocked_by)]];
|
|
92743
93024
|
return [
|
|
92744
93025
|
...fields.priority ? ["--priority", fields.priority] : [],
|
|
@@ -92772,10 +93053,10 @@ async function runFlow(job, ws, deps, io) {
|
|
|
92772
93053
|
const placed = await placeDraft(ws, deps.api);
|
|
92773
93054
|
if (!placed.ok) return fail(placed.error);
|
|
92774
93055
|
}
|
|
92775
|
-
const body =
|
|
92776
|
-
|
|
93056
|
+
const body = path33.join(ws.board, ".sync", `${ws.task}.request.md`);
|
|
93057
|
+
fs30.mkdirSync(path33.dirname(body), { recursive: true });
|
|
92777
93058
|
if (!ws.number) return fail("This task has no number yet.");
|
|
92778
|
-
|
|
93059
|
+
fs30.writeFileSync(body, `${said.request || title}
|
|
92779
93060
|
${isBuilder(ws) ? `
|
|
92780
93061
|
${draftLine(ws)}
|
|
92781
93062
|
` : ""}${pictures(job, ws, ws.number)}`);
|
|
@@ -92793,7 +93074,7 @@ ${draftLine(ws)}
|
|
|
92793
93074
|
...cardFlags(ws, flow.metadata),
|
|
92794
93075
|
"--json"
|
|
92795
93076
|
]));
|
|
92796
|
-
|
|
93077
|
+
fs30.rmSync(body, { force: true });
|
|
92797
93078
|
if (!created.ok) return fail(created.error);
|
|
92798
93079
|
id = created.value;
|
|
92799
93080
|
}
|
|
@@ -92809,7 +93090,7 @@ ${draftLine(ws)}
|
|
|
92809
93090
|
if (io.lost()) return fail("");
|
|
92810
93091
|
return await workOn(card);
|
|
92811
93092
|
} finally {
|
|
92812
|
-
|
|
93093
|
+
fs30.rmSync(path33.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
|
|
92813
93094
|
const left = working.get(key) - 1;
|
|
92814
93095
|
if (left) working.set(key, left);
|
|
92815
93096
|
else working.delete(key);
|
|
@@ -92882,7 +93163,7 @@ ${draftLine(ws)}
|
|
|
92882
93163
|
}
|
|
92883
93164
|
function carryArgs(verb) {
|
|
92884
93165
|
if (!["refine", "resolve", "revise", "implement"].includes(verb)) return [];
|
|
92885
|
-
const transcript = writeTranscript(job,
|
|
93166
|
+
const transcript = writeTranscript(job, path33.join(ws.board, ".sync", `${ws.task}.discussion`));
|
|
92886
93167
|
return [
|
|
92887
93168
|
...job.resume ? ["--session", job.resume, ...job.fork ? ["--fork"] : []] : [],
|
|
92888
93169
|
...transcript ? ["--transcript", transcript] : []
|
|
@@ -92901,15 +93182,15 @@ async function confirmFlowStopped(ws, job, deps) {
|
|
|
92901
93182
|
}
|
|
92902
93183
|
|
|
92903
93184
|
// src/recovery.ts
|
|
92904
|
-
import
|
|
92905
|
-
import
|
|
93185
|
+
import fs31 from "node:fs";
|
|
93186
|
+
import path34 from "node:path";
|
|
92906
93187
|
var PREPARE_REASON = "Runner update prepare.";
|
|
92907
93188
|
var UPDATE_REASON = "Runner update checkpoint.";
|
|
92908
93189
|
var UNCERTAIN = "\u66F4\u65B0\u4E2D\u65AD\u65F6\u6709\u64CD\u4F5C\u7ED3\u679C\u5C1A\u672A\u786E\u8BA4\uFF0C\u8BF7\u68C0\u67E5\u5DF2\u6709\u7ED3\u679C\u540E\u518D\u7EED\u8DD1\u3002";
|
|
92909
|
-
var fileOf = (id) =>
|
|
93190
|
+
var fileOf = (id) => path34.join(runnerHome(), "checkpoints", `${encodeURIComponent(id)}.json`);
|
|
92910
93191
|
function readCheckpoint(id) {
|
|
92911
93192
|
try {
|
|
92912
|
-
const held4 = JSON.parse(
|
|
93193
|
+
const held4 = JSON.parse(fs31.readFileSync(fileOf(id), "utf8"));
|
|
92913
93194
|
if (!held4 || !Array.isArray(held4.pending) || !held4.pending.every((id2) => typeof id2 === "string")) throw new Error("\u8FDB\u5EA6\u683C\u5F0F\u9519\u8BEF");
|
|
92914
93195
|
return held4;
|
|
92915
93196
|
} catch (e2) {
|
|
@@ -92919,12 +93200,12 @@ function readCheckpoint(id) {
|
|
|
92919
93200
|
}
|
|
92920
93201
|
function saveCheckpoint(id, checkpoint) {
|
|
92921
93202
|
const file2 = fileOf(id);
|
|
92922
|
-
|
|
92923
|
-
|
|
92924
|
-
|
|
93203
|
+
fs31.mkdirSync(path34.dirname(file2), { recursive: true, mode: 448 });
|
|
93204
|
+
fs31.writeFileSync(`${file2}.tmp`, JSON.stringify(checkpoint), { mode: 384 });
|
|
93205
|
+
fs31.renameSync(`${file2}.tmp`, file2);
|
|
92925
93206
|
}
|
|
92926
93207
|
function clearCheckpoint(id) {
|
|
92927
|
-
|
|
93208
|
+
fs31.rmSync(fileOf(id), { force: true });
|
|
92928
93209
|
}
|
|
92929
93210
|
function checkpointEvent(checkpoint, event2) {
|
|
92930
93211
|
if (event2.kind === "tool_call") {
|
|
@@ -92936,19 +93217,30 @@ function checkpointEvent(checkpoint, event2) {
|
|
|
92936
93217
|
checkpoint.pending = checkpoint.pending.filter((id) => id !== event2.data.toolCallId);
|
|
92937
93218
|
}
|
|
92938
93219
|
}
|
|
93220
|
+
async function stopReply(id, timeout) {
|
|
93221
|
+
const checkpoint = readCheckpoint(id);
|
|
93222
|
+
if (!checkpoint?.mark) return checkpoint?.started === false;
|
|
93223
|
+
killMarked(checkpoint.mark, checkpoint.process);
|
|
93224
|
+
const until = Date.now() + timeout;
|
|
93225
|
+
while (!processesStopped(checkpoint.mark, checkpoint.process)) {
|
|
93226
|
+
if (Date.now() >= until) return false;
|
|
93227
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
93228
|
+
}
|
|
93229
|
+
return true;
|
|
93230
|
+
}
|
|
92939
93231
|
|
|
92940
93232
|
// src/lock.ts
|
|
92941
|
-
import
|
|
92942
|
-
import
|
|
93233
|
+
import crypto5 from "node:crypto";
|
|
93234
|
+
import fs32 from "node:fs";
|
|
92943
93235
|
import net from "node:net";
|
|
92944
|
-
import
|
|
93236
|
+
import path35 from "node:path";
|
|
92945
93237
|
var RETRY_MS = 5e3;
|
|
92946
93238
|
var KIND_MS = 1e3;
|
|
92947
93239
|
var HOLDERS = ["claude-code", "codex", "terminal"];
|
|
92948
93240
|
function lockPath() {
|
|
92949
93241
|
const home4 = runnerHome();
|
|
92950
|
-
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${
|
|
92951
|
-
return
|
|
93242
|
+
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${crypto5.createHash("sha256").update(home4).digest("hex").slice(0, 16)}`;
|
|
93243
|
+
return path35.join(home4, "runner.sock");
|
|
92952
93244
|
}
|
|
92953
93245
|
function holdMachine(kind, onHeld, onWaiting) {
|
|
92954
93246
|
const where = lockPath();
|
|
@@ -92963,12 +93255,12 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92963
93255
|
const attempt = () => {
|
|
92964
93256
|
timer = null;
|
|
92965
93257
|
if (closed) return;
|
|
92966
|
-
if (process.platform !== "win32")
|
|
93258
|
+
if (process.platform !== "win32") fs32.mkdirSync(path35.dirname(where), { recursive: true, mode: 448 });
|
|
92967
93259
|
const s = net.createServer((peer) => {
|
|
92968
93260
|
peers.add(peer);
|
|
92969
93261
|
peer.on("error", () => {
|
|
92970
93262
|
}).on("close", () => peers.delete(peer));
|
|
92971
|
-
peer.write(`${JSON.stringify({ kind })}
|
|
93263
|
+
peer.write(`${JSON.stringify({ kind, settings: 1 })}
|
|
92972
93264
|
`);
|
|
92973
93265
|
});
|
|
92974
93266
|
s.once("error", (e2) => {
|
|
@@ -93011,7 +93303,7 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
93011
93303
|
later(0);
|
|
93012
93304
|
});
|
|
93013
93305
|
removeIfStill.once("error", () => {
|
|
93014
|
-
|
|
93306
|
+
fs32.rmSync(where, { force: true });
|
|
93015
93307
|
later(50 + Math.random() * 200);
|
|
93016
93308
|
});
|
|
93017
93309
|
return;
|
|
@@ -93040,17 +93332,17 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
93040
93332
|
}
|
|
93041
93333
|
|
|
93042
93334
|
// src/handoff.ts
|
|
93043
|
-
import
|
|
93044
|
-
import
|
|
93045
|
-
import
|
|
93046
|
-
import { execFileSync } from "node:child_process";
|
|
93047
|
-
var digest = (value) =>
|
|
93048
|
-
var git3 = (cwd, ...args) =>
|
|
93335
|
+
import crypto6 from "node:crypto";
|
|
93336
|
+
import fs33 from "node:fs";
|
|
93337
|
+
import path36 from "node:path";
|
|
93338
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
93339
|
+
var digest = (value) => crypto6.createHash("sha256").update(value).digest("hex");
|
|
93340
|
+
var git3 = (cwd, ...args) => execFileSync2("git", ["-C", cwd, ...args], { encoding: "utf8", timeout: 15e3, maxBuffer: 16 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] });
|
|
93049
93341
|
function authorizedFolder(folder) {
|
|
93050
93342
|
if (!folder) return null;
|
|
93051
93343
|
try {
|
|
93052
|
-
const real =
|
|
93053
|
-
return allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
93344
|
+
const real = fs33.realpathSync(folder);
|
|
93345
|
+
return allowedProjects().some((root) => real === root || real.startsWith(root + path36.sep)) ? real : null;
|
|
93054
93346
|
} catch {
|
|
93055
93347
|
return null;
|
|
93056
93348
|
}
|
|
@@ -93060,9 +93352,9 @@ function progressFolder(job, folder) {
|
|
|
93060
93352
|
if (!token) return folder;
|
|
93061
93353
|
if (!/^[a-zA-Z0-9-]{1,80}$/.test(token)) return null;
|
|
93062
93354
|
try {
|
|
93063
|
-
const dir =
|
|
93064
|
-
if (!dir.startsWith(
|
|
93065
|
-
const marker = JSON.parse(
|
|
93355
|
+
const dir = fs33.realpathSync(path36.join(folder, ".akb", "handoffs", token));
|
|
93356
|
+
if (!dir.startsWith(fs33.realpathSync(folder) + path36.sep)) return null;
|
|
93357
|
+
const marker = JSON.parse(fs33.readFileSync(path36.join(dir, ".akb", "handoff.json"), "utf8"));
|
|
93066
93358
|
return marker.task === job.task && marker.isolation === token ? dir : null;
|
|
93067
93359
|
} catch {
|
|
93068
93360
|
return null;
|
|
@@ -93070,24 +93362,24 @@ function progressFolder(job, folder) {
|
|
|
93070
93362
|
}
|
|
93071
93363
|
function progressEvidence(job, folder) {
|
|
93072
93364
|
try {
|
|
93073
|
-
const board =
|
|
93074
|
-
const deliveries =
|
|
93075
|
-
const rows =
|
|
93365
|
+
const board = path36.join(folder, ".akb", "kanban");
|
|
93366
|
+
const deliveries = path36.join(board, "deliveries");
|
|
93367
|
+
const rows = fs33.readdirSync(deliveries).filter((name) => name.endsWith(".json")).map((name) => JSON.parse(fs33.readFileSync(path36.join(deliveries, name), "utf8"))).filter((row2) => row2.cardId === job.number).sort((a3, b2) => (b2.startedAt ?? 0) - (a3.startedAt ?? 0));
|
|
93076
93368
|
const row = rows[0];
|
|
93077
93369
|
if (!row?.deliveryId || !row.base || !row.branch || !row.worktree || row.commitMode !== "auto") return null;
|
|
93078
|
-
const tree =
|
|
93079
|
-
if (!tree.startsWith(
|
|
93370
|
+
const tree = fs33.realpathSync(path36.resolve(folder, row.worktree));
|
|
93371
|
+
if (!tree.startsWith(fs33.realpathSync(folder) + path36.sep)) return null;
|
|
93080
93372
|
if (git3(tree, "rev-parse", "--show-toplevel").trim() !== tree) return null;
|
|
93081
93373
|
if (git3(tree, "branch", "--show-current").trim() !== row.branch) return null;
|
|
93082
93374
|
git3(tree, "cat-file", "-e", `${row.base}^{commit}`);
|
|
93083
93375
|
const changed = git3(tree, "ls-files", "-z", "--cached", "--others", "--exclude-standard").split("\0").filter(Boolean).sort();
|
|
93084
93376
|
const files = changed.map((name) => {
|
|
93085
|
-
const file2 =
|
|
93377
|
+
const file2 = path36.join(tree, name);
|
|
93086
93378
|
try {
|
|
93087
|
-
const stat =
|
|
93088
|
-
if (stat.isSymbolicLink()) return [name, "link", digest(
|
|
93379
|
+
const stat = fs33.lstatSync(file2);
|
|
93380
|
+
if (stat.isSymbolicLink()) return [name, "link", digest(fs33.readlinkSync(file2))];
|
|
93089
93381
|
if (!stat.isFile()) throw new Error("\u65E0\u6CD5\u9A8C\u8BC1\u6587\u4EF6\u7C7B\u578B");
|
|
93090
|
-
return [name, stat.mode & 511, digest(
|
|
93382
|
+
return [name, stat.mode & 511, digest(fs33.readFileSync(file2))];
|
|
93091
93383
|
} catch (e2) {
|
|
93092
93384
|
if (e2.code === "ENOENT") return [name, "deleted"];
|
|
93093
93385
|
throw e2;
|
|
@@ -93112,56 +93404,56 @@ function progressEvidence(job, folder) {
|
|
|
93112
93404
|
function restartFolder(job, folder) {
|
|
93113
93405
|
const token = job.handoff?.isolation ?? job.id;
|
|
93114
93406
|
if (!/^[a-zA-Z0-9-]{1,80}$/.test(token)) throw new Error("\u9694\u79BB\u76EE\u5F55\u7F16\u53F7\u65E0\u6548\u3002");
|
|
93115
|
-
const dir =
|
|
93116
|
-
const marker =
|
|
93117
|
-
for (const parent of [
|
|
93118
|
-
if (
|
|
93407
|
+
const dir = path36.join(folder, ".akb", "handoffs", token);
|
|
93408
|
+
const marker = path36.join(dir, ".akb", "handoff.json");
|
|
93409
|
+
for (const parent of [path36.join(folder, ".akb"), path36.dirname(dir), dir]) {
|
|
93410
|
+
if (fs33.lstatSync(parent, { throwIfNoEntry: false })?.isSymbolicLink()) throw new Error("\u9694\u79BB\u76EE\u5F55\u4E0D\u80FD\u901A\u8FC7\u7B26\u53F7\u94FE\u63A5\u521B\u5EFA\u3002");
|
|
93119
93411
|
}
|
|
93120
|
-
if (
|
|
93412
|
+
if (fs33.existsSync(dir)) {
|
|
93121
93413
|
if (job.handoff?.recovering) {
|
|
93122
93414
|
try {
|
|
93123
|
-
const saved = JSON.parse(
|
|
93124
|
-
if (saved.task === job.task && saved.isolation === token && git3(dir, "rev-parse", "--show-toplevel").trim() ===
|
|
93415
|
+
const saved = JSON.parse(fs33.readFileSync(marker, "utf8"));
|
|
93416
|
+
if (saved.task === job.task && saved.isolation === token && git3(dir, "rev-parse", "--show-toplevel").trim() === fs33.realpathSync(dir)) return dir;
|
|
93125
93417
|
} catch {
|
|
93126
93418
|
}
|
|
93127
93419
|
}
|
|
93128
93420
|
throw new Error("\u91CD\u542F\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002");
|
|
93129
93421
|
}
|
|
93130
|
-
|
|
93422
|
+
fs33.mkdirSync(path36.dirname(dir), { recursive: true });
|
|
93131
93423
|
git3(folder, "worktree", "add", "--detach", dir, "HEAD");
|
|
93132
|
-
if (
|
|
93133
|
-
|
|
93134
|
-
|
|
93424
|
+
if (fs33.lstatSync(path36.dirname(marker), { throwIfNoEntry: false })?.isSymbolicLink()) throw new Error("\u9694\u79BB\u6807\u8BB0\u76EE\u5F55\u65E0\u6548\u3002");
|
|
93425
|
+
fs33.mkdirSync(path36.dirname(marker), { recursive: true });
|
|
93426
|
+
fs33.writeFileSync(marker, JSON.stringify({ task: job.task, isolation: token }), { flag: "wx" });
|
|
93135
93427
|
return dir;
|
|
93136
93428
|
}
|
|
93137
93429
|
|
|
93138
93430
|
// src/jobs.ts
|
|
93139
93431
|
import { spawn as spawn4 } from "node:child_process";
|
|
93140
|
-
import
|
|
93141
|
-
import
|
|
93432
|
+
import fs35 from "node:fs";
|
|
93433
|
+
import path38 from "node:path";
|
|
93142
93434
|
|
|
93143
93435
|
// ../cli/src/lib/agent/catalog.ts
|
|
93144
|
-
import
|
|
93145
|
-
import
|
|
93436
|
+
import fs34 from "node:fs";
|
|
93437
|
+
import path37 from "node:path";
|
|
93146
93438
|
var CATALOGUE = "https://models.dev/api.json";
|
|
93147
93439
|
var FRESH_FOR_MS = 24 * 60 * 6e4;
|
|
93148
93440
|
var ANSWER_BY_MS = 2e4;
|
|
93149
93441
|
function cacheFile() {
|
|
93150
|
-
return
|
|
93442
|
+
return path37.join(machineHome(), "models-dev.json");
|
|
93151
93443
|
}
|
|
93152
93444
|
var held2;
|
|
93153
93445
|
function readCache() {
|
|
93154
93446
|
const file2 = cacheFile();
|
|
93155
93447
|
let stamp2;
|
|
93156
93448
|
try {
|
|
93157
|
-
const stat =
|
|
93449
|
+
const stat = fs34.statSync(file2);
|
|
93158
93450
|
stamp2 = `${stat.mtimeMs}:${stat.size}`;
|
|
93159
93451
|
} catch {
|
|
93160
93452
|
return void 0;
|
|
93161
93453
|
}
|
|
93162
93454
|
if (held2?.stamp === stamp2) return held2.cached;
|
|
93163
93455
|
try {
|
|
93164
|
-
const data = JSON.parse(
|
|
93456
|
+
const data = JSON.parse(fs34.readFileSync(file2, "utf8"));
|
|
93165
93457
|
if (!data || typeof data.limits !== "object" || !data.limits) return void 0;
|
|
93166
93458
|
const cached2 = {
|
|
93167
93459
|
fetchedAt: typeof data.fetchedAt === "number" ? data.fetchedAt : 0,
|
|
@@ -93200,8 +93492,8 @@ function refreshCatalog() {
|
|
|
93200
93492
|
const limits = limitsIn(await answer.json());
|
|
93201
93493
|
if (Object.keys(limits).length === 0) return;
|
|
93202
93494
|
const file2 = cacheFile();
|
|
93203
|
-
|
|
93204
|
-
|
|
93495
|
+
fs34.mkdirSync(path37.dirname(file2), { recursive: true });
|
|
93496
|
+
fs34.writeFileSync(file2, JSON.stringify({ fetchedAt: Date.now(), limits }));
|
|
93205
93497
|
} catch {
|
|
93206
93498
|
}
|
|
93207
93499
|
})();
|
|
@@ -93276,32 +93568,32 @@ var defaultDeps = (machineId2) => ({
|
|
|
93276
93568
|
akb: currentAkb,
|
|
93277
93569
|
runtimes: detectRuntimes
|
|
93278
93570
|
});
|
|
93279
|
-
var ownFolder = () =>
|
|
93571
|
+
var ownFolder = () => path38.join(runnerHome(), "work");
|
|
93280
93572
|
function folderFor(job) {
|
|
93281
93573
|
if (!job.projectDir) {
|
|
93282
|
-
const cwd =
|
|
93283
|
-
|
|
93574
|
+
const cwd = path38.join(ownFolder(), job.id);
|
|
93575
|
+
fs35.mkdirSync(cwd, { recursive: true });
|
|
93284
93576
|
return { cwd };
|
|
93285
93577
|
}
|
|
93286
93578
|
const real = realpath4(job.projectDir);
|
|
93287
|
-
if (real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
93579
|
+
if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path38.sep))) return { cwd: real };
|
|
93288
93580
|
return { refused: `This Runner is not allowed to work in ${job.projectDir}.` };
|
|
93289
93581
|
}
|
|
93290
93582
|
function realpath4(p2) {
|
|
93291
93583
|
try {
|
|
93292
|
-
return
|
|
93584
|
+
return fs35.realpathSync(p2);
|
|
93293
93585
|
} catch {
|
|
93294
93586
|
return null;
|
|
93295
93587
|
}
|
|
93296
93588
|
}
|
|
93297
|
-
var attachmentsOf = (job) =>
|
|
93589
|
+
var attachmentsOf = (job) => path38.join(runnerHome(), "attachments", job.id);
|
|
93298
93590
|
function writeAttachments(job) {
|
|
93299
93591
|
if (!job.attachments.length) return "";
|
|
93300
93592
|
const dir = attachmentsOf(job);
|
|
93301
|
-
|
|
93593
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
93302
93594
|
const files = job.attachments.map((a3) => {
|
|
93303
|
-
const file2 =
|
|
93304
|
-
|
|
93595
|
+
const file2 = path38.join(dir, path38.basename(a3.name));
|
|
93596
|
+
fs35.writeFileSync(file2, Buffer.from(a3.content, "base64"));
|
|
93305
93597
|
return file2;
|
|
93306
93598
|
});
|
|
93307
93599
|
return `
|
|
@@ -93568,24 +93860,32 @@ async function runJob(id, deps, track = () => {
|
|
|
93568
93860
|
const claim = await deps.api.claimJob(deps.machineId, id);
|
|
93569
93861
|
if (!claim.ok || !claim.value.claimed || stopped2() || !held3(deps, lease)) return;
|
|
93570
93862
|
const job = claim.value.job;
|
|
93863
|
+
if (deps.authorize && !await deps.authorize(job)) {
|
|
93864
|
+
await deps.api.finishJob(deps.machineId, id, "failed", "\u9879\u76EE\u76EE\u5F55\u6388\u6743\u5DF2\u64A4\u9500\u6216\u6682\u65F6\u65E0\u6CD5\u9A8C\u8BC1\uFF0C\u8BF7\u91CD\u65B0\u786E\u8BA4\u540E\u91CD\u8BD5\u3002");
|
|
93865
|
+
return;
|
|
93866
|
+
}
|
|
93571
93867
|
const releases = [];
|
|
93572
93868
|
try {
|
|
93573
93869
|
await runClaimed(job, { ...deps, akb: deps.akb() }, track, (dir) => releases.push(hold(dir)), lease);
|
|
93574
93870
|
} finally {
|
|
93575
93871
|
for (const release2 of releases) release2();
|
|
93576
|
-
|
|
93872
|
+
fs35.rmSync(attachmentsOf(job), { recursive: true, force: true });
|
|
93577
93873
|
}
|
|
93578
93874
|
}
|
|
93579
93875
|
async function runClaimed(job, deps, track, keep2, lease) {
|
|
93580
93876
|
const id = job.id;
|
|
93581
|
-
const checkpoint = readCheckpoint(id) ?? { pending: [] };
|
|
93582
|
-
const recovering = checkpoint.updating === true;
|
|
93877
|
+
const checkpoint = readCheckpoint(id) ?? (job.recoveryOf ? readCheckpoint(job.recoveryOf) : null) ?? { pending: [], started: false };
|
|
93878
|
+
const recovering = checkpoint.updating === true || !!job.recoveryOf;
|
|
93583
93879
|
const persist = () => {
|
|
93584
93880
|
checkpoint.updating ||= readCheckpoint(id)?.updating;
|
|
93585
93881
|
saveCheckpoint(id, checkpoint);
|
|
93586
93882
|
};
|
|
93587
|
-
|
|
93588
|
-
|
|
93883
|
+
const manual = job.manualRecovery === true;
|
|
93884
|
+
if (manual && checkpoint.completed?.outcome === "failed") delete checkpoint.completed;
|
|
93885
|
+
checkpoint.session ??= job.resume ?? void 0;
|
|
93886
|
+
if (recovering && !checkpoint.completed && (!manual && (checkpoint.pending.length || checkpoint.opaque) || !job.flow && checkpoint.started && !checkpoint.session)) {
|
|
93887
|
+
saveCheckpoint(id, checkpoint);
|
|
93888
|
+
await deps.api.finishJob(deps.machineId, id, "failed", job.recoveryOf ? "recovery_failed" : UNCERTAIN);
|
|
93589
93889
|
return;
|
|
93590
93890
|
}
|
|
93591
93891
|
if (recovering && checkpoint.session) job = { ...job, resume: checkpoint.session, fork: false };
|
|
@@ -93653,7 +93953,7 @@ async function runClaimed(job, deps, track, keep2, lease) {
|
|
|
93653
93953
|
discussed = board.board;
|
|
93654
93954
|
}
|
|
93655
93955
|
if (job.discussion) {
|
|
93656
|
-
const wrote = recovering &&
|
|
93956
|
+
const wrote = recovering && fs35.existsSync(goalsFileOf(job)) ? { file: goalsFileOf(job) } : await writeGoals({ ...job, discussion: job.discussion }, deps.api.listWorkflows);
|
|
93657
93957
|
if ("error" in wrote) throw new Error(wrote.error);
|
|
93658
93958
|
goalFile = wrote.file;
|
|
93659
93959
|
}
|
|
@@ -93666,7 +93966,7 @@ async function runClaimed(job, deps, track, keep2, lease) {
|
|
|
93666
93966
|
This task came out of a discussion. Read it for what the card leaves out: ${file2}` : "";
|
|
93667
93967
|
const promptOf = (said2) => {
|
|
93668
93968
|
const lines = (head2 + said2).trim();
|
|
93669
|
-
const prompt = recovering && checkpoint.started ? "
|
|
93969
|
+
const prompt = recovering && (checkpoint.started || job.recoveryOf) ? "\u8FDE\u63A5\u6062\u590D\u540E\u7EE7\u7EED\u4E4B\u524D\u4E2D\u65AD\u7684\u56DE\u590D\u3002\u5148\u6838\u5BF9\u5DF2\u6709\u8FDB\u5EA6\u548C\u7ED3\u679C\uFF0C\u4FDD\u7559\u5B8C\u6210\u7684\u5DE5\u4F5C\uFF0C\u4E0D\u8981\u91CD\u590D\u5DF2\u7ECF\u6267\u884C\u7684\u64CD\u4F5C\u3002" : cloudPrompt(job);
|
|
93670
93970
|
return lines ? `${lines}
|
|
93671
93971
|
|
|
93672
93972
|
---
|
|
@@ -93674,9 +93974,9 @@ This task came out of a discussion. Read it for what the card leaves out: ${file
|
|
|
93674
93974
|
${prompt}` : prompt;
|
|
93675
93975
|
};
|
|
93676
93976
|
const planned = (resume, fork, said2 = "") => {
|
|
93677
|
-
let p2 = deps.plan(job.runtime, promptOf(said2), cwd, resume, job.model, settingsOf(job), fork, job
|
|
93678
|
-
if (ws) p2 = { ...p2, env:
|
|
93679
|
-
if (goalFile) p2 = { ...p2, env: { ...
|
|
93977
|
+
let p2 = deps.plan(job.runtime, promptOf(said2), cwd, resume, job.model, settingsOf(job), fork, cloudLanguage(job));
|
|
93978
|
+
if (ws) p2 = { ...p2, env: akbEnv(deps.akb, ws.board, ws.task, cloudLanguage(job), p2.env) };
|
|
93979
|
+
if (goalFile) p2 = { ...p2, env: { ...akbEnv(deps.akb, discussed, void 0, cloudLanguage(job), p2.env), KANBAN_GOALS: goalFile, KANBAN_IDEAS: goalFile } };
|
|
93680
93980
|
if (job.chat || job.discussion) {
|
|
93681
93981
|
const { CLAUDE_CODE_MAX_RETRIES: _2, ...env2 } = p2.env;
|
|
93682
93982
|
p2 = { ...p2, env: env2 };
|
|
@@ -93695,9 +93995,14 @@ ${prompt}` : prompt;
|
|
|
93695
93995
|
await deps.api.finishJob(deps.machineId, id, "failed", e2 instanceof Error ? e2.message : String(e2));
|
|
93696
93996
|
return;
|
|
93697
93997
|
}
|
|
93998
|
+
if (deps.authorize && !await deps.authorize(job)) return finish(deps, id, lease, "failed", "\u9879\u76EE\u76EE\u5F55\u6388\u6743\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u786E\u8BA4\u540E\u91CD\u8BD5\u3002");
|
|
93698
93999
|
if (!held3(deps, lease)) return;
|
|
93699
94000
|
const stream = streamOut(deps, id, lease);
|
|
94001
|
+
if (run2?.startNote) stream.out(`${run2.startNote}
|
|
94002
|
+
`);
|
|
94003
|
+
let replyProgress = false;
|
|
93700
94004
|
const remember = (event2) => {
|
|
94005
|
+
if (["message", "tool_call", "tool_call_update"].includes(event2.kind)) replyProgress = true;
|
|
93701
94006
|
if (stream.lost()) return;
|
|
93702
94007
|
checkpointEvent(checkpoint, event2);
|
|
93703
94008
|
const session = run2?.session();
|
|
@@ -93758,6 +94063,7 @@ ${prompt}` : prompt;
|
|
|
93758
94063
|
if (!ended3.ok) return finish(deps, id, lease, "failed", ended3.reason, proof);
|
|
93759
94064
|
return sendBack(deps, id, lease, ws, { ...ended3.report, ...proof }, () => keepChat(job, ended3.report.reply));
|
|
93760
94065
|
}
|
|
94066
|
+
checkpoint.mark = stopMark();
|
|
93761
94067
|
checkpoint.started = true;
|
|
93762
94068
|
checkpoint.opaque = !run2.converse && !run2.renderer?.events;
|
|
93763
94069
|
checkpoint.session = run2.session() ?? checkpoint.session;
|
|
@@ -93765,7 +94071,11 @@ ${prompt}` : prompt;
|
|
|
93765
94071
|
if (run2.converse) {
|
|
93766
94072
|
const plan3 = run2;
|
|
93767
94073
|
const converse = run2.converse;
|
|
93768
|
-
const child = spawn4(plan3.command, plan3.args, { cwd, env: plan3.env, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94074
|
+
const child = spawn4(plan3.command, plan3.args, { cwd, env: markEnv(plan3.env, checkpoint.mark), detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94075
|
+
if (child.pid) {
|
|
94076
|
+
checkpoint.process = { pid: child.pid, since: Date.now() };
|
|
94077
|
+
persist();
|
|
94078
|
+
}
|
|
93769
94079
|
stream.adopt(child);
|
|
93770
94080
|
child.stdin.on("error", () => {
|
|
93771
94081
|
});
|
|
@@ -93773,22 +94083,33 @@ ${prompt}` : prompt;
|
|
|
93773
94083
|
child.stderr.on("data", (chunk) => stream.out(quietLines(plan3, chunk)));
|
|
93774
94084
|
const spawned = new Promise((resolve2) => child.on("error", (e2) => resolve2(e2.message)));
|
|
93775
94085
|
const end = await Promise.race([
|
|
93776
|
-
converse(child, remember),
|
|
94086
|
+
converse(child, remember, false),
|
|
93777
94087
|
spawned.then((error) => ({ ok: false, error })),
|
|
93778
94088
|
// Killed, the turn ends with what it said so far; one that never does is not waited on.
|
|
93779
94089
|
stream.whenAsked.then(() => wait2(KILL_GRACE_MS * 2)).then(() => ({ ok: true }))
|
|
93780
94090
|
]);
|
|
94091
|
+
if (!end.ok && !recovering && job.resume && (job.chat || job.discussion) && sessionMissing(end.error ?? "") && !replyProgress && !checkpoint.pending.length && !stream.asked() && !stream.lost()) {
|
|
94092
|
+
stop(child);
|
|
94093
|
+
await stream.end();
|
|
94094
|
+
if (!await stream.confirmed()) return finish(deps, id, lease, "failed", "recovery_failed");
|
|
94095
|
+
clearCheckpoint(id);
|
|
94096
|
+
return runClaimed({ ...job, resume: null, fork: false, sessionFallback: true }, deps, track, keep2, lease);
|
|
94097
|
+
}
|
|
93781
94098
|
if (!stream.asked()) complete(end.ok ? "done" : "failed", told(report(job, plan3, end)), end.ok ? void 0 : end.error);
|
|
93782
94099
|
stop(child);
|
|
93783
94100
|
await stream.end();
|
|
93784
94101
|
if (stream.lost()) return;
|
|
93785
94102
|
const ok = end.ok || stream.asked();
|
|
93786
94103
|
const said2 = told(stream.asked() ? cutShort(report(job, plan3, end), stream.said()) : report(job, plan3, end));
|
|
93787
|
-
if (!ok || !ws) return finish(deps, id, lease, ok ? "done" : "failed", ok ? "" : end.
|
|
94104
|
+
if (!ok || !ws) return finish(deps, id, lease, ok ? "done" : "failed", ok ? "" : replyReason(end.ok ? void 0 : end.error, job), said2);
|
|
93788
94105
|
return sendBack(deps, id, lease, ws, said2, () => keepChat(job, said2.reply));
|
|
93789
94106
|
}
|
|
93790
94107
|
const printed = async (plan3) => {
|
|
93791
|
-
const child = spawn4(plan3.command, plan3.args, { cwd, env: plan3.env, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94108
|
+
const child = spawn4(plan3.command, plan3.args, { cwd, env: markEnv(plan3.env, checkpoint.mark), detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94109
|
+
if (child.pid) {
|
|
94110
|
+
checkpoint.process = { pid: child.pid, since: Date.now() };
|
|
94111
|
+
persist();
|
|
94112
|
+
}
|
|
93792
94113
|
stream.adopt(child);
|
|
93793
94114
|
child.stdin.on("error", () => {
|
|
93794
94115
|
});
|
|
@@ -93830,17 +94151,18 @@ ${prompt}` : prompt;
|
|
|
93830
94151
|
if (fresh && ended2.code !== 0 && plan2.renderer.result() === void 0 && !ended2.acted && (!missingSessionOnly || sessionMissing(`${ended2.stderr}
|
|
93831
94152
|
${plan2.renderer.failure?.() ?? ""}`)) && !stream.asked() && !stream.lost()) {
|
|
93832
94153
|
plan2 = fresh();
|
|
94154
|
+
job = { ...job, sessionFallback: missingSessionOnly };
|
|
93833
94155
|
run2 = plan2;
|
|
93834
94156
|
ended2 = await printed(plan2);
|
|
93835
94157
|
}
|
|
93836
94158
|
const renderer = plan2.renderer;
|
|
93837
94159
|
if (!stream.asked()) {
|
|
93838
|
-
const reason = ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`);
|
|
94160
|
+
const reason = replyReason(ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`), job);
|
|
93839
94161
|
complete(reason ? "failed" : "done", told(report(job, plan2)), reason);
|
|
93840
94162
|
}
|
|
93841
94163
|
await stream.end();
|
|
93842
94164
|
if (stream.lost()) return;
|
|
93843
|
-
const failure = stream.asked() ? void 0 : ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`);
|
|
94165
|
+
const failure = stream.asked() ? void 0 : replyReason(ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`), job);
|
|
93844
94166
|
const said = told(stream.asked() ? cutShort(report(job, plan2), stream.said()) : report(job, plan2));
|
|
93845
94167
|
if (failure || !ws) return finish(deps, id, lease, failure ? "failed" : "done", failure, said);
|
|
93846
94168
|
return sendBack(deps, id, lease, ws, said, () => keepChat(job, said.reply));
|
|
@@ -93880,18 +94202,24 @@ async function runAgentJob(job, deps, track, keep2, lease, checkpoint, persist)
|
|
|
93880
94202
|
}
|
|
93881
94203
|
var quietLines = (plan2, chunk) => chunk.split("\n").filter((line) => line && !plan2.quiet(line)).map((line) => `${line}
|
|
93882
94204
|
`).join("");
|
|
93883
|
-
var
|
|
93884
|
-
|
|
94205
|
+
var replyReason = (reason, job) => {
|
|
94206
|
+
if (!reason) return reason;
|
|
94207
|
+
if (job.recoveryOf) return "recovery_failed";
|
|
94208
|
+
if (job.sessionFallback && !/auth|login|log.in|permission|directory|ENOENT|not installed|rate.limit|network|connect|登录|权限|目录/i.test(reason)) return "session_unavailable";
|
|
94209
|
+
return reason;
|
|
94210
|
+
};
|
|
94211
|
+
var sessionMissing = (text3) => !/auth|unauthorized|forbidden|login|log.in|登录|权限/i.test(text3) && (/\b(?:session|conversation|thread)\b[^\n]*(?:\bnot found\b|\bdoes not exist\b)/i.test(text3) || /\bno (?:conversation|session|thread) found\b/i.test(text3));
|
|
94212
|
+
function signalTree(child, signal2) {
|
|
93885
94213
|
if (!child.pid) return;
|
|
93886
94214
|
if (process.platform === "win32") {
|
|
93887
94215
|
const kill = spawn4("taskkill", ["/PID", String(child.pid), "/T", "/F"], { stdio: "ignore" });
|
|
93888
|
-
kill.on("error", () => child.kill(
|
|
94216
|
+
kill.on("error", () => child.kill(signal2));
|
|
93889
94217
|
return;
|
|
93890
94218
|
}
|
|
93891
94219
|
try {
|
|
93892
|
-
process.kill(-child.pid,
|
|
94220
|
+
process.kill(-child.pid, signal2);
|
|
93893
94221
|
} catch {
|
|
93894
|
-
child.kill(
|
|
94222
|
+
child.kill(signal2);
|
|
93895
94223
|
}
|
|
93896
94224
|
}
|
|
93897
94225
|
var stop = (child) => {
|
|
@@ -93964,8 +94292,8 @@ async function runTest(job, deps, lease) {
|
|
|
93964
94292
|
const report2 = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
|
|
93965
94293
|
if (!report2?.installed) return finish2("failed", "not_installed");
|
|
93966
94294
|
if (report2.loggedIn === false) return finish2("failed", "signed_out");
|
|
93967
|
-
const cwd =
|
|
93968
|
-
|
|
94295
|
+
const cwd = path38.join(ownFolder(), "test");
|
|
94296
|
+
fs35.mkdirSync(cwd, { recursive: true });
|
|
93969
94297
|
const run2 = deps.plan(job.runtime, job.prompt, cwd, null, job.model, settingsOf(job));
|
|
93970
94298
|
const startedAt = Date.now();
|
|
93971
94299
|
if (run2.converse) {
|
|
@@ -94120,9 +94448,15 @@ var POLL_MS = 6e4;
|
|
|
94120
94448
|
var BACKOFF_MS3 = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
94121
94449
|
var LOOK_LATE_MS = 6e4;
|
|
94122
94450
|
function startRunner(options) {
|
|
94451
|
+
adoptLegacy();
|
|
94452
|
+
const account = readSession()?.subject;
|
|
94453
|
+
const generation = accountGeneration();
|
|
94454
|
+
const releaseRecord = executorRecord();
|
|
94123
94455
|
let registration = null;
|
|
94124
94456
|
let connected = false;
|
|
94125
94457
|
let closed = false;
|
|
94458
|
+
let ownsExecution = false;
|
|
94459
|
+
let redetect = false;
|
|
94126
94460
|
let preparing = false;
|
|
94127
94461
|
let attempts = 0;
|
|
94128
94462
|
let live = null;
|
|
@@ -94140,7 +94474,12 @@ function startRunner(options) {
|
|
|
94140
94474
|
const stopped2 = new Promise((resolve2) => stop2 = resolve2);
|
|
94141
94475
|
const deps = () => {
|
|
94142
94476
|
const base = options.deps ?? defaultDeps(registration.machineId);
|
|
94143
|
-
return { ...base,
|
|
94477
|
+
return { ...base, ...options.deps ? {} : { authorize: async (job) => {
|
|
94478
|
+
if (!validAccount()) return false;
|
|
94479
|
+
if (!job.projectDir) return true;
|
|
94480
|
+
const folders2 = await listFolders(registration.machineId);
|
|
94481
|
+
return validAccount() && folders2.ok && folders2.value.folders.some((f2) => f2.project === job.project && f2.path === job.projectDir);
|
|
94482
|
+
} }, runtimes: () => base.runtimes().then(redetected) };
|
|
94144
94483
|
};
|
|
94145
94484
|
const register2 = async () => {
|
|
94146
94485
|
const answer = await register(registration);
|
|
@@ -94155,7 +94494,7 @@ function startRunner(options) {
|
|
|
94155
94494
|
};
|
|
94156
94495
|
const idle2 = () => running.size ? t.running(running.size) : t.connected(registration.machineName);
|
|
94157
94496
|
const schedule = (ms) => {
|
|
94158
|
-
if (closed) return;
|
|
94497
|
+
if (closed || !ownsExecution) return;
|
|
94159
94498
|
if (timer) clearTimeout(timer);
|
|
94160
94499
|
timer = setTimeout(tick, ms);
|
|
94161
94500
|
};
|
|
@@ -94203,9 +94542,14 @@ function startRunner(options) {
|
|
|
94203
94542
|
await close(false);
|
|
94204
94543
|
stop2(s);
|
|
94205
94544
|
};
|
|
94545
|
+
const validAccount = () => readSession()?.subject === account && accountGeneration() === generation;
|
|
94206
94546
|
const tick = async () => {
|
|
94207
|
-
if (!
|
|
94208
|
-
|
|
94547
|
+
if (closed || !ownsExecution) return;
|
|
94548
|
+
if (!validAccount()) return finish2({ reason: "refused", message: "\u8D26\u53F7\u5DF2\u9000\u51FA\u6216\u5207\u6362\u3002" });
|
|
94549
|
+
if (!registration || redetect) {
|
|
94550
|
+
redetect = false;
|
|
94551
|
+
registration = await options.registration();
|
|
94552
|
+
} else {
|
|
94209
94553
|
const was = registration.runtimes;
|
|
94210
94554
|
const runtimes = await refreshModels(was);
|
|
94211
94555
|
if (registration.runtimes === was) registration = { ...registration, runtimes };
|
|
@@ -94283,15 +94627,17 @@ function startRunner(options) {
|
|
|
94283
94627
|
for (const id of attempted) if (!listed2.has(id) && !running.has(id)) attempted.delete(id);
|
|
94284
94628
|
for (const job of list.value.jobs) {
|
|
94285
94629
|
if (closed || preparing) break;
|
|
94286
|
-
if (job.state === "claimed" && !running.has(job.id) && !attempted.has(job.id)) {
|
|
94630
|
+
if ((job.state === "claimed" || job.state === "interrupted") && !running.has(job.id) && (!attempted.has(job.id) || !job.flow && !!(job.chat || job.discussion))) {
|
|
94287
94631
|
const failure = await stopLeftOn(job);
|
|
94288
94632
|
if (closed || preparing) break;
|
|
94289
94633
|
const checkpoint = readCheckpoint(job.id);
|
|
94290
|
-
const
|
|
94634
|
+
const reply = !job.flow && !!(job.chat || job.discussion);
|
|
94635
|
+
const processesStopped2 = reply ? await stopReply(job.id, deps().stopMs) : false;
|
|
94636
|
+
const uncertain = !!checkpoint && (checkpoint.updating || reply) && !checkpoint.completed && (checkpoint.pending.length > 0 || checkpoint.opaque || !job.flow && checkpoint.started && !checkpoint.session);
|
|
94291
94637
|
if (checkpoint?.updating) status(uncertain ? UNCERTAIN : "\u6B63\u5728\u6062\u590D\u66F4\u65B0\u524D\u7684\u4EFB\u52A1\u2026");
|
|
94292
|
-
const reason = failure ?? (uncertain ? UNCERTAIN :
|
|
94293
|
-
const recovered = await finishJob(registration.machineId, job.id, "failed", reason, checkpoint?.session ? { session: checkpoint.session } :
|
|
94294
|
-
if (recovered.ok && reason === UPDATE_REASON) readAgain = true;
|
|
94638
|
+
const reason = failure ?? (checkpoint?.updating ? uncertain ? UNCERTAIN : UPDATE_REASON : "The Runner restarted while this job was running.");
|
|
94639
|
+
const recovered = await finishJob(registration.machineId, job.id, "failed", reason, { ...checkpoint?.session ? { session: checkpoint.session } : {}, ...processesStopped2 ? { processesStopped: true } : {} });
|
|
94640
|
+
if (recovered.ok && (reason === UPDATE_REASON || processesStopped2 && recovered.value.finished)) readAgain = true;
|
|
94295
94641
|
continue;
|
|
94296
94642
|
}
|
|
94297
94643
|
if (job.state !== "waiting" || running.has(job.id)) continue;
|
|
@@ -94381,20 +94727,42 @@ function startRunner(options) {
|
|
|
94381
94727
|
else await Promise.race([stops, new Promise((resolve2) => timeout = setTimeout(resolve2, (options.deps?.stopMs ?? STOP_MS) + 1e3))]);
|
|
94382
94728
|
clearTimeout(timeout);
|
|
94383
94729
|
if (release2 && !lock.waited() && registration) await release(registration.machineId);
|
|
94730
|
+
clearInterval(accountWatch);
|
|
94384
94731
|
lock.release();
|
|
94732
|
+
releaseRecord();
|
|
94385
94733
|
};
|
|
94734
|
+
let refresh2 = "";
|
|
94735
|
+
const accountWatch = setInterval(() => {
|
|
94736
|
+
try {
|
|
94737
|
+
const value = fs36.readFileSync(path39.join(runnerHome(), "settings-refresh"), "utf8");
|
|
94738
|
+
if (value !== refresh2) {
|
|
94739
|
+
refresh2 = value;
|
|
94740
|
+
redetect = true;
|
|
94741
|
+
if (!closed) schedule(0);
|
|
94742
|
+
}
|
|
94743
|
+
} catch {
|
|
94744
|
+
}
|
|
94745
|
+
if (!closed && !validAccount()) void finish2({ reason: "refused", message: "\u8D26\u53F7\u5DF2\u9000\u51FA\u6216\u5207\u6362\u3002" });
|
|
94746
|
+
}, 200);
|
|
94747
|
+
accountWatch.unref();
|
|
94386
94748
|
removeLegacy();
|
|
94387
94749
|
pruneChats();
|
|
94388
|
-
const lock = holdMachine(options.kind, () =>
|
|
94750
|
+
const lock = holdMachine(options.kind, () => {
|
|
94751
|
+
ownsExecution = true;
|
|
94752
|
+
void tick();
|
|
94753
|
+
}, (holder) => {
|
|
94389
94754
|
status(t.waitingHere(holder));
|
|
94390
94755
|
options.onWaiting?.(holder);
|
|
94391
94756
|
});
|
|
94392
|
-
return { stopped: stopped2, close: () => close(true), update: () => close(false, true), renew: () =>
|
|
94757
|
+
return { stopped: stopped2, close: () => close(true), update: () => close(false, true), renew: () => {
|
|
94758
|
+
redetect = true;
|
|
94759
|
+
schedule(0);
|
|
94760
|
+
} };
|
|
94393
94761
|
}
|
|
94394
94762
|
|
|
94395
94763
|
// src/signin.ts
|
|
94396
94764
|
import { spawn as spawn5 } from "node:child_process";
|
|
94397
|
-
import
|
|
94765
|
+
import crypto7 from "node:crypto";
|
|
94398
94766
|
import http from "node:http";
|
|
94399
94767
|
var WAIT_MS = 10 * 60 * 1e3;
|
|
94400
94768
|
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";
|
|
@@ -94419,8 +94787,9 @@ var PAGE = (outcome, lang) => {
|
|
|
94419
94787
|
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>`;
|
|
94420
94788
|
};
|
|
94421
94789
|
async function signIn(options = {}) {
|
|
94422
|
-
const
|
|
94423
|
-
const
|
|
94790
|
+
const generation = accountGeneration();
|
|
94791
|
+
const verifier = base64url(crypto7.randomBytes(32));
|
|
94792
|
+
const challenge = base64url(crypto7.createHash("sha256").update(verifier).digest());
|
|
94424
94793
|
let finish2 = () => {
|
|
94425
94794
|
};
|
|
94426
94795
|
const answered = new Promise((resolve2) => finish2 = resolve2);
|
|
@@ -94435,7 +94804,7 @@ async function signIn(options = {}) {
|
|
|
94435
94804
|
const params = asked.searchParams;
|
|
94436
94805
|
const code = params.get("code");
|
|
94437
94806
|
const error = params.get("error");
|
|
94438
|
-
const failure2 = code ? await exchange(code, verifier) : {
|
|
94807
|
+
const failure2 = code ? await exchange(code, verifier, generation, options.signal) : {
|
|
94439
94808
|
why: error === "access_denied" ? "denied" : "other",
|
|
94440
94809
|
detail: params.get("error_description") || error || "no code came back"
|
|
94441
94810
|
};
|
|
@@ -94465,7 +94834,7 @@ async function signIn(options = {}) {
|
|
|
94465
94834
|
server.close();
|
|
94466
94835
|
return failure;
|
|
94467
94836
|
}
|
|
94468
|
-
async function exchange(code, verifier) {
|
|
94837
|
+
async function exchange(code, verifier, generation, signal2) {
|
|
94469
94838
|
const { supabaseUrl, anonKey } = cloudEndpoints();
|
|
94470
94839
|
let response;
|
|
94471
94840
|
try {
|
|
@@ -94479,6 +94848,7 @@ async function exchange(code, verifier) {
|
|
|
94479
94848
|
}
|
|
94480
94849
|
const session = response.ok ? sessionFrom(await response.json().catch(() => ({}))) : null;
|
|
94481
94850
|
if (!session) return { why: "other", detail: `Cloud answered ${response.status}` };
|
|
94851
|
+
if (signal2?.aborted || accountGeneration() !== generation) return { why: "cancelled", detail: "cancelled" };
|
|
94482
94852
|
writeSession(session);
|
|
94483
94853
|
return null;
|
|
94484
94854
|
}
|
|
@@ -94523,8 +94893,8 @@ async function main() {
|
|
|
94523
94893
|
tell({ type: "update-deferred" });
|
|
94524
94894
|
});
|
|
94525
94895
|
});
|
|
94526
|
-
for (const
|
|
94527
|
-
process.on(
|
|
94896
|
+
for (const signal2 of ["SIGINT", "SIGTERM"]) {
|
|
94897
|
+
process.on(signal2, async () => {
|
|
94528
94898
|
await runner.close();
|
|
94529
94899
|
status(t.stopped());
|
|
94530
94900
|
process.exit(0);
|