oh-my-design-cli 0.1.0
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/LICENSE +21 -0
- package/README.ja.md +145 -0
- package/README.ko.md +245 -0
- package/README.md +245 -0
- package/README.zh-TW.md +145 -0
- package/data/reference-tags.md +104 -0
- package/data/synonyms.json +79 -0
- package/data/vocabulary.json +516 -0
- package/dist/bin/oh-my-design.js +858 -0
- package/dist/bin/oh-my-design.js.map +1 -0
- package/dist/chunk-6YNSV3VY.js +35 -0
- package/dist/chunk-6YNSV3VY.js.map +1 -0
- package/dist/chunk-MHFYGZSO.js +337 -0
- package/dist/chunk-MHFYGZSO.js.map +1 -0
- package/dist/chunk-N2JG6N4Q.js +264 -0
- package/dist/chunk-N2JG6N4Q.js.map +1 -0
- package/dist/chunk-OOQQEUGX.js +46 -0
- package/dist/chunk-OOQQEUGX.js.map +1 -0
- package/dist/chunk-OR5DHENY.js +250 -0
- package/dist/chunk-OR5DHENY.js.map +1 -0
- package/dist/customizer-CM76752R.js +8 -0
- package/dist/customizer-CM76752R.js.map +1 -0
- package/dist/index.d.ts +559 -0
- package/dist/index.js +3113 -0
- package/dist/index.js.map +1 -0
- package/dist/init-STACB7E5.js +635 -0
- package/dist/init-STACB7E5.js.map +1 -0
- package/dist/install-skills-CM6VXFZJ.js +152 -0
- package/dist/install-skills-CM6VXFZJ.js.map +1 -0
- package/dist/learn-33LHKEJA.js +140 -0
- package/dist/learn-33LHKEJA.js.map +1 -0
- package/dist/reference-YMNAOXJQ.js +47 -0
- package/dist/reference-YMNAOXJQ.js.map +1 -0
- package/dist/reference-parser-TM3CJPNE.js +10 -0
- package/dist/reference-parser-TM3CJPNE.js.map +1 -0
- package/dist/remember-UAFA5B2O.js +78 -0
- package/dist/remember-UAFA5B2O.js.map +1 -0
- package/dist/sync-P7X4S2DK.js +404 -0
- package/dist/sync-P7X4S2DK.js.map +1 -0
- package/dist/templates/templates/design-md.hbs +44 -0
- package/dist/templates/templates/partials/agent-prompt-guide.hbs +28 -0
- package/dist/templates/templates/partials/color-palette.hbs +49 -0
- package/dist/templates/templates/partials/component-stylings.hbs +28 -0
- package/dist/templates/templates/partials/depth-elevation.hbs +31 -0
- package/dist/templates/templates/partials/dos-donts.hbs +13 -0
- package/dist/templates/templates/partials/layout.hbs +30 -0
- package/dist/templates/templates/partials/responsive.hbs +25 -0
- package/dist/templates/templates/partials/shadcn-tokens.hbs +64 -0
- package/dist/templates/templates/partials/typography.hbs +43 -0
- package/dist/templates/templates/partials/visual-theme.hbs +26 -0
- package/package.json +68 -0
- package/references/Claude-Design-Sys-Prompt.txt +421 -0
- package/references/airbnb/DESIGN.md +427 -0
- package/references/airbnb/README.md +23 -0
- package/references/airbnb/preview-dark.html +234 -0
- package/references/airbnb/preview.html +233 -0
- package/references/airtable/DESIGN.md +107 -0
- package/references/airtable/README.md +23 -0
- package/references/airtable/preview-dark.html +165 -0
- package/references/airtable/preview.html +164 -0
- package/references/apple/DESIGN.md +496 -0
- package/references/apple/README.md +24 -0
- package/references/apple/preview-dark.html +420 -0
- package/references/apple/preview.html +414 -0
- package/references/baemin/DESIGN.md +260 -0
- package/references/baemin/README.md +19 -0
- package/references/bmw/DESIGN.md +180 -0
- package/references/bmw/README.md +23 -0
- package/references/bmw/preview-dark.html +211 -0
- package/references/bmw/preview.html +210 -0
- package/references/cal/DESIGN.md +259 -0
- package/references/cal/README.md +23 -0
- package/references/cal/preview-dark.html +449 -0
- package/references/cal/preview.html +575 -0
- package/references/claude/DESIGN.md +455 -0
- package/references/claude/README.md +24 -0
- package/references/claude/preview-dark.html +803 -0
- package/references/claude/preview.html +826 -0
- package/references/clay/DESIGN.md +304 -0
- package/references/clay/README.md +23 -0
- package/references/clay/preview-dark.html +316 -0
- package/references/clay/preview.html +315 -0
- package/references/clickhouse/DESIGN.md +281 -0
- package/references/clickhouse/README.md +24 -0
- package/references/clickhouse/preview-dark.html +834 -0
- package/references/clickhouse/preview.html +786 -0
- package/references/cohere/DESIGN.md +266 -0
- package/references/cohere/README.md +24 -0
- package/references/cohere/preview-dark.html +803 -0
- package/references/cohere/preview.html +807 -0
- package/references/coinbase/DESIGN.md +129 -0
- package/references/coinbase/README.md +23 -0
- package/references/coinbase/preview-dark.html +164 -0
- package/references/coinbase/preview.html +163 -0
- package/references/composio/DESIGN.md +307 -0
- package/references/composio/README.md +24 -0
- package/references/composio/preview-dark.html +958 -0
- package/references/composio/preview.html +933 -0
- package/references/cursor/DESIGN.md +322 -0
- package/references/cursor/README.md +24 -0
- package/references/cursor/preview-dark.html +393 -0
- package/references/cursor/preview.html +383 -0
- package/references/dcard/DESIGN.md +302 -0
- package/references/dcard/README.md +12 -0
- package/references/dcard/_research/forum-1440px.png +0 -0
- package/references/dcard/_research.md +77 -0
- package/references/elevenlabs/DESIGN.md +265 -0
- package/references/elevenlabs/README.md +23 -0
- package/references/elevenlabs/preview-dark.html +252 -0
- package/references/elevenlabs/preview.html +251 -0
- package/references/expo/DESIGN.md +281 -0
- package/references/expo/README.md +24 -0
- package/references/expo/preview-dark.html +533 -0
- package/references/expo/preview.html +533 -0
- package/references/ferrari/DESIGN.md +314 -0
- package/references/ferrari/README.md +23 -0
- package/references/ferrari/preview-dark.html +1162 -0
- package/references/ferrari/preview.html +1122 -0
- package/references/figma/DESIGN.md +399 -0
- package/references/figma/README.md +24 -0
- package/references/figma/preview-dark.html +822 -0
- package/references/figma/preview.html +832 -0
- package/references/framer/DESIGN.md +246 -0
- package/references/framer/README.md +23 -0
- package/references/framer/preview-dark.html +902 -0
- package/references/framer/preview.html +883 -0
- package/references/freee/DESIGN.md +308 -0
- package/references/freee/README.md +12 -0
- package/references/freee/_research/vibes-storybook-1440px.png +0 -0
- package/references/freee/_research.md +77 -0
- package/references/hashicorp/DESIGN.md +278 -0
- package/references/hashicorp/README.md +24 -0
- package/references/hashicorp/preview-dark.html +1202 -0
- package/references/hashicorp/preview.html +1193 -0
- package/references/ibm/DESIGN.md +332 -0
- package/references/ibm/README.md +24 -0
- package/references/ibm/preview-dark.html +443 -0
- package/references/ibm/preview.html +428 -0
- package/references/intercom/DESIGN.md +146 -0
- package/references/intercom/README.md +23 -0
- package/references/intercom/preview-dark.html +185 -0
- package/references/intercom/preview.html +184 -0
- package/references/kakao/DESIGN.md +261 -0
- package/references/kakao/README.md +18 -0
- package/references/karrot/DESIGN.md +252 -0
- package/references/karrot/README.md +18 -0
- package/references/kraken/DESIGN.md +146 -0
- package/references/kraken/README.md +23 -0
- package/references/kraken/preview-dark.html +169 -0
- package/references/kraken/preview.html +168 -0
- package/references/lamborghini/DESIGN.md +288 -0
- package/references/lamborghini/README.md +23 -0
- package/references/lamborghini/preview-dark.html +303 -0
- package/references/lamborghini/preview.html +381 -0
- package/references/line/DESIGN.md +375 -0
- package/references/line/README.md +12 -0
- package/references/line/_research/home-1440px.png +0 -0
- package/references/line/_research.md +65 -0
- package/references/linear.app/DESIGN.md +526 -0
- package/references/linear.app/README.md +24 -0
- package/references/linear.app/preview-dark.html +383 -0
- package/references/linear.app/preview.html +373 -0
- package/references/lovable/DESIGN.md +298 -0
- package/references/lovable/README.md +24 -0
- package/references/lovable/preview-dark.html +349 -0
- package/references/lovable/preview.html +348 -0
- package/references/mercari/DESIGN.md +294 -0
- package/references/mercari/README.md +12 -0
- package/references/mercari/_research/home-1440px.png +0 -0
- package/references/mercari/_research.md +77 -0
- package/references/minimax/DESIGN.md +257 -0
- package/references/minimax/README.md +24 -0
- package/references/minimax/preview-dark.html +1262 -0
- package/references/minimax/preview.html +1248 -0
- package/references/mintlify/DESIGN.md +341 -0
- package/references/mintlify/README.md +24 -0
- package/references/mintlify/preview-dark.html +409 -0
- package/references/mintlify/preview.html +398 -0
- package/references/miro/DESIGN.md +108 -0
- package/references/miro/README.md +23 -0
- package/references/miro/preview-dark.html +174 -0
- package/references/miro/preview.html +173 -0
- package/references/mistral.ai/DESIGN.md +261 -0
- package/references/mistral.ai/README.md +24 -0
- package/references/mistral.ai/preview-dark.html +806 -0
- package/references/mistral.ai/preview.html +805 -0
- package/references/mongodb/DESIGN.md +266 -0
- package/references/mongodb/README.md +23 -0
- package/references/mongodb/preview-dark.html +260 -0
- package/references/mongodb/preview.html +259 -0
- package/references/notion/DESIGN.md +492 -0
- package/references/notion/README.md +24 -0
- package/references/notion/preview-dark.html +372 -0
- package/references/notion/preview.html +364 -0
- package/references/nvidia/DESIGN.md +308 -0
- package/references/nvidia/README.md +24 -0
- package/references/nvidia/preview-dark.html +374 -0
- package/references/nvidia/preview.html +366 -0
- package/references/ollama/DESIGN.md +267 -0
- package/references/ollama/README.md +24 -0
- package/references/ollama/preview-dark.html +678 -0
- package/references/ollama/preview.html +678 -0
- package/references/opencode.ai/DESIGN.md +295 -0
- package/references/opencode.ai/README.md +24 -0
- package/references/opencode.ai/preview-dark.html +366 -0
- package/references/opencode.ai/preview.html +357 -0
- package/references/pinkoi/DESIGN.md +309 -0
- package/references/pinkoi/README.md +12 -0
- package/references/pinkoi/_research/browse-1440px.png +0 -0
- package/references/pinkoi/_research.md +115 -0
- package/references/pinterest/DESIGN.md +230 -0
- package/references/pinterest/README.md +23 -0
- package/references/pinterest/preview-dark.html +233 -0
- package/references/pinterest/preview.html +232 -0
- package/references/posthog/DESIGN.md +256 -0
- package/references/posthog/README.md +23 -0
- package/references/posthog/preview-dark.html +699 -0
- package/references/posthog/preview.html +749 -0
- package/references/raycast/DESIGN.md +268 -0
- package/references/raycast/README.md +23 -0
- package/references/raycast/preview-dark.html +606 -0
- package/references/raycast/preview.html +688 -0
- package/references/renault/DESIGN.md +311 -0
- package/references/renault/README.md +23 -0
- package/references/renault/preview-dark.html +406 -0
- package/references/renault/preview.html +606 -0
- package/references/replicate/DESIGN.md +261 -0
- package/references/replicate/README.md +24 -0
- package/references/replicate/preview-dark.html +828 -0
- package/references/replicate/preview.html +831 -0
- package/references/resend/DESIGN.md +303 -0
- package/references/resend/README.md +23 -0
- package/references/resend/preview-dark.html +355 -0
- package/references/resend/preview.html +354 -0
- package/references/revolut/DESIGN.md +185 -0
- package/references/revolut/README.md +23 -0
- package/references/revolut/preview-dark.html +234 -0
- package/references/revolut/preview.html +233 -0
- package/references/runwayml/DESIGN.md +244 -0
- package/references/runwayml/README.md +24 -0
- package/references/runwayml/preview-dark.html +664 -0
- package/references/runwayml/preview.html +665 -0
- package/references/sanity/DESIGN.md +357 -0
- package/references/sanity/README.md +24 -0
- package/references/sanity/preview-dark.html +990 -0
- package/references/sanity/preview.html +1135 -0
- package/references/sentry/DESIGN.md +262 -0
- package/references/sentry/README.md +24 -0
- package/references/sentry/preview-dark.html +626 -0
- package/references/sentry/preview.html +951 -0
- package/references/spacex/DESIGN.md +205 -0
- package/references/spacex/README.md +23 -0
- package/references/spacex/preview-dark.html +221 -0
- package/references/spacex/preview.html +220 -0
- package/references/spotify/DESIGN.md +246 -0
- package/references/spotify/README.md +23 -0
- package/references/spotify/preview-dark.html +231 -0
- package/references/spotify/preview.html +230 -0
- package/references/stripe/DESIGN.md +473 -0
- package/references/stripe/README.md +24 -0
- package/references/stripe/preview-dark.html +428 -0
- package/references/stripe/preview.html +419 -0
- package/references/supabase/DESIGN.md +255 -0
- package/references/supabase/README.md +24 -0
- package/references/supabase/preview-dark.html +977 -0
- package/references/supabase/preview.html +955 -0
- package/references/superhuman/DESIGN.md +252 -0
- package/references/superhuman/README.md +23 -0
- package/references/superhuman/preview-dark.html +973 -0
- package/references/superhuman/preview.html +951 -0
- package/references/tesla/DESIGN.md +286 -0
- package/references/tesla/README.md +23 -0
- package/references/tesla/preview-dark.html +947 -0
- package/references/tesla/preview.html +925 -0
- package/references/together.ai/DESIGN.md +263 -0
- package/references/together.ai/README.md +24 -0
- package/references/together.ai/preview-dark.html +892 -0
- package/references/together.ai/preview.html +897 -0
- package/references/toss/DESIGN.md +387 -0
- package/references/toss/README.md +19 -0
- package/references/uber/DESIGN.md +295 -0
- package/references/uber/README.md +24 -0
- package/references/uber/preview-dark.html +1120 -0
- package/references/uber/preview.html +1119 -0
- package/references/vercel/DESIGN.md +456 -0
- package/references/vercel/README.md +24 -0
- package/references/vercel/preview-dark.html +368 -0
- package/references/vercel/preview.html +367 -0
- package/references/voltagent/DESIGN.md +323 -0
- package/references/voltagent/README.md +24 -0
- package/references/voltagent/preview-dark.html +487 -0
- package/references/voltagent/preview.html +766 -0
- package/references/warp/DESIGN.md +253 -0
- package/references/warp/README.md +23 -0
- package/references/warp/preview-dark.html +500 -0
- package/references/warp/preview.html +533 -0
- package/references/webflow/DESIGN.md +109 -0
- package/references/webflow/README.md +23 -0
- package/references/webflow/preview-dark.html +147 -0
- package/references/webflow/preview.html +146 -0
- package/references/wise/DESIGN.md +173 -0
- package/references/wise/README.md +23 -0
- package/references/wise/preview-dark.html +230 -0
- package/references/wise/preview.html +229 -0
- package/references/x.ai/DESIGN.md +267 -0
- package/references/x.ai/README.md +24 -0
- package/references/x.ai/preview-dark.html +356 -0
- package/references/x.ai/preview.html +407 -0
- package/references/zapier/DESIGN.md +328 -0
- package/references/zapier/README.md +24 -0
- package/references/zapier/preview-dark.html +380 -0
- package/references/zapier/preview.html +372 -0
- package/skills/omd-apply/SKILL.md +85 -0
- package/skills/omd-init/SKILL.md +167 -0
- package/skills/omd-learn/SKILL.md +81 -0
- package/skills/omd-remember/SKILL.md +44 -0
- package/skills/omd-sync/SKILL.md +38 -0
|
@@ -0,0 +1,635 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/cli/init.ts
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import {
|
|
7
|
+
writeFileSync as writeFileSync2,
|
|
8
|
+
readFileSync as readFileSync4,
|
|
9
|
+
mkdirSync as mkdirSync2,
|
|
10
|
+
existsSync as existsSync2
|
|
11
|
+
} from "fs";
|
|
12
|
+
import { join as join4, relative, dirname as dirname4 } from "path";
|
|
13
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
14
|
+
|
|
15
|
+
// src/core/vocabulary.ts
|
|
16
|
+
import { readFileSync } from "fs";
|
|
17
|
+
import { fileURLToPath } from "url";
|
|
18
|
+
import { dirname, join } from "path";
|
|
19
|
+
var cachedVocab = null;
|
|
20
|
+
var cachedSynonyms = null;
|
|
21
|
+
function dataDir() {
|
|
22
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const candidates = [
|
|
24
|
+
join(here, "..", "data"),
|
|
25
|
+
join(here, "..", "..", "data")
|
|
26
|
+
];
|
|
27
|
+
for (const c of candidates) {
|
|
28
|
+
try {
|
|
29
|
+
readFileSync(join(c, "vocabulary.json"), "utf8");
|
|
30
|
+
return c;
|
|
31
|
+
} catch {
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
throw new Error("data/vocabulary.json not found relative to " + here);
|
|
35
|
+
}
|
|
36
|
+
function loadVocabulary() {
|
|
37
|
+
if (cachedVocab) return cachedVocab;
|
|
38
|
+
const path = join(dataDir(), "vocabulary.json");
|
|
39
|
+
cachedVocab = JSON.parse(readFileSync(path, "utf8"));
|
|
40
|
+
return cachedVocab;
|
|
41
|
+
}
|
|
42
|
+
function loadSynonyms() {
|
|
43
|
+
if (cachedSynonyms) return cachedSynonyms;
|
|
44
|
+
const path = join(dataDir(), "synonyms.json");
|
|
45
|
+
cachedSynonyms = JSON.parse(readFileSync(path, "utf8"));
|
|
46
|
+
return cachedSynonyms;
|
|
47
|
+
}
|
|
48
|
+
var MODIFIER_RE = /\b(primarily|mostly|slightly|very|not)\s+([a-z][a-z-]*)/gi;
|
|
49
|
+
function tokenize(description) {
|
|
50
|
+
return description.toLowerCase().split(/[^a-z-]+/).filter(Boolean);
|
|
51
|
+
}
|
|
52
|
+
function extractKeywords(description) {
|
|
53
|
+
const vocab = loadVocabulary();
|
|
54
|
+
const { map: synonyms } = loadSynonyms();
|
|
55
|
+
const lower = description.toLowerCase();
|
|
56
|
+
const modifierOverrides = /* @__PURE__ */ new Map();
|
|
57
|
+
let match;
|
|
58
|
+
const modRe = new RegExp(MODIFIER_RE.source, MODIFIER_RE.flags);
|
|
59
|
+
while ((match = modRe.exec(lower)) !== null) {
|
|
60
|
+
const modName = match[1];
|
|
61
|
+
const target = match[2];
|
|
62
|
+
const value = vocab.modifiers[modName];
|
|
63
|
+
if (value !== void 0) modifierOverrides.set(target, value);
|
|
64
|
+
}
|
|
65
|
+
const tokens = tokenize(description);
|
|
66
|
+
const seen = /* @__PURE__ */ new Set();
|
|
67
|
+
const results = [];
|
|
68
|
+
for (const token of tokens) {
|
|
69
|
+
if (seen.has(token)) continue;
|
|
70
|
+
seen.add(token);
|
|
71
|
+
if (vocab.keywords[token]) {
|
|
72
|
+
results.push({
|
|
73
|
+
keyword: token,
|
|
74
|
+
modifier: modifierOverrides.get(token) ?? 1,
|
|
75
|
+
matchedAs: "direct"
|
|
76
|
+
});
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const syn = synonyms[token];
|
|
80
|
+
if (syn && vocab.keywords[syn]) {
|
|
81
|
+
results.push({
|
|
82
|
+
keyword: syn,
|
|
83
|
+
modifier: modifierOverrides.get(token) ?? 1,
|
|
84
|
+
matchedAs: "synonym",
|
|
85
|
+
synonymSource: token
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
return results;
|
|
90
|
+
}
|
|
91
|
+
function resolveConflicts(keywords) {
|
|
92
|
+
const vocab = loadVocabulary();
|
|
93
|
+
const kept = [];
|
|
94
|
+
const dropped = [];
|
|
95
|
+
for (const kw of keywords) {
|
|
96
|
+
const spec = vocab.keywords[kw.keyword];
|
|
97
|
+
if (!spec) continue;
|
|
98
|
+
const conflictingHere = keywords.filter(
|
|
99
|
+
(other) => other.keyword !== kw.keyword && spec.conflicts_with.includes(other.keyword)
|
|
100
|
+
);
|
|
101
|
+
if (conflictingHere.length === 0) {
|
|
102
|
+
kept.push(kw);
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
const strictlyHigherThanAll = conflictingHere.every(
|
|
106
|
+
(c) => kw.modifier > c.modifier + 1e-9
|
|
107
|
+
);
|
|
108
|
+
if (strictlyHigherThanAll) {
|
|
109
|
+
kept.push(kw);
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
dropped.push({
|
|
113
|
+
keyword: kw.keyword,
|
|
114
|
+
reason: `conflicts with ${conflictingHere.map((c) => c.keyword).join(",")}`
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
const warnings = [];
|
|
118
|
+
const keptSet = new Set(kept.map((k) => k.keyword));
|
|
119
|
+
const warned = /* @__PURE__ */ new Set();
|
|
120
|
+
for (const kw of keywords) {
|
|
121
|
+
const spec = vocab.keywords[kw.keyword];
|
|
122
|
+
if (!spec) continue;
|
|
123
|
+
const conflictingHere = keywords.filter(
|
|
124
|
+
(other) => other.keyword !== kw.keyword && spec.conflicts_with.includes(other.keyword)
|
|
125
|
+
);
|
|
126
|
+
if (conflictingHere.length === 0) continue;
|
|
127
|
+
const groupKeys = [kw.keyword, ...conflictingHere.map((c) => c.keyword)];
|
|
128
|
+
const groupHasWinner = groupKeys.some((k) => keptSet.has(k));
|
|
129
|
+
if (groupHasWinner) continue;
|
|
130
|
+
const pairKey = [...new Set(groupKeys)].sort().join(",");
|
|
131
|
+
if (warned.has(pairKey)) continue;
|
|
132
|
+
warned.add(pairKey);
|
|
133
|
+
warnings.push(
|
|
134
|
+
`${kw.keyword} \u2194 ${conflictingHere.map((c) => c.keyword).join(",")}: use "primarily <kw>" or "very <kw>" to pick a winner`
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
return { kept, dropped, warnings };
|
|
138
|
+
}
|
|
139
|
+
function clamp(value, lo, hi) {
|
|
140
|
+
return Math.max(lo, Math.min(hi, value));
|
|
141
|
+
}
|
|
142
|
+
function snap(value, spec) {
|
|
143
|
+
if (spec.type === "int") return Math.round(value);
|
|
144
|
+
if (spec.type === "enum") {
|
|
145
|
+
const [lo, hi] = spec.domain;
|
|
146
|
+
return Math.abs(value - lo) < Math.abs(value - hi) ? lo : hi;
|
|
147
|
+
}
|
|
148
|
+
return Number(value.toFixed(3));
|
|
149
|
+
}
|
|
150
|
+
function buildDeltaSet(description) {
|
|
151
|
+
const vocab = loadVocabulary();
|
|
152
|
+
const matched = extractKeywords(description);
|
|
153
|
+
const { kept, dropped, warnings } = resolveConflicts(matched);
|
|
154
|
+
const axes = {};
|
|
155
|
+
const voiceHintSet = /* @__PURE__ */ new Set();
|
|
156
|
+
for (const kw of kept) {
|
|
157
|
+
const spec = vocab.keywords[kw.keyword];
|
|
158
|
+
const multiplier = kw.modifier;
|
|
159
|
+
for (const hint of spec.voice_hints) voiceHintSet.add(hint);
|
|
160
|
+
for (const [axisName, axisDelta] of Object.entries(spec.axes)) {
|
|
161
|
+
const bucket = axes[axisName] ?? {
|
|
162
|
+
value: 0,
|
|
163
|
+
rangeUnion: [axisDelta.range[0], axisDelta.range[1]],
|
|
164
|
+
sources: []
|
|
165
|
+
};
|
|
166
|
+
bucket.value += axisDelta.delta * multiplier;
|
|
167
|
+
bucket.rangeUnion = [
|
|
168
|
+
Math.min(bucket.rangeUnion[0], axisDelta.range[0]),
|
|
169
|
+
Math.max(bucket.rangeUnion[1], axisDelta.range[1])
|
|
170
|
+
];
|
|
171
|
+
bucket.sources.push(kw.keyword);
|
|
172
|
+
axes[axisName] = bucket;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
for (const [axisName, bucket] of Object.entries(axes)) {
|
|
176
|
+
const registry = vocab.axis_registry[axisName];
|
|
177
|
+
if (!registry) continue;
|
|
178
|
+
let v = clamp(bucket.value, bucket.rangeUnion[0], bucket.rangeUnion[1]);
|
|
179
|
+
v = clamp(v, registry.domain[0], registry.domain[1]);
|
|
180
|
+
bucket.value = snap(v, registry);
|
|
181
|
+
bucket.sources.sort();
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
axes,
|
|
185
|
+
voiceHints: [...voiceHintSet],
|
|
186
|
+
unresolved: [],
|
|
187
|
+
warnings,
|
|
188
|
+
droppedKeywords: dropped,
|
|
189
|
+
matchedKeywords: kept
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// src/core/recommend.ts
|
|
194
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
195
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
196
|
+
import { dirname as dirname2, join as join2 } from "path";
|
|
197
|
+
var CATEGORY_HINTS = {
|
|
198
|
+
Consumer: [
|
|
199
|
+
"marketplace",
|
|
200
|
+
"shopping",
|
|
201
|
+
"ecommerce",
|
|
202
|
+
"consumer",
|
|
203
|
+
"b2c",
|
|
204
|
+
"retail",
|
|
205
|
+
"subscription",
|
|
206
|
+
"family",
|
|
207
|
+
"families",
|
|
208
|
+
"meal",
|
|
209
|
+
"meals",
|
|
210
|
+
"meal-kit",
|
|
211
|
+
"food",
|
|
212
|
+
"travel",
|
|
213
|
+
"social",
|
|
214
|
+
"community",
|
|
215
|
+
"buyer",
|
|
216
|
+
"seller",
|
|
217
|
+
"parents",
|
|
218
|
+
"kids",
|
|
219
|
+
"lifestyle",
|
|
220
|
+
"recipe",
|
|
221
|
+
"recipes"
|
|
222
|
+
],
|
|
223
|
+
Fintech: [
|
|
224
|
+
"fintech",
|
|
225
|
+
"banking",
|
|
226
|
+
"bank",
|
|
227
|
+
"payment",
|
|
228
|
+
"payments",
|
|
229
|
+
"crypto",
|
|
230
|
+
"trading",
|
|
231
|
+
"wallet",
|
|
232
|
+
"invest",
|
|
233
|
+
"investing",
|
|
234
|
+
"money",
|
|
235
|
+
"finance",
|
|
236
|
+
"financial",
|
|
237
|
+
"lending",
|
|
238
|
+
"remittance",
|
|
239
|
+
"tax"
|
|
240
|
+
],
|
|
241
|
+
"Developer Tools": [
|
|
242
|
+
"developer",
|
|
243
|
+
"devtool",
|
|
244
|
+
"devtools",
|
|
245
|
+
"dev-tool",
|
|
246
|
+
"deploy",
|
|
247
|
+
"deployment",
|
|
248
|
+
"build",
|
|
249
|
+
"ci",
|
|
250
|
+
"cd",
|
|
251
|
+
"cli",
|
|
252
|
+
"sdk",
|
|
253
|
+
"editor",
|
|
254
|
+
"ide",
|
|
255
|
+
"engineering",
|
|
256
|
+
"compiler",
|
|
257
|
+
"runtime"
|
|
258
|
+
],
|
|
259
|
+
AI: [
|
|
260
|
+
"ai",
|
|
261
|
+
"ml",
|
|
262
|
+
"llm",
|
|
263
|
+
"agent",
|
|
264
|
+
"agents",
|
|
265
|
+
"model",
|
|
266
|
+
"models",
|
|
267
|
+
"inference",
|
|
268
|
+
"gpt",
|
|
269
|
+
"chatbot",
|
|
270
|
+
"rag",
|
|
271
|
+
"embedding",
|
|
272
|
+
"embeddings",
|
|
273
|
+
"mcp"
|
|
274
|
+
],
|
|
275
|
+
"Design Tools": [
|
|
276
|
+
"design",
|
|
277
|
+
"design-tool",
|
|
278
|
+
"whiteboard",
|
|
279
|
+
"prototype",
|
|
280
|
+
"prototyping",
|
|
281
|
+
"wireframe",
|
|
282
|
+
"wireframes",
|
|
283
|
+
"mockup",
|
|
284
|
+
"mockups",
|
|
285
|
+
"figma-like",
|
|
286
|
+
"illustration",
|
|
287
|
+
"canvas"
|
|
288
|
+
],
|
|
289
|
+
Productivity: [
|
|
290
|
+
"saas",
|
|
291
|
+
"workspace",
|
|
292
|
+
"team",
|
|
293
|
+
"teams",
|
|
294
|
+
"project-management",
|
|
295
|
+
"enterprise",
|
|
296
|
+
"b2b",
|
|
297
|
+
"crm",
|
|
298
|
+
"docs",
|
|
299
|
+
"wiki",
|
|
300
|
+
"collaboration",
|
|
301
|
+
"kanban",
|
|
302
|
+
"scheduling",
|
|
303
|
+
"meetings"
|
|
304
|
+
],
|
|
305
|
+
Backend: [
|
|
306
|
+
"backend",
|
|
307
|
+
"database",
|
|
308
|
+
"db",
|
|
309
|
+
"api",
|
|
310
|
+
"apis",
|
|
311
|
+
"observability",
|
|
312
|
+
"monitoring",
|
|
313
|
+
"logging",
|
|
314
|
+
"analytics",
|
|
315
|
+
"pipeline",
|
|
316
|
+
"data-pipeline",
|
|
317
|
+
"streaming",
|
|
318
|
+
"queue",
|
|
319
|
+
"cache"
|
|
320
|
+
],
|
|
321
|
+
Automotive: [
|
|
322
|
+
"car",
|
|
323
|
+
"cars",
|
|
324
|
+
"vehicle",
|
|
325
|
+
"vehicles",
|
|
326
|
+
"auto",
|
|
327
|
+
"automotive",
|
|
328
|
+
"driving",
|
|
329
|
+
"ev",
|
|
330
|
+
"electric-vehicle"
|
|
331
|
+
],
|
|
332
|
+
Marketing: [
|
|
333
|
+
"marketing",
|
|
334
|
+
"seo",
|
|
335
|
+
"campaign",
|
|
336
|
+
"campaigns",
|
|
337
|
+
"newsletter",
|
|
338
|
+
"email-marketing",
|
|
339
|
+
"attribution"
|
|
340
|
+
]
|
|
341
|
+
};
|
|
342
|
+
function matchedCategoriesFor(queryTokens, queryStems) {
|
|
343
|
+
const out = /* @__PURE__ */ new Set();
|
|
344
|
+
for (const [category, hints] of Object.entries(CATEGORY_HINTS)) {
|
|
345
|
+
for (const hint of hints) {
|
|
346
|
+
if (queryTokens.has(hint) || queryStems.has(stem(hint))) {
|
|
347
|
+
out.add(category);
|
|
348
|
+
break;
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
return out;
|
|
353
|
+
}
|
|
354
|
+
var cachedTags = null;
|
|
355
|
+
function stem(s) {
|
|
356
|
+
let out = s;
|
|
357
|
+
for (const suffix of ["ing", "ed", "ly", "es", "s"]) {
|
|
358
|
+
if (out.length - suffix.length >= 3 && out.endsWith(suffix)) {
|
|
359
|
+
out = out.slice(0, -suffix.length);
|
|
360
|
+
break;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return out;
|
|
364
|
+
}
|
|
365
|
+
function tagsFilePath() {
|
|
366
|
+
const here = dirname2(fileURLToPath2(import.meta.url));
|
|
367
|
+
const candidates = [
|
|
368
|
+
join2(here, "..", "data", "reference-tags.md"),
|
|
369
|
+
join2(here, "..", "..", "data", "reference-tags.md")
|
|
370
|
+
];
|
|
371
|
+
for (const c of candidates) {
|
|
372
|
+
try {
|
|
373
|
+
readFileSync2(c, "utf8");
|
|
374
|
+
return c;
|
|
375
|
+
} catch {
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
throw new Error("data/reference-tags.md not found");
|
|
379
|
+
}
|
|
380
|
+
var ROW_RE = /^\|\s*([a-z0-9._-]+)\s*\|\s*([^|]*?)\s*\|\s*([^|]*?)\s*\|\s*([^|]*?)\s*\|$/i;
|
|
381
|
+
function loadReferenceTags() {
|
|
382
|
+
if (cachedTags) return cachedTags;
|
|
383
|
+
const raw = readFileSync2(tagsFilePath(), "utf8");
|
|
384
|
+
const rows = [];
|
|
385
|
+
for (const line of raw.split("\n")) {
|
|
386
|
+
const m = ROW_RE.exec(line);
|
|
387
|
+
if (!m) continue;
|
|
388
|
+
const [, id, color, category, keywordsRaw] = m;
|
|
389
|
+
if (id === "id") continue;
|
|
390
|
+
if (id.startsWith("---")) continue;
|
|
391
|
+
rows.push({
|
|
392
|
+
id: id.trim(),
|
|
393
|
+
color: color.trim(),
|
|
394
|
+
category: category.trim(),
|
|
395
|
+
keywords: keywordsRaw.split(",").map((k) => k.trim().toLowerCase()).filter(Boolean)
|
|
396
|
+
});
|
|
397
|
+
}
|
|
398
|
+
cachedTags = rows;
|
|
399
|
+
return rows;
|
|
400
|
+
}
|
|
401
|
+
function recommend(description, opts = {}) {
|
|
402
|
+
const topK = opts.topK ?? 5;
|
|
403
|
+
const diversityByCategory = opts.diversityByCategory ?? true;
|
|
404
|
+
const tags = loadReferenceTags();
|
|
405
|
+
const rawTokens = [
|
|
406
|
+
...tokenize(description),
|
|
407
|
+
...description.toLowerCase().split(/[^a-z0-9-]+/).filter(Boolean)
|
|
408
|
+
];
|
|
409
|
+
const queryTokens = new Set(rawTokens);
|
|
410
|
+
const queryStems = new Set(rawTokens.map(stem));
|
|
411
|
+
const matchedCategories = matchedCategoriesFor(queryTokens, queryStems);
|
|
412
|
+
const tagMatchByRef = tags.map(
|
|
413
|
+
(t) => t.keywords.filter(
|
|
414
|
+
(kw) => queryTokens.has(kw) || queryStems.has(stem(kw))
|
|
415
|
+
)
|
|
416
|
+
);
|
|
417
|
+
const totalTagMatches = tagMatchByRef.reduce((a, m) => a + m.length, 0);
|
|
418
|
+
const scored = tags.map((t, i) => {
|
|
419
|
+
const matched = tagMatchByRef[i];
|
|
420
|
+
const tagScore = matched.length;
|
|
421
|
+
const categoryHit = matchedCategories.has(t.category);
|
|
422
|
+
const categoryBonus = categoryHit && (tagScore > 0 || totalTagMatches === 0) ? 0.5 : 0;
|
|
423
|
+
const score = tagScore + categoryBonus;
|
|
424
|
+
const ratio = matched.length / Math.max(1, t.keywords.length);
|
|
425
|
+
return {
|
|
426
|
+
id: t.id,
|
|
427
|
+
category: t.category,
|
|
428
|
+
color: t.color,
|
|
429
|
+
keywords: t.keywords,
|
|
430
|
+
score,
|
|
431
|
+
matchedKeywords: matched,
|
|
432
|
+
matchedCategories: categoryHit ? [t.category] : [],
|
|
433
|
+
_ratio: ratio
|
|
434
|
+
};
|
|
435
|
+
});
|
|
436
|
+
scored.sort(
|
|
437
|
+
(a, b) => b.score - a.score || b._ratio - a._ratio || a.id.localeCompare(b.id)
|
|
438
|
+
);
|
|
439
|
+
const stripRatio = (s) => s.map(({ _ratio, ...rest }) => {
|
|
440
|
+
void _ratio;
|
|
441
|
+
return rest;
|
|
442
|
+
});
|
|
443
|
+
if (!diversityByCategory) return stripRatio(scored.slice(0, topK));
|
|
444
|
+
const picked = stripRatio(scored).slice(0, 0);
|
|
445
|
+
const pickedSet = /* @__PURE__ */ new Set();
|
|
446
|
+
const usedCategories = /* @__PURE__ */ new Set();
|
|
447
|
+
const allHits = stripRatio(scored);
|
|
448
|
+
for (const hit of allHits) {
|
|
449
|
+
if (picked.length >= topK) break;
|
|
450
|
+
if (usedCategories.has(hit.category)) continue;
|
|
451
|
+
picked.push(hit);
|
|
452
|
+
pickedSet.add(hit.id);
|
|
453
|
+
usedCategories.add(hit.category);
|
|
454
|
+
}
|
|
455
|
+
for (const hit of allHits) {
|
|
456
|
+
if (picked.length >= topK) break;
|
|
457
|
+
if (pickedSet.has(hit.id)) continue;
|
|
458
|
+
picked.push(hit);
|
|
459
|
+
pickedSet.add(hit.id);
|
|
460
|
+
}
|
|
461
|
+
return picked;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
// src/core/init-deprecate.ts
|
|
465
|
+
import {
|
|
466
|
+
existsSync,
|
|
467
|
+
readFileSync as readFileSync3,
|
|
468
|
+
writeFileSync,
|
|
469
|
+
unlinkSync,
|
|
470
|
+
mkdirSync
|
|
471
|
+
} from "fs";
|
|
472
|
+
import { dirname as dirname3, join as join3 } from "path";
|
|
473
|
+
function deprecationHeader(opts) {
|
|
474
|
+
const now = (opts.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
475
|
+
const lines = [
|
|
476
|
+
"<!--",
|
|
477
|
+
"omd:deprecated",
|
|
478
|
+
` deprecated_at: ${now}`
|
|
479
|
+
];
|
|
480
|
+
if (opts.previousReference)
|
|
481
|
+
lines.push(` previous_reference: ${opts.previousReference}`);
|
|
482
|
+
lines.push(` new_reference: ${opts.newReference}`);
|
|
483
|
+
if (opts.preferencesReplayed !== void 0)
|
|
484
|
+
lines.push(` preferences_replayed: ${opts.preferencesReplayed}`);
|
|
485
|
+
if (opts.preferencesOrphaned !== void 0)
|
|
486
|
+
lines.push(` preferences_orphaned: ${opts.preferencesOrphaned}`);
|
|
487
|
+
if (opts.orphanFile) lines.push(` orphan_file: ${opts.orphanFile}`);
|
|
488
|
+
lines.push(` reason: ${opts.reason}`);
|
|
489
|
+
lines.push("-->", "", "");
|
|
490
|
+
return lines.join("\n");
|
|
491
|
+
}
|
|
492
|
+
function deprecateDesignMd(opts) {
|
|
493
|
+
const from = join3(opts.projectRoot, "DESIGN.md");
|
|
494
|
+
const baseTo = join3(opts.projectRoot, "DESIGN_DEPRECATED.md");
|
|
495
|
+
if (!existsSync(from)) {
|
|
496
|
+
return { renamed: false, from, to: baseTo };
|
|
497
|
+
}
|
|
498
|
+
let target = baseTo;
|
|
499
|
+
if (existsSync(baseTo)) {
|
|
500
|
+
const ts = (opts.now ?? /* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
501
|
+
target = join3(opts.projectRoot, `DESIGN_DEPRECATED.${ts}.md`);
|
|
502
|
+
}
|
|
503
|
+
mkdirSync(dirname3(target), { recursive: true });
|
|
504
|
+
const prior = readFileSync3(from, "utf8");
|
|
505
|
+
writeFileSync(target, deprecationHeader(opts) + prior, "utf8");
|
|
506
|
+
unlinkSync(from);
|
|
507
|
+
return { renamed: true, from, to: target };
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/cli/init.ts
|
|
511
|
+
function runInitRecommend(opts) {
|
|
512
|
+
const hits = recommend(opts.description, { topK: opts.topK ?? 5 });
|
|
513
|
+
const delta = buildDeltaSet(opts.description);
|
|
514
|
+
if (opts.json) {
|
|
515
|
+
process.stdout.write(
|
|
516
|
+
JSON.stringify(
|
|
517
|
+
{
|
|
518
|
+
description: opts.description,
|
|
519
|
+
recommendations: hits,
|
|
520
|
+
delta_set: delta
|
|
521
|
+
},
|
|
522
|
+
null,
|
|
523
|
+
2
|
|
524
|
+
)
|
|
525
|
+
);
|
|
526
|
+
process.stdout.write("\n");
|
|
527
|
+
return 0;
|
|
528
|
+
}
|
|
529
|
+
p.intro(pc.bold("omd init \u2014 recommend"));
|
|
530
|
+
p.log.message(pc.dim(`Query: "${opts.description}"
|
|
531
|
+
`));
|
|
532
|
+
if (delta.matchedKeywords.length > 0) {
|
|
533
|
+
p.log.message(
|
|
534
|
+
pc.bold("Matched keywords: ") + delta.matchedKeywords.map((k) => pc.cyan(k.keyword) + pc.dim(` (${k.modifier.toFixed(2)})`)).join(", ")
|
|
535
|
+
);
|
|
536
|
+
}
|
|
537
|
+
if (delta.warnings.length > 0) {
|
|
538
|
+
for (const w of delta.warnings) p.log.warn(w);
|
|
539
|
+
}
|
|
540
|
+
p.log.message(pc.bold("\nTop references:"));
|
|
541
|
+
for (const [i, hit] of hits.entries()) {
|
|
542
|
+
const scoreStr = pc.dim(`[${hit.score.toFixed(2)}]`);
|
|
543
|
+
const matched = hit.matchedKeywords.length > 0 ? pc.green(hit.matchedKeywords.join(", ")) : pc.dim("(no direct tag match)");
|
|
544
|
+
p.log.message(
|
|
545
|
+
` ${i + 1}. ${pc.bold(hit.id.padEnd(14))} ${scoreStr} ${pc.dim(hit.category.padEnd(14))} ${matched}`
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
p.outro(
|
|
549
|
+
pc.dim('Next: `omd init prepare --ref <id> --description "..."` to stage.')
|
|
550
|
+
);
|
|
551
|
+
return 0;
|
|
552
|
+
}
|
|
553
|
+
function runInitPrepare(opts) {
|
|
554
|
+
const projectRoot = opts.dir ?? process.cwd();
|
|
555
|
+
const relRoot = relative(process.cwd(), projectRoot) || ".";
|
|
556
|
+
const refPath = findReferencePath(opts.ref);
|
|
557
|
+
if (!refPath) {
|
|
558
|
+
console.error(pc.red(`omd init prepare: reference not found: ${opts.ref}`));
|
|
559
|
+
return 1;
|
|
560
|
+
}
|
|
561
|
+
const referenceMd = readFileSync4(refPath, "utf8");
|
|
562
|
+
const delta = buildDeltaSet(opts.description);
|
|
563
|
+
const deprecate = deprecateDesignMd({
|
|
564
|
+
projectRoot,
|
|
565
|
+
newReference: opts.ref,
|
|
566
|
+
reason: opts.reason ?? "user-initiated omd init"
|
|
567
|
+
});
|
|
568
|
+
const contextPath = join4(projectRoot, ".omd", "init-context.json");
|
|
569
|
+
mkdirSync2(join4(projectRoot, ".omd"), { recursive: true });
|
|
570
|
+
const context = {
|
|
571
|
+
schema: "omd.init-context/v1",
|
|
572
|
+
created_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
573
|
+
reference_id: opts.ref,
|
|
574
|
+
description: opts.description,
|
|
575
|
+
delta_set: delta,
|
|
576
|
+
deprecated_from: deprecate.renamed ? deprecate.to : null
|
|
577
|
+
};
|
|
578
|
+
writeFileSync2(contextPath, JSON.stringify(context, null, 2) + "\n", "utf8");
|
|
579
|
+
if (opts.json) {
|
|
580
|
+
process.stdout.write(
|
|
581
|
+
JSON.stringify(
|
|
582
|
+
{
|
|
583
|
+
project_root: projectRoot,
|
|
584
|
+
reference_path: refPath,
|
|
585
|
+
context_path: contextPath,
|
|
586
|
+
deprecated_from: deprecate.renamed ? deprecate.to : null,
|
|
587
|
+
reference_md: referenceMd,
|
|
588
|
+
delta_set: delta
|
|
589
|
+
},
|
|
590
|
+
null,
|
|
591
|
+
2
|
|
592
|
+
)
|
|
593
|
+
);
|
|
594
|
+
process.stdout.write("\n");
|
|
595
|
+
return 0;
|
|
596
|
+
}
|
|
597
|
+
p.intro(pc.bold("omd init \u2014 prepare") + pc.dim(` (${relRoot})`));
|
|
598
|
+
p.log.message(`Reference: ${pc.cyan(opts.ref)}`);
|
|
599
|
+
p.log.message(`Description: ${pc.dim(opts.description)}`);
|
|
600
|
+
if (deprecate.renamed) {
|
|
601
|
+
p.log.warn(
|
|
602
|
+
`Existing DESIGN.md renamed \u2192 ${relative(projectRoot, deprecate.to)}`
|
|
603
|
+
);
|
|
604
|
+
}
|
|
605
|
+
p.log.success(
|
|
606
|
+
`Context staged \u2192 ${relative(projectRoot, contextPath)}`
|
|
607
|
+
);
|
|
608
|
+
p.outro(
|
|
609
|
+
pc.dim(
|
|
610
|
+
"Next: have your agent (Claude Code / Codex / OpenCode) run the `omd:init` skill to generate DESIGN.md from this context."
|
|
611
|
+
)
|
|
612
|
+
);
|
|
613
|
+
return 0;
|
|
614
|
+
}
|
|
615
|
+
function findReferencePath(refId) {
|
|
616
|
+
const root = findRepoRoot();
|
|
617
|
+
if (!root) return null;
|
|
618
|
+
const path = join4(root, "references", refId, "DESIGN.md");
|
|
619
|
+
return existsSync2(path) ? path : null;
|
|
620
|
+
}
|
|
621
|
+
function findRepoRoot() {
|
|
622
|
+
let cur = dirname4(fileURLToPath3(import.meta.url));
|
|
623
|
+
for (let i = 0; i < 8; i++) {
|
|
624
|
+
if (existsSync2(join4(cur, "references"))) return cur;
|
|
625
|
+
const parent = dirname4(cur);
|
|
626
|
+
if (parent === cur) break;
|
|
627
|
+
cur = parent;
|
|
628
|
+
}
|
|
629
|
+
return null;
|
|
630
|
+
}
|
|
631
|
+
export {
|
|
632
|
+
runInitPrepare,
|
|
633
|
+
runInitRecommend
|
|
634
|
+
};
|
|
635
|
+
//# sourceMappingURL=init-STACB7E5.js.map
|