wildcrane-runner 0.6.16 → 0.6.18
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 +1385 -1395
- package/dist/akb/package.json +1 -1
- package/dist/launcher.mjs +4912 -31
- package/dist/runner.mjs +1028 -695
- package/package.json +1 -1
package/dist/runner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// wildcrane-runner 0.6.
|
|
1
|
+
// wildcrane-runner 0.6.18 — 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.18" : "0.0.0";
|
|
84442
|
+
var AKB_VERSION = true ? "0.11.16" : "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.16",
|
|
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,30 +87059,49 @@ 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;
|
|
87021
|
-
var gitLimits = { timeoutMs: 3e4 };
|
|
87022
|
-
var GitTimeoutError = class extends Error {
|
|
87023
|
-
};
|
|
87024
|
-
function spawnGit(args, options) {
|
|
87025
|
-
const out = spawnSync2("git", args, {
|
|
87026
|
-
...options,
|
|
87027
|
-
encoding: "utf8",
|
|
87028
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
87029
|
-
timeout: gitLimits.timeoutMs,
|
|
87030
|
-
killSignal: "SIGKILL"
|
|
87031
|
-
});
|
|
87032
|
-
if (out.error?.code === "ETIMEDOUT") throw new GitTimeoutError(`Git ${args[0]} timed out after ${gitLimits.timeoutMs / 1e3}s; the command was killed.`);
|
|
87033
|
-
return out;
|
|
87034
|
-
}
|
|
87035
87099
|
function git(args, cwd = REPO_ROOT) {
|
|
87036
87100
|
try {
|
|
87037
|
-
const out =
|
|
87101
|
+
const out = spawnSync2("git", args, { cwd, encoding: "utf8", maxBuffer: MAX_OUTPUT, windowsHide: true });
|
|
87038
87102
|
if (out.error || out.status !== 0) return null;
|
|
87039
87103
|
return out.stdout;
|
|
87040
|
-
} catch
|
|
87041
|
-
if (error instanceof GitTimeoutError) throw error;
|
|
87104
|
+
} catch {
|
|
87042
87105
|
return null;
|
|
87043
87106
|
}
|
|
87044
87107
|
}
|
|
@@ -87174,10 +87237,15 @@ var CODEX = {
|
|
|
87174
87237
|
forkArgs(argv, resumeId, _sessionId, cwd) {
|
|
87175
87238
|
return [...codexExtraArgs(argv, cwd), "fork", resumeId];
|
|
87176
87239
|
},
|
|
87177
|
-
//
|
|
87178
|
-
// `developer_instructions` in the user's config.toml, which is then left out of board runs.
|
|
87240
|
+
// 自设系统指令保持原样;无法追加时由调用方明确提示。
|
|
87179
87241
|
systemPrompt(text3, argv) {
|
|
87180
|
-
|
|
87242
|
+
if (namesFlag(argv, ["developer_instructions", "model_instructions_file"])) return {};
|
|
87243
|
+
try {
|
|
87244
|
+
const config = fs7.readFileSync(path10.join(process.env.CODEX_HOME || home2(".codex"), "config.toml"), "utf8");
|
|
87245
|
+
if (/^\s*(?:developer_instructions|model_instructions_file)\s*=/m.test(config)) return {};
|
|
87246
|
+
} catch {
|
|
87247
|
+
}
|
|
87248
|
+
return { args: ["-c", `developer_instructions=${JSON.stringify(text3)}`] };
|
|
87181
87249
|
},
|
|
87182
87250
|
// What Codex takes, in the order Claude Code's dialog draws the same four: who pays for
|
|
87183
87251
|
// the run and where it goes, that endpoint's address, the key, a model, and how hard that
|
|
@@ -87305,7 +87373,7 @@ var CODEX = {
|
|
|
87305
87373
|
// No `providerEnv` either: the pick already drops and sets OPENAI_API_KEY, and there is
|
|
87306
87374
|
// no second variable to drop. Codex reads no base URL from the environment — an exported
|
|
87307
87375
|
// OPENAI_BASE_URL moves nothing — and where a run goes is settled on its command line.
|
|
87308
|
-
env: () => (
|
|
87376
|
+
env: () => codexProxyEnv(),
|
|
87309
87377
|
// A completed turn carries its token counts and nothing else. The model comes from the
|
|
87310
87378
|
// session's rollout on disk instead, and the price is worked out from the two
|
|
87311
87379
|
// (agent/wire/codex-stream.ts). A model whose rates the board doesn't know shows no price.
|
|
@@ -87498,9 +87566,9 @@ var DSH = {
|
|
|
87498
87566
|
// dsh-acp's persona IS its system prompt, so the ask is added to the one in effect: the
|
|
87499
87567
|
// user's own `DSH_SYSTEM_PROMPT`, else the bridge's default. A `--persona` on the command
|
|
87500
87568
|
// line outranks both, and is left alone.
|
|
87501
|
-
systemPrompt(text3, argv) {
|
|
87569
|
+
systemPrompt(text3, argv, env2) {
|
|
87502
87570
|
if (namesFlag(argv, ["--persona"])) return {};
|
|
87503
|
-
return { env: { DSH_SYSTEM_PROMPT: `${
|
|
87571
|
+
return { env: { DSH_SYSTEM_PROMPT: `${env2.DSH_SYSTEM_PROMPT || DSH_PERSONA}
|
|
87504
87572
|
|
|
87505
87573
|
${text3}` } };
|
|
87506
87574
|
},
|
|
@@ -87891,12 +87959,12 @@ var OPENCODE = {
|
|
|
87891
87959
|
env: () => ({ ...process.env }),
|
|
87892
87960
|
// `instructions` files join the system prompt, and OpenCode adds this config's list to the
|
|
87893
87961
|
// user's own rather than replacing it.
|
|
87894
|
-
systemPrompt(text3) {
|
|
87962
|
+
systemPrompt(text3, _argv, env2) {
|
|
87895
87963
|
const file2 = machineFile("opencode-language.md", `${text3}
|
|
87896
87964
|
`);
|
|
87897
87965
|
let own = {};
|
|
87898
87966
|
try {
|
|
87899
|
-
own = obj2(JSON.parse(
|
|
87967
|
+
own = obj2(JSON.parse(env2.OPENCODE_CONFIG_CONTENT ?? "{}"));
|
|
87900
87968
|
} catch {
|
|
87901
87969
|
}
|
|
87902
87970
|
const instructions = [...Array.isArray(own.instructions) ? own.instructions : [], file2];
|
|
@@ -88039,26 +88107,18 @@ var HARNESSES = [CLAUDE_CODE, CODEX, CURSOR, OPENCODE, KIMI, DSH, ZCODE, GROK].m
|
|
|
88039
88107
|
var DEFAULT_HARNESS = HARNESSES[0];
|
|
88040
88108
|
checkHarnesses(HARNESSES);
|
|
88041
88109
|
|
|
88110
|
+
// ../cli/src/lib/agent/run-settings.ts
|
|
88111
|
+
import path12 from "node:path";
|
|
88112
|
+
|
|
88042
88113
|
// ../cli/src/lib/agent/env.ts
|
|
88043
88114
|
var RUN_ENV = "KANBAN_RUN";
|
|
88044
88115
|
var SCHEDULED_AGENTS_ENV = "AI4KANBAN_SCHEDULED_AGENTS";
|
|
88116
|
+
var STOP_ENV = "KANBAN_STOP_ID";
|
|
88045
88117
|
var SESSION_VARS = {
|
|
88046
88118
|
"claude-code": "CLAUDE_CODE_SESSION_ID",
|
|
88047
88119
|
codex: "CODEX_THREAD_ID"
|
|
88048
88120
|
};
|
|
88049
88121
|
|
|
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
88122
|
// ../cli/src/lib/agent/providers.ts
|
|
88063
88123
|
function providerSetting(settings) {
|
|
88064
88124
|
return settings.find((s) => s.kind === "provider");
|
|
@@ -88150,11 +88210,34 @@ function effectiveValues(harness, held4) {
|
|
|
88150
88210
|
}
|
|
88151
88211
|
return out;
|
|
88152
88212
|
}
|
|
88153
|
-
function
|
|
88154
|
-
const
|
|
88155
|
-
|
|
88156
|
-
|
|
88157
|
-
|
|
88213
|
+
function languageEnv(given) {
|
|
88214
|
+
const env2 = { ...given };
|
|
88215
|
+
if (env2.DSH_SYSTEM_PROMPT) {
|
|
88216
|
+
const parts = env2.DSH_SYSTEM_PROMPT.split("\n\n");
|
|
88217
|
+
while (isSystemLanguage(parts.at(-1) ?? "")) parts.pop();
|
|
88218
|
+
env2.DSH_SYSTEM_PROMPT = parts.join("\n\n");
|
|
88219
|
+
}
|
|
88220
|
+
try {
|
|
88221
|
+
const config = JSON.parse(env2.OPENCODE_CONFIG_CONTENT ?? "{}");
|
|
88222
|
+
if (Array.isArray(config.instructions)) {
|
|
88223
|
+
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)));
|
|
88224
|
+
env2.OPENCODE_CONFIG_CONTENT = JSON.stringify(config);
|
|
88225
|
+
}
|
|
88226
|
+
} catch {
|
|
88227
|
+
}
|
|
88228
|
+
return env2;
|
|
88229
|
+
}
|
|
88230
|
+
function withSystemLanguage(harness, argv, env2, language) {
|
|
88231
|
+
env2 = languageEnv(env2);
|
|
88232
|
+
const text3 = systemLanguage(language);
|
|
88233
|
+
if (!text3) return { argv, env: env2 };
|
|
88234
|
+
const added = argv.length ? harness.systemPrompt?.(text3, argv, env2) : void 0;
|
|
88235
|
+
if (!added?.args?.length && !Object.keys(added?.env ?? {}).length) {
|
|
88236
|
+
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.";
|
|
88237
|
+
return { argv, env: env2, note };
|
|
88238
|
+
}
|
|
88239
|
+
const at2 = /^node(?:\.exe)?$/.test(path12.basename(argv[0])) && argv[1] && !argv[1].startsWith("-") ? 2 : 1;
|
|
88240
|
+
return { argv: [...argv.slice(0, at2), ...added?.args ?? [], ...argv.slice(at2)], env: { ...env2, ...added?.env } };
|
|
88158
88241
|
}
|
|
88159
88242
|
|
|
88160
88243
|
// src/api.ts
|
|
@@ -88167,6 +88250,7 @@ __export(api_exports, {
|
|
|
88167
88250
|
claimJob: () => claimJob,
|
|
88168
88251
|
commitBoard: () => commitBoard,
|
|
88169
88252
|
createArtifact: () => createArtifact,
|
|
88253
|
+
createProject: () => createProject,
|
|
88170
88254
|
createUpload: () => createUpload,
|
|
88171
88255
|
createVersion: () => createVersion,
|
|
88172
88256
|
dispatchReview: () => dispatchReview,
|
|
@@ -88216,14 +88300,14 @@ __export(api_exports, {
|
|
|
88216
88300
|
|
|
88217
88301
|
// src/goals.ts
|
|
88218
88302
|
import fs9 from "node:fs";
|
|
88219
|
-
import
|
|
88303
|
+
import path13 from "node:path";
|
|
88220
88304
|
function goalsOf(held4) {
|
|
88221
88305
|
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
88306
|
const goals = held4.goals ?? held4.ideas;
|
|
88223
88307
|
if (!Array.isArray(goals)) throw new Error("The goals array is missing or invalid.");
|
|
88224
88308
|
return goals;
|
|
88225
88309
|
}
|
|
88226
|
-
var goalsFileOf = (job) =>
|
|
88310
|
+
var goalsFileOf = (job) => path13.join(runnerHome(), "ideas", `${job.id}.json`);
|
|
88227
88311
|
async function writeGoals(job, list) {
|
|
88228
88312
|
let goals;
|
|
88229
88313
|
try {
|
|
@@ -88240,7 +88324,7 @@ async function writeGoals(job, list) {
|
|
|
88240
88324
|
after = page.value.next;
|
|
88241
88325
|
} while (after);
|
|
88242
88326
|
const file2 = goalsFileOf(job);
|
|
88243
|
-
fs9.mkdirSync(
|
|
88327
|
+
fs9.mkdirSync(path13.dirname(file2), { recursive: true });
|
|
88244
88328
|
fs9.writeFileSync(file2, `${JSON.stringify({ workflows, ideas: goals }, null, 2)}
|
|
88245
88329
|
`);
|
|
88246
88330
|
return { file: file2 };
|
|
@@ -88257,8 +88341,8 @@ function readGoals(file2) {
|
|
|
88257
88341
|
|
|
88258
88342
|
// src/secrets.ts
|
|
88259
88343
|
import fs10 from "node:fs";
|
|
88260
|
-
import
|
|
88261
|
-
var file = () =>
|
|
88344
|
+
import path14 from "node:path";
|
|
88345
|
+
var file = () => path14.join(runnerHome(), "secrets.json");
|
|
88262
88346
|
function readAll() {
|
|
88263
88347
|
try {
|
|
88264
88348
|
const held4 = JSON.parse(fs10.readFileSync(file(), "utf8"));
|
|
@@ -88287,10 +88371,10 @@ var secretsSet = () => Object.fromEntries(Object.entries(readAll()).map(([id, ke
|
|
|
88287
88371
|
|
|
88288
88372
|
// src/api.ts
|
|
88289
88373
|
var RUNTIMES = ["claude-code", "codex", "cursor", "opencode", "kimi", "dsh", "zcode", "grok"];
|
|
88290
|
-
var PROTOCOL =
|
|
88374
|
+
var PROTOCOL = 15;
|
|
88291
88375
|
var TIMEOUT_MS = 2e4;
|
|
88292
|
-
async function send(method, route, body, signedIn, ms, type) {
|
|
88293
|
-
const headers = { accept: "application/json" };
|
|
88376
|
+
async function send(method, route, body, signedIn, ms, type, extra = {}) {
|
|
88377
|
+
const headers = { accept: "application/json", ...extra };
|
|
88294
88378
|
if (signedIn) {
|
|
88295
88379
|
const token = await accessToken();
|
|
88296
88380
|
if (!token.ok) {
|
|
@@ -88374,7 +88458,11 @@ var listFolders = (machineId2) => request("GET", `/v1/runner/folders?machine=${q
|
|
|
88374
88458
|
var listElsewhere = (machineId2) => request("GET", `/v1/runner/folders?machine=${q(machineId2)}&elsewhere=1`);
|
|
88375
88459
|
var listMachineTasks = (machineId2) => request("GET", `/v1/runner/tasks?machine=${q(machineId2)}`);
|
|
88376
88460
|
var stopTask = (task, how) => request("POST", how === "chat" ? `/v1/tasks/${q(task)}/chat/stop` : `/v1/tasks/${q(task)}/stop`, {});
|
|
88377
|
-
var addFolder = (machineId2, name,
|
|
88461
|
+
var addFolder = (machineId2, name, path40, project) => request("POST", "/v1/runner/folders", { machineId: machineId2, name, path: path40, ...project ? { project } : {} });
|
|
88462
|
+
async function createProject(name, workspace, key) {
|
|
88463
|
+
const sent = await send("POST", "/v1/projects", { name, workspace }, true, TIMEOUT_MS, void 0, { "idempotency-key": key });
|
|
88464
|
+
return sent.ok ? answerOf(sent.value) : sent;
|
|
88465
|
+
}
|
|
88378
88466
|
var removeFolder = (machineId2, project) => request("POST", `/v1/runner/folders/${q(project)}/remove`, { machineId: machineId2 });
|
|
88379
88467
|
var readBoard = (project, since) => request("GET", `/v1/projects/${q(project)}/board${since === null ? "" : `?since=${since}`}`);
|
|
88380
88468
|
async function commitBoard(project, job, machine, files) {
|
|
@@ -88448,7 +88536,7 @@ function commandOf(harness) {
|
|
|
88448
88536
|
const [binary, ...flags] = splitCommand(harness.command);
|
|
88449
88537
|
return [spawnName(chooseCopy(harness, SPAWN_MS), binary), ...flags];
|
|
88450
88538
|
}
|
|
88451
|
-
function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false,
|
|
88539
|
+
function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, language = null) {
|
|
88452
88540
|
const harness = HARNESSES2[runtime];
|
|
88453
88541
|
const values = held(runtime, model, given);
|
|
88454
88542
|
const [binary, ...flags] = commandOf(harness);
|
|
@@ -88457,21 +88545,22 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88457
88545
|
const copied = fork && resume && harness.forkArgs ? harness.forkArgs(base, resume, id, cwd) : null;
|
|
88458
88546
|
if (fork) resume = null;
|
|
88459
88547
|
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" }),
|
|
88548
|
+
const quiet = (line) => harness.quietStderr?.(line) ?? false;
|
|
88549
|
+
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
88550
|
if (harness.client) {
|
|
88463
88551
|
const client = harness.client(effectiveValues(harness, values));
|
|
88464
88552
|
let session;
|
|
88465
88553
|
let named2;
|
|
88466
88554
|
return {
|
|
88555
|
+
startNote: note,
|
|
88467
88556
|
command: argv[0],
|
|
88468
88557
|
args: argv.slice(1),
|
|
88469
88558
|
env: env2,
|
|
88470
|
-
converse: (child, event2) => client.turn({
|
|
88559
|
+
converse: (child, event2, restart = true) => client.turn({
|
|
88471
88560
|
stdout: child.stdout,
|
|
88472
88561
|
stdin: child.stdin,
|
|
88473
88562
|
prompt,
|
|
88474
|
-
restartPrompt: prompt,
|
|
88563
|
+
restartPrompt: restart ? prompt : void 0,
|
|
88475
88564
|
cwd,
|
|
88476
88565
|
resumeId: resume ?? void 0,
|
|
88477
88566
|
log: () => {
|
|
@@ -88490,6 +88579,7 @@ function plan(runtime, prompt, cwd, resume, model, given = {}, fork = false, lin
|
|
|
88490
88579
|
const renderer = harness.renderer(cwd, argv[0], argv);
|
|
88491
88580
|
const toStdin = harness.stdinPrompt?.(argv);
|
|
88492
88581
|
return {
|
|
88582
|
+
startNote: note,
|
|
88493
88583
|
command: argv[0],
|
|
88494
88584
|
args: [...argv.slice(1), ...toStdin ? [] : [prompt]],
|
|
88495
88585
|
env: env2,
|
|
@@ -88541,14 +88631,14 @@ var listed = (harness) => async () => (harness.models?.() ?? []).map((id) => ({
|
|
|
88541
88631
|
var readModels = (name) => (MODELS[name] ?? listed(HARNESSES2[name]))().catch(() => []);
|
|
88542
88632
|
var MODELS = {
|
|
88543
88633
|
"claude-code": async () => {
|
|
88544
|
-
const cached2 = claudeModels(
|
|
88634
|
+
const cached2 = claudeModels(path15.join(process.env.CLAUDE_CONFIG_DIR || path15.join(os4.homedir(), ".claude"), "cache", "model-catalog"));
|
|
88545
88635
|
return cached2.length ? cached2 : [
|
|
88546
88636
|
{ id: "opus", name: "Opus" },
|
|
88547
88637
|
{ id: "sonnet", name: "Sonnet" },
|
|
88548
88638
|
{ id: "haiku", name: "Haiku" }
|
|
88549
88639
|
];
|
|
88550
88640
|
},
|
|
88551
|
-
codex: async () => codexModels(
|
|
88641
|
+
codex: async () => codexModels(path15.join(process.env.CODEX_HOME || path15.join(os4.homedir(), ".codex"), "models_cache.json")),
|
|
88552
88642
|
opencode: async () => opencodeModels(await output(commandOf(HARNESSES2.opencode)[0], ["models"])),
|
|
88553
88643
|
cursor: () => cursorModels()
|
|
88554
88644
|
};
|
|
@@ -88620,7 +88710,7 @@ function claudeModels(dir) {
|
|
|
88620
88710
|
}
|
|
88621
88711
|
const catalogs = files.flatMap((f2) => {
|
|
88622
88712
|
try {
|
|
88623
|
-
const data = obj(JSON.parse(fs11.readFileSync(
|
|
88713
|
+
const data = obj(JSON.parse(fs11.readFileSync(path15.join(dir, f2), "utf8")));
|
|
88624
88714
|
const catalog = obj(data.catalog);
|
|
88625
88715
|
const surface = str(catalog.surface);
|
|
88626
88716
|
return surface === "cc" || surface === "ccd" ? [{ surface, at: Number(data.fetchedAt) || 0, config: obj(catalog.config) }] : [];
|
|
@@ -88812,6 +88902,114 @@ function connectCloudLive(handlers) {
|
|
|
88812
88902
|
};
|
|
88813
88903
|
}
|
|
88814
88904
|
|
|
88905
|
+
// src/folders.ts
|
|
88906
|
+
import fs12 from "node:fs";
|
|
88907
|
+
import path16 from "node:path";
|
|
88908
|
+
var projectsFile = () => path16.join(runnerHome(), "projects.json");
|
|
88909
|
+
function realpath(p2) {
|
|
88910
|
+
try {
|
|
88911
|
+
return fs12.realpathSync(p2);
|
|
88912
|
+
} catch {
|
|
88913
|
+
return null;
|
|
88914
|
+
}
|
|
88915
|
+
}
|
|
88916
|
+
function readGrants() {
|
|
88917
|
+
try {
|
|
88918
|
+
const held4 = JSON.parse(fs12.readFileSync(projectsFile(), "utf8"));
|
|
88919
|
+
if (!Array.isArray(held4.projects)) throw new Error("invalid_projects");
|
|
88920
|
+
return held4;
|
|
88921
|
+
} catch (error) {
|
|
88922
|
+
if (error.code === "ENOENT") return { projects: [] };
|
|
88923
|
+
throw error;
|
|
88924
|
+
}
|
|
88925
|
+
}
|
|
88926
|
+
function listOf(held4) {
|
|
88927
|
+
const subject = readSession()?.subject;
|
|
88928
|
+
if (!held4.accounts) return held4.projects;
|
|
88929
|
+
return subject ? held4.accounts[subject] ?? [] : [];
|
|
88930
|
+
}
|
|
88931
|
+
function update2(change) {
|
|
88932
|
+
fs12.mkdirSync(runnerHome(), { recursive: true, mode: 448 });
|
|
88933
|
+
const lock = `${projectsFile()}.lock`;
|
|
88934
|
+
let fd;
|
|
88935
|
+
const until = Date.now() + 2e3;
|
|
88936
|
+
for (; ; ) {
|
|
88937
|
+
try {
|
|
88938
|
+
fd = fs12.openSync(lock, "wx", 384);
|
|
88939
|
+
fs12.writeFileSync(fd, String(process.pid));
|
|
88940
|
+
break;
|
|
88941
|
+
} catch {
|
|
88942
|
+
try {
|
|
88943
|
+
const pid = Number(fs12.readFileSync(lock, "utf8"));
|
|
88944
|
+
if (pid > 0) {
|
|
88945
|
+
try {
|
|
88946
|
+
process.kill(pid, 0);
|
|
88947
|
+
} catch {
|
|
88948
|
+
fs12.rmSync(lock, { force: true });
|
|
88949
|
+
}
|
|
88950
|
+
}
|
|
88951
|
+
} catch {
|
|
88952
|
+
}
|
|
88953
|
+
if (Date.now() > until) throw new Error("authorization_busy");
|
|
88954
|
+
Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, 10);
|
|
88955
|
+
}
|
|
88956
|
+
}
|
|
88957
|
+
try {
|
|
88958
|
+
const held4 = readGrants();
|
|
88959
|
+
const subject = readSession()?.subject;
|
|
88960
|
+
const before = listOf(held4);
|
|
88961
|
+
const after = [...new Set(change(before))];
|
|
88962
|
+
if (subject) {
|
|
88963
|
+
if (!held4.accounts) {
|
|
88964
|
+
held4.accounts = { [subject]: held4.projects };
|
|
88965
|
+
held4.legacyOwner = subject;
|
|
88966
|
+
}
|
|
88967
|
+
held4.accounts[subject] = after;
|
|
88968
|
+
held4.projects = after;
|
|
88969
|
+
} else held4.projects = after;
|
|
88970
|
+
const tmp = `${projectsFile()}.${process.pid}.tmp`;
|
|
88971
|
+
fs12.writeFileSync(tmp, `${JSON.stringify(held4, null, 2)}
|
|
88972
|
+
`, { mode: 384 });
|
|
88973
|
+
fs12.renameSync(tmp, projectsFile());
|
|
88974
|
+
return before.filter((p2) => !after.includes(p2));
|
|
88975
|
+
} finally {
|
|
88976
|
+
fs12.closeSync(fd);
|
|
88977
|
+
fs12.rmSync(lock, { force: true });
|
|
88978
|
+
}
|
|
88979
|
+
}
|
|
88980
|
+
function adoptLegacy() {
|
|
88981
|
+
if (readSession() && !readGrants().accounts) update2((list) => list);
|
|
88982
|
+
}
|
|
88983
|
+
function allowedProjects() {
|
|
88984
|
+
return listOf(readGrants()).flatMap((p2) => {
|
|
88985
|
+
const real = realpath(p2);
|
|
88986
|
+
return real && fs12.statSync(real).isDirectory() ? [real] : [];
|
|
88987
|
+
});
|
|
88988
|
+
}
|
|
88989
|
+
|
|
88990
|
+
// src/connect.ts
|
|
88991
|
+
import fs36 from "node:fs";
|
|
88992
|
+
import path39 from "node:path";
|
|
88993
|
+
|
|
88994
|
+
// src/settings-control.ts
|
|
88995
|
+
import fs13 from "node:fs";
|
|
88996
|
+
import path17 from "node:path";
|
|
88997
|
+
var directory = () => path17.join(runnerHome(), "executors");
|
|
88998
|
+
var epochFile = () => path17.join(runnerHome(), "account-generation");
|
|
88999
|
+
function accountGeneration() {
|
|
89000
|
+
try {
|
|
89001
|
+
return fs13.readFileSync(epochFile(), "utf8");
|
|
89002
|
+
} catch {
|
|
89003
|
+
return "";
|
|
89004
|
+
}
|
|
89005
|
+
}
|
|
89006
|
+
function executorRecord() {
|
|
89007
|
+
fs13.mkdirSync(directory(), { recursive: true, mode: 448 });
|
|
89008
|
+
const file2 = path17.join(directory(), `${process.pid}.json`);
|
|
89009
|
+
fs13.writeFileSync(file2, "{}", { mode: 384 });
|
|
89010
|
+
return () => fs13.rmSync(file2, { force: true });
|
|
89011
|
+
}
|
|
89012
|
+
|
|
88815
89013
|
// ../cli/src/lib/cadence.ts
|
|
88816
89014
|
var AUTO_CADENCE = "auto";
|
|
88817
89015
|
var isAuto = (cadence) => cadence.trim().toLowerCase() === AUTO_CADENCE;
|
|
@@ -88927,48 +89125,48 @@ async function askDueAgents(machineId2, now = Date.now()) {
|
|
|
88927
89125
|
|
|
88928
89126
|
// src/akb-version.ts
|
|
88929
89127
|
import { execFile } from "node:child_process";
|
|
88930
|
-
import
|
|
88931
|
-
import
|
|
89128
|
+
import fs17 from "node:fs";
|
|
89129
|
+
import path21 from "node:path";
|
|
88932
89130
|
|
|
88933
89131
|
// src/akb.ts
|
|
88934
89132
|
import { spawn as spawn3 } from "node:child_process";
|
|
88935
|
-
import
|
|
88936
|
-
import
|
|
89133
|
+
import fs14 from "node:fs";
|
|
89134
|
+
import path18 from "node:path";
|
|
88937
89135
|
import { fileURLToPath } from "node:url";
|
|
88938
|
-
var akbHome = () =>
|
|
89136
|
+
var akbHome = () => path18.join(runnerHome(), "bin", "akb");
|
|
88939
89137
|
var BUNDLED_SHIM = `bundled-${AKB_VERSION}`;
|
|
88940
89138
|
var bundledAkb = () => ({
|
|
88941
89139
|
command: process.execPath,
|
|
88942
|
-
args: [
|
|
89140
|
+
args: [path18.join(path18.dirname(fileURLToPath(import.meta.url)), "akb", "bin", "ai4kanban.mjs")],
|
|
88943
89141
|
version: AKB_VERSION,
|
|
88944
|
-
shim:
|
|
89142
|
+
shim: path18.join(akbHome(), BUNDLED_SHIM)
|
|
88945
89143
|
});
|
|
88946
89144
|
var quote = (s) => /^[\w./:@=-]+$/.test(s) ? s : `"${s}"`;
|
|
88947
89145
|
function shimDir(akb) {
|
|
88948
89146
|
const dir = akb.shim;
|
|
88949
89147
|
const line = [akb.command, ...akb.args].map(quote).join(" ");
|
|
88950
|
-
const [file2, text3] = process.platform === "win32" ? [
|
|
88951
|
-
`] : [
|
|
89148
|
+
const [file2, text3] = process.platform === "win32" ? [path18.join(dir, "akb.cmd"), `@${line} %*\r
|
|
89149
|
+
`] : [path18.join(dir, "akb"), `#!/bin/sh
|
|
88952
89150
|
exec ${line} "$@"
|
|
88953
89151
|
`];
|
|
88954
89152
|
try {
|
|
88955
|
-
if (
|
|
89153
|
+
if (fs14.readFileSync(file2, "utf8") === text3) return dir;
|
|
88956
89154
|
} catch {
|
|
88957
89155
|
}
|
|
88958
|
-
|
|
88959
|
-
|
|
89156
|
+
fs14.mkdirSync(dir, { recursive: true });
|
|
89157
|
+
fs14.writeFileSync(file2, text3, { mode: 493 });
|
|
88960
89158
|
return dir;
|
|
88961
89159
|
}
|
|
88962
|
-
function akbEnv(akb, board, task,
|
|
89160
|
+
function akbEnv(akb, board, task, language, base = process.env) {
|
|
88963
89161
|
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(
|
|
89162
|
+
const dropped = ["AI4KANBAN_BOARD", "AI4KANBAN_TASK", "AI4KANBAN_EXECUTION", LANGUAGE_ENV, LANGUAGE_LINE_ENV, SCHEDULED_AGENTS_ENV];
|
|
89163
|
+
for (const [k, v2] of Object.entries(base)) if (!k.startsWith("KANBAN_") && !dropped.includes(k)) env2[k] = v2;
|
|
88966
89164
|
const key = Object.keys(env2).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
88967
|
-
env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(
|
|
89165
|
+
env2[key] = [shimDir(akb), env2[key]].filter(Boolean).join(path18.delimiter);
|
|
88968
89166
|
env2.AI4KANBAN_COMMAND = "akb";
|
|
88969
89167
|
if (board) env2.AI4KANBAN_BOARD = board;
|
|
88970
89168
|
if (task) env2.AI4KANBAN_TASK = task;
|
|
88971
|
-
if (
|
|
89169
|
+
if (language !== void 0) env2[LANGUAGE_ENV] = language ?? "";
|
|
88972
89170
|
return env2;
|
|
88973
89171
|
}
|
|
88974
89172
|
var KEEP = 256 * 1024;
|
|
@@ -88982,7 +89180,7 @@ function runAkb(akb, args, opts) {
|
|
|
88982
89180
|
};
|
|
88983
89181
|
let child;
|
|
88984
89182
|
try {
|
|
88985
|
-
child = spawn3(akb.command, [...akb.args, ...args], { cwd: opts.cwd, env: { ...akbEnv(akb, opts.board, opts.task, opts.
|
|
89183
|
+
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
89184
|
} catch (e2) {
|
|
88987
89185
|
return resolve2({ code: null, out: "", last: e2 instanceof Error ? e2.message : String(e2) });
|
|
88988
89186
|
}
|
|
@@ -89013,65 +89211,45 @@ function answerOf2(ran) {
|
|
|
89013
89211
|
|
|
89014
89212
|
// src/cache.ts
|
|
89015
89213
|
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
|
|
89214
|
+
import crypto2 from "node:crypto";
|
|
89215
|
+
import fs15 from "node:fs";
|
|
89216
|
+
import path19 from "node:path";
|
|
89043
89217
|
var IDLE_MS = 7 * 24 * 60 * 6e4;
|
|
89044
89218
|
var SWEEP_MS = 24 * 60 * 6e4;
|
|
89045
89219
|
var PROJECT_ID = /^[\w-]{1,100}$/;
|
|
89046
|
-
var cacheRoot = () =>
|
|
89220
|
+
var cacheRoot = () => path19.join(runnerHome(), "cache");
|
|
89047
89221
|
function cacheDir(project) {
|
|
89048
89222
|
if (!PROJECT_ID.test(project)) throw new Error("This job names no project.");
|
|
89049
|
-
return
|
|
89223
|
+
return path19.join(cacheRoot(), project);
|
|
89050
89224
|
}
|
|
89051
|
-
var akbDir = (dir) =>
|
|
89052
|
-
var usedFile = (dir) =>
|
|
89053
|
-
var unsentFile = (dir) =>
|
|
89225
|
+
var akbDir = (dir) => path19.join(dir, ".akb");
|
|
89226
|
+
var usedFile = (dir) => path19.join(akbDir(dir), "used.json");
|
|
89227
|
+
var unsentFile = (dir) => path19.join(akbDir(dir), "unsent");
|
|
89054
89228
|
function markUsed(dir, at2 = Date.now()) {
|
|
89055
|
-
|
|
89056
|
-
|
|
89229
|
+
fs15.mkdirSync(akbDir(dir), { recursive: true });
|
|
89230
|
+
fs15.writeFileSync(usedFile(dir), `${JSON.stringify({ at: at2 })}
|
|
89057
89231
|
`);
|
|
89058
89232
|
}
|
|
89059
89233
|
function usedAt(dir) {
|
|
89060
89234
|
try {
|
|
89061
|
-
const at2 = JSON.parse(
|
|
89235
|
+
const at2 = JSON.parse(fs15.readFileSync(usedFile(dir), "utf8")).at;
|
|
89062
89236
|
return typeof at2 === "number" ? at2 : null;
|
|
89063
89237
|
} catch {
|
|
89064
89238
|
return null;
|
|
89065
89239
|
}
|
|
89066
89240
|
}
|
|
89067
|
-
var unsent = (dir) =>
|
|
89241
|
+
var unsent = (dir) => fs15.existsSync(unsentFile(dir));
|
|
89068
89242
|
function markUnsent(dir, unsent2) {
|
|
89069
|
-
if (!unsent2) return void
|
|
89070
|
-
|
|
89071
|
-
|
|
89243
|
+
if (!unsent2) return void fs15.rmSync(unsentFile(dir), { force: true });
|
|
89244
|
+
fs15.mkdirSync(akbDir(dir), { recursive: true });
|
|
89245
|
+
fs15.writeFileSync(unsentFile(dir), "");
|
|
89072
89246
|
}
|
|
89073
89247
|
var holds = /* @__PURE__ */ new Map();
|
|
89248
|
+
var holdsDir = () => path19.join(runnerHome(), "holds");
|
|
89249
|
+
var holdFile = (dir) => path19.join(holdsDir(), `${crypto2.createHash("sha256").update(dir).digest("hex")}.${process.pid}`);
|
|
89074
89250
|
function hold(dir) {
|
|
89251
|
+
fs15.mkdirSync(holdsDir(), { recursive: true, mode: 448 });
|
|
89252
|
+
fs15.writeFileSync(holdFile(dir), "", { mode: 384 });
|
|
89075
89253
|
holds.set(dir, (holds.get(dir) ?? 0) + 1);
|
|
89076
89254
|
let held4 = true;
|
|
89077
89255
|
return () => {
|
|
@@ -89079,30 +89257,49 @@ function hold(dir) {
|
|
|
89079
89257
|
held4 = false;
|
|
89080
89258
|
const left = holds.get(dir) - 1;
|
|
89081
89259
|
if (left) holds.set(dir, left);
|
|
89082
|
-
else
|
|
89260
|
+
else {
|
|
89261
|
+
holds.delete(dir);
|
|
89262
|
+
fs15.rmSync(holdFile(dir), { force: true });
|
|
89263
|
+
}
|
|
89083
89264
|
};
|
|
89084
89265
|
}
|
|
89085
89266
|
function paused(dir) {
|
|
89086
89267
|
try {
|
|
89087
|
-
const file2 =
|
|
89088
|
-
const held4 = JSON.parse(
|
|
89268
|
+
const file2 = path19.join(projectStateDir(path19.join(akbDir(dir), "kanban")), SESSIONS_FILE);
|
|
89269
|
+
const held4 = JSON.parse(fs15.readFileSync(file2, "utf8"));
|
|
89089
89270
|
return (held4.deliveries ?? []).some((d2) => d2.status === "active");
|
|
89090
89271
|
} catch {
|
|
89091
89272
|
return false;
|
|
89092
89273
|
}
|
|
89093
89274
|
}
|
|
89094
|
-
|
|
89275
|
+
function busy(dir) {
|
|
89276
|
+
if (holds.has(dir)) return true;
|
|
89277
|
+
const prefix = path19.basename(holdFile(dir)).split(".")[0] + ".";
|
|
89278
|
+
try {
|
|
89279
|
+
return fs15.readdirSync(holdsDir()).filter((file2) => file2.startsWith(prefix)).some((file2) => {
|
|
89280
|
+
try {
|
|
89281
|
+
process.kill(Number(file2.split(".")[1]), 0);
|
|
89282
|
+
return true;
|
|
89283
|
+
} catch {
|
|
89284
|
+
fs15.rmSync(path19.join(holdsDir(), file2), { force: true });
|
|
89285
|
+
return false;
|
|
89286
|
+
}
|
|
89287
|
+
});
|
|
89288
|
+
} catch {
|
|
89289
|
+
return false;
|
|
89290
|
+
}
|
|
89291
|
+
}
|
|
89095
89292
|
var kept2 = (dir) => busy(dir) || unsent(dir) || paused(dir);
|
|
89096
89293
|
function clearAkb(dir) {
|
|
89097
89294
|
dir = realpath2(dir);
|
|
89098
89295
|
if (kept2(dir)) return false;
|
|
89099
89296
|
let entries;
|
|
89100
89297
|
try {
|
|
89101
|
-
entries =
|
|
89298
|
+
entries = fs15.readdirSync(akbDir(dir));
|
|
89102
89299
|
} catch {
|
|
89103
89300
|
return true;
|
|
89104
89301
|
}
|
|
89105
|
-
for (const name of entries)
|
|
89302
|
+
for (const name of entries) fs15.rmSync(path19.join(akbDir(dir), name), { recursive: true, force: true });
|
|
89106
89303
|
spawnSync3("git", ["-C", dir, "worktree", "prune"], { stdio: "ignore" });
|
|
89107
89304
|
return true;
|
|
89108
89305
|
}
|
|
@@ -89117,7 +89314,7 @@ async function readAccess(machineId2) {
|
|
|
89117
89314
|
}
|
|
89118
89315
|
function realpath2(p2) {
|
|
89119
89316
|
try {
|
|
89120
|
-
return
|
|
89317
|
+
return fs15.realpathSync(p2);
|
|
89121
89318
|
} catch {
|
|
89122
89319
|
return p2;
|
|
89123
89320
|
}
|
|
@@ -89132,22 +89329,22 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89132
89329
|
const swept = [];
|
|
89133
89330
|
let cached2 = [];
|
|
89134
89331
|
try {
|
|
89135
|
-
cached2 =
|
|
89332
|
+
cached2 = fs15.readdirSync(cacheRoot(), { withFileTypes: true });
|
|
89136
89333
|
} catch {
|
|
89137
89334
|
}
|
|
89138
89335
|
for (const e2 of cached2) {
|
|
89139
|
-
const dir =
|
|
89336
|
+
const dir = path19.join(cacheRoot(), e2.name);
|
|
89140
89337
|
if (!e2.isDirectory() || kept2(dir)) continue;
|
|
89141
89338
|
const gone = access && !access.projects.has(e2.name);
|
|
89142
89339
|
if (idle(dir, now) || gone) {
|
|
89143
|
-
|
|
89340
|
+
fs15.rmSync(dir, { recursive: true, force: true });
|
|
89144
89341
|
swept.push(dir);
|
|
89145
89342
|
}
|
|
89146
89343
|
}
|
|
89147
89344
|
for (const dir of allowedProjects()) {
|
|
89148
89345
|
let held4 = [];
|
|
89149
89346
|
try {
|
|
89150
|
-
held4 =
|
|
89347
|
+
held4 = fs15.readdirSync(akbDir(dir));
|
|
89151
89348
|
} catch {
|
|
89152
89349
|
}
|
|
89153
89350
|
if (!held4.length) continue;
|
|
@@ -89158,31 +89355,31 @@ async function sweepCache(machineId2, now = Date.now()) {
|
|
|
89158
89355
|
}
|
|
89159
89356
|
function removeLegacy() {
|
|
89160
89357
|
const home4 = runnerHome();
|
|
89161
|
-
for (const name of ["boards", "akb-bin"])
|
|
89358
|
+
for (const name of ["boards", "akb-bin"]) fs15.rmSync(path19.join(home4, name), { recursive: true, force: true });
|
|
89162
89359
|
let entries = [];
|
|
89163
89360
|
try {
|
|
89164
|
-
entries =
|
|
89361
|
+
entries = fs15.readdirSync(home4, { withFileTypes: true });
|
|
89165
89362
|
} catch {
|
|
89166
89363
|
return;
|
|
89167
89364
|
}
|
|
89168
89365
|
for (const e2 of entries) {
|
|
89169
|
-
const account =
|
|
89170
|
-
if (!e2.isDirectory() || !
|
|
89171
|
-
|
|
89172
|
-
if (!
|
|
89366
|
+
const account = path19.join(home4, e2.name);
|
|
89367
|
+
if (!e2.isDirectory() || !fs15.existsSync(path19.join(account, "unfiled"))) continue;
|
|
89368
|
+
fs15.rmSync(path19.join(account, "unfiled"), { recursive: true, force: true });
|
|
89369
|
+
if (!fs15.readdirSync(account).length) fs15.rmdirSync(account);
|
|
89173
89370
|
}
|
|
89174
89371
|
}
|
|
89175
89372
|
|
|
89176
89373
|
// src/update.ts
|
|
89177
|
-
import
|
|
89178
|
-
import
|
|
89179
|
-
import
|
|
89374
|
+
import crypto3 from "node:crypto";
|
|
89375
|
+
import fs16 from "node:fs";
|
|
89376
|
+
import path20 from "node:path";
|
|
89180
89377
|
import zlib from "node:zlib";
|
|
89181
89378
|
var TIMEOUT_MS2 = 6e4;
|
|
89182
89379
|
var registry = () => (process.env.npm_config_registry || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
89183
89380
|
async function installPackage(pkg, version, nodeVersion = process.versions.node) {
|
|
89184
89381
|
const dir = pkg.dirOf(version);
|
|
89185
|
-
if (
|
|
89382
|
+
if (fs16.existsSync(pkg.entryOf(dir))) return { ok: true, dir };
|
|
89186
89383
|
let meta;
|
|
89187
89384
|
let tarball;
|
|
89188
89385
|
try {
|
|
@@ -89199,17 +89396,17 @@ async function installPackage(pkg, version, nodeVersion = process.versions.node)
|
|
|
89199
89396
|
return { ok: false, why: "unreachable", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89200
89397
|
}
|
|
89201
89398
|
const expected = /^sha512-(.+)$/.exec(meta.dist.integrity ?? "")?.[1];
|
|
89202
|
-
const actual =
|
|
89399
|
+
const actual = crypto3.createHash("sha512").update(tarball).digest("base64");
|
|
89203
89400
|
if (!expected || expected !== actual) return { ok: false, why: "integrity", detail: "sha512 mismatch" };
|
|
89204
89401
|
const staging = `${dir}.${process.pid}.tmp`;
|
|
89205
89402
|
try {
|
|
89206
|
-
|
|
89403
|
+
fs16.rmSync(staging, { recursive: true, force: true });
|
|
89207
89404
|
extract(zlib.gunzipSync(tarball), staging);
|
|
89208
|
-
if (!
|
|
89209
|
-
|
|
89210
|
-
|
|
89405
|
+
if (!fs16.existsSync(pkg.entryOf(staging))) throw new Error(`the package carries no ${path20.relative(staging, pkg.entryOf(staging))}`);
|
|
89406
|
+
fs16.rmSync(dir, { recursive: true, force: true });
|
|
89407
|
+
fs16.renameSync(staging, dir);
|
|
89211
89408
|
} catch (e2) {
|
|
89212
|
-
|
|
89409
|
+
fs16.rmSync(staging, { recursive: true, force: true });
|
|
89213
89410
|
return { ok: false, why: "integrity", detail: e2 instanceof Error ? e2.message : String(e2) };
|
|
89214
89411
|
}
|
|
89215
89412
|
return { ok: true, dir };
|
|
@@ -89239,12 +89436,12 @@ function extract(tar, into) {
|
|
|
89239
89436
|
if (type !== "0" && type !== "5") continue;
|
|
89240
89437
|
const relative = name.replace(/^[^/]+\//, "");
|
|
89241
89438
|
if (!relative) continue;
|
|
89242
|
-
const target =
|
|
89243
|
-
if (!target.startsWith(
|
|
89244
|
-
if (type === "5")
|
|
89439
|
+
const target = path20.resolve(into, relative);
|
|
89440
|
+
if (!target.startsWith(path20.resolve(into) + path20.sep)) throw new Error(`refusing ${name}`);
|
|
89441
|
+
if (type === "5") fs16.mkdirSync(target, { recursive: true });
|
|
89245
89442
|
else {
|
|
89246
|
-
|
|
89247
|
-
|
|
89443
|
+
fs16.mkdirSync(path20.dirname(target), { recursive: true });
|
|
89444
|
+
fs16.writeFileSync(target, body);
|
|
89248
89445
|
}
|
|
89249
89446
|
}
|
|
89250
89447
|
}
|
|
@@ -89292,33 +89489,33 @@ function meets(version, comparator) {
|
|
|
89292
89489
|
// src/akb-version.ts
|
|
89293
89490
|
var CHECK_MS2 = 1e4;
|
|
89294
89491
|
var VERSION2 = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
|
|
89295
|
-
var stateFile = () =>
|
|
89296
|
-
var akbVersionDir = (version) =>
|
|
89297
|
-
var entryOf = (dir) =>
|
|
89492
|
+
var stateFile = () => path21.join(akbHome(), "state.json");
|
|
89493
|
+
var akbVersionDir = (version) => path21.join(akbHome(), version);
|
|
89494
|
+
var entryOf = (dir) => path21.join(dir, "bin", "ai4kanban.mjs");
|
|
89298
89495
|
var AKB = { name: "wildcrane", dirOf: akbVersionDir, entryOf };
|
|
89299
89496
|
function readAkbState() {
|
|
89300
89497
|
try {
|
|
89301
|
-
const held4 = JSON.parse(
|
|
89498
|
+
const held4 = JSON.parse(fs17.readFileSync(stateFile(), "utf8"));
|
|
89302
89499
|
return { current: held4.current ?? null, bad: held4.bad ?? [] };
|
|
89303
89500
|
} catch {
|
|
89304
89501
|
return { current: null, bad: [] };
|
|
89305
89502
|
}
|
|
89306
89503
|
}
|
|
89307
89504
|
function writeAkbState(state) {
|
|
89308
|
-
|
|
89505
|
+
fs17.mkdirSync(akbHome(), { recursive: true });
|
|
89309
89506
|
const staging = `${stateFile()}.${process.pid}.tmp`;
|
|
89310
|
-
|
|
89507
|
+
fs17.writeFileSync(staging, `${JSON.stringify(state, null, 2)}
|
|
89311
89508
|
`);
|
|
89312
|
-
|
|
89509
|
+
fs17.renameSync(staging, stateFile());
|
|
89313
89510
|
}
|
|
89314
89511
|
function contractOf(dir) {
|
|
89315
89512
|
try {
|
|
89316
|
-
return JSON.parse(
|
|
89513
|
+
return JSON.parse(fs17.readFileSync(path21.join(dir, "package.json"), "utf8")).akbContract ?? null;
|
|
89317
89514
|
} catch {
|
|
89318
89515
|
return null;
|
|
89319
89516
|
}
|
|
89320
89517
|
}
|
|
89321
|
-
var usable = (dir) =>
|
|
89518
|
+
var usable = (dir) => fs17.existsSync(entryOf(dir)) && contractOf(dir) === AKB_CONTRACT;
|
|
89322
89519
|
function currentAkb() {
|
|
89323
89520
|
const { current } = readAkbState();
|
|
89324
89521
|
if (!current) return bundledAkb();
|
|
@@ -89326,10 +89523,10 @@ function currentAkb() {
|
|
|
89326
89523
|
if (!usable(dir)) return bundledAkb();
|
|
89327
89524
|
try {
|
|
89328
89525
|
const now = /* @__PURE__ */ new Date();
|
|
89329
|
-
|
|
89526
|
+
fs17.utimesSync(dir, now, now);
|
|
89330
89527
|
} catch {
|
|
89331
89528
|
}
|
|
89332
|
-
return { command: process.execPath, args: [entryOf(dir)], version: current, shim:
|
|
89529
|
+
return { command: process.execPath, args: [entryOf(dir)], version: current, shim: path21.join(dir, "shim") };
|
|
89333
89530
|
}
|
|
89334
89531
|
var answers2 = (dir, version) => new Promise((resolve2) => {
|
|
89335
89532
|
execFile(process.execPath, [entryOf(dir), "--version"], { timeout: CHECK_MS2, killSignal: "SIGKILL" }, (error, stdout) => resolve2(!error && stdout.trim().split(/\s+/).at(-1) === version));
|
|
@@ -89369,20 +89566,20 @@ function sweepAkb(now = Date.now()) {
|
|
|
89369
89566
|
const { current } = readAkbState();
|
|
89370
89567
|
let entries = [];
|
|
89371
89568
|
try {
|
|
89372
|
-
entries =
|
|
89569
|
+
entries = fs17.readdirSync(akbHome(), { withFileTypes: true });
|
|
89373
89570
|
} catch {
|
|
89374
89571
|
return;
|
|
89375
89572
|
}
|
|
89376
89573
|
for (const e2 of entries) {
|
|
89377
89574
|
if (!e2.isDirectory() || e2.name === current || e2.name === BUNDLED_SHIM) continue;
|
|
89378
|
-
const dir =
|
|
89379
|
-
if (now -
|
|
89575
|
+
const dir = path21.join(akbHome(), e2.name);
|
|
89576
|
+
if (now - fs17.statSync(dir).mtimeMs > IDLE_MS) fs17.rmSync(dir, { recursive: true, force: true });
|
|
89380
89577
|
}
|
|
89381
89578
|
}
|
|
89382
89579
|
|
|
89383
89580
|
// src/chats.ts
|
|
89384
|
-
import
|
|
89385
|
-
import
|
|
89581
|
+
import fs19 from "node:fs";
|
|
89582
|
+
import path23 from "node:path";
|
|
89386
89583
|
|
|
89387
89584
|
// ../cloud/src/config.ts
|
|
89388
89585
|
var CLAIM_LEASE_SECONDS = 15 * 60;
|
|
@@ -89398,18 +89595,18 @@ var CONTACT_ATTEMPT_WINDOW_SECONDS = 60 * 60;
|
|
|
89398
89595
|
var CHAT_KEEP_DAYS = 30;
|
|
89399
89596
|
|
|
89400
89597
|
// ../cli/src/lib/agent/task-chats.ts
|
|
89401
|
-
import
|
|
89402
|
-
import
|
|
89598
|
+
import fs18 from "node:fs";
|
|
89599
|
+
import path22 from "node:path";
|
|
89403
89600
|
var TASK = /^[\w-]{1,100}$/;
|
|
89404
|
-
var taskChatsDir = (home4 = machineHome()) =>
|
|
89601
|
+
var taskChatsDir = (home4 = machineHome()) => path22.join(home4, "chats");
|
|
89405
89602
|
function taskChatFile(task, home4) {
|
|
89406
89603
|
if (!TASK.test(task)) throw new Error(`${task} is not a task id.`);
|
|
89407
|
-
return
|
|
89604
|
+
return path22.join(taskChatsDir(home4), `${task}.jsonl`);
|
|
89408
89605
|
}
|
|
89409
89606
|
function readTaskChat(task, home4) {
|
|
89410
89607
|
let text3;
|
|
89411
89608
|
try {
|
|
89412
|
-
text3 =
|
|
89609
|
+
text3 = fs18.readFileSync(taskChatFile(task, home4), "utf8");
|
|
89413
89610
|
} catch {
|
|
89414
89611
|
return [];
|
|
89415
89612
|
}
|
|
@@ -89430,18 +89627,18 @@ var DAY_MS = 24 * 60 * 6e4;
|
|
|
89430
89627
|
var REVIEW_EVERY_MS = DAY_MS;
|
|
89431
89628
|
var KEEP_MS2 = CHAT_KEEP_DAYS * DAY_MS;
|
|
89432
89629
|
var home3 = () => runnerHome();
|
|
89433
|
-
var reviewedFile = () =>
|
|
89630
|
+
var reviewedFile = () => path23.join(taskChatsDir(home3()), "reviewed.json");
|
|
89434
89631
|
function readReviewed() {
|
|
89435
89632
|
try {
|
|
89436
|
-
const held4 = JSON.parse(
|
|
89633
|
+
const held4 = JSON.parse(fs19.readFileSync(reviewedFile(), "utf8"));
|
|
89437
89634
|
return { checkedAt: Number(held4.checkedAt) || 0, tasks: held4.tasks ?? {} };
|
|
89438
89635
|
} catch {
|
|
89439
89636
|
return { checkedAt: 0, tasks: {} };
|
|
89440
89637
|
}
|
|
89441
89638
|
}
|
|
89442
89639
|
function writeReviewed(reviewed) {
|
|
89443
|
-
|
|
89444
|
-
|
|
89640
|
+
fs19.mkdirSync(path23.dirname(reviewedFile()), { recursive: true });
|
|
89641
|
+
fs19.writeFileSync(reviewedFile(), `${JSON.stringify(reviewed, null, 2)}
|
|
89445
89642
|
`);
|
|
89446
89643
|
}
|
|
89447
89644
|
function keepChat(job, reply, at2 = Date.now()) {
|
|
@@ -89451,16 +89648,16 @@ function keepChat(job, reply, at2 = Date.now()) {
|
|
|
89451
89648
|
{ id: job.id, role: "agent", text: reply, at: at2, runtime: job.runtime, model: job.model ?? null }
|
|
89452
89649
|
];
|
|
89453
89650
|
const file2 = taskChatFile(job.task, home3());
|
|
89454
|
-
|
|
89455
|
-
|
|
89651
|
+
fs19.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
89652
|
+
fs19.appendFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89456
89653
|
`).join(""));
|
|
89457
89654
|
}
|
|
89458
89655
|
function keepCloudChat(task, messages) {
|
|
89459
89656
|
const file2 = taskChatFile(task, home3());
|
|
89460
|
-
if (!messages.length) return
|
|
89657
|
+
if (!messages.length) return fs19.rmSync(file2, { force: true });
|
|
89461
89658
|
const lines = messages.map((m) => ({ id: m.id, role: m.role, text: m.body, at: Date.parse(m.created_at) || Date.now() }));
|
|
89462
|
-
|
|
89463
|
-
|
|
89659
|
+
fs19.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
89660
|
+
fs19.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89464
89661
|
`).join(""));
|
|
89465
89662
|
}
|
|
89466
89663
|
async function keepDecisions(task, read2) {
|
|
@@ -89478,13 +89675,13 @@ async function keepDecisions(task, read2) {
|
|
|
89478
89675
|
const ids = new Set(comments.map((c2) => c2.id));
|
|
89479
89676
|
const lines = [...readTaskChat(task, home3()).filter((l2) => !ids.has(l2.id)), ...comments].sort((a3, b2) => a3.at - b2.at);
|
|
89480
89677
|
const file2 = taskChatFile(task, home3());
|
|
89481
|
-
|
|
89482
|
-
|
|
89678
|
+
fs19.mkdirSync(path23.dirname(file2), { recursive: true });
|
|
89679
|
+
fs19.writeFileSync(file2, lines.map((l2) => `${JSON.stringify(l2)}
|
|
89483
89680
|
`).join(""));
|
|
89484
89681
|
}
|
|
89485
89682
|
var tasksKept = () => {
|
|
89486
89683
|
try {
|
|
89487
|
-
return
|
|
89684
|
+
return fs19.readdirSync(taskChatsDir(home3())).map((n) => /^([\w-]{1,100})\.jsonl$/.exec(n)?.[1]).filter((t2) => !!t2);
|
|
89488
89685
|
} catch {
|
|
89489
89686
|
return [];
|
|
89490
89687
|
}
|
|
@@ -89495,9 +89692,9 @@ function pruneChats(now = Date.now()) {
|
|
|
89495
89692
|
const kept4 = lines.filter((l2) => now - l2.at < KEEP_MS2);
|
|
89496
89693
|
if (kept4.length === lines.length) continue;
|
|
89497
89694
|
const file2 = taskChatFile(task, home3());
|
|
89498
|
-
if (kept4.length)
|
|
89695
|
+
if (kept4.length) fs19.writeFileSync(file2, kept4.map((l2) => `${JSON.stringify(l2)}
|
|
89499
89696
|
`).join(""));
|
|
89500
|
-
else
|
|
89697
|
+
else fs19.rmSync(file2, { force: true });
|
|
89501
89698
|
}
|
|
89502
89699
|
}
|
|
89503
89700
|
var lastOf = (task) => readTaskChat(task, home3()).at(-1);
|
|
@@ -89535,28 +89732,28 @@ async function reviewChats(machineId2, runtimes, now = Date.now()) {
|
|
|
89535
89732
|
}
|
|
89536
89733
|
|
|
89537
89734
|
// src/board-watch.ts
|
|
89538
|
-
import
|
|
89539
|
-
import
|
|
89735
|
+
import fs23 from "node:fs";
|
|
89736
|
+
import path27 from "node:path";
|
|
89540
89737
|
|
|
89541
89738
|
// ../cloud/src/board-files.ts
|
|
89542
89739
|
var ROOTS = ["todo/", ".archive/", "memory/", "workflows/", "triage/", "assets/", "rules/"];
|
|
89543
89740
|
var SETTINGS = ["modules.md", "config.md"];
|
|
89544
|
-
var isSettingsPath = (
|
|
89741
|
+
var isSettingsPath = (path40) => SETTINGS.includes(path40) || /^rules\/(?:workflows\/)?[^/]+\.md$/.test(path40);
|
|
89545
89742
|
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) =>
|
|
89743
|
+
function isBoardPath(path40) {
|
|
89744
|
+
if (!path40 || path40.length > 500 || path40.startsWith("/") || path40.includes("\\") || path40.includes("\0")) return false;
|
|
89745
|
+
if (path40.split("/").some((part) => !part || part === "." || part === "..")) return false;
|
|
89746
|
+
if (path40 === "todo/README.md" || path40.split("/").includes(".sync")) return false;
|
|
89747
|
+
if (path40.startsWith("workflows/")) return true;
|
|
89748
|
+
if (SETTINGS.includes(path40)) return true;
|
|
89749
|
+
if (path40.startsWith("rules/")) return isSettingsPath(path40);
|
|
89750
|
+
if (path40.startsWith("assets/")) return path40.endsWith(".json");
|
|
89751
|
+
return ROOTS.some((root) => path40.startsWith(root)) && path40.endsWith(".md");
|
|
89555
89752
|
}
|
|
89556
89753
|
var CARD = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]*\.md$/;
|
|
89557
89754
|
var ROOT = /^(?:todo|\.archive)\/(?:[^/]+\/)*(\d+)-[^/]+\/root\.md$/;
|
|
89558
|
-
function numberOfCard(
|
|
89559
|
-
const n = ROOT.exec(
|
|
89755
|
+
function numberOfCard(path40) {
|
|
89756
|
+
const n = ROOT.exec(path40)?.[1] ?? CARD.exec(path40)?.[1];
|
|
89560
89757
|
return n ? Number(n) : null;
|
|
89561
89758
|
}
|
|
89562
89759
|
var cardSlug = (task) => task.toLowerCase().replace(/_/g, "-");
|
|
@@ -89764,9 +89961,9 @@ function collect(body, card, host) {
|
|
|
89764
89961
|
|
|
89765
89962
|
// src/task-folder.ts
|
|
89766
89963
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
89767
|
-
import
|
|
89768
|
-
import
|
|
89769
|
-
import
|
|
89964
|
+
import crypto4 from "node:crypto";
|
|
89965
|
+
import fs22 from "node:fs";
|
|
89966
|
+
import path26 from "node:path";
|
|
89770
89967
|
|
|
89771
89968
|
// node_modules/node-diff3/dist/diff3.mjs
|
|
89772
89969
|
function LCS(buffer1, buffer2) {
|
|
@@ -90005,8 +90202,8 @@ function unquote2(v2) {
|
|
|
90005
90202
|
|
|
90006
90203
|
// ../cloud/src/triage-files.ts
|
|
90007
90204
|
var ITEM = /^triage\/(?:(dismissed|archived)\/)?([^/]+)\.md$/;
|
|
90008
|
-
function itemAt(
|
|
90009
|
-
const m = ITEM.exec(
|
|
90205
|
+
function itemAt(path40) {
|
|
90206
|
+
const m = ITEM.exec(path40);
|
|
90010
90207
|
if (!m) return null;
|
|
90011
90208
|
return { state: m[1] === "dismissed" ? "dismissed" : m[1] === "archived" ? "carded" : "open", name: m[2] };
|
|
90012
90209
|
}
|
|
@@ -90023,11 +90220,11 @@ function stampItem(content, fields) {
|
|
|
90023
90220
|
}
|
|
90024
90221
|
|
|
90025
90222
|
// ../cli/src/lib/agents/shared-memory.ts
|
|
90026
|
-
import
|
|
90027
|
-
import
|
|
90223
|
+
import fs20 from "node:fs";
|
|
90224
|
+
import path24 from "node:path";
|
|
90028
90225
|
|
|
90029
90226
|
// ../cli/src/agents/builder/AGENT.md
|
|
90030
|
-
var AGENT_default = "---\nname: builder\ndescription:
|
|
90227
|
+
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
90228
|
|
|
90032
90229
|
// ../cli/src/agents/api-designer/AGENT.md
|
|
90033
90230
|
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 +90799,10 @@ function readScalar(value) {
|
|
|
90602
90799
|
function readBlock(lines, start, parentIndent) {
|
|
90603
90800
|
if (start >= lines.length || lines[start].indent <= parentIndent) return ["", start];
|
|
90604
90801
|
const indent = lines[start].indent;
|
|
90605
|
-
if (lines[start].text.startsWith("-")) return
|
|
90802
|
+
if (lines[start].text.startsWith("-")) return readList(lines, start, indent);
|
|
90606
90803
|
return readMap(lines, start, indent);
|
|
90607
90804
|
}
|
|
90608
|
-
function
|
|
90805
|
+
function readList(lines, start, indent) {
|
|
90609
90806
|
const out = [];
|
|
90610
90807
|
let i = start;
|
|
90611
90808
|
while (i < lines.length && lines[i].indent === indent && lines[i].text.startsWith("-")) {
|
|
@@ -90757,16 +90954,16 @@ function sharedMemory(board) {
|
|
|
90757
90954
|
const at2 = /^([^/]+)\/AGENT\.md$/.exec(key);
|
|
90758
90955
|
if (at2) take(at2[1], text3, true);
|
|
90759
90956
|
}
|
|
90760
|
-
const root =
|
|
90957
|
+
const root = path24.join(board, "agents");
|
|
90761
90958
|
let folders2 = [];
|
|
90762
90959
|
try {
|
|
90763
|
-
folders2 =
|
|
90960
|
+
folders2 = fs20.readdirSync(root, { withFileTypes: true }).filter((e2) => e2.isDirectory() && !e2.name.startsWith(".")).map((e2) => e2.name);
|
|
90764
90961
|
} catch {
|
|
90765
90962
|
}
|
|
90766
90963
|
for (const folder of folders2.sort()) {
|
|
90767
90964
|
let text3 = null;
|
|
90768
90965
|
try {
|
|
90769
|
-
text3 =
|
|
90966
|
+
text3 = fs20.readFileSync(path24.join(root, folder, "AGENT.md"), "utf8");
|
|
90770
90967
|
} catch {
|
|
90771
90968
|
}
|
|
90772
90969
|
take(folder, text3, false);
|
|
@@ -90790,16 +90987,16 @@ function openTaskFolder(job, projectDir2) {
|
|
|
90790
90987
|
projectDir2 ??= openCached(job.project);
|
|
90791
90988
|
keepOutOfGit(projectDir2);
|
|
90792
90989
|
markUsed(projectDir2);
|
|
90793
|
-
const board =
|
|
90794
|
-
|
|
90990
|
+
const board = path26.join(projectDir2, ".akb", "kanban");
|
|
90991
|
+
fs22.mkdirSync(board, { recursive: true });
|
|
90795
90992
|
return { task, cloudTask: task, board, cwd: projectDir2, project: job.project, number: job.number ?? null, workflow: job.workflow ?? job.flow?.workflow ?? null };
|
|
90796
90993
|
}
|
|
90797
90994
|
function openAgentFolder(job, projectDir2) {
|
|
90798
90995
|
if (!job.project || !job.agent) throw new Error("This job names no project.");
|
|
90799
90996
|
keepOutOfGit(projectDir2);
|
|
90800
90997
|
markUsed(projectDir2);
|
|
90801
|
-
const board =
|
|
90802
|
-
|
|
90998
|
+
const board = path26.join(projectDir2, ".akb", "kanban");
|
|
90999
|
+
fs22.mkdirSync(board, { recursive: true });
|
|
90803
91000
|
return {
|
|
90804
91001
|
task: `agent-${safe(job.agent.workflow ? `${job.agent.workflow}-${job.agent.name}` : job.agent.name)}`,
|
|
90805
91002
|
cloudTask: job.agent.tasks?.[0]?.id ?? null,
|
|
@@ -90814,13 +91011,13 @@ function openDiscussionFolder(job, projectDir2) {
|
|
|
90814
91011
|
if (!job.project) throw new Error("This job names no project.");
|
|
90815
91012
|
keepOutOfGit(projectDir2);
|
|
90816
91013
|
markUsed(projectDir2);
|
|
90817
|
-
const board =
|
|
90818
|
-
|
|
91014
|
+
const board = path26.join(projectDir2, ".akb", "kanban");
|
|
91015
|
+
fs22.mkdirSync(board, { recursive: true });
|
|
90819
91016
|
return { task: "discussion", cloudTask: null, board, cwd: projectDir2, project: job.project, number: null, workflow: null };
|
|
90820
91017
|
}
|
|
90821
91018
|
var boardFolder = (ws) => ({ task: "board", cloudTask: null, board: ws.board, cwd: ws.cwd, project: ws.project, number: null, workflow: null });
|
|
90822
91019
|
function keptBoard(cwd) {
|
|
90823
|
-
const board =
|
|
91020
|
+
const board = path26.join(cwd, ".akb", "kanban");
|
|
90824
91021
|
const base = readBase({ cwd });
|
|
90825
91022
|
const project = base.project ?? /^projects\/([^/]+)\//.exec(Object.keys(base.files).find((p2) => p2.startsWith("projects/")) ?? "")?.[1];
|
|
90826
91023
|
return base.head_seq === null || !project ? null : boardFolder({ board, cwd, project });
|
|
@@ -90837,8 +91034,8 @@ function inFolder(dir, work) {
|
|
|
90837
91034
|
var safe = (name) => name.replace(/[^\w.-]/g, "_") || "default";
|
|
90838
91035
|
function openCached(project) {
|
|
90839
91036
|
const dir = cacheDir(project);
|
|
90840
|
-
if (
|
|
90841
|
-
|
|
91037
|
+
if (fs22.existsSync(path26.join(dir, ".git"))) return dir;
|
|
91038
|
+
fs22.mkdirSync(dir, { recursive: true });
|
|
90842
91039
|
const git4 = (...args) => spawnSync4("git", ["-C", dir, ...args], { encoding: "utf8" }).status === 0;
|
|
90843
91040
|
if (git4("init", "-q")) git4("-c", "user.name=WildCrane", "-c", "user.email=runner@wildcrane.ai", "commit", "-q", "--allow-empty", "-m", "general");
|
|
90844
91041
|
return dir;
|
|
@@ -90851,56 +91048,56 @@ function keepOutOfGit(dir, folders2 = SKILL_FOLDERS) {
|
|
|
90851
91048
|
if (inside.status !== 0) return;
|
|
90852
91049
|
const missing = [".akb/", ...folders2.map((f2) => `${f2}/`)].filter((p2) => git4("check-ignore", "-q", p2).status !== 0);
|
|
90853
91050
|
if (!missing.length) return;
|
|
90854
|
-
const exclude =
|
|
90855
|
-
|
|
90856
|
-
const held4 =
|
|
90857
|
-
|
|
91051
|
+
const exclude = path26.resolve(dir, inside.stdout.trim());
|
|
91052
|
+
fs22.mkdirSync(path26.dirname(exclude), { recursive: true });
|
|
91053
|
+
const held4 = fs22.existsSync(exclude) ? fs22.readFileSync(exclude, "utf8") : "";
|
|
91054
|
+
fs22.writeFileSync(exclude, `${held4}${held4 && !held4.endsWith("\n") ? "\n" : ""}${missing.join("\n")}
|
|
90858
91055
|
`);
|
|
90859
91056
|
}
|
|
90860
|
-
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ??
|
|
91057
|
+
var cardFile = (ws) => (ws.number ? findCard(ws.board, ws.number) : null) ?? path26.join(ws.board, "todo", `${ws.number ?? 0}-task.md`);
|
|
90861
91058
|
function findCard(board, number) {
|
|
90862
91059
|
const named2 = new RegExp(`^${number}-`);
|
|
90863
91060
|
const walk = (dir) => {
|
|
90864
91061
|
let entries;
|
|
90865
91062
|
try {
|
|
90866
|
-
entries =
|
|
91063
|
+
entries = fs22.readdirSync(dir, { withFileTypes: true });
|
|
90867
91064
|
} catch {
|
|
90868
91065
|
return null;
|
|
90869
91066
|
}
|
|
90870
91067
|
for (const e2 of entries) {
|
|
90871
91068
|
if (!named2.test(e2.name)) continue;
|
|
90872
|
-
if (e2.isFile() && e2.name.endsWith(".md")) return
|
|
90873
|
-
const root =
|
|
90874
|
-
if (e2.isDirectory() &&
|
|
91069
|
+
if (e2.isFile() && e2.name.endsWith(".md")) return path26.join(dir, e2.name);
|
|
91070
|
+
const root = path26.join(dir, e2.name, "root.md");
|
|
91071
|
+
if (e2.isDirectory() && fs22.existsSync(root)) return root;
|
|
90875
91072
|
}
|
|
90876
91073
|
for (const e2 of entries) if (e2.isDirectory() && !e2.name.startsWith(".")) {
|
|
90877
|
-
const hit = walk(
|
|
91074
|
+
const hit = walk(path26.join(dir, e2.name));
|
|
90878
91075
|
if (hit) return hit;
|
|
90879
91076
|
}
|
|
90880
91077
|
return null;
|
|
90881
91078
|
};
|
|
90882
|
-
return walk(
|
|
91079
|
+
return walk(path26.join(board, "todo")) ?? walk(path26.join(board, ".archive"));
|
|
90883
91080
|
}
|
|
90884
91081
|
function akbCardOf(ws) {
|
|
90885
91082
|
return ws.number && findCard(ws.board, ws.number) ? ws.number : void 0;
|
|
90886
91083
|
}
|
|
90887
|
-
var recordFile = (ws) =>
|
|
91084
|
+
var recordFile = (ws) => path26.join(ws.board, ".sync", `${ws.task}.json`);
|
|
90888
91085
|
function readRecord(ws) {
|
|
90889
91086
|
try {
|
|
90890
|
-
return { ...EMPTY, ...JSON.parse(
|
|
91087
|
+
return { ...EMPTY, ...JSON.parse(fs22.readFileSync(recordFile(ws), "utf8")) };
|
|
90891
91088
|
} catch {
|
|
90892
91089
|
return structuredClone(EMPTY);
|
|
90893
91090
|
}
|
|
90894
91091
|
}
|
|
90895
91092
|
function writeRecord(ws, record) {
|
|
90896
|
-
|
|
90897
|
-
|
|
91093
|
+
fs22.mkdirSync(path26.dirname(recordFile(ws)), { recursive: true });
|
|
91094
|
+
fs22.writeFileSync(recordFile(ws), `${JSON.stringify(record, null, 2)}
|
|
90898
91095
|
`);
|
|
90899
91096
|
}
|
|
90900
|
-
var baseFile = (ws) =>
|
|
91097
|
+
var baseFile = (ws) => path26.join(ws.cwd, ".akb", "base.json");
|
|
90901
91098
|
function readBase(ws) {
|
|
90902
91099
|
try {
|
|
90903
|
-
const base = JSON.parse(
|
|
91100
|
+
const base = JSON.parse(fs22.readFileSync(baseFile(ws), "utf8"));
|
|
90904
91101
|
if (base.layout === "workspace") return base;
|
|
90905
91102
|
} catch {
|
|
90906
91103
|
}
|
|
@@ -90908,25 +91105,25 @@ function readBase(ws) {
|
|
|
90908
91105
|
}
|
|
90909
91106
|
function writeBase(ws, base) {
|
|
90910
91107
|
const file2 = baseFile(ws);
|
|
90911
|
-
|
|
90912
|
-
|
|
90913
|
-
|
|
91108
|
+
fs22.mkdirSync(path26.dirname(file2), { recursive: true });
|
|
91109
|
+
fs22.writeFileSync(`${file2}.tmp`, JSON.stringify(base));
|
|
91110
|
+
fs22.renameSync(`${file2}.tmp`, file2);
|
|
90914
91111
|
}
|
|
90915
|
-
var hashOf = (bytes2) =>
|
|
91112
|
+
var hashOf = (bytes2) => crypto4.createHash("sha256").update(bytes2).digest("hex");
|
|
90916
91113
|
function hashFile(file2) {
|
|
90917
91114
|
try {
|
|
90918
|
-
return hashOf(
|
|
91115
|
+
return hashOf(fs22.readFileSync(file2));
|
|
90919
91116
|
} catch {
|
|
90920
91117
|
return null;
|
|
90921
91118
|
}
|
|
90922
91119
|
}
|
|
90923
91120
|
function write(file2, bytes2) {
|
|
90924
|
-
|
|
90925
|
-
|
|
91121
|
+
fs22.mkdirSync(path26.dirname(file2), { recursive: true });
|
|
91122
|
+
fs22.writeFileSync(file2, bytes2);
|
|
90926
91123
|
}
|
|
90927
91124
|
function readText(file2) {
|
|
90928
91125
|
try {
|
|
90929
|
-
return
|
|
91126
|
+
return fs22.readFileSync(file2, "utf8");
|
|
90930
91127
|
} catch {
|
|
90931
91128
|
return null;
|
|
90932
91129
|
}
|
|
@@ -90934,14 +91131,14 @@ function readText(file2) {
|
|
|
90934
91131
|
function filesUnder(dir, base = dir) {
|
|
90935
91132
|
let entries;
|
|
90936
91133
|
try {
|
|
90937
|
-
entries =
|
|
91134
|
+
entries = fs22.readdirSync(dir, { withFileTypes: true });
|
|
90938
91135
|
} catch {
|
|
90939
91136
|
return [];
|
|
90940
91137
|
}
|
|
90941
91138
|
return entries.flatMap((e2) => {
|
|
90942
|
-
const full =
|
|
91139
|
+
const full = path26.join(dir, e2.name);
|
|
90943
91140
|
if (e2.isDirectory()) return filesUnder(full, base);
|
|
90944
|
-
return e2.isFile() ? [
|
|
91141
|
+
return e2.isFile() ? [path26.relative(base, full).split(path26.sep).join("/")] : [];
|
|
90945
91142
|
});
|
|
90946
91143
|
}
|
|
90947
91144
|
var kept3 = isBoardPath;
|
|
@@ -90957,18 +91154,18 @@ function viewOf(ws, base, shared) {
|
|
|
90957
91154
|
}
|
|
90958
91155
|
function assetFiles(ws, list) {
|
|
90959
91156
|
const card = cardFile(ws);
|
|
90960
|
-
return new Set(Object.keys(assetsOf(list)).map((name) => assetPath(ws, name, card)).filter((f2) => !!f2).map((f2) =>
|
|
91157
|
+
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
91158
|
}
|
|
90962
91159
|
var assetsListOf = (ws, base) => base.files[rootOf(ws) + assetsFile(ws.task)]?.content;
|
|
90963
91160
|
var localFiles = (ws, base) => {
|
|
90964
|
-
const assets = /* @__PURE__ */ new Set([...assetFiles(ws, assetsListOf(ws, base)), ...assetFiles(ws, readText(
|
|
91161
|
+
const assets = /* @__PURE__ */ new Set([...assetFiles(ws, assetsListOf(ws, base)), ...assetFiles(ws, readText(path26.join(ws.board, assetsFile(ws.task))))]);
|
|
90965
91162
|
return filesUnder(ws.board).filter((p2) => kept3(p2) && !assets.has(p2));
|
|
90966
91163
|
};
|
|
90967
91164
|
var SKILL_PATH = /^skills\/([a-z0-9]+(?:-[a-z0-9]+)*)\/((?:[\w.-]+\/)*[\w.-]+)$/;
|
|
90968
91165
|
function pullTools(ws, record, files) {
|
|
90969
91166
|
const held4 = record.tools?.skills ?? {};
|
|
90970
91167
|
const ours = new Set(Object.keys(held4).map((name) => name.split("/")[1]));
|
|
90971
|
-
const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) =>
|
|
91168
|
+
const theirs = (skill) => !ours.has(skill) && SKILL_ROOTS.some((root) => fs22.existsSync(path26.join(ws.cwd, root, skill)));
|
|
90972
91169
|
const kept4 = Object.keys(files).map((name) => SKILL_PATH.exec(name)?.[1]).filter((skill) => skill && !theirs(skill));
|
|
90973
91170
|
const skills = {};
|
|
90974
91171
|
for (const [name, text3] of Object.entries(files)) {
|
|
@@ -90976,7 +91173,7 @@ function pullTools(ws, record, files) {
|
|
|
90976
91173
|
if (!at2 || at2[1] === "kanban" || !kept4.includes(at2[1]) || at2[2].split("/").includes("..")) continue;
|
|
90977
91174
|
skills[name] = hashOf(text3);
|
|
90978
91175
|
for (const root of SKILL_ROOTS) {
|
|
90979
|
-
const file2 =
|
|
91176
|
+
const file2 = path26.join(ws.cwd, root, at2[1], at2[2]);
|
|
90980
91177
|
if (held4[name] !== skills[name] || hashFile(file2) !== skills[name]) write(file2, text3);
|
|
90981
91178
|
}
|
|
90982
91179
|
}
|
|
@@ -90985,8 +91182,8 @@ function pullTools(ws, record, files) {
|
|
|
90985
91182
|
const [, skill, rest] = SKILL_PATH.exec(name) ?? [];
|
|
90986
91183
|
if (!skill || !rest) continue;
|
|
90987
91184
|
for (const root of SKILL_ROOTS) {
|
|
90988
|
-
|
|
90989
|
-
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`)))
|
|
91185
|
+
fs22.rmSync(path26.join(ws.cwd, root, skill, rest), { force: true });
|
|
91186
|
+
if (!Object.keys(skills).some((n) => n.startsWith(`skills/${skill}/`))) fs22.rmSync(path26.join(ws.cwd, root, skill), { recursive: true, force: true });
|
|
90990
91187
|
}
|
|
90991
91188
|
}
|
|
90992
91189
|
const names2 = [...new Set(Object.keys(skills).map((name) => name.split("/")[1]))];
|
|
@@ -91014,7 +91211,7 @@ async function pullWorkflow(ws, record, base) {
|
|
|
91014
91211
|
files = read2.value.files;
|
|
91015
91212
|
found = true;
|
|
91016
91213
|
if (!record.builtin) {
|
|
91017
|
-
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(
|
|
91214
|
+
for (const [name, text3] of Object.entries(files)) if (isBoardPath(root + name)) write(path26.join(ws.board, root, name), text3);
|
|
91018
91215
|
}
|
|
91019
91216
|
}
|
|
91020
91217
|
}
|
|
@@ -91022,14 +91219,14 @@ async function pullWorkflow(ws, record, base) {
|
|
|
91022
91219
|
}
|
|
91023
91220
|
pullAgents(ws, base, ws.workflow && !record.builtin ? files : {});
|
|
91024
91221
|
const placed = readPlaced(ws);
|
|
91025
|
-
for (const name of Object.keys(record.agents ?? {})) if (!placed[name])
|
|
91222
|
+
for (const name of Object.keys(record.agents ?? {})) if (!placed[name]) fs22.rmSync(path26.join(ws.board, name), { force: true });
|
|
91026
91223
|
record.agents = {};
|
|
91027
91224
|
return { ok: true, value: void 0 };
|
|
91028
91225
|
}
|
|
91029
|
-
var agentsRecord = (ws) =>
|
|
91226
|
+
var agentsRecord = (ws) => path26.join(ws.board, ".sync", "agents.json");
|
|
91030
91227
|
function readPlaced(ws) {
|
|
91031
91228
|
try {
|
|
91032
|
-
return JSON.parse(
|
|
91229
|
+
return JSON.parse(fs22.readFileSync(agentsRecord(ws), "utf8"));
|
|
91033
91230
|
} catch {
|
|
91034
91231
|
return {};
|
|
91035
91232
|
}
|
|
@@ -91050,8 +91247,8 @@ function pullAgents(ws, base, own) {
|
|
|
91050
91247
|
const names2 = /* @__PURE__ */ new Set();
|
|
91051
91248
|
for (const [name, text3] of Object.entries(files)) {
|
|
91052
91249
|
const agent = /^agents\/([^/]+)\//.exec(name)?.[1];
|
|
91053
|
-
const file2 =
|
|
91054
|
-
if (!agent || taken.has(agent) || !file2.startsWith(
|
|
91250
|
+
const file2 = path26.resolve(ws.board, name);
|
|
91251
|
+
if (!agent || taken.has(agent) || !file2.startsWith(path26.join(ws.board, "agents") + path26.sep)) continue;
|
|
91055
91252
|
names2.add(agent);
|
|
91056
91253
|
agents[name] = text3;
|
|
91057
91254
|
}
|
|
@@ -91061,51 +91258,51 @@ function pullAgents(ws, base, own) {
|
|
|
91061
91258
|
const hashes = {};
|
|
91062
91259
|
for (const [name, text3] of Object.entries(agents)) {
|
|
91063
91260
|
hashes[name] = hashOf(text3);
|
|
91064
|
-
if (hashFile(
|
|
91261
|
+
if (hashFile(path26.join(ws.board, name)) !== hashes[name]) write(path26.join(ws.board, name), text3);
|
|
91065
91262
|
}
|
|
91066
|
-
for (const name of Object.keys(before)) if (!hashes[name])
|
|
91263
|
+
for (const name of Object.keys(before)) if (!hashes[name]) fs22.rmSync(path26.join(ws.board, name), { force: true });
|
|
91067
91264
|
write(agentsRecord(ws), `${JSON.stringify(hashes, null, 2)}
|
|
91068
91265
|
`);
|
|
91069
91266
|
}
|
|
91070
91267
|
function pullDraftAgents(ws, record) {
|
|
91071
91268
|
if (ws.workflow !== BUILDER) return;
|
|
91072
|
-
const root =
|
|
91269
|
+
const root = path26.join(ws.board, "workflows", draftFolder(ws.task), "agents");
|
|
91073
91270
|
record.agents ??= {};
|
|
91074
91271
|
for (const name of filesUnder(root)) {
|
|
91075
|
-
const text3 =
|
|
91272
|
+
const text3 = fs22.readFileSync(path26.join(root, name));
|
|
91076
91273
|
const at2 = `agents/${name}`;
|
|
91077
91274
|
record.agents[at2] = hashOf(text3);
|
|
91078
|
-
if (hashFile(
|
|
91275
|
+
if (hashFile(path26.join(ws.board, at2)) !== record.agents[at2]) write(path26.join(ws.board, at2), text3);
|
|
91079
91276
|
}
|
|
91080
91277
|
}
|
|
91081
91278
|
function workflowFile(ws) {
|
|
91082
91279
|
if (!ws.workflow || readRecord(ws).builtin) return null;
|
|
91083
|
-
const file2 =
|
|
91084
|
-
return
|
|
91280
|
+
const file2 = path26.join(ws.board, "workflows", workflowFolder(ws.workflow), "WORKFLOW.md");
|
|
91281
|
+
return fs22.existsSync(file2) ? file2 : null;
|
|
91085
91282
|
}
|
|
91086
91283
|
function assetPath(ws, name, owner) {
|
|
91087
91284
|
if (/^[a-z][\w+.-]*:/i.test(name) || name.startsWith("#") || name.startsWith("//")) return null;
|
|
91088
|
-
if (
|
|
91285
|
+
if (path26.isAbsolute(name)) throw new Error("\u8D44\u6E90\u8DEF\u5F84\u4E0D\u80FD\u662F\u7EDD\u5BF9\u8DEF\u5F84");
|
|
91089
91286
|
const held4 = /^\.(assets|mockups)\//.exec(name);
|
|
91090
91287
|
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 +
|
|
91288
|
+
const root = held4 && state ? path26.join(state, held4[1]) : ws.board;
|
|
91289
|
+
const file2 = held4 && state ? path26.resolve(root, name.slice(held4[0].length)) : path26.resolve(path26.dirname(owner), name);
|
|
91290
|
+
const roots = [ws.board, ...state ? ["assets", "mockups"].map((folder) => path26.join(state, folder, ...ws.number ? [String(ws.number)] : [])) : []];
|
|
91291
|
+
const inside = (file3, root2) => file3.startsWith(root2 + path26.sep);
|
|
91095
91292
|
if (!roots.some((root2) => inside(file2, root2))) throw new Error("\u8D44\u6E90\u8DEF\u5F84\u8D8A\u754C");
|
|
91096
91293
|
let existing = file2;
|
|
91097
|
-
while (!
|
|
91098
|
-
const real =
|
|
91294
|
+
while (!fs22.existsSync(existing) && path26.dirname(existing) !== existing) existing = path26.dirname(existing);
|
|
91295
|
+
const real = fs22.realpathSync(existing);
|
|
91099
91296
|
let stateParent = state;
|
|
91100
|
-
while (stateParent && !
|
|
91101
|
-
const realState = state && stateParent ?
|
|
91102
|
-
const realRoots = [
|
|
91297
|
+
while (stateParent && !fs22.existsSync(stateParent) && path26.dirname(stateParent) !== stateParent) stateParent = path26.dirname(stateParent);
|
|
91298
|
+
const realState = state && stateParent ? path26.resolve(fs22.realpathSync(stateParent), path26.relative(stateParent, state)) : null;
|
|
91299
|
+
const realRoots = [fs22.realpathSync(ws.board), ...realState ? ["assets", "mockups"].map((folder) => path26.join(realState, folder, ...ws.number ? [String(ws.number)] : [])) : []];
|
|
91103
91300
|
if (!realRoots.some((root2) => real === root2 || inside(real, root2))) throw new Error("\u7B26\u53F7\u94FE\u63A5\u8D8A\u754C");
|
|
91104
91301
|
return file2;
|
|
91105
91302
|
}
|
|
91106
91303
|
function cardAssetsDir(ws, id) {
|
|
91107
91304
|
const state = stateDir(ws);
|
|
91108
|
-
return state &&
|
|
91305
|
+
return state && path26.join(state, "assets", String(id));
|
|
91109
91306
|
}
|
|
91110
91307
|
function stateDir(ws) {
|
|
91111
91308
|
try {
|
|
@@ -91144,13 +91341,13 @@ var pullChanges = (ws) => inFolder(ws.cwd, async () => {
|
|
|
91144
91341
|
const p2 = f2.path.startsWith(root) ? f2.path.slice(root.length) : f2.path;
|
|
91145
91342
|
const isShared = p2.startsWith(MEMORY2) && shared(p2.slice(MEMORY2.length));
|
|
91146
91343
|
if (kept3(p2) && isShared === !f2.path.startsWith(root)) {
|
|
91147
|
-
const file2 =
|
|
91344
|
+
const file2 = path26.join(ws.board, p2);
|
|
91148
91345
|
const here = readText(file2);
|
|
91149
91346
|
if (here !== f2.content && here !== (base.files[f2.path]?.content ?? null)) {
|
|
91150
91347
|
skipped = true;
|
|
91151
91348
|
continue;
|
|
91152
91349
|
}
|
|
91153
|
-
if (f2.content === null)
|
|
91350
|
+
if (f2.content === null) fs22.rmSync(file2, { force: true });
|
|
91154
91351
|
else if (here !== f2.content) write(file2, f2.content);
|
|
91155
91352
|
}
|
|
91156
91353
|
if (f2.content === null) delete base.files[f2.path];
|
|
@@ -91181,13 +91378,13 @@ async function readCloud(ws) {
|
|
|
91181
91378
|
writeBase(ws, base);
|
|
91182
91379
|
const reset = (view2) => {
|
|
91183
91380
|
for (const [p2, content] of view2) {
|
|
91184
|
-
const file2 =
|
|
91381
|
+
const file2 = path26.join(ws.board, p2);
|
|
91185
91382
|
if (kept3(p2) && readText(file2) !== content) write(file2, content);
|
|
91186
91383
|
}
|
|
91187
91384
|
};
|
|
91188
91385
|
const view = viewOf(ws, base, sharedMemory(ws.board));
|
|
91189
91386
|
const first = (p2) => isSettingsPath(p2) && !known2.has(rootOf(ws) + p2);
|
|
91190
|
-
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2))
|
|
91387
|
+
for (const p2 of localFiles(ws, base)) if (!view.has(p2) && !first(p2)) fs22.rmSync(path26.join(ws.board, p2), { force: true });
|
|
91191
91388
|
reset(view);
|
|
91192
91389
|
const record = readRecord(ws);
|
|
91193
91390
|
const workflow = await pullWorkflow(ws, record, base);
|
|
@@ -91201,18 +91398,18 @@ async function readCloud(ws) {
|
|
|
91201
91398
|
return { ok: true, value: void 0 };
|
|
91202
91399
|
}
|
|
91203
91400
|
function writeIndex(board) {
|
|
91204
|
-
const todo =
|
|
91401
|
+
const todo = path26.join(board, "todo");
|
|
91205
91402
|
const cards = [];
|
|
91206
91403
|
let entries = [];
|
|
91207
91404
|
try {
|
|
91208
|
-
entries =
|
|
91405
|
+
entries = fs22.readdirSync(todo, { withFileTypes: true });
|
|
91209
91406
|
} catch {
|
|
91210
91407
|
}
|
|
91211
91408
|
for (const e2 of entries) {
|
|
91212
91409
|
const id = /^(\d+)-/.exec(e2.name)?.[1];
|
|
91213
91410
|
if (!id) continue;
|
|
91214
91411
|
const link = e2.isDirectory() ? `${e2.name}/root.md` : e2.name.endsWith(".md") ? e2.name : null;
|
|
91215
|
-
const text4 = link && readText(
|
|
91412
|
+
const text4 = link && readText(path26.join(todo, link));
|
|
91216
91413
|
if (text4 === null || !link) continue;
|
|
91217
91414
|
cards.push({ id: Number(id), title: cardFront(text4).title ?? e2.name.replace(/\.md$/, ""), link });
|
|
91218
91415
|
}
|
|
@@ -91227,7 +91424,7 @@ the number at the front of a filename is the task id.
|
|
|
91227
91424
|
|
|
91228
91425
|
${list}
|
|
91229
91426
|
`;
|
|
91230
|
-
if (readText(
|
|
91427
|
+
if (readText(path26.join(todo, "README.md")) !== text3) write(path26.join(todo, "README.md"), text3);
|
|
91231
91428
|
}
|
|
91232
91429
|
var workspaceOf = (ws) => readBase(ws).workspace ?? null;
|
|
91233
91430
|
async function pullAssets(ws, record, assets) {
|
|
@@ -91235,51 +91432,74 @@ async function pullAssets(ws, record, assets) {
|
|
|
91235
91432
|
record.task = ws.cloudTask;
|
|
91236
91433
|
record.number = ws.number;
|
|
91237
91434
|
}
|
|
91238
|
-
const isCompare = (value) => !!value && typeof value === "object" && "a" in value && "b" in value;
|
|
91239
91435
|
const file2 = cardFile(ws);
|
|
91240
91436
|
const out = {};
|
|
91241
91437
|
for (const [name, ref] of Object.entries(assets)) {
|
|
91242
91438
|
const target = assetPath(ws, name, file2);
|
|
91243
91439
|
if (!target) continue;
|
|
91440
|
+
const held4 = record.assets[name];
|
|
91441
|
+
let kind = held4?.artifact === ref.artifact ? held4.kind : void 0;
|
|
91244
91442
|
let version = ref.version;
|
|
91245
|
-
|
|
91443
|
+
const localHash = hashFile(target);
|
|
91444
|
+
const current = held4?.artifact === ref.artifact && held4.version === version && localHash === (held4.localHash ?? held4.hash);
|
|
91445
|
+
if (version === void 0 || !kind || !current && kind !== "html") {
|
|
91246
91446
|
const latest = await readArtifact(ref.artifact);
|
|
91247
91447
|
if (!latest.ok) return latest;
|
|
91248
|
-
version
|
|
91448
|
+
version ??= latest.value.latest_version ?? 0;
|
|
91449
|
+
kind = latest.value.type;
|
|
91450
|
+
if (!kind) return { ok: false, code: "bad_request", error: `${name}: \u8D44\u6E90\u7C7B\u578B\u7F3A\u5931` };
|
|
91249
91451
|
}
|
|
91250
|
-
|
|
91251
|
-
|
|
91252
|
-
out[name] = { ...held4, version };
|
|
91452
|
+
if (kind === "html" && held4?.artifact === ref.artifact) {
|
|
91453
|
+
out[name] = { ...held4, kind, version };
|
|
91253
91454
|
continue;
|
|
91254
91455
|
}
|
|
91255
|
-
if (held4?.artifact === ref.artifact && held4.version === version &&
|
|
91256
|
-
out[name] = held4;
|
|
91456
|
+
if (held4?.artifact === ref.artifact && held4.version === version && current) {
|
|
91457
|
+
out[name] = { ...held4, kind };
|
|
91257
91458
|
continue;
|
|
91258
91459
|
}
|
|
91259
91460
|
const bytes2 = await readAsset(ref.artifact, version);
|
|
91260
91461
|
if (!bytes2.ok) return bytes2;
|
|
91261
91462
|
let local = bytes2.value;
|
|
91262
|
-
let kind = held4?.kind;
|
|
91263
91463
|
const dependencies = [];
|
|
91264
|
-
if (
|
|
91464
|
+
if (kind === "storyboard" || kind === "compare") {
|
|
91465
|
+
let data;
|
|
91265
91466
|
try {
|
|
91266
|
-
|
|
91467
|
+
data = JSON.parse(Buffer.from(local).toString());
|
|
91468
|
+
} catch {
|
|
91469
|
+
}
|
|
91470
|
+
if (data !== void 0) {
|
|
91471
|
+
let changed = false;
|
|
91267
91472
|
const restore = (src) => {
|
|
91268
91473
|
const name2 = Object.entries(assets).find(([, r2]) => r2.artifact === src)?.[0];
|
|
91269
|
-
if (name2) dependencies.push(name2);
|
|
91270
91474
|
if (!name2) return src;
|
|
91271
|
-
if (/^\.(assets|mockups)\//.test(name2)) return name2;
|
|
91272
91475
|
const child = assetPath(ws, name2, file2);
|
|
91273
|
-
|
|
91476
|
+
if (!child) return src;
|
|
91477
|
+
dependencies.push(name2);
|
|
91478
|
+
const restored2 = /^\.(assets|mockups)\//.test(name2) ? name2 : path26.relative(path26.dirname(target), child).split(path26.sep).join("/");
|
|
91479
|
+
if (restored2 !== src) changed = true;
|
|
91480
|
+
return restored2;
|
|
91274
91481
|
};
|
|
91275
|
-
const restored = mapReferences(
|
|
91276
|
-
if (
|
|
91277
|
-
|
|
91278
|
-
|
|
91482
|
+
const restored = mapReferences(data, kind, restore);
|
|
91483
|
+
if (changed) local = Buffer.from(JSON.stringify(restored));
|
|
91484
|
+
}
|
|
91485
|
+
}
|
|
91486
|
+
if (held4?.artifact === ref.artifact && held4.version === version && !held4.localHash && (kind === "storyboard" || kind === "compare")) {
|
|
91487
|
+
const source = readText(target);
|
|
91488
|
+
if (source !== null) {
|
|
91489
|
+
let same = false;
|
|
91490
|
+
try {
|
|
91491
|
+
same = JSON.stringify(JSON.parse(source)) === JSON.stringify(JSON.parse(Buffer.from(local).toString()));
|
|
91492
|
+
} catch {
|
|
91493
|
+
}
|
|
91494
|
+
if (!same) {
|
|
91495
|
+
out[name] = { ...held4, kind };
|
|
91496
|
+
continue;
|
|
91497
|
+
}
|
|
91498
|
+
local = Buffer.from(source);
|
|
91279
91499
|
}
|
|
91280
91500
|
}
|
|
91281
91501
|
write(target, local);
|
|
91282
|
-
out[name] = { ...held4, kind, dependencies:
|
|
91502
|
+
out[name] = { ...held4, kind, dependencies: [...new Set(dependencies)], artifact: ref.artifact, version, hash: hashOf(bytes2.value), localHash: hashOf(local) };
|
|
91283
91503
|
}
|
|
91284
91504
|
record.assets = out;
|
|
91285
91505
|
return { ok: true, value: void 0 };
|
|
@@ -91292,14 +91512,14 @@ async function readAsset(artifact, version) {
|
|
|
91292
91512
|
return { ok: true, value: Buffer.from(typeof content === "string" ? content : JSON.stringify(content)) };
|
|
91293
91513
|
}
|
|
91294
91514
|
async function sentOf(file2) {
|
|
91295
|
-
const ext =
|
|
91515
|
+
const ext = path26.extname(file2).toLowerCase();
|
|
91296
91516
|
const kind = kindOf(ext);
|
|
91297
|
-
if (kind !== "html") return { bytes:
|
|
91517
|
+
if (kind !== "html") return { bytes: fs22.readFileSync(file2), type: TYPES[ext] ?? "application/octet-stream", kind };
|
|
91298
91518
|
let page;
|
|
91299
91519
|
try {
|
|
91300
91520
|
page = await (await Promise.resolve().then(() => (init_mockup(), mockup_exports))).drawMockup(file2);
|
|
91301
91521
|
} catch (e2) {
|
|
91302
|
-
console.error(`runner: ${
|
|
91522
|
+
console.error(`runner: ${path26.basename(file2)} could not be drawn: ${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
91303
91523
|
page = UNDRAWN;
|
|
91304
91524
|
}
|
|
91305
91525
|
return { bytes: Buffer.from(page), type: "text/html", kind };
|
|
@@ -91324,14 +91544,14 @@ async function pushAssets(ws, record, before) {
|
|
|
91324
91544
|
if (body === null) return { ok: true, value: void 0 };
|
|
91325
91545
|
const refs = {};
|
|
91326
91546
|
const canonical = (target) => {
|
|
91327
|
-
const real = (file3) =>
|
|
91547
|
+
const real = (file3) => fs22.existsSync(file3) ? fs22.realpathSync(file3) : file3;
|
|
91328
91548
|
target = real(target);
|
|
91329
91549
|
const state = stateDir(ws);
|
|
91330
91550
|
for (const folder of ["assets", "mockups"]) {
|
|
91331
|
-
const root = state && real(
|
|
91332
|
-
if (root && target.startsWith(root +
|
|
91551
|
+
const root = state && real(path26.join(state, folder));
|
|
91552
|
+
if (root && target.startsWith(root + path26.sep)) return `.${folder}/${path26.relative(root, target).split(path26.sep).join("/")}`;
|
|
91333
91553
|
}
|
|
91334
|
-
return
|
|
91554
|
+
return path26.relative(real(path26.dirname(file2)), target).split(path26.sep).join("/");
|
|
91335
91555
|
};
|
|
91336
91556
|
try {
|
|
91337
91557
|
const graph = collect(body, file2, {
|
|
@@ -91341,13 +91561,13 @@ async function pushAssets(ws, record, before) {
|
|
|
91341
91561
|
const target = assetPath(ws, src, owner);
|
|
91342
91562
|
if (!target) return null;
|
|
91343
91563
|
const key = owner === file2 && before[src] ? src : canonical(target);
|
|
91344
|
-
if (!
|
|
91564
|
+
if (!fs22.statSync(target, { throwIfNoEntry: false })?.isFile()) {
|
|
91345
91565
|
if (before[key]) return { key, file: null };
|
|
91346
91566
|
throw new Error("\u660E\u786E\u5F15\u7528\u7684\u8D44\u6E90\u6587\u4EF6\u4E0D\u5B58\u5728");
|
|
91347
91567
|
}
|
|
91348
|
-
return { key: canonical(
|
|
91568
|
+
return { key: canonical(fs22.realpathSync(target)), file: target };
|
|
91349
91569
|
},
|
|
91350
|
-
readJSON: (target) => JSON.parse(
|
|
91570
|
+
readJSON: (target) => JSON.parse(fs22.readFileSync(target, "utf8")),
|
|
91351
91571
|
retained: (key) => (record.assets[key]?.dependencies ?? []).map((src) => {
|
|
91352
91572
|
const kind = record.assets[src]?.kind;
|
|
91353
91573
|
return { src, purpose: kind === "storyboard" || kind === "compare" ? kind : "asset" };
|
|
@@ -91368,6 +91588,13 @@ async function pushAssets(ws, record, before) {
|
|
|
91368
91588
|
}
|
|
91369
91589
|
continue;
|
|
91370
91590
|
}
|
|
91591
|
+
const kind = node.kind === "asset" ? kindOf(path26.extname(node.file).toLowerCase()) : node.kind;
|
|
91592
|
+
if (previous && previous.kind !== kind) {
|
|
91593
|
+
const artifact = await readArtifact(previous.artifact);
|
|
91594
|
+
if (!artifact.ok) return artifact;
|
|
91595
|
+
if (!artifact.value.type) return { ok: false, code: "bad_request", error: `${node.key}: \u8D44\u6E90\u7C7B\u578B\u7F3A\u5931` };
|
|
91596
|
+
previous.kind = artifact.value.type;
|
|
91597
|
+
}
|
|
91371
91598
|
let out = await sentOf(node.file);
|
|
91372
91599
|
if (node.kind !== "asset") {
|
|
91373
91600
|
const data = mapReferences(node.data, node.kind, (src) => {
|
|
@@ -91378,9 +91605,12 @@ async function pushAssets(ws, record, before) {
|
|
|
91378
91605
|
}
|
|
91379
91606
|
const hash = hashOf(out.bytes);
|
|
91380
91607
|
let entry = previous;
|
|
91381
|
-
|
|
91608
|
+
const localHash = hashFile(node.file);
|
|
91609
|
+
const restored = node.kind !== "asset" || out.kind === "html" && previous?.hash === localHash;
|
|
91610
|
+
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);
|
|
91611
|
+
if (!entry || !unchanged && entry.hash !== hash || entry.kind && entry.kind !== out.kind) {
|
|
91382
91612
|
if (!ws.cloudTask) continue;
|
|
91383
|
-
let artifact = previous && (previous.kind ?? kindOf(
|
|
91613
|
+
let artifact = previous && (previous.kind ?? kindOf(path26.extname(node.file).toLowerCase())) === out.kind ? previous.artifact : void 0;
|
|
91384
91614
|
if (!artifact) {
|
|
91385
91615
|
const made = await createArtifact(ws.cloudTask, node.key.slice(0, 200), out.kind);
|
|
91386
91616
|
if (!made.ok) return { ...made, error: `${node.key}: ${made.error}` };
|
|
@@ -91390,7 +91620,7 @@ async function pushAssets(ws, record, before) {
|
|
|
91390
91620
|
if (!sent.ok) return { ...sent, error: `${node.key}: ${sent.error}` };
|
|
91391
91621
|
entry = { artifact, version: sent.value, hash, kind: out.kind };
|
|
91392
91622
|
}
|
|
91393
|
-
entry = { ...entry, localHash:
|
|
91623
|
+
entry = { ...entry, localHash: localHash ?? void 0, dependencies: [...node.dependencies.values()] };
|
|
91394
91624
|
for (const alias of node.aliases) {
|
|
91395
91625
|
record.assets[alias] = entry;
|
|
91396
91626
|
refs[alias] = { artifact: entry.artifact, version: entry.version };
|
|
@@ -91400,24 +91630,24 @@ async function pushAssets(ws, record, before) {
|
|
|
91400
91630
|
} catch (error) {
|
|
91401
91631
|
return { ok: false, code: "bad_request", error: error instanceof Error ? error.message : String(error) };
|
|
91402
91632
|
}
|
|
91403
|
-
const list =
|
|
91404
|
-
if (Object.keys(refs).length ||
|
|
91633
|
+
const list = path26.join(ws.board, assetsFile(ws.task));
|
|
91634
|
+
if (Object.keys(refs).length || fs22.existsSync(list)) {
|
|
91405
91635
|
if (JSON.stringify(assetsOf(readText(list))) !== JSON.stringify(refs)) write(list, assetsText(refs));
|
|
91406
91636
|
}
|
|
91407
91637
|
return { ok: true, value: void 0 };
|
|
91408
91638
|
}
|
|
91409
91639
|
function resetSorted(ws) {
|
|
91410
|
-
for (const sub of ["dismissed", "archived"])
|
|
91640
|
+
for (const sub of ["dismissed", "archived"]) fs22.rmSync(path26.join(ws.board, "triage", sub), { recursive: true, force: true });
|
|
91411
91641
|
for (const [p2, content] of viewOf(ws, readBase(ws), sharedMemory(ws.board))) {
|
|
91412
|
-
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(
|
|
91642
|
+
if (/^triage\/(?:dismissed|archived)\//.test(p2)) write(path26.join(ws.board, p2), content);
|
|
91413
91643
|
}
|
|
91414
91644
|
}
|
|
91415
91645
|
function proposeItems(ws, base) {
|
|
91416
91646
|
const root = rootOf(ws);
|
|
91417
91647
|
for (const p2 of localFiles(ws, base)) {
|
|
91418
91648
|
if (itemAt(p2)?.state !== "open" || base.files[root + p2]) continue;
|
|
91419
|
-
const file2 =
|
|
91420
|
-
const content =
|
|
91649
|
+
const file2 = path26.join(ws.board, p2);
|
|
91650
|
+
const content = fs22.readFileSync(file2, "utf8");
|
|
91421
91651
|
const said = (key) => new RegExp(`^${key}:`, "m").test(content.split(/\n---/)[0] ?? "");
|
|
91422
91652
|
const fields = {
|
|
91423
91653
|
...ws.cloudTask && !said("source_task") ? { source_task: ws.cloudTask } : {},
|
|
@@ -91457,9 +91687,9 @@ async function send2(ws, job) {
|
|
|
91457
91687
|
const record = readRecord(ws);
|
|
91458
91688
|
const base = readBase(ws);
|
|
91459
91689
|
const fail = (error, conflict = false, code) => ({ ok: false, conflict, error, ...code ? {} : { offline: true } });
|
|
91460
|
-
const tasks = ws.cloudTask ? [{ folder: ws, record }] : filesUnder(
|
|
91690
|
+
const tasks = ws.cloudTask ? [{ folder: ws, record }] : filesUnder(path26.join(ws.board, ".sync")).filter((name) => name.endsWith(".json")).flatMap((name) => {
|
|
91461
91691
|
try {
|
|
91462
|
-
const held4 = JSON.parse(
|
|
91692
|
+
const held4 = JSON.parse(fs22.readFileSync(path26.join(ws.board, ".sync", name), "utf8"));
|
|
91463
91693
|
if (!held4.task || !TASK_ID.test(held4.task) || !held4.number) return [];
|
|
91464
91694
|
return [{ folder: { ...ws, task: held4.task, cloudTask: held4.task, number: held4.number }, record: held4 }];
|
|
91465
91695
|
} catch {
|
|
@@ -91479,7 +91709,7 @@ async function send2(ws, job) {
|
|
|
91479
91709
|
const owed = (p2) => !job.id && busy(ws.cwd) && itemAt(p2)?.state === "open" && !base.files[rootOf(ws) + p2];
|
|
91480
91710
|
for (const p2 of local) {
|
|
91481
91711
|
if (owed(p2)) continue;
|
|
91482
|
-
const content =
|
|
91712
|
+
const content = fs22.readFileSync(path26.join(ws.board, p2), "utf8");
|
|
91483
91713
|
const remote = remoteOf(ws, shared, p2);
|
|
91484
91714
|
localOf.set(remote, p2);
|
|
91485
91715
|
const held4 = base.files[remote];
|
|
@@ -91511,15 +91741,15 @@ async function send2(ws, job) {
|
|
|
91511
91741
|
changes.splice(at2, 1);
|
|
91512
91742
|
delete base.files[theirs.path];
|
|
91513
91743
|
writeBase(ws, base);
|
|
91514
|
-
|
|
91744
|
+
fs22.rmSync(path26.join(ws.board, p2), { force: true });
|
|
91515
91745
|
writeIndex(ws.board);
|
|
91516
91746
|
continue;
|
|
91517
91747
|
}
|
|
91518
91748
|
if (at2 < 0) continue;
|
|
91519
91749
|
const merged = itemAt(p2) ? { content: theirs.content } : mergeFile(base.files[theirs.path]?.content ?? null, changes[at2].content, theirs.content);
|
|
91520
91750
|
changes[at2] = { path: theirs.path, content: merged.content, base_seq: theirs.seq };
|
|
91521
|
-
if (merged.content === null)
|
|
91522
|
-
else write(
|
|
91751
|
+
if (merged.content === null) fs22.rmSync(path26.join(ws.board, p2), { force: true });
|
|
91752
|
+
else write(path26.join(ws.board, p2), merged.content);
|
|
91523
91753
|
}
|
|
91524
91754
|
if (!changes.length) return { ok: true, changed: false };
|
|
91525
91755
|
sent = await commitBoard(ws.project, job.id, job.machineId, changes);
|
|
@@ -91541,7 +91771,7 @@ var BUSY_MS = 3e4;
|
|
|
91541
91771
|
function keptFolders() {
|
|
91542
91772
|
let cached2 = [];
|
|
91543
91773
|
try {
|
|
91544
|
-
cached2 =
|
|
91774
|
+
cached2 = fs23.readdirSync(cacheRoot()).map((name) => path27.join(cacheRoot(), name));
|
|
91545
91775
|
} catch {
|
|
91546
91776
|
}
|
|
91547
91777
|
return [.../* @__PURE__ */ new Set([...allowedProjects(), ...cached2])].flatMap((dir) => [keptBoard(dir)].filter((ws) => !!ws));
|
|
@@ -91577,8 +91807,8 @@ function watchBoards(machineId2, ms, lookMs = LOOK_MS, pullMs = PULL_MS, busyMs
|
|
|
91577
91807
|
const watch = (ws) => {
|
|
91578
91808
|
let watcher;
|
|
91579
91809
|
try {
|
|
91580
|
-
watcher =
|
|
91581
|
-
const p2 = name && String(name).split(
|
|
91810
|
+
watcher = fs23.watch(ws.board, { recursive: true }, (_event, name) => {
|
|
91811
|
+
const p2 = name && String(name).split(path27.sep).join("/");
|
|
91582
91812
|
const held4 = watched.get(ws.cwd);
|
|
91583
91813
|
if (closed || !p2 || !isBoardPath(p2) || !held4) return;
|
|
91584
91814
|
const job = busy(ws.cwd);
|
|
@@ -91641,8 +91871,8 @@ function watchBoards(machineId2, ms, lookMs = LOOK_MS, pullMs = PULL_MS, busyMs
|
|
|
91641
91871
|
|
|
91642
91872
|
// src/diff.ts
|
|
91643
91873
|
import { execFile as execFile2 } from "node:child_process";
|
|
91644
|
-
import
|
|
91645
|
-
import
|
|
91874
|
+
import fs24 from "node:fs";
|
|
91875
|
+
import path28 from "node:path";
|
|
91646
91876
|
var FILE_BYTES = 256 * 1024;
|
|
91647
91877
|
var TOTAL_BYTES = 1024 * 1024;
|
|
91648
91878
|
var EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
@@ -91659,7 +91889,7 @@ var git2 = (dir, args, maxBuffer = 4 * TOTAL_BYTES) => new Promise(
|
|
|
91659
91889
|
function projectDir(placed, project) {
|
|
91660
91890
|
if (placed) {
|
|
91661
91891
|
const real = realpath3(placed);
|
|
91662
|
-
return real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
91892
|
+
return real && allowedProjects().some((root) => real === root || real.startsWith(root + path28.sep)) ? real : null;
|
|
91663
91893
|
}
|
|
91664
91894
|
let cached2;
|
|
91665
91895
|
try {
|
|
@@ -91667,11 +91897,11 @@ function projectDir(placed, project) {
|
|
|
91667
91897
|
} catch {
|
|
91668
91898
|
return null;
|
|
91669
91899
|
}
|
|
91670
|
-
return
|
|
91900
|
+
return fs24.existsSync(path28.join(cached2, ".git")) ? cached2 : null;
|
|
91671
91901
|
}
|
|
91672
91902
|
function realpath3(p2) {
|
|
91673
91903
|
try {
|
|
91674
|
-
return
|
|
91904
|
+
return fs24.realpathSync(p2);
|
|
91675
91905
|
} catch {
|
|
91676
91906
|
return null;
|
|
91677
91907
|
}
|
|
@@ -91717,18 +91947,21 @@ async function answerHint(machineId2, hint2) {
|
|
|
91717
91947
|
|
|
91718
91948
|
// ../cli/src/lib/agent/stop.ts
|
|
91719
91949
|
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
91720
|
-
import
|
|
91950
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
91951
|
+
import fs25 from "node:fs";
|
|
91721
91952
|
var runMark = (sessionId) => ({ name: RUN_ENV, value: sessionId });
|
|
91953
|
+
var stopMark = () => ({ name: STOP_ENV, value: randomUUID2() });
|
|
91954
|
+
var markEnv = (env2, mark) => ({ ...env2, [mark.name]: mark.value });
|
|
91722
91955
|
var WINDOWS3 = process.platform === "win32";
|
|
91723
91956
|
function markedInProc(entry, strict = false) {
|
|
91724
91957
|
const pids = [];
|
|
91725
|
-
for (const name of
|
|
91958
|
+
for (const name of fs25.readdirSync("/proc")) {
|
|
91726
91959
|
if (!/^\d+$/.test(name)) continue;
|
|
91727
91960
|
try {
|
|
91728
|
-
if (
|
|
91961
|
+
if (fs25.readFileSync(`/proc/${name}/environ`, "utf8").split("\0").includes(entry)) pids.push(Number(name));
|
|
91729
91962
|
} catch (error) {
|
|
91730
91963
|
if (strict && !["ENOENT", "ESRCH"].includes(error.code ?? "")) {
|
|
91731
|
-
const stat =
|
|
91964
|
+
const stat = fs25.statSync(`/proc/${name}`, { throwIfNoEntry: false });
|
|
91732
91965
|
if (stat?.uid === process.getuid?.()) throw error;
|
|
91733
91966
|
}
|
|
91734
91967
|
}
|
|
@@ -91761,6 +91994,24 @@ function markedInPs(entry, roots) {
|
|
|
91761
91994
|
}
|
|
91762
91995
|
return [...found];
|
|
91763
91996
|
}
|
|
91997
|
+
function marked(mark, roots = []) {
|
|
91998
|
+
if (WINDOWS3 || !mark.value) return [];
|
|
91999
|
+
const entry = `${mark.name}=${mark.value}`;
|
|
92000
|
+
try {
|
|
92001
|
+
const pids = process.platform === "linux" ? markedInProc(entry) : markedInPs(entry, roots);
|
|
92002
|
+
return pids.filter((pid) => pid !== process.pid);
|
|
92003
|
+
} catch {
|
|
92004
|
+
return [];
|
|
92005
|
+
}
|
|
92006
|
+
}
|
|
92007
|
+
function signal(pids, sig) {
|
|
92008
|
+
for (const pid of pids) {
|
|
92009
|
+
try {
|
|
92010
|
+
process.kill(pid, sig);
|
|
92011
|
+
} catch {
|
|
92012
|
+
}
|
|
92013
|
+
}
|
|
92014
|
+
}
|
|
91764
92015
|
function startedUnder(list, root, since) {
|
|
91765
92016
|
const self2 = list.procs.find((p2) => p2.pid === root);
|
|
91766
92017
|
const from = since ?? self2?.startedAt;
|
|
@@ -91804,6 +92055,21 @@ function procsOnWindows() {
|
|
|
91804
92055
|
});
|
|
91805
92056
|
return ps.status === 0 && ps.stdout ? readProcList(ps.stdout) : void 0;
|
|
91806
92057
|
}
|
|
92058
|
+
function killUnderOnWindows(pid, since) {
|
|
92059
|
+
if (!WINDOWS3 || !pid) return;
|
|
92060
|
+
const list = procsOnWindows();
|
|
92061
|
+
if (!list) return;
|
|
92062
|
+
const pids = startedUnder(list, pid, since).filter((p2) => p2 !== process.pid);
|
|
92063
|
+
if (!pids.length) return;
|
|
92064
|
+
spawnSync5("taskkill", ["/F", ...pids.flatMap((p2) => ["/PID", String(p2)])], { stdio: "ignore", windowsHide: true, timeout: 1e4 });
|
|
92065
|
+
}
|
|
92066
|
+
function killMarked(mark, agent) {
|
|
92067
|
+
if (WINDOWS3) {
|
|
92068
|
+
if (agent) killUnderOnWindows(agent.pid, agent.since);
|
|
92069
|
+
return;
|
|
92070
|
+
}
|
|
92071
|
+
signal(marked(mark), "SIGKILL");
|
|
92072
|
+
}
|
|
91807
92073
|
function processesStopped(mark, root) {
|
|
91808
92074
|
try {
|
|
91809
92075
|
if (WINDOWS3) {
|
|
@@ -91821,8 +92087,8 @@ function processesStopped(mark, root) {
|
|
|
91821
92087
|
}
|
|
91822
92088
|
|
|
91823
92089
|
// src/flow.ts
|
|
91824
|
-
import
|
|
91825
|
-
import
|
|
92090
|
+
import fs30 from "node:fs";
|
|
92091
|
+
import path33 from "node:path";
|
|
91826
92092
|
|
|
91827
92093
|
// ../cli/src/lib/question-block.ts
|
|
91828
92094
|
var MODES = ["single", "multi"];
|
|
@@ -91980,13 +92246,13 @@ function reviewOf(meta) {
|
|
|
91980
92246
|
}
|
|
91981
92247
|
|
|
91982
92248
|
// src/triage.ts
|
|
91983
|
-
import
|
|
91984
|
-
import
|
|
92249
|
+
import fs26 from "node:fs";
|
|
92250
|
+
import path29 from "node:path";
|
|
91985
92251
|
|
|
91986
92252
|
// ../cli/src/lib/signals/identity.ts
|
|
91987
|
-
import { createHash } from "node:crypto";
|
|
92253
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
91988
92254
|
var DERIVED = "derived-";
|
|
91989
|
-
var derivedSourceId = (seed) => `${DERIVED}${
|
|
92255
|
+
var derivedSourceId = (seed) => `${DERIVED}${createHash2("sha256").update(seed).digest("hex").slice(0, 16)}`;
|
|
91990
92256
|
|
|
91991
92257
|
// ../cli/src/lib/slug.ts
|
|
91992
92258
|
function slugify(s) {
|
|
@@ -91995,8 +92261,8 @@ function slugify(s) {
|
|
|
91995
92261
|
}
|
|
91996
92262
|
|
|
91997
92263
|
// src/triage.ts
|
|
91998
|
-
var triageDir = (board) =>
|
|
91999
|
-
var rejectedDir = (board) =>
|
|
92264
|
+
var triageDir = (board) => path29.join(board, "triage");
|
|
92265
|
+
var rejectedDir = (board) => path29.join(board, ".archive", REJECTIONS_TO_REVIEW);
|
|
92000
92266
|
var SCRATCH = ["dismissed", "archived"];
|
|
92001
92267
|
var stamp = (at2) => formatStamp(at2 ? new Date(at2) : /* @__PURE__ */ new Date());
|
|
92002
92268
|
function slugOf(title) {
|
|
@@ -92005,7 +92271,7 @@ function slugOf(title) {
|
|
|
92005
92271
|
function freeName(dir, title) {
|
|
92006
92272
|
const stem = slugOf(title);
|
|
92007
92273
|
let name = `${stem}.md`;
|
|
92008
|
-
for (let n = 2;
|
|
92274
|
+
for (let n = 2; fs26.existsSync(path29.join(dir, name)); n++) name = `${stem}-${n}.md`;
|
|
92009
92275
|
return name;
|
|
92010
92276
|
}
|
|
92011
92277
|
function itemText(item, fields = {}) {
|
|
@@ -92025,17 +92291,17 @@ ${item.text.trim()}
|
|
|
92025
92291
|
`;
|
|
92026
92292
|
}
|
|
92027
92293
|
function writeItem(dir, item, fields = {}) {
|
|
92028
|
-
|
|
92294
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
92029
92295
|
const name = freeName(dir, item.title);
|
|
92030
|
-
|
|
92296
|
+
fs26.writeFileSync(path29.join(dir, name), itemText(item, item.workflow ? { workflow: workflowName(item.workflow), ...fields } : fields));
|
|
92031
92297
|
return name;
|
|
92032
92298
|
}
|
|
92033
92299
|
function layOut(board, rejections) {
|
|
92034
92300
|
clearLaid(board);
|
|
92035
92301
|
const dir = rejectedDir(board);
|
|
92036
|
-
|
|
92302
|
+
fs26.mkdirSync(dir, { recursive: true });
|
|
92037
92303
|
for (const t2 of rejections.tasks) {
|
|
92038
|
-
|
|
92304
|
+
fs26.writeFileSync(path29.join(dir, `${t2.number}-${slugify(t2.title)}.md`), [
|
|
92039
92305
|
"---",
|
|
92040
92306
|
`title: ${yamlScalar(t2.title)}`,
|
|
92041
92307
|
"status: todo",
|
|
@@ -92050,20 +92316,20 @@ function layOut(board, rejections) {
|
|
|
92050
92316
|
].join("\n"));
|
|
92051
92317
|
}
|
|
92052
92318
|
for (const item of rejections.triage) {
|
|
92053
|
-
const sub =
|
|
92319
|
+
const sub = path29.join(triageDir(board), item.state === "dismissed" ? "dismissed" : "archived");
|
|
92054
92320
|
const fields = item.state === "dismissed" ? { dismissed_at: stamp(item.dismissed_at), dismissed_by: "user", ...item.dismissed_reason ? { dismissed_reason: item.dismissed_reason } : {} } : {};
|
|
92055
92321
|
writeItem(sub, item, fields);
|
|
92056
92322
|
}
|
|
92057
92323
|
return { tasks: rejections.tasks.map((t2) => t2.id), triage: rejections.triage.map((i) => i.id) };
|
|
92058
92324
|
}
|
|
92059
92325
|
function clearLaid(board) {
|
|
92060
|
-
|
|
92061
|
-
for (const sub of SCRATCH)
|
|
92326
|
+
fs26.rmSync(rejectedDir(board), { recursive: true, force: true });
|
|
92327
|
+
for (const sub of SCRATCH) fs26.rmSync(path29.join(triageDir(board), sub), { recursive: true, force: true });
|
|
92062
92328
|
}
|
|
92063
92329
|
|
|
92064
92330
|
// src/kanban-skill.ts
|
|
92065
|
-
import
|
|
92066
|
-
import
|
|
92331
|
+
import fs27 from "node:fs";
|
|
92332
|
+
import path30 from "node:path";
|
|
92067
92333
|
|
|
92068
92334
|
// ../skill/SKILL.md
|
|
92069
92335
|
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 +92342,24 @@ var CONTENT = `${SKILL_default.trimEnd()}
|
|
|
92076
92342
|
var MANAGED = /^<!-- ai4kanban \S+ -->$/m;
|
|
92077
92343
|
function prepareKanbanSkill(root) {
|
|
92078
92344
|
for (const folder of SKILL_FOLDERS) {
|
|
92079
|
-
const dir =
|
|
92080
|
-
const file2 =
|
|
92345
|
+
const dir = path30.join(root, folder);
|
|
92346
|
+
const file2 = path30.join(dir, "SKILL.md");
|
|
92081
92347
|
try {
|
|
92082
92348
|
let linked = false;
|
|
92083
92349
|
let at2 = root;
|
|
92084
92350
|
for (const name of `${folder}/SKILL.md`.split("/")) {
|
|
92085
|
-
at2 =
|
|
92086
|
-
if (
|
|
92351
|
+
at2 = path30.join(at2, name);
|
|
92352
|
+
if (fs27.lstatSync(at2, { throwIfNoEntry: false })?.isSymbolicLink()) linked = true;
|
|
92087
92353
|
}
|
|
92088
|
-
const held4 =
|
|
92089
|
-
const exists =
|
|
92354
|
+
const held4 = fs27.existsSync(file2) ? fs27.readFileSync(file2, "utf8") : null;
|
|
92355
|
+
const exists = fs27.lstatSync(dir, { throwIfNoEntry: false }) !== void 0;
|
|
92090
92356
|
if (linked || exists && !MANAGED.test(held4 ?? "")) {
|
|
92091
92357
|
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
92358
|
continue;
|
|
92093
92359
|
}
|
|
92094
92360
|
if (held4 !== CONTENT) {
|
|
92095
|
-
|
|
92096
|
-
|
|
92361
|
+
fs27.mkdirSync(dir, { recursive: true });
|
|
92362
|
+
fs27.writeFileSync(file2, CONTENT);
|
|
92097
92363
|
}
|
|
92098
92364
|
} catch (e2) {
|
|
92099
92365
|
throw new Error(`\u65E0\u6CD5\u51C6\u5907 ${folder}\uFF1A${e2 instanceof Error ? e2.message : String(e2)}`);
|
|
@@ -92103,27 +92369,18 @@ function prepareKanbanSkill(root) {
|
|
|
92103
92369
|
|
|
92104
92370
|
// ../cli/src/lib/skill/hook.ts
|
|
92105
92371
|
import { spawnSync as spawnSync6 } from "node:child_process";
|
|
92106
|
-
import
|
|
92107
|
-
import
|
|
92108
|
-
|
|
92109
|
-
// ../cli/src/lib/agent/landing-lock.ts
|
|
92110
|
-
var landingLimits = { staleMs: 5 * 6e4 };
|
|
92111
|
-
|
|
92112
|
-
// ../cli/src/lib/skill/hook.ts
|
|
92372
|
+
import fs28 from "node:fs";
|
|
92373
|
+
import path31 from "node:path";
|
|
92113
92374
|
var MARKER = "# ai4kanban commit guard";
|
|
92114
92375
|
var MARKER_LINE = new RegExp(`^${MARKER}\\b`, "m");
|
|
92115
92376
|
var CHECK = [
|
|
92116
92377
|
"try{",
|
|
92117
92378
|
'const[top,branch]=require("child_process")',
|
|
92118
|
-
'.execFileSync("git",["rev-parse","--show-toplevel","--abbrev-ref","HEAD"],{encoding:"utf8"
|
|
92379
|
+
'.execFileSync("git",["rev-parse","--show-toplevel","--abbrev-ref","HEAD"],{encoding:"utf8"}).trim().split("\\n");',
|
|
92119
92380
|
'if(/\\/\\.akb\\/worktrees\\//.test(top+"/"))process.exit(0);',
|
|
92120
92381
|
'const d=(JSON.parse(require("fs").readFileSync(process.argv[1],"utf8")).deliveries||[])',
|
|
92121
|
-
'.find((x)=>x&&x.status==="active"&&x.commitMode==="auto"&&x.targetBranch===branch&&x.landing
|
|
92382
|
+
'.find((x)=>x&&x.status==="active"&&x.commitMode==="auto"&&x.targetBranch===branch&&(!x.landing||x.landing.status!=="landed"));',
|
|
92122
92383
|
"if(!d)process.exit(0);",
|
|
92123
|
-
'const fs=require("fs"),lock=process.argv[2],entries=fs.readdirSync(lock);',
|
|
92124
|
-
`if(Date.now()-fs.statSync(lock).mtimeMs>${landingLimits.staleMs})process.exit(0);`,
|
|
92125
|
-
"if(entries.length!==1||!/^\\d+-[a-f0-9-]{36}$/.test(entries[0]))process.exit(0);",
|
|
92126
|
-
'try{process.kill(Number(entries[0].split("-")[0]),0)}catch(e){if(e.code!=="EPERM")process.exit(0)}',
|
|
92127
92384
|
"process.stderr.write(",
|
|
92128
92385
|
'"ai4kanban: delivery "+d.deliveryId+" is landing #"+d.cardId+" on "+branch+", so a commit here moves the target under it\\n"',
|
|
92129
92386
|
'+" \u2014 commit on another branch, or `git commit --no-verify` to commit anyway.\\n");',
|
|
@@ -92131,7 +92388,7 @@ var CHECK = [
|
|
|
92131
92388
|
"}catch(e){process.exit(0)}"
|
|
92132
92389
|
].join("");
|
|
92133
92390
|
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)}
|
|
92391
|
+
var guardLine = (sessions) => `if command -v node >/dev/null 2>&1; then node -e '${CHECK}' ${quoted(sessions)} || exit 1; fi`;
|
|
92135
92392
|
function hookScript(sessions) {
|
|
92136
92393
|
return [
|
|
92137
92394
|
"#!/bin/sh",
|
|
@@ -92147,7 +92404,7 @@ function hookScript(sessions) {
|
|
|
92147
92404
|
}
|
|
92148
92405
|
var read = (file2) => {
|
|
92149
92406
|
try {
|
|
92150
|
-
return
|
|
92407
|
+
return fs28.readFileSync(file2, "utf8");
|
|
92151
92408
|
} catch {
|
|
92152
92409
|
return null;
|
|
92153
92410
|
}
|
|
@@ -92159,7 +92416,7 @@ function hooksDir(root) {
|
|
|
92159
92416
|
windowsHide: true
|
|
92160
92417
|
});
|
|
92161
92418
|
if (out.error || out.status !== 0 || !out.stdout.trim()) return null;
|
|
92162
|
-
return
|
|
92419
|
+
return path31.resolve(root, out.stdout.trim());
|
|
92163
92420
|
}
|
|
92164
92421
|
function hasOwnHooksPath(root) {
|
|
92165
92422
|
const out = spawnSync6("git", ["config", "--get", "core.hooksPath"], {
|
|
@@ -92169,21 +92426,21 @@ function hasOwnHooksPath(root) {
|
|
|
92169
92426
|
});
|
|
92170
92427
|
return !out.error && out.status === 0 && !!out.stdout.trim();
|
|
92171
92428
|
}
|
|
92172
|
-
var sessionsPath = (root, board) =>
|
|
92173
|
-
function readCommitHook(root, board =
|
|
92429
|
+
var sessionsPath = (root, board) => path31.join(projectStateDir(board, root), SESSIONS_FILE);
|
|
92430
|
+
function readCommitHook(root, board = path31.join(root, "docs", "kanban")) {
|
|
92174
92431
|
const dir = hooksDir(root);
|
|
92175
92432
|
if (!dir) return { state: "no-git" };
|
|
92176
|
-
const where = shown(root,
|
|
92433
|
+
const where = shown(root, path31.join(dir, "pre-commit"));
|
|
92177
92434
|
const line = guardLine(sessionsPath(root, board));
|
|
92178
92435
|
if (hasOwnHooksPath(root)) return { state: "hooks-path", path: where, line };
|
|
92179
|
-
const file2 =
|
|
92180
|
-
if (
|
|
92436
|
+
const file2 = path31.join(dir, "pre-commit");
|
|
92437
|
+
if (fs28.lstatSync(file2, { throwIfNoEntry: false })?.isSymbolicLink()) return { state: "foreign", path: where, line };
|
|
92181
92438
|
const text3 = read(file2);
|
|
92182
92439
|
if (text3 === null) return { state: "absent", path: where };
|
|
92183
92440
|
return MARKER_LINE.test(text3) ? { state: "ours", path: where } : { state: "foreign", path: where, line };
|
|
92184
92441
|
}
|
|
92185
|
-
var shown = (root, p2) => (
|
|
92186
|
-
function installCommitHook(root, board =
|
|
92442
|
+
var shown = (root, p2) => (path31.relative(root, p2) || p2).split(path31.sep).join("/");
|
|
92443
|
+
function installCommitHook(root, board = path31.join(root, "docs", "kanban")) {
|
|
92187
92444
|
try {
|
|
92188
92445
|
return placeCommitHook(root, board);
|
|
92189
92446
|
} catch (e2) {
|
|
@@ -92200,12 +92457,12 @@ function placeCommitHook(root, board) {
|
|
|
92200
92457
|
${hook.line}`
|
|
92201
92458
|
};
|
|
92202
92459
|
}
|
|
92203
|
-
const file2 =
|
|
92460
|
+
const file2 = path31.join(root, hook.path);
|
|
92204
92461
|
try {
|
|
92205
|
-
|
|
92462
|
+
fs28.mkdirSync(path31.dirname(file2), { recursive: true });
|
|
92206
92463
|
const text3 = hookScript(sessionsPath(root, board));
|
|
92207
|
-
if (read(file2) !== text3)
|
|
92208
|
-
|
|
92464
|
+
if (read(file2) !== text3) fs28.writeFileSync(file2, text3, { mode: 493 });
|
|
92465
|
+
fs28.chmodSync(file2, 493);
|
|
92209
92466
|
} catch (e2) {
|
|
92210
92467
|
return { note: `${hook.path} could not be written \u2014 ${e2 instanceof Error ? e2.message : String(e2)}` };
|
|
92211
92468
|
}
|
|
@@ -92213,8 +92470,8 @@ ${hook.line}`
|
|
|
92213
92470
|
}
|
|
92214
92471
|
|
|
92215
92472
|
// src/built.ts
|
|
92216
|
-
import
|
|
92217
|
-
import
|
|
92473
|
+
import fs29 from "node:fs";
|
|
92474
|
+
import path32 from "node:path";
|
|
92218
92475
|
|
|
92219
92476
|
// ../cli/src/lib/spec-agent-names.ts
|
|
92220
92477
|
var LEGACY_SPEC_AGENT_NAMES = {
|
|
@@ -92390,12 +92647,12 @@ function checkWorkflowFiles(value, official = false) {
|
|
|
92390
92647
|
|
|
92391
92648
|
// src/built.ts
|
|
92392
92649
|
var isBuilder = (ws) => ws.workflow === BUILDER;
|
|
92393
|
-
var draftDir = (ws) =>
|
|
92394
|
-
var draftLine = (ws) => `<!-- workflow folder: ${
|
|
92650
|
+
var draftDir = (ws) => path32.join(ws.board, "workflows", draftFolder(ws.task));
|
|
92651
|
+
var draftLine = (ws) => `<!-- workflow folder: ${path32.relative(ws.cwd, draftDir(ws)).split(path32.sep).join("/")}/ -->`;
|
|
92395
92652
|
var skeleton = (name) => ["---", `name: ${/\s#/.test(name) ? JSON.stringify(name) : yamlScalar(name)}`, "needsArtifact: false", "---", ""].join("\n");
|
|
92396
92653
|
async function placeDraft(ws, read2) {
|
|
92397
92654
|
const dir = draftDir(ws);
|
|
92398
|
-
if (
|
|
92655
|
+
if (fs29.existsSync(path32.join(dir, WORKFLOW_FILE))) return { ok: true, value: void 0 };
|
|
92399
92656
|
const task = await read2.readTask(ws.task);
|
|
92400
92657
|
if (!task.ok) return task;
|
|
92401
92658
|
let files = { [WORKFLOW_FILE]: skeleton(task.value.title.trim() || "Untitled") };
|
|
@@ -92406,10 +92663,10 @@ async function placeDraft(ws, read2) {
|
|
|
92406
92663
|
files = held4.value.files;
|
|
92407
92664
|
}
|
|
92408
92665
|
for (const [name, text3] of Object.entries(files)) {
|
|
92409
|
-
const file2 =
|
|
92410
|
-
if (!file2.startsWith(dir +
|
|
92411
|
-
|
|
92412
|
-
|
|
92666
|
+
const file2 = path32.resolve(dir, name);
|
|
92667
|
+
if (!file2.startsWith(dir + path32.sep)) continue;
|
|
92668
|
+
fs29.mkdirSync(path32.dirname(file2), { recursive: true });
|
|
92669
|
+
fs29.writeFileSync(file2, text3);
|
|
92413
92670
|
}
|
|
92414
92671
|
return { ok: true, value: void 0 };
|
|
92415
92672
|
}
|
|
@@ -92421,19 +92678,19 @@ async function builtWorkflow(ws, akb) {
|
|
|
92421
92678
|
const dir = draftDir(ws);
|
|
92422
92679
|
let source;
|
|
92423
92680
|
try {
|
|
92424
|
-
source =
|
|
92681
|
+
source = fs29.readFileSync(path32.join(dir, WORKFLOW_FILE), "utf8");
|
|
92425
92682
|
} catch {
|
|
92426
92683
|
return fail(`workflows/${id}/${WORKFLOW_FILE} is missing.`);
|
|
92427
92684
|
}
|
|
92428
92685
|
const read2 = parseWorkflowFile(id, source, `workflows/${id}/${WORKFLOW_FILE}`);
|
|
92429
92686
|
if ("problem" in read2) return fail(read2.problem);
|
|
92430
92687
|
const names2 = named(read2.def);
|
|
92431
|
-
|
|
92688
|
+
fs29.rmSync(path32.join(dir, "agents"), { recursive: true, force: true });
|
|
92432
92689
|
for (const name of names2) {
|
|
92433
|
-
const from =
|
|
92434
|
-
if (
|
|
92690
|
+
const from = path32.join(ws.board, "agents", name);
|
|
92691
|
+
if (fs29.existsSync(from)) fs29.cpSync(from, path32.join(dir, "agents", name), { recursive: true });
|
|
92435
92692
|
}
|
|
92436
|
-
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2,
|
|
92693
|
+
const files = Object.fromEntries(filesUnder(dir).map((f2) => [f2, fs29.readFileSync(path32.join(dir, f2), "utf8")]));
|
|
92437
92694
|
const checked = checkWorkflowFiles(files);
|
|
92438
92695
|
if (!checked.ok) return fail(`${checked.file} ${checked.reason}.`);
|
|
92439
92696
|
const run2 = async (args) => answerOf2(await runAkb(akb, [...args, "--json", "--board", ws.board], { cwd: ws.cwd, board: ws.board }));
|
|
@@ -92468,7 +92725,7 @@ function spentBy(runs) {
|
|
|
92468
92725
|
}
|
|
92469
92726
|
function reviewOf2(file2) {
|
|
92470
92727
|
try {
|
|
92471
|
-
const meta = parseFrontmatter(
|
|
92728
|
+
const meta = parseFrontmatter(fs30.readFileSync(file2, "utf8")).meta;
|
|
92472
92729
|
return meta ? reviewOf(meta) : null;
|
|
92473
92730
|
} catch {
|
|
92474
92731
|
return null;
|
|
@@ -92476,8 +92733,8 @@ function reviewOf2(file2) {
|
|
|
92476
92733
|
}
|
|
92477
92734
|
function mcpConfig(servers, file2) {
|
|
92478
92735
|
if (!Object.keys(servers).length) return null;
|
|
92479
|
-
|
|
92480
|
-
|
|
92736
|
+
fs30.mkdirSync(path33.dirname(file2), { recursive: true });
|
|
92737
|
+
fs30.writeFileSync(file2, `${JSON.stringify({ mcpServers: servers }, null, 2)}
|
|
92481
92738
|
`);
|
|
92482
92739
|
return file2;
|
|
92483
92740
|
}
|
|
@@ -92516,7 +92773,7 @@ function deliveryEnding(ws, id) {
|
|
|
92516
92773
|
if (!id) return null;
|
|
92517
92774
|
let held4;
|
|
92518
92775
|
try {
|
|
92519
|
-
held4 = JSON.parse(
|
|
92776
|
+
held4 = JSON.parse(fs30.readFileSync(path33.join(ws.board, "deliveries", `${path33.basename(id)}.json`), "utf8"));
|
|
92520
92777
|
} catch {
|
|
92521
92778
|
return null;
|
|
92522
92779
|
}
|
|
@@ -92528,16 +92785,16 @@ function deliveryEnding(ws, id) {
|
|
|
92528
92785
|
return null;
|
|
92529
92786
|
}
|
|
92530
92787
|
function checkoutsOf(ws, id) {
|
|
92531
|
-
const dir =
|
|
92788
|
+
const dir = path33.join(ws.board, "deliveries");
|
|
92532
92789
|
let names2;
|
|
92533
92790
|
try {
|
|
92534
|
-
names2 =
|
|
92791
|
+
names2 = fs30.readdirSync(dir).filter((n) => n.endsWith(".json"));
|
|
92535
92792
|
} catch {
|
|
92536
92793
|
return [];
|
|
92537
92794
|
}
|
|
92538
92795
|
return names2.flatMap((n) => {
|
|
92539
92796
|
try {
|
|
92540
|
-
const held4 = JSON.parse(
|
|
92797
|
+
const held4 = JSON.parse(fs30.readFileSync(path33.join(dir, n), "utf8"));
|
|
92541
92798
|
return held4.cardId === id && held4.worktree && held4.deliveryId ? [held4.deliveryId] : [];
|
|
92542
92799
|
} catch {
|
|
92543
92800
|
return [];
|
|
@@ -92591,7 +92848,7 @@ function boardAkb(job, ws, deps, io, task) {
|
|
|
92591
92848
|
const at2 = args.includes("--") ? args.indexOf("--") : args.length;
|
|
92592
92849
|
const full = [...args.slice(0, at2), "--board", ws.board, ...args.slice(at2)];
|
|
92593
92850
|
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,
|
|
92851
|
+
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
92852
|
log?.end();
|
|
92596
92853
|
return ran;
|
|
92597
92854
|
};
|
|
@@ -92601,7 +92858,7 @@ async function setUp(job, ws, deps, io) {
|
|
|
92601
92858
|
const runtime = job.runtime;
|
|
92602
92859
|
const missing = unavailable(runtime, await deps.runtimes());
|
|
92603
92860
|
if (missing) return missing;
|
|
92604
|
-
if (!
|
|
92861
|
+
if (!fs30.existsSync(path33.join(ws.board, "config.md"))) {
|
|
92605
92862
|
const init = await akb(["raw", "init"]);
|
|
92606
92863
|
if (init.code !== 0) return refusal(init);
|
|
92607
92864
|
}
|
|
@@ -92618,7 +92875,7 @@ async function setUp(job, ws, deps, io) {
|
|
|
92618
92875
|
const used = await akb(["agent", "use", runtime]);
|
|
92619
92876
|
if (used.code !== 0) return refusal(used);
|
|
92620
92877
|
const servers = mcpServersOf(ws);
|
|
92621
|
-
const mcpFile =
|
|
92878
|
+
const mcpFile = path33.join(ws.board, ".sync", `${ws.task}.mcp.json`);
|
|
92622
92879
|
const takes = new Set(settingKeys(runtime));
|
|
92623
92880
|
const given = job.settings ?? {};
|
|
92624
92881
|
const values = { ...given, model: job.model ?? "" };
|
|
@@ -92676,8 +92933,8 @@ async function reviewRejections(job, ws, deps, io) {
|
|
|
92676
92933
|
if (ran.code !== 0) return { runs, failure: refusal(ran) };
|
|
92677
92934
|
const sent = await push2({ id: job.id, machineId: deps.machineId });
|
|
92678
92935
|
if (!sent.ok) return { runs, failure: sent.error };
|
|
92679
|
-
const
|
|
92680
|
-
return
|
|
92936
|
+
const marked2 = await deps.api.markReviewed(laid.tasks, laid.triage);
|
|
92937
|
+
return marked2.ok ? { runs } : { runs, failure: marked2.error };
|
|
92681
92938
|
});
|
|
92682
92939
|
}
|
|
92683
92940
|
async function learnRejections(job, ws, deps, io) {
|
|
@@ -92718,19 +92975,19 @@ async function runAgent(job, ws, deps, io) {
|
|
|
92718
92975
|
}
|
|
92719
92976
|
function writeTranscript(job, dir) {
|
|
92720
92977
|
if (!job.transcript) return "";
|
|
92721
|
-
const file2 =
|
|
92722
|
-
|
|
92723
|
-
|
|
92978
|
+
const file2 = path33.join(dir, "discussion.md");
|
|
92979
|
+
fs30.mkdirSync(dir, { recursive: true });
|
|
92980
|
+
fs30.writeFileSync(file2, `${job.transcript}
|
|
92724
92981
|
`);
|
|
92725
92982
|
return file2;
|
|
92726
92983
|
}
|
|
92727
92984
|
function pictures(job, ws, id) {
|
|
92728
92985
|
const dir = cardAssetsDir(ws, id);
|
|
92729
92986
|
if (!job.attachments.length || !dir) return "";
|
|
92730
|
-
|
|
92987
|
+
fs30.mkdirSync(dir, { recursive: true });
|
|
92731
92988
|
return job.attachments.map((a3, i) => {
|
|
92732
|
-
const file2 = `${i + 1}-${
|
|
92733
|
-
|
|
92989
|
+
const file2 = `${i + 1}-${path33.basename(a3.name).replace(/[^\w.-]+/g, "-")}`;
|
|
92990
|
+
fs30.writeFileSync(path33.join(dir, file2), Buffer.from(a3.content, "base64"));
|
|
92734
92991
|
return `
|
|
92735
92992
|
<Asset src=".assets/${id}/${file2}" label="${a3.name.replace(/["<>]/g, "") || file2}" />
|
|
92736
92993
|
`;
|
|
@@ -92738,7 +92995,7 @@ function pictures(job, ws, id) {
|
|
|
92738
92995
|
}
|
|
92739
92996
|
function cardFlags(ws, fields) {
|
|
92740
92997
|
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(
|
|
92998
|
+
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
92999
|
const lists = [["--modules", fields.modules ?? []], ["--related", open(fields.related)], ["--blocked-by", open(fields.blocked_by)]];
|
|
92743
93000
|
return [
|
|
92744
93001
|
...fields.priority ? ["--priority", fields.priority] : [],
|
|
@@ -92772,10 +93029,10 @@ async function runFlow(job, ws, deps, io) {
|
|
|
92772
93029
|
const placed = await placeDraft(ws, deps.api);
|
|
92773
93030
|
if (!placed.ok) return fail(placed.error);
|
|
92774
93031
|
}
|
|
92775
|
-
const body =
|
|
92776
|
-
|
|
93032
|
+
const body = path33.join(ws.board, ".sync", `${ws.task}.request.md`);
|
|
93033
|
+
fs30.mkdirSync(path33.dirname(body), { recursive: true });
|
|
92777
93034
|
if (!ws.number) return fail("This task has no number yet.");
|
|
92778
|
-
|
|
93035
|
+
fs30.writeFileSync(body, `${said.request || title}
|
|
92779
93036
|
${isBuilder(ws) ? `
|
|
92780
93037
|
${draftLine(ws)}
|
|
92781
93038
|
` : ""}${pictures(job, ws, ws.number)}`);
|
|
@@ -92793,7 +93050,7 @@ ${draftLine(ws)}
|
|
|
92793
93050
|
...cardFlags(ws, flow.metadata),
|
|
92794
93051
|
"--json"
|
|
92795
93052
|
]));
|
|
92796
|
-
|
|
93053
|
+
fs30.rmSync(body, { force: true });
|
|
92797
93054
|
if (!created.ok) return fail(created.error);
|
|
92798
93055
|
id = created.value;
|
|
92799
93056
|
}
|
|
@@ -92809,7 +93066,7 @@ ${draftLine(ws)}
|
|
|
92809
93066
|
if (io.lost()) return fail("");
|
|
92810
93067
|
return await workOn(card);
|
|
92811
93068
|
} finally {
|
|
92812
|
-
|
|
93069
|
+
fs30.rmSync(path33.join(ws.board, ".sync", `${ws.task}.discussion`), { recursive: true, force: true });
|
|
92813
93070
|
const left = working.get(key) - 1;
|
|
92814
93071
|
if (left) working.set(key, left);
|
|
92815
93072
|
else working.delete(key);
|
|
@@ -92826,31 +93083,18 @@ ${draftLine(ws)}
|
|
|
92826
93083
|
}
|
|
92827
93084
|
if (verb === "revise" && !text3) return fail("Say what to change.");
|
|
92828
93085
|
let note = verb === "resolve" || verb === "revise" ? text3 : "";
|
|
92829
|
-
let continuation;
|
|
92830
|
-
let expectedDelivery;
|
|
92831
93086
|
if (verb === "implement" && flow.resume) {
|
|
92832
|
-
const
|
|
92833
|
-
const resumed = answerOf2(restored);
|
|
93087
|
+
const resumed = answerOf2(await akb(["delivery", "resume", String(id2), "--json"]));
|
|
92834
93088
|
if (io.lost()) return fail("");
|
|
92835
93089
|
if (resumed?.landed) return { ok: true, report: { card: id2 } };
|
|
92836
|
-
if (restored.code !== 0 && resumed?.error?.reason !== "deliveryActive") return fail(resumed?.error?.message ?? refusal(restored));
|
|
92837
|
-
const deliveryId = resumed?.deliveryId ?? resumed?.error?.args?.id;
|
|
92838
|
-
if (!deliveryId) return fail("\u627E\u4E0D\u5230\u4E0A\u6B21\u6784\u5EFA\u7684\u4EA4\u4ED8\u8BB0\u5F55\uFF0C\u65E0\u6CD5\u6062\u590D\u539F\u5BF9\u8BDD\u3002");
|
|
92839
|
-
expectedDelivery = deliveryId;
|
|
92840
|
-
const previous = answerOf2(await akb(["run", "list", "--card", String(id2), "--all", "--json"]))?.runs?.filter((r2) => ["implement", "conflict", "hook"].includes(r2.action ?? "") && r2.deliveryId === deliveryId).sort((a3, b2) => (b2.startedAt ?? 0) - (a3.startedAt ?? 0))[0];
|
|
92841
|
-
if (!previous) return fail("\u627E\u4E0D\u5230\u4E0A\u6B21\u6784\u5EFA\u7684\u8FD0\u884C\u8BB0\u5F55\uFF0C\u65E0\u6CD5\u6062\u590D\u539F\u5BF9\u8BDD\u3002");
|
|
92842
|
-
continuation = previous.status === "done" ? ["run", "log", previous.sessionId] : ["run", "resume", previous.sessionId, "--require-session"];
|
|
92843
93090
|
} else if (verb === "implement" && text3) {
|
|
92844
93091
|
const resolved = await akb(["card", "resolve", String(id2), "--follow", "--events", "--json", "--", text3], true);
|
|
92845
93092
|
if (io.lost()) return fail("");
|
|
92846
93093
|
if (resolved.code !== 0) note = text3;
|
|
92847
93094
|
}
|
|
92848
|
-
const ran = await akb(
|
|
93095
|
+
const ran = await akb(["card", verb, String(id2), "--follow", "--events", "--json", ...carryArgs(verb), ...note ? ["--", note] : []], true);
|
|
92849
93096
|
if (io.lost()) return fail("");
|
|
92850
93097
|
const answer = answerOf2(ran);
|
|
92851
|
-
if (expectedDelivery && answer?.delivery?.id && answer.delivery.id !== expectedDelivery) {
|
|
92852
|
-
return fail("\u7EED\u8DD1\u8FD4\u56DE\u4E86\u5176\u4ED6\u4EA4\u4ED8\u7684\u7ED3\u679C\uFF0C\u539F\u4EA4\u4ED8\u4FDD\u6301\u672A\u5B8C\u6210\u3002");
|
|
92853
|
-
}
|
|
92854
93098
|
if (verb === "implement") {
|
|
92855
93099
|
const ending = deliveryEnding(ws, answer?.delivery?.id ?? answer?.error?.delivery?.id);
|
|
92856
93100
|
if (ending) return ending;
|
|
@@ -92882,7 +93126,7 @@ ${draftLine(ws)}
|
|
|
92882
93126
|
}
|
|
92883
93127
|
function carryArgs(verb) {
|
|
92884
93128
|
if (!["refine", "resolve", "revise", "implement"].includes(verb)) return [];
|
|
92885
|
-
const transcript = writeTranscript(job,
|
|
93129
|
+
const transcript = writeTranscript(job, path33.join(ws.board, ".sync", `${ws.task}.discussion`));
|
|
92886
93130
|
return [
|
|
92887
93131
|
...job.resume ? ["--session", job.resume, ...job.fork ? ["--fork"] : []] : [],
|
|
92888
93132
|
...transcript ? ["--transcript", transcript] : []
|
|
@@ -92901,15 +93145,15 @@ async function confirmFlowStopped(ws, job, deps) {
|
|
|
92901
93145
|
}
|
|
92902
93146
|
|
|
92903
93147
|
// src/recovery.ts
|
|
92904
|
-
import
|
|
92905
|
-
import
|
|
93148
|
+
import fs31 from "node:fs";
|
|
93149
|
+
import path34 from "node:path";
|
|
92906
93150
|
var PREPARE_REASON = "Runner update prepare.";
|
|
92907
93151
|
var UPDATE_REASON = "Runner update checkpoint.";
|
|
92908
93152
|
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) =>
|
|
93153
|
+
var fileOf = (id) => path34.join(runnerHome(), "checkpoints", `${encodeURIComponent(id)}.json`);
|
|
92910
93154
|
function readCheckpoint(id) {
|
|
92911
93155
|
try {
|
|
92912
|
-
const held4 = JSON.parse(
|
|
93156
|
+
const held4 = JSON.parse(fs31.readFileSync(fileOf(id), "utf8"));
|
|
92913
93157
|
if (!held4 || !Array.isArray(held4.pending) || !held4.pending.every((id2) => typeof id2 === "string")) throw new Error("\u8FDB\u5EA6\u683C\u5F0F\u9519\u8BEF");
|
|
92914
93158
|
return held4;
|
|
92915
93159
|
} catch (e2) {
|
|
@@ -92919,12 +93163,12 @@ function readCheckpoint(id) {
|
|
|
92919
93163
|
}
|
|
92920
93164
|
function saveCheckpoint(id, checkpoint) {
|
|
92921
93165
|
const file2 = fileOf(id);
|
|
92922
|
-
|
|
92923
|
-
|
|
92924
|
-
|
|
93166
|
+
fs31.mkdirSync(path34.dirname(file2), { recursive: true, mode: 448 });
|
|
93167
|
+
fs31.writeFileSync(`${file2}.tmp`, JSON.stringify(checkpoint), { mode: 384 });
|
|
93168
|
+
fs31.renameSync(`${file2}.tmp`, file2);
|
|
92925
93169
|
}
|
|
92926
93170
|
function clearCheckpoint(id) {
|
|
92927
|
-
|
|
93171
|
+
fs31.rmSync(fileOf(id), { force: true });
|
|
92928
93172
|
}
|
|
92929
93173
|
function checkpointEvent(checkpoint, event2) {
|
|
92930
93174
|
if (event2.kind === "tool_call") {
|
|
@@ -92936,19 +93180,30 @@ function checkpointEvent(checkpoint, event2) {
|
|
|
92936
93180
|
checkpoint.pending = checkpoint.pending.filter((id) => id !== event2.data.toolCallId);
|
|
92937
93181
|
}
|
|
92938
93182
|
}
|
|
93183
|
+
async function stopReply(id, timeout) {
|
|
93184
|
+
const checkpoint = readCheckpoint(id);
|
|
93185
|
+
if (!checkpoint?.mark) return checkpoint?.started === false;
|
|
93186
|
+
killMarked(checkpoint.mark, checkpoint.process);
|
|
93187
|
+
const until = Date.now() + timeout;
|
|
93188
|
+
while (!processesStopped(checkpoint.mark, checkpoint.process)) {
|
|
93189
|
+
if (Date.now() >= until) return false;
|
|
93190
|
+
await new Promise((resolve2) => setTimeout(resolve2, 50));
|
|
93191
|
+
}
|
|
93192
|
+
return true;
|
|
93193
|
+
}
|
|
92939
93194
|
|
|
92940
93195
|
// src/lock.ts
|
|
92941
|
-
import
|
|
92942
|
-
import
|
|
93196
|
+
import crypto5 from "node:crypto";
|
|
93197
|
+
import fs32 from "node:fs";
|
|
92943
93198
|
import net from "node:net";
|
|
92944
|
-
import
|
|
93199
|
+
import path35 from "node:path";
|
|
92945
93200
|
var RETRY_MS = 5e3;
|
|
92946
93201
|
var KIND_MS = 1e3;
|
|
92947
93202
|
var HOLDERS = ["claude-code", "codex", "terminal"];
|
|
92948
93203
|
function lockPath() {
|
|
92949
93204
|
const home4 = runnerHome();
|
|
92950
|
-
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${
|
|
92951
|
-
return
|
|
93205
|
+
if (process.platform === "win32") return `\\\\.\\pipe\\wildcrane-${crypto5.createHash("sha256").update(home4).digest("hex").slice(0, 16)}`;
|
|
93206
|
+
return path35.join(home4, "runner.sock");
|
|
92952
93207
|
}
|
|
92953
93208
|
function holdMachine(kind, onHeld, onWaiting) {
|
|
92954
93209
|
const where = lockPath();
|
|
@@ -92963,12 +93218,12 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
92963
93218
|
const attempt = () => {
|
|
92964
93219
|
timer = null;
|
|
92965
93220
|
if (closed) return;
|
|
92966
|
-
if (process.platform !== "win32")
|
|
93221
|
+
if (process.platform !== "win32") fs32.mkdirSync(path35.dirname(where), { recursive: true, mode: 448 });
|
|
92967
93222
|
const s = net.createServer((peer) => {
|
|
92968
93223
|
peers.add(peer);
|
|
92969
93224
|
peer.on("error", () => {
|
|
92970
93225
|
}).on("close", () => peers.delete(peer));
|
|
92971
|
-
peer.write(`${JSON.stringify({ kind })}
|
|
93226
|
+
peer.write(`${JSON.stringify({ kind, settings: 1 })}
|
|
92972
93227
|
`);
|
|
92973
93228
|
});
|
|
92974
93229
|
s.once("error", (e2) => {
|
|
@@ -93011,7 +93266,7 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
93011
93266
|
later(0);
|
|
93012
93267
|
});
|
|
93013
93268
|
removeIfStill.once("error", () => {
|
|
93014
|
-
|
|
93269
|
+
fs32.rmSync(where, { force: true });
|
|
93015
93270
|
later(50 + Math.random() * 200);
|
|
93016
93271
|
});
|
|
93017
93272
|
return;
|
|
@@ -93040,17 +93295,17 @@ function holdMachine(kind, onHeld, onWaiting) {
|
|
|
93040
93295
|
}
|
|
93041
93296
|
|
|
93042
93297
|
// 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) =>
|
|
93298
|
+
import crypto6 from "node:crypto";
|
|
93299
|
+
import fs33 from "node:fs";
|
|
93300
|
+
import path36 from "node:path";
|
|
93301
|
+
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
93302
|
+
var digest = (value) => crypto6.createHash("sha256").update(value).digest("hex");
|
|
93303
|
+
var git3 = (cwd, ...args) => execFileSync2("git", ["-C", cwd, ...args], { encoding: "utf8", timeout: 15e3, maxBuffer: 16 * 1024 * 1024, stdio: ["ignore", "pipe", "ignore"] });
|
|
93049
93304
|
function authorizedFolder(folder) {
|
|
93050
93305
|
if (!folder) return null;
|
|
93051
93306
|
try {
|
|
93052
|
-
const real =
|
|
93053
|
-
return allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
93307
|
+
const real = fs33.realpathSync(folder);
|
|
93308
|
+
return allowedProjects().some((root) => real === root || real.startsWith(root + path36.sep)) ? real : null;
|
|
93054
93309
|
} catch {
|
|
93055
93310
|
return null;
|
|
93056
93311
|
}
|
|
@@ -93060,9 +93315,9 @@ function progressFolder(job, folder) {
|
|
|
93060
93315
|
if (!token) return folder;
|
|
93061
93316
|
if (!/^[a-zA-Z0-9-]{1,80}$/.test(token)) return null;
|
|
93062
93317
|
try {
|
|
93063
|
-
const dir =
|
|
93064
|
-
if (!dir.startsWith(
|
|
93065
|
-
const marker = JSON.parse(
|
|
93318
|
+
const dir = fs33.realpathSync(path36.join(folder, ".akb", "handoffs", token));
|
|
93319
|
+
if (!dir.startsWith(fs33.realpathSync(folder) + path36.sep)) return null;
|
|
93320
|
+
const marker = JSON.parse(fs33.readFileSync(path36.join(dir, ".akb", "handoff.json"), "utf8"));
|
|
93066
93321
|
return marker.task === job.task && marker.isolation === token ? dir : null;
|
|
93067
93322
|
} catch {
|
|
93068
93323
|
return null;
|
|
@@ -93070,24 +93325,24 @@ function progressFolder(job, folder) {
|
|
|
93070
93325
|
}
|
|
93071
93326
|
function progressEvidence(job, folder) {
|
|
93072
93327
|
try {
|
|
93073
|
-
const board =
|
|
93074
|
-
const deliveries =
|
|
93075
|
-
const rows =
|
|
93328
|
+
const board = path36.join(folder, ".akb", "kanban");
|
|
93329
|
+
const deliveries = path36.join(board, "deliveries");
|
|
93330
|
+
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
93331
|
const row = rows[0];
|
|
93077
93332
|
if (!row?.deliveryId || !row.base || !row.branch || !row.worktree || row.commitMode !== "auto") return null;
|
|
93078
|
-
const tree =
|
|
93079
|
-
if (!tree.startsWith(
|
|
93333
|
+
const tree = fs33.realpathSync(path36.resolve(folder, row.worktree));
|
|
93334
|
+
if (!tree.startsWith(fs33.realpathSync(folder) + path36.sep)) return null;
|
|
93080
93335
|
if (git3(tree, "rev-parse", "--show-toplevel").trim() !== tree) return null;
|
|
93081
93336
|
if (git3(tree, "branch", "--show-current").trim() !== row.branch) return null;
|
|
93082
93337
|
git3(tree, "cat-file", "-e", `${row.base}^{commit}`);
|
|
93083
93338
|
const changed = git3(tree, "ls-files", "-z", "--cached", "--others", "--exclude-standard").split("\0").filter(Boolean).sort();
|
|
93084
93339
|
const files = changed.map((name) => {
|
|
93085
|
-
const file2 =
|
|
93340
|
+
const file2 = path36.join(tree, name);
|
|
93086
93341
|
try {
|
|
93087
|
-
const stat =
|
|
93088
|
-
if (stat.isSymbolicLink()) return [name, "link", digest(
|
|
93342
|
+
const stat = fs33.lstatSync(file2);
|
|
93343
|
+
if (stat.isSymbolicLink()) return [name, "link", digest(fs33.readlinkSync(file2))];
|
|
93089
93344
|
if (!stat.isFile()) throw new Error("\u65E0\u6CD5\u9A8C\u8BC1\u6587\u4EF6\u7C7B\u578B");
|
|
93090
|
-
return [name, stat.mode & 511, digest(
|
|
93345
|
+
return [name, stat.mode & 511, digest(fs33.readFileSync(file2))];
|
|
93091
93346
|
} catch (e2) {
|
|
93092
93347
|
if (e2.code === "ENOENT") return [name, "deleted"];
|
|
93093
93348
|
throw e2;
|
|
@@ -93112,56 +93367,56 @@ function progressEvidence(job, folder) {
|
|
|
93112
93367
|
function restartFolder(job, folder) {
|
|
93113
93368
|
const token = job.handoff?.isolation ?? job.id;
|
|
93114
93369
|
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 (
|
|
93370
|
+
const dir = path36.join(folder, ".akb", "handoffs", token);
|
|
93371
|
+
const marker = path36.join(dir, ".akb", "handoff.json");
|
|
93372
|
+
for (const parent of [path36.join(folder, ".akb"), path36.dirname(dir), dir]) {
|
|
93373
|
+
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
93374
|
}
|
|
93120
|
-
if (
|
|
93375
|
+
if (fs33.existsSync(dir)) {
|
|
93121
93376
|
if (job.handoff?.recovering) {
|
|
93122
93377
|
try {
|
|
93123
|
-
const saved = JSON.parse(
|
|
93124
|
-
if (saved.task === job.task && saved.isolation === token && git3(dir, "rev-parse", "--show-toplevel").trim() ===
|
|
93378
|
+
const saved = JSON.parse(fs33.readFileSync(marker, "utf8"));
|
|
93379
|
+
if (saved.task === job.task && saved.isolation === token && git3(dir, "rev-parse", "--show-toplevel").trim() === fs33.realpathSync(dir)) return dir;
|
|
93125
93380
|
} catch {
|
|
93126
93381
|
}
|
|
93127
93382
|
}
|
|
93128
93383
|
throw new Error("\u91CD\u542F\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u8BF7\u91CD\u65B0\u68C0\u67E5\u3002");
|
|
93129
93384
|
}
|
|
93130
|
-
|
|
93385
|
+
fs33.mkdirSync(path36.dirname(dir), { recursive: true });
|
|
93131
93386
|
git3(folder, "worktree", "add", "--detach", dir, "HEAD");
|
|
93132
|
-
if (
|
|
93133
|
-
|
|
93134
|
-
|
|
93387
|
+
if (fs33.lstatSync(path36.dirname(marker), { throwIfNoEntry: false })?.isSymbolicLink()) throw new Error("\u9694\u79BB\u6807\u8BB0\u76EE\u5F55\u65E0\u6548\u3002");
|
|
93388
|
+
fs33.mkdirSync(path36.dirname(marker), { recursive: true });
|
|
93389
|
+
fs33.writeFileSync(marker, JSON.stringify({ task: job.task, isolation: token }), { flag: "wx" });
|
|
93135
93390
|
return dir;
|
|
93136
93391
|
}
|
|
93137
93392
|
|
|
93138
93393
|
// src/jobs.ts
|
|
93139
93394
|
import { spawn as spawn4 } from "node:child_process";
|
|
93140
|
-
import
|
|
93141
|
-
import
|
|
93395
|
+
import fs35 from "node:fs";
|
|
93396
|
+
import path38 from "node:path";
|
|
93142
93397
|
|
|
93143
93398
|
// ../cli/src/lib/agent/catalog.ts
|
|
93144
|
-
import
|
|
93145
|
-
import
|
|
93399
|
+
import fs34 from "node:fs";
|
|
93400
|
+
import path37 from "node:path";
|
|
93146
93401
|
var CATALOGUE = "https://models.dev/api.json";
|
|
93147
93402
|
var FRESH_FOR_MS = 24 * 60 * 6e4;
|
|
93148
93403
|
var ANSWER_BY_MS = 2e4;
|
|
93149
93404
|
function cacheFile() {
|
|
93150
|
-
return
|
|
93405
|
+
return path37.join(machineHome(), "models-dev.json");
|
|
93151
93406
|
}
|
|
93152
93407
|
var held2;
|
|
93153
93408
|
function readCache() {
|
|
93154
93409
|
const file2 = cacheFile();
|
|
93155
93410
|
let stamp2;
|
|
93156
93411
|
try {
|
|
93157
|
-
const stat =
|
|
93412
|
+
const stat = fs34.statSync(file2);
|
|
93158
93413
|
stamp2 = `${stat.mtimeMs}:${stat.size}`;
|
|
93159
93414
|
} catch {
|
|
93160
93415
|
return void 0;
|
|
93161
93416
|
}
|
|
93162
93417
|
if (held2?.stamp === stamp2) return held2.cached;
|
|
93163
93418
|
try {
|
|
93164
|
-
const data = JSON.parse(
|
|
93419
|
+
const data = JSON.parse(fs34.readFileSync(file2, "utf8"));
|
|
93165
93420
|
if (!data || typeof data.limits !== "object" || !data.limits) return void 0;
|
|
93166
93421
|
const cached2 = {
|
|
93167
93422
|
fetchedAt: typeof data.fetchedAt === "number" ? data.fetchedAt : 0,
|
|
@@ -93200,8 +93455,8 @@ function refreshCatalog() {
|
|
|
93200
93455
|
const limits = limitsIn(await answer.json());
|
|
93201
93456
|
if (Object.keys(limits).length === 0) return;
|
|
93202
93457
|
const file2 = cacheFile();
|
|
93203
|
-
|
|
93204
|
-
|
|
93458
|
+
fs34.mkdirSync(path37.dirname(file2), { recursive: true });
|
|
93459
|
+
fs34.writeFileSync(file2, JSON.stringify({ fetchedAt: Date.now(), limits }));
|
|
93205
93460
|
} catch {
|
|
93206
93461
|
}
|
|
93207
93462
|
})();
|
|
@@ -93276,32 +93531,32 @@ var defaultDeps = (machineId2) => ({
|
|
|
93276
93531
|
akb: currentAkb,
|
|
93277
93532
|
runtimes: detectRuntimes
|
|
93278
93533
|
});
|
|
93279
|
-
var ownFolder = () =>
|
|
93534
|
+
var ownFolder = () => path38.join(runnerHome(), "work");
|
|
93280
93535
|
function folderFor(job) {
|
|
93281
93536
|
if (!job.projectDir) {
|
|
93282
|
-
const cwd =
|
|
93283
|
-
|
|
93537
|
+
const cwd = path38.join(ownFolder(), job.id);
|
|
93538
|
+
fs35.mkdirSync(cwd, { recursive: true });
|
|
93284
93539
|
return { cwd };
|
|
93285
93540
|
}
|
|
93286
93541
|
const real = realpath4(job.projectDir);
|
|
93287
|
-
if (real && allowedProjects().some((root) => real === root || real.startsWith(root +
|
|
93542
|
+
if (real && allowedProjects().some((root) => real === root || real.startsWith(root + path38.sep))) return { cwd: real };
|
|
93288
93543
|
return { refused: `This Runner is not allowed to work in ${job.projectDir}.` };
|
|
93289
93544
|
}
|
|
93290
93545
|
function realpath4(p2) {
|
|
93291
93546
|
try {
|
|
93292
|
-
return
|
|
93547
|
+
return fs35.realpathSync(p2);
|
|
93293
93548
|
} catch {
|
|
93294
93549
|
return null;
|
|
93295
93550
|
}
|
|
93296
93551
|
}
|
|
93297
|
-
var attachmentsOf = (job) =>
|
|
93552
|
+
var attachmentsOf = (job) => path38.join(runnerHome(), "attachments", job.id);
|
|
93298
93553
|
function writeAttachments(job) {
|
|
93299
93554
|
if (!job.attachments.length) return "";
|
|
93300
93555
|
const dir = attachmentsOf(job);
|
|
93301
|
-
|
|
93556
|
+
fs35.mkdirSync(dir, { recursive: true });
|
|
93302
93557
|
const files = job.attachments.map((a3) => {
|
|
93303
|
-
const file2 =
|
|
93304
|
-
|
|
93558
|
+
const file2 = path38.join(dir, path38.basename(a3.name));
|
|
93559
|
+
fs35.writeFileSync(file2, Buffer.from(a3.content, "base64"));
|
|
93305
93560
|
return file2;
|
|
93306
93561
|
});
|
|
93307
93562
|
return `
|
|
@@ -93568,24 +93823,32 @@ async function runJob(id, deps, track = () => {
|
|
|
93568
93823
|
const claim = await deps.api.claimJob(deps.machineId, id);
|
|
93569
93824
|
if (!claim.ok || !claim.value.claimed || stopped2() || !held3(deps, lease)) return;
|
|
93570
93825
|
const job = claim.value.job;
|
|
93826
|
+
if (deps.authorize && !await deps.authorize(job)) {
|
|
93827
|
+
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");
|
|
93828
|
+
return;
|
|
93829
|
+
}
|
|
93571
93830
|
const releases = [];
|
|
93572
93831
|
try {
|
|
93573
93832
|
await runClaimed(job, { ...deps, akb: deps.akb() }, track, (dir) => releases.push(hold(dir)), lease);
|
|
93574
93833
|
} finally {
|
|
93575
93834
|
for (const release2 of releases) release2();
|
|
93576
|
-
|
|
93835
|
+
fs35.rmSync(attachmentsOf(job), { recursive: true, force: true });
|
|
93577
93836
|
}
|
|
93578
93837
|
}
|
|
93579
93838
|
async function runClaimed(job, deps, track, keep2, lease) {
|
|
93580
93839
|
const id = job.id;
|
|
93581
|
-
const checkpoint = readCheckpoint(id) ?? { pending: [] };
|
|
93582
|
-
const recovering = checkpoint.updating === true;
|
|
93840
|
+
const checkpoint = readCheckpoint(id) ?? (job.recoveryOf ? readCheckpoint(job.recoveryOf) : null) ?? { pending: [], started: false };
|
|
93841
|
+
const recovering = checkpoint.updating === true || !!job.recoveryOf;
|
|
93583
93842
|
const persist = () => {
|
|
93584
93843
|
checkpoint.updating ||= readCheckpoint(id)?.updating;
|
|
93585
93844
|
saveCheckpoint(id, checkpoint);
|
|
93586
93845
|
};
|
|
93587
|
-
|
|
93588
|
-
|
|
93846
|
+
const manual = job.manualRecovery === true;
|
|
93847
|
+
if (manual && checkpoint.completed?.outcome === "failed") delete checkpoint.completed;
|
|
93848
|
+
checkpoint.session ??= job.resume ?? void 0;
|
|
93849
|
+
if (recovering && !checkpoint.completed && (!manual && (checkpoint.pending.length || checkpoint.opaque) || !job.flow && checkpoint.started && !checkpoint.session)) {
|
|
93850
|
+
saveCheckpoint(id, checkpoint);
|
|
93851
|
+
await deps.api.finishJob(deps.machineId, id, "failed", job.recoveryOf ? "recovery_failed" : UNCERTAIN);
|
|
93589
93852
|
return;
|
|
93590
93853
|
}
|
|
93591
93854
|
if (recovering && checkpoint.session) job = { ...job, resume: checkpoint.session, fork: false };
|
|
@@ -93653,7 +93916,7 @@ async function runClaimed(job, deps, track, keep2, lease) {
|
|
|
93653
93916
|
discussed = board.board;
|
|
93654
93917
|
}
|
|
93655
93918
|
if (job.discussion) {
|
|
93656
|
-
const wrote = recovering &&
|
|
93919
|
+
const wrote = recovering && fs35.existsSync(goalsFileOf(job)) ? { file: goalsFileOf(job) } : await writeGoals({ ...job, discussion: job.discussion }, deps.api.listWorkflows);
|
|
93657
93920
|
if ("error" in wrote) throw new Error(wrote.error);
|
|
93658
93921
|
goalFile = wrote.file;
|
|
93659
93922
|
}
|
|
@@ -93666,7 +93929,7 @@ async function runClaimed(job, deps, track, keep2, lease) {
|
|
|
93666
93929
|
This task came out of a discussion. Read it for what the card leaves out: ${file2}` : "";
|
|
93667
93930
|
const promptOf = (said2) => {
|
|
93668
93931
|
const lines = (head2 + said2).trim();
|
|
93669
|
-
const prompt = recovering && checkpoint.started ? "
|
|
93932
|
+
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
93933
|
return lines ? `${lines}
|
|
93671
93934
|
|
|
93672
93935
|
---
|
|
@@ -93674,9 +93937,9 @@ This task came out of a discussion. Read it for what the card leaves out: ${file
|
|
|
93674
93937
|
${prompt}` : prompt;
|
|
93675
93938
|
};
|
|
93676
93939
|
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: { ...
|
|
93940
|
+
let p2 = deps.plan(job.runtime, promptOf(said2), cwd, resume, job.model, settingsOf(job), fork, cloudLanguage(job));
|
|
93941
|
+
if (ws) p2 = { ...p2, env: akbEnv(deps.akb, ws.board, ws.task, cloudLanguage(job), p2.env) };
|
|
93942
|
+
if (goalFile) p2 = { ...p2, env: { ...akbEnv(deps.akb, discussed, void 0, cloudLanguage(job), p2.env), KANBAN_GOALS: goalFile, KANBAN_IDEAS: goalFile } };
|
|
93680
93943
|
if (job.chat || job.discussion) {
|
|
93681
93944
|
const { CLAUDE_CODE_MAX_RETRIES: _2, ...env2 } = p2.env;
|
|
93682
93945
|
p2 = { ...p2, env: env2 };
|
|
@@ -93695,9 +93958,14 @@ ${prompt}` : prompt;
|
|
|
93695
93958
|
await deps.api.finishJob(deps.machineId, id, "failed", e2 instanceof Error ? e2.message : String(e2));
|
|
93696
93959
|
return;
|
|
93697
93960
|
}
|
|
93961
|
+
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
93962
|
if (!held3(deps, lease)) return;
|
|
93699
93963
|
const stream = streamOut(deps, id, lease);
|
|
93964
|
+
if (run2?.startNote) stream.out(`${run2.startNote}
|
|
93965
|
+
`);
|
|
93966
|
+
let replyProgress = false;
|
|
93700
93967
|
const remember = (event2) => {
|
|
93968
|
+
if (["message", "tool_call", "tool_call_update"].includes(event2.kind)) replyProgress = true;
|
|
93701
93969
|
if (stream.lost()) return;
|
|
93702
93970
|
checkpointEvent(checkpoint, event2);
|
|
93703
93971
|
const session = run2?.session();
|
|
@@ -93758,6 +94026,7 @@ ${prompt}` : prompt;
|
|
|
93758
94026
|
if (!ended3.ok) return finish(deps, id, lease, "failed", ended3.reason, proof);
|
|
93759
94027
|
return sendBack(deps, id, lease, ws, { ...ended3.report, ...proof }, () => keepChat(job, ended3.report.reply));
|
|
93760
94028
|
}
|
|
94029
|
+
checkpoint.mark = stopMark();
|
|
93761
94030
|
checkpoint.started = true;
|
|
93762
94031
|
checkpoint.opaque = !run2.converse && !run2.renderer?.events;
|
|
93763
94032
|
checkpoint.session = run2.session() ?? checkpoint.session;
|
|
@@ -93765,7 +94034,11 @@ ${prompt}` : prompt;
|
|
|
93765
94034
|
if (run2.converse) {
|
|
93766
94035
|
const plan3 = run2;
|
|
93767
94036
|
const converse = run2.converse;
|
|
93768
|
-
const child = spawn4(plan3.command, plan3.args, { cwd, env: plan3.env, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94037
|
+
const child = spawn4(plan3.command, plan3.args, { cwd, env: markEnv(plan3.env, checkpoint.mark), detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94038
|
+
if (child.pid) {
|
|
94039
|
+
checkpoint.process = { pid: child.pid, since: Date.now() };
|
|
94040
|
+
persist();
|
|
94041
|
+
}
|
|
93769
94042
|
stream.adopt(child);
|
|
93770
94043
|
child.stdin.on("error", () => {
|
|
93771
94044
|
});
|
|
@@ -93773,22 +94046,33 @@ ${prompt}` : prompt;
|
|
|
93773
94046
|
child.stderr.on("data", (chunk) => stream.out(quietLines(plan3, chunk)));
|
|
93774
94047
|
const spawned = new Promise((resolve2) => child.on("error", (e2) => resolve2(e2.message)));
|
|
93775
94048
|
const end = await Promise.race([
|
|
93776
|
-
converse(child, remember),
|
|
94049
|
+
converse(child, remember, false),
|
|
93777
94050
|
spawned.then((error) => ({ ok: false, error })),
|
|
93778
94051
|
// Killed, the turn ends with what it said so far; one that never does is not waited on.
|
|
93779
94052
|
stream.whenAsked.then(() => wait2(KILL_GRACE_MS * 2)).then(() => ({ ok: true }))
|
|
93780
94053
|
]);
|
|
94054
|
+
if (!end.ok && !recovering && job.resume && (job.chat || job.discussion) && sessionMissing(end.error ?? "") && !replyProgress && !checkpoint.pending.length && !stream.asked() && !stream.lost()) {
|
|
94055
|
+
stop(child);
|
|
94056
|
+
await stream.end();
|
|
94057
|
+
if (!await stream.confirmed()) return finish(deps, id, lease, "failed", "recovery_failed");
|
|
94058
|
+
clearCheckpoint(id);
|
|
94059
|
+
return runClaimed({ ...job, resume: null, fork: false, sessionFallback: true }, deps, track, keep2, lease);
|
|
94060
|
+
}
|
|
93781
94061
|
if (!stream.asked()) complete(end.ok ? "done" : "failed", told(report(job, plan3, end)), end.ok ? void 0 : end.error);
|
|
93782
94062
|
stop(child);
|
|
93783
94063
|
await stream.end();
|
|
93784
94064
|
if (stream.lost()) return;
|
|
93785
94065
|
const ok = end.ok || stream.asked();
|
|
93786
94066
|
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.
|
|
94067
|
+
if (!ok || !ws) return finish(deps, id, lease, ok ? "done" : "failed", ok ? "" : replyReason(end.ok ? void 0 : end.error, job), said2);
|
|
93788
94068
|
return sendBack(deps, id, lease, ws, said2, () => keepChat(job, said2.reply));
|
|
93789
94069
|
}
|
|
93790
94070
|
const printed = async (plan3) => {
|
|
93791
|
-
const child = spawn4(plan3.command, plan3.args, { cwd, env: plan3.env, detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94071
|
+
const child = spawn4(plan3.command, plan3.args, { cwd, env: markEnv(plan3.env, checkpoint.mark), detached: process.platform !== "win32", stdio: ["pipe", "pipe", "pipe"] });
|
|
94072
|
+
if (child.pid) {
|
|
94073
|
+
checkpoint.process = { pid: child.pid, since: Date.now() };
|
|
94074
|
+
persist();
|
|
94075
|
+
}
|
|
93792
94076
|
stream.adopt(child);
|
|
93793
94077
|
child.stdin.on("error", () => {
|
|
93794
94078
|
});
|
|
@@ -93830,17 +94114,18 @@ ${prompt}` : prompt;
|
|
|
93830
94114
|
if (fresh && ended2.code !== 0 && plan2.renderer.result() === void 0 && !ended2.acted && (!missingSessionOnly || sessionMissing(`${ended2.stderr}
|
|
93831
94115
|
${plan2.renderer.failure?.() ?? ""}`)) && !stream.asked() && !stream.lost()) {
|
|
93832
94116
|
plan2 = fresh();
|
|
94117
|
+
job = { ...job, sessionFallback: missingSessionOnly };
|
|
93833
94118
|
run2 = plan2;
|
|
93834
94119
|
ended2 = await printed(plan2);
|
|
93835
94120
|
}
|
|
93836
94121
|
const renderer = plan2.renderer;
|
|
93837
94122
|
if (!stream.asked()) {
|
|
93838
|
-
const reason = ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`);
|
|
94123
|
+
const reason = replyReason(ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`), job);
|
|
93839
94124
|
complete(reason ? "failed" : "done", told(report(job, plan2)), reason);
|
|
93840
94125
|
}
|
|
93841
94126
|
await stream.end();
|
|
93842
94127
|
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}.`);
|
|
94128
|
+
const failure = stream.asked() ? void 0 : replyReason(ended2.error ?? renderer.failure?.() ?? (ended2.code === 0 ? void 0 : `Exited with code ${ended2.code}.`), job);
|
|
93844
94129
|
const said = told(stream.asked() ? cutShort(report(job, plan2), stream.said()) : report(job, plan2));
|
|
93845
94130
|
if (failure || !ws) return finish(deps, id, lease, failure ? "failed" : "done", failure, said);
|
|
93846
94131
|
return sendBack(deps, id, lease, ws, said, () => keepChat(job, said.reply));
|
|
@@ -93880,18 +94165,24 @@ async function runAgentJob(job, deps, track, keep2, lease, checkpoint, persist)
|
|
|
93880
94165
|
}
|
|
93881
94166
|
var quietLines = (plan2, chunk) => chunk.split("\n").filter((line) => line && !plan2.quiet(line)).map((line) => `${line}
|
|
93882
94167
|
`).join("");
|
|
93883
|
-
var
|
|
93884
|
-
|
|
94168
|
+
var replyReason = (reason, job) => {
|
|
94169
|
+
if (!reason) return reason;
|
|
94170
|
+
if (job.recoveryOf) return "recovery_failed";
|
|
94171
|
+
if (job.sessionFallback && !/auth|login|log.in|permission|directory|ENOENT|not installed|rate.limit|network|connect|登录|权限|目录/i.test(reason)) return "session_unavailable";
|
|
94172
|
+
return reason;
|
|
94173
|
+
};
|
|
94174
|
+
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));
|
|
94175
|
+
function signalTree(child, signal2) {
|
|
93885
94176
|
if (!child.pid) return;
|
|
93886
94177
|
if (process.platform === "win32") {
|
|
93887
94178
|
const kill = spawn4("taskkill", ["/PID", String(child.pid), "/T", "/F"], { stdio: "ignore" });
|
|
93888
|
-
kill.on("error", () => child.kill(
|
|
94179
|
+
kill.on("error", () => child.kill(signal2));
|
|
93889
94180
|
return;
|
|
93890
94181
|
}
|
|
93891
94182
|
try {
|
|
93892
|
-
process.kill(-child.pid,
|
|
94183
|
+
process.kill(-child.pid, signal2);
|
|
93893
94184
|
} catch {
|
|
93894
|
-
child.kill(
|
|
94185
|
+
child.kill(signal2);
|
|
93895
94186
|
}
|
|
93896
94187
|
}
|
|
93897
94188
|
var stop = (child) => {
|
|
@@ -93964,8 +94255,8 @@ async function runTest(job, deps, lease) {
|
|
|
93964
94255
|
const report2 = (await deps.runtimes()).find((r2) => r2.name === job.runtime);
|
|
93965
94256
|
if (!report2?.installed) return finish2("failed", "not_installed");
|
|
93966
94257
|
if (report2.loggedIn === false) return finish2("failed", "signed_out");
|
|
93967
|
-
const cwd =
|
|
93968
|
-
|
|
94258
|
+
const cwd = path38.join(ownFolder(), "test");
|
|
94259
|
+
fs35.mkdirSync(cwd, { recursive: true });
|
|
93969
94260
|
const run2 = deps.plan(job.runtime, job.prompt, cwd, null, job.model, settingsOf(job));
|
|
93970
94261
|
const startedAt = Date.now();
|
|
93971
94262
|
if (run2.converse) {
|
|
@@ -94120,9 +94411,15 @@ var POLL_MS = 6e4;
|
|
|
94120
94411
|
var BACKOFF_MS3 = [1e3, 2e3, 5e3, 1e4, 3e4];
|
|
94121
94412
|
var LOOK_LATE_MS = 6e4;
|
|
94122
94413
|
function startRunner(options) {
|
|
94414
|
+
adoptLegacy();
|
|
94415
|
+
const account = readSession()?.subject;
|
|
94416
|
+
const generation = accountGeneration();
|
|
94417
|
+
const releaseRecord = executorRecord();
|
|
94123
94418
|
let registration = null;
|
|
94124
94419
|
let connected = false;
|
|
94125
94420
|
let closed = false;
|
|
94421
|
+
let ownsExecution = false;
|
|
94422
|
+
let redetect = false;
|
|
94126
94423
|
let preparing = false;
|
|
94127
94424
|
let attempts = 0;
|
|
94128
94425
|
let live = null;
|
|
@@ -94140,7 +94437,12 @@ function startRunner(options) {
|
|
|
94140
94437
|
const stopped2 = new Promise((resolve2) => stop2 = resolve2);
|
|
94141
94438
|
const deps = () => {
|
|
94142
94439
|
const base = options.deps ?? defaultDeps(registration.machineId);
|
|
94143
|
-
return { ...base,
|
|
94440
|
+
return { ...base, ...options.deps ? {} : { authorize: async (job) => {
|
|
94441
|
+
if (!validAccount()) return false;
|
|
94442
|
+
if (!job.projectDir) return true;
|
|
94443
|
+
const folders2 = await listFolders(registration.machineId);
|
|
94444
|
+
return validAccount() && folders2.ok && folders2.value.folders.some((f2) => f2.project === job.project && f2.path === job.projectDir);
|
|
94445
|
+
} }, runtimes: () => base.runtimes().then(redetected) };
|
|
94144
94446
|
};
|
|
94145
94447
|
const register2 = async () => {
|
|
94146
94448
|
const answer = await register(registration);
|
|
@@ -94155,7 +94457,7 @@ function startRunner(options) {
|
|
|
94155
94457
|
};
|
|
94156
94458
|
const idle2 = () => running.size ? t.running(running.size) : t.connected(registration.machineName);
|
|
94157
94459
|
const schedule = (ms) => {
|
|
94158
|
-
if (closed) return;
|
|
94460
|
+
if (closed || !ownsExecution) return;
|
|
94159
94461
|
if (timer) clearTimeout(timer);
|
|
94160
94462
|
timer = setTimeout(tick, ms);
|
|
94161
94463
|
};
|
|
@@ -94203,9 +94505,14 @@ function startRunner(options) {
|
|
|
94203
94505
|
await close(false);
|
|
94204
94506
|
stop2(s);
|
|
94205
94507
|
};
|
|
94508
|
+
const validAccount = () => readSession()?.subject === account && accountGeneration() === generation;
|
|
94206
94509
|
const tick = async () => {
|
|
94207
|
-
if (!
|
|
94208
|
-
|
|
94510
|
+
if (closed || !ownsExecution) return;
|
|
94511
|
+
if (!validAccount()) return finish2({ reason: "refused", message: "\u8D26\u53F7\u5DF2\u9000\u51FA\u6216\u5207\u6362\u3002" });
|
|
94512
|
+
if (!registration || redetect) {
|
|
94513
|
+
redetect = false;
|
|
94514
|
+
registration = await options.registration();
|
|
94515
|
+
} else {
|
|
94209
94516
|
const was = registration.runtimes;
|
|
94210
94517
|
const runtimes = await refreshModels(was);
|
|
94211
94518
|
if (registration.runtimes === was) registration = { ...registration, runtimes };
|
|
@@ -94283,15 +94590,17 @@ function startRunner(options) {
|
|
|
94283
94590
|
for (const id of attempted) if (!listed2.has(id) && !running.has(id)) attempted.delete(id);
|
|
94284
94591
|
for (const job of list.value.jobs) {
|
|
94285
94592
|
if (closed || preparing) break;
|
|
94286
|
-
if (job.state === "claimed" && !running.has(job.id) && !attempted.has(job.id)) {
|
|
94593
|
+
if ((job.state === "claimed" || job.state === "interrupted") && !running.has(job.id) && (!attempted.has(job.id) || !job.flow && !!(job.chat || job.discussion))) {
|
|
94287
94594
|
const failure = await stopLeftOn(job);
|
|
94288
94595
|
if (closed || preparing) break;
|
|
94289
94596
|
const checkpoint = readCheckpoint(job.id);
|
|
94290
|
-
const
|
|
94597
|
+
const reply = !job.flow && !!(job.chat || job.discussion);
|
|
94598
|
+
const processesStopped2 = reply ? await stopReply(job.id, deps().stopMs) : false;
|
|
94599
|
+
const uncertain = !!checkpoint && (checkpoint.updating || reply) && !checkpoint.completed && (checkpoint.pending.length > 0 || checkpoint.opaque || !job.flow && checkpoint.started && !checkpoint.session);
|
|
94291
94600
|
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;
|
|
94601
|
+
const reason = failure ?? (checkpoint?.updating ? uncertain ? UNCERTAIN : UPDATE_REASON : "The Runner restarted while this job was running.");
|
|
94602
|
+
const recovered = await finishJob(registration.machineId, job.id, "failed", reason, { ...checkpoint?.session ? { session: checkpoint.session } : {}, ...processesStopped2 ? { processesStopped: true } : {} });
|
|
94603
|
+
if (recovered.ok && (reason === UPDATE_REASON || processesStopped2 && recovered.value.finished)) readAgain = true;
|
|
94295
94604
|
continue;
|
|
94296
94605
|
}
|
|
94297
94606
|
if (job.state !== "waiting" || running.has(job.id)) continue;
|
|
@@ -94381,20 +94690,42 @@ function startRunner(options) {
|
|
|
94381
94690
|
else await Promise.race([stops, new Promise((resolve2) => timeout = setTimeout(resolve2, (options.deps?.stopMs ?? STOP_MS) + 1e3))]);
|
|
94382
94691
|
clearTimeout(timeout);
|
|
94383
94692
|
if (release2 && !lock.waited() && registration) await release(registration.machineId);
|
|
94693
|
+
clearInterval(accountWatch);
|
|
94384
94694
|
lock.release();
|
|
94695
|
+
releaseRecord();
|
|
94385
94696
|
};
|
|
94697
|
+
let refresh2 = "";
|
|
94698
|
+
const accountWatch = setInterval(() => {
|
|
94699
|
+
try {
|
|
94700
|
+
const value = fs36.readFileSync(path39.join(runnerHome(), "settings-refresh"), "utf8");
|
|
94701
|
+
if (value !== refresh2) {
|
|
94702
|
+
refresh2 = value;
|
|
94703
|
+
redetect = true;
|
|
94704
|
+
if (!closed) schedule(0);
|
|
94705
|
+
}
|
|
94706
|
+
} catch {
|
|
94707
|
+
}
|
|
94708
|
+
if (!closed && !validAccount()) void finish2({ reason: "refused", message: "\u8D26\u53F7\u5DF2\u9000\u51FA\u6216\u5207\u6362\u3002" });
|
|
94709
|
+
}, 200);
|
|
94710
|
+
accountWatch.unref();
|
|
94386
94711
|
removeLegacy();
|
|
94387
94712
|
pruneChats();
|
|
94388
|
-
const lock = holdMachine(options.kind, () =>
|
|
94713
|
+
const lock = holdMachine(options.kind, () => {
|
|
94714
|
+
ownsExecution = true;
|
|
94715
|
+
void tick();
|
|
94716
|
+
}, (holder) => {
|
|
94389
94717
|
status(t.waitingHere(holder));
|
|
94390
94718
|
options.onWaiting?.(holder);
|
|
94391
94719
|
});
|
|
94392
|
-
return { stopped: stopped2, close: () => close(true), update: () => close(false, true), renew: () =>
|
|
94720
|
+
return { stopped: stopped2, close: () => close(true), update: () => close(false, true), renew: () => {
|
|
94721
|
+
redetect = true;
|
|
94722
|
+
schedule(0);
|
|
94723
|
+
} };
|
|
94393
94724
|
}
|
|
94394
94725
|
|
|
94395
94726
|
// src/signin.ts
|
|
94396
94727
|
import { spawn as spawn5 } from "node:child_process";
|
|
94397
|
-
import
|
|
94728
|
+
import crypto7 from "node:crypto";
|
|
94398
94729
|
import http from "node:http";
|
|
94399
94730
|
var WAIT_MS = 10 * 60 * 1e3;
|
|
94400
94731
|
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 +94750,9 @@ var PAGE = (outcome, lang) => {
|
|
|
94419
94750
|
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
94751
|
};
|
|
94421
94752
|
async function signIn(options = {}) {
|
|
94422
|
-
const
|
|
94423
|
-
const
|
|
94753
|
+
const generation = accountGeneration();
|
|
94754
|
+
const verifier = base64url(crypto7.randomBytes(32));
|
|
94755
|
+
const challenge = base64url(crypto7.createHash("sha256").update(verifier).digest());
|
|
94424
94756
|
let finish2 = () => {
|
|
94425
94757
|
};
|
|
94426
94758
|
const answered = new Promise((resolve2) => finish2 = resolve2);
|
|
@@ -94435,7 +94767,7 @@ async function signIn(options = {}) {
|
|
|
94435
94767
|
const params = asked.searchParams;
|
|
94436
94768
|
const code = params.get("code");
|
|
94437
94769
|
const error = params.get("error");
|
|
94438
|
-
const failure2 = code ? await exchange(code, verifier) : {
|
|
94770
|
+
const failure2 = code ? await exchange(code, verifier, generation, options.signal) : {
|
|
94439
94771
|
why: error === "access_denied" ? "denied" : "other",
|
|
94440
94772
|
detail: params.get("error_description") || error || "no code came back"
|
|
94441
94773
|
};
|
|
@@ -94465,7 +94797,7 @@ async function signIn(options = {}) {
|
|
|
94465
94797
|
server.close();
|
|
94466
94798
|
return failure;
|
|
94467
94799
|
}
|
|
94468
|
-
async function exchange(code, verifier) {
|
|
94800
|
+
async function exchange(code, verifier, generation, signal2) {
|
|
94469
94801
|
const { supabaseUrl, anonKey } = cloudEndpoints();
|
|
94470
94802
|
let response;
|
|
94471
94803
|
try {
|
|
@@ -94479,6 +94811,7 @@ async function exchange(code, verifier) {
|
|
|
94479
94811
|
}
|
|
94480
94812
|
const session = response.ok ? sessionFrom(await response.json().catch(() => ({}))) : null;
|
|
94481
94813
|
if (!session) return { why: "other", detail: `Cloud answered ${response.status}` };
|
|
94814
|
+
if (signal2?.aborted || accountGeneration() !== generation) return { why: "cancelled", detail: "cancelled" };
|
|
94482
94815
|
writeSession(session);
|
|
94483
94816
|
return null;
|
|
94484
94817
|
}
|
|
@@ -94523,8 +94856,8 @@ async function main() {
|
|
|
94523
94856
|
tell({ type: "update-deferred" });
|
|
94524
94857
|
});
|
|
94525
94858
|
});
|
|
94526
|
-
for (const
|
|
94527
|
-
process.on(
|
|
94859
|
+
for (const signal2 of ["SIGINT", "SIGTERM"]) {
|
|
94860
|
+
process.on(signal2, async () => {
|
|
94528
94861
|
await runner.close();
|
|
94529
94862
|
status(t.stopped());
|
|
94530
94863
|
process.exit(0);
|