@takemo101/mikan 0.0.2 → 0.0.3
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 +59 -3
- package/dist/bin.js +1904 -1073
- package/package.json +5 -1
package/dist/bin.js
CHANGED
|
@@ -34460,11 +34460,11 @@ import { Buffer as Buffer2 } from "buffer";
|
|
|
34460
34460
|
import { Buffer as Buffer3 } from "buffer";
|
|
34461
34461
|
import { EventEmitter as EventEmitter2 } from "events";
|
|
34462
34462
|
import { mkdir, writeFile as writeFileNode } from "fs/promises";
|
|
34463
|
-
import { dirname as
|
|
34463
|
+
import { dirname as dirname7, isAbsolute, resolve as resolve4 } from "path";
|
|
34464
34464
|
import { fileURLToPath } from "url";
|
|
34465
34465
|
import { resolve as resolve22, isAbsolute as isAbsolute2, parse as parse7 } from "path";
|
|
34466
|
-
import { existsSync as
|
|
34467
|
-
import { basename as
|
|
34466
|
+
import { existsSync as existsSync8 } from "fs";
|
|
34467
|
+
import { basename as basename4, join as join9 } from "path";
|
|
34468
34468
|
import os4 from "os";
|
|
34469
34469
|
import path4 from "path";
|
|
34470
34470
|
import { EventEmitter as EventEmitter3 } from "events";
|
|
@@ -38016,7 +38016,7 @@ async function resolveBundledFilePath(loadBundledFile, fallbackPath, metaUrl) {
|
|
|
38016
38016
|
if (isAbsolute(loadedPath)) {
|
|
38017
38017
|
return loadedPath;
|
|
38018
38018
|
}
|
|
38019
|
-
return resolve4(
|
|
38019
|
+
return resolve4(dirname7(fileURLToPath(metaUrl)), loadedPath);
|
|
38020
38020
|
}
|
|
38021
38021
|
function standardSleep(msOrDate) {
|
|
38022
38022
|
const ms = msOrDate instanceof Date ? msOrDate.getTime() - Date.now() : msOrDate;
|
|
@@ -38025,7 +38025,7 @@ function standardSleep(msOrDate) {
|
|
|
38025
38025
|
async function writeFilePortable(destination, data, options) {
|
|
38026
38026
|
const destinationPath = destination instanceof URL ? fileURLToPath(destination) : destination;
|
|
38027
38027
|
if (options?.createPath) {
|
|
38028
|
-
await mkdir(
|
|
38028
|
+
await mkdir(dirname7(destinationPath), { recursive: true });
|
|
38029
38029
|
}
|
|
38030
38030
|
const bytes = typeof data === "string" ? TEXT_ENCODER.encode(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
|
|
38031
38031
|
await writeFileNode(destinationPath, bytes, { mode: options?.mode });
|
|
@@ -38115,7 +38115,7 @@ function getBunfsRootPath() {
|
|
|
38115
38115
|
return process.platform === "win32" ? "B:\\~BUN\\root" : "/$bunfs/root";
|
|
38116
38116
|
}
|
|
38117
38117
|
function normalizeBunfsPath(fileName) {
|
|
38118
|
-
return
|
|
38118
|
+
return join9(getBunfsRootPath(), basename4(fileName));
|
|
38119
38119
|
}
|
|
38120
38120
|
|
|
38121
38121
|
class UnsupportedWorker {
|
|
@@ -50485,7 +50485,7 @@ var init_index_081xws23 = __esm(async () => {
|
|
|
50485
50485
|
return this.options.workerPath;
|
|
50486
50486
|
}
|
|
50487
50487
|
let workerPath = new URL("./parser.worker.js", import.meta.url).href;
|
|
50488
|
-
if (!
|
|
50488
|
+
if (!existsSync8(resolve22(import.meta.dirname, "parser.worker.js"))) {
|
|
50489
50489
|
workerPath = new URL("./parser.worker.ts", import.meta.url).href;
|
|
50490
50490
|
}
|
|
50491
50491
|
return workerPath;
|
|
@@ -70949,7 +70949,7 @@ var init_chunk_2mx7fq49 = () => {};
|
|
|
70949
70949
|
|
|
70950
70950
|
// ../../node_modules/.bun/react@19.2.6/node_modules/react/cjs/react-jsx-dev-runtime.development.js
|
|
70951
70951
|
var require_react_jsx_dev_runtime_development = __commonJS((exports) => {
|
|
70952
|
-
var
|
|
70952
|
+
var React4 = __toESM(require_react());
|
|
70953
70953
|
(function() {
|
|
70954
70954
|
function getComponentNameFromType(type) {
|
|
70955
70955
|
if (type == null)
|
|
@@ -71141,17 +71141,17 @@ React keys must be passed directly to JSX without using spread:
|
|
|
71141
71141
|
function isValidElement(object2) {
|
|
71142
71142
|
return typeof object2 === "object" && object2 !== null && object2.$$typeof === REACT_ELEMENT_TYPE;
|
|
71143
71143
|
}
|
|
71144
|
-
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals =
|
|
71144
|
+
var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_PORTAL_TYPE = Symbol.for("react.portal"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"), REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"), REACT_PROFILER_TYPE = Symbol.for("react.profiler"), REACT_CONSUMER_TYPE = Symbol.for("react.consumer"), REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"), REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"), REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"), REACT_MEMO_TYPE = Symbol.for("react.memo"), REACT_LAZY_TYPE = Symbol.for("react.lazy"), REACT_ACTIVITY_TYPE = Symbol.for("react.activity"), REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), ReactSharedInternals = React4.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, hasOwnProperty = Object.prototype.hasOwnProperty, isArrayImpl = Array.isArray, createTask = console.createTask ? console.createTask : function() {
|
|
71145
71145
|
return null;
|
|
71146
71146
|
};
|
|
71147
|
-
|
|
71147
|
+
React4 = {
|
|
71148
71148
|
react_stack_bottom_frame: function(callStackForError) {
|
|
71149
71149
|
return callStackForError();
|
|
71150
71150
|
}
|
|
71151
71151
|
};
|
|
71152
71152
|
var specialPropKeyWarningShown;
|
|
71153
71153
|
var didWarnAboutElementRef = {};
|
|
71154
|
-
var unknownOwnerDebugStack =
|
|
71154
|
+
var unknownOwnerDebugStack = React4.react_stack_bottom_frame.bind(React4, UnknownOwner)();
|
|
71155
71155
|
var unknownOwnerDebugTask = createTask(getTaskName(UnknownOwner));
|
|
71156
71156
|
var didWarnAboutKeySpread = {};
|
|
71157
71157
|
exports.Fragment = REACT_FRAGMENT_TYPE;
|
|
@@ -71435,7 +71435,7 @@ var require_scheduler = __commonJS((exports, module) => {
|
|
|
71435
71435
|
|
|
71436
71436
|
// ../../node_modules/.bun/react-reconciler@0.33.0+d86b59289c1a13ae/node_modules/react-reconciler/cjs/react-reconciler.development.js
|
|
71437
71437
|
var require_react_reconciler_development = __commonJS((exports, module) => {
|
|
71438
|
-
var
|
|
71438
|
+
var React4 = __toESM(require_react());
|
|
71439
71439
|
var Scheduler = __toESM(require_scheduler());
|
|
71440
71440
|
module.exports = function($$$config) {
|
|
71441
71441
|
function findHook(fiber, id) {
|
|
@@ -80057,7 +80057,7 @@ Check the render method of %s.`, getComponentNameFromFiber(current) || "Unknown"
|
|
|
80057
80057
|
Symbol.for("react.tracing_marker");
|
|
80058
80058
|
var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel");
|
|
80059
80059
|
Symbol.for("react.view_transition");
|
|
80060
|
-
var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals =
|
|
80060
|
+
var MAYBE_ITERATOR_SYMBOL = Symbol.iterator, REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"), isArrayImpl = Array.isArray, ReactSharedInternals = React4.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, rendererVersion = $$$config.rendererVersion, rendererPackageName = $$$config.rendererPackageName, extraDevToolsConfig = $$$config.extraDevToolsConfig, getPublicInstance = $$$config.getPublicInstance, getRootHostContext = $$$config.getRootHostContext, getChildHostContext = $$$config.getChildHostContext, prepareForCommit = $$$config.prepareForCommit, resetAfterCommit = $$$config.resetAfterCommit, createInstance = $$$config.createInstance;
|
|
80061
80061
|
$$$config.cloneMutableInstance;
|
|
80062
80062
|
var { appendInitialChild, finalizeInitialChildren, shouldSetTextContent, createTextInstance } = $$$config;
|
|
80063
80063
|
$$$config.cloneMutableTextInstance;
|
|
@@ -81926,7 +81926,7 @@ var require_backend = __commonJS((exports, module) => {
|
|
|
81926
81926
|
return o2 && typeof Symbol == "function" && o2.constructor === Symbol && o2 !== Symbol.prototype ? "symbol" : typeof o2;
|
|
81927
81927
|
}, _typeof(o);
|
|
81928
81928
|
}
|
|
81929
|
-
var ErrorStackParser = __webpack_require__2(206),
|
|
81929
|
+
var ErrorStackParser = __webpack_require__2(206), React4 = __webpack_require__2(189), assign = Object.assign, ReactSharedInternals = React4.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, REACT_CONTEXT_TYPE = Symbol.for("react.context"), REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"), hasOwnProperty = Object.prototype.hasOwnProperty, hookLog = [], primitiveStackCache = null;
|
|
81930
81930
|
function getPrimitiveStackCache() {
|
|
81931
81931
|
if (primitiveStackCache === null) {
|
|
81932
81932
|
var cache = new Map;
|
|
@@ -98861,13 +98861,13 @@ function createRoot(renderer) {
|
|
|
98861
98861
|
return {
|
|
98862
98862
|
render: (node) => {
|
|
98863
98863
|
engine.attach(renderer);
|
|
98864
|
-
container = _render(
|
|
98864
|
+
container = _render(import_react5.default.createElement(AppContext.Provider, { value: { keyHandler: renderer.keyInput, renderer } }, import_react5.default.createElement(ErrorBoundary, null, node)), renderer.root);
|
|
98865
98865
|
},
|
|
98866
98866
|
unmount: cleanup
|
|
98867
98867
|
};
|
|
98868
98868
|
}
|
|
98869
|
-
var
|
|
98870
|
-
return
|
|
98869
|
+
var import_react4, import_react5, import_react6, import_jsx_dev_runtime, import_react_reconciler, import_constants, import_react7, import_constants2, textNodeKeys, SpanRenderable, TextModifierRenderable, BoldSpanRenderable, ItalicSpanRenderable, UnderlineSpanRenderable, LineBreakRenderable, LinkRenderable, baseComponents, componentCatalogue, AppContext, useAppContext = () => {
|
|
98870
|
+
return import_react4.useContext(AppContext);
|
|
98871
98871
|
}, ErrorBoundary, package_default2, idCounter, currentUpdatePriority, hostConfig, reconciler, _r, flushSync, createPortal;
|
|
98872
98872
|
var init_chunk_w83f8rxy = __esm(async () => {
|
|
98873
98873
|
init_chunk_2mx7fq49();
|
|
@@ -98878,13 +98878,13 @@ var init_chunk_w83f8rxy = __esm(async () => {
|
|
|
98878
98878
|
init_core3(),
|
|
98879
98879
|
init_core3()
|
|
98880
98880
|
]);
|
|
98881
|
-
|
|
98882
|
-
|
|
98883
|
-
|
|
98881
|
+
import_react4 = __toESM(require_react(), 1);
|
|
98882
|
+
import_react5 = __toESM(require_react(), 1);
|
|
98883
|
+
import_react6 = __toESM(require_react(), 1);
|
|
98884
98884
|
import_jsx_dev_runtime = __toESM(require_jsx_dev_runtime(), 1);
|
|
98885
98885
|
import_react_reconciler = __toESM(require_react_reconciler(), 1);
|
|
98886
98886
|
import_constants = __toESM(require_constants(), 1);
|
|
98887
|
-
|
|
98887
|
+
import_react7 = __toESM(require_react(), 1);
|
|
98888
98888
|
import_constants2 = __toESM(require_constants(), 1);
|
|
98889
98889
|
textNodeKeys = ["span", "b", "strong", "i", "em", "u", "br", "a"];
|
|
98890
98890
|
SpanRenderable = class SpanRenderable extends TextNodeRenderable {
|
|
@@ -98963,11 +98963,11 @@ var init_chunk_w83f8rxy = __esm(async () => {
|
|
|
98963
98963
|
a: LinkRenderable
|
|
98964
98964
|
};
|
|
98965
98965
|
componentCatalogue = { ...baseComponents };
|
|
98966
|
-
AppContext =
|
|
98966
|
+
AppContext = import_react4.createContext({
|
|
98967
98967
|
keyHandler: null,
|
|
98968
98968
|
renderer: null
|
|
98969
98969
|
});
|
|
98970
|
-
ErrorBoundary = class ErrorBoundary extends
|
|
98970
|
+
ErrorBoundary = class ErrorBoundary extends import_react6.default.Component {
|
|
98971
98971
|
constructor(props) {
|
|
98972
98972
|
super(props);
|
|
98973
98973
|
this.state = { hasError: false, error: null };
|
|
@@ -99183,7 +99183,7 @@ var init_chunk_w83f8rxy = __esm(async () => {
|
|
|
99183
99183
|
return false;
|
|
99184
99184
|
},
|
|
99185
99185
|
NotPendingTransition: null,
|
|
99186
|
-
HostTransitionContext:
|
|
99186
|
+
HostTransitionContext: import_react7.createContext(null),
|
|
99187
99187
|
resetFormInstance() {},
|
|
99188
99188
|
requestPostPaintCallback() {},
|
|
99189
99189
|
trackSchedulerEvent() {},
|
|
@@ -99269,7 +99269,7 @@ __export(exports_react, {
|
|
|
99269
99269
|
createRoot: () => createRoot,
|
|
99270
99270
|
createReactSlotRegistry: () => createReactSlotRegistry,
|
|
99271
99271
|
createPortal: () => createPortal,
|
|
99272
|
-
createElement: () =>
|
|
99272
|
+
createElement: () => import_react19.createElement,
|
|
99273
99273
|
componentCatalogue: () => componentCatalogue,
|
|
99274
99274
|
baseComponents: () => baseComponents,
|
|
99275
99275
|
TimeToFirstDraw: () => TimeToFirstDraw,
|
|
@@ -99277,11 +99277,11 @@ __export(exports_react, {
|
|
|
99277
99277
|
AppContext: () => AppContext
|
|
99278
99278
|
});
|
|
99279
99279
|
function useEffectEvent(handler) {
|
|
99280
|
-
const handlerRef =
|
|
99281
|
-
|
|
99280
|
+
const handlerRef = import_react9.useRef(handler);
|
|
99281
|
+
import_react9.useLayoutEffect(() => {
|
|
99282
99282
|
handlerRef.current = handler;
|
|
99283
99283
|
});
|
|
99284
|
-
return
|
|
99284
|
+
return import_react9.useCallback((...args) => {
|
|
99285
99285
|
const fn = handlerRef.current;
|
|
99286
99286
|
return fn(...args);
|
|
99287
99287
|
}, []);
|
|
@@ -99327,17 +99327,17 @@ function createSlot(registry2, options = {}) {
|
|
|
99327
99327
|
};
|
|
99328
99328
|
}
|
|
99329
99329
|
function Slot(props) {
|
|
99330
|
-
const [version2, setVersion] =
|
|
99330
|
+
const [version2, setVersion] = import_react17.useState(0);
|
|
99331
99331
|
const registry2 = props.registry;
|
|
99332
99332
|
const slotName = String(props.name);
|
|
99333
|
-
const renderFailuresByPluginRef =
|
|
99334
|
-
const pendingRenderReportsRef =
|
|
99335
|
-
|
|
99333
|
+
const renderFailuresByPluginRef = import_react17.useRef(new Map);
|
|
99334
|
+
const pendingRenderReportsRef = import_react17.useRef(new Map);
|
|
99335
|
+
import_react17.useEffect(() => {
|
|
99336
99336
|
return registry2.subscribe(() => {
|
|
99337
99337
|
setVersion((current) => current + 1);
|
|
99338
99338
|
});
|
|
99339
99339
|
}, [registry2]);
|
|
99340
|
-
|
|
99340
|
+
import_react17.useEffect(() => {
|
|
99341
99341
|
if (pendingRenderReportsRef.current.size === 0) {
|
|
99342
99342
|
return;
|
|
99343
99343
|
}
|
|
@@ -99354,7 +99354,7 @@ function Slot(props) {
|
|
|
99354
99354
|
renderFailuresByPluginRef.current.set(`${report.slot}:${report.pluginId}:render`, failure);
|
|
99355
99355
|
}
|
|
99356
99356
|
});
|
|
99357
|
-
const entries =
|
|
99357
|
+
const entries = import_react17.useMemo(() => registry2.resolveEntries(props.name), [registry2, props.name, version2]);
|
|
99358
99358
|
const slotProps = getSlotProps(props);
|
|
99359
99359
|
const renderEntry = (entry, fallbackOnFailure) => {
|
|
99360
99360
|
const key = `${slotName}:${entry.id}`;
|
|
@@ -99399,7 +99399,7 @@ function Slot(props) {
|
|
|
99399
99399
|
if (placeholder === null || placeholder === undefined || placeholder === false) {
|
|
99400
99400
|
return fallbackOnFailure ?? null;
|
|
99401
99401
|
}
|
|
99402
|
-
return /* @__PURE__ */ import_jsx_dev_runtime.jsxDEV(
|
|
99402
|
+
return /* @__PURE__ */ import_jsx_dev_runtime.jsxDEV(import_react17.Fragment, {
|
|
99403
99403
|
children: placeholder
|
|
99404
99404
|
}, key, false, undefined, this);
|
|
99405
99405
|
}
|
|
@@ -99456,7 +99456,7 @@ function Slot(props) {
|
|
|
99456
99456
|
]
|
|
99457
99457
|
}, undefined, true, undefined, this);
|
|
99458
99458
|
}
|
|
99459
|
-
var
|
|
99459
|
+
var import_react8, import_react9, import_react10, import_react11, import_react12, import_react13, import_react14, import_react15, import_react16, import_react17, import_react18, import_react19, useRenderer = () => {
|
|
99460
99460
|
const { renderer } = useAppContext();
|
|
99461
99461
|
if (!renderer) {
|
|
99462
99462
|
throw new Error("Renderer not found.");
|
|
@@ -99465,7 +99465,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99465
99465
|
}, useBlur = (handler) => {
|
|
99466
99466
|
const renderer = useRenderer();
|
|
99467
99467
|
const stableHandler = useEffectEvent(handler);
|
|
99468
|
-
|
|
99468
|
+
import_react8.useEffect(() => {
|
|
99469
99469
|
renderer.on("blur", stableHandler);
|
|
99470
99470
|
return () => {
|
|
99471
99471
|
renderer.off("blur", stableHandler);
|
|
@@ -99474,7 +99474,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99474
99474
|
}, useFocus = (handler) => {
|
|
99475
99475
|
const renderer = useRenderer();
|
|
99476
99476
|
const stableHandler = useEffectEvent(handler);
|
|
99477
|
-
|
|
99477
|
+
import_react10.useEffect(() => {
|
|
99478
99478
|
renderer.on("focus", stableHandler);
|
|
99479
99479
|
return () => {
|
|
99480
99480
|
renderer.off("focus", stableHandler);
|
|
@@ -99483,7 +99483,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99483
99483
|
}, useKeyboard = (handler, options = { release: false }) => {
|
|
99484
99484
|
const { keyHandler } = useAppContext();
|
|
99485
99485
|
const stableHandler = useEffectEvent(handler);
|
|
99486
|
-
|
|
99486
|
+
import_react11.useEffect(() => {
|
|
99487
99487
|
keyHandler?.on("keypress", stableHandler);
|
|
99488
99488
|
if (options?.release) {
|
|
99489
99489
|
keyHandler?.on("keyrelease", stableHandler);
|
|
@@ -99498,7 +99498,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99498
99498
|
}, usePaste = (handler) => {
|
|
99499
99499
|
const { keyHandler } = useAppContext();
|
|
99500
99500
|
const stableHandler = useEffectEvent(handler);
|
|
99501
|
-
|
|
99501
|
+
import_react12.useEffect(() => {
|
|
99502
99502
|
keyHandler?.on("paste", stableHandler);
|
|
99503
99503
|
return () => {
|
|
99504
99504
|
keyHandler?.off("paste", stableHandler);
|
|
@@ -99507,7 +99507,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99507
99507
|
}, useOnResize = (callback) => {
|
|
99508
99508
|
const renderer = useRenderer();
|
|
99509
99509
|
const stableCallback = useEffectEvent(callback);
|
|
99510
|
-
|
|
99510
|
+
import_react13.useEffect(() => {
|
|
99511
99511
|
renderer.on("resize", stableCallback);
|
|
99512
99512
|
return () => {
|
|
99513
99513
|
renderer.off("resize", stableCallback);
|
|
@@ -99517,7 +99517,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99517
99517
|
}, useSelectionHandler = (handler) => {
|
|
99518
99518
|
const renderer = useRenderer();
|
|
99519
99519
|
const stableHandler = useEffectEvent(handler);
|
|
99520
|
-
|
|
99520
|
+
import_react14.useEffect(() => {
|
|
99521
99521
|
renderer.on("selection", stableHandler);
|
|
99522
99522
|
return () => {
|
|
99523
99523
|
renderer.off("selection", stableHandler);
|
|
@@ -99525,7 +99525,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99525
99525
|
}, [renderer]);
|
|
99526
99526
|
}, useTerminalDimensions = () => {
|
|
99527
99527
|
const renderer = useRenderer();
|
|
99528
|
-
const [dimensions, setDimensions] =
|
|
99528
|
+
const [dimensions, setDimensions] = import_react15.useState({
|
|
99529
99529
|
width: renderer.width,
|
|
99530
99530
|
height: renderer.height
|
|
99531
99531
|
});
|
|
@@ -99536,7 +99536,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99536
99536
|
return dimensions;
|
|
99537
99537
|
}, useTimeline = (options = {}) => {
|
|
99538
99538
|
const timeline = new Timeline(options);
|
|
99539
|
-
|
|
99539
|
+
import_react16.useEffect(() => {
|
|
99540
99540
|
if (!options.autoplay) {
|
|
99541
99541
|
timeline.play();
|
|
99542
99542
|
}
|
|
@@ -99548,7 +99548,7 @@ var import_react5, import_react6, import_react7, import_react8, import_react9, i
|
|
|
99548
99548
|
}, []);
|
|
99549
99549
|
return timeline;
|
|
99550
99550
|
}, PluginErrorBoundary, TimeToFirstDraw = (props) => {
|
|
99551
|
-
return
|
|
99551
|
+
return import_react18.createElement("time-to-first-draw", props);
|
|
99552
99552
|
};
|
|
99553
99553
|
var init_react = __esm(async () => {
|
|
99554
99554
|
init_chunk_2mx7fq49();
|
|
@@ -99558,9 +99558,6 @@ var init_react = __esm(async () => {
|
|
|
99558
99558
|
init_core3(),
|
|
99559
99559
|
init_core3()
|
|
99560
99560
|
]);
|
|
99561
|
-
import_react5 = __toESM(require_react(), 1);
|
|
99562
|
-
import_react6 = __toESM(require_react(), 1);
|
|
99563
|
-
import_react7 = __toESM(require_react(), 1);
|
|
99564
99561
|
import_react8 = __toESM(require_react(), 1);
|
|
99565
99562
|
import_react9 = __toESM(require_react(), 1);
|
|
99566
99563
|
import_react10 = __toESM(require_react(), 1);
|
|
@@ -99570,7 +99567,10 @@ var init_react = __esm(async () => {
|
|
|
99570
99567
|
import_react14 = __toESM(require_react(), 1);
|
|
99571
99568
|
import_react15 = __toESM(require_react(), 1);
|
|
99572
99569
|
import_react16 = __toESM(require_react(), 1);
|
|
99573
|
-
|
|
99570
|
+
import_react17 = __toESM(require_react(), 1);
|
|
99571
|
+
import_react18 = __toESM(require_react(), 1);
|
|
99572
|
+
import_react19 = __toESM(require_react(), 1);
|
|
99573
|
+
PluginErrorBoundary = class PluginErrorBoundary extends import_react17.default.Component {
|
|
99574
99574
|
constructor(props) {
|
|
99575
99575
|
super(props);
|
|
99576
99576
|
this.state = { failure: null };
|
|
@@ -99604,22 +99604,88 @@ var init_react = __esm(async () => {
|
|
|
99604
99604
|
extend2({ "time-to-first-draw": TimeToFirstDrawRenderable });
|
|
99605
99605
|
});
|
|
99606
99606
|
|
|
99607
|
-
// src/index.ts
|
|
99608
|
-
import { readFileSync as
|
|
99609
|
-
import { basename as basename4, join as join9 } from "path";
|
|
99607
|
+
// ../mcp/src/index.ts
|
|
99608
|
+
import { readFileSync as readFileSync7 } from "fs";
|
|
99610
99609
|
|
|
99611
|
-
// ../core/src/
|
|
99612
|
-
import {
|
|
99613
|
-
|
|
99614
|
-
|
|
99615
|
-
|
|
99616
|
-
|
|
99617
|
-
|
|
99618
|
-
|
|
99619
|
-
|
|
99620
|
-
|
|
99621
|
-
|
|
99622
|
-
|
|
99610
|
+
// ../core/src/board-scan.ts
|
|
99611
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "fs";
|
|
99612
|
+
import { join } from "path";
|
|
99613
|
+
|
|
99614
|
+
// ../core/src/dependency.ts
|
|
99615
|
+
function deriveDependencyState(byId, warnings) {
|
|
99616
|
+
for (const item of [...byId.values()].flat()) {
|
|
99617
|
+
const issueId = String(item.issue.id);
|
|
99618
|
+
const unmet = new Map;
|
|
99619
|
+
for (const dependency of item.issue.dependencies) {
|
|
99620
|
+
const dependencyId = String(dependency);
|
|
99621
|
+
if (dependencyId === issueId) {
|
|
99622
|
+
unmet.set(dependencyId, dependency);
|
|
99623
|
+
warnings.push({
|
|
99624
|
+
kind: "dependency_self",
|
|
99625
|
+
message: `${issueId} depends on itself`,
|
|
99626
|
+
issueId,
|
|
99627
|
+
path: item.path
|
|
99628
|
+
});
|
|
99629
|
+
continue;
|
|
99630
|
+
}
|
|
99631
|
+
const matches = byId.get(dependencyId) ?? [];
|
|
99632
|
+
const target = matches[0];
|
|
99633
|
+
if (!target) {
|
|
99634
|
+
unmet.set(dependencyId, dependency);
|
|
99635
|
+
warnings.push({
|
|
99636
|
+
kind: "dependency_missing",
|
|
99637
|
+
message: `${issueId} depends on missing Issue ${dependencyId}`,
|
|
99638
|
+
issueId,
|
|
99639
|
+
path: item.path
|
|
99640
|
+
});
|
|
99641
|
+
continue;
|
|
99642
|
+
}
|
|
99643
|
+
if (hasDependencyPath(dependencyId, issueId, byId)) {
|
|
99644
|
+
unmet.set(dependencyId, dependency);
|
|
99645
|
+
warnings.push({
|
|
99646
|
+
kind: "dependency_cycle",
|
|
99647
|
+
message: `${issueId} has cyclic dependency through ${dependencyId}`,
|
|
99648
|
+
issueId,
|
|
99649
|
+
path: item.path
|
|
99650
|
+
});
|
|
99651
|
+
continue;
|
|
99652
|
+
}
|
|
99653
|
+
const targetStatus = String(target.status);
|
|
99654
|
+
if (targetStatus === "archived") {
|
|
99655
|
+
unmet.set(dependencyId, dependency);
|
|
99656
|
+
warnings.push({
|
|
99657
|
+
kind: "dependency_archived",
|
|
99658
|
+
message: `${issueId} depends on archived Issue ${dependencyId}`,
|
|
99659
|
+
issueId,
|
|
99660
|
+
path: item.path
|
|
99661
|
+
});
|
|
99662
|
+
continue;
|
|
99663
|
+
}
|
|
99664
|
+
if (targetStatus !== "completed") {
|
|
99665
|
+
unmet.set(dependencyId, dependency);
|
|
99666
|
+
warnings.push({
|
|
99667
|
+
kind: "dependency_incomplete",
|
|
99668
|
+
message: `${issueId} depends on incomplete Issue ${dependencyId}`,
|
|
99669
|
+
issueId,
|
|
99670
|
+
path: item.path
|
|
99671
|
+
});
|
|
99672
|
+
}
|
|
99673
|
+
}
|
|
99674
|
+
item.unmetDependencies = [...unmet.values()];
|
|
99675
|
+
item.dependencyStatus = item.unmetDependencies.length > 0 ? "blocked" : "ready";
|
|
99676
|
+
}
|
|
99677
|
+
}
|
|
99678
|
+
function hasDependencyPath(fromId, toId, byId, seen = new Set) {
|
|
99679
|
+
if (fromId === toId)
|
|
99680
|
+
return true;
|
|
99681
|
+
if (seen.has(fromId))
|
|
99682
|
+
return false;
|
|
99683
|
+
seen.add(fromId);
|
|
99684
|
+
const [item] = byId.get(fromId) ?? [];
|
|
99685
|
+
if (!item)
|
|
99686
|
+
return false;
|
|
99687
|
+
return item.issue.dependencies.some((dependency) => hasDependencyPath(String(dependency), toId, byId, seen));
|
|
99688
|
+
}
|
|
99623
99689
|
|
|
99624
99690
|
// ../../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/index.js
|
|
99625
99691
|
var composer = require_composer();
|
|
@@ -99671,18 +99737,11 @@ var $visitAsync = visit.visitAsync;
|
|
|
99671
99737
|
init_external();
|
|
99672
99738
|
init_external();
|
|
99673
99739
|
|
|
99674
|
-
// ../core/src/
|
|
99740
|
+
// ../core/src/primitives.ts
|
|
99675
99741
|
var issueIdPattern = /^[A-Z][A-Z0-9]*-\d{3,}$/;
|
|
99676
99742
|
var statusOrLabelPattern = /^[a-z][a-z0-9-]*$/;
|
|
99677
99743
|
var projectKeyPattern = /^[A-Z][A-Z0-9]*$/;
|
|
99678
99744
|
var utcTimestampPattern = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
|
|
99679
|
-
var frontmatterSchema = exports_external.object({
|
|
99680
|
-
id: exports_external.string().min(1),
|
|
99681
|
-
title: exports_external.string().min(1),
|
|
99682
|
-
labels: exports_external.array(exports_external.string()).optional().default([]),
|
|
99683
|
-
created_at: exports_external.string().min(1),
|
|
99684
|
-
updated_at: exports_external.string().min(1)
|
|
99685
|
-
}).passthrough();
|
|
99686
99745
|
function parseIssueId(input) {
|
|
99687
99746
|
if (!issueIdPattern.test(input)) {
|
|
99688
99747
|
return invalidFrontmatter(`id must look like MIK-001: ${input}`);
|
|
@@ -99715,12 +99774,124 @@ function parseUtcTimestamp(input) {
|
|
|
99715
99774
|
}
|
|
99716
99775
|
return { ok: true, value: input };
|
|
99717
99776
|
}
|
|
99777
|
+
function invalidFrontmatter(message) {
|
|
99778
|
+
return invalidFrontmatterResult(message);
|
|
99779
|
+
}
|
|
99780
|
+
function invalidFrontmatterResult(message) {
|
|
99781
|
+
return {
|
|
99782
|
+
ok: false,
|
|
99783
|
+
error: {
|
|
99784
|
+
kind: "invalid_frontmatter",
|
|
99785
|
+
message
|
|
99786
|
+
}
|
|
99787
|
+
};
|
|
99788
|
+
}
|
|
99789
|
+
|
|
99790
|
+
// ../core/src/issue-markdown.ts
|
|
99791
|
+
var frontmatterSchema = exports_external.object({
|
|
99792
|
+
id: exports_external.string().min(1),
|
|
99793
|
+
title: exports_external.string().min(1),
|
|
99794
|
+
labels: exports_external.array(exports_external.string()).optional().default([]),
|
|
99795
|
+
depends_on: exports_external.array(exports_external.string()).optional().default([]),
|
|
99796
|
+
created_at: exports_external.string().min(1),
|
|
99797
|
+
updated_at: exports_external.string().min(1)
|
|
99798
|
+
}).passthrough();
|
|
99718
99799
|
function parseIssueMarkdown(markdown) {
|
|
99719
99800
|
const parsed = parseIssueDocument(markdown);
|
|
99720
99801
|
if (!parsed.ok)
|
|
99721
99802
|
return parsed;
|
|
99722
99803
|
return { ok: true, value: parsed.value.issue };
|
|
99723
99804
|
}
|
|
99805
|
+
function parseIssueDocument(markdown) {
|
|
99806
|
+
const frontmatter = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(markdown);
|
|
99807
|
+
if (!frontmatter) {
|
|
99808
|
+
return {
|
|
99809
|
+
ok: false,
|
|
99810
|
+
error: {
|
|
99811
|
+
kind: "missing_frontmatter",
|
|
99812
|
+
message: "Issue Markdown must start with YAML frontmatter"
|
|
99813
|
+
}
|
|
99814
|
+
};
|
|
99815
|
+
}
|
|
99816
|
+
const frontmatterSource = frontmatter[1] ?? "";
|
|
99817
|
+
let rawFrontmatter;
|
|
99818
|
+
try {
|
|
99819
|
+
rawFrontmatter = $parse(frontmatterSource);
|
|
99820
|
+
} catch (error51) {
|
|
99821
|
+
return invalidFrontmatterResult(error51 instanceof Error ? error51.message : String(error51));
|
|
99822
|
+
}
|
|
99823
|
+
const parsedFrontmatter = frontmatterSchema.safeParse(rawFrontmatter);
|
|
99824
|
+
if (!parsedFrontmatter.success) {
|
|
99825
|
+
return invalidFrontmatterResult(parsedFrontmatter.error.issues.map(formatZodIssue).join("; "));
|
|
99826
|
+
}
|
|
99827
|
+
const errors4 = [];
|
|
99828
|
+
let issueId;
|
|
99829
|
+
const id = parseIssueId(parsedFrontmatter.data.id);
|
|
99830
|
+
if (id.ok)
|
|
99831
|
+
issueId = id.value;
|
|
99832
|
+
else
|
|
99833
|
+
errors4.push(id.error.message);
|
|
99834
|
+
const labels = [];
|
|
99835
|
+
for (const rawLabel of parsedFrontmatter.data.labels) {
|
|
99836
|
+
const label = parseLabelId(rawLabel);
|
|
99837
|
+
if (label.ok)
|
|
99838
|
+
labels.push(label.value);
|
|
99839
|
+
else
|
|
99840
|
+
errors4.push(label.error.message);
|
|
99841
|
+
}
|
|
99842
|
+
const dependencies = [];
|
|
99843
|
+
for (const rawDependency of parsedFrontmatter.data.depends_on) {
|
|
99844
|
+
const dependency = parseIssueId(rawDependency);
|
|
99845
|
+
if (dependency.ok)
|
|
99846
|
+
dependencies.push(dependency.value);
|
|
99847
|
+
else
|
|
99848
|
+
errors4.push(`depends_on: ${dependency.error.message}`);
|
|
99849
|
+
}
|
|
99850
|
+
let createdAt;
|
|
99851
|
+
const parsedCreatedAt = parseUtcTimestamp(parsedFrontmatter.data.created_at);
|
|
99852
|
+
if (parsedCreatedAt.ok)
|
|
99853
|
+
createdAt = parsedCreatedAt.value;
|
|
99854
|
+
else
|
|
99855
|
+
errors4.push(`created_at: ${parsedCreatedAt.error.message}`);
|
|
99856
|
+
let updatedAt;
|
|
99857
|
+
const parsedUpdatedAt = parseUtcTimestamp(parsedFrontmatter.data.updated_at);
|
|
99858
|
+
if (parsedUpdatedAt.ok)
|
|
99859
|
+
updatedAt = parsedUpdatedAt.value;
|
|
99860
|
+
else
|
|
99861
|
+
errors4.push(`updated_at: ${parsedUpdatedAt.error.message}`);
|
|
99862
|
+
if (errors4.length > 0 || !issueId || !createdAt || !updatedAt) {
|
|
99863
|
+
return invalidFrontmatterResult(errors4.join("; "));
|
|
99864
|
+
}
|
|
99865
|
+
return {
|
|
99866
|
+
ok: true,
|
|
99867
|
+
value: {
|
|
99868
|
+
frontmatter: parsedFrontmatter.data,
|
|
99869
|
+
issue: {
|
|
99870
|
+
id: issueId,
|
|
99871
|
+
title: parsedFrontmatter.data.title,
|
|
99872
|
+
labels,
|
|
99873
|
+
dependencies,
|
|
99874
|
+
createdAt,
|
|
99875
|
+
updatedAt,
|
|
99876
|
+
body: markdown.slice(frontmatter[0].length)
|
|
99877
|
+
}
|
|
99878
|
+
}
|
|
99879
|
+
};
|
|
99880
|
+
}
|
|
99881
|
+
function serializeIssue(input) {
|
|
99882
|
+
return `---
|
|
99883
|
+
${$stringify(input.frontmatter).trim()}
|
|
99884
|
+
---
|
|
99885
|
+
${input.body.startsWith(`
|
|
99886
|
+
`) ? "" : `
|
|
99887
|
+
`}${input.body}`;
|
|
99888
|
+
}
|
|
99889
|
+
function formatZodIssue(issue2) {
|
|
99890
|
+
const path = issue2.path.length > 0 ? `${issue2.path.join(".")}: ` : "";
|
|
99891
|
+
return `${path}${issue2.message}`;
|
|
99892
|
+
}
|
|
99893
|
+
|
|
99894
|
+
// ../core/src/board-scan.ts
|
|
99724
99895
|
function scanBoard(options) {
|
|
99725
99896
|
const mikanRoot = join(options.projectRoot, ".mikan");
|
|
99726
99897
|
const configuredStatuses = options.config.board.columns.map((column) => column.id);
|
|
@@ -99755,7 +99926,9 @@ function scanBoard(options) {
|
|
|
99755
99926
|
const item = {
|
|
99756
99927
|
issue: parsed.value,
|
|
99757
99928
|
status: status.value,
|
|
99758
|
-
path
|
|
99929
|
+
path,
|
|
99930
|
+
unmetDependencies: [],
|
|
99931
|
+
dependencyStatus: "ready"
|
|
99759
99932
|
};
|
|
99760
99933
|
const id = String(parsed.value.id);
|
|
99761
99934
|
const matches = byId.get(id) ?? [];
|
|
@@ -99784,6 +99957,7 @@ function scanBoard(options) {
|
|
|
99784
99957
|
});
|
|
99785
99958
|
}
|
|
99786
99959
|
}
|
|
99960
|
+
deriveDependencyState(byId, warnings);
|
|
99787
99961
|
if (existsSync(mikanRoot)) {
|
|
99788
99962
|
const configured = new Set(configuredStatuses.concat([".state", "templates"]));
|
|
99789
99963
|
for (const entry of readdirSync(mikanRoot, { withFileTypes: true })) {
|
|
@@ -99864,6 +100038,101 @@ function findIssueById(options) {
|
|
|
99864
100038
|
}
|
|
99865
100039
|
return { ok: true, value: matches[0] };
|
|
99866
100040
|
}
|
|
100041
|
+
function sortedMarkdownFiles(directory) {
|
|
100042
|
+
return readdirSync(directory).filter((entry) => entry.endsWith(".md")).filter((entry) => statSync(join(directory, entry)).isFile()).sort();
|
|
100043
|
+
}
|
|
100044
|
+
function readHookFailureWarnings(projectRoot) {
|
|
100045
|
+
const path = join(projectRoot, ".mikan", ".state", "hook-log.ndjson");
|
|
100046
|
+
if (!existsSync(path))
|
|
100047
|
+
return [];
|
|
100048
|
+
return readFileSync(path, "utf8").split(`
|
|
100049
|
+
`).filter((line) => line.trim().length > 0).flatMap((line) => {
|
|
100050
|
+
let entry;
|
|
100051
|
+
try {
|
|
100052
|
+
entry = JSON.parse(line);
|
|
100053
|
+
} catch {
|
|
100054
|
+
return [];
|
|
100055
|
+
}
|
|
100056
|
+
if (!isHookFailureEntry(entry))
|
|
100057
|
+
return [];
|
|
100058
|
+
const issueId = entry.issue_id;
|
|
100059
|
+
const command = entry.command;
|
|
100060
|
+
const exitCode = entry.exit_code;
|
|
100061
|
+
const detail = entry.error ? `: ${entry.error}` : "";
|
|
100062
|
+
return [
|
|
100063
|
+
{
|
|
100064
|
+
kind: "hook_failure",
|
|
100065
|
+
message: `Hook failed for ${issueId}: ${command} exited ${exitCode}${detail}`,
|
|
100066
|
+
path,
|
|
100067
|
+
issueId
|
|
100068
|
+
}
|
|
100069
|
+
];
|
|
100070
|
+
});
|
|
100071
|
+
}
|
|
100072
|
+
function isHookFailureEntry(entry) {
|
|
100073
|
+
if (!entry || typeof entry !== "object")
|
|
100074
|
+
return false;
|
|
100075
|
+
const value = entry;
|
|
100076
|
+
return typeof value.issue_id === "string" && typeof value.command === "string" && typeof value.exit_code === "number" && (value.error === undefined || typeof value.error === "string");
|
|
100077
|
+
}
|
|
100078
|
+
// ../core/src/issue-mutations.ts
|
|
100079
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, renameSync as renameSync2 } from "fs";
|
|
100080
|
+
import { basename as basename2, dirname as dirname2, join as join3 } from "path";
|
|
100081
|
+
|
|
100082
|
+
// ../core/src/write-lock.ts
|
|
100083
|
+
import {
|
|
100084
|
+
existsSync as existsSync2,
|
|
100085
|
+
mkdirSync,
|
|
100086
|
+
renameSync,
|
|
100087
|
+
rmSync,
|
|
100088
|
+
writeFileSync
|
|
100089
|
+
} from "fs";
|
|
100090
|
+
import { basename, dirname, join as join2 } from "path";
|
|
100091
|
+
function isWriteLocked(projectRoot) {
|
|
100092
|
+
return existsSync2(lockPath(projectRoot));
|
|
100093
|
+
}
|
|
100094
|
+
function withWriteLock(projectRoot, operation) {
|
|
100095
|
+
const path = lockPath(projectRoot);
|
|
100096
|
+
if (existsSync2(path)) {
|
|
100097
|
+
return {
|
|
100098
|
+
ok: false,
|
|
100099
|
+
error: { kind: "lock_held", message: "mikan write lock is held", path }
|
|
100100
|
+
};
|
|
100101
|
+
}
|
|
100102
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
100103
|
+
try {
|
|
100104
|
+
writeFileSync(path, String(process.pid), { flag: "wx" });
|
|
100105
|
+
} catch {
|
|
100106
|
+
return {
|
|
100107
|
+
ok: false,
|
|
100108
|
+
error: { kind: "lock_held", message: "mikan write lock is held", path }
|
|
100109
|
+
};
|
|
100110
|
+
}
|
|
100111
|
+
try {
|
|
100112
|
+
return operation();
|
|
100113
|
+
} catch (error51) {
|
|
100114
|
+
return {
|
|
100115
|
+
ok: false,
|
|
100116
|
+
error: {
|
|
100117
|
+
kind: "io_error",
|
|
100118
|
+
message: error51 instanceof Error ? error51.message : String(error51)
|
|
100119
|
+
}
|
|
100120
|
+
};
|
|
100121
|
+
} finally {
|
|
100122
|
+
rmSync(path, { force: true });
|
|
100123
|
+
}
|
|
100124
|
+
}
|
|
100125
|
+
function atomicWriteFile(path, content) {
|
|
100126
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
100127
|
+
const tmp = join2(dirname(path), `.${basename(path)}.${process.pid}.${Date.now()}.tmp`);
|
|
100128
|
+
writeFileSync(tmp, content);
|
|
100129
|
+
renameSync(tmp, path);
|
|
100130
|
+
}
|
|
100131
|
+
function lockPath(projectRoot) {
|
|
100132
|
+
return join2(projectRoot, ".mikan", ".state", "write.lock");
|
|
100133
|
+
}
|
|
100134
|
+
|
|
100135
|
+
// ../core/src/issue-mutations.ts
|
|
99867
100136
|
function createIssue(options) {
|
|
99868
100137
|
const status = options.status ?? "backlog";
|
|
99869
100138
|
const statusValidation = validateStatus(options.config, status);
|
|
@@ -99872,6 +100141,9 @@ function createIssue(options) {
|
|
|
99872
100141
|
const labelsValidation = validateLabels(options.config, options.labels ?? []);
|
|
99873
100142
|
if (!labelsValidation.ok)
|
|
99874
100143
|
return labelsValidation;
|
|
100144
|
+
const dependenciesValidation = validateDependencies(options.dependencies ?? []);
|
|
100145
|
+
if (!dependenciesValidation.ok)
|
|
100146
|
+
return dependenciesValidation;
|
|
99875
100147
|
const projectKey = options.config.project?.key ?? "MIK";
|
|
99876
100148
|
const parsedProjectKey = parseProjectKey(projectKey);
|
|
99877
100149
|
if (!parsedProjectKey.ok) {
|
|
@@ -99915,13 +100187,14 @@ function createIssue(options) {
|
|
|
99915
100187
|
id,
|
|
99916
100188
|
title: options.title,
|
|
99917
100189
|
labels: options.labels ?? [],
|
|
100190
|
+
depends_on: dependenciesValidation.value.map(String),
|
|
99918
100191
|
created_at: now,
|
|
99919
100192
|
updated_at: now
|
|
99920
100193
|
},
|
|
99921
100194
|
body
|
|
99922
100195
|
});
|
|
99923
|
-
const path =
|
|
99924
|
-
if (
|
|
100196
|
+
const path = join3(options.projectRoot, ".mikan", status, `${id}.md`);
|
|
100197
|
+
if (existsSync3(path)) {
|
|
99925
100198
|
return {
|
|
99926
100199
|
ok: false,
|
|
99927
100200
|
error: {
|
|
@@ -99939,10 +100212,11 @@ function createIssue(options) {
|
|
|
99939
100212
|
error: { kind: "malformed_issue", message: parsed.error.message, path }
|
|
99940
100213
|
};
|
|
99941
100214
|
}
|
|
99942
|
-
return {
|
|
99943
|
-
|
|
99944
|
-
|
|
99945
|
-
|
|
100215
|
+
return findIssueById({
|
|
100216
|
+
projectRoot: options.projectRoot,
|
|
100217
|
+
config: options.config,
|
|
100218
|
+
id
|
|
100219
|
+
});
|
|
99946
100220
|
});
|
|
99947
100221
|
}
|
|
99948
100222
|
function updateIssue(options) {
|
|
@@ -99954,6 +100228,9 @@ function updateIssue(options) {
|
|
|
99954
100228
|
const labelsValidation = validateLabels(options.config, labels);
|
|
99955
100229
|
if (!labelsValidation.ok)
|
|
99956
100230
|
return labelsValidation;
|
|
100231
|
+
const dependenciesValidation = options.dependencies ? validateDependencies(options.dependencies) : undefined;
|
|
100232
|
+
if (dependenciesValidation && !dependenciesValidation.ok)
|
|
100233
|
+
return dependenciesValidation;
|
|
99957
100234
|
const document2 = readIssueDocument(target.value.path);
|
|
99958
100235
|
if (!document2.ok)
|
|
99959
100236
|
return document2;
|
|
@@ -99962,6 +100239,7 @@ function updateIssue(options) {
|
|
|
99962
100239
|
...document2.value.frontmatter,
|
|
99963
100240
|
title: options.title ?? target.value.issue.title,
|
|
99964
100241
|
labels,
|
|
100242
|
+
...dependenciesValidation ? { depends_on: dependenciesValidation.value.map(String) } : {},
|
|
99965
100243
|
updated_at: utcNow(options.now)
|
|
99966
100244
|
},
|
|
99967
100245
|
body: options.body ?? target.value.issue.body
|
|
@@ -99978,7 +100256,7 @@ function updateIssue(options) {
|
|
|
99978
100256
|
}
|
|
99979
100257
|
};
|
|
99980
100258
|
}
|
|
99981
|
-
return
|
|
100259
|
+
return findIssueById(options);
|
|
99982
100260
|
});
|
|
99983
100261
|
}
|
|
99984
100262
|
function moveIssue(options) {
|
|
@@ -99992,8 +100270,8 @@ function moveIssue(options) {
|
|
|
99992
100270
|
const existingLabels = validateLabels(options.config, target.value.issue.labels.map(String));
|
|
99993
100271
|
if (!existingLabels.ok)
|
|
99994
100272
|
return existingLabels;
|
|
99995
|
-
const destination =
|
|
99996
|
-
if (destination !== target.value.path &&
|
|
100273
|
+
const destination = join3(options.projectRoot, ".mikan", options.status, basename2(target.value.path));
|
|
100274
|
+
if (destination !== target.value.path && existsSync3(destination)) {
|
|
99997
100275
|
return {
|
|
99998
100276
|
ok: false,
|
|
99999
100277
|
error: {
|
|
@@ -100003,7 +100281,7 @@ function moveIssue(options) {
|
|
|
100003
100281
|
}
|
|
100004
100282
|
};
|
|
100005
100283
|
}
|
|
100006
|
-
|
|
100284
|
+
mkdirSync2(dirname2(destination), { recursive: true });
|
|
100007
100285
|
const document2 = readIssueDocument(target.value.path);
|
|
100008
100286
|
if (!document2.ok)
|
|
100009
100287
|
return document2;
|
|
@@ -100020,8 +100298,8 @@ function moveIssue(options) {
|
|
|
100020
100298
|
});
|
|
100021
100299
|
atomicWriteFile(target.value.path, updated);
|
|
100022
100300
|
if (destination !== target.value.path)
|
|
100023
|
-
|
|
100024
|
-
const parsed = parseIssueMarkdown(
|
|
100301
|
+
renameSync2(target.value.path, destination);
|
|
100302
|
+
const parsed = parseIssueMarkdown(readFileSync2(destination, "utf8"));
|
|
100025
100303
|
if (!parsed.ok) {
|
|
100026
100304
|
return {
|
|
100027
100305
|
ok: false,
|
|
@@ -100032,14 +100310,11 @@ function moveIssue(options) {
|
|
|
100032
100310
|
}
|
|
100033
100311
|
};
|
|
100034
100312
|
}
|
|
100035
|
-
return {
|
|
100036
|
-
|
|
100037
|
-
|
|
100038
|
-
|
|
100039
|
-
|
|
100040
|
-
path: destination
|
|
100041
|
-
}
|
|
100042
|
-
};
|
|
100313
|
+
return findIssueById({
|
|
100314
|
+
projectRoot: options.projectRoot,
|
|
100315
|
+
config: options.config,
|
|
100316
|
+
id: options.id
|
|
100317
|
+
});
|
|
100043
100318
|
});
|
|
100044
100319
|
}
|
|
100045
100320
|
function appendIssue(options) {
|
|
@@ -100073,7 +100348,7 @@ function appendIssue(options) {
|
|
|
100073
100348
|
}
|
|
100074
100349
|
};
|
|
100075
100350
|
}
|
|
100076
|
-
return
|
|
100351
|
+
return findIssueById(options);
|
|
100077
100352
|
});
|
|
100078
100353
|
}
|
|
100079
100354
|
function appendToSection(body, section, entry) {
|
|
@@ -100106,78 +100381,8 @@ ${entry.trim()}
|
|
|
100106
100381
|
${after ? `
|
|
100107
100382
|
${after}` : ""}`;
|
|
100108
100383
|
}
|
|
100109
|
-
function isWriteLocked(projectRoot) {
|
|
100110
|
-
return existsSync(lockPath(projectRoot));
|
|
100111
|
-
}
|
|
100112
|
-
function parseIssueDocument(markdown) {
|
|
100113
|
-
const frontmatter = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/.exec(markdown);
|
|
100114
|
-
if (!frontmatter) {
|
|
100115
|
-
return {
|
|
100116
|
-
ok: false,
|
|
100117
|
-
error: {
|
|
100118
|
-
kind: "missing_frontmatter",
|
|
100119
|
-
message: "Issue Markdown must start with YAML frontmatter"
|
|
100120
|
-
}
|
|
100121
|
-
};
|
|
100122
|
-
}
|
|
100123
|
-
const frontmatterSource = frontmatter[1] ?? "";
|
|
100124
|
-
let rawFrontmatter;
|
|
100125
|
-
try {
|
|
100126
|
-
rawFrontmatter = $parse(frontmatterSource);
|
|
100127
|
-
} catch (error51) {
|
|
100128
|
-
return invalidFrontmatterResult(error51 instanceof Error ? error51.message : String(error51));
|
|
100129
|
-
}
|
|
100130
|
-
const parsedFrontmatter = frontmatterSchema.safeParse(rawFrontmatter);
|
|
100131
|
-
if (!parsedFrontmatter.success) {
|
|
100132
|
-
return invalidFrontmatterResult(parsedFrontmatter.error.issues.map(formatZodIssue).join("; "));
|
|
100133
|
-
}
|
|
100134
|
-
const errors4 = [];
|
|
100135
|
-
let issueId;
|
|
100136
|
-
const id = parseIssueId(parsedFrontmatter.data.id);
|
|
100137
|
-
if (id.ok)
|
|
100138
|
-
issueId = id.value;
|
|
100139
|
-
else
|
|
100140
|
-
errors4.push(id.error.message);
|
|
100141
|
-
const labels = [];
|
|
100142
|
-
for (const rawLabel of parsedFrontmatter.data.labels) {
|
|
100143
|
-
const label = parseLabelId(rawLabel);
|
|
100144
|
-
if (label.ok)
|
|
100145
|
-
labels.push(label.value);
|
|
100146
|
-
else
|
|
100147
|
-
errors4.push(label.error.message);
|
|
100148
|
-
}
|
|
100149
|
-
let createdAt;
|
|
100150
|
-
const parsedCreatedAt = parseUtcTimestamp(parsedFrontmatter.data.created_at);
|
|
100151
|
-
if (parsedCreatedAt.ok)
|
|
100152
|
-
createdAt = parsedCreatedAt.value;
|
|
100153
|
-
else
|
|
100154
|
-
errors4.push(`created_at: ${parsedCreatedAt.error.message}`);
|
|
100155
|
-
let updatedAt;
|
|
100156
|
-
const parsedUpdatedAt = parseUtcTimestamp(parsedFrontmatter.data.updated_at);
|
|
100157
|
-
if (parsedUpdatedAt.ok)
|
|
100158
|
-
updatedAt = parsedUpdatedAt.value;
|
|
100159
|
-
else
|
|
100160
|
-
errors4.push(`updated_at: ${parsedUpdatedAt.error.message}`);
|
|
100161
|
-
if (errors4.length > 0 || !issueId || !createdAt || !updatedAt) {
|
|
100162
|
-
return invalidFrontmatterResult(errors4.join("; "));
|
|
100163
|
-
}
|
|
100164
|
-
return {
|
|
100165
|
-
ok: true,
|
|
100166
|
-
value: {
|
|
100167
|
-
frontmatter: parsedFrontmatter.data,
|
|
100168
|
-
issue: {
|
|
100169
|
-
id: issueId,
|
|
100170
|
-
title: parsedFrontmatter.data.title,
|
|
100171
|
-
labels,
|
|
100172
|
-
createdAt,
|
|
100173
|
-
updatedAt,
|
|
100174
|
-
body: markdown.slice(frontmatter[0].length)
|
|
100175
|
-
}
|
|
100176
|
-
}
|
|
100177
|
-
};
|
|
100178
|
-
}
|
|
100179
100384
|
function readIssueDocument(path) {
|
|
100180
|
-
const parsed = parseIssueDocument(
|
|
100385
|
+
const parsed = parseIssueDocument(readFileSync2(path, "utf8"));
|
|
100181
100386
|
if (!parsed.ok) {
|
|
100182
100387
|
return {
|
|
100183
100388
|
ok: false,
|
|
@@ -100186,14 +100391,6 @@ function readIssueDocument(path) {
|
|
|
100186
100391
|
}
|
|
100187
100392
|
return parsed;
|
|
100188
100393
|
}
|
|
100189
|
-
function serializeIssue(input) {
|
|
100190
|
-
return `---
|
|
100191
|
-
${$stringify(input.frontmatter).trim()}
|
|
100192
|
-
---
|
|
100193
|
-
${input.body.startsWith(`
|
|
100194
|
-
`) ? "" : `
|
|
100195
|
-
`}${input.body}`;
|
|
100196
|
-
}
|
|
100197
100394
|
function validateStatus(config2, status) {
|
|
100198
100395
|
if (!config2.board.columns.some((column) => column.id === status)) {
|
|
100199
100396
|
return {
|
|
@@ -100230,79 +100427,19 @@ function validateLabels(config2, labels) {
|
|
|
100230
100427
|
}
|
|
100231
100428
|
return { ok: true, value: parsed };
|
|
100232
100429
|
}
|
|
100233
|
-
function
|
|
100234
|
-
const
|
|
100235
|
-
|
|
100236
|
-
|
|
100237
|
-
|
|
100238
|
-
|
|
100239
|
-
|
|
100240
|
-
|
|
100241
|
-
|
|
100242
|
-
try {
|
|
100243
|
-
writeFileSync(path, String(process.pid), { flag: "wx" });
|
|
100244
|
-
} catch {
|
|
100245
|
-
return {
|
|
100246
|
-
ok: false,
|
|
100247
|
-
error: { kind: "lock_held", message: "mikan write lock is held", path }
|
|
100248
|
-
};
|
|
100249
|
-
}
|
|
100250
|
-
try {
|
|
100251
|
-
return operation();
|
|
100252
|
-
} catch (error51) {
|
|
100253
|
-
return {
|
|
100254
|
-
ok: false,
|
|
100255
|
-
error: {
|
|
100256
|
-
kind: "io_error",
|
|
100257
|
-
message: error51 instanceof Error ? error51.message : String(error51)
|
|
100258
|
-
}
|
|
100259
|
-
};
|
|
100260
|
-
} finally {
|
|
100261
|
-
rmSync(path, { force: true });
|
|
100262
|
-
}
|
|
100263
|
-
}
|
|
100264
|
-
function atomicWriteFile(path, content) {
|
|
100265
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
100266
|
-
const tmp = join(dirname(path), `.${basename(path)}.${process.pid}.${Date.now()}.tmp`);
|
|
100267
|
-
writeFileSync(tmp, content);
|
|
100268
|
-
renameSync(tmp, path);
|
|
100269
|
-
}
|
|
100270
|
-
function sortedMarkdownFiles(directory) {
|
|
100271
|
-
return readdirSync(directory).filter((entry) => entry.endsWith(".md")).filter((entry) => statSync(join(directory, entry)).isFile()).sort();
|
|
100272
|
-
}
|
|
100273
|
-
function readHookFailureWarnings(projectRoot) {
|
|
100274
|
-
const path = join(projectRoot, ".mikan", ".state", "hook-log.ndjson");
|
|
100275
|
-
if (!existsSync(path))
|
|
100276
|
-
return [];
|
|
100277
|
-
return readFileSync(path, "utf8").split(`
|
|
100278
|
-
`).filter((line) => line.trim().length > 0).flatMap((line) => {
|
|
100279
|
-
let entry;
|
|
100280
|
-
try {
|
|
100281
|
-
entry = JSON.parse(line);
|
|
100282
|
-
} catch {
|
|
100283
|
-
return [];
|
|
100430
|
+
function validateDependencies(dependencies) {
|
|
100431
|
+
const parsed = [];
|
|
100432
|
+
for (const dependency of dependencies) {
|
|
100433
|
+
const dependencyId = parseIssueId(dependency);
|
|
100434
|
+
if (!dependencyId.ok) {
|
|
100435
|
+
return {
|
|
100436
|
+
ok: false,
|
|
100437
|
+
error: { kind: "malformed_issue", message: dependencyId.error.message }
|
|
100438
|
+
};
|
|
100284
100439
|
}
|
|
100285
|
-
|
|
100286
|
-
|
|
100287
|
-
|
|
100288
|
-
const command = entry.command;
|
|
100289
|
-
const exitCode = entry.exit_code;
|
|
100290
|
-
const detail = entry.error ? `: ${entry.error}` : "";
|
|
100291
|
-
return [
|
|
100292
|
-
{
|
|
100293
|
-
kind: "hook_failure",
|
|
100294
|
-
message: `Hook failed for ${issueId}: ${command} exited ${exitCode}${detail}`,
|
|
100295
|
-
path,
|
|
100296
|
-
issueId
|
|
100297
|
-
}
|
|
100298
|
-
];
|
|
100299
|
-
});
|
|
100300
|
-
}
|
|
100301
|
-
function isHookFailureEntry(entry) {
|
|
100302
|
-
if (!entry || typeof entry !== "object")
|
|
100303
|
-
return false;
|
|
100304
|
-
const value = entry;
|
|
100305
|
-
return typeof value.issue_id === "string" && typeof value.command === "string" && typeof value.exit_code === "number" && (value.error === undefined || typeof value.error === "string");
|
|
100440
|
+
parsed.push(dependencyId.value);
|
|
100441
|
+
}
|
|
100442
|
+
return { ok: true, value: parsed };
|
|
100306
100443
|
}
|
|
100307
100444
|
function defaultIssueBody(title) {
|
|
100308
100445
|
return `# ${title}
|
|
@@ -100334,38 +100471,15 @@ ${message}`;
|
|
|
100334
100471
|
function utcNow(now) {
|
|
100335
100472
|
return (now?.() ?? new Date).toISOString().replace(/\.\d{3}Z$/, "Z");
|
|
100336
100473
|
}
|
|
100337
|
-
function lockPath(projectRoot) {
|
|
100338
|
-
return join(projectRoot, ".mikan", ".state", "write.lock");
|
|
100339
|
-
}
|
|
100340
|
-
function invalidFrontmatter(message) {
|
|
100341
|
-
return invalidFrontmatterResult(message);
|
|
100342
|
-
}
|
|
100343
|
-
function invalidFrontmatterResult(message) {
|
|
100344
|
-
return {
|
|
100345
|
-
ok: false,
|
|
100346
|
-
error: {
|
|
100347
|
-
kind: "invalid_frontmatter",
|
|
100348
|
-
message
|
|
100349
|
-
}
|
|
100350
|
-
};
|
|
100351
|
-
}
|
|
100352
|
-
function formatZodIssue(issue2) {
|
|
100353
|
-
const path = issue2.path.length > 0 ? `${issue2.path.join(".")}: ` : "";
|
|
100354
|
-
return `${path}${issue2.message}`;
|
|
100355
|
-
}
|
|
100356
|
-
|
|
100357
|
-
// ../mcp/src/index.ts
|
|
100358
|
-
import { readFileSync as readFileSync6 } from "fs";
|
|
100359
|
-
|
|
100360
100474
|
// ../project-config/src/index.ts
|
|
100361
100475
|
import {
|
|
100362
|
-
existsSync as
|
|
100363
|
-
mkdirSync as
|
|
100364
|
-
readFileSync as
|
|
100476
|
+
existsSync as existsSync4,
|
|
100477
|
+
mkdirSync as mkdirSync3,
|
|
100478
|
+
readFileSync as readFileSync3,
|
|
100365
100479
|
statSync as statSync2,
|
|
100366
100480
|
writeFileSync as writeFileSync2
|
|
100367
100481
|
} from "fs";
|
|
100368
|
-
import { dirname as
|
|
100482
|
+
import { dirname as dirname3, join as join4 } from "path";
|
|
100369
100483
|
var DEFAULT_COLUMNS = [
|
|
100370
100484
|
{ id: "backlog", title: "Backlog" },
|
|
100371
100485
|
{ id: "ready", title: "Ready" },
|
|
@@ -100452,11 +100566,11 @@ var projectConfigSchema = exports_external.object({
|
|
|
100452
100566
|
function findProjectConfig(startDir = process.cwd()) {
|
|
100453
100567
|
let current = normalizeStartDirectory(startDir);
|
|
100454
100568
|
while (true) {
|
|
100455
|
-
const configPath =
|
|
100456
|
-
if (
|
|
100569
|
+
const configPath = join4(current, ".mikan", "config.yaml");
|
|
100570
|
+
if (existsSync4(configPath)) {
|
|
100457
100571
|
return { ok: true, value: { projectRoot: current, configPath } };
|
|
100458
100572
|
}
|
|
100459
|
-
const parent =
|
|
100573
|
+
const parent = dirname3(current);
|
|
100460
100574
|
if (parent === current) {
|
|
100461
100575
|
return {
|
|
100462
100576
|
ok: false,
|
|
@@ -100475,7 +100589,7 @@ function loadProjectConfig(startDir = process.cwd()) {
|
|
|
100475
100589
|
return found;
|
|
100476
100590
|
let raw;
|
|
100477
100591
|
try {
|
|
100478
|
-
raw =
|
|
100592
|
+
raw = readFileSync3(found.value.configPath, "utf8");
|
|
100479
100593
|
} catch (error51) {
|
|
100480
100594
|
return {
|
|
100481
100595
|
ok: false,
|
|
@@ -100519,8 +100633,8 @@ function loadProjectConfig(startDir = process.cwd()) {
|
|
|
100519
100633
|
};
|
|
100520
100634
|
}
|
|
100521
100635
|
function initProject(projectRoot, options) {
|
|
100522
|
-
const mikanRoot =
|
|
100523
|
-
const configPath =
|
|
100636
|
+
const mikanRoot = join4(projectRoot, ".mikan");
|
|
100637
|
+
const configPath = join4(mikanRoot, "config.yaml");
|
|
100524
100638
|
const configInput = {
|
|
100525
100639
|
project: {
|
|
100526
100640
|
key: options.key,
|
|
@@ -100544,13 +100658,13 @@ function initProject(projectRoot, options) {
|
|
|
100544
100658
|
}
|
|
100545
100659
|
const config2 = parsedConfig.data;
|
|
100546
100660
|
try {
|
|
100547
|
-
|
|
100661
|
+
mkdirSync3(mikanRoot, { recursive: true });
|
|
100548
100662
|
for (const column of DEFAULT_COLUMNS) {
|
|
100549
|
-
|
|
100663
|
+
mkdirSync3(join4(mikanRoot, column.id), { recursive: true });
|
|
100550
100664
|
}
|
|
100551
|
-
|
|
100552
|
-
|
|
100553
|
-
writeFileSync2(
|
|
100665
|
+
mkdirSync3(join4(mikanRoot, ".state"), { recursive: true });
|
|
100666
|
+
mkdirSync3(join4(mikanRoot, "templates"), { recursive: true });
|
|
100667
|
+
writeFileSync2(join4(mikanRoot, "templates", "issue.md"), defaultIssueTemplate());
|
|
100554
100668
|
writeFileSync2(configPath, $stringify(config2));
|
|
100555
100669
|
} catch (error51) {
|
|
100556
100670
|
return {
|
|
@@ -100582,9 +100696,9 @@ function formatConfigIssue(issue2) {
|
|
|
100582
100696
|
return `${path}${issue2.message}`;
|
|
100583
100697
|
}
|
|
100584
100698
|
function normalizeStartDirectory(startDir) {
|
|
100585
|
-
if (!
|
|
100699
|
+
if (!existsSync4(startDir))
|
|
100586
100700
|
return startDir;
|
|
100587
|
-
return statSync2(startDir).isDirectory() ? startDir :
|
|
100701
|
+
return statSync2(startDir).isDirectory() ? startDir : dirname3(startDir);
|
|
100588
100702
|
}
|
|
100589
100703
|
function defaultIssueTemplate() {
|
|
100590
100704
|
return `---
|
|
@@ -103656,9 +103770,9 @@ function resolveTypeName2(prop) {
|
|
|
103656
103770
|
|
|
103657
103771
|
// ../../node_modules/.bun/incur@0.4.8/node_modules/incur/dist/SyncMcp.js
|
|
103658
103772
|
import { execFile } from "child_process";
|
|
103659
|
-
import { existsSync as
|
|
103773
|
+
import { existsSync as existsSync5, mkdirSync as mkdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
103660
103774
|
import { homedir } from "os";
|
|
103661
|
-
import { dirname as
|
|
103775
|
+
import { dirname as dirname4, join as join5 } from "path";
|
|
103662
103776
|
async function register2(name, options = {}) {
|
|
103663
103777
|
const runner = detectRunner();
|
|
103664
103778
|
const command = options.command ?? `${runner} ${detectPackageSpecifier(name)} --mcp`;
|
|
@@ -103684,11 +103798,11 @@ async function register2(name, options = {}) {
|
|
|
103684
103798
|
return { command, agents };
|
|
103685
103799
|
}
|
|
103686
103800
|
function registerAmp(name, command) {
|
|
103687
|
-
const configPath =
|
|
103801
|
+
const configPath = join5(homedir(), ".config", "amp", "settings.json");
|
|
103688
103802
|
let config2 = {};
|
|
103689
|
-
if (
|
|
103803
|
+
if (existsSync5(configPath)) {
|
|
103690
103804
|
try {
|
|
103691
|
-
config2 = JSON.parse(
|
|
103805
|
+
config2 = JSON.parse(readFileSync4(configPath, "utf-8"));
|
|
103692
103806
|
} catch {
|
|
103693
103807
|
return false;
|
|
103694
103808
|
}
|
|
@@ -103699,9 +103813,9 @@ function registerAmp(name, command) {
|
|
|
103699
103813
|
const servers = config2["amp.mcpServers"] ?? {};
|
|
103700
103814
|
servers[name] = { command: cmd, args };
|
|
103701
103815
|
config2["amp.mcpServers"] = servers;
|
|
103702
|
-
const dir =
|
|
103703
|
-
if (!
|
|
103704
|
-
|
|
103816
|
+
const dir = dirname4(configPath);
|
|
103817
|
+
if (!existsSync5(dir))
|
|
103818
|
+
mkdirSync4(dir, { recursive: true });
|
|
103705
103819
|
writeFileSync3(configPath, JSON.stringify(config2, null, 2) + `
|
|
103706
103820
|
`);
|
|
103707
103821
|
return true;
|
|
@@ -103714,7 +103828,7 @@ function detectPackageSpecifier(name) {
|
|
|
103714
103828
|
if (!match)
|
|
103715
103829
|
return name;
|
|
103716
103830
|
try {
|
|
103717
|
-
const pkg = JSON.parse(
|
|
103831
|
+
const pkg = JSON.parse(readFileSync4(join5(match[1], "package.json"), "utf-8"));
|
|
103718
103832
|
const deps = pkg.dependencies ?? {};
|
|
103719
103833
|
const spec = deps[name];
|
|
103720
103834
|
if (!spec || Object.keys(deps).length !== 1)
|
|
@@ -106311,116 +106425,85 @@ function resolveDisplayName(name, aliases) {
|
|
|
106311
106425
|
const bin = process.argv[1];
|
|
106312
106426
|
if (!bin)
|
|
106313
106427
|
return name;
|
|
106314
|
-
const
|
|
106315
|
-
if (
|
|
106428
|
+
const basename4 = path3.basename(bin);
|
|
106429
|
+
if (basename4 === name)
|
|
106316
106430
|
return name;
|
|
106317
|
-
if (aliases?.includes(
|
|
106318
|
-
return
|
|
106431
|
+
if (aliases?.includes(basename4))
|
|
106432
|
+
return basename4;
|
|
106319
106433
|
return name;
|
|
106320
106434
|
}
|
|
106321
|
-
// ../mcp/src/installers.ts
|
|
106435
|
+
// ../mcp/src/installers/shared.ts
|
|
106322
106436
|
import {
|
|
106323
106437
|
chmodSync,
|
|
106324
|
-
existsSync as
|
|
106325
|
-
mkdirSync as
|
|
106326
|
-
readFileSync as
|
|
106327
|
-
renameSync as
|
|
106438
|
+
existsSync as existsSync7,
|
|
106439
|
+
mkdirSync as mkdirSync6,
|
|
106440
|
+
readFileSync as readFileSync6,
|
|
106441
|
+
renameSync as renameSync3,
|
|
106328
106442
|
statSync as statSync3,
|
|
106329
106443
|
writeFileSync as writeFileSync4
|
|
106330
106444
|
} from "fs";
|
|
106331
106445
|
import { homedir as homedir4 } from "os";
|
|
106332
|
-
import { dirname as
|
|
106446
|
+
import { dirname as dirname6, join as join8, resolve as resolve3 } from "path";
|
|
106333
106447
|
var defaultServerName = "mikan";
|
|
106334
106448
|
var defaultCommand = "mikan";
|
|
106335
106449
|
var defaultArgs = ["mcp"];
|
|
106336
|
-
|
|
106337
|
-
|
|
106338
|
-
{ agent: "antigravity", install: installAntigravityMcpServer },
|
|
106339
|
-
{ agent: "jcode", install: installJcodeMcpServer }
|
|
106340
|
-
];
|
|
106341
|
-
function installMcpServerForAgent(agent, options = {}) {
|
|
106342
|
-
const installer = mcpAgentInstallers.find((entry) => entry.agent === agent);
|
|
106343
|
-
if (!installer) {
|
|
106344
|
-
throw new Error(`Unsupported MCP agent: ${agent}. Supported agents: ${mcpAgentInstallers.map((entry) => entry.agent).join(", ")}`);
|
|
106345
|
-
}
|
|
106346
|
-
return installer.install(options);
|
|
106450
|
+
function isGlobalScope(options) {
|
|
106451
|
+
return options.global !== false;
|
|
106347
106452
|
}
|
|
106348
|
-
function
|
|
106349
|
-
|
|
106350
|
-
|
|
106351
|
-
|
|
106352
|
-
|
|
106353
|
-
const serverName = options.serverName ?? defaultServerName;
|
|
106354
|
-
servers[serverName] = {
|
|
106355
|
-
command: options.command ?? defaultCommand,
|
|
106356
|
-
args: options.args ?? defaultArgs
|
|
106357
|
-
};
|
|
106358
|
-
config2.mcpServers = servers;
|
|
106359
|
-
writeJsonObject(path4, config2);
|
|
106360
|
-
return {
|
|
106361
|
-
agent: "pi",
|
|
106362
|
-
path: path4,
|
|
106363
|
-
serverName,
|
|
106364
|
-
scope: global2 ? "global" : "workspace"
|
|
106365
|
-
};
|
|
106453
|
+
function workspacePath(options, ...segments) {
|
|
106454
|
+
return resolve3(options.cwd ?? process.cwd(), ...segments);
|
|
106455
|
+
}
|
|
106456
|
+
function homePath(options, ...segments) {
|
|
106457
|
+
return join8(options.home ?? homedir4(), ...segments);
|
|
106366
106458
|
}
|
|
106367
|
-
function
|
|
106368
|
-
|
|
106369
|
-
|
|
106370
|
-
|
|
106371
|
-
|
|
106372
|
-
const serverName = options.serverName ?? defaultServerName;
|
|
106373
|
-
servers[serverName] = {
|
|
106459
|
+
function resolveServerName(options) {
|
|
106460
|
+
return options.serverName ?? defaultServerName;
|
|
106461
|
+
}
|
|
106462
|
+
function buildServerSpec(options) {
|
|
106463
|
+
return {
|
|
106374
106464
|
command: options.command ?? defaultCommand,
|
|
106375
|
-
args: options.args ?? defaultArgs,
|
|
106465
|
+
args: options.args ?? [...defaultArgs],
|
|
106376
106466
|
env: options.env ?? {}
|
|
106377
106467
|
};
|
|
106378
|
-
config2.mcpServers = servers;
|
|
106379
|
-
writeJsonObject(path4, config2);
|
|
106380
|
-
return {
|
|
106381
|
-
agent: "antigravity",
|
|
106382
|
-
path: path4,
|
|
106383
|
-
serverName,
|
|
106384
|
-
scope: global2 ? "cli-global" : "workspace"
|
|
106385
|
-
};
|
|
106386
106468
|
}
|
|
106387
|
-
function
|
|
106388
|
-
const global2 = options.global !== false;
|
|
106389
|
-
const path4 = global2 ? join6(options.home ?? homedir4(), ".jcode", "mcp.json") : resolve3(options.cwd ?? process.cwd(), ".jcode", "mcp.json");
|
|
106390
|
-
const config2 = readJsonObject(path4);
|
|
106391
|
-
const servers = objectProperty(config2, "servers");
|
|
106392
|
-
const serverName = options.serverName ?? defaultServerName;
|
|
106393
|
-
servers[serverName] = {
|
|
106394
|
-
command: options.command ?? defaultCommand,
|
|
106395
|
-
args: options.args ?? defaultArgs,
|
|
106396
|
-
env: options.env ?? {},
|
|
106397
|
-
shared: true
|
|
106398
|
-
};
|
|
106399
|
-
config2.servers = servers;
|
|
106400
|
-
writeJsonObject(path4, config2);
|
|
106469
|
+
function createInstaller(adapter) {
|
|
106401
106470
|
return {
|
|
106402
|
-
agent:
|
|
106403
|
-
|
|
106404
|
-
|
|
106405
|
-
|
|
106471
|
+
agent: adapter.agent,
|
|
106472
|
+
install: (options = {}) => {
|
|
106473
|
+
const { path: path4, scope } = adapter.resolveTarget(options);
|
|
106474
|
+
const serverName = resolveServerName(options);
|
|
106475
|
+
const spec = buildServerSpec(options);
|
|
106476
|
+
const config2 = readJsonObject(path4);
|
|
106477
|
+
const servers = objectProperty(config2, adapter.serversKey);
|
|
106478
|
+
servers[serverName] = adapter.buildEntry(spec);
|
|
106479
|
+
config2[adapter.serversKey] = servers;
|
|
106480
|
+
writeJsonObject(path4, config2);
|
|
106481
|
+
return { agent: adapter.agent, path: path4, serverName, scope };
|
|
106482
|
+
}
|
|
106406
106483
|
};
|
|
106407
106484
|
}
|
|
106408
106485
|
function readJsonObject(path4) {
|
|
106409
|
-
if (!
|
|
106486
|
+
if (!existsSync7(path4))
|
|
106410
106487
|
return {};
|
|
106411
|
-
const parsed = JSON.parse(
|
|
106488
|
+
const parsed = JSON.parse(readFileSync6(path4, "utf8"));
|
|
106412
106489
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
106413
106490
|
return {};
|
|
106414
106491
|
return parsed;
|
|
106415
106492
|
}
|
|
106416
|
-
function
|
|
106417
|
-
|
|
106493
|
+
function writeTextFileAtomic(path4, contents) {
|
|
106494
|
+
mkdirSync6(dirname6(path4), { recursive: true });
|
|
106418
106495
|
const tmpPath = `${path4}.${process.pid}.tmp`;
|
|
106419
|
-
const mode =
|
|
106420
|
-
writeFileSync4(tmpPath,
|
|
106421
|
-
`, "utf8");
|
|
106496
|
+
const mode = existsSync7(path4) ? statSync3(path4).mode & 511 : 384;
|
|
106497
|
+
writeFileSync4(tmpPath, contents, "utf8");
|
|
106422
106498
|
chmodSync(tmpPath, mode);
|
|
106423
|
-
|
|
106499
|
+
renameSync3(tmpPath, path4);
|
|
106500
|
+
}
|
|
106501
|
+
function writeJsonObject(path4, config2) {
|
|
106502
|
+
writeTextFileAtomic(path4, `${JSON.stringify(config2, null, 2)}
|
|
106503
|
+
`);
|
|
106504
|
+
}
|
|
106505
|
+
function readTextFile(path4) {
|
|
106506
|
+
return existsSync7(path4) ? readFileSync6(path4, "utf8") : "";
|
|
106424
106507
|
}
|
|
106425
106508
|
function objectProperty(config2, key) {
|
|
106426
106509
|
const value = config2[key];
|
|
@@ -106429,6 +106512,308 @@ function objectProperty(config2, key) {
|
|
|
106429
106512
|
return value;
|
|
106430
106513
|
}
|
|
106431
106514
|
|
|
106515
|
+
// ../mcp/src/installers/antigravity.ts
|
|
106516
|
+
var antigravityAdapter = {
|
|
106517
|
+
agent: "antigravity",
|
|
106518
|
+
serversKey: "mcpServers",
|
|
106519
|
+
resolveTarget: (options) => isGlobalScope(options) ? {
|
|
106520
|
+
path: homePath(options, ".gemini", "antigravity-cli", "mcp_config.json"),
|
|
106521
|
+
scope: "cli-global"
|
|
106522
|
+
} : {
|
|
106523
|
+
path: workspacePath(options, ".agents", "mcp_config.json"),
|
|
106524
|
+
scope: "workspace"
|
|
106525
|
+
},
|
|
106526
|
+
buildEntry: (spec) => ({
|
|
106527
|
+
command: spec.command,
|
|
106528
|
+
args: spec.args,
|
|
106529
|
+
env: spec.env
|
|
106530
|
+
})
|
|
106531
|
+
};
|
|
106532
|
+
var antigravityInstaller = createInstaller(antigravityAdapter);
|
|
106533
|
+
|
|
106534
|
+
// ../mcp/src/installers/claude-code.ts
|
|
106535
|
+
var claudeCodeAdapter = {
|
|
106536
|
+
agent: "claude-code",
|
|
106537
|
+
serversKey: "mcpServers",
|
|
106538
|
+
resolveTarget: (options) => isGlobalScope(options) ? { path: homePath(options, ".claude.json"), scope: "global" } : { path: workspacePath(options, ".mcp.json"), scope: "workspace" },
|
|
106539
|
+
buildEntry: (spec) => ({ command: spec.command, args: spec.args })
|
|
106540
|
+
};
|
|
106541
|
+
var claudeCodeInstaller = createInstaller(claudeCodeAdapter);
|
|
106542
|
+
|
|
106543
|
+
// ../mcp/src/installers/codex.ts
|
|
106544
|
+
function tomlBasicString(value) {
|
|
106545
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
|
|
106546
|
+
}
|
|
106547
|
+
function tomlKey(key) {
|
|
106548
|
+
return /^[A-Za-z0-9_-]+$/.test(key) ? key : tomlBasicString(key);
|
|
106549
|
+
}
|
|
106550
|
+
function tableHeader(serverName) {
|
|
106551
|
+
return `[mcp_servers.${tomlKey(serverName)}]`;
|
|
106552
|
+
}
|
|
106553
|
+
function regexEscape(value) {
|
|
106554
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
106555
|
+
}
|
|
106556
|
+
function hasParentFormDefinition(existing, serverName) {
|
|
106557
|
+
const name = regexEscape(serverName);
|
|
106558
|
+
if (new RegExp(`^\\s*mcp_servers\\s*\\.\\s*${name}\\b`, "m").test(existing)) {
|
|
106559
|
+
return true;
|
|
106560
|
+
}
|
|
106561
|
+
const assignment = new RegExp(`^\\s*${name}\\s*[.=]`);
|
|
106562
|
+
let inParentTable = false;
|
|
106563
|
+
for (const line of existing.split(`
|
|
106564
|
+
`)) {
|
|
106565
|
+
const trimmed = line.trim();
|
|
106566
|
+
if (trimmed.startsWith("[")) {
|
|
106567
|
+
inParentTable = trimmed === "[mcp_servers]";
|
|
106568
|
+
continue;
|
|
106569
|
+
}
|
|
106570
|
+
if (inParentTable && assignment.test(line))
|
|
106571
|
+
return true;
|
|
106572
|
+
}
|
|
106573
|
+
return false;
|
|
106574
|
+
}
|
|
106575
|
+
function renderServerTable(serverName, spec) {
|
|
106576
|
+
const lines = [tableHeader(serverName)];
|
|
106577
|
+
lines.push(`command = ${tomlBasicString(spec.command)}`);
|
|
106578
|
+
lines.push(`args = [${spec.args.map(tomlBasicString).join(", ")}]`);
|
|
106579
|
+
const envEntries2 = Object.entries(spec.env);
|
|
106580
|
+
if (envEntries2.length > 0) {
|
|
106581
|
+
const inline = envEntries2.map(([key, value]) => `${tomlKey(key)} = ${tomlBasicString(value)}`).join(", ");
|
|
106582
|
+
lines.push(`env = { ${inline} }`);
|
|
106583
|
+
}
|
|
106584
|
+
return lines.join(`
|
|
106585
|
+
`);
|
|
106586
|
+
}
|
|
106587
|
+
function upsertServerTable(existing, serverName, tableText) {
|
|
106588
|
+
const header = tableHeader(serverName);
|
|
106589
|
+
const lines = existing.split(`
|
|
106590
|
+
`);
|
|
106591
|
+
const startIdx = lines.findIndex((line) => line.trim() === header);
|
|
106592
|
+
if (startIdx === -1) {
|
|
106593
|
+
const trimmed = existing.replace(/\s*$/, "");
|
|
106594
|
+
return trimmed.length > 0 ? `${trimmed}
|
|
106595
|
+
|
|
106596
|
+
${tableText}
|
|
106597
|
+
` : `${tableText}
|
|
106598
|
+
`;
|
|
106599
|
+
}
|
|
106600
|
+
let endIdx = lines.length;
|
|
106601
|
+
for (let i = startIdx + 1;i < lines.length; i++) {
|
|
106602
|
+
if ((lines[i] ?? "").trim().startsWith("[")) {
|
|
106603
|
+
endIdx = i;
|
|
106604
|
+
break;
|
|
106605
|
+
}
|
|
106606
|
+
}
|
|
106607
|
+
const merged = [
|
|
106608
|
+
...lines.slice(0, startIdx),
|
|
106609
|
+
...tableText.split(`
|
|
106610
|
+
`),
|
|
106611
|
+
...lines.slice(endIdx)
|
|
106612
|
+
];
|
|
106613
|
+
const result = merged.join(`
|
|
106614
|
+
`);
|
|
106615
|
+
return result.endsWith(`
|
|
106616
|
+
`) ? result : `${result}
|
|
106617
|
+
`;
|
|
106618
|
+
}
|
|
106619
|
+
function installCodexMcpServer(options = {}) {
|
|
106620
|
+
if (!isGlobalScope(options)) {
|
|
106621
|
+
throw new Error("Codex MCP configuration is global-only; it has no workspace-local " + "scope. Re-run `mikan mcp add --agent codex` without --no-global to " + "register the server in ~/.codex/config.toml.");
|
|
106622
|
+
}
|
|
106623
|
+
const path4 = homePath(options, ".codex", "config.toml");
|
|
106624
|
+
const serverName = resolveServerName(options);
|
|
106625
|
+
const spec = buildServerSpec(options);
|
|
106626
|
+
const existing = readTextFile(path4);
|
|
106627
|
+
const hasCanonicalTable = existing.split(`
|
|
106628
|
+
`).some((line) => line.trim() === tableHeader(serverName));
|
|
106629
|
+
if (!hasCanonicalTable && hasParentFormDefinition(existing, serverName)) {
|
|
106630
|
+
throw new Error(`mikan found an existing '${serverName}' MCP server in ${path4} defined ` + "under a [mcp_servers] table form it cannot safely merge. Edit that " + "entry manually or use `codex mcp add` instead.");
|
|
106631
|
+
}
|
|
106632
|
+
const table2 = renderServerTable(serverName, spec);
|
|
106633
|
+
writeTextFileAtomic(path4, upsertServerTable(existing, serverName, table2));
|
|
106634
|
+
return { agent: "codex", path: path4, serverName, scope: "global" };
|
|
106635
|
+
}
|
|
106636
|
+
var codexInstaller = {
|
|
106637
|
+
agent: "codex",
|
|
106638
|
+
install: installCodexMcpServer
|
|
106639
|
+
};
|
|
106640
|
+
|
|
106641
|
+
// ../mcp/src/installers/jcode.ts
|
|
106642
|
+
var jcodeAdapter = {
|
|
106643
|
+
agent: "jcode",
|
|
106644
|
+
serversKey: "servers",
|
|
106645
|
+
resolveTarget: (options) => isGlobalScope(options) ? { path: homePath(options, ".jcode", "mcp.json"), scope: "global" } : {
|
|
106646
|
+
path: workspacePath(options, ".jcode", "mcp.json"),
|
|
106647
|
+
scope: "workspace"
|
|
106648
|
+
},
|
|
106649
|
+
buildEntry: (spec) => ({
|
|
106650
|
+
command: spec.command,
|
|
106651
|
+
args: spec.args,
|
|
106652
|
+
env: spec.env,
|
|
106653
|
+
shared: true
|
|
106654
|
+
})
|
|
106655
|
+
};
|
|
106656
|
+
var jcodeInstaller = createInstaller(jcodeAdapter);
|
|
106657
|
+
|
|
106658
|
+
// ../mcp/src/installers/opencode.ts
|
|
106659
|
+
var opencodeAdapter = {
|
|
106660
|
+
agent: "opencode",
|
|
106661
|
+
serversKey: "mcp",
|
|
106662
|
+
resolveTarget: (options) => isGlobalScope(options) ? {
|
|
106663
|
+
path: homePath(options, ".config", "opencode", "opencode.json"),
|
|
106664
|
+
scope: "global"
|
|
106665
|
+
} : {
|
|
106666
|
+
path: workspacePath(options, "opencode.json"),
|
|
106667
|
+
scope: "workspace"
|
|
106668
|
+
},
|
|
106669
|
+
buildEntry: (spec) => ({
|
|
106670
|
+
type: "local",
|
|
106671
|
+
command: [spec.command, ...spec.args],
|
|
106672
|
+
enabled: true,
|
|
106673
|
+
environment: spec.env
|
|
106674
|
+
})
|
|
106675
|
+
};
|
|
106676
|
+
var opencodeInstaller = createInstaller(opencodeAdapter);
|
|
106677
|
+
|
|
106678
|
+
// ../mcp/src/installers/pi.ts
|
|
106679
|
+
var piAdapter = {
|
|
106680
|
+
agent: "pi",
|
|
106681
|
+
serversKey: "mcpServers",
|
|
106682
|
+
resolveTarget: (options) => isGlobalScope(options) ? {
|
|
106683
|
+
path: homePath(options, ".config", "mcp", "mcp.json"),
|
|
106684
|
+
scope: "global"
|
|
106685
|
+
} : { path: workspacePath(options, ".mcp.json"), scope: "workspace" },
|
|
106686
|
+
buildEntry: (spec) => ({ command: spec.command, args: spec.args })
|
|
106687
|
+
};
|
|
106688
|
+
var piInstaller = createInstaller(piAdapter);
|
|
106689
|
+
|
|
106690
|
+
// ../mcp/src/installers/index.ts
|
|
106691
|
+
var mcpAgentInstallers = [
|
|
106692
|
+
piInstaller,
|
|
106693
|
+
antigravityInstaller,
|
|
106694
|
+
jcodeInstaller,
|
|
106695
|
+
claudeCodeInstaller,
|
|
106696
|
+
opencodeInstaller,
|
|
106697
|
+
codexInstaller
|
|
106698
|
+
];
|
|
106699
|
+
function installMcpServerForAgent(agent, options = {}) {
|
|
106700
|
+
const installer = mcpAgentInstallers.find((entry) => entry.agent === agent);
|
|
106701
|
+
if (!installer) {
|
|
106702
|
+
throw new Error(`Unsupported MCP agent: ${agent}. Supported agents: ${mcpAgentInstallers.map((entry) => entry.agent).join(", ")}`);
|
|
106703
|
+
}
|
|
106704
|
+
return installer.install(options);
|
|
106705
|
+
}
|
|
106706
|
+
// ../mcp/src/skills/shared.ts
|
|
106707
|
+
var skillDocument = `---
|
|
106708
|
+
name: mikan
|
|
106709
|
+
description: mikan is a local-first Issue board for AI-assisted development. Use it to read the board and to create, update, move, and append to Issues through the mikan MCP tools. Trigger when the user wants to see the board, add or change an Issue, move an Issue to another Status, record a Report or Note, or decide what to work on next.
|
|
106710
|
+
---
|
|
106711
|
+
|
|
106712
|
+
# mikan
|
|
106713
|
+
|
|
106714
|
+
mikan is a tiny, local-first, Markdown-backed Issue board. Each Issue has a
|
|
106715
|
+
stable Issue ID such as \`MIK-001\`, one current Status (the board Column it
|
|
106716
|
+
lives in), optional Labels, and a body that can hold Reports and Notes.
|
|
106717
|
+
|
|
106718
|
+
Drive mikan through its MCP tools rather than editing the Markdown files
|
|
106719
|
+
directly:
|
|
106720
|
+
|
|
106721
|
+
- \`get_board\`, \`list_issues\`, \`get_issue\` \u2014 read the board and individual Issues.
|
|
106722
|
+
- \`create_issue\` \u2014 create an Issue (title, optional body, status, labels, depends_on).
|
|
106723
|
+
- \`update_issue\` \u2014 update an Issue's title, labels, dependencies, or body.
|
|
106724
|
+
- \`move_issue\` \u2014 move an Issue to another Status, including \`blocked\` and \`completed\`.
|
|
106725
|
+
- \`append_issue\` \u2014 append a Report (with a source) or a Note to an Issue.
|
|
106726
|
+
|
|
106727
|
+
## Statuses
|
|
106728
|
+
|
|
106729
|
+
The standard Statuses are \`backlog\`, \`ready\`, \`active\`, \`blocked\`,
|
|
106730
|
+
\`completed\`, and \`archived\`. An Issue's Status is the board Column it sits in;
|
|
106731
|
+
change it with \`move_issue\`.
|
|
106732
|
+
|
|
106733
|
+
## Dependencies are advisory
|
|
106734
|
+
|
|
106735
|
+
An Issue may declare \`depends_on\` (prerequisite Issue IDs). Read tools also
|
|
106736
|
+
return \`unmet_dependencies\` and \`dependency_status\` (\`ready\` or \`blocked\`).
|
|
106737
|
+
These are advisory read-model data to help humans and agents pick an order.
|
|
106738
|
+
mikan does not schedule, auto-move, or block Issues on dependencies.
|
|
106739
|
+
|
|
106740
|
+
## Vocabulary
|
|
106741
|
+
|
|
106742
|
+
Use Issue, Issue ID, Status, Column, Label, Report, Note, and Dependency. Avoid
|
|
106743
|
+
Task, ticket, profile, and role.
|
|
106744
|
+
`;
|
|
106745
|
+
function globalSkillPath(options, ...segments) {
|
|
106746
|
+
return homePath(options, ...segments);
|
|
106747
|
+
}
|
|
106748
|
+
function workspaceSkillPath(options, ...segments) {
|
|
106749
|
+
return workspacePath(options, ...segments);
|
|
106750
|
+
}
|
|
106751
|
+
function createSkillInstaller(adapter) {
|
|
106752
|
+
return {
|
|
106753
|
+
agent: adapter.agent,
|
|
106754
|
+
install: (options = {}) => {
|
|
106755
|
+
const { path: path4, scope } = adapter.resolveTarget(options);
|
|
106756
|
+
writeTextFileAtomic(path4, skillDocument);
|
|
106757
|
+
return { agent: adapter.agent, path: path4, scope };
|
|
106758
|
+
}
|
|
106759
|
+
};
|
|
106760
|
+
}
|
|
106761
|
+
|
|
106762
|
+
// ../mcp/src/skills/claude-code.ts
|
|
106763
|
+
var claudeCodeAdapter2 = {
|
|
106764
|
+
agent: "claude-code",
|
|
106765
|
+
resolveTarget: (options) => isGlobalScope(options) ? {
|
|
106766
|
+
path: globalSkillPath(options, ".claude", "skills", "mikan", "SKILL.md"),
|
|
106767
|
+
scope: "global"
|
|
106768
|
+
} : {
|
|
106769
|
+
path: workspaceSkillPath(options, ".claude", "skills", "mikan", "SKILL.md"),
|
|
106770
|
+
scope: "workspace"
|
|
106771
|
+
}
|
|
106772
|
+
};
|
|
106773
|
+
var claudeCodeSkillInstaller = createSkillInstaller(claudeCodeAdapter2);
|
|
106774
|
+
|
|
106775
|
+
// ../mcp/src/skills/codex.ts
|
|
106776
|
+
var codexAdapter = {
|
|
106777
|
+
agent: "codex",
|
|
106778
|
+
resolveTarget: (options) => {
|
|
106779
|
+
if (!isGlobalScope(options)) {
|
|
106780
|
+
throw new Error("Codex skills are global-only; Codex has no workspace-local skill " + "directory. Re-run `mikan skills add --agent codex` without " + "--no-global to install into ~/.codex/skills/.");
|
|
106781
|
+
}
|
|
106782
|
+
return {
|
|
106783
|
+
path: globalSkillPath(options, ".codex", "skills", "mikan", "SKILL.md"),
|
|
106784
|
+
scope: "global"
|
|
106785
|
+
};
|
|
106786
|
+
}
|
|
106787
|
+
};
|
|
106788
|
+
var codexSkillInstaller = createSkillInstaller(codexAdapter);
|
|
106789
|
+
|
|
106790
|
+
// ../mcp/src/skills/opencode.ts
|
|
106791
|
+
var opencodeAdapter2 = {
|
|
106792
|
+
agent: "opencode",
|
|
106793
|
+
resolveTarget: (options) => isGlobalScope(options) ? {
|
|
106794
|
+
path: globalSkillPath(options, ".config", "opencode", "skills", "mikan", "SKILL.md"),
|
|
106795
|
+
scope: "global"
|
|
106796
|
+
} : {
|
|
106797
|
+
path: workspaceSkillPath(options, ".opencode", "skills", "mikan", "SKILL.md"),
|
|
106798
|
+
scope: "workspace"
|
|
106799
|
+
}
|
|
106800
|
+
};
|
|
106801
|
+
var opencodeSkillInstaller = createSkillInstaller(opencodeAdapter2);
|
|
106802
|
+
|
|
106803
|
+
// ../mcp/src/skills/index.ts
|
|
106804
|
+
var skillAgentInstallers = [
|
|
106805
|
+
claudeCodeSkillInstaller,
|
|
106806
|
+
opencodeSkillInstaller,
|
|
106807
|
+
codexSkillInstaller
|
|
106808
|
+
];
|
|
106809
|
+
function installSkillForAgent(agent, options = {}) {
|
|
106810
|
+
const installer = skillAgentInstallers.find((entry) => entry.agent === agent);
|
|
106811
|
+
if (!installer) {
|
|
106812
|
+
throw new Error(`Unsupported skill agent: ${agent}. Supported agents: ${skillAgentInstallers.map((entry) => entry.agent).join(", ")}`);
|
|
106813
|
+
}
|
|
106814
|
+
return installer.install(options);
|
|
106815
|
+
}
|
|
106816
|
+
|
|
106432
106817
|
// ../mcp/src/index.ts
|
|
106433
106818
|
function getBoardTool(args, runtime = {}) {
|
|
106434
106819
|
const loaded = load(runtime.cwd);
|
|
@@ -106486,7 +106871,7 @@ function getIssueTool(args, runtime = {}) {
|
|
|
106486
106871
|
return coreError(found.error.kind, found.error.message);
|
|
106487
106872
|
return ok({
|
|
106488
106873
|
...formatIssue2(found.value, board.value.warnings),
|
|
106489
|
-
markdown:
|
|
106874
|
+
markdown: readFileSync7(found.value.path, "utf8")
|
|
106490
106875
|
});
|
|
106491
106876
|
}
|
|
106492
106877
|
function createIssueTool(args, runtime = {}) {
|
|
@@ -106500,6 +106885,7 @@ function createIssueTool(args, runtime = {}) {
|
|
|
106500
106885
|
body: args.body,
|
|
106501
106886
|
status: args.status,
|
|
106502
106887
|
labels: args.labels,
|
|
106888
|
+
dependencies: args.depends_on,
|
|
106503
106889
|
now: runtime.now
|
|
106504
106890
|
});
|
|
106505
106891
|
if (!result.ok)
|
|
@@ -106517,6 +106903,7 @@ function updateIssueTool(args, runtime = {}) {
|
|
|
106517
106903
|
title: args.title,
|
|
106518
106904
|
labels: args.labels,
|
|
106519
106905
|
body: args.body,
|
|
106906
|
+
dependencies: args.depends_on,
|
|
106520
106907
|
now: runtime.now
|
|
106521
106908
|
});
|
|
106522
106909
|
if (!result.ok)
|
|
@@ -106580,16 +106967,18 @@ function createMikanMcpCli(runtime = {}) {
|
|
|
106580
106967
|
title: exports_external.string(),
|
|
106581
106968
|
body: exports_external.string().optional(),
|
|
106582
106969
|
status: exports_external.string().optional(),
|
|
106583
|
-
labels: exports_external.array(exports_external.string()).optional()
|
|
106970
|
+
labels: exports_external.array(exports_external.string()).optional(),
|
|
106971
|
+
depends_on: exports_external.array(exports_external.string()).optional()
|
|
106584
106972
|
}),
|
|
106585
106973
|
run: (context) => forIncur(context, createIssueTool(context.args, runtime))
|
|
106586
106974
|
}).command("update_issue", {
|
|
106587
|
-
description: "Update title, labels, or body through the core update primitive.",
|
|
106975
|
+
description: "Update title, labels, dependencies, or body through the core update primitive.",
|
|
106588
106976
|
args: exports_external.object({
|
|
106589
106977
|
id: exports_external.string(),
|
|
106590
106978
|
title: exports_external.string().optional(),
|
|
106591
106979
|
labels: exports_external.array(exports_external.string()).optional(),
|
|
106592
|
-
body: exports_external.string().optional()
|
|
106980
|
+
body: exports_external.string().optional(),
|
|
106981
|
+
depends_on: exports_external.array(exports_external.string()).optional()
|
|
106593
106982
|
}),
|
|
106594
106983
|
run: (context) => forIncur(context, updateIssueTool(context.args, runtime))
|
|
106595
106984
|
}).command("move_issue", {
|
|
@@ -106614,6 +107003,16 @@ function createMikanMcpCli(runtime = {}) {
|
|
|
106614
107003
|
async function startMcpServer(runtime = {}) {
|
|
106615
107004
|
await createMikanMcpCli(runtime).serve(["--mcp"]);
|
|
106616
107005
|
}
|
|
107006
|
+
async function getMcpManifest(runtime = {}, options = {}) {
|
|
107007
|
+
let manifest = "";
|
|
107008
|
+
await createMikanMcpCli(runtime).serve([options.full ? "--llms-full" : "--llms"], {
|
|
107009
|
+
stdout: (chunk) => {
|
|
107010
|
+
manifest += chunk;
|
|
107011
|
+
},
|
|
107012
|
+
exit: () => {}
|
|
107013
|
+
});
|
|
107014
|
+
return manifest;
|
|
107015
|
+
}
|
|
106617
107016
|
function formatColumn(column) {
|
|
106618
107017
|
return {
|
|
106619
107018
|
...column,
|
|
@@ -106630,6 +107029,9 @@ function formatIssue2(issue2, warnings) {
|
|
|
106630
107029
|
body: issue2.issue.body,
|
|
106631
107030
|
status: String(issue2.status),
|
|
106632
107031
|
path: issue2.path,
|
|
107032
|
+
depends_on: issue2.issue.dependencies.map(String),
|
|
107033
|
+
unmet_dependencies: issue2.unmetDependencies.map(String),
|
|
107034
|
+
dependency_status: issue2.dependencyStatus,
|
|
106633
107035
|
warnings: warnings.filter((warning) => warning.issueId === String(issue2.issue.id) || warning.path === issue2.path)
|
|
106634
107036
|
};
|
|
106635
107037
|
}
|
|
@@ -106657,12 +107059,11 @@ function coreError(code, message) {
|
|
|
106657
107059
|
}
|
|
106658
107060
|
|
|
106659
107061
|
// ../tui/src/index.ts
|
|
106660
|
-
|
|
106661
|
-
var import_react17 = __toESM(require_react(), 1);
|
|
107062
|
+
var import_react20 = __toESM(require_react(), 1);
|
|
106662
107063
|
// ../tui/package.json
|
|
106663
107064
|
var package_default = {
|
|
106664
107065
|
name: "@mikan/tui",
|
|
106665
|
-
version: "0.0.
|
|
107066
|
+
version: "0.0.3",
|
|
106666
107067
|
private: true,
|
|
106667
107068
|
type: "module",
|
|
106668
107069
|
exports: {
|
|
@@ -106682,6 +107083,10 @@ var package_default = {
|
|
|
106682
107083
|
}
|
|
106683
107084
|
};
|
|
106684
107085
|
|
|
107086
|
+
// ../tui/src/board-view.ts
|
|
107087
|
+
await init_core3();
|
|
107088
|
+
var import_react = __toESM(require_react(), 1);
|
|
107089
|
+
|
|
106685
107090
|
// ../tui/src/formatting.ts
|
|
106686
107091
|
function formatLabels(labels) {
|
|
106687
107092
|
return labels.map((label) => `#${label}`).join(" ");
|
|
@@ -106697,42 +107102,111 @@ function formatLineRange(options) {
|
|
|
106697
107102
|
].filter(Boolean).join(" | ");
|
|
106698
107103
|
}
|
|
106699
107104
|
function visibleCardCountForViewport(viewportHeight) {
|
|
106700
|
-
return Math.max(1,
|
|
107105
|
+
return Math.max(1, viewportHeight - 6);
|
|
107106
|
+
}
|
|
107107
|
+
var MIN_COLUMN_WIDTH = 40;
|
|
107108
|
+
var MIN_VISIBLE_COLUMNS = 2;
|
|
107109
|
+
var MAX_VISIBLE_COLUMNS = 5;
|
|
107110
|
+
function visibleColumnCountForViewport(viewportWidth) {
|
|
107111
|
+
const fitted = Math.floor(viewportWidth / MIN_COLUMN_WIDTH);
|
|
107112
|
+
return Math.min(MAX_VISIBLE_COLUMNS, Math.max(MIN_VISIBLE_COLUMNS, fitted));
|
|
106701
107113
|
}
|
|
106702
107114
|
function visibleDetailLineCount(viewportHeight) {
|
|
106703
|
-
return Math.max(1, viewportHeight -
|
|
107115
|
+
return Math.max(1, viewportHeight - 8);
|
|
106704
107116
|
}
|
|
106705
107117
|
function footerText(mode) {
|
|
106706
|
-
if (mode === "modal")
|
|
106707
|
-
return "Modal | enter confirm | esc cancel";
|
|
107118
|
+
if (mode === "modal") {
|
|
107119
|
+
return "Modal | enter confirm | esc cancel | ? keys";
|
|
107120
|
+
}
|
|
106708
107121
|
if (mode === "detail") {
|
|
106709
|
-
return "Detail |
|
|
107122
|
+
return "Detail | \u2191\u2193 scroll | esc board | ? keys";
|
|
106710
107123
|
}
|
|
106711
|
-
return "Board |
|
|
107124
|
+
return "Board | \u2191\u2193 card | \u2190\u2192 column | enter detail | ? keys";
|
|
106712
107125
|
}
|
|
106713
107126
|
|
|
106714
|
-
// ../tui/src/
|
|
106715
|
-
|
|
106716
|
-
|
|
107127
|
+
// ../tui/src/selection.ts
|
|
107128
|
+
function clamp(value, min, max) {
|
|
107129
|
+
return Math.min(max, Math.max(min, value));
|
|
107130
|
+
}
|
|
107131
|
+
function clampSelection(model, selection) {
|
|
107132
|
+
const columnIndex = clamp(selection.columnIndex, 0, Math.max(0, model.columns.length - 1));
|
|
107133
|
+
const maxCardIndex = Math.max(0, (model.columns[columnIndex]?.cards.length ?? 1) - 1);
|
|
106717
107134
|
return {
|
|
106718
|
-
|
|
106719
|
-
|
|
106720
|
-
|
|
106721
|
-
|
|
106722
|
-
|
|
106723
|
-
|
|
106724
|
-
|
|
106725
|
-
|
|
106726
|
-
|
|
106727
|
-
|
|
106728
|
-
},
|
|
106729
|
-
feedback: {
|
|
106730
|
-
warning: "#f6c177",
|
|
106731
|
-
error: "#d66a4a",
|
|
106732
|
-
success: "#8faa5f"
|
|
107135
|
+
...selection,
|
|
107136
|
+
columnIndex,
|
|
107137
|
+
cardIndex: clamp(selection.cardIndex, 0, maxCardIndex)
|
|
107138
|
+
};
|
|
107139
|
+
}
|
|
107140
|
+
function findSelectionByCardId(model, cardId) {
|
|
107141
|
+
for (const [columnIndex, column] of model.columns.entries()) {
|
|
107142
|
+
const cardIndex = column.cards.findIndex((card) => card.id === cardId);
|
|
107143
|
+
if (cardIndex !== -1) {
|
|
107144
|
+
return { columnIndex, cardIndex, detailOpen: false };
|
|
106733
107145
|
}
|
|
107146
|
+
}
|
|
107147
|
+
return;
|
|
107148
|
+
}
|
|
107149
|
+
|
|
107150
|
+
// ../tui/src/board-view-model.ts
|
|
107151
|
+
function buildBoardViewModel(model, selection, options = {}) {
|
|
107152
|
+
const visibleCardCount = Math.max(1, options.visibleCardCount ?? (options.viewportHeight ? visibleCardCountForViewport(options.viewportHeight) : 6));
|
|
107153
|
+
const columns = model.columns.map((column, columnIndex) => {
|
|
107154
|
+
const cards = column.cards.map((card, cardIndex) => ({
|
|
107155
|
+
...card,
|
|
107156
|
+
selected: columnIndex === selection.columnIndex && cardIndex === selection.cardIndex,
|
|
107157
|
+
labelsText: card.labels.join(", ")
|
|
107158
|
+
}));
|
|
107159
|
+
const maxCardStart = Math.max(0, cards.length - visibleCardCount);
|
|
107160
|
+
const cardStart = cards.length <= visibleCardCount ? 0 : columnIndex === selection.columnIndex ? clamp(selection.cardIndex - Math.floor(visibleCardCount / 2), 0, maxCardStart) : 0;
|
|
107161
|
+
const visibleCards = cards.slice(cardStart, cardStart + visibleCardCount);
|
|
107162
|
+
const cardEnd = cardStart + visibleCards.length;
|
|
107163
|
+
return {
|
|
107164
|
+
id: column.id,
|
|
107165
|
+
title: column.title,
|
|
107166
|
+
count: column.cards.length,
|
|
107167
|
+
active: columnIndex === selection.columnIndex,
|
|
107168
|
+
empty: column.cards.length === 0,
|
|
107169
|
+
emptyText: "No Issues",
|
|
107170
|
+
cards,
|
|
107171
|
+
visibleCards,
|
|
107172
|
+
laneFillLineCount: Math.max(0, visibleCardCount - visibleCards.length),
|
|
107173
|
+
hiddenCardsBefore: cardStart,
|
|
107174
|
+
hiddenCardsAfter: Math.max(0, cards.length - cardEnd),
|
|
107175
|
+
cardRangeText: cards.length > visibleCardCount ? `${cardStart + 1}-${cardEnd}/${cards.length} | \u2191${cardStart} | \u2193${Math.max(0, cards.length - cardEnd)}` : ""
|
|
107176
|
+
};
|
|
107177
|
+
});
|
|
107178
|
+
const visibleColumnCount = Math.max(1, options.visibleColumnCount ?? (options.viewportWidth ? visibleColumnCountForViewport(options.viewportWidth) : 3));
|
|
107179
|
+
const maxStart = Math.max(0, columns.length - visibleColumnCount);
|
|
107180
|
+
const start = clamp(selection.columnIndex - (visibleColumnCount - 1), 0, maxStart);
|
|
107181
|
+
const visibleColumns = columns.slice(start, start + visibleColumnCount);
|
|
107182
|
+
const hasColumnsBefore = start > 0;
|
|
107183
|
+
const hasColumnsAfter = start + visibleColumnCount < columns.length;
|
|
107184
|
+
return {
|
|
107185
|
+
columns,
|
|
107186
|
+
visibleColumns,
|
|
107187
|
+
groups: [{ columns: visibleColumns }],
|
|
107188
|
+
hasColumnsBefore,
|
|
107189
|
+
hasColumnsAfter,
|
|
107190
|
+
columnViewportText: `Columns: ${hasColumnsBefore ? "\u25C0 " : ""}${visibleColumns.map((column) => column.title).join(" / ")}${hasColumnsAfter ? " \u25B6" : ""}`
|
|
106734
107191
|
};
|
|
106735
107192
|
}
|
|
107193
|
+
function columnWidthPercent(index2, count) {
|
|
107194
|
+
const safeCount = Math.max(1, count);
|
|
107195
|
+
const base = Math.floor(100 / safeCount);
|
|
107196
|
+
const remainder = 100 - base * safeCount;
|
|
107197
|
+
const extraStart = Math.floor((safeCount - remainder) / 2);
|
|
107198
|
+
const width = index2 >= extraStart && index2 < extraStart + remainder ? base + 1 : base;
|
|
107199
|
+
return `${width}%`;
|
|
107200
|
+
}
|
|
107201
|
+
function formatWarningSummary(warnings) {
|
|
107202
|
+
if (warnings.length === 0)
|
|
107203
|
+
return "";
|
|
107204
|
+
const kinds = [...new Set(warnings.map((warning) => warning.split(":")[0]))].filter(Boolean).join(", ");
|
|
107205
|
+
return `Warnings: ${warnings.length}${kinds ? ` ${kinds}` : ""} | w details`;
|
|
107206
|
+
}
|
|
107207
|
+
|
|
107208
|
+
// ../tui/src/model.ts
|
|
107209
|
+
import { readFileSync as readFileSync8 } from "fs";
|
|
106736
107210
|
function loadTuiModel(cwd = process.cwd()) {
|
|
106737
107211
|
const loaded = loadProjectConfig(cwd);
|
|
106738
107212
|
if (!loaded.ok)
|
|
@@ -106752,89 +107226,27 @@ function buildTuiModel(board) {
|
|
|
106752
107226
|
title: column.title,
|
|
106753
107227
|
cards: column.issues.map(formatCard)
|
|
106754
107228
|
})),
|
|
106755
|
-
warnings: board.warnings.map(
|
|
107229
|
+
warnings: board.warnings.map(formatWarning),
|
|
107230
|
+
...board.warnings.length > 0 ? { warningDetails: board.warnings.map(formatTuiWarning) } : {}
|
|
106756
107231
|
};
|
|
106757
107232
|
}
|
|
106758
|
-
function
|
|
106759
|
-
|
|
106760
|
-
return { ...selection, detailOpen: true, detailScrollOffset: 0 };
|
|
106761
|
-
}
|
|
106762
|
-
if (selection.detailOpen && !selection.moveOpen && !selection.noteOpen && (direction === "up" || direction === "down")) {
|
|
106763
|
-
return {
|
|
106764
|
-
...selection,
|
|
106765
|
-
detailScrollOffset: clamp((selection.detailScrollOffset ?? 0) + (direction === "down" ? 1 : -1), 0, detailScrollMax(model, selection, options))
|
|
106766
|
-
};
|
|
106767
|
-
}
|
|
106768
|
-
if (direction === "escape") {
|
|
106769
|
-
if (selection.archiveOpen) {
|
|
106770
|
-
return { ...selection, archiveOpen: false };
|
|
106771
|
-
}
|
|
106772
|
-
return {
|
|
106773
|
-
...selection,
|
|
106774
|
-
detailOpen: false,
|
|
106775
|
-
moveOpen: false,
|
|
106776
|
-
noteOpen: false
|
|
106777
|
-
};
|
|
106778
|
-
}
|
|
106779
|
-
if (direction === "move") {
|
|
106780
|
-
return {
|
|
106781
|
-
...selection,
|
|
106782
|
-
archiveOpen: false,
|
|
106783
|
-
detailOpen: false,
|
|
106784
|
-
noteOpen: false,
|
|
106785
|
-
moveOpen: true,
|
|
106786
|
-
moveTargetIndex: 0
|
|
106787
|
-
};
|
|
106788
|
-
}
|
|
106789
|
-
if (direction === "append-note") {
|
|
106790
|
-
return {
|
|
106791
|
-
...selection,
|
|
106792
|
-
archiveOpen: false,
|
|
106793
|
-
detailOpen: false,
|
|
106794
|
-
moveOpen: false,
|
|
106795
|
-
noteOpen: true
|
|
106796
|
-
};
|
|
106797
|
-
}
|
|
106798
|
-
if (direction === "archive") {
|
|
106799
|
-
return {
|
|
106800
|
-
...selection,
|
|
106801
|
-
archiveOpen: true,
|
|
106802
|
-
moveOpen: false,
|
|
106803
|
-
noteOpen: false
|
|
106804
|
-
};
|
|
106805
|
-
}
|
|
106806
|
-
const columnIndex = clamp(selection.columnIndex + (direction === "right" ? 1 : direction === "left" ? -1 : 0), 0, Math.max(0, model.columns.length - 1));
|
|
106807
|
-
const maxCardIndex = Math.max(0, (model.columns[columnIndex]?.cards.length ?? 1) - 1);
|
|
106808
|
-
const cardIndex = clamp(direction === "up" ? selection.cardIndex - 1 : direction === "down" ? selection.cardIndex + 1 : Math.min(selection.cardIndex, maxCardIndex), 0, maxCardIndex);
|
|
106809
|
-
return { ...selection, columnIndex, cardIndex };
|
|
107233
|
+
function formatWarning(warning) {
|
|
107234
|
+
return `${warning.kind}: ${warning.message}`;
|
|
106810
107235
|
}
|
|
106811
|
-
function
|
|
106812
|
-
const selectedCard = options.model.columns[options.selection.columnIndex]?.cards[options.selection.cardIndex];
|
|
106813
|
-
const model = loadTuiModel(options.cwd);
|
|
106814
|
-
const foundSelection = selectedCard ? findSelectionByCardId(model, selectedCard.id) : undefined;
|
|
106815
|
-
const selection = foundSelection ?? clampSelection(model, options.selection);
|
|
106816
|
-
const stillSelected = Boolean(foundSelection);
|
|
107236
|
+
function formatTuiWarning(warning) {
|
|
106817
107237
|
return {
|
|
106818
|
-
|
|
106819
|
-
|
|
106820
|
-
|
|
106821
|
-
|
|
106822
|
-
|
|
106823
|
-
detailScrollMax: stillSelected ? options.selection.detailScrollMax : undefined,
|
|
106824
|
-
moveOpen: stillSelected ? options.selection.moveOpen : false,
|
|
106825
|
-
moveTargetIndex: stillSelected ? options.selection.moveTargetIndex : undefined,
|
|
106826
|
-
noteOpen: stillSelected ? options.selection.noteOpen : false,
|
|
106827
|
-
noteDraft: stillSelected ? options.selection.noteDraft : undefined,
|
|
106828
|
-
message: options.selection.message,
|
|
106829
|
-
archiveOpen: stillSelected ? options.selection.archiveOpen : false
|
|
106830
|
-
}
|
|
107238
|
+
text: formatWarning(warning),
|
|
107239
|
+
kind: warning.kind,
|
|
107240
|
+
message: warning.message,
|
|
107241
|
+
issueId: warning.issueId,
|
|
107242
|
+
path: warning.path
|
|
106831
107243
|
};
|
|
106832
107244
|
}
|
|
106833
107245
|
function getSelectedDetails(model, selection) {
|
|
106834
107246
|
const card = model.columns[selection.columnIndex]?.cards[selection.cardIndex];
|
|
106835
107247
|
if (!card)
|
|
106836
107248
|
return;
|
|
106837
|
-
const markdown =
|
|
107249
|
+
const markdown = readFileSync8(card.path, "utf8");
|
|
106838
107250
|
return {
|
|
106839
107251
|
card,
|
|
106840
107252
|
markdown,
|
|
@@ -106845,162 +107257,128 @@ function getSelectedDetails(model, selection) {
|
|
|
106845
107257
|
herdr: extractSection(markdown, "Herdr") || extractSection(markdown, "herdr")
|
|
106846
107258
|
};
|
|
106847
107259
|
}
|
|
106848
|
-
function
|
|
106849
|
-
return
|
|
107260
|
+
function cardDependsOn(card) {
|
|
107261
|
+
return card.dependsOn ?? [];
|
|
106850
107262
|
}
|
|
106851
|
-
function
|
|
106852
|
-
|
|
106853
|
-
selection,
|
|
106854
|
-
theme = buildTuiTheme(),
|
|
106855
|
-
viewportHeight
|
|
106856
|
-
}) {
|
|
106857
|
-
const details = selection.detailOpen ? getSelectedDetails(model, selection) : undefined;
|
|
106858
|
-
return import_react17.default.createElement("box", {
|
|
106859
|
-
id: "mikan-app",
|
|
106860
|
-
style: {
|
|
106861
|
-
backgroundColor: theme.base.canvas,
|
|
106862
|
-
color: theme.base.text,
|
|
106863
|
-
flexDirection: "column",
|
|
106864
|
-
height: "100%"
|
|
106865
|
-
}
|
|
106866
|
-
}, import_react17.default.createElement(Header, { theme }), import_react17.default.createElement("box", {
|
|
106867
|
-
id: "mikan-main",
|
|
106868
|
-
style: { flexDirection: "column", flexGrow: 1, minHeight: 0 }
|
|
106869
|
-
}, details ? import_react17.default.createElement(DetailPage, {
|
|
106870
|
-
model,
|
|
106871
|
-
selection,
|
|
106872
|
-
theme,
|
|
106873
|
-
viewportHeight
|
|
106874
|
-
}) : import_react17.default.createElement(BoardView, {
|
|
106875
|
-
model,
|
|
106876
|
-
selection,
|
|
106877
|
-
theme,
|
|
106878
|
-
viewportHeight
|
|
106879
|
-
})), selection.moveOpen ? import_react17.default.createElement(MovePrompt, { model, selection, theme }) : undefined, selection.noteOpen ? import_react17.default.createElement(NotePrompt, { model, selection, theme }) : undefined, selection.archiveOpen ? import_react17.default.createElement(ArchivePrompt, { model, selection, theme }) : undefined, import_react17.default.createElement(Footer, {
|
|
106880
|
-
message: selection.message,
|
|
106881
|
-
mode: footerMode(selection),
|
|
106882
|
-
theme
|
|
106883
|
-
}));
|
|
107263
|
+
function cardUnmetDependencies(card) {
|
|
107264
|
+
return card.unmetDependencies ?? [];
|
|
106884
107265
|
}
|
|
106885
|
-
function
|
|
106886
|
-
|
|
106887
|
-
return import_react17.default.createElement("text", {
|
|
106888
|
-
id: "mikan-header",
|
|
106889
|
-
style: { color: theme.interactive.accent },
|
|
106890
|
-
content: `\uD83C\uDF4A mikan v${TUI_VERSION}`
|
|
106891
|
-
});
|
|
107266
|
+
function cardDependencyStatus(card) {
|
|
107267
|
+
return card.dependencyStatus ?? "ready";
|
|
106892
107268
|
}
|
|
106893
|
-
function
|
|
106894
|
-
const details = getSelectedDetails(model, selection);
|
|
106895
|
-
if (!details)
|
|
106896
|
-
return;
|
|
106897
|
-
const markdown = stripFrontmatter(details.markdown).trimEnd();
|
|
106898
|
-
const markdownLines = markdown.split(`
|
|
106899
|
-
`);
|
|
106900
|
-
const visibleLineCount = options.visibleLineCount ?? (options.viewportHeight ? visibleDetailLineCount(options.viewportHeight) : 40);
|
|
106901
|
-
const offset = clamp(selection.detailScrollOffset ?? 0, 0, Math.max(0, markdownLines.length - visibleLineCount));
|
|
106902
|
-
const visibleMarkdownLines = markdownLines.slice(offset, offset + visibleLineCount);
|
|
106903
|
-
const lineEnd = offset + visibleMarkdownLines.length;
|
|
107269
|
+
function formatCard(issue2) {
|
|
106904
107270
|
return {
|
|
106905
|
-
id:
|
|
106906
|
-
title:
|
|
106907
|
-
|
|
106908
|
-
|
|
106909
|
-
|
|
106910
|
-
|
|
106911
|
-
|
|
106912
|
-
|
|
106913
|
-
lineRangeText: formatLineRange({
|
|
106914
|
-
start: offset + 1,
|
|
106915
|
-
end: lineEnd,
|
|
106916
|
-
total: markdownLines.length,
|
|
106917
|
-
hiddenBefore: offset,
|
|
106918
|
-
hiddenAfter: Math.max(0, markdownLines.length - lineEnd)
|
|
106919
|
-
})
|
|
107271
|
+
id: String(issue2.issue.id),
|
|
107272
|
+
title: issue2.issue.title,
|
|
107273
|
+
labels: issue2.issue.labels.map(String),
|
|
107274
|
+
status: String(issue2.status),
|
|
107275
|
+
path: issue2.path,
|
|
107276
|
+
dependsOn: issue2.issue.dependencies.map(String),
|
|
107277
|
+
unmetDependencies: issue2.unmetDependencies.map(String),
|
|
107278
|
+
dependencyStatus: issue2.dependencyStatus
|
|
106920
107279
|
};
|
|
106921
107280
|
}
|
|
106922
|
-
function
|
|
106923
|
-
|
|
106924
|
-
|
|
106925
|
-
|
|
106926
|
-
|
|
106927
|
-
|
|
106928
|
-
|
|
106929
|
-
|
|
106930
|
-
|
|
106931
|
-
|
|
106932
|
-
|
|
106933
|
-
|
|
106934
|
-
|
|
106935
|
-
|
|
106936
|
-
|
|
106937
|
-
|
|
106938
|
-
|
|
106939
|
-
|
|
106940
|
-
|
|
106941
|
-
|
|
106942
|
-
|
|
106943
|
-
|
|
106944
|
-
|
|
106945
|
-
|
|
106946
|
-
}
|
|
106947
|
-
}
|
|
106948
|
-
|
|
106949
|
-
|
|
106950
|
-
|
|
106951
|
-
|
|
106952
|
-
|
|
106953
|
-
|
|
107281
|
+
function stripFrontmatter(markdown) {
|
|
107282
|
+
if (!markdown.startsWith(`---
|
|
107283
|
+
`))
|
|
107284
|
+
return markdown;
|
|
107285
|
+
const end = markdown.indexOf(`
|
|
107286
|
+
---
|
|
107287
|
+
`, 4);
|
|
107288
|
+
if (end === -1)
|
|
107289
|
+
return markdown;
|
|
107290
|
+
return markdown.slice(end + `
|
|
107291
|
+
---
|
|
107292
|
+
`.length).trimStart();
|
|
107293
|
+
}
|
|
107294
|
+
function extractSection(markdown, section) {
|
|
107295
|
+
const lines = markdown.split(`
|
|
107296
|
+
`);
|
|
107297
|
+
const start = lines.findIndex((line) => line.trim().toLowerCase() === `## ${section}`.toLowerCase());
|
|
107298
|
+
if (start === -1)
|
|
107299
|
+
return "";
|
|
107300
|
+
let end = lines.length;
|
|
107301
|
+
for (let index2 = start + 1;index2 < lines.length; index2++) {
|
|
107302
|
+
if (/^##\s+/.test(lines[index2] ?? "")) {
|
|
107303
|
+
end = index2;
|
|
107304
|
+
break;
|
|
107305
|
+
}
|
|
107306
|
+
}
|
|
107307
|
+
return lines.slice(start + 1, end).join(`
|
|
107308
|
+
`).trim();
|
|
107309
|
+
}
|
|
107310
|
+
|
|
107311
|
+
// ../tui/src/theme.ts
|
|
107312
|
+
function buildTuiTheme() {
|
|
106954
107313
|
return {
|
|
106955
|
-
|
|
106956
|
-
|
|
106957
|
-
|
|
106958
|
-
|
|
106959
|
-
|
|
106960
|
-
|
|
107314
|
+
base: {
|
|
107315
|
+
canvas: "#1f1a14",
|
|
107316
|
+
surface: "#2a2118",
|
|
107317
|
+
text: "#eadfce",
|
|
107318
|
+
muted: "#9c8870"
|
|
107319
|
+
},
|
|
107320
|
+
interactive: {
|
|
107321
|
+
accent: "#f0a04b",
|
|
107322
|
+
focus: "#f6c177",
|
|
107323
|
+
selectedSurface: "#3a2a1d"
|
|
107324
|
+
},
|
|
107325
|
+
feedback: {
|
|
107326
|
+
warning: "#f6c177",
|
|
107327
|
+
error: "#d66a4a",
|
|
107328
|
+
success: "#8faa5f"
|
|
107329
|
+
}
|
|
106961
107330
|
};
|
|
106962
107331
|
}
|
|
107332
|
+
|
|
107333
|
+
// ../tui/src/board-view.ts
|
|
106963
107334
|
function BoardView({
|
|
106964
107335
|
model,
|
|
106965
107336
|
selection,
|
|
106966
107337
|
theme = buildTuiTheme(),
|
|
106967
|
-
viewportHeight
|
|
107338
|
+
viewportHeight,
|
|
107339
|
+
viewportWidth,
|
|
107340
|
+
columns
|
|
106968
107341
|
}) {
|
|
106969
|
-
const view = buildBoardViewModel(model, selection, {
|
|
106970
|
-
|
|
107342
|
+
const view = buildBoardViewModel(model, selection, {
|
|
107343
|
+
viewportHeight,
|
|
107344
|
+
...typeof columns === "number" ? { visibleColumnCount: columns } : { viewportWidth }
|
|
107345
|
+
});
|
|
107346
|
+
return import_react.default.createElement("box", {
|
|
106971
107347
|
id: "mikan-board",
|
|
106972
107348
|
style: { flexDirection: "column", flexGrow: 1, minHeight: 0 }
|
|
106973
|
-
},
|
|
107349
|
+
}, model.warnings.length > 0 ? import_react.default.createElement("text", {
|
|
107350
|
+
content: formatWarningSummary(model.warnings),
|
|
107351
|
+
style: { color: theme.feedback.warning }
|
|
107352
|
+
}) : undefined, import_react.default.createElement("text", { content: view.columnViewportText }), ...view.groups.map((group, groupIndex) => import_react.default.createElement("box", {
|
|
106974
107353
|
key: `group-${groupIndex}`,
|
|
106975
107354
|
id: `board-row-${groupIndex}`,
|
|
106976
107355
|
style: { flexDirection: "row", flexGrow: 1, minHeight: 0 }
|
|
106977
|
-
}, ...group.columns.map((column) =>
|
|
107356
|
+
}, ...group.columns.map((column, columnIndex) => import_react.default.createElement(ColumnPane, {
|
|
106978
107357
|
key: column.id,
|
|
106979
107358
|
column,
|
|
106980
107359
|
theme,
|
|
106981
|
-
width:
|
|
106982
|
-
}))))
|
|
106983
|
-
content: [
|
|
106984
|
-
`Warnings: ${model.warnings.length}`,
|
|
106985
|
-
...model.warnings
|
|
106986
|
-
].join(`
|
|
106987
|
-
`)
|
|
106988
|
-
}) : undefined);
|
|
107360
|
+
width: columnWidthPercent(columnIndex, group.columns.length)
|
|
107361
|
+
})))));
|
|
106989
107362
|
}
|
|
106990
107363
|
function ColumnPane(props) {
|
|
106991
107364
|
const theme = props.theme ?? buildTuiTheme();
|
|
106992
|
-
const
|
|
106993
|
-
|
|
106994
|
-
|
|
106995
|
-
|
|
106996
|
-
|
|
106997
|
-
|
|
106998
|
-
|
|
106999
|
-
|
|
107000
|
-
|
|
107001
|
-
|
|
107365
|
+
const cardChildren = props.column.empty ? [
|
|
107366
|
+
import_react.default.createElement("text", {
|
|
107367
|
+
id: `column-${props.column.id}-empty`,
|
|
107368
|
+
content: props.column.emptyText
|
|
107369
|
+
})
|
|
107370
|
+
] : props.column.visibleCards.map((card) => import_react.default.createElement(IssueCard, {
|
|
107371
|
+
key: card.id,
|
|
107372
|
+
card,
|
|
107373
|
+
selected: card.selected,
|
|
107374
|
+
theme
|
|
107375
|
+
}));
|
|
107376
|
+
const children = cardChildren;
|
|
107377
|
+
return import_react.default.createElement("box", {
|
|
107002
107378
|
id: `column-${props.column.id}`,
|
|
107003
107379
|
title: `${props.column.active ? "\u25B6 " : ""}${props.column.title} (${props.column.count})`,
|
|
107380
|
+
bottomTitle: props.column.cardRangeText || undefined,
|
|
107381
|
+
bottomTitleAlignment: "center",
|
|
107004
107382
|
border: true,
|
|
107005
107383
|
focused: props.column.active,
|
|
107006
107384
|
style: {
|
|
@@ -107012,31 +107390,141 @@ function ColumnPane(props) {
|
|
|
107012
107390
|
}
|
|
107013
107391
|
}, ...children);
|
|
107014
107392
|
}
|
|
107393
|
+
function issueCardContent(card, selected, theme) {
|
|
107394
|
+
const chunks = [];
|
|
107395
|
+
if (selected)
|
|
107396
|
+
chunks.push(fg(theme.interactive.focus)("\u25B6 "));
|
|
107397
|
+
chunks.push(fg(theme.interactive.accent)(card.id));
|
|
107398
|
+
if (cardDependencyStatus(card) === "blocked") {
|
|
107399
|
+
chunks.push(fg(theme.base.text)(" "));
|
|
107400
|
+
chunks.push(fg(theme.feedback.warning)("deps!"));
|
|
107401
|
+
}
|
|
107402
|
+
chunks.push(fg(theme.base.muted)(" \u2502 "));
|
|
107403
|
+
chunks.push(fg(theme.base.text)(card.title));
|
|
107404
|
+
if (card.labels.length > 0) {
|
|
107405
|
+
chunks.push(fg(theme.base.text)(" "));
|
|
107406
|
+
chunks.push(fg(theme.base.muted)(formatLabels(card.labels)));
|
|
107407
|
+
}
|
|
107408
|
+
return new StyledText(chunks);
|
|
107409
|
+
}
|
|
107015
107410
|
function IssueCard(props) {
|
|
107016
107411
|
const theme = props.theme ?? buildTuiTheme();
|
|
107017
|
-
return
|
|
107412
|
+
return import_react.default.createElement("box", {
|
|
107018
107413
|
id: `card-${props.card.id}`,
|
|
107019
|
-
border:
|
|
107414
|
+
border: false,
|
|
107020
107415
|
focused: props.selected,
|
|
107021
107416
|
style: {
|
|
107022
107417
|
backgroundColor: props.selected ? theme.interactive.selectedSurface : theme.base.surface,
|
|
107023
|
-
borderColor: props.selected ? theme.interactive.focus : theme.base.muted,
|
|
107024
|
-
color: props.selected ? theme.interactive.focus : theme.base.text,
|
|
107025
107418
|
flexDirection: "column",
|
|
107026
|
-
height:
|
|
107419
|
+
height: 1
|
|
107027
107420
|
}
|
|
107028
|
-
},
|
|
107029
|
-
content:
|
|
107421
|
+
}, import_react.default.createElement("text", {
|
|
107422
|
+
content: issueCardContent(props.card, props.selected, theme)
|
|
107030
107423
|
}));
|
|
107031
107424
|
}
|
|
107425
|
+
function Footer(props) {
|
|
107426
|
+
const theme = props.theme ?? buildTuiTheme();
|
|
107427
|
+
return import_react.default.createElement("text", {
|
|
107428
|
+
id: "mikan-footer",
|
|
107429
|
+
style: { color: theme.base.muted, marginTop: "auto" },
|
|
107430
|
+
content: [footerText(props.mode ?? "board"), props.message].filter(Boolean).join(" ")
|
|
107431
|
+
});
|
|
107432
|
+
}
|
|
107433
|
+
|
|
107434
|
+
// ../tui/src/detail-view.ts
|
|
107435
|
+
await init_core3();
|
|
107436
|
+
var import_react2 = __toESM(require_react(), 1);
|
|
107437
|
+
|
|
107438
|
+
// ../tui/src/detail-view-model.ts
|
|
107439
|
+
function buildDetailPageViewModel(model, selection, options = {}) {
|
|
107440
|
+
const details = getSelectedDetails(model, selection);
|
|
107441
|
+
if (!details)
|
|
107442
|
+
return;
|
|
107443
|
+
const markdown = stripFrontmatter(details.markdown).trimEnd();
|
|
107444
|
+
const markdownLines = markdown.split(`
|
|
107445
|
+
`);
|
|
107446
|
+
const visibleLineCount = options.visibleLineCount ?? (options.viewportHeight ? visibleDetailLineCount(options.viewportHeight) : 40);
|
|
107447
|
+
const offset = clamp(selection.detailScrollOffset ?? 0, 0, Math.max(0, markdownLines.length - visibleLineCount));
|
|
107448
|
+
const visibleMarkdownLines = markdownLines.slice(offset, offset + visibleLineCount);
|
|
107449
|
+
const lineEnd = offset + visibleMarkdownLines.length;
|
|
107450
|
+
return {
|
|
107451
|
+
id: details.card.id,
|
|
107452
|
+
title: details.card.title,
|
|
107453
|
+
status: details.card.status,
|
|
107454
|
+
labelsText: details.card.labels.join(", "),
|
|
107455
|
+
dependsOnText: cardDependsOn(details.card).join(", "),
|
|
107456
|
+
unmetDependenciesText: cardUnmetDependencies(details.card).join(", "),
|
|
107457
|
+
dependencyStatus: cardDependencyStatus(details.card),
|
|
107458
|
+
warningCount: warningCountForCard(model.warningDetails, details.card),
|
|
107459
|
+
markdown,
|
|
107460
|
+
visibleMarkdownLines,
|
|
107461
|
+
hiddenLinesBefore: offset,
|
|
107462
|
+
hiddenLinesAfter: Math.max(0, markdownLines.length - lineEnd),
|
|
107463
|
+
lineRangeText: formatLineRange({
|
|
107464
|
+
start: offset + 1,
|
|
107465
|
+
end: lineEnd,
|
|
107466
|
+
total: markdownLines.length,
|
|
107467
|
+
hiddenBefore: offset,
|
|
107468
|
+
hiddenAfter: Math.max(0, markdownLines.length - lineEnd)
|
|
107469
|
+
})
|
|
107470
|
+
};
|
|
107471
|
+
}
|
|
107472
|
+
function warningCountForCard(warnings, card) {
|
|
107473
|
+
return (warnings ?? []).filter((warning) => warning.issueId === card.id || warning.path === card.path).length;
|
|
107474
|
+
}
|
|
107475
|
+
|
|
107476
|
+
// ../tui/src/detail-view.ts
|
|
107477
|
+
function detailLabelsText(page) {
|
|
107478
|
+
return page.labelsText ? formatLabels(page.labelsText.split(", ").filter(Boolean)) : "none";
|
|
107479
|
+
}
|
|
107480
|
+
function detailDependencyText(page) {
|
|
107481
|
+
if (page.unmetDependenciesText)
|
|
107482
|
+
return `deps unmet ${page.unmetDependenciesText}`;
|
|
107483
|
+
return page.dependsOnText ? `deps ${page.dependencyStatus}` : "";
|
|
107484
|
+
}
|
|
107485
|
+
function detailStatusColor(status, theme) {
|
|
107486
|
+
if (status === "completed")
|
|
107487
|
+
return theme.feedback.success;
|
|
107488
|
+
if (status === "blocked")
|
|
107489
|
+
return theme.feedback.warning;
|
|
107490
|
+
if (status === "active")
|
|
107491
|
+
return theme.interactive.accent;
|
|
107492
|
+
return theme.base.muted;
|
|
107493
|
+
}
|
|
107494
|
+
function detailTitleContent(page, theme) {
|
|
107495
|
+
const chunks = [
|
|
107496
|
+
fg(theme.interactive.accent)(page.id),
|
|
107497
|
+
fg(theme.base.muted)(" \u2502 "),
|
|
107498
|
+
fg(theme.base.text)(page.title)
|
|
107499
|
+
];
|
|
107500
|
+
if (page.lineRangeText) {
|
|
107501
|
+
chunks.push(fg(theme.base.muted)(" \u2502 "));
|
|
107502
|
+
chunks.push(fg(theme.base.muted)(page.lineRangeText));
|
|
107503
|
+
}
|
|
107504
|
+
return new StyledText(chunks);
|
|
107505
|
+
}
|
|
107506
|
+
function detailMetaContent(page, theme) {
|
|
107507
|
+
const chunks = [
|
|
107508
|
+
fg(detailStatusColor(page.status, theme))(page.status),
|
|
107509
|
+
fg(theme.base.muted)(" \xB7 labels "),
|
|
107510
|
+
fg(theme.base.muted)(detailLabelsText(page))
|
|
107511
|
+
];
|
|
107512
|
+
const dependency = detailDependencyText(page);
|
|
107513
|
+
if (dependency)
|
|
107514
|
+
chunks.push(fg(theme.feedback.warning)(` \xB7 ${dependency}`));
|
|
107515
|
+
if (page.warningCount > 0) {
|
|
107516
|
+
chunks.push(fg(theme.feedback.warning)(` \xB7 warnings ${page.warningCount}`));
|
|
107517
|
+
}
|
|
107518
|
+
return new StyledText(chunks);
|
|
107519
|
+
}
|
|
107032
107520
|
function DetailPage(props) {
|
|
107033
107521
|
const page = buildDetailPageViewModel(props.model, props.selection, {
|
|
107034
107522
|
viewportHeight: props.viewportHeight
|
|
107035
107523
|
});
|
|
107036
107524
|
const theme = props.theme ?? buildTuiTheme();
|
|
107037
107525
|
if (!page)
|
|
107038
|
-
return
|
|
107039
|
-
return
|
|
107526
|
+
return import_react2.default.createElement("text", { content: "No Issue selected" });
|
|
107527
|
+
return import_react2.default.createElement("box", {
|
|
107040
107528
|
id: "detail-page",
|
|
107041
107529
|
title: "Detail",
|
|
107042
107530
|
border: true,
|
|
@@ -107047,20 +107535,18 @@ function DetailPage(props) {
|
|
|
107047
107535
|
flexGrow: 1,
|
|
107048
107536
|
overflow: "hidden"
|
|
107049
107537
|
}
|
|
107050
|
-
},
|
|
107538
|
+
}, import_react2.default.createElement("box", {
|
|
107051
107539
|
id: "detail-header",
|
|
107052
107540
|
style: {
|
|
107053
107541
|
backgroundColor: theme.base.surface,
|
|
107054
107542
|
flexDirection: "column",
|
|
107055
107543
|
flexShrink: 0
|
|
107056
107544
|
}
|
|
107057
|
-
},
|
|
107058
|
-
content:
|
|
107059
|
-
}),
|
|
107060
|
-
content:
|
|
107061
|
-
}),
|
|
107062
|
-
content: "\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"
|
|
107063
|
-
})), import_react17.default.createElement("box", {
|
|
107545
|
+
}, import_react2.default.createElement("text", {
|
|
107546
|
+
content: detailTitleContent(page, theme)
|
|
107547
|
+
}), import_react2.default.createElement("text", {
|
|
107548
|
+
content: detailMetaContent(page, theme)
|
|
107549
|
+
})), import_react2.default.createElement("box", {
|
|
107064
107550
|
id: "detail-markdown-body",
|
|
107065
107551
|
style: {
|
|
107066
107552
|
flexDirection: "column",
|
|
@@ -107068,7 +107554,7 @@ function DetailPage(props) {
|
|
|
107068
107554
|
minHeight: 0,
|
|
107069
107555
|
overflow: "hidden"
|
|
107070
107556
|
}
|
|
107071
|
-
},
|
|
107557
|
+
}, import_react2.default.createElement("markdown", {
|
|
107072
107558
|
id: "detail-markdown",
|
|
107073
107559
|
content: page.visibleMarkdownLines.join(`
|
|
107074
107560
|
`),
|
|
@@ -107079,47 +107565,256 @@ function DetailPage(props) {
|
|
|
107079
107565
|
}
|
|
107080
107566
|
})));
|
|
107081
107567
|
}
|
|
107568
|
+
|
|
107569
|
+
// ../tui/src/modals.ts
|
|
107570
|
+
var import_react3 = __toESM(require_react(), 1);
|
|
107571
|
+
|
|
107572
|
+
// ../tui/src/navigation.ts
|
|
107573
|
+
function moveSelection(model, selection, direction, options = {}) {
|
|
107574
|
+
if (direction === "enter") {
|
|
107575
|
+
const card = model.columns[selection.columnIndex]?.cards[selection.cardIndex];
|
|
107576
|
+
if (!card) {
|
|
107577
|
+
return { ...selection, detailOpen: false, message: "No Issue selected" };
|
|
107578
|
+
}
|
|
107579
|
+
return {
|
|
107580
|
+
...selection,
|
|
107581
|
+
detailOpen: true,
|
|
107582
|
+
detailScrollOffset: 0,
|
|
107583
|
+
message: undefined
|
|
107584
|
+
};
|
|
107585
|
+
}
|
|
107586
|
+
if (selection.detailOpen && !selection.moveOpen && !selection.noteOpen) {
|
|
107587
|
+
if (direction === "up" || direction === "down") {
|
|
107588
|
+
return {
|
|
107589
|
+
...selection,
|
|
107590
|
+
detailScrollOffset: clamp((selection.detailScrollOffset ?? 0) + (direction === "down" ? 1 : -1), 0, detailScrollMax(model, selection, options))
|
|
107591
|
+
};
|
|
107592
|
+
}
|
|
107593
|
+
if (direction === "left" || direction === "right") {
|
|
107594
|
+
return selection;
|
|
107595
|
+
}
|
|
107596
|
+
}
|
|
107597
|
+
if (direction === "escape") {
|
|
107598
|
+
if (selection.helpOpen) {
|
|
107599
|
+
return { ...selection, helpOpen: false };
|
|
107600
|
+
}
|
|
107601
|
+
if (selection.archiveOpen) {
|
|
107602
|
+
return { ...selection, archiveOpen: false };
|
|
107603
|
+
}
|
|
107604
|
+
if (selection.warningsOpen) {
|
|
107605
|
+
return { ...selection, warningsOpen: false };
|
|
107606
|
+
}
|
|
107607
|
+
return {
|
|
107608
|
+
...selection,
|
|
107609
|
+
detailOpen: false,
|
|
107610
|
+
moveOpen: false,
|
|
107611
|
+
noteOpen: false
|
|
107612
|
+
};
|
|
107613
|
+
}
|
|
107614
|
+
if (direction === "move") {
|
|
107615
|
+
return {
|
|
107616
|
+
...selection,
|
|
107617
|
+
archiveOpen: false,
|
|
107618
|
+
detailOpen: false,
|
|
107619
|
+
noteOpen: false,
|
|
107620
|
+
moveOpen: true,
|
|
107621
|
+
moveTargetIndex: 0
|
|
107622
|
+
};
|
|
107623
|
+
}
|
|
107624
|
+
if (direction === "append-note") {
|
|
107625
|
+
return {
|
|
107626
|
+
...selection,
|
|
107627
|
+
archiveOpen: false,
|
|
107628
|
+
detailOpen: false,
|
|
107629
|
+
moveOpen: false,
|
|
107630
|
+
noteOpen: true
|
|
107631
|
+
};
|
|
107632
|
+
}
|
|
107633
|
+
if (direction === "archive") {
|
|
107634
|
+
return {
|
|
107635
|
+
...selection,
|
|
107636
|
+
archiveOpen: true,
|
|
107637
|
+
moveOpen: false,
|
|
107638
|
+
noteOpen: false
|
|
107639
|
+
};
|
|
107640
|
+
}
|
|
107641
|
+
if (direction === "warnings") {
|
|
107642
|
+
return model.warnings.length > 0 ? { ...selection, warningsOpen: !selection.warningsOpen } : { ...selection, message: "No warnings" };
|
|
107643
|
+
}
|
|
107644
|
+
if (direction === "help") {
|
|
107645
|
+
return { ...selection, helpOpen: !selection.helpOpen };
|
|
107646
|
+
}
|
|
107647
|
+
const columnIndex = clamp(selection.columnIndex + (direction === "right" ? 1 : direction === "left" ? -1 : 0), 0, Math.max(0, model.columns.length - 1));
|
|
107648
|
+
const maxCardIndex = Math.max(0, (model.columns[columnIndex]?.cards.length ?? 1) - 1);
|
|
107649
|
+
const cardIndex = clamp(direction === "up" ? selection.cardIndex - 1 : direction === "down" ? selection.cardIndex + 1 : Math.min(selection.cardIndex, maxCardIndex), 0, maxCardIndex);
|
|
107650
|
+
return { ...selection, columnIndex, cardIndex };
|
|
107651
|
+
}
|
|
107652
|
+
function getMoveTargets(model, selection) {
|
|
107653
|
+
const currentStatus = model.columns[selection.columnIndex]?.id;
|
|
107654
|
+
return model.columns.filter((column) => column.id !== currentStatus).map((column) => ({ id: column.id, title: column.title }));
|
|
107655
|
+
}
|
|
107656
|
+
function getAdjacentMoveTarget(model, selection, direction) {
|
|
107657
|
+
const offset = direction === "left" ? -1 : 1;
|
|
107658
|
+
const column = model.columns[selection.columnIndex + offset];
|
|
107659
|
+
return column ? { id: column.id, title: column.title } : undefined;
|
|
107660
|
+
}
|
|
107661
|
+
function applyNoteInput(selection, keyName2, shift = false) {
|
|
107662
|
+
if (!selection.noteOpen || !keyName2)
|
|
107663
|
+
return selection;
|
|
107664
|
+
if (keyName2 === "backspace") {
|
|
107665
|
+
return {
|
|
107666
|
+
...selection,
|
|
107667
|
+
noteDraft: (selection.noteDraft ?? "").slice(0, -1)
|
|
107668
|
+
};
|
|
107669
|
+
}
|
|
107670
|
+
const character = keyName2 === "space" ? " " : keyName2;
|
|
107671
|
+
if (character.length !== 1)
|
|
107672
|
+
return selection;
|
|
107673
|
+
const value = shift && /[a-z]/.test(character) ? character.toUpperCase() : character;
|
|
107674
|
+
return { ...selection, noteDraft: `${selection.noteDraft ?? ""}${value}` };
|
|
107675
|
+
}
|
|
107676
|
+
function footerMode(selection) {
|
|
107677
|
+
if (selection.moveOpen || selection.noteOpen || selection.archiveOpen) {
|
|
107678
|
+
return "modal";
|
|
107679
|
+
}
|
|
107680
|
+
return selection.detailOpen ? "detail" : "board";
|
|
107681
|
+
}
|
|
107682
|
+
function keyToTuiAction(keyName2, shift = false) {
|
|
107683
|
+
if (shift && keyName2 === "h")
|
|
107684
|
+
return "move-left";
|
|
107685
|
+
if (shift && keyName2 === "l")
|
|
107686
|
+
return "move-right";
|
|
107687
|
+
switch (keyName2) {
|
|
107688
|
+
case "left":
|
|
107689
|
+
case "right":
|
|
107690
|
+
case "up":
|
|
107691
|
+
case "down":
|
|
107692
|
+
case "enter":
|
|
107693
|
+
case "escape":
|
|
107694
|
+
return keyName2;
|
|
107695
|
+
case "h":
|
|
107696
|
+
return "left";
|
|
107697
|
+
case "l":
|
|
107698
|
+
return "right";
|
|
107699
|
+
case "j":
|
|
107700
|
+
return "down";
|
|
107701
|
+
case "k":
|
|
107702
|
+
return "up";
|
|
107703
|
+
case "return":
|
|
107704
|
+
return "enter";
|
|
107705
|
+
case "H":
|
|
107706
|
+
return "move-left";
|
|
107707
|
+
case "L":
|
|
107708
|
+
return "move-right";
|
|
107709
|
+
case "r":
|
|
107710
|
+
return "reload";
|
|
107711
|
+
case "m":
|
|
107712
|
+
return "move";
|
|
107713
|
+
case "n":
|
|
107714
|
+
return "append-note";
|
|
107715
|
+
case "a":
|
|
107716
|
+
return "archive";
|
|
107717
|
+
case "w":
|
|
107718
|
+
return "warnings";
|
|
107719
|
+
case "?":
|
|
107720
|
+
return "help";
|
|
107721
|
+
case "q":
|
|
107722
|
+
return "quit";
|
|
107723
|
+
default:
|
|
107724
|
+
return;
|
|
107725
|
+
}
|
|
107726
|
+
}
|
|
107727
|
+
function detailScrollMax(model, selection, options = {}) {
|
|
107728
|
+
const details = getSelectedDetails(model, selection);
|
|
107729
|
+
if (!details)
|
|
107730
|
+
return 0;
|
|
107731
|
+
const visibleLineCount = options.viewportHeight ? visibleDetailLineCount(options.viewportHeight) : 40;
|
|
107732
|
+
return Math.max(0, stripFrontmatter(details.markdown).trimEnd().split(`
|
|
107733
|
+
`).length - visibleLineCount);
|
|
107734
|
+
}
|
|
107735
|
+
|
|
107736
|
+
// ../tui/src/prompt-view-model.ts
|
|
107737
|
+
function buildMovePromptViewModel(model, selection) {
|
|
107738
|
+
const card = model.columns[selection.columnIndex]?.cards[selection.cardIndex];
|
|
107739
|
+
if (!card)
|
|
107740
|
+
return;
|
|
107741
|
+
const targetIndex = selection.moveTargetIndex ?? 0;
|
|
107742
|
+
return {
|
|
107743
|
+
title: `Move ${card.id}`,
|
|
107744
|
+
focused: Boolean(selection.moveOpen),
|
|
107745
|
+
targets: getMoveTargets(model, selection).map((target, index2) => ({
|
|
107746
|
+
...target,
|
|
107747
|
+
selected: index2 === targetIndex
|
|
107748
|
+
})),
|
|
107749
|
+
hint: "enter move esc cancel"
|
|
107750
|
+
};
|
|
107751
|
+
}
|
|
107752
|
+
function buildNotePromptViewModel(model, selection) {
|
|
107753
|
+
const card = model.columns[selection.columnIndex]?.cards[selection.cardIndex];
|
|
107754
|
+
if (!card)
|
|
107755
|
+
return;
|
|
107756
|
+
return {
|
|
107757
|
+
title: `Append note to ${card.id}`,
|
|
107758
|
+
focused: Boolean(selection.noteOpen),
|
|
107759
|
+
draft: selection.noteDraft ?? "",
|
|
107760
|
+
hint: "enter append esc cancel"
|
|
107761
|
+
};
|
|
107762
|
+
}
|
|
107763
|
+
function buildArchivePromptViewModel(model, selection) {
|
|
107764
|
+
const card = model.columns[selection.columnIndex]?.cards[selection.cardIndex];
|
|
107765
|
+
if (!card)
|
|
107766
|
+
return;
|
|
107767
|
+
return {
|
|
107768
|
+
title: `Archive ${card.id}?`,
|
|
107769
|
+
focused: Boolean(selection.archiveOpen),
|
|
107770
|
+
body: `${card.title}
|
|
107771
|
+
Move to archived. It will disappear from the default board.`,
|
|
107772
|
+
hint: "enter archive esc cancel"
|
|
107773
|
+
};
|
|
107774
|
+
}
|
|
107775
|
+
|
|
107776
|
+
// ../tui/src/modals.ts
|
|
107082
107777
|
function MovePrompt(props) {
|
|
107083
107778
|
const theme = props.theme ?? buildTuiTheme();
|
|
107084
|
-
return
|
|
107779
|
+
return import_react3.default.createElement("box", {
|
|
107085
107780
|
id: "move-modal-backdrop",
|
|
107086
107781
|
style: modalBackdropStyle(theme)
|
|
107087
|
-
},
|
|
107782
|
+
}, import_react3.default.createElement("box", {
|
|
107088
107783
|
id: "move-prompt",
|
|
107089
107784
|
title: "Move Issue",
|
|
107090
107785
|
border: true,
|
|
107091
107786
|
style: modalStyle(theme)
|
|
107092
|
-
},
|
|
107787
|
+
}, import_react3.default.createElement("text", {
|
|
107093
107788
|
content: renderMoveInteraction(props.model, props.selection).join(`
|
|
107094
107789
|
`)
|
|
107095
107790
|
})));
|
|
107096
107791
|
}
|
|
107097
107792
|
function NotePrompt(props) {
|
|
107098
107793
|
const theme = props.theme ?? buildTuiTheme();
|
|
107099
|
-
return
|
|
107794
|
+
return import_react3.default.createElement("box", {
|
|
107100
107795
|
id: "note-modal-backdrop",
|
|
107101
107796
|
style: modalBackdropStyle(theme)
|
|
107102
|
-
},
|
|
107797
|
+
}, import_react3.default.createElement("box", {
|
|
107103
107798
|
id: "note-prompt",
|
|
107104
107799
|
title: "Append Note",
|
|
107105
107800
|
border: true,
|
|
107106
107801
|
style: modalStyle(theme)
|
|
107107
|
-
},
|
|
107802
|
+
}, import_react3.default.createElement("text", {
|
|
107108
107803
|
content: renderNoteInteraction(props.model, props.selection).join(`
|
|
107109
107804
|
`)
|
|
107110
107805
|
})));
|
|
107111
107806
|
}
|
|
107112
107807
|
function ArchivePrompt(props) {
|
|
107113
107808
|
const theme = props.theme ?? buildTuiTheme();
|
|
107114
|
-
return
|
|
107809
|
+
return import_react3.default.createElement("box", {
|
|
107115
107810
|
id: "archive-modal-backdrop",
|
|
107116
107811
|
style: modalBackdropStyle(theme)
|
|
107117
|
-
},
|
|
107812
|
+
}, import_react3.default.createElement("box", {
|
|
107118
107813
|
id: "archive-prompt",
|
|
107119
107814
|
title: "Archive Issue",
|
|
107120
107815
|
border: true,
|
|
107121
107816
|
style: modalStyle(theme)
|
|
107122
|
-
},
|
|
107817
|
+
}, import_react3.default.createElement("text", {
|
|
107123
107818
|
content: renderArchiveInteraction(props.model, props.selection).join(`
|
|
107124
107819
|
`)
|
|
107125
107820
|
})));
|
|
@@ -107146,43 +107841,103 @@ function modalStyle(theme) {
|
|
|
107146
107841
|
width: "70%"
|
|
107147
107842
|
};
|
|
107148
107843
|
}
|
|
107149
|
-
function
|
|
107844
|
+
function HelpPanel(props) {
|
|
107150
107845
|
const theme = props.theme ?? buildTuiTheme();
|
|
107151
|
-
return
|
|
107152
|
-
id: "
|
|
107153
|
-
style:
|
|
107154
|
-
|
|
107155
|
-
|
|
107846
|
+
return import_react3.default.createElement("box", {
|
|
107847
|
+
id: "help-panel-backdrop",
|
|
107848
|
+
style: modalBackdropStyle(theme)
|
|
107849
|
+
}, import_react3.default.createElement("box", {
|
|
107850
|
+
id: "help-panel",
|
|
107851
|
+
title: "Key help",
|
|
107852
|
+
border: true,
|
|
107853
|
+
style: modalStyle(theme)
|
|
107854
|
+
}, import_react3.default.createElement("text", { content: renderKeyHelp().join(`
|
|
107855
|
+
`) })));
|
|
107156
107856
|
}
|
|
107157
|
-
function
|
|
107158
|
-
|
|
107159
|
-
|
|
107160
|
-
|
|
107161
|
-
|
|
107857
|
+
function WarningPanel(props) {
|
|
107858
|
+
const theme = props.theme ?? buildTuiTheme();
|
|
107859
|
+
return import_react3.default.createElement("box", {
|
|
107860
|
+
id: "warning-panel",
|
|
107861
|
+
title: "Warning details",
|
|
107862
|
+
border: true,
|
|
107863
|
+
style: {
|
|
107864
|
+
backgroundColor: theme.base.surface,
|
|
107865
|
+
borderColor: theme.feedback.warning,
|
|
107866
|
+
flexDirection: "column"
|
|
107867
|
+
}
|
|
107868
|
+
}, import_react3.default.createElement("text", {
|
|
107869
|
+
content: props.model.warnings.length > 0 ? props.model.warnings.map((warning) => `! ${warning}`).join(`
|
|
107870
|
+
`) : "No warnings"
|
|
107871
|
+
}));
|
|
107162
107872
|
}
|
|
107163
|
-
function
|
|
107164
|
-
const
|
|
107165
|
-
|
|
107873
|
+
function renderMoveInteraction(model, selection) {
|
|
107874
|
+
const view = buildMovePromptViewModel(model, selection);
|
|
107875
|
+
if (!view)
|
|
107876
|
+
return ["Move", "No Issue selected"];
|
|
107877
|
+
return [
|
|
107878
|
+
`${view.title} to Status`,
|
|
107879
|
+
...view.targets.map((target) => `${target.selected ? ">" : " "} ${target.id} (${target.title})`),
|
|
107880
|
+
view.hint
|
|
107881
|
+
];
|
|
107166
107882
|
}
|
|
107167
|
-
function
|
|
107168
|
-
const
|
|
107169
|
-
|
|
107170
|
-
|
|
107883
|
+
function renderNoteInteraction(model, selection) {
|
|
107884
|
+
const view = buildNotePromptViewModel(model, selection);
|
|
107885
|
+
if (!view)
|
|
107886
|
+
return ["Append note", "No Issue selected"];
|
|
107887
|
+
return [
|
|
107888
|
+
view.title,
|
|
107889
|
+
`Note: ${view.draft}`,
|
|
107890
|
+
...view.feedback ? [view.feedback] : [],
|
|
107891
|
+
view.hint
|
|
107892
|
+
];
|
|
107171
107893
|
}
|
|
107172
|
-
function
|
|
107173
|
-
|
|
107174
|
-
|
|
107175
|
-
|
|
107176
|
-
|
|
107894
|
+
function renderArchiveInteraction(model, selection) {
|
|
107895
|
+
const view = buildArchivePromptViewModel(model, selection);
|
|
107896
|
+
if (!view)
|
|
107897
|
+
return ["Archive", "No Issue selected"];
|
|
107898
|
+
return [view.title, view.body, view.hint];
|
|
107899
|
+
}
|
|
107900
|
+
function renderKeyHelp() {
|
|
107901
|
+
return [
|
|
107902
|
+
"Key help",
|
|
107903
|
+
"\u2191/\u2193 or j/k card/scroll",
|
|
107904
|
+
"\u2190/\u2192 or h/l column",
|
|
107905
|
+
"enter detail/confirm",
|
|
107906
|
+
"esc back/cancel",
|
|
107907
|
+
"H/L move Issue",
|
|
107908
|
+
"m move menu",
|
|
107909
|
+
"n append Note",
|
|
107910
|
+
"a archive Issue",
|
|
107911
|
+
"w warning details",
|
|
107912
|
+
"r reload",
|
|
107913
|
+
"q quit"
|
|
107914
|
+
];
|
|
107915
|
+
}
|
|
107916
|
+
|
|
107917
|
+
// ../tui/src/mutations.ts
|
|
107918
|
+
function refreshTuiModel(options) {
|
|
107919
|
+
const selectedCard = options.model.columns[options.selection.columnIndex]?.cards[options.selection.cardIndex];
|
|
107920
|
+
const model = loadTuiModel(options.cwd);
|
|
107921
|
+
const foundSelection = selectedCard ? findSelectionByCardId(model, selectedCard.id) : undefined;
|
|
107922
|
+
const selection = foundSelection ?? clampSelection(model, options.selection);
|
|
107923
|
+
const stillSelected = Boolean(foundSelection);
|
|
107924
|
+
return {
|
|
107925
|
+
model,
|
|
107926
|
+
selection: {
|
|
107177
107927
|
...selection,
|
|
107178
|
-
|
|
107179
|
-
|
|
107180
|
-
|
|
107181
|
-
|
|
107182
|
-
|
|
107183
|
-
|
|
107184
|
-
|
|
107185
|
-
|
|
107928
|
+
detailOpen: stillSelected ? options.selection.detailOpen : false,
|
|
107929
|
+
detailScrollOffset: stillSelected ? options.selection.detailScrollOffset : undefined,
|
|
107930
|
+
detailScrollMax: stillSelected ? options.selection.detailScrollMax : undefined,
|
|
107931
|
+
moveOpen: stillSelected ? options.selection.moveOpen : false,
|
|
107932
|
+
moveTargetIndex: stillSelected ? options.selection.moveTargetIndex : undefined,
|
|
107933
|
+
noteOpen: stillSelected ? options.selection.noteOpen : false,
|
|
107934
|
+
noteDraft: stillSelected ? options.selection.noteDraft : undefined,
|
|
107935
|
+
message: options.selection.message,
|
|
107936
|
+
archiveOpen: stillSelected ? options.selection.archiveOpen : false,
|
|
107937
|
+
warningsOpen: options.selection.warningsOpen,
|
|
107938
|
+
helpOpen: options.selection.helpOpen
|
|
107939
|
+
}
|
|
107940
|
+
};
|
|
107186
107941
|
}
|
|
107187
107942
|
function moveSelectedIssueByDirection(options) {
|
|
107188
107943
|
const target = getAdjacentMoveTarget(options.model, options.selection, options.direction);
|
|
@@ -107325,70 +108080,57 @@ function appendSelectedIssueNote(options) {
|
|
|
107325
108080
|
message: `${card.id} note appended`
|
|
107326
108081
|
};
|
|
107327
108082
|
}
|
|
107328
|
-
|
|
107329
|
-
|
|
107330
|
-
|
|
107331
|
-
|
|
107332
|
-
|
|
107333
|
-
return {
|
|
107334
|
-
title: `Move ${card.id}`,
|
|
107335
|
-
focused: Boolean(selection.moveOpen),
|
|
107336
|
-
targets: getMoveTargets(model, selection).map((target, index2) => ({
|
|
107337
|
-
...target,
|
|
107338
|
-
selected: index2 === targetIndex
|
|
107339
|
-
})),
|
|
107340
|
-
hint: "enter move esc cancel"
|
|
107341
|
-
};
|
|
107342
|
-
}
|
|
107343
|
-
function buildNotePromptViewModel(model, selection) {
|
|
107344
|
-
const card = model.columns[selection.columnIndex]?.cards[selection.cardIndex];
|
|
107345
|
-
if (!card)
|
|
107346
|
-
return;
|
|
107347
|
-
return {
|
|
107348
|
-
title: `Append note to ${card.id}`,
|
|
107349
|
-
focused: Boolean(selection.noteOpen),
|
|
107350
|
-
draft: selection.noteDraft ?? "",
|
|
107351
|
-
hint: "enter append esc cancel"
|
|
107352
|
-
};
|
|
107353
|
-
}
|
|
107354
|
-
function buildArchivePromptViewModel(model, selection) {
|
|
107355
|
-
const card = model.columns[selection.columnIndex]?.cards[selection.cardIndex];
|
|
107356
|
-
if (!card)
|
|
107357
|
-
return;
|
|
107358
|
-
return {
|
|
107359
|
-
title: `Archive ${card.id}?`,
|
|
107360
|
-
focused: Boolean(selection.archiveOpen),
|
|
107361
|
-
body: `${card.title}
|
|
107362
|
-
Move to archived. It will disappear from the default board.`,
|
|
107363
|
-
hint: "enter archive esc cancel"
|
|
107364
|
-
};
|
|
107365
|
-
}
|
|
107366
|
-
function renderMoveInteraction(model, selection) {
|
|
107367
|
-
const view = buildMovePromptViewModel(model, selection);
|
|
107368
|
-
if (!view)
|
|
107369
|
-
return ["Move", "No Issue selected"];
|
|
107370
|
-
return [
|
|
107371
|
-
`${view.title} to Status`,
|
|
107372
|
-
...view.targets.map((target) => `${target.selected ? ">" : " "} ${target.id} (${target.title})`),
|
|
107373
|
-
view.hint
|
|
107374
|
-
];
|
|
108083
|
+
|
|
108084
|
+
// ../tui/src/index.ts
|
|
108085
|
+
var TUI_VERSION = package_default.version;
|
|
108086
|
+
function createTuiAppElement(props) {
|
|
108087
|
+
return import_react20.default.createElement(TuiAppView, props);
|
|
107375
108088
|
}
|
|
107376
|
-
function
|
|
107377
|
-
|
|
107378
|
-
|
|
107379
|
-
|
|
107380
|
-
|
|
107381
|
-
|
|
107382
|
-
|
|
107383
|
-
|
|
107384
|
-
|
|
107385
|
-
|
|
108089
|
+
function TuiAppView({
|
|
108090
|
+
model,
|
|
108091
|
+
selection,
|
|
108092
|
+
theme = buildTuiTheme(),
|
|
108093
|
+
viewportHeight,
|
|
108094
|
+
viewportWidth,
|
|
108095
|
+
columns
|
|
108096
|
+
}) {
|
|
108097
|
+
const details = selection.detailOpen ? getSelectedDetails(model, selection) : undefined;
|
|
108098
|
+
return import_react20.default.createElement("box", {
|
|
108099
|
+
id: "mikan-app",
|
|
108100
|
+
style: {
|
|
108101
|
+
backgroundColor: theme.base.canvas,
|
|
108102
|
+
color: theme.base.text,
|
|
108103
|
+
flexDirection: "column",
|
|
108104
|
+
height: "100%"
|
|
108105
|
+
}
|
|
108106
|
+
}, import_react20.default.createElement(Header, { theme }), import_react20.default.createElement("box", {
|
|
108107
|
+
id: "mikan-main",
|
|
108108
|
+
style: { flexDirection: "column", flexGrow: 1, minHeight: 0 }
|
|
108109
|
+
}, details ? import_react20.default.createElement(DetailPage, {
|
|
108110
|
+
model,
|
|
108111
|
+
selection,
|
|
108112
|
+
theme,
|
|
108113
|
+
viewportHeight
|
|
108114
|
+
}) : import_react20.default.createElement(BoardView, {
|
|
108115
|
+
model,
|
|
108116
|
+
selection,
|
|
108117
|
+
theme,
|
|
108118
|
+
viewportHeight,
|
|
108119
|
+
viewportWidth,
|
|
108120
|
+
columns
|
|
108121
|
+
})), selection.moveOpen ? import_react20.default.createElement(MovePrompt, { model, selection, theme }) : undefined, selection.noteOpen ? import_react20.default.createElement(NotePrompt, { model, selection, theme }) : undefined, selection.archiveOpen ? import_react20.default.createElement(ArchivePrompt, { model, selection, theme }) : undefined, selection.warningsOpen ? import_react20.default.createElement(WarningPanel, { model, theme }) : undefined, selection.helpOpen ? import_react20.default.createElement(HelpPanel, { theme }) : undefined, import_react20.default.createElement(Footer, {
|
|
108122
|
+
message: selection.message,
|
|
108123
|
+
mode: footerMode(selection),
|
|
108124
|
+
theme
|
|
108125
|
+
}));
|
|
107386
108126
|
}
|
|
107387
|
-
function
|
|
107388
|
-
const
|
|
107389
|
-
|
|
107390
|
-
|
|
107391
|
-
|
|
108127
|
+
function Header(props) {
|
|
108128
|
+
const theme = props.theme ?? buildTuiTheme();
|
|
108129
|
+
return import_react20.default.createElement("text", {
|
|
108130
|
+
id: "mikan-header",
|
|
108131
|
+
style: { color: theme.interactive.accent },
|
|
108132
|
+
content: `\uD83C\uDF4A mikan v${TUI_VERSION}`
|
|
108133
|
+
});
|
|
107392
108134
|
}
|
|
107393
108135
|
async function launchTui(options = {}) {
|
|
107394
108136
|
const { createCliRenderer: createCliRenderer2 } = await init_core3().then(() => exports_core3);
|
|
@@ -107401,17 +108143,17 @@ async function launchTui(options = {}) {
|
|
|
107401
108143
|
renderer.destroy();
|
|
107402
108144
|
};
|
|
107403
108145
|
function App() {
|
|
107404
|
-
const [model, setModel] =
|
|
107405
|
-
const [selection, setSelection] =
|
|
108146
|
+
const [model, setModel] = import_react20.default.useState(() => loadTuiModel(options.cwd));
|
|
108147
|
+
const [selection, setSelection] = import_react20.default.useState({
|
|
107406
108148
|
columnIndex: 0,
|
|
107407
108149
|
cardIndex: 0,
|
|
107408
108150
|
detailOpen: false
|
|
107409
108151
|
});
|
|
107410
|
-
const modelRef =
|
|
107411
|
-
const selectionRef =
|
|
108152
|
+
const modelRef = import_react20.default.useRef(model);
|
|
108153
|
+
const selectionRef = import_react20.default.useRef(selection);
|
|
107412
108154
|
modelRef.current = model;
|
|
107413
108155
|
selectionRef.current = selection;
|
|
107414
|
-
|
|
108156
|
+
import_react20.default.useEffect(() => {
|
|
107415
108157
|
const interval = setInterval(() => {
|
|
107416
108158
|
const refreshed = refreshTuiModel({
|
|
107417
108159
|
cwd: options.cwd,
|
|
@@ -107427,7 +108169,17 @@ async function launchTui(options = {}) {
|
|
|
107427
108169
|
}, []);
|
|
107428
108170
|
useKeyboard2((key) => {
|
|
107429
108171
|
const action = keyToTuiAction(key.name, key.shift);
|
|
108172
|
+
if (selection.helpOpen) {
|
|
108173
|
+
if (action === "escape" || action === "help") {
|
|
108174
|
+
setSelection((current) => moveSelection(model, current, action));
|
|
108175
|
+
}
|
|
108176
|
+
return;
|
|
108177
|
+
}
|
|
107430
108178
|
if (selection.noteOpen) {
|
|
108179
|
+
if (action === "help") {
|
|
108180
|
+
setSelection((current) => moveSelection(model, current, action));
|
|
108181
|
+
return;
|
|
108182
|
+
}
|
|
107431
108183
|
if (action === "escape") {
|
|
107432
108184
|
setSelection((current) => moveSelection(model, current, action));
|
|
107433
108185
|
return;
|
|
@@ -107447,6 +108199,10 @@ async function launchTui(options = {}) {
|
|
|
107447
108199
|
return;
|
|
107448
108200
|
}
|
|
107449
108201
|
if (selection.archiveOpen) {
|
|
108202
|
+
if (action === "help") {
|
|
108203
|
+
setSelection((current) => moveSelection(model, current, action));
|
|
108204
|
+
return;
|
|
108205
|
+
}
|
|
107450
108206
|
if (action === "escape") {
|
|
107451
108207
|
setSelection((current) => moveSelection(model, current, action));
|
|
107452
108208
|
return;
|
|
@@ -107512,138 +108268,165 @@ async function launchTui(options = {}) {
|
|
|
107512
108268
|
setSelection((current) => moveSelection(model, current, action));
|
|
107513
108269
|
return;
|
|
107514
108270
|
}
|
|
107515
|
-
setSelection((current) => moveSelection(model, current, action, {
|
|
107516
|
-
viewportHeight: renderer.height
|
|
107517
|
-
}));
|
|
107518
|
-
});
|
|
107519
|
-
return createTuiAppElement({
|
|
107520
|
-
model,
|
|
107521
|
-
selection,
|
|
107522
|
-
viewportHeight: renderer.height
|
|
107523
|
-
|
|
107524
|
-
|
|
107525
|
-
|
|
107526
|
-
|
|
107527
|
-
|
|
107528
|
-
|
|
107529
|
-
|
|
107530
|
-
|
|
107531
|
-
|
|
107532
|
-
|
|
107533
|
-
|
|
107534
|
-
|
|
107535
|
-
|
|
107536
|
-
|
|
107537
|
-
|
|
107538
|
-
|
|
107539
|
-
|
|
107540
|
-
|
|
107541
|
-
|
|
107542
|
-
|
|
107543
|
-
|
|
107544
|
-
|
|
107545
|
-
|
|
107546
|
-
|
|
107547
|
-
|
|
107548
|
-
|
|
107549
|
-
|
|
107550
|
-
|
|
107551
|
-
|
|
107552
|
-
|
|
107553
|
-
|
|
107554
|
-
|
|
107555
|
-
|
|
107556
|
-
|
|
107557
|
-
|
|
107558
|
-
|
|
107559
|
-
|
|
107560
|
-
|
|
107561
|
-
|
|
107562
|
-
|
|
107563
|
-
|
|
107564
|
-
|
|
107565
|
-
|
|
107566
|
-
|
|
108271
|
+
setSelection((current) => moveSelection(model, current, action, {
|
|
108272
|
+
viewportHeight: renderer.height
|
|
108273
|
+
}));
|
|
108274
|
+
});
|
|
108275
|
+
return createTuiAppElement({
|
|
108276
|
+
model,
|
|
108277
|
+
selection,
|
|
108278
|
+
viewportHeight: renderer.height,
|
|
108279
|
+
viewportWidth: renderer.width,
|
|
108280
|
+
columns: options.columns
|
|
108281
|
+
});
|
|
108282
|
+
}
|
|
108283
|
+
root.render(import_react20.default.createElement(App));
|
|
108284
|
+
process.once("SIGINT", stop);
|
|
108285
|
+
}
|
|
108286
|
+
|
|
108287
|
+
// src/args.ts
|
|
108288
|
+
var commands = [
|
|
108289
|
+
"init",
|
|
108290
|
+
"add",
|
|
108291
|
+
"list",
|
|
108292
|
+
"show",
|
|
108293
|
+
"update",
|
|
108294
|
+
"move",
|
|
108295
|
+
"append",
|
|
108296
|
+
"mcp",
|
|
108297
|
+
"skills",
|
|
108298
|
+
"tui",
|
|
108299
|
+
"watch"
|
|
108300
|
+
];
|
|
108301
|
+
var commandOptions = {
|
|
108302
|
+
init: [
|
|
108303
|
+
{ name: "key", short: "k", value: true },
|
|
108304
|
+
{ name: "name", short: "n", value: true }
|
|
108305
|
+
],
|
|
108306
|
+
add: [
|
|
108307
|
+
{ name: "status", short: "s", value: true },
|
|
108308
|
+
{ name: "label", short: "l", value: true },
|
|
108309
|
+
{ name: "depends-on", value: true }
|
|
108310
|
+
],
|
|
108311
|
+
list: [
|
|
108312
|
+
{ name: "status", short: "s", value: true },
|
|
108313
|
+
{ name: "include-archived", short: "a", value: false }
|
|
108314
|
+
],
|
|
108315
|
+
show: [],
|
|
108316
|
+
update: [
|
|
108317
|
+
{ name: "title", short: "t", value: true },
|
|
108318
|
+
{ name: "label", short: "l", value: true },
|
|
108319
|
+
{ name: "depends-on", value: true },
|
|
108320
|
+
{ name: "body", short: "b", value: true }
|
|
108321
|
+
],
|
|
108322
|
+
move: [{ name: "log", short: "l", value: true }],
|
|
108323
|
+
append: [
|
|
108324
|
+
{ name: "section", short: "S", value: true },
|
|
108325
|
+
{ name: "body", short: "b", value: true },
|
|
108326
|
+
{ name: "source", short: "s", value: true }
|
|
108327
|
+
],
|
|
108328
|
+
mcp: [
|
|
108329
|
+
{ name: "agent", short: "a", value: true },
|
|
108330
|
+
{ name: "no-global", value: false },
|
|
108331
|
+
{ name: "full", value: false }
|
|
108332
|
+
],
|
|
108333
|
+
skills: [
|
|
108334
|
+
{ name: "agent", short: "a", value: true },
|
|
108335
|
+
{ name: "no-global", value: false }
|
|
108336
|
+
],
|
|
108337
|
+
tui: [{ name: "columns", short: "c", value: true }],
|
|
108338
|
+
watch: [{ name: "quiet", short: "q", value: false }]
|
|
108339
|
+
};
|
|
108340
|
+
function parseArgs(args, command) {
|
|
108341
|
+
const positionals = [];
|
|
108342
|
+
const flags = new Map;
|
|
108343
|
+
for (let index2 = 0;index2 < args.length; index2++) {
|
|
108344
|
+
const arg = args[index2];
|
|
108345
|
+
if (!arg)
|
|
108346
|
+
continue;
|
|
108347
|
+
if (!arg.startsWith("-")) {
|
|
108348
|
+
positionals.push(arg);
|
|
108349
|
+
continue;
|
|
108350
|
+
}
|
|
108351
|
+
const parsed = parseOptionToken(arg, command);
|
|
108352
|
+
if (!parsed.ok)
|
|
108353
|
+
return parsed;
|
|
108354
|
+
const { spec, inlineValue, displayName } = parsed.value;
|
|
108355
|
+
const values = flags.get(spec.name) ?? [];
|
|
108356
|
+
if (!spec.value) {
|
|
108357
|
+
if (inlineValue !== undefined) {
|
|
108358
|
+
return {
|
|
108359
|
+
ok: false,
|
|
108360
|
+
error: `${displayName} does not take a value`
|
|
108361
|
+
};
|
|
108362
|
+
}
|
|
108363
|
+
values.push("true");
|
|
108364
|
+
flags.set(spec.name, values);
|
|
108365
|
+
continue;
|
|
108366
|
+
}
|
|
108367
|
+
const value = inlineValue ?? args[index2 + 1];
|
|
108368
|
+
if (!value || value.startsWith("-")) {
|
|
108369
|
+
return { ok: false, error: `Missing value for ${displayName}` };
|
|
108370
|
+
}
|
|
108371
|
+
if (inlineValue === undefined)
|
|
108372
|
+
index2++;
|
|
108373
|
+
values.push(value);
|
|
108374
|
+
flags.set(spec.name, values);
|
|
107567
108375
|
}
|
|
108376
|
+
return { ok: true, value: { positionals, flags } };
|
|
107568
108377
|
}
|
|
107569
|
-
function
|
|
107570
|
-
const
|
|
107571
|
-
const
|
|
107572
|
-
|
|
107573
|
-
|
|
107574
|
-
|
|
107575
|
-
|
|
107576
|
-
};
|
|
108378
|
+
function parseOptionToken(token, command) {
|
|
108379
|
+
const equalsIndex = token.indexOf("=");
|
|
108380
|
+
const raw = equalsIndex === -1 ? token : token.slice(0, equalsIndex);
|
|
108381
|
+
const inlineValue = equalsIndex === -1 ? undefined : token.slice(equalsIndex + 1);
|
|
108382
|
+
const spec = optionSpecFor(command, raw);
|
|
108383
|
+
if (!spec)
|
|
108384
|
+
return { ok: false, error: `Unknown option: ${raw}` };
|
|
108385
|
+
return { ok: true, value: { spec, inlineValue, displayName: raw } };
|
|
107577
108386
|
}
|
|
107578
|
-
function
|
|
107579
|
-
|
|
107580
|
-
|
|
107581
|
-
|
|
107582
|
-
|
|
107583
|
-
|
|
108387
|
+
function optionSpecFor(command, raw) {
|
|
108388
|
+
if (isHelpFlag(raw))
|
|
108389
|
+
return { name: "help", short: "h", value: false };
|
|
108390
|
+
if (raw.startsWith("--")) {
|
|
108391
|
+
const name = raw.slice(2);
|
|
108392
|
+
return commandOptions[command].find((option) => option.name === name);
|
|
108393
|
+
}
|
|
108394
|
+
if (raw.startsWith("-") && raw.length === 2) {
|
|
108395
|
+
const short = raw.slice(1);
|
|
108396
|
+
return commandOptions[command].find((option) => option.short === short);
|
|
107584
108397
|
}
|
|
107585
108398
|
return;
|
|
107586
108399
|
}
|
|
107587
|
-
function
|
|
107588
|
-
return
|
|
107589
|
-
id: String(issue2.issue.id),
|
|
107590
|
-
title: issue2.issue.title,
|
|
107591
|
-
labels: issue2.issue.labels.map(String),
|
|
107592
|
-
status: String(issue2.status),
|
|
107593
|
-
path: issue2.path
|
|
107594
|
-
};
|
|
107595
|
-
}
|
|
107596
|
-
function detailScrollMax(model, selection, options = {}) {
|
|
107597
|
-
const details = getSelectedDetails(model, selection);
|
|
107598
|
-
if (!details)
|
|
107599
|
-
return 0;
|
|
107600
|
-
const visibleLineCount = options.viewportHeight ? visibleDetailLineCount(options.viewportHeight) : 40;
|
|
107601
|
-
return Math.max(0, stripFrontmatter(details.markdown).trimEnd().split(`
|
|
107602
|
-
`).length - visibleLineCount);
|
|
108400
|
+
function isHelpFlag(input) {
|
|
108401
|
+
return input === "-h" || input === "--help";
|
|
107603
108402
|
}
|
|
107604
|
-
function
|
|
107605
|
-
|
|
107606
|
-
`))
|
|
107607
|
-
return markdown;
|
|
107608
|
-
const end = markdown.indexOf(`
|
|
107609
|
-
---
|
|
107610
|
-
`, 4);
|
|
107611
|
-
if (end === -1)
|
|
107612
|
-
return markdown;
|
|
107613
|
-
return markdown.slice(end + `
|
|
107614
|
-
---
|
|
107615
|
-
`.length).trimStart();
|
|
108403
|
+
function isCommandName(input) {
|
|
108404
|
+
return commands.includes(input);
|
|
107616
108405
|
}
|
|
107617
|
-
|
|
107618
|
-
|
|
107619
|
-
|
|
107620
|
-
|
|
107621
|
-
if (start === -1)
|
|
107622
|
-
return "";
|
|
107623
|
-
let end = lines.length;
|
|
107624
|
-
for (let index2 = start + 1;index2 < lines.length; index2++) {
|
|
107625
|
-
if (/^##\s+/.test(lines[index2] ?? "")) {
|
|
107626
|
-
end = index2;
|
|
107627
|
-
break;
|
|
107628
|
-
}
|
|
107629
|
-
}
|
|
107630
|
-
return lines.slice(start + 1, end).join(`
|
|
107631
|
-
`).trim();
|
|
108406
|
+
|
|
108407
|
+
// src/cli-output.ts
|
|
108408
|
+
function ok2(stdout) {
|
|
108409
|
+
return { exitCode: 0, stdout, stderr: "" };
|
|
107632
108410
|
}
|
|
107633
|
-
function
|
|
107634
|
-
return
|
|
108411
|
+
function fail(stderr) {
|
|
108412
|
+
return { exitCode: 1, stdout: "", stderr: `${stderr}
|
|
108413
|
+
` };
|
|
107635
108414
|
}
|
|
107636
108415
|
|
|
108416
|
+
// src/commands.ts
|
|
108417
|
+
import { readFileSync as readFileSync10 } from "fs";
|
|
108418
|
+
import { basename as basename5, join as join11 } from "path";
|
|
108419
|
+
|
|
107637
108420
|
// src/watch.ts
|
|
107638
108421
|
import {
|
|
107639
108422
|
appendFileSync,
|
|
107640
|
-
existsSync as
|
|
107641
|
-
mkdirSync as
|
|
107642
|
-
readFileSync as
|
|
107643
|
-
renameSync as
|
|
108423
|
+
existsSync as existsSync9,
|
|
108424
|
+
mkdirSync as mkdirSync7,
|
|
108425
|
+
readFileSync as readFileSync9,
|
|
108426
|
+
renameSync as renameSync4,
|
|
107644
108427
|
writeFileSync as writeFileSync6
|
|
107645
108428
|
} from "fs";
|
|
107646
|
-
import { dirname as
|
|
108429
|
+
import { dirname as dirname8, join as join10 } from "path";
|
|
107647
108430
|
function runWatchOnce(options = {}) {
|
|
107648
108431
|
const loaded = loadProjectConfig(options.cwd ?? process.cwd());
|
|
107649
108432
|
if (!loaded.ok)
|
|
@@ -107717,11 +108500,11 @@ function appendPlaceholderStatusLog(loaded, issue2, fromStatus, now) {
|
|
|
107717
108500
|
}
|
|
107718
108501
|
function fireHooks(loaded, issue2, fromStatus, toStatus, options) {
|
|
107719
108502
|
const hooks = loaded.config.hooks;
|
|
107720
|
-
const
|
|
108503
|
+
const commands2 = [
|
|
107721
108504
|
...hooks?.on_enter?.[toStatus] ?? [],
|
|
107722
108505
|
...hooks?.on_transition?.[`${fromStatus}->${toStatus}`] ?? []
|
|
107723
108506
|
];
|
|
107724
|
-
for (const command of
|
|
108507
|
+
for (const command of commands2) {
|
|
107725
108508
|
const rendered = renderHookCommand(command, {
|
|
107726
108509
|
project_root: loaded.projectRoot,
|
|
107727
108510
|
issue_path: issue2.path,
|
|
@@ -107781,122 +108564,34 @@ function renderHookCommand(command, values) {
|
|
|
107781
108564
|
return command.replace(/{{\s*([a-z_]+)\s*}}/g, (match, key) => values[key] ?? match);
|
|
107782
108565
|
}
|
|
107783
108566
|
function appendHookFailure(projectRoot, entry) {
|
|
107784
|
-
const path5 =
|
|
107785
|
-
|
|
108567
|
+
const path5 = join10(projectRoot, ".mikan", ".state", "hook-log.ndjson");
|
|
108568
|
+
mkdirSync7(dirname8(path5), { recursive: true });
|
|
107786
108569
|
appendFileSync(path5, `${JSON.stringify(entry)}
|
|
107787
108570
|
`);
|
|
107788
108571
|
}
|
|
107789
108572
|
function readSnapshot(path5) {
|
|
107790
|
-
if (!
|
|
108573
|
+
if (!existsSync9(path5))
|
|
107791
108574
|
return;
|
|
107792
108575
|
try {
|
|
107793
|
-
return JSON.parse(
|
|
108576
|
+
return JSON.parse(readFileSync9(path5, "utf8"));
|
|
107794
108577
|
} catch {
|
|
107795
108578
|
return;
|
|
107796
108579
|
}
|
|
107797
108580
|
}
|
|
107798
108581
|
function writeSnapshot(path5, snapshot) {
|
|
107799
|
-
|
|
108582
|
+
mkdirSync7(dirname8(path5), { recursive: true });
|
|
107800
108583
|
const tmp = `${path5}.${process.pid}.${Date.now()}.tmp`;
|
|
107801
108584
|
writeFileSync6(tmp, JSON.stringify(snapshot, null, 2));
|
|
107802
|
-
|
|
108585
|
+
renameSync4(tmp, path5);
|
|
107803
108586
|
}
|
|
107804
108587
|
function watcherSnapshotPath(projectRoot) {
|
|
107805
|
-
return
|
|
108588
|
+
return join10(projectRoot, ".mikan", ".state", "watcher-snapshot.json");
|
|
107806
108589
|
}
|
|
107807
108590
|
function utcNow2(now) {
|
|
107808
108591
|
return (now?.() ?? new Date).toISOString().replace(".000Z", "Z");
|
|
107809
108592
|
}
|
|
107810
108593
|
|
|
107811
|
-
// src/
|
|
107812
|
-
async function runCli(argv = process.argv.slice(2), options = {}) {
|
|
107813
|
-
const cwd = options.cwd ?? process.cwd();
|
|
107814
|
-
const command = argv[0];
|
|
107815
|
-
if (!command || isHelpFlag(command))
|
|
107816
|
-
return ok2(helpText());
|
|
107817
|
-
if (command === "help") {
|
|
107818
|
-
const topic = argv[1];
|
|
107819
|
-
return topic ? commandHelp(topic) : ok2(helpText());
|
|
107820
|
-
}
|
|
107821
|
-
if (!isCommandName(command)) {
|
|
107822
|
-
return fail(`Unknown command: ${command}
|
|
107823
|
-
|
|
107824
|
-
Run \`mikan help\` to see available commands.`);
|
|
107825
|
-
}
|
|
107826
|
-
if (argv.slice(1).some(isHelpFlag))
|
|
107827
|
-
return commandHelp(command);
|
|
107828
|
-
const parsed = parseArgs(argv.slice(1), command);
|
|
107829
|
-
if (!parsed.ok) {
|
|
107830
|
-
return fail(`${parsed.error}
|
|
107831
|
-
|
|
107832
|
-
Run \`mikan help ${command}\` for usage.`);
|
|
107833
|
-
}
|
|
107834
|
-
try {
|
|
107835
|
-
switch (command) {
|
|
107836
|
-
case "init":
|
|
107837
|
-
return runInit(cwd, parsed.value);
|
|
107838
|
-
case "add":
|
|
107839
|
-
return runAdd(cwd, parsed.value, options);
|
|
107840
|
-
case "list":
|
|
107841
|
-
return runList(cwd, parsed.value);
|
|
107842
|
-
case "show":
|
|
107843
|
-
return runShow(cwd, parsed.value);
|
|
107844
|
-
case "update":
|
|
107845
|
-
return runUpdate(cwd, parsed.value, options);
|
|
107846
|
-
case "move":
|
|
107847
|
-
return runMove(cwd, parsed.value, options);
|
|
107848
|
-
case "append":
|
|
107849
|
-
return runAppend(cwd, parsed.value, options);
|
|
107850
|
-
case "mcp":
|
|
107851
|
-
return runMcp(cwd, parsed.value, options);
|
|
107852
|
-
case "tui":
|
|
107853
|
-
return ok2(`Starting mikan OpenTUI board
|
|
107854
|
-
`);
|
|
107855
|
-
case "watch":
|
|
107856
|
-
return runWatch(cwd, parsed.value);
|
|
107857
|
-
default:
|
|
107858
|
-
return ok2(helpText());
|
|
107859
|
-
}
|
|
107860
|
-
} catch (error51) {
|
|
107861
|
-
return fail(error51 instanceof Error ? error51.message : String(error51));
|
|
107862
|
-
}
|
|
107863
|
-
}
|
|
107864
|
-
async function main(argv = process.argv.slice(2)) {
|
|
107865
|
-
const result = await runInteractiveCommand(argv, { cwd: process.cwd() });
|
|
107866
|
-
if (result.stdout)
|
|
107867
|
-
process.stdout.write(result.stdout);
|
|
107868
|
-
if (result.stderr)
|
|
107869
|
-
process.stderr.write(result.stderr);
|
|
107870
|
-
process.exitCode = result.exitCode;
|
|
107871
|
-
}
|
|
107872
|
-
async function runInteractiveCommand(argv = process.argv.slice(2), options = {}) {
|
|
107873
|
-
const cwd = options.cwd ?? process.cwd();
|
|
107874
|
-
if (!argv.some(isHelpFlag)) {
|
|
107875
|
-
if (argv[0] === "mcp" && argv[1] !== "add") {
|
|
107876
|
-
await (options.launchMcp ?? (() => startMcpServer({ cwd })))();
|
|
107877
|
-
return ok2("");
|
|
107878
|
-
}
|
|
107879
|
-
if (argv[0] === "tui") {
|
|
107880
|
-
const loaded = loadProjectConfig(cwd);
|
|
107881
|
-
if (!loaded.ok)
|
|
107882
|
-
return fail(loaded.error.message);
|
|
107883
|
-
await (options.launchTui ?? (() => launchTui({ cwd })))();
|
|
107884
|
-
return ok2("");
|
|
107885
|
-
}
|
|
107886
|
-
if (argv[0] === "watch") {
|
|
107887
|
-
const parsed = parseArgs(argv.slice(1), "watch");
|
|
107888
|
-
if (!parsed.ok) {
|
|
107889
|
-
return fail(`${parsed.error}
|
|
107890
|
-
|
|
107891
|
-
Run \`mikan help watch\` for usage.`);
|
|
107892
|
-
}
|
|
107893
|
-
const quiet = parsed.value.flags.has("quiet");
|
|
107894
|
-
(options.launchWatch ?? (() => watchProject({ cwd, quiet })))();
|
|
107895
|
-
return ok2("");
|
|
107896
|
-
}
|
|
107897
|
-
}
|
|
107898
|
-
return runCli(argv, { cwd, home: options.home });
|
|
107899
|
-
}
|
|
108594
|
+
// src/commands.ts
|
|
107900
108595
|
function runMcp(cwd, parsed, options) {
|
|
107901
108596
|
if (parsed.positionals[0] !== "add") {
|
|
107902
108597
|
return ok2(`Starting mikan MCP server on stdio
|
|
@@ -107920,6 +108615,41 @@ ${hint}`);
|
|
|
107920
108615
|
return fail(error51 instanceof Error ? error51.message : String(error51));
|
|
107921
108616
|
}
|
|
107922
108617
|
}
|
|
108618
|
+
async function runMcpLlms(cwd, args) {
|
|
108619
|
+
const parsed = parseArgs(args, "mcp");
|
|
108620
|
+
if (!parsed.ok) {
|
|
108621
|
+
return fail(`${parsed.error}
|
|
108622
|
+
|
|
108623
|
+
Run \`mikan help mcp\` for usage.`);
|
|
108624
|
+
}
|
|
108625
|
+
if (parsed.value.flags.has("agent")) {
|
|
108626
|
+
return fail(`incur-backed discovery only prints a manifest; it cannot install for a specific agent.
|
|
108627
|
+
` + "Use `mikan mcp add --agent <agent>` for native MCP registration.");
|
|
108628
|
+
}
|
|
108629
|
+
const manifest = await getMcpManifest({ cwd }, { full: parsed.value.flags.has("full") });
|
|
108630
|
+
return ok2(manifest.endsWith(`
|
|
108631
|
+
`) ? manifest : `${manifest}
|
|
108632
|
+
`);
|
|
108633
|
+
}
|
|
108634
|
+
function runSkills(cwd, parsed, options) {
|
|
108635
|
+
if (parsed.positionals[0] !== "add") {
|
|
108636
|
+
return fail("Usage: mikan skills add --agent <agent>");
|
|
108637
|
+
}
|
|
108638
|
+
const agent = parsed.flags.get("agent")?.at(-1);
|
|
108639
|
+
if (!agent)
|
|
108640
|
+
return fail("Usage: mikan skills add --agent <agent>");
|
|
108641
|
+
try {
|
|
108642
|
+
const result = installSkillForAgent(agent, {
|
|
108643
|
+
cwd,
|
|
108644
|
+
home: options.home,
|
|
108645
|
+
global: !parsed.flags.has("no-global")
|
|
108646
|
+
});
|
|
108647
|
+
return ok2(`Installed mikan skill for ${result.agent} (${result.scope}): ${result.path}
|
|
108648
|
+
`);
|
|
108649
|
+
} catch (error51) {
|
|
108650
|
+
return fail(error51 instanceof Error ? error51.message : String(error51));
|
|
108651
|
+
}
|
|
108652
|
+
}
|
|
107923
108653
|
function runWatch(cwd, parsed) {
|
|
107924
108654
|
const lines = [];
|
|
107925
108655
|
runWatchOnce({
|
|
@@ -107933,17 +108663,17 @@ function runWatch(cwd, parsed) {
|
|
|
107933
108663
|
}
|
|
107934
108664
|
function runInit(cwd, parsed) {
|
|
107935
108665
|
const key = parsed.flags.get("key")?.at(-1) ?? "MIK";
|
|
107936
|
-
const name = parsed.flags.get("name")?.at(-1) ??
|
|
108666
|
+
const name = parsed.flags.get("name")?.at(-1) ?? basename5(cwd);
|
|
107937
108667
|
const initialized = initProject(cwd, { key, name });
|
|
107938
108668
|
if (!initialized.ok)
|
|
107939
108669
|
return fail(initialized.error.message);
|
|
107940
|
-
return ok2(`Initialized mikan project at ${
|
|
108670
|
+
return ok2(`Initialized mikan project at ${join11(cwd, ".mikan")}
|
|
107941
108671
|
`);
|
|
107942
108672
|
}
|
|
107943
108673
|
function runAdd(cwd, parsed, options) {
|
|
107944
108674
|
const title = parsed.positionals[0];
|
|
107945
108675
|
if (!title)
|
|
107946
|
-
return fail("Usage: mikan add <title> [--status status] [--label label]");
|
|
108676
|
+
return fail("Usage: mikan add <title> [--status status] [--label label] [--depends-on issue-id]");
|
|
107947
108677
|
const loaded = loadProjectConfig(cwd);
|
|
107948
108678
|
if (!loaded.ok)
|
|
107949
108679
|
return fail(loaded.error.message);
|
|
@@ -107953,6 +108683,7 @@ function runAdd(cwd, parsed, options) {
|
|
|
107953
108683
|
title,
|
|
107954
108684
|
status: parsed.flags.get("status")?.at(-1),
|
|
107955
108685
|
labels: parsed.flags.get("label") ?? [],
|
|
108686
|
+
dependencies: parsed.flags.get("depends-on") ?? [],
|
|
107956
108687
|
now: options.now
|
|
107957
108688
|
});
|
|
107958
108689
|
if (!result.ok)
|
|
@@ -107997,12 +108728,16 @@ function runShow(cwd, parsed) {
|
|
|
107997
108728
|
});
|
|
107998
108729
|
if (!found.ok)
|
|
107999
108730
|
return fail(found.error.message);
|
|
108000
|
-
return
|
|
108731
|
+
return {
|
|
108732
|
+
exitCode: 0,
|
|
108733
|
+
stdout: readFileSync10(found.value.path, "utf8"),
|
|
108734
|
+
stderr: formatDependencyShowInfo(found.value)
|
|
108735
|
+
};
|
|
108001
108736
|
}
|
|
108002
108737
|
function runUpdate(cwd, parsed, options) {
|
|
108003
108738
|
const id = parsed.positionals[0];
|
|
108004
108739
|
if (!id)
|
|
108005
|
-
return fail("Usage: mikan update <issue-id> [--title title] [--label label] [--body body]");
|
|
108740
|
+
return fail("Usage: mikan update <issue-id> [--title title] [--label label] [--depends-on issue-id] [--body body]");
|
|
108006
108741
|
const loaded = loadProjectConfig(cwd);
|
|
108007
108742
|
if (!loaded.ok)
|
|
108008
108743
|
return fail(loaded.error.message);
|
|
@@ -108012,6 +108747,7 @@ function runUpdate(cwd, parsed, options) {
|
|
|
108012
108747
|
id,
|
|
108013
108748
|
title: parsed.flags.get("title")?.at(-1),
|
|
108014
108749
|
labels: parsed.flags.has("label") ? parsed.flags.get("label") ?? [] : undefined,
|
|
108750
|
+
dependencies: parsed.flags.has("depends-on") ? parsed.flags.get("depends-on") ?? [] : undefined,
|
|
108015
108751
|
body: parsed.flags.get("body")?.at(-1),
|
|
108016
108752
|
now: options.now
|
|
108017
108753
|
});
|
|
@@ -108064,142 +108800,52 @@ function runAppend(cwd, parsed, options) {
|
|
|
108064
108800
|
return ok2(`${String(result.value.issue.id)} appended ${section}
|
|
108065
108801
|
`);
|
|
108066
108802
|
}
|
|
108067
|
-
var commands = [
|
|
108068
|
-
"init",
|
|
108069
|
-
"add",
|
|
108070
|
-
"list",
|
|
108071
|
-
"show",
|
|
108072
|
-
"update",
|
|
108073
|
-
"move",
|
|
108074
|
-
"append",
|
|
108075
|
-
"mcp",
|
|
108076
|
-
"tui",
|
|
108077
|
-
"watch"
|
|
108078
|
-
];
|
|
108079
|
-
var commandOptions = {
|
|
108080
|
-
init: [
|
|
108081
|
-
{ name: "key", short: "k", value: true },
|
|
108082
|
-
{ name: "name", short: "n", value: true }
|
|
108083
|
-
],
|
|
108084
|
-
add: [
|
|
108085
|
-
{ name: "status", short: "s", value: true },
|
|
108086
|
-
{ name: "label", short: "l", value: true }
|
|
108087
|
-
],
|
|
108088
|
-
list: [
|
|
108089
|
-
{ name: "status", short: "s", value: true },
|
|
108090
|
-
{ name: "include-archived", short: "a", value: false }
|
|
108091
|
-
],
|
|
108092
|
-
show: [],
|
|
108093
|
-
update: [
|
|
108094
|
-
{ name: "title", short: "t", value: true },
|
|
108095
|
-
{ name: "label", short: "l", value: true },
|
|
108096
|
-
{ name: "body", short: "b", value: true }
|
|
108097
|
-
],
|
|
108098
|
-
move: [{ name: "log", short: "l", value: true }],
|
|
108099
|
-
append: [
|
|
108100
|
-
{ name: "section", short: "S", value: true },
|
|
108101
|
-
{ name: "body", short: "b", value: true },
|
|
108102
|
-
{ name: "source", short: "s", value: true }
|
|
108103
|
-
],
|
|
108104
|
-
mcp: [
|
|
108105
|
-
{ name: "agent", short: "a", value: true },
|
|
108106
|
-
{ name: "no-global", value: false }
|
|
108107
|
-
],
|
|
108108
|
-
tui: [],
|
|
108109
|
-
watch: [{ name: "quiet", short: "q", value: false }]
|
|
108110
|
-
};
|
|
108111
|
-
function parseArgs(args, command) {
|
|
108112
|
-
const positionals = [];
|
|
108113
|
-
const flags = new Map;
|
|
108114
|
-
for (let index2 = 0;index2 < args.length; index2++) {
|
|
108115
|
-
const arg = args[index2];
|
|
108116
|
-
if (!arg)
|
|
108117
|
-
continue;
|
|
108118
|
-
if (!arg.startsWith("-")) {
|
|
108119
|
-
positionals.push(arg);
|
|
108120
|
-
continue;
|
|
108121
|
-
}
|
|
108122
|
-
const parsed = parseOptionToken(arg, command);
|
|
108123
|
-
if (!parsed.ok)
|
|
108124
|
-
return parsed;
|
|
108125
|
-
const { spec, inlineValue, displayName } = parsed.value;
|
|
108126
|
-
const values = flags.get(spec.name) ?? [];
|
|
108127
|
-
if (!spec.value) {
|
|
108128
|
-
if (inlineValue !== undefined) {
|
|
108129
|
-
return {
|
|
108130
|
-
ok: false,
|
|
108131
|
-
error: `${displayName} does not take a value`
|
|
108132
|
-
};
|
|
108133
|
-
}
|
|
108134
|
-
values.push("true");
|
|
108135
|
-
flags.set(spec.name, values);
|
|
108136
|
-
continue;
|
|
108137
|
-
}
|
|
108138
|
-
const value = inlineValue ?? args[index2 + 1];
|
|
108139
|
-
if (!value || value.startsWith("-")) {
|
|
108140
|
-
return { ok: false, error: `Missing value for ${displayName}` };
|
|
108141
|
-
}
|
|
108142
|
-
if (inlineValue === undefined)
|
|
108143
|
-
index2++;
|
|
108144
|
-
values.push(value);
|
|
108145
|
-
flags.set(spec.name, values);
|
|
108146
|
-
}
|
|
108147
|
-
return { ok: true, value: { positionals, flags } };
|
|
108148
|
-
}
|
|
108149
|
-
function parseOptionToken(token, command) {
|
|
108150
|
-
const equalsIndex = token.indexOf("=");
|
|
108151
|
-
const raw = equalsIndex === -1 ? token : token.slice(0, equalsIndex);
|
|
108152
|
-
const inlineValue = equalsIndex === -1 ? undefined : token.slice(equalsIndex + 1);
|
|
108153
|
-
const spec = optionSpecFor(command, raw);
|
|
108154
|
-
if (!spec)
|
|
108155
|
-
return { ok: false, error: `Unknown option: ${raw}` };
|
|
108156
|
-
return { ok: true, value: { spec, inlineValue, displayName: raw } };
|
|
108157
|
-
}
|
|
108158
|
-
function optionSpecFor(command, raw) {
|
|
108159
|
-
if (isHelpFlag(raw))
|
|
108160
|
-
return { name: "help", short: "h", value: false };
|
|
108161
|
-
if (raw.startsWith("--")) {
|
|
108162
|
-
const name = raw.slice(2);
|
|
108163
|
-
return commandOptions[command].find((option) => option.name === name);
|
|
108164
|
-
}
|
|
108165
|
-
if (raw.startsWith("-") && raw.length === 2) {
|
|
108166
|
-
const short = raw.slice(1);
|
|
108167
|
-
return commandOptions[command].find((option) => option.short === short);
|
|
108168
|
-
}
|
|
108169
|
-
return;
|
|
108170
|
-
}
|
|
108171
|
-
function isHelpFlag(input) {
|
|
108172
|
-
return input === "-h" || input === "--help";
|
|
108173
|
-
}
|
|
108174
|
-
function isCommandName(input) {
|
|
108175
|
-
return commands.includes(input);
|
|
108176
|
-
}
|
|
108177
108803
|
function formatBoard(columns) {
|
|
108178
108804
|
const lines = [];
|
|
108179
108805
|
for (const column of columns) {
|
|
108180
108806
|
lines.push(`${column.title}`);
|
|
108181
108807
|
for (const item of column.issues) {
|
|
108182
108808
|
const labels = item.issue.labels.length > 0 ? ` [${item.issue.labels.map(String).join(", ")}]` : "";
|
|
108183
|
-
lines.push(` ${String(item.issue.id)} ${item.issue.title}${labels}`);
|
|
108809
|
+
lines.push(` ${String(item.issue.id)} ${item.issue.title}${labels}${formatDependencyListSuffix(item)}`);
|
|
108184
108810
|
}
|
|
108185
108811
|
}
|
|
108186
108812
|
return `${lines.join(`
|
|
108187
108813
|
`)}
|
|
108188
108814
|
`;
|
|
108189
108815
|
}
|
|
108816
|
+
function formatDependencyListSuffix(item) {
|
|
108817
|
+
const dependsOn = item.issue.dependencies.map(String);
|
|
108818
|
+
const unmet = item.unmetDependencies.map(String);
|
|
108819
|
+
if (dependsOn.length === 0 && unmet.length === 0)
|
|
108820
|
+
return "";
|
|
108821
|
+
const parts = [
|
|
108822
|
+
`depends_on=${dependsOn.length > 0 ? dependsOn.join(",") : "-"}`,
|
|
108823
|
+
`unmet_dependencies=${unmet.length > 0 ? unmet.join(",") : "-"}`,
|
|
108824
|
+
`dependency_status=${item.dependencyStatus}`
|
|
108825
|
+
];
|
|
108826
|
+
return ` ${parts.join(" ")}`;
|
|
108827
|
+
}
|
|
108828
|
+
function formatDependencyShowInfo(item) {
|
|
108829
|
+
const dependsOn = item.issue.dependencies.map(String);
|
|
108830
|
+
const unmet = item.unmetDependencies.map(String);
|
|
108831
|
+
if (dependsOn.length === 0 && unmet.length === 0)
|
|
108832
|
+
return "";
|
|
108833
|
+
return [
|
|
108834
|
+
`Dependency Status: ${item.dependencyStatus}`,
|
|
108835
|
+
`Depends On: ${dependsOn.length > 0 ? dependsOn.join(", ") : "-"}`,
|
|
108836
|
+
`Unmet Dependencies: ${unmet.length > 0 ? unmet.join(", ") : "-"}`,
|
|
108837
|
+
""
|
|
108838
|
+
].join(`
|
|
108839
|
+
`);
|
|
108840
|
+
}
|
|
108190
108841
|
function formatWarnings(warnings) {
|
|
108191
108842
|
if (warnings.length === 0)
|
|
108192
108843
|
return "";
|
|
108193
108844
|
return warnings.map((warning) => `warning ${warning.kind}: ${warning.message}
|
|
108194
108845
|
`).join("");
|
|
108195
108846
|
}
|
|
108196
|
-
|
|
108197
|
-
|
|
108198
|
-
}
|
|
108199
|
-
function fail(stderr) {
|
|
108200
|
-
return { exitCode: 1, stdout: "", stderr: `${stderr}
|
|
108201
|
-
` };
|
|
108202
|
-
}
|
|
108847
|
+
|
|
108848
|
+
// src/help.ts
|
|
108203
108849
|
function commandHelp(topic) {
|
|
108204
108850
|
if (!isCommandName(topic)) {
|
|
108205
108851
|
return fail(`Unknown help topic: ${topic}
|
|
@@ -108225,6 +108871,7 @@ Commands:
|
|
|
108225
108871
|
tui Open the read-only board
|
|
108226
108872
|
watch Run the polling watcher
|
|
108227
108873
|
mcp Start the stdio MCP server
|
|
108874
|
+
skills Install agent-facing mikan usage guidance
|
|
108228
108875
|
|
|
108229
108876
|
Run \`mikan help <command>\` for command-specific options.
|
|
108230
108877
|
`;
|
|
@@ -108251,6 +108898,7 @@ Usage:
|
|
|
108251
108898
|
Options:
|
|
108252
108899
|
-s, --status <status> Add to Status (default: backlog)
|
|
108253
108900
|
-l, --label <label> Add label; repeat for multiple labels
|
|
108901
|
+
--depends-on <issue-id> Add dependency; repeat for multiple dependencies
|
|
108254
108902
|
-h, --help Show this help
|
|
108255
108903
|
|
|
108256
108904
|
Examples:
|
|
@@ -108285,6 +108933,7 @@ Usage:
|
|
|
108285
108933
|
Options:
|
|
108286
108934
|
-t, --title <title> Replace title
|
|
108287
108935
|
-l, --label <label> Replace labels; repeat for multiple labels
|
|
108936
|
+
--depends-on <issue-id> Replace dependencies; repeat for multiple dependencies
|
|
108288
108937
|
-b, --body <body> Replace body Markdown
|
|
108289
108938
|
-h, --help Show this help
|
|
108290
108939
|
`;
|
|
@@ -108314,10 +108963,22 @@ Options:
|
|
|
108314
108963
|
return `Open the read-only board.
|
|
108315
108964
|
|
|
108316
108965
|
Usage:
|
|
108317
|
-
mikan tui
|
|
108966
|
+
mikan tui [options]
|
|
108318
108967
|
|
|
108319
108968
|
Options:
|
|
108969
|
+
-c, --columns <auto|2|3|4|5> Preferred visible Column count (default: auto)
|
|
108320
108970
|
-h, --help Show this help
|
|
108971
|
+
|
|
108972
|
+
Examples:
|
|
108973
|
+
mikan tui
|
|
108974
|
+
mikan tui --columns auto
|
|
108975
|
+
mikan tui --columns 3
|
|
108976
|
+
mikan tui -c 5
|
|
108977
|
+
|
|
108978
|
+
Notes:
|
|
108979
|
+
--columns sets how many Status Columns the board shows at once. auto
|
|
108980
|
+
derives 2..5 Columns from terminal width and keeps the sliding viewport;
|
|
108981
|
+
a fixed 2..5 pins that count. It never changes configured Statuses.
|
|
108321
108982
|
`;
|
|
108322
108983
|
case "watch":
|
|
108323
108984
|
return `Run the polling watcher.
|
|
@@ -108330,24 +108991,194 @@ Options:
|
|
|
108330
108991
|
-h, --help Show this help
|
|
108331
108992
|
`;
|
|
108332
108993
|
case "mcp":
|
|
108333
|
-
return `Start the stdio MCP server
|
|
108994
|
+
return `Start the stdio MCP server, register it with an agent, or print its manifest.
|
|
108334
108995
|
|
|
108335
108996
|
Usage:
|
|
108336
108997
|
mikan mcp
|
|
108337
108998
|
mikan mcp add --agent <agent> [--no-global]
|
|
108999
|
+
mikan mcp llms [--full]
|
|
108338
109000
|
|
|
108339
109001
|
Options:
|
|
108340
|
-
-a, --agent <agent> Agent to configure: pi, antigravity, jcode
|
|
109002
|
+
-a, --agent <agent> Agent to configure: pi, antigravity, jcode, claude-code, opencode, codex
|
|
108341
109003
|
--no-global Write workspace-local config instead of global config
|
|
109004
|
+
--full With llms: print the full incur manifest
|
|
108342
109005
|
-h, --help Show this help
|
|
108343
109006
|
|
|
109007
|
+
Notes:
|
|
109008
|
+
codex registers in global ~/.codex/config.toml only; --no-global is rejected.
|
|
109009
|
+
Use mikan mcp add for native per-agent registration. Use mikan mcp llms for
|
|
109010
|
+
incur-backed discovery: it prints a manifest for agents that read incur
|
|
109011
|
+
manifests directly and never installs anything. Passing --agent to llms is
|
|
109012
|
+
rejected; install with mikan mcp add --agent <agent> instead.
|
|
109013
|
+
|
|
108344
109014
|
Examples:
|
|
108345
109015
|
mikan mcp add --agent pi
|
|
108346
109016
|
mikan mcp add --agent antigravity --no-global
|
|
108347
109017
|
mikan mcp add -a jcode
|
|
109018
|
+
mikan mcp add --agent claude-code
|
|
109019
|
+
mikan mcp add --agent opencode --no-global
|
|
109020
|
+
mikan mcp add --agent codex
|
|
109021
|
+
mikan mcp llms
|
|
109022
|
+
mikan mcp llms --full
|
|
109023
|
+
`;
|
|
109024
|
+
case "skills":
|
|
109025
|
+
return `Install agent-facing mikan usage guidance.
|
|
109026
|
+
|
|
109027
|
+
mikan skills add installs lightweight instructions that teach an agent how to
|
|
109028
|
+
use mikan. It is separate from mikan mcp add, which registers the MCP tools;
|
|
109029
|
+
installing skills never changes MCP config.
|
|
109030
|
+
|
|
109031
|
+
Usage:
|
|
109032
|
+
mikan skills add --agent <agent> [--no-global]
|
|
109033
|
+
|
|
109034
|
+
Options:
|
|
109035
|
+
-a, --agent <agent> Agent to install the mikan skill for: claude-code, opencode, codex
|
|
109036
|
+
--no-global Install workspace-local guidance instead of global
|
|
109037
|
+
-h, --help Show this help
|
|
109038
|
+
|
|
109039
|
+
Notes:
|
|
109040
|
+
codex installs the skill globally only; --no-global is rejected for codex.
|
|
109041
|
+
|
|
109042
|
+
Examples:
|
|
109043
|
+
mikan skills add --agent claude-code
|
|
109044
|
+
mikan skills add --agent opencode --no-global
|
|
109045
|
+
mikan skills add -a codex
|
|
108348
109046
|
`;
|
|
108349
109047
|
}
|
|
108350
109048
|
}
|
|
108351
109049
|
|
|
109050
|
+
// src/tui-options.ts
|
|
109051
|
+
var DEFAULT_TUI_COLUMNS = "auto";
|
|
109052
|
+
var NUMERIC_TUI_COLUMNS = /^[2-5]$/;
|
|
109053
|
+
function parseTuiColumnsOption(raw) {
|
|
109054
|
+
if (raw === undefined)
|
|
109055
|
+
return { ok: true, value: DEFAULT_TUI_COLUMNS };
|
|
109056
|
+
if (raw === "auto")
|
|
109057
|
+
return { ok: true, value: "auto" };
|
|
109058
|
+
if (NUMERIC_TUI_COLUMNS.test(raw)) {
|
|
109059
|
+
return { ok: true, value: Number(raw) };
|
|
109060
|
+
}
|
|
109061
|
+
return {
|
|
109062
|
+
ok: false,
|
|
109063
|
+
error: `Invalid --columns value: ${raw}. Expected auto, 2, 3, 4, or 5.`
|
|
109064
|
+
};
|
|
109065
|
+
}
|
|
109066
|
+
|
|
109067
|
+
// src/index.ts
|
|
109068
|
+
async function runCli(argv = process.argv.slice(2), options = {}) {
|
|
109069
|
+
const cwd = options.cwd ?? process.cwd();
|
|
109070
|
+
const command = argv[0];
|
|
109071
|
+
if (!command || isHelpFlag(command))
|
|
109072
|
+
return ok2(helpText());
|
|
109073
|
+
if (command === "help") {
|
|
109074
|
+
const topic = argv[1];
|
|
109075
|
+
return topic ? commandHelp(topic) : ok2(helpText());
|
|
109076
|
+
}
|
|
109077
|
+
if (!isCommandName(command)) {
|
|
109078
|
+
return fail(`Unknown command: ${command}
|
|
109079
|
+
|
|
109080
|
+
Run \`mikan help\` to see available commands.`);
|
|
109081
|
+
}
|
|
109082
|
+
if (argv.slice(1).some(isHelpFlag))
|
|
109083
|
+
return commandHelp(command);
|
|
109084
|
+
const parsed = parseArgs(argv.slice(1), command);
|
|
109085
|
+
if (!parsed.ok) {
|
|
109086
|
+
return fail(`${parsed.error}
|
|
109087
|
+
|
|
109088
|
+
Run \`mikan help ${command}\` for usage.`);
|
|
109089
|
+
}
|
|
109090
|
+
try {
|
|
109091
|
+
switch (command) {
|
|
109092
|
+
case "init":
|
|
109093
|
+
return runInit(cwd, parsed.value);
|
|
109094
|
+
case "add":
|
|
109095
|
+
return runAdd(cwd, parsed.value, options);
|
|
109096
|
+
case "list":
|
|
109097
|
+
return runList(cwd, parsed.value);
|
|
109098
|
+
case "show":
|
|
109099
|
+
return runShow(cwd, parsed.value);
|
|
109100
|
+
case "update":
|
|
109101
|
+
return runUpdate(cwd, parsed.value, options);
|
|
109102
|
+
case "move":
|
|
109103
|
+
return runMove(cwd, parsed.value, options);
|
|
109104
|
+
case "append":
|
|
109105
|
+
return runAppend(cwd, parsed.value, options);
|
|
109106
|
+
case "mcp":
|
|
109107
|
+
return runMcp(cwd, parsed.value, options);
|
|
109108
|
+
case "skills":
|
|
109109
|
+
return runSkills(cwd, parsed.value, options);
|
|
109110
|
+
case "tui": {
|
|
109111
|
+
const columns = parseTuiColumnsOption(parsed.value.flags.get("columns")?.at(-1));
|
|
109112
|
+
if (!columns.ok) {
|
|
109113
|
+
return fail(`${columns.error}
|
|
109114
|
+
|
|
109115
|
+
Run \`mikan help tui\` for usage.`);
|
|
109116
|
+
}
|
|
109117
|
+
return ok2(`Starting mikan OpenTUI board
|
|
109118
|
+
`);
|
|
109119
|
+
}
|
|
109120
|
+
case "watch":
|
|
109121
|
+
return runWatch(cwd, parsed.value);
|
|
109122
|
+
default:
|
|
109123
|
+
return ok2(helpText());
|
|
109124
|
+
}
|
|
109125
|
+
} catch (error51) {
|
|
109126
|
+
return fail(error51 instanceof Error ? error51.message : String(error51));
|
|
109127
|
+
}
|
|
109128
|
+
}
|
|
109129
|
+
async function main(argv = process.argv.slice(2)) {
|
|
109130
|
+
const result = await runInteractiveCommand(argv, { cwd: process.cwd() });
|
|
109131
|
+
if (result.stdout)
|
|
109132
|
+
process.stdout.write(result.stdout);
|
|
109133
|
+
if (result.stderr)
|
|
109134
|
+
process.stderr.write(result.stderr);
|
|
109135
|
+
process.exitCode = result.exitCode;
|
|
109136
|
+
}
|
|
109137
|
+
async function runInteractiveCommand(argv = process.argv.slice(2), options = {}) {
|
|
109138
|
+
const cwd = options.cwd ?? process.cwd();
|
|
109139
|
+
if (!argv.some(isHelpFlag)) {
|
|
109140
|
+
if (argv[0] === "mcp" && argv[1] === "llms") {
|
|
109141
|
+
return runMcpLlms(cwd, argv.slice(2));
|
|
109142
|
+
}
|
|
109143
|
+
if (argv[0] === "mcp" && argv[1] !== "add") {
|
|
109144
|
+
await (options.launchMcp ?? (() => startMcpServer({ cwd })))();
|
|
109145
|
+
return ok2("");
|
|
109146
|
+
}
|
|
109147
|
+
if (argv[0] === "tui") {
|
|
109148
|
+
const parsed = parseArgs(argv.slice(1), "tui");
|
|
109149
|
+
if (!parsed.ok) {
|
|
109150
|
+
return fail(`${parsed.error}
|
|
109151
|
+
|
|
109152
|
+
Run \`mikan help tui\` for usage.`);
|
|
109153
|
+
}
|
|
109154
|
+
const columns = parseTuiColumnsOption(parsed.value.flags.get("columns")?.at(-1));
|
|
109155
|
+
if (!columns.ok) {
|
|
109156
|
+
return fail(`${columns.error}
|
|
109157
|
+
|
|
109158
|
+
Run \`mikan help tui\` for usage.`);
|
|
109159
|
+
}
|
|
109160
|
+
const loaded = loadProjectConfig(cwd);
|
|
109161
|
+
if (!loaded.ok)
|
|
109162
|
+
return fail(loaded.error.message);
|
|
109163
|
+
await (options.launchTui ?? ((launchOptions) => launchTui({ cwd, columns: launchOptions.columns })))({
|
|
109164
|
+
columns: columns.value
|
|
109165
|
+
});
|
|
109166
|
+
return ok2("");
|
|
109167
|
+
}
|
|
109168
|
+
if (argv[0] === "watch") {
|
|
109169
|
+
const parsed = parseArgs(argv.slice(1), "watch");
|
|
109170
|
+
if (!parsed.ok) {
|
|
109171
|
+
return fail(`${parsed.error}
|
|
109172
|
+
|
|
109173
|
+
Run \`mikan help watch\` for usage.`);
|
|
109174
|
+
}
|
|
109175
|
+
const quiet = parsed.value.flags.has("quiet");
|
|
109176
|
+
(options.launchWatch ?? (() => watchProject({ cwd, quiet })))();
|
|
109177
|
+
return ok2("");
|
|
109178
|
+
}
|
|
109179
|
+
}
|
|
109180
|
+
return runCli(argv, { cwd, home: options.home });
|
|
109181
|
+
}
|
|
109182
|
+
|
|
108352
109183
|
// src/bin.ts
|
|
108353
109184
|
await main();
|