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/index.js
CHANGED
|
@@ -5079,7 +5079,7 @@ var recursive = /* @__PURE__ */ new WeakMap();
|
|
|
5079
5079
|
var NONE = 0;
|
|
5080
5080
|
var ASSUMED = 1;
|
|
5081
5081
|
var PROVEN = 2;
|
|
5082
|
-
function isRecursive(inst, stack,
|
|
5082
|
+
function isRecursive(inst, stack, resolve2) {
|
|
5083
5083
|
const cached2 = recursive.get(inst);
|
|
5084
5084
|
if (cached2 !== void 0)
|
|
5085
5085
|
return cached2 ? PROVEN : NONE;
|
|
@@ -5089,7 +5089,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
5089
5089
|
let result = NONE;
|
|
5090
5090
|
const check2 = (child) => {
|
|
5091
5091
|
if (result !== PROVEN && child?._zod) {
|
|
5092
|
-
const answer = isRecursive(child, stack,
|
|
5092
|
+
const answer = isRecursive(child, stack, resolve2);
|
|
5093
5093
|
if (answer > result)
|
|
5094
5094
|
result = answer;
|
|
5095
5095
|
}
|
|
@@ -5100,7 +5100,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
5100
5100
|
const desc = Object.getOwnPropertyDescriptor(sh, key);
|
|
5101
5101
|
if (spread && !desc.enumerable)
|
|
5102
5102
|
continue;
|
|
5103
|
-
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack,
|
|
5103
|
+
const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve2) : NONE;
|
|
5104
5104
|
if (child > answer)
|
|
5105
5105
|
answer = child;
|
|
5106
5106
|
}
|
|
@@ -5164,7 +5164,7 @@ function isRecursive(inst, stack, resolve3) {
|
|
|
5164
5164
|
break;
|
|
5165
5165
|
// `$ZodLazy` caches its inner on the def, so a resolved edge is followed exactly
|
|
5166
5166
|
case "lazy": {
|
|
5167
|
-
const inner = def._cachedInner ?? (
|
|
5167
|
+
const inner = def._cachedInner ?? (resolve2 ? inst._zod.innerType : void 0);
|
|
5168
5168
|
merge2(inner ? isRecursive(inner, stack, false) : ASSUMED);
|
|
5169
5169
|
break;
|
|
5170
5170
|
}
|
|
@@ -19777,7 +19777,7 @@ var MAX_BUFFER = 16 * 1024 * 1024;
|
|
|
19777
19777
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
19778
19778
|
function createRunner(options = {}) {
|
|
19779
19779
|
const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
19780
|
-
return (command, args, options2) => new Promise((
|
|
19780
|
+
return (command, args, options2) => new Promise((resolve2, reject) => {
|
|
19781
19781
|
const child = spawn(command, args, {
|
|
19782
19782
|
cwd: options2?.cwd,
|
|
19783
19783
|
env: process.env,
|
|
@@ -19797,7 +19797,7 @@ function createRunner(options = {}) {
|
|
|
19797
19797
|
if (settled) return;
|
|
19798
19798
|
settled = true;
|
|
19799
19799
|
clearTimeout(timer);
|
|
19800
|
-
|
|
19800
|
+
resolve2(result);
|
|
19801
19801
|
};
|
|
19802
19802
|
const timer = setTimeout(() => {
|
|
19803
19803
|
child.kill("SIGTERM");
|
|
@@ -19843,47 +19843,57 @@ function createRunner(options = {}) {
|
|
|
19843
19843
|
|
|
19844
19844
|
// packages/core/src/paths.ts
|
|
19845
19845
|
import { homedir } from "node:os";
|
|
19846
|
-
import {
|
|
19846
|
+
import { posix, win32 } from "node:path";
|
|
19847
19847
|
var APP_DIR = "opencode-skills-deck";
|
|
19848
|
+
function pathFor(platform) {
|
|
19849
|
+
return platform === "win32" ? win32 : posix;
|
|
19850
|
+
}
|
|
19851
|
+
function styleOf(path) {
|
|
19852
|
+
return /^[A-Za-z]:[\\/]/.test(path) || path.startsWith("\\\\") ? "win32" : "linux";
|
|
19853
|
+
}
|
|
19848
19854
|
function configRootOf(platform, env, home) {
|
|
19849
|
-
|
|
19855
|
+
const path = pathFor(platform);
|
|
19856
|
+
return env.XDG_CONFIG_HOME ?? (platform === "win32" ? env.APPDATA ?? path.join(home, "AppData", "Roaming") : path.join(home, ".config"));
|
|
19850
19857
|
}
|
|
19851
19858
|
function stateRootOf(platform, env, home) {
|
|
19852
|
-
|
|
19859
|
+
const path = pathFor(platform);
|
|
19860
|
+
return env.XDG_STATE_HOME ?? (platform === "win32" ? env.LOCALAPPDATA ?? path.join(home, "AppData", "Local") : path.join(home, ".local", "state"));
|
|
19853
19861
|
}
|
|
19854
19862
|
function opencodeConfigDir(options = {}) {
|
|
19855
19863
|
const platform = options.platform ?? process.platform;
|
|
19856
19864
|
const env = options.env ?? process.env;
|
|
19857
19865
|
const home = options.home ?? homedir();
|
|
19858
|
-
return
|
|
19866
|
+
return pathFor(platform).join(configRootOf(platform, env, home), "opencode");
|
|
19859
19867
|
}
|
|
19860
19868
|
function opencodeSkillsDir(options = {}) {
|
|
19861
|
-
return
|
|
19869
|
+
return pathFor(options.platform ?? process.platform).join(opencodeConfigDir(options), "skills");
|
|
19862
19870
|
}
|
|
19863
19871
|
function repoSessionSlug(repo) {
|
|
19864
19872
|
return repo.replace(/[^a-zA-Z0-9._-]+/g, "__");
|
|
19865
19873
|
}
|
|
19866
19874
|
function sessionsDirFor(paths, repo) {
|
|
19867
|
-
|
|
19875
|
+
if (!repo) return paths.sessionsDir;
|
|
19876
|
+
return pathFor(styleOf(paths.sessionsDir)).join(paths.sessionsDir, repoSessionSlug(repo));
|
|
19868
19877
|
}
|
|
19869
19878
|
function resolvePaths(options = {}) {
|
|
19870
19879
|
const platform = options.platform ?? process.platform;
|
|
19871
19880
|
const env = options.env ?? process.env;
|
|
19872
19881
|
const home = options.home ?? homedir();
|
|
19882
|
+
const path = pathFor(platform);
|
|
19873
19883
|
const configRoot = configRootOf(platform, env, home);
|
|
19874
19884
|
const stateRoot = stateRootOf(platform, env, home);
|
|
19875
|
-
const configDir =
|
|
19876
|
-
const stateDir =
|
|
19885
|
+
const configDir = path.join(configRoot, APP_DIR);
|
|
19886
|
+
const stateDir = path.join(stateRoot, APP_DIR);
|
|
19877
19887
|
return {
|
|
19878
19888
|
configDir,
|
|
19879
19889
|
stateDir,
|
|
19880
|
-
sessionsDir:
|
|
19881
|
-
issueCacheDir:
|
|
19890
|
+
sessionsDir: path.join(stateDir, "sessions"),
|
|
19891
|
+
issueCacheDir: path.join(stateDir, "issues")
|
|
19882
19892
|
};
|
|
19883
19893
|
}
|
|
19884
19894
|
|
|
19885
19895
|
// packages/core/src/repo.ts
|
|
19886
|
-
import {
|
|
19896
|
+
import { join as join2, posix as posix2, win32 as win322 } from "node:path";
|
|
19887
19897
|
var REMOTE_PATTERNS = [
|
|
19888
19898
|
/^git@[^:]+:(?<owner>[^/]+)\/(?<name>[^/]+?)(?:\.git)?$/,
|
|
19889
19899
|
/^(?:ssh|git|https?):\/\/(?:[^@/]+@)?[^/]+\/(?<owner>[^/]+)\/(?<name>[^/]+?)(?:\.git)?\/?$/
|
|
@@ -19908,7 +19918,10 @@ function branchName(issueNumber, title) {
|
|
|
19908
19918
|
return slug ? `issue/${issueNumber}-${slug}` : `issue/${issueNumber}`;
|
|
19909
19919
|
}
|
|
19910
19920
|
function issueWorktreePath(repoRoot, issueNumber) {
|
|
19911
|
-
return
|
|
19921
|
+
return join2(repoRoot, ".worktrees", `issue-${issueNumber}`);
|
|
19922
|
+
}
|
|
19923
|
+
function pathStyleOf(path) {
|
|
19924
|
+
return /^[A-Za-z]:[\\/]/.test(path) || path.startsWith("\\\\") ? win322 : posix2;
|
|
19912
19925
|
}
|
|
19913
19926
|
async function resolveRepoRoot(directory, runner) {
|
|
19914
19927
|
let worktreeRoot;
|
|
@@ -19924,14 +19937,14 @@ async function resolveRepoRoot(directory, runner) {
|
|
|
19924
19937
|
cwd: worktreeRoot
|
|
19925
19938
|
});
|
|
19926
19939
|
const common = stdout.trim();
|
|
19927
|
-
if (common.endsWith(".git")) return dirname(common);
|
|
19940
|
+
if (common.endsWith(".git")) return pathStyleOf(common).dirname(common);
|
|
19928
19941
|
} catch {
|
|
19929
19942
|
try {
|
|
19930
19943
|
const { stdout } = await runner("git", ["rev-parse", "--git-common-dir"], {
|
|
19931
19944
|
cwd: worktreeRoot
|
|
19932
19945
|
});
|
|
19933
|
-
const common = resolve(worktreeRoot, stdout.trim());
|
|
19934
|
-
if (common.endsWith(".git")) return dirname(common);
|
|
19946
|
+
const common = pathStyleOf(worktreeRoot).resolve(worktreeRoot, stdout.trim());
|
|
19947
|
+
if (common.endsWith(".git")) return pathStyleOf(common).dirname(common);
|
|
19935
19948
|
} catch {
|
|
19936
19949
|
}
|
|
19937
19950
|
}
|
|
@@ -20014,9 +20027,9 @@ import {
|
|
|
20014
20027
|
watch,
|
|
20015
20028
|
writeFileSync
|
|
20016
20029
|
} from "node:fs";
|
|
20017
|
-
import { join as
|
|
20030
|
+
import { join as join3 } from "node:path";
|
|
20018
20031
|
function sessionFilePath(dir, key) {
|
|
20019
|
-
return
|
|
20032
|
+
return join3(dir, `${key}.json`);
|
|
20020
20033
|
}
|
|
20021
20034
|
function readSession(dir, key) {
|
|
20022
20035
|
try {
|
|
@@ -20049,7 +20062,7 @@ var SESSION_RETENTION_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
|
20049
20062
|
|
|
20050
20063
|
// packages/core/src/worktree.ts
|
|
20051
20064
|
import { existsSync as existsSync2, readFileSync as readFileSync3, realpathSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
20052
|
-
import { join as
|
|
20065
|
+
import { join as join4, resolve, sep } from "node:path";
|
|
20053
20066
|
async function defaultBranch(input2) {
|
|
20054
20067
|
if (input2.configured) return input2.configured;
|
|
20055
20068
|
try {
|
|
@@ -20066,7 +20079,7 @@ async function ensureWorktreesExcluded(input2) {
|
|
|
20066
20079
|
const { stdout } = await input2.runner("git", ["rev-parse", "--git-path", "info/exclude"], {
|
|
20067
20080
|
cwd: input2.repoRoot
|
|
20068
20081
|
});
|
|
20069
|
-
const path =
|
|
20082
|
+
const path = join4(input2.repoRoot, stdout.trim());
|
|
20070
20083
|
const existing = existsSync2(path) ? readFileSync3(path, "utf8") : "";
|
|
20071
20084
|
if (existing.split("\n").some((line) => line.trim() === ".worktrees/")) return;
|
|
20072
20085
|
const suffix = existing.endsWith("\n") || existing === "" ? "" : "\n";
|
|
@@ -20109,7 +20122,7 @@ function normalized(path) {
|
|
|
20109
20122
|
try {
|
|
20110
20123
|
return realpathSync(path).replace(/\/+$/, "");
|
|
20111
20124
|
} catch {
|
|
20112
|
-
return
|
|
20125
|
+
return resolve(path).replace(/\/+$/, "");
|
|
20113
20126
|
}
|
|
20114
20127
|
}
|
|
20115
20128
|
async function branchExists(input2) {
|
|
@@ -20159,14 +20172,14 @@ async function removeWorktree(input2) {
|
|
|
20159
20172
|
return { removed: true };
|
|
20160
20173
|
}
|
|
20161
20174
|
function worktreeIssueNumber(directory) {
|
|
20162
|
-
const name = normalized(directory).split(
|
|
20175
|
+
const name = normalized(directory).split(/[\\/]/).at(-1) ?? "";
|
|
20163
20176
|
const match = /^issue-(\d+)$/.exec(name);
|
|
20164
20177
|
if (!match) return null;
|
|
20165
20178
|
const value = Number(match[1]);
|
|
20166
20179
|
return Number.isSafeInteger(value) && value > 0 ? value : null;
|
|
20167
20180
|
}
|
|
20168
20181
|
function isInsideWorktrees(repoRoot, directory) {
|
|
20169
|
-
const root = normalized(
|
|
20182
|
+
const root = normalized(join4(repoRoot, ".worktrees"));
|
|
20170
20183
|
return normalized(directory).startsWith(`${root}${sep}`);
|
|
20171
20184
|
}
|
|
20172
20185
|
async function readWorktreeStatus(input2) {
|
|
@@ -20228,7 +20241,7 @@ function selectOrphanWorktrees(worktrees, openIssueNumbers) {
|
|
|
20228
20241
|
|
|
20229
20242
|
// packages/core/src/issue.ts
|
|
20230
20243
|
import { mkdirSync as mkdirSync2, readFileSync as readFileSync4, renameSync as renameSync2, rmSync as rmSync2, writeFileSync as writeFileSync3 } from "node:fs";
|
|
20231
|
-
import { dirname
|
|
20244
|
+
import { dirname, join as join5 } from "node:path";
|
|
20232
20245
|
var SUMMARY_HEADING = /summary|要約|概要/i;
|
|
20233
20246
|
var CRITERIA_HEADING = /acceptance criteria|受け入れ基準|完了条件|acceptance/i;
|
|
20234
20247
|
var BULLET = /^\s*(?:[-*+]|\d+\.)\s+(?:\[[ xX]\]\s*)?(.+)$/;
|
|
@@ -20286,7 +20299,7 @@ async function fetchIssues(input2) {
|
|
|
20286
20299
|
return rows.map(toIssue).sort((left, right) => left.number - right.number);
|
|
20287
20300
|
}
|
|
20288
20301
|
function issueCachePath(paths, repo) {
|
|
20289
|
-
return
|
|
20302
|
+
return join5(paths.issueCacheDir, `${repo.owner}__${repo.name}.json`);
|
|
20290
20303
|
}
|
|
20291
20304
|
function normalizeCachedIssue(value) {
|
|
20292
20305
|
if (!value || typeof value !== "object") return null;
|
|
@@ -20324,7 +20337,7 @@ function readIssueCache(path) {
|
|
|
20324
20337
|
}
|
|
20325
20338
|
}
|
|
20326
20339
|
function writeIssueCache(path, cache) {
|
|
20327
|
-
mkdirSync2(
|
|
20340
|
+
mkdirSync2(dirname(path), { recursive: true });
|
|
20328
20341
|
const temporary = `${path}.${process.pid}.${Date.now()}.tmp`;
|
|
20329
20342
|
writeFileSync3(temporary, `${JSON.stringify(cache, null, 2)}
|
|
20330
20343
|
`);
|
|
@@ -20405,7 +20418,7 @@ async function loadIssuesResult(input2) {
|
|
|
20405
20418
|
// packages/core/src/skills.ts
|
|
20406
20419
|
import { createHash } from "node:crypto";
|
|
20407
20420
|
import { cpSync, existsSync as existsSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync5, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
20408
|
-
import { join as
|
|
20421
|
+
import { join as join6, relative, sep as sep2 } from "node:path";
|
|
20409
20422
|
var MANIFEST_NAME = ".skills-deck.json";
|
|
20410
20423
|
function hashSkillDir(dir) {
|
|
20411
20424
|
const hash2 = createHash("sha256");
|
|
@@ -20414,7 +20427,7 @@ function hashSkillDir(dir) {
|
|
|
20414
20427
|
(left, right) => left.name.localeCompare(right.name)
|
|
20415
20428
|
);
|
|
20416
20429
|
for (const entry of entries) {
|
|
20417
|
-
const absolute =
|
|
20430
|
+
const absolute = join6(current, entry.name);
|
|
20418
20431
|
const key = relative(dir, absolute).split(sep2).join("/");
|
|
20419
20432
|
if (entry.isDirectory()) {
|
|
20420
20433
|
hash2.update(`d:${key}
|
|
@@ -20433,7 +20446,7 @@ function hashSkillDir(dir) {
|
|
|
20433
20446
|
}
|
|
20434
20447
|
function readManifest(targetDir) {
|
|
20435
20448
|
try {
|
|
20436
|
-
const parsed = JSON.parse(readFileSync5(
|
|
20449
|
+
const parsed = JSON.parse(readFileSync5(join6(targetDir, MANIFEST_NAME), "utf8"));
|
|
20437
20450
|
if (!parsed || typeof parsed.version !== "string" || typeof parsed.skills !== "object") return null;
|
|
20438
20451
|
return parsed;
|
|
20439
20452
|
} catch {
|
|
@@ -20441,19 +20454,19 @@ function readManifest(targetDir) {
|
|
|
20441
20454
|
}
|
|
20442
20455
|
}
|
|
20443
20456
|
function writeManifest(targetDir, manifest) {
|
|
20444
|
-
writeFileSync4(
|
|
20457
|
+
writeFileSync4(join6(targetDir, MANIFEST_NAME), `${JSON.stringify(manifest, null, 2)}
|
|
20445
20458
|
`);
|
|
20446
20459
|
}
|
|
20447
20460
|
function readBundledVersion(sourceDir) {
|
|
20448
20461
|
try {
|
|
20449
|
-
return readFileSync5(
|
|
20462
|
+
return readFileSync5(join6(sourceDir, "VERSION"), "utf8").trim() || "unknown";
|
|
20450
20463
|
} catch {
|
|
20451
20464
|
return "unknown";
|
|
20452
20465
|
}
|
|
20453
20466
|
}
|
|
20454
20467
|
function skillNames(sourceDir) {
|
|
20455
20468
|
if (!existsSync3(sourceDir)) return [];
|
|
20456
|
-
return readdirSync2(sourceDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => existsSync3(
|
|
20469
|
+
return readdirSync2(sourceDir, { withFileTypes: true }).filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => existsSync3(join6(sourceDir, name, "SKILL.md"))).sort();
|
|
20457
20470
|
}
|
|
20458
20471
|
function bundledSkillNames(sourceDir) {
|
|
20459
20472
|
return skillNames(sourceDir);
|
|
@@ -20466,8 +20479,8 @@ function installBundledSkills(input2) {
|
|
|
20466
20479
|
const manifest = readManifest(input2.targetDir) ?? { version: version2, skills: {} };
|
|
20467
20480
|
const now = new Date(input2.now ?? Date.now()).toISOString();
|
|
20468
20481
|
for (const name of skillNames(input2.sourceDir)) {
|
|
20469
|
-
const source =
|
|
20470
|
-
const target =
|
|
20482
|
+
const source = join6(input2.sourceDir, name);
|
|
20483
|
+
const target = join6(input2.targetDir, name);
|
|
20471
20484
|
const sourceHash = hashSkillDir(source);
|
|
20472
20485
|
if (!existsSync3(target)) {
|
|
20473
20486
|
cpSync(source, target, { recursive: true });
|