opencode-skills-deck 0.3.0 → 0.3.1
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/dist/index.js +52 -39
- package/dist/index.js.map +3 -3
- package/dist/tui.js +48 -38
- package/dist/tui.js.map +3 -3
- package/package.json +1 -1
package/dist/tui.js
CHANGED
|
@@ -5089,7 +5089,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
5089
5089
|
var NONE = 0;
|
|
5090
5090
|
var ASSUMED = 1;
|
|
5091
5091
|
var PROVEN = 2;
|
|
5092
|
-
function isRecursive(inst, stack,
|
|
5092
|
+
function isRecursive(inst, stack, resolve2) {
|
|
5093
5093
|
const cached2 = recursive.get(inst);
|
|
5094
5094
|
if (cached2 !== void 0)
|
|
5095
5095
|
return cached2 ? PROVEN : NONE;
|
|
@@ -5099,7 +5099,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
5099
5099
|
let result = NONE;
|
|
5100
5100
|
const check2 = (child) => {
|
|
5101
5101
|
if (result !== PROVEN && child?._zod) {
|
|
5102
|
-
const answer = isRecursive(child, stack,
|
|
5102
|
+
const answer = isRecursive(child, stack, resolve2);
|
|
5103
5103
|
if (answer > result)
|
|
5104
5104
|
result = answer;
|
|
5105
5105
|
}
|
|
@@ -5110,7 +5110,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
5110
5110
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
5111
5111
|
if (spread && !desc.enumerable)
|
|
5112
5112
|
continue;
|
|
5113
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
5113
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve2) : NONE;
|
|
5114
5114
|
if (child > answer)
|
|
5115
5115
|
answer = child;
|
|
5116
5116
|
}
|
|
@@ -5174,7 +5174,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
5174
5174
|
break;
|
|
5175
5175
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5176
5176
|
case "lazy": {
|
|
5177
|
-
const inner = def._cachedInner ?? (
|
|
5177
|
+
const inner = def._cachedInner ?? (resolve2 ? inst._zod.innerType : void 0);
|
|
5178
5178
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5179
5179
|
break;
|
|
5180
5180
|
}
|
|
@@ -19793,7 +19793,7 @@ var MAX_BUFFER = 16 * 1024 * 1024;
|
|
|
19793
19793
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
19794
19794
|
function createRunner(options = {}) {
|
|
19795
19795
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
19796
|
-
return (command, args, options2) => new Promise((
|
|
19796
|
+
return (command, args, options2) => new Promise((resolve2, reject) => {
|
|
19797
19797
|
const child = spawn(command, args, {
|
|
19798
19798
|
cwd: options2?.cwd,
|
|
19799
19799
|
env: process.env,
|
|
@@ -19813,7 +19813,7 @@ function createRunner(options = {}) {
|
|
|
19813
19813
|
if (settled) return;
|
|
19814
19814
|
settled = true;
|
|
19815
19815
|
clearTimeout(timer);
|
|
19816
|
-
|
|
19816
|
+
resolve2(result);
|
|
19817
19817
|
};
|
|
19818
19818
|
const timer = setTimeout(() => {
|
|
19819
19819
|
child.kill("SIGTERM");
|
|
@@ -19859,48 +19859,58 @@ function createRunner(options = {}) {
|
|
|
19859
19859
|
|
|
19860
19860
|
// packages/core/src/paths.ts
|
|
19861
19861
|
import { homedir } from "node:os";
|
|
19862
|
-
import {
|
|
19862
|
+
import { posix, win32 } from "node:path";
|
|
19863
19863
|
var APP_DIR = "opencode-skills-deck";
|
|
19864
|
+
function pathFor(platform) {
|
|
19865
|
+
return platform === "win32" ? win32 : posix;
|
|
19866
|
+
}
|
|
19867
|
+
function styleOf(path) {
|
|
19868
|
+
return /^[A-Za-z]:[\\/]/.test(path) || path.startsWith("\\\\") ? "win32" : "linux";
|
|
19869
|
+
}
|
|
19864
19870
|
function configRootOf(platform, env, home) {
|
|
19865
|
-
|
|
19871
|
+
const path = pathFor(platform);
|
|
19872
|
+
return env.XDG_CONFIG_HOME ?? (platform === "win32" ? env.APPDATA ?? path.join(home, "AppData", "Roaming") : path.join(home, ".config"));
|
|
19866
19873
|
}
|
|
19867
19874
|
function stateRootOf(platform, env, home) {
|
|
19868
|
-
|
|
19875
|
+
const path = pathFor(platform);
|
|
19876
|
+
return env.XDG_STATE_HOME ?? (platform === "win32" ? env.LOCALAPPDATA ?? path.join(home, "AppData", "Local") : path.join(home, ".local", "state"));
|
|
19869
19877
|
}
|
|
19870
19878
|
function opencodeConfigDir(options = {}) {
|
|
19871
19879
|
const platform = options.platform ?? process.platform;
|
|
19872
19880
|
const env = options.env ?? process.env;
|
|
19873
19881
|
const home = options.home ?? homedir();
|
|
19874
|
-
return
|
|
19882
|
+
return pathFor(platform).join(configRootOf(platform, env, home), "opencode");
|
|
19875
19883
|
}
|
|
19876
19884
|
function opencodeSkillsDir(options = {}) {
|
|
19877
|
-
return
|
|
19885
|
+
return pathFor(options.platform ?? process.platform).join(opencodeConfigDir(options), "skills");
|
|
19878
19886
|
}
|
|
19879
19887
|
function repoSessionSlug(repo) {
|
|
19880
19888
|
return repo.replace(/[^a-zA-Z0-9._-]+/g, "__");
|
|
19881
19889
|
}
|
|
19882
19890
|
function sessionsDirFor(paths, repo) {
|
|
19883
|
-
|
|
19891
|
+
if (!repo) return paths.sessionsDir;
|
|
19892
|
+
return pathFor(styleOf(paths.sessionsDir)).join(paths.sessionsDir, repoSessionSlug(repo));
|
|
19884
19893
|
}
|
|
19885
19894
|
function resolvePaths(options = {}) {
|
|
19886
19895
|
const platform = options.platform ?? process.platform;
|
|
19887
19896
|
const env = options.env ?? process.env;
|
|
19888
19897
|
const home = options.home ?? homedir();
|
|
19898
|
+
const path = pathFor(platform);
|
|
19889
19899
|
const configRoot = configRootOf(platform, env, home);
|
|
19890
19900
|
const stateRoot = stateRootOf(platform, env, home);
|
|
19891
|
-
const configDir =
|
|
19892
|
-
const stateDir =
|
|
19901
|
+
const configDir = path.join(configRoot, APP_DIR);
|
|
19902
|
+
const stateDir = path.join(stateRoot, APP_DIR);
|
|
19893
19903
|
return {
|
|
19894
19904
|
configDir,
|
|
19895
19905
|
stateDir,
|
|
19896
|
-
sessionsDir:
|
|
19897
|
-
issueCacheDir:
|
|
19906
|
+
sessionsDir: path.join(stateDir, "sessions"),
|
|
19907
|
+
issueCacheDir: path.join(stateDir, "issues")
|
|
19898
19908
|
};
|
|
19899
19909
|
}
|
|
19900
19910
|
|
|
19901
19911
|
// packages/core/src/repo.ts
|
|
19902
19912
|
import { execFileSync } from "node:child_process";
|
|
19903
|
-
import {
|
|
19913
|
+
import { join as join2, posix as posix2, win32 as win322 } from "node:path";
|
|
19904
19914
|
var REMOTE_PATTERNS = [
|
|
19905
19915
|
/^git@[^:]+:(?<owner>[^/]+)\/(?<name>[^/]+?)(?:\.git)?$/,
|
|
19906
19916
|
/^(?:ssh|git|https?):\/\/(?:[^@/]+@)?[^/]+\/(?<owner>[^/]+)\/(?<name>[^/]+?)(?:\.git)?\/?$/
|
|
@@ -19925,7 +19935,7 @@ function branchName(issueNumber, title) {
|
|
|
19925
19935
|
return slug ? `issue/${issueNumber}-${slug}` : `issue/${issueNumber}`;
|
|
19926
19936
|
}
|
|
19927
19937
|
function issueWorktreePath(repoRoot, issueNumber) {
|
|
19928
|
-
return
|
|
19938
|
+
return join2(repoRoot, ".worktrees", `issue-${issueNumber}`);
|
|
19929
19939
|
}
|
|
19930
19940
|
function issueKey(issueNumber) {
|
|
19931
19941
|
return `issue-${issueNumber}`;
|
|
@@ -19981,10 +19991,10 @@ import {
|
|
|
19981
19991
|
watch,
|
|
19982
19992
|
writeFileSync
|
|
19983
19993
|
} from "node:fs";
|
|
19984
|
-
import { join as
|
|
19994
|
+
import { join as join3 } from "node:path";
|
|
19985
19995
|
var STARTUP_GRACE_MS = 2e4;
|
|
19986
19996
|
function sessionFilePath(dir, key) {
|
|
19987
|
-
return
|
|
19997
|
+
return join3(dir, `${key}.json`);
|
|
19988
19998
|
}
|
|
19989
19999
|
function readSessions(dir) {
|
|
19990
20000
|
if (!existsSync(dir)) return [];
|
|
@@ -20111,7 +20121,7 @@ function migrateLegacySessions(input2) {
|
|
|
20111
20121
|
// packages/core/src/terminal.ts
|
|
20112
20122
|
import { spawn as spawn2 } from "node:child_process";
|
|
20113
20123
|
import { existsSync as existsSync2 } from "node:fs";
|
|
20114
|
-
import { delimiter, join as
|
|
20124
|
+
import { delimiter, join as join4 } from "node:path";
|
|
20115
20125
|
var DARWIN_BINARIES = {
|
|
20116
20126
|
alacritty: "/Applications/Alacritty.app/Contents/MacOS/alacritty",
|
|
20117
20127
|
kitty: "/Applications/kitty.app/Contents/MacOS/kitty"
|
|
@@ -20120,7 +20130,7 @@ function whichInPath(command, env) {
|
|
|
20120
20130
|
const pathValue = env.PATH ?? "";
|
|
20121
20131
|
for (const directory of pathValue.split(delimiter)) {
|
|
20122
20132
|
if (!directory) continue;
|
|
20123
|
-
const candidate =
|
|
20133
|
+
const candidate = join4(directory, command);
|
|
20124
20134
|
if (existsSync2(candidate)) return candidate;
|
|
20125
20135
|
}
|
|
20126
20136
|
return null;
|
|
@@ -20196,7 +20206,7 @@ function launchInTerminal(input2) {
|
|
|
20196
20206
|
|
|
20197
20207
|
// packages/core/src/worktree.ts
|
|
20198
20208
|
import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
20199
|
-
import { join as
|
|
20209
|
+
import { join as join5, resolve, sep } from "node:path";
|
|
20200
20210
|
async function defaultBranch(input2) {
|
|
20201
20211
|
if (input2.configured) return input2.configured;
|
|
20202
20212
|
try {
|
|
@@ -20213,7 +20223,7 @@ async function ensureWorktreesExcluded(input2) {
|
|
|
20213
20223
|
const { stdout } = await input2.runner("git", ["rev-parse", "--git-path", "info/exclude"], {
|
|
20214
20224
|
cwd: input2.repoRoot
|
|
20215
20225
|
});
|
|
20216
|
-
const path =
|
|
20226
|
+
const path = join5(input2.repoRoot, stdout.trim());
|
|
20217
20227
|
const existing = existsSync3(path) ? readFileSync3(path, "utf8") : "";
|
|
20218
20228
|
if (existing.split("\n").some((line) => line.trim() === ".worktrees/")) return;
|
|
20219
20229
|
const suffix = existing.endsWith("\n") || existing === "" ? "" : "\n";
|
|
@@ -20256,11 +20266,11 @@ function normalized(path) {
|
|
|
20256
20266
|
try {
|
|
20257
20267
|
return realpathSync(path).replace(/\/+$/, "");
|
|
20258
20268
|
} catch {
|
|
20259
|
-
return
|
|
20269
|
+
return resolve(path).replace(/\/+$/, "");
|
|
20260
20270
|
}
|
|
20261
20271
|
}
|
|
20262
20272
|
async function findOrphanWorktrees(input2) {
|
|
20263
|
-
const root = normalized(
|
|
20273
|
+
const root = normalized(join5(input2.repoRoot, ".worktrees"));
|
|
20264
20274
|
const known = new Set(
|
|
20265
20275
|
input2.records.map((record2) => record2.worktree).filter((value) => Boolean(value)).map(normalized)
|
|
20266
20276
|
);
|
|
@@ -20426,7 +20436,7 @@ function dispatchDialogue(input2) {
|
|
|
20426
20436
|
|
|
20427
20437
|
// packages/core/src/issue.ts
|
|
20428
20438
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
20429
|
-
import { dirname
|
|
20439
|
+
import { dirname, join as join6 } from "node:path";
|
|
20430
20440
|
var SUMMARY_HEADING = /summary|要約|概要/i;
|
|
20431
20441
|
var CRITERIA_HEADING = /acceptance criteria|受け入れ基準|完了条件|acceptance/i;
|
|
20432
20442
|
var BULLET = /^\s*(?:[-*+]|\d+\.)\s+(?:\[[ xX]\]\s*)?(.+)$/;
|
|
@@ -20484,7 +20494,7 @@ async function fetchIssues(input2) {
|
|
|
20484
20494
|
return rows.map(toIssue).sort((left, right) => left.number - right.number);
|
|
20485
20495
|
}
|
|
20486
20496
|
function issueCachePath(paths, repo) {
|
|
20487
|
-
return
|
|
20497
|
+
return join6(paths.issueCacheDir, `${repo.owner}__${repo.name}.json`);
|
|
20488
20498
|
}
|
|
20489
20499
|
function normalizeCachedIssue(value) {
|
|
20490
20500
|
if (!value || typeof value !== "object") return null;
|
|
@@ -20522,7 +20532,7 @@ function readIssueCache(path) {
|
|
|
20522
20532
|
}
|
|
20523
20533
|
}
|
|
20524
20534
|
function writeIssueCache(path, cache) {
|
|
20525
|
-
mkdirSync2(
|
|
20535
|
+
mkdirSync2(dirname(path), { recursive: true });
|
|
20526
20536
|
const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
20527
20537
|
writeFileSync3(temporary, `${JSON.stringify(cache, null, 2)}
|
|
20528
20538
|
`);
|
|
@@ -20580,7 +20590,7 @@ async function loadIssues(input2) {
|
|
|
20580
20590
|
// packages/core/src/skills.ts
|
|
20581
20591
|
import { createHash } from "node:crypto";
|
|
20582
20592
|
import { cpSync, existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
20583
|
-
import { join as
|
|
20593
|
+
import { join as join7, relative, sep as sep2 } from "node:path";
|
|
20584
20594
|
var MANIFEST_NAME = ".skills-deck.json";
|
|
20585
20595
|
function hashSkillDir(dir) {
|
|
20586
20596
|
const hash2 = createHash("sha256");
|
|
@@ -20589,7 +20599,7 @@ function hashSkillDir(dir) {
|
|
|
20589
20599
|
(left, right) => left.name.localeCompare(right.name)
|
|
20590
20600
|
);
|
|
20591
20601
|
for (const entry of entries) {
|
|
20592
|
-
const absolute =
|
|
20602
|
+
const absolute = join7(current, entry.name);
|
|
20593
20603
|
const key = relative(dir, absolute).split(sep2).join("/");
|
|
20594
20604
|
if (entry.isDirectory()) {
|
|
20595
20605
|
hash2.update(`d:${key}
|
|
@@ -20608,7 +20618,7 @@ function hashSkillDir(dir) {
|
|
|
20608
20618
|
}
|
|
20609
20619
|
function readManifest(targetDir) {
|
|
20610
20620
|
try {
|
|
20611
|
-
const parsed = JSON.parse(readFileSync5(
|
|
20621
|
+
const parsed = JSON.parse(readFileSync5(join7(targetDir, MANIFEST_NAME), "utf8"));
|
|
20612
20622
|
if (!parsed || typeof parsed.version !== "string" || typeof parsed.skills !== "object") return null;
|
|
20613
20623
|
return parsed;
|
|
20614
20624
|
} catch {
|
|
@@ -20616,19 +20626,19 @@ function readManifest(targetDir) {
|
|
|
20616
20626
|
}
|
|
20617
20627
|
}
|
|
20618
20628
|
function writeManifest(targetDir, manifest) {
|
|
20619
|
-
writeFileSync4(
|
|
20629
|
+
writeFileSync4(join7(targetDir, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
|
|
20620
20630
|
`);
|
|
20621
20631
|
}
|
|
20622
20632
|
function readBundledVersion(sourceDir) {
|
|
20623
20633
|
try {
|
|
20624
|
-
return readFileSync5(
|
|
20634
|
+
return readFileSync5(join7(sourceDir, "VERSION"), "utf8").trim() || "unknown";
|
|
20625
20635
|
} catch {
|
|
20626
20636
|
return "unknown";
|
|
20627
20637
|
}
|
|
20628
20638
|
}
|
|
20629
20639
|
function skillNames(sourceDir) {
|
|
20630
20640
|
if (!existsSync4(sourceDir)) return [];
|
|
20631
|
-
return readdirSync2(sourceDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => existsSync4(
|
|
20641
|
+
return readdirSync2(sourceDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => existsSync4(join7(sourceDir, name, "SKILL.md"))).sort();
|
|
20632
20642
|
}
|
|
20633
20643
|
function installBundledSkills(input2) {
|
|
20634
20644
|
const result = { installed: [], updated: [], skipped: [], unchanged: [] };
|
|
@@ -20638,8 +20648,8 @@ function installBundledSkills(input2) {
|
|
|
20638
20648
|
const manifest = readManifest(input2.targetDir) ?? { version: version2, skills: {} };
|
|
20639
20649
|
const now = new Date(input2.now ?? Date.now()).toISOString();
|
|
20640
20650
|
for (const name of skillNames(input2.sourceDir)) {
|
|
20641
|
-
const source =
|
|
20642
|
-
const target =
|
|
20651
|
+
const source = join7(input2.sourceDir, name);
|
|
20652
|
+
const target = join7(input2.targetDir, name);
|
|
20643
20653
|
const sourceHash = hashSkillDir(source);
|
|
20644
20654
|
if (!existsSync4(target)) {
|
|
20645
20655
|
cpSync(source, target, { recursive: true });
|
|
@@ -21509,7 +21519,7 @@ function ControlTower() {
|
|
|
21509
21519
|
async function withDialog(open2) {
|
|
21510
21520
|
setDialogOpen(true);
|
|
21511
21521
|
try {
|
|
21512
|
-
await new Promise((
|
|
21522
|
+
await new Promise((resolve2) => setTimeout(resolve2, 0));
|
|
21513
21523
|
return await open2();
|
|
21514
21524
|
} finally {
|
|
21515
21525
|
setDialogOpen(false);
|